aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore3
-rw-r--r--Makefile.am14
-rw-r--r--configure.ac90
-rw-r--r--docs/Makefile.am8
-rw-r--r--docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt5
-rw-r--r--docs/libdbusmenu-gtk/reference/Makefile.am2
-rw-r--r--docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-sections.txt20
-rw-r--r--libdbusmenu-glib/Makefile.am2
-rw-r--r--libdbusmenu-glib/client-menuitem.c2
-rw-r--r--libdbusmenu-glib/client-private.h3
-rw-r--r--libdbusmenu-glib/client.c5
-rw-r--r--libdbusmenu-glib/dbus-menu.xml13
-rw-r--r--libdbusmenu-glib/defaults.c1
-rw-r--r--libdbusmenu-glib/menuitem-proxy.c2
-rw-r--r--libdbusmenu-glib/menuitem.c19
-rw-r--r--libdbusmenu-glib/menuitem.h67
-rw-r--r--libdbusmenu-glib/server.c129
-rw-r--r--libdbusmenu-gtk/Makefile.am33
-rw-r--r--libdbusmenu-gtk/client.c185
-rw-r--r--libdbusmenu-gtk/dbusmenu-gtk.h1
-rw-r--r--libdbusmenu-gtk/genericmenuitem-enum-types.c.in116
-rw-r--r--libdbusmenu-gtk/genericmenuitem-enum-types.h.in65
-rw-r--r--libdbusmenu-gtk/genericmenuitem.c119
-rw-r--r--libdbusmenu-gtk/genericmenuitem.h71
-rw-r--r--libdbusmenu-gtk/menu.c14
-rw-r--r--libdbusmenu-gtk/parser.c176
-rw-r--r--libdbusmenu-gtk/serializablemenuitem.c288
-rw-r--r--libdbusmenu-gtk/serializablemenuitem.h133
-rw-r--r--tests/Makefile.am54
-rw-r--r--tests/test-gtk-label-client.c2
-rw-r--r--tests/test-gtk-label.json53
-rw-r--r--tests/test-gtk-objects.c4
-rw-r--r--tests/test-gtk-parser.c16
-rw-r--r--tests/test-gtk-shortcut-client.c2
-rw-r--r--tests/test-gtk-shortcut-server.c4
-rw-r--r--tests/test-gtk-submenu-client.c2
-rw-r--r--tools/Makefile.am6
-rw-r--r--tools/testapp/Makefile.am12
38 files changed, 1060 insertions, 681 deletions
diff --git a/.bzrignore b/.bzrignore
index ea8b315..0073e93 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -254,3 +254,6 @@ tests/test-gtk-submenu
tests/test-gtk-submenu-client
tests/test-gtk-submenu-server
tests/test-json-01.output.json
+genericmenuitem-enum-types.c
+genericmenuitem-enum-types.h
+libdbusmenu_gtk3_la-genericmenuitem-enum-types.lo
diff --git a/Makefile.am b/Makefile.am
index c2c0980..6b11b31 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,13 +1,23 @@
+ACLOCAL_AMFLAGS = -I m4
+
EXTRA_DIST = \
COPYING.2.1 \
COPYING-GPL3 \
m4/introspection.m4
+if WANT_TESTS
+TESTS_SUBDIR = tests
+endif
+
+if WANT_LIBDBUSMENUGTK
+LIBDBUSMENUGTK_SUBDIR = libdbusmenu-gtk
+endif
+
SUBDIRS = \
libdbusmenu-glib \
- libdbusmenu-gtk \
+ $(LIBDBUSMENUGTK_SUBDIR) \
tools \
- tests \
+ $(TESTS_SUBDIR) \
docs \
po
diff --git a/configure.ac b/configure.ac
index 0618dd1..6276327 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,11 +1,11 @@
-AC_INIT(libdbusmenu, 0.4.2, ted@canonical.com)
+AC_INIT(libdbusmenu, 0.4.94, ted@canonical.com)
AC_COPYRIGHT([Copyright 2009,2010 Canonical])
AC_PREREQ(2.62)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(libdbusmenu, 0.4.2, [-Wno-portability])
+AM_INIT_AUTOMAKE(libdbusmenu, 0.4.94, [-Wno-portability])
AM_MAINTAINER_MODE
@@ -58,27 +58,37 @@ AC_SUBST(DBUSMENUGLIB_LIBS)
GTK_REQUIRED_VERSION=2.16
GTK3_REQUIRED_VERSION=2.91
+AC_ARG_ENABLE([gtk],
+ AC_HELP_STRING([--disable-gtk], [Disable libdbusmenu-gtk library]),
+ [enable_gtk=$enableval], [enable_gtk=auto])
+AM_CONDITIONAL([WANT_LIBDBUSMENUGTK], [test "x$enable_gtk" != "xno"])
+
AC_ARG_WITH([gtk],
[AS_HELP_STRING([--with-gtk],
- [Which version of gtk to use @<:@default=2@:>@])],
+ [Which version of gtk to use @<:@default=3@:>@])],
[],
- [with_gtk=2])
+ [with_gtk=3])
+AM_CONDITIONAL([USE_GTK3], [test "x$with_gtk" = "x3"])
+
+AS_IF([test "x$enable_gtk" != "xno"],[
AS_IF([test "x$with_gtk" = x3],
[PKG_CHECK_MODULES(DBUSMENUGTK, gtk+-3.0 >= $GTK3_REQUIRED_VERSION
- glib-2.0 >= $GLIB_REQUIRED_VERSION)
- AC_SUBST(DBUSMENUGTK_CFLAGS)
- AC_SUBST(DBUSMENUGTK_LIBS)
+ glib-2.0 >= $GLIB_REQUIRED_VERSION,
+ [have_gtk=yes]
+)
AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available])
],
[test "x$with_gtk" = x2],
[PKG_CHECK_MODULES(DBUSMENUGTK, gtk+-2.0 >= $GTK_REQUIRED_VERSION
- glib-2.0 >= $GLIB_REQUIRED_VERSION)
- AC_SUBST(DBUSMENUGTK_CFLAGS)
- AC_SUBST(DBUSMENUGTK_LIBS)
+ glib-2.0 >= $GLIB_REQUIRED_VERSION,
+ [have_gtk=yes]
+)
],
[AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])]
)
-AM_CONDITIONAL(USE_GTK3, [test "x$with_gtk" = x3])
+])
+AC_SUBST(DBUSMENUGTK_CFLAGS)
+AC_SUBST(DBUSMENUGTK_LIBS)
###########################
# Dependencies - dumper
@@ -86,8 +96,17 @@ AM_CONDITIONAL(USE_GTK3, [test "x$with_gtk" = x3])
X11_REQUIRED_VERSION=1.3
+AC_ARG_ENABLE([dumper],
+ AC_HELP_STRING([--disable-dumper], [Disable dbusmenudumper tool]),
+ [enable_dumper=$enableval], [enable_dumper=auto])
+AM_CONDITIONAL([WANT_DBUSMENUDUMPER], [test "x$enable_dumper" != "xno"])
+
+AS_IF([test "x$enable_dumper" != "xno"],[
PKG_CHECK_MODULES(DBUSMENUDUMPER, gtk+-2.0 >= $GTK_REQUIRED_VERSION
- x11 >= $X11_REQUIRED_VERSION)
+ x11 >= $X11_REQUIRED_VERSION,
+ [have_dumper=yes]
+)
+])
AC_SUBST(DBUSMENUDUMPER_CFLAGS)
AC_SUBST(DBUSMENUDUMPER_LIBS)
@@ -96,11 +115,20 @@ AC_SUBST(DBUSMENUDUMPER_LIBS)
# Dependencies - Testing
###########################
-JSON_GLIB_REQUIRED_VERSION=0.6.0
+JSON_GLIB_REQUIRED_VERSION=0.13.4
GIO_UNIX_REQUIRED_VERSION=2.24
+AC_ARG_ENABLE([tests],
+ AC_HELP_STRING([--disable-tests], [Disable tests]),
+ [enable_tests=$enableval], [enable_tests=auto])
+AM_CONDITIONAL([WANT_TESTS], [test "x$enable_tests" != "xno"])
+
+AS_IF([test "x$enable_tests" != "xno"],[
PKG_CHECK_MODULES(DBUSMENUTESTS, json-glib-1.0 >= $JSON_GLIB_REQUIRED_VERSION
- gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION)
+ gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION,
+ [have_tests=yes]
+)
+])
AC_SUBST(DBUSMENUTESTS_CFLAGS)
AC_SUBST(DBUSMENUTESTS_LIBS)
@@ -121,7 +149,17 @@ AM_CONDITIONAL(INTROSPECTION_TEN, [test "x$introspection_ten" = "xyes"])
# Vala API Generation
###########################
+AC_ARG_ENABLE([vala],
+ AC_HELP_STRING([--disable-vala], [Disable vala]),
+ [enable_vala=$enableval], [enable_vala=auto])
+
+AS_IF([test "x$enable_vala" != "xno"],[
+ AM_COND_IF([HAVE_INTROSPECTION],,[
+ AC_MSG_ERROR([Vala bindings require introspection support, please --enable-introspection])
+ ])
AC_PATH_PROG([VALA_API_GEN], [vapigen])
+])
+AM_CONDITIONAL([HAVE_VALA], [test -n "$VALA_API_GEN"])
###########################
# XSLT Processor
@@ -133,8 +171,8 @@ AC_PATH_PROG([XSLT_PROC], [xsltproc])
# Lib versioning
###########################
-LIBDBUSMENU_CURRENT=3
-LIBDBUSMENU_REVISION=13
+LIBDBUSMENU_CURRENT=4
+LIBDBUSMENU_REVISION=4
LIBDBUSMENU_AGE=0
AC_SUBST(LIBDBUSMENU_CURRENT)
@@ -199,3 +237,23 @@ libdbusmenu Configuration:
GTK+ Version: $with_gtk
])
+AS_IF([test "x$have_tests" = "xyes"],
+ AC_MSG_NOTICE([ Tests: yes]),
+ AC_MSG_NOTICE([ Tests: no])
+)
+
+AS_IF([test "x$enable_gtk" = "xno"],
+ AC_MSG_NOTICE([ Gtk: no]),
+ AC_MSG_NOTICE([ Gtk: yes (gtk$with_gtk)])
+)
+
+AM_COND_IF([HAVE_VALA],
+ AC_MSG_NOTICE([ Vala bindings: yes]),
+ AC_MSG_NOTICE([ Vala bindings no])
+)
+
+AS_IF([test "x$have_dumper" = "xyes"],
+ AC_MSG_NOTICE([ Dumper: yes]),
+ AC_MSG_NOTICE([ Dumper: no])
+)
+
diff --git a/docs/Makefile.am b/docs/Makefile.am
index 87ffe5f..23a4c86 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -1 +1,7 @@
-SUBDIRS = libdbusmenu-glib libdbusmenu-gtk
+if WANT_LIBDBUSMENUGTK
+LIBDBUSMENUGTK_SUBDIR = libdbusmenu-gtk
+endif
+
+SUBDIRS = \
+ libdbusmenu-glib \
+ $(LIBDBUSMENUGTK_SUBDIR)
diff --git a/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt
index 4d1e50a..d95ec4c 100644
--- a/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt
+++ b/docs/libdbusmenu-glib/reference/libdbusmenu-glib-sections.txt
@@ -59,6 +59,7 @@ DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE
DBUSMENU_MENUITEM_PROP_TOGGLE_STATE
DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY
DBUSMENU_MENUITEM_PROP_SHORTCUT
+DBUSMENU_MENUITEM_PROP_DISPOSITION
DBUSMENU_MENUITEM_TOGGLE_CHECK
DBUSMENU_MENUITEM_TOGGLE_RADIO
DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED
@@ -70,6 +71,10 @@ DBUSMENU_MENUITEM_SHORTCUT_ALT
DBUSMENU_MENUITEM_SHORTCUT_CONTROL
DBUSMENU_MENUITEM_SHORTCUT_SHIFT
DBUSMENU_MENUITEM_SHORTCUT_SUPER
+DBUSMENU_MENUITEM_DISPOSITION_NORMAL
+DBUSMENU_MENUITEM_DISPOSITION_INFORMATIVE
+DBUSMENU_MENUITEM_DISPOSITION_WARNING
+DBUSMENU_MENUITEM_DISPOSITION_ALERT
DBUSMENU_MENUITEM_EVENT_ACTIVATED
DBUSMENU_MENUITEM_EVENT_CLOSED
DBUSMENU_MENUITEM_EVENT_OPENED
diff --git a/docs/libdbusmenu-gtk/reference/Makefile.am b/docs/libdbusmenu-gtk/reference/Makefile.am
index 06d0009..62f80ba 100644
--- a/docs/libdbusmenu-gtk/reference/Makefile.am
+++ b/docs/libdbusmenu-gtk/reference/Makefile.am
@@ -54,7 +54,7 @@ CFILE_GLOB=$(top_srcdir)/libdbusmenu-gtk/*.c
# Header files to ignore when scanning.
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
-IGNORE_HFILES=genericmenuitem.h
+IGNORE_HFILES=genericmenuitem.h genericmenuitem-enum-types.h
# Images to copy into HTML directory.
# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
diff --git a/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-sections.txt b/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-sections.txt
index efffeaa..bc1f0ba 100644
--- a/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-sections.txt
+++ b/docs/libdbusmenu-gtk/reference/libdbusmenu-gtk-sections.txt
@@ -23,26 +23,6 @@ DbusmenuGtkClientPrivate
</SECTION>
<SECTION>
-<FILE>serializablemenuitem</FILE>
-<TITLE>DbusmenuGtkSerializableMenuItem</TITLE>
-DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_PROP_MENUITEM
-DbusmenuGtkSerializableMenuItemClass
-dbusmenu_gtk_serializable_menu_item_build_menuitem
-dbusmenu_gtk_serializable_menu_item_register_to_client
-dbusmenu_gtk_serializable_menu_item_set_menuitem
-<SUBSECTION Standard>
-DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM
-DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM
-DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_CLASS
-DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM_CLASS
-DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_GET_CLASS
-<SUBSECTION Private>
-DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM
-dbusmenu_gtk_serializable_menu_item_get_type
-DbusmenuGtkSerializableMenuItemPrivate
-</SECTION>
-
-<SECTION>
<FILE>menu</FILE>
<TITLE>DbusmenuGtkMenu</TITLE>
DbusmenuGtkMenuClass
diff --git a/libdbusmenu-glib/Makefile.am b/libdbusmenu-glib/Makefile.am
index 5b04415..7d4ea5d 100644
--- a/libdbusmenu-glib/Makefile.am
+++ b/libdbusmenu-glib/Makefile.am
@@ -189,6 +189,7 @@ endif
# VAPI Files
#########################
+if HAVE_VALA
if HAVE_INTROSPECTION
vapidir = $(datadir)/vala/vapi
@@ -200,4 +201,5 @@ Dbusmenu-0.4.vapi: Dbusmenu-0.4.gir
CLEANFILES += $(vapi_DATA)
endif
+endif
diff --git a/libdbusmenu-glib/client-menuitem.c b/libdbusmenu-glib/client-menuitem.c
index 60f8637..483470a 100644
--- a/libdbusmenu-glib/client-menuitem.c
+++ b/libdbusmenu-glib/client-menuitem.c
@@ -106,7 +106,7 @@ static void
handle_event (DbusmenuMenuitem * mi, const gchar * name, GVariant * variant, guint timestamp)
{
DbusmenuClientMenuitemPrivate * priv = DBUSMENU_CLIENT_MENUITEM_GET_PRIVATE(mi);
- dbusmenu_client_send_event(priv->client, dbusmenu_menuitem_get_id(mi), name, variant, timestamp);
+ dbusmenu_client_send_event(priv->client, dbusmenu_menuitem_get_id(mi), name, variant, timestamp, mi);
return;
}
diff --git a/libdbusmenu-glib/client-private.h b/libdbusmenu-glib/client-private.h
index f6df372..44c0066 100644
--- a/libdbusmenu-glib/client-private.h
+++ b/libdbusmenu-glib/client-private.h
@@ -37,7 +37,8 @@ void dbusmenu_client_send_event (DbusmenuClient * client,
gint id,
const gchar * name,
GVariant * variant,
- guint timestamp);
+ guint timestamp,
+ DbusmenuMenuitem * mi);
void dbusmenu_client_send_about_to_show(DbusmenuClient * client,
gint id,
void (*cb) (gpointer user_data),
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index 45cf0d1..588c940 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -1239,7 +1239,7 @@ menuproxy_signal_cb (GDBusProxy * proxy, gchar * sender, gchar * signal, GVarian
} else if (priv->root == NULL) {
/* Drop out here, all the rest of these really need to have a root
node so we can just ignore them if there isn't one. */
- } else if (g_strcmp0(signal, "ItemPropertiesUpdated") == 0) {
+ } else if (g_strcmp0(signal, "ItemsPropertiesUpdated") == 0) {
/* Remove before adding just incase there is a duplicate, against the
rules, but we can handle it so let's do it. */
GVariantIter ritems;
@@ -1516,14 +1516,13 @@ menuitem_call_cb (GObject * proxy, GAsyncResult * res, gpointer userdata)
/* Sends the event over DBus to the server on the other side
of the bus. */
void
-dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name, GVariant * variant, guint timestamp)
+dbusmenu_client_send_event (DbusmenuClient * client, gint id, const gchar * name, GVariant * variant, guint timestamp, DbusmenuMenuitem * mi)
{
g_return_if_fail(DBUSMENU_IS_CLIENT(client));
g_return_if_fail(id >= 0);
g_return_if_fail(name != NULL);
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
- DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
if (mi == NULL) {
g_warning("Asked to activate a menuitem %d that we don't know about", id);
return;
diff --git a/libdbusmenu-glib/dbus-menu.xml b/libdbusmenu-glib/dbus-menu.xml
index a36c148..4b5a5d8 100644
--- a/libdbusmenu-glib/dbus-menu.xml
+++ b/libdbusmenu-glib/dbus-menu.xml
@@ -157,6 +157,19 @@ License version 3 and version 2.1 along with this program. If not, see
</td>
<td>""</td>
</tr>
+ <tr>
+ <td>disposition</td>
+ <td>string</td>
+ <td>
+ How the menuitem feels the information it's displaying to the
+ user should be presented.
+ - "normal" a standard menu item
+ - "informative" providing additional information to the user
+ - "warning" looking at potentially harmful results
+ - "alert" something bad could potentially happen
+ </td>
+ <td>"normal"</td>
+ </tr>
</table>
Vendor specific properties can be added by prefixing them with
diff --git a/libdbusmenu-glib/defaults.c b/libdbusmenu-glib/defaults.c
index aa479b1..a5caf0b 100644
--- a/libdbusmenu-glib/defaults.c
+++ b/libdbusmenu-glib/defaults.c
@@ -87,6 +87,7 @@ dbusmenu_defaults_init (DbusmenuDefaults *self)
dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE, G_VARIANT_TYPE_INT32, NULL);
dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_SHORTCUT, G_VARIANT_TYPE("aas"), NULL);
dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY, G_VARIANT_TYPE_STRING, NULL);
+ dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_DEFAULT, DBUSMENU_MENUITEM_PROP_DISPOSITION, G_VARIANT_TYPE_STRING, g_variant_new_string(DBUSMENU_MENUITEM_DISPOSITION_NORMAL));
/* Separator defaults */
dbusmenu_defaults_default_set(self, DBUSMENU_CLIENT_TYPES_SEPARATOR, DBUSMENU_MENUITEM_PROP_VISIBLE, G_VARIANT_TYPE_BOOLEAN, g_variant_new_boolean(TRUE));
diff --git a/libdbusmenu-glib/menuitem-proxy.c b/libdbusmenu-glib/menuitem-proxy.c
index ae6a334..fdbd892 100644
--- a/libdbusmenu-glib/menuitem-proxy.c
+++ b/libdbusmenu-glib/menuitem-proxy.c
@@ -188,6 +188,7 @@ proxy_item_child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, gui
DbusmenuMenuitemProxy * pmi = DBUSMENU_MENUITEM_PROXY(user_data);
DbusmenuMenuitemProxy * child_pmi = dbusmenu_menuitem_proxy_new(child);
dbusmenu_menuitem_child_add_position(DBUSMENU_MENUITEM(pmi), DBUSMENU_MENUITEM(child_pmi), position);
+ g_object_unref (child_pmi);
return;
}
@@ -283,6 +284,7 @@ add_menuitem (DbusmenuMenuitemProxy * pmi, DbusmenuMenuitem * mi)
for (child = children; child != NULL; child = g_list_next(child)) {
DbusmenuMenuitemProxy * child_pmi = dbusmenu_menuitem_proxy_new(DBUSMENU_MENUITEM(child->data));
dbusmenu_menuitem_child_append(DBUSMENU_MENUITEM(pmi), DBUSMENU_MENUITEM(child_pmi));
+ g_object_unref (child_pmi);
}
return;
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index bdaf49f..4e037ee 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -575,7 +575,7 @@ dbusmenu_menuitem_set_realized (DbusmenuMenuitem * mi)
* has. The list is valid until another child related function
* is called, where it might be changed.
*
- * Return value: (transfer none): A #GList of pointers to #DbusmenuMenuitem objects.
+ * Return value: (transfer none) (element-type Dbusmenu.Menuitem): A #GList of pointers to #DbusmenuMenuitem objects.
*/
GList *
dbusmenu_menuitem_get_children (DbusmenuMenuitem * mi)
@@ -1694,25 +1694,20 @@ dbusmenu_menuitem_handle_event (DbusmenuMenuitem * mi, const gchar * name, GVari
#endif
DbusmenuMenuitemClass * class = DBUSMENU_MENUITEM_GET_CLASS(mi);
- /* We need to keep a ref to the variant because the signal
- handler will drop the floating ref and then we'll be up
- a creek if we don't have our own later. */
- if (variant != NULL) {
- g_variant_ref_sink(variant);
+ gboolean handled = FALSE;
+ if (variant == NULL) {
+ variant = g_variant_new_int32(0);
}
- gboolean handled = FALSE;
+ g_variant_ref_sink(variant);
+
g_signal_emit(G_OBJECT(mi), signals[EVENT], g_quark_from_string(name), name, variant, timestamp, &handled);
if (!handled && class->handle_event != NULL) {
class->handle_event(mi, name, variant, timestamp);
}
- if (variant != NULL) {
- g_variant_unref(variant);
- }
-
- return;
+ g_variant_unref(variant);
}
/**
diff --git a/libdbusmenu-glib/menuitem.h b/libdbusmenu-glib/menuitem.h
index afd1d4e..985e1a3 100644
--- a/libdbusmenu-glib/menuitem.h
+++ b/libdbusmenu-glib/menuitem.h
@@ -41,7 +41,9 @@ G_BEGIN_DECLS
#define DBUSMENU_IS_MENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUSMENU_TYPE_MENUITEM))
#define DBUSMENU_MENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_TYPE_MENUITEM, DbusmenuMenuitemClass))
-
+/* ***************************************** */
+/* ********* GLib Object Signals ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED:
*
@@ -103,6 +105,9 @@ G_BEGIN_DECLS
*/
#define DBUSMENU_MENUITEM_SIGNAL_EVENT "event"
+/* ***************************************** */
+/* ********* Menuitem Properties ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_PROP_TYPE:
*
@@ -184,7 +189,17 @@ G_BEGIN_DECLS
* #DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU. Type: #G_VARIANT_TYPE_STRING
*/
#define DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY "children-display"
+/**
+ * DBUSMENU_MENUITEM_PROP_DISPOSITION:
+ *
+ * #DbusmenuMenuitem property to tell what type of information that the
+ * menu item is displaying to the user. Type: #G_VARIANT_TYPE_STRING
+ */
+#define DBUSMENU_MENUITEM_PROP_DISPOSITION "disposition"
+/* ***************************************** */
+/* ********* Toggle Values ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_TOGGLE_CHECK:
*
@@ -200,6 +215,9 @@ G_BEGIN_DECLS
*/
#define DBUSMENU_MENUITEM_TOGGLE_RADIO "radio"
+/* ***************************************** */
+/* ********* Toggle States ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED:
*
@@ -222,6 +240,9 @@ G_BEGIN_DECLS
*/
#define DBUSMENU_MENUITEM_TOGGLE_STATE_UNKNOWN -1
+/* ***************************************** */
+/* ********* Icon specials ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_ICON_NAME_BLANK:
*
@@ -230,6 +251,9 @@ G_BEGIN_DECLS
*/
#define DBUSMENU_MENUITEM_ICON_NAME_BLANK "blank-icon"
+/* ***************************************** */
+/* ********* Shortcut Modifiers ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_SHORTCUT_CONTROL:
*
@@ -259,6 +283,9 @@ G_BEGIN_DECLS
*/
#define DBUSMENU_MENUITEM_SHORTCUT_SUPER "Super"
+/* ***************************************** */
+/* ********* Child Display Types ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU:
*
@@ -267,6 +294,44 @@ G_BEGIN_DECLS
*/
#define DBUSMENU_MENUITEM_CHILD_DISPLAY_SUBMENU "submenu"
+/* ***************************************** */
+/* ********* Menuitem Dispositions ********* */
+/* ***************************************** */
+/**
+ * DBUSMENU_MENUITEM_DISPOSITION_NORMAL:
+ *
+ * Used in #DBUSMENU_MENUITEM_PROP_DISPOSITION to have a menu
+ * item displayed in the normal manner. Default value.
+ */
+#define DBUSMENU_MENUITEM_DISPOSITION_NORMAL "normal"
+/**
+ * DBUSMENU_MENUITEM_DISPOSITION_INFORMATIVE:
+ *
+ * Used in #DBUSMENU_MENUITEM_PROP_DISPOSITION to have a menu
+ * item displayed in a way that conveys it's giving additional
+ * information to the user.
+ */
+#define DBUSMENU_MENUITEM_DISPOSITION_INFORMATIVE "informative"
+/**
+ * DBUSMENU_MENUITEM_DISPOSITION_WARNING:
+ *
+ * Used in #DBUSMENU_MENUITEM_PROP_DISPOSITION to have a menu
+ * item displayed in a way that conveys it's giving a warning
+ * to the user.
+ */
+#define DBUSMENU_MENUITEM_DISPOSITION_WARNING "warning"
+/**
+ * DBUSMENU_MENUITEM_DISPOSITION_ALERT:
+ *
+ * Used in #DBUSMENU_MENUITEM_PROP_DISPOSITION to have a menu
+ * item displayed in a way that conveys it's giving an alert
+ * to the user.
+ */
+#define DBUSMENU_MENUITEM_DISPOSITION_ALERT "alert"
+
+/* ***************************************** */
+/* ********* Dbusmenu Events ********* */
+/* ***************************************** */
/**
* DBUSMENU_MENUITEM_EVENT_ACTIVATED:
*
diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c
index 7bfac3a..9c085f7 100644
--- a/libdbusmenu-glib/server.c
+++ b/libdbusmenu-glib/server.c
@@ -455,6 +455,7 @@ set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
g_return_if_fail(priv->bus_lookup != NULL);
}
+ g_object_ref(obj);
g_bus_get(G_BUS_TYPE_SESSION, priv->bus_lookup, bus_got_cb, obj);
} else {
register_object(DBUSMENU_SERVER(obj));
@@ -694,6 +695,7 @@ bus_got_cb (GObject * obj, GAsyncResult * result, gpointer user_data)
if (error != NULL) {
g_warning("Unable to get session bus: %s", error->message);
g_error_free(error);
+ g_object_unref(G_OBJECT(user_data));
return;
}
@@ -706,6 +708,7 @@ bus_got_cb (GObject * obj, GAsyncResult * result, gpointer user_data)
register_object(DBUSMENU_SERVER(user_data));
+ g_object_unref(G_OBJECT(user_data));
return;
}
@@ -949,11 +952,13 @@ menuitem_property_idle (gpointer user_data)
}
}
+ /* these are going to be standard references in all code paths and must be unrefed */
GVariant * megadata[2];
gboolean gotsomething = FALSE;
if (item_init) {
megadata[0] = g_variant_builder_end(&itembuilder);
+ g_variant_ref_sink(megadata[0]);
gotsomething = TRUE;
} else {
GError * error = NULL;
@@ -967,13 +972,14 @@ menuitem_property_idle (gpointer user_data)
if (removeitem_init) {
megadata[1] = g_variant_builder_end(&removeitembuilder);
+ g_variant_ref_sink(megadata[1]);
gotsomething = TRUE;
} else {
GError * error = NULL;
- megadata[1] = g_variant_parse(G_VARIANT_TYPE("a(ia(s))"), "[ ]", NULL, NULL, &error);
+ megadata[1] = g_variant_parse(G_VARIANT_TYPE("a(ias)"), "[ ]", NULL, NULL, &error);
if (error != NULL) {
- g_warning("Unable to parse '[ ]' as a 'a(ia(s))': %s", error->message);
+ g_warning("Unable to parse '[ ]' as a 'a(ias)': %s", error->message);
g_error_free(error);
}
}
@@ -983,14 +989,14 @@ menuitem_property_idle (gpointer user_data)
NULL,
priv->dbusobject,
DBUSMENU_INTERFACE,
- "ItemPropertiesUpdated",
+ "ItemsPropertiesUpdated",
g_variant_new_tuple(megadata, 2),
NULL);
- } else {
- g_variant_unref(megadata[0]);
- g_variant_unref(megadata[1]);
}
+ g_variant_unref(megadata[0]);
+ g_variant_unref(megadata[1]);
+
/* Clean everything up */
prop_array_teardown(priv->prop_array);
priv->prop_array = NULL;
@@ -1193,9 +1199,11 @@ bus_get_layout (DbusmenuServer * server, GVariant * params, GDBusMethodInvocatio
g_return_if_fail(priv != NULL);
/* Input */
- gint parent = g_variant_get_int32(g_variant_get_child_value(params, 0));
- gint recurse = g_variant_get_int32(g_variant_get_child_value(params, 1));
- const gchar ** props = g_variant_get_strv(g_variant_get_child_value(params, 2), NULL);
+ gint32 parent;
+ gint32 recurse;
+ const gchar ** props;
+
+ g_variant_get(params, "(ii^a&s)", &parent, &recurse, &props);
/* Output */
guint revision = priv->layout_revision;
@@ -1208,6 +1216,7 @@ bus_get_layout (DbusmenuServer * server, GVariant * params, GDBusMethodInvocatio
items = dbusmenu_menuitem_build_variant(mi, props, recurse);
}
}
+ g_free(props);
/* What happens if we don't have anything? */
if (items == NULL) {
@@ -1254,9 +1263,11 @@ bus_get_property (DbusmenuServer * server, GVariant * params, GDBusMethodInvocat
"There currently isn't a layout in this server");
return;
}
-
- gint id = g_variant_get_int32(g_variant_get_child_value(params, 0));
- const gchar * property = g_variant_get_string(g_variant_get_child_value(params, 1), NULL);
+
+ gint32 id;
+ const gchar * property;
+
+ g_variant_get(params, "(i&s)", &id, &property);
DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
@@ -1298,7 +1309,8 @@ bus_get_properties (DbusmenuServer * server, GVariant * params, GDBusMethodInvoc
return;
}
- gint id = g_variant_get_int32(g_variant_get_child_value(params, 0));
+ gint32 id;
+ g_variant_get(params, "(i)", &id);
DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
@@ -1326,28 +1338,43 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
if (priv->root == NULL) {
+ /* Allow a request for just id 0 when root is null. Return no properties.
+ So that a request always returns a valid structure no matter the
+ state of the structure in the server.
+ */
GVariant * idlist = g_variant_get_child_value(params, 0);
- if (g_variant_n_children(idlist) == 1 && g_variant_get_int32(g_variant_get_child_value(idlist, 0)) == 0) {
- GVariant * final = g_variant_parse(g_variant_type_new("(a(ia{sv}))"), "([(0, {})],)", NULL, NULL, NULL);
- g_dbus_method_invocation_return_value(invocation, final);
- return;
- }
+ if (g_variant_n_children(idlist) == 1) {
- g_dbus_method_invocation_return_error(invocation,
- error_quark(),
- NO_VALID_LAYOUT,
- "There currently isn't a layout in this server");
+ GVariant *id_v = g_variant_get_child_value(idlist, 0);
+ gint32 id = g_variant_get_int32(id_v);
+ g_variant_unref(id_v);
+
+ if (id == 0) {
+
+ GVariant * final = g_variant_parse(G_VARIANT_TYPE("(a(ia{sv}))"), "([(0, {})],)", NULL, NULL, NULL);
+ g_dbus_method_invocation_return_value(invocation, final);
+ g_variant_unref(final);
+ }
+ } else {
+
+ g_dbus_method_invocation_return_error(invocation,
+ error_quark(),
+ NO_VALID_LAYOUT,
+ "There currently isn't a layout in this server");
+ }
+ g_variant_unref(idlist);
return;
}
- GVariantIter ids;
- g_variant_iter_init(&ids, g_variant_get_child_value(params, 0));
+ GVariantIter *ids;
+ g_variant_get(params, "(aias)", &ids, NULL);
+ /* TODO: implementation ignores propertyNames declared in XML */
GVariantBuilder builder;
gboolean builder_init = FALSE;
- gint id;
- while (g_variant_iter_next(&ids, "i", &id)) {
+ gint32 id;
+ while (g_variant_iter_loop(ids, "i", &id)) {
DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
if (mi == NULL) continue;
@@ -1363,7 +1390,7 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
if (props == NULL) {
GError * error = NULL;
- props = g_variant_parse(g_variant_type_new("a{sv}"), "{}", NULL, NULL, &error);
+ props = g_variant_parse(G_VARIANT_TYPE("a{sv}"), "{}", NULL, NULL, &error);
if (error != NULL) {
g_warning("Unable to parse '{}' as a 'a{sv}': %s", error->message);
g_error_free(error);
@@ -1376,18 +1403,20 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
g_variant_builder_add_value(&builder, mi_data);
}
+ g_variant_iter_free(ids);
+ /* a standard reference that must be unrefed */
GVariant * ret = NULL;
if (builder_init) {
ret = g_variant_builder_end(&builder);
+ g_variant_ref_sink(ret);
} else {
GError * error = NULL;
- ret = g_variant_parse(g_variant_type_new("a(ia{sv})"), "[]", NULL, NULL, NULL);
+ ret = g_variant_parse(G_VARIANT_TYPE("a(ia{sv})"), "[]", NULL, NULL, &error);
if (error != NULL) {
g_warning("Unable to parse '[]' as a 'a(ia{sv})': %s", error->message);
g_error_free(error);
- ret = NULL;
}
}
@@ -1395,6 +1424,7 @@ bus_get_group_properties (DbusmenuServer * server, GVariant * params, GDBusMetho
if (ret != NULL) {
g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
g_variant_builder_add_value(&builder, ret);
+ g_variant_unref(ret);
final = g_variant_builder_end(&builder);
} else {
g_warning("Error building property list, final variant is NULL");
@@ -1433,7 +1463,8 @@ static void
bus_get_children (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * invocation)
{
DbusmenuServerPrivate * priv = DBUSMENU_SERVER_GET_PRIVATE(server);
- gint id = g_variant_get_int32(g_variant_get_child_value(params, 0));
+ gint32 id;
+ g_variant_get(params, "(i)", &id);
if (priv->root == NULL) {
g_dbus_method_invocation_return_error(invocation,
@@ -1467,7 +1498,7 @@ bus_get_children (DbusmenuServer * server, GVariant * params, GDBusMethodInvocat
ret = g_variant_new_tuple(&end, 1);
} else {
GError * error = NULL;
- ret = g_variant_parse(g_variant_type_new("(a(ia{sv}))"), "([(0, {})],)", NULL, NULL, &error);
+ ret = g_variant_parse(G_VARIANT_TYPE("(a(ia{sv}))"), "([(0, {})],)", NULL, NULL, &error);
if (error != NULL) {
g_warning("Unable to parse '([(0, {})],)' as a '(a(ia{sv}))': %s", error->message);
g_error_free(error);
@@ -1519,32 +1550,35 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i
return;
}
- gint id = g_variant_get_int32(g_variant_get_child_value(params, 0));
+ gint32 id;
+ gchar *etype;
+ GVariant *data;
+ guint32 ts;
+
+ g_variant_get(params, "(isvu)", &id, &etype, &data, &ts);
+
DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
if (mi == NULL) {
+
g_dbus_method_invocation_return_error(invocation,
error_quark(),
INVALID_MENUITEM_ID,
"The ID supplied %d does not refer to a menu item we have",
id);
- return;
- }
-
- idle_event_t * event_data = g_new0(idle_event_t, 1);
- event_data->mi = mi;
- g_object_ref(event_data->mi);
- event_data->eventid = g_strdup(g_variant_get_string(g_variant_get_child_value(params, 1), NULL));
- event_data->timestamp = g_variant_get_uint32(g_variant_get_child_value(params, 3));
- event_data->variant = g_variant_get_child_value(params, 2);
+ g_free(etype);
+ g_variant_unref(data);
- if (g_variant_is_of_type(event_data->variant, G_VARIANT_TYPE_VARIANT)) {
- event_data->variant = g_variant_get_variant(event_data->variant);
- }
+ } else {
- g_variant_ref_sink(event_data->variant);
+ idle_event_t * event_data = g_new0(idle_event_t, 1);
+ event_data->mi = g_object_ref(mi);
+ event_data->eventid = etype;
+ event_data->timestamp = ts;
+ event_data->variant = data; /* give away our reference */
- g_timeout_add(0, event_local_handler, event_data);
+ g_timeout_add(0, event_local_handler, event_data);
+ }
g_dbus_method_invocation_return_value(invocation, NULL);
return;
@@ -1564,7 +1598,8 @@ bus_about_to_show (DbusmenuServer * server, GVariant * params, GDBusMethodInvoca
return;
}
- gint id = g_variant_get_int32(g_variant_get_child_value(params, 0));
+ gint32 id;
+ g_variant_get(params, "(i)", &id);
DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id);
if (mi == NULL) {
diff --git a/libdbusmenu-gtk/Makefile.am b/libdbusmenu-gtk/Makefile.am
index aa36445..b4564d1 100644
--- a/libdbusmenu-gtk/Makefile.am
+++ b/libdbusmenu-gtk/Makefile.am
@@ -1,6 +1,4 @@
-CLEANFILES =
-
if USE_GTK3
VER=3
GTKGIR=Gtk-3.0
@@ -13,10 +11,28 @@ GTKVALA=gtk+-2.0
lib_LTLIBRARIES = libdbusmenu-gtk.la
endif
+BUILT_SOURCES =
+CLEANFILES =
+DISTCLEANFILES =
EXTRA_DIST = \
dbusmenu-gtk-0.4.pc.in \
dbusmenu-gtk3-0.4.pc.in
+##############
+# Enum Stuff
+##############
+
+include $(top_srcdir)/Makefile.am.enum
+
+glib_enum_h = genericmenuitem-enum-types.h
+glib_enum_c = genericmenuitem-enum-types.c
+glib_enum_headers = $(srcdir)/genericmenuitem.h
+
+
+#####################
+# Include Directory
+#####################
+
libdbusmenu_gtkincludedir=$(includedir)/libdbusmenu-0.4/libdbusmenu-gtk$(VER)/
libdbusmenu_gtkinclude_HEADERS = \
@@ -24,22 +40,21 @@ libdbusmenu_gtkinclude_HEADERS = \
client.h \
menu.h \
menuitem.h \
- parser.h \
- serializablemenuitem.h
+ parser.h
libdbusmenu_gtk_la_SOURCES = \
client.h \
client.c \
genericmenuitem.h \
genericmenuitem.c \
+ genericmenuitem-enum-types.h \
+ genericmenuitem-enum-types.c \
menu.h \
menu.c \
menuitem.h \
menuitem.c \
parser.h \
- parser.c \
- serializablemenuitem.h \
- serializablemenuitem.c
+ parser.c
libdbusmenu_gtk_la_LDFLAGS = \
-version-info $(LIBDBUSMENU_CURRENT):$(LIBDBUSMENU_REVISION):$(LIBDBUSMENU_AGE) \
@@ -92,7 +107,7 @@ INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir) --includedir=$(top_buildd
if HAVE_INTROSPECTION
-introspection_sources = $(filter-out genericmenuitem.%, $(libdbusmenu_gtkinclude_HEADERS) $(libdbusmenu_gtk_la_SOURCES))
+introspection_sources = $(filter-out genericmenuitem%, $(libdbusmenu_gtkinclude_HEADERS) $(libdbusmenu_gtk_la_SOURCES))
DbusmenuGtk$(VER)-0.4.gir: libdbusmenu-gtk$(VER).la
DbusmenuGtk_0_4_gir_INCLUDES = \
@@ -129,6 +144,7 @@ endif
# VAPI Files
#########################
+if HAVE_VALA
if HAVE_INTROSPECTION
vapidir = $(datadir)/vala/vapi
@@ -152,4 +168,5 @@ DbusmenuGtk$(VER)-0.4.tmp.gir: DbusmenuGtk$(VER)-0.4.gir
CLEANFILES += $(vapi_DATA) DbusmenuGtk$(VER)-0.4.tmp.gir
endif
+endif
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
index 7f05d46..1051f20 100644
--- a/libdbusmenu-gtk/client.c
+++ b/libdbusmenu-gtk/client.c
@@ -31,10 +31,12 @@ License version 3 and version 2.1 along with this program. If not, see
#endif
#include <gtk/gtk.h>
+#include <glib.h>
#include "client.h"
#include "menuitem.h"
#include "genericmenuitem.h"
+#include "genericmenuitem-enum-types.h"
/* Private */
struct _DbusmenuGtkClientPrivate {
@@ -59,6 +61,7 @@ static void move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint n
static void item_activate (DbusmenuClient * client, DbusmenuMenuitem * mi, guint timestamp, gpointer userdata);
static void theme_dir_changed (DbusmenuClient * client, GStrv theme_dirs, gpointer userdata);
static void remove_theme_dirs (GtkIconTheme * theme, GStrv dirs);
+static void event_result (DbusmenuClient * client, DbusmenuMenuitem * mi, const gchar * event, GVariant * variant, guint timestamp, GError * error);
static gboolean new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
static gboolean new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
@@ -119,6 +122,7 @@ dbusmenu_gtkclient_init (DbusmenuGtkClient *self)
g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM, G_CALLBACK(new_menuitem), NULL);
g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_ITEM_ACTIVATE, G_CALLBACK(item_activate), NULL);
g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_ICON_THEME_DIRS_CHANGED, G_CALLBACK(theme_dir_changed), NULL);
+ g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_EVENT_RESULT, G_CALLBACK(event_result), NULL);
theme_dir_changed(DBUSMENU_CLIENT(self), dbusmenu_client_get_icon_paths(DBUSMENU_CLIENT(self)), NULL);
@@ -448,8 +452,97 @@ dbusmenu_gtkclient_get_accel_group (DbusmenuGtkClient * client)
/* Internal Functions */
-static const gchar * data_menuitem = "dbusmenugtk-data-gtkmenuitem";
-static const gchar * data_menu = "dbusmenugtk-data-gtkmenu";
+static const gchar * data_menuitem = "dbusmenugtk-data-gtkmenuitem";
+static const gchar * data_menu = "dbusmenugtk-data-gtkmenu";
+static const gchar * data_activating = "dbusmenugtk-data-activating";
+static const gchar * data_idle_close_id = "dbusmenugtk-data-idle-close-id";
+static const gchar * data_delayed_close = "dbusmenugtk-data-delayed-close";
+
+static void
+menu_item_start_activating(DbusmenuMenuitem * mi)
+{
+ /* Mark this item and all it's parents as activating */
+ DbusmenuMenuitem * parent = mi;
+ do {
+ g_object_set_data(G_OBJECT(parent), data_activating,
+ GINT_TO_POINTER(TRUE));
+ } while ((parent = dbusmenu_menuitem_get_parent (parent)) != NULL);
+
+ GVariant * variant = g_variant_new("i", 0);
+ dbusmenu_menuitem_handle_event(mi, DBUSMENU_MENUITEM_EVENT_ACTIVATED, variant, gtk_get_current_event_time());
+}
+
+static gboolean
+menu_item_is_activating(DbusmenuMenuitem * mi)
+{
+ return GPOINTER_TO_INT(g_object_get_data(G_OBJECT(mi), data_activating));
+}
+
+static void
+menu_item_stop_activating(DbusmenuMenuitem * mi)
+{
+ if (!menu_item_is_activating(mi))
+ return;
+
+ /* Mark this item and all it's parents as not activating and finally
+ send their queued close event. */
+ g_object_set_data(G_OBJECT(mi), data_activating, GINT_TO_POINTER(FALSE));
+
+ /* There is one master root parent that we don't care about, so stop
+ right before it */
+ DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (mi);
+ while (dbusmenu_menuitem_get_parent (parent) != NULL &&
+ menu_item_is_activating(parent)) {
+ /* Now clean up the activating flag */
+ g_object_set_data(G_OBJECT(parent), data_activating,
+ GINT_TO_POINTER(FALSE));
+
+ gboolean should_close = FALSE;
+
+ /* Note that dbus might be fast enough to have already
+ processed the app's reply before close_in_idle() is called.
+ So to avoid that, we shut down any pending close_in_idle call */
+ guint id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(parent),
+ data_idle_close_id));
+ if (id > 0) {
+ g_source_remove(id);
+ g_object_set_data(G_OBJECT(parent), data_idle_close_id,
+ GINT_TO_POINTER(0));
+ should_close = TRUE;
+ }
+
+ gboolean delayed = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(mi),
+ data_delayed_close));
+ if (delayed) {
+ g_object_set_data(G_OBJECT(mi), data_delayed_close,
+ GINT_TO_POINTER(FALSE));
+ should_close = TRUE;
+ }
+
+ /* And finally send a delayed closed event if one would have
+ happened */
+ if (should_close) {
+ dbusmenu_menuitem_handle_event(parent,
+ DBUSMENU_MENUITEM_EVENT_CLOSED,
+ NULL,
+ gtk_get_current_event_time());
+ }
+
+ parent = dbusmenu_menuitem_get_parent (parent);
+ }
+}
+
+static void
+event_result (DbusmenuClient * client, DbusmenuMenuitem * mi,
+ const gchar * event, GVariant * variant, guint timestamp,
+ GError * error)
+{
+ if (g_strcmp0(event, DBUSMENU_MENUITEM_EVENT_ACTIVATED) == 0) {
+ menu_item_stop_activating(mi);
+ }
+
+ return;
+}
/* This is the call back for the GTK widget for when it gets
clicked on by the user to send it back across the bus. */
@@ -457,8 +550,7 @@ static gboolean
menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
{
if (gtk_menu_item_get_submenu(gmi) == NULL) {
- GVariant * variant = g_variant_new("i", 0);
- dbusmenu_menuitem_handle_event(mi, DBUSMENU_MENUITEM_EVENT_ACTIVATED, variant, gtk_get_current_event_time());
+ menu_item_start_activating(mi);
} else {
/* TODO: We need to stop the display of the submenu
until this callback returns. */
@@ -467,13 +559,42 @@ menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
return TRUE;
}
+static gboolean
+close_in_idle (DbusmenuMenuitem * mi)
+{
+ /* Don't send closed signal if we also sent activating signal.
+ We'd just be asking for race conditions. We'll send closed
+ when done with activation. */
+ if (!menu_item_is_activating(mi))
+ dbusmenu_menuitem_handle_event(mi, DBUSMENU_MENUITEM_EVENT_CLOSED, NULL, gtk_get_current_event_time());
+ else
+ g_object_set_data(G_OBJECT(mi), data_delayed_close, GINT_TO_POINTER(TRUE));
+
+ g_object_set_data(G_OBJECT(mi), data_idle_close_id, GINT_TO_POINTER(0));
+ return FALSE;
+}
+
static void
submenu_notify_visible_cb (GtkWidget * menu, GParamSpec * pspec, DbusmenuMenuitem * mi)
{
- if (gtk_widget_get_visible (menu))
- dbusmenu_menuitem_handle_event(mi, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, gtk_get_current_event_time());
- else
- dbusmenu_menuitem_handle_event(mi, DBUSMENU_MENUITEM_EVENT_CLOSED, NULL, gtk_get_current_event_time());
+ if (gtk_widget_get_visible (menu)) {
+ menu_item_stop_activating(mi); /* just in case */
+ dbusmenu_menuitem_handle_event(mi, DBUSMENU_MENUITEM_EVENT_OPENED, NULL, gtk_get_current_event_time());
+ } else {
+ /* Try to close in the idle loop because we actually get a menu
+ close notification before we get notified that a menu item
+ was clicked. We want to give that clicked signal some
+ time, so we wait until all queued signals are handled before
+ continuing. (our handling of the closed signal depends on
+ whether the user clicked an item or not) */
+ guint id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(mi),
+ data_idle_close_id));
+ if (id == 0) {
+ id = g_idle_add((GSourceFunc)close_in_idle, mi);
+ g_object_set_data(G_OBJECT(mi), data_idle_close_id,
+ GINT_TO_POINTER(id));
+ }
+ }
}
/* Process the visible property */
@@ -571,7 +692,8 @@ process_submenu (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * variant, D
} else {
/* We need to build a menu for these guys to live in. */
GtkMenu * menu = GTK_MENU(gtk_menu_new());
- g_object_set_data(G_OBJECT(mi), data_menu, menu);
+ g_object_ref_sink(menu);
+ g_object_set_data_full(G_OBJECT(mi), data_menu, menu, g_object_unref);
gtk_menu_item_set_submenu(gmi, GTK_WIDGET(menu));
@@ -581,6 +703,20 @@ process_submenu (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * variant, D
return;
}
+/* Process the disposition changing */
+static void
+process_disposition (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * variant, DbusmenuGtkClient * gtkclient)
+{
+ /* We can only handle generic menu items here. Perhaps someone else
+ will find the value useful. Not us. */
+ if (!IS_GENERICMENUITEM(gmi)) {
+ return;
+ }
+
+ genericmenuitem_set_disposition(GENERICMENUITEM(gmi), genericmenuitem_disposition_get_value_from_nick(g_variant_get_string(variant, NULL)));
+ return;
+}
+
/* Whenever we have a property change on a DbusmenuMenuitem
we need to be responsive to that. */
static void
@@ -600,6 +736,8 @@ menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * variant, Db
process_toggle_state(mi, gmi, variant);
} else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY)) {
process_submenu(mi, gmi, variant, gtkclient);
+ } else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_DISPOSITION)) {
+ process_disposition(mi, gmi, variant, gtkclient);
}
return;
@@ -616,19 +754,6 @@ menu_shortcut_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value,
return;
}
-/* Call back that happens when the DbusmenuMenuitem
- is destroyed. We're making sure to clean up everything
- else down the pipe. */
-static void
-destoryed_dbusmenuitem_cb (gpointer udata, GObject * dbusmenuitem)
-{
- #ifdef MASSIVEDEBUGGING
- g_debug("DbusmenuMenuitem was destroyed");
- #endif
- gtk_widget_destroy(GTK_WIDGET(udata));
- return;
-}
-
/* The new menuitem signal only happens if we don't have a type handler
for the type of the item. This should be an error condition and we're
printing out a message. */
@@ -731,11 +856,8 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem *
#endif
/* Attach these two */
- g_object_set_data(G_OBJECT(item), data_menuitem, gmi);
- g_object_ref(G_OBJECT(gmi));
- #ifdef MASSIVEDEBUGGING
- g_signal_connect(G_OBJECT(gmi), "destroy", G_CALLBACK(destroy_gmi), item);
- #endif
+ g_object_ref_sink(G_OBJECT(gmi));
+ g_object_set_data_full(G_OBJECT(item), data_menuitem, gmi, (GDestroyNotify)gtk_widget_destroy);
/* DbusmenuMenuitem signals */
g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), client);
@@ -746,15 +868,13 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem *
/* GtkMenuitem signals */
g_signal_connect(G_OBJECT(gmi), "activate", G_CALLBACK(menu_pressed_cb), item);
- /* Life insurance */
- g_object_weak_ref(G_OBJECT(item), destoryed_dbusmenuitem_cb, gmi);
-
/* Check our set of props to see if any are set already */
process_visible(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_VISIBLE));
process_sensitive(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_ENABLED));
process_toggle_type(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE));
process_toggle_state(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE));
process_submenu(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY), client);
+ process_disposition(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_DISPOSITION), client);
refresh_shortcut(client, item);
/* Oh, we're a child, let's deal with that */
@@ -801,7 +921,7 @@ delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, DbusmenuGtkClient
if (menu != NULL) {
gtk_widget_destroy(GTK_WIDGET(menu));
- g_object_set_data(G_OBJECT(mi), data_menu, NULL);
+ g_object_steal_data(G_OBJECT(mi), data_menu);
}
}
@@ -905,11 +1025,10 @@ new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusmenu
GtkMenuItem * gmi;
gmi = GTK_MENU_ITEM(g_object_new(GENERICMENUITEM_TYPE, NULL));
- gtk_menu_item_set_label(gmi, dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_LABEL));
if (gmi != NULL) {
+ gtk_menu_item_set_label(gmi, dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_LABEL));
dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
- g_object_unref(gmi);
} else {
return FALSE;
}
diff --git a/libdbusmenu-gtk/dbusmenu-gtk.h b/libdbusmenu-gtk/dbusmenu-gtk.h
index f2fe5be..de63c61 100644
--- a/libdbusmenu-gtk/dbusmenu-gtk.h
+++ b/libdbusmenu-gtk/dbusmenu-gtk.h
@@ -36,6 +36,5 @@ License version 3 and version 2.1 along with this program. If not, see
#include <libdbusmenu-gtk/client.h>
#include <libdbusmenu-gtk/menu.h>
#include <libdbusmenu-gtk/menuitem.h>
-#include <libdbusmenu-gtk/serializablemenuitem.h>
#endif /* __DBUSMENU_GLIB_H__ */
diff --git a/libdbusmenu-gtk/genericmenuitem-enum-types.c.in b/libdbusmenu-gtk/genericmenuitem-enum-types.c.in
new file mode 100644
index 0000000..8b2c046
--- /dev/null
+++ b/libdbusmenu-gtk/genericmenuitem-enum-types.c.in
@@ -0,0 +1,116 @@
+/*** BEGIN file-header ***/
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+ the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#include "genericmenuitem-enum-types.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+#include "@basename@"
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+/**
+ @enum_name@_get_type:
+
+ Builds a GLib type for the #@EnumName@ enumeration.
+
+ Return value: A unique #GType for the #@EnumName@ enum.
+*/
+GType
+@enum_name@_get_type (void)
+{
+ static GType etype = 0;
+ if (G_UNLIKELY(etype == 0)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL}
+ };
+
+ etype = g_@type@_register_static (g_intern_static_string("@EnumName@"), values);
+ }
+
+ return etype;
+}
+
+/**
+ @enum_name@_get_nick:
+ @value: The value of @EnumName@ to get the nick of
+
+ Looks up in the enum table for the nick of @value.
+
+ Return value: The nick for the given value or #NULL on error
+*/
+const gchar *
+@enum_name@_get_nick (@EnumName@ value)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(@enum_name@_get_type()));
+ g_return_val_if_fail(class != NULL, NULL);
+
+ const gchar * ret = NULL;
+ GEnumValue * val = g_enum_get_value(class, value);
+ if (val != NULL) {
+ ret = val->value_nick;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+/**
+ @enum_name@_get_value_from_nick:
+ @nick: The enum nick to lookup
+
+ Looks up in the enum table for the value of @nick.
+
+ Return value: The value for the given @nick
+*/
+@EnumName@
+@enum_name@_get_value_from_nick (const gchar * nick)
+{
+ GEnumClass * class = G_ENUM_CLASS(g_type_class_ref(@enum_name@_get_type()));
+ g_return_val_if_fail(class != NULL, 0);
+
+ @EnumName@ ret = 0;
+ GEnumValue * val = g_enum_get_value_by_nick(class, nick);
+ if (val != NULL) {
+ ret = val->value;
+ }
+
+ g_type_class_unref(class);
+ return ret;
+}
+
+
+/*** END value-tail ***/
diff --git a/libdbusmenu-gtk/genericmenuitem-enum-types.h.in b/libdbusmenu-gtk/genericmenuitem-enum-types.h.in
new file mode 100644
index 0000000..5758438
--- /dev/null
+++ b/libdbusmenu-gtk/genericmenuitem-enum-types.h.in
@@ -0,0 +1,65 @@
+/*** BEGIN file-header ***/
+/*
+Enums from the dbusmenu headers
+
+Copyright 2011 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+ the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+<http://www.gnu.org/licenses/>
+*/
+
+#ifndef __DBUSMENU_ENUM_TYPES_H__
+#define __DBUSMENU_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+#endif /* __DBUSMENU_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
+/*** BEGIN file-production ***/
+/* Enumerations from file: "@filename@" */
+#include "@basename@"
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+const gchar * @enum_name@_get_nick (@EnumName@ value) G_GNUC_CONST;
+@EnumName@ @enum_name@_get_value_from_nick (const gchar * nick) G_GNUC_CONST;
+
+/**
+ DBUSMENU_TYPE_@ENUMSHORT@:
+
+ Gets the #GType value for the type associated with the
+ #@EnumName@ enumerated type.
+*/
+#define DBUSMENU_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
+
+/*** END value-header ***/
diff --git a/libdbusmenu-gtk/genericmenuitem.c b/libdbusmenu-gtk/genericmenuitem.c
index 3652ceb..5488f93 100644
--- a/libdbusmenu-gtk/genericmenuitem.c
+++ b/libdbusmenu-gtk/genericmenuitem.c
@@ -30,6 +30,8 @@ License version 3 and version 2.1 along with this program. If not, see
#include "config.h"
#endif
+#include <gdk/gdk.h>
+
#include "genericmenuitem.h"
/*
@@ -40,6 +42,7 @@ License version 3 and version 2.1 along with this program. If not, see
struct _GenericmenuitemPrivate {
GenericmenuitemCheckType check_type;
GenericmenuitemState state;
+ GenericmenuitemDisposition disposition;
};
/* Private macro */
@@ -102,6 +105,7 @@ genericmenuitem_init (Genericmenuitem *self)
self->priv->check_type = GENERICMENUITEM_CHECK_TYPE_NONE;
self->priv->state = GENERICMENUITEM_STATE_UNCHECKED;
+ self->priv->disposition = GENERICMENUITEM_DISPOSITION_NORMAL;
return;
}
@@ -165,18 +169,61 @@ set_label_helper (GtkWidget * widget, gpointer data)
style. It should be considered for caching when
optimizing. */
static gint
-get_hpadding (GtkWidget * widget)
+get_toggle_space (GtkWidget * widget)
{
gint padding = 0;
- gtk_widget_style_get(widget, "horizontal-padding", &padding, NULL);
+ gtk_widget_style_get(widget, "toggle-spacing", &padding, NULL);
return padding;
}
+/* Get the value to put in the span for the disposition */
+static gchar *
+get_text_color (GenericmenuitemDisposition disposition, GtkWidget * widget)
+{
+ struct {const gchar * color_name; const gchar * default_color;} values[] = {
+ /* NORMAL */ { NULL, NULL},
+ /* INFO */ { "informational-color", "blue"},
+ /* WARN */ { "warning-color", "orange"},
+ /* ALERT */ { "error-color", "red"}
+ };
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+ GtkStyleContext * context = gtk_widget_get_style_context(widget);
+ GdkRGBA color;
+
+ if (gtk_style_context_lookup_color(context, values[disposition].color_name, &color)) {
+ return g_strdup_printf("rgb(%d, %d, %d)", (gint)(color.red * 255), (gint)(color.green * 255), (gint)(color.blue * 255));
+ }
+#endif
+
+ return g_strdup(values[disposition].default_color);
+}
+
/* Set the label on the item */
static void
-set_label (GtkMenuItem * menu_item, const gchar * label)
+set_label (GtkMenuItem * menu_item, const gchar * in_label)
{
- if (label == NULL) return;
+ if (in_label == NULL) return;
+
+ /* Build a label that might include the colors of the disposition
+ so that it gets rendered in the menuitem. */
+ gchar * local_label = NULL;
+ switch (GENERICMENUITEM(menu_item)->priv->disposition) {
+ case GENERICMENUITEM_DISPOSITION_NORMAL:
+ local_label = g_strdup(in_label);
+ break;
+ case GENERICMENUITEM_DISPOSITION_INFORMATIONAL:
+ case GENERICMENUITEM_DISPOSITION_WARNING:
+ case GENERICMENUITEM_DISPOSITION_ALERT: {
+ gchar * color = get_text_color(GENERICMENUITEM(menu_item)->priv->disposition, GTK_WIDGET(menu_item));
+ local_label = g_markup_printf_escaped("<span fgcolor=\"%s\">%s</span>", color, in_label);
+ g_free(color);
+ break;
+ }
+ default:
+ g_warn_if_reached();
+ break;
+ }
GtkWidget * child = gtk_bin_get_child(GTK_BIN(menu_item));
GtkLabel * labelw = NULL;
@@ -194,10 +241,10 @@ set_label (GtkMenuItem * menu_item, const gchar * label)
/* We need to put the child into a new box and
make the box the child of the menu item. Basically
we're inserting a box in the middle. */
- GtkWidget * hbox = gtk_hbox_new(FALSE, 0);
+ GtkWidget * hbox = gtk_hbox_new(FALSE, get_toggle_space(GTK_WIDGET(menu_item)));
g_object_ref(child);
gtk_container_remove(GTK_CONTAINER(menu_item), child);
- gtk_box_pack_start(GTK_BOX(hbox), child, FALSE, FALSE, get_hpadding(GTK_WIDGET(menu_item)));
+ gtk_box_pack_start(GTK_BOX(hbox), child, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(menu_item), hbox);
gtk_widget_show(hbox);
g_object_unref(child);
@@ -211,10 +258,12 @@ set_label (GtkMenuItem * menu_item, const gchar * label)
update the one that we already have. */
if (labelw == NULL) {
/* Build it */
- labelw = GTK_LABEL(gtk_accel_label_new(label));
+ labelw = GTK_LABEL(gtk_accel_label_new(local_label));
gtk_label_set_use_underline(GTK_LABEL(labelw), TRUE);
+ gtk_label_set_use_markup(GTK_LABEL(labelw), TRUE);
gtk_misc_set_alignment(GTK_MISC(labelw), 0.0, 0.5);
gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(labelw), GTK_WIDGET(menu_item));
+ gtk_label_set_markup_with_mnemonic(labelw, local_label);
gtk_widget_show(GTK_WIDGET(labelw));
/* Check to see if it needs to be in the bin for this
@@ -222,17 +271,17 @@ set_label (GtkMenuItem * menu_item, const gchar * label)
if (child == NULL) {
gtk_container_add(GTK_CONTAINER(menu_item), GTK_WIDGET(labelw));
} else {
- gtk_box_pack_end(GTK_BOX(child), GTK_WIDGET(labelw), TRUE, TRUE, get_hpadding(GTK_WIDGET(menu_item)));
+ gtk_box_pack_end(GTK_BOX(child), GTK_WIDGET(labelw), TRUE, TRUE, 0);
}
} else {
/* Oh, just an update. No biggie. */
- if (!g_strcmp0(label, gtk_label_get_label(labelw))) {
+ if (!g_strcmp0(local_label, gtk_label_get_label(labelw))) {
/* The only reason to suppress the update is if we had
a label and the value was the same as the one we're
getting in. */
suppress_update = TRUE;
} else {
- gtk_label_set_label(labelw, label);
+ gtk_label_set_markup_with_mnemonic(labelw, local_label);
}
}
@@ -241,6 +290,12 @@ set_label (GtkMenuItem * menu_item, const gchar * label)
g_object_notify(G_OBJECT(menu_item), "label");
}
+ /* Clean up this */
+ if (local_label != NULL) {
+ g_free(local_label);
+ local_label = NULL;
+ }
+
return;
}
@@ -401,10 +456,10 @@ genericmenuitem_set_image (Genericmenuitem * menu_item, GtkWidget * image)
/* We need to put the child into a new box and
make the box the child of the menu item. Basically
we're inserting a box in the middle. */
- GtkWidget * hbox = gtk_hbox_new(FALSE, 0);
+ GtkWidget * hbox = gtk_hbox_new(FALSE, get_toggle_space(GTK_WIDGET(menu_item)));
g_object_ref(child);
gtk_container_remove(GTK_CONTAINER(menu_item), child);
- gtk_box_pack_end(GTK_BOX(hbox), child, TRUE, TRUE, get_hpadding(GTK_WIDGET(menu_item)));
+ gtk_box_pack_end(GTK_BOX(hbox), child, TRUE, TRUE, 0);
gtk_container_add(GTK_CONTAINER(menu_item), hbox);
gtk_widget_show(hbox);
g_object_unref(child);
@@ -429,7 +484,7 @@ genericmenuitem_set_image (Genericmenuitem * menu_item, GtkWidget * image)
if (child == NULL) {
gtk_container_add(GTK_CONTAINER(menu_item), GTK_WIDGET(image));
} else {
- gtk_box_pack_start(GTK_BOX(child), GTK_WIDGET(image), FALSE, FALSE, get_hpadding(GTK_WIDGET(menu_item)));
+ gtk_box_pack_start(GTK_BOX(child), GTK_WIDGET(image), FALSE, FALSE, 0);
}
gtk_widget_show(image);
@@ -466,3 +521,41 @@ genericmenuitem_get_image (Genericmenuitem * menu_item)
return imagew;
}
+
+/**
+ * genericmenuitem_set_disposition:
+ * @item: A #Genericmenuitem
+ * @disposition: The disposition of the item
+ *
+ * Sets the disposition of the menuitem.
+ */
+void
+genericmenuitem_set_disposition (Genericmenuitem * item, GenericmenuitemDisposition disposition)
+{
+ g_return_if_fail(IS_GENERICMENUITEM(item));
+
+ if (item->priv->disposition == disposition)
+ return;
+
+ item->priv->disposition = disposition;
+
+ set_label(GTK_MENU_ITEM(item), get_label(GTK_MENU_ITEM(item)));
+
+ return;
+}
+
+/**
+ * genericmenuitem_get_disposition:
+ * @item: A #Genericmenuitem
+ *
+ * Gets the disposition of the menuitem.
+ *
+ * Return value: The disposition of the menuitem.
+ */
+GenericmenuitemDisposition
+genericmenuitem_get_disposition (Genericmenuitem * item)
+{
+ g_return_val_if_fail(IS_GENERICMENUITEM(item), GENERICMENUITEM_DISPOSITION_NORMAL);
+
+ return item->priv->disposition;
+}
diff --git a/libdbusmenu-gtk/genericmenuitem.h b/libdbusmenu-gtk/genericmenuitem.h
index 5e3c640..0b7df55 100644
--- a/libdbusmenu-gtk/genericmenuitem.h
+++ b/libdbusmenu-gtk/genericmenuitem.h
@@ -42,11 +42,9 @@ G_BEGIN_DECLS
#define IS_GENERICMENUITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GENERICMENUITEM_TYPE))
#define GENERICMENUITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GENERICMENUITEM_TYPE, GenericmenuitemClass))
-typedef struct _Genericmenuitem Genericmenuitem;
-typedef struct _GenericmenuitemClass GenericmenuitemClass;
-typedef struct _GenericmenuitemPrivate GenericmenuitemPrivate;
-typedef enum _GenericmenuitemCheckType GenericmenuitemCheckType;
-typedef enum _GenericmenuitemState GenericmenuitemState;
+typedef struct _Genericmenuitem Genericmenuitem;
+typedef struct _GenericmenuitemClass GenericmenuitemClass;
+typedef struct _GenericmenuitemPrivate GenericmenuitemPrivate;
/*
GenericmenuitemClass:
@@ -65,26 +63,61 @@ struct _Genericmenuitem {
GenericmenuitemPrivate * priv;
};
-enum _GenericmenuitemCheckType {
+/**
+ * GenericmenuitemCheckType:
+ * @GENERICMENUITEM_CHECK_TYPE_NONE: No check
+ * @GENERICMENUITEM_CHECK_TYPE_CHECKBOX: Nice little check
+ * @GENERICMENUITEM_CHECK_TYPE_RADIO: Radio button
+ *
+ * Tracks what type of checkmark should be shown on the item
+ */
+typedef enum { /*< prefix=GENERICMENUITEM_CHECK_TYPE >*/
GENERICMENUITEM_CHECK_TYPE_NONE,
GENERICMENUITEM_CHECK_TYPE_CHECKBOX,
GENERICMENUITEM_CHECK_TYPE_RADIO
-};
-
-enum _GenericmenuitemState {
+} GenericmenuitemCheckType;
+
+/**
+ * GenericmenuitemState:
+ * @GENERICMENUITEM_STATE_UNCHECKED: No check visisble
+ * @GENERICMENUITEM_STATE_CHECKED: Check visible
+ * @GENERICMENUITEM_STATE_INDETERMINATE: We have no clue
+ *
+ * What the state of the check mark on the item is
+ */
+typedef enum { /*< prefix=GENERICMENUITEM_STATE >*/
GENERICMENUITEM_STATE_UNCHECKED,
GENERICMENUITEM_STATE_CHECKED,
GENERICMENUITEM_STATE_INDETERMINATE
-};
-
-GType genericmenuitem_get_type (void);
-void genericmenuitem_set_check_type (Genericmenuitem * item,
- GenericmenuitemCheckType check_type);
-void genericmenuitem_set_state (Genericmenuitem * item,
- GenericmenuitemState state);
-void genericmenuitem_set_image (Genericmenuitem * item,
- GtkWidget * image);
-GtkWidget * genericmenuitem_get_image (Genericmenuitem * item);
+} GenericmenuitemState;
+
+/**
+ * GenericmenuitemDisposition:
+ * @GENERICMENUITEM_DISPOSITION_NORMAL: Normal state
+ * @GENERICMENUITEM_DISPOSITION_INFORMATIONAL: Item is informational
+ * @GENERICMENUITEM_DISPOSITION_WARNING: Oh, you should watch out for this one
+ * @GENERICMENUITEM_DISPOSITION_ALERT: Boom!
+ *
+ * What the disposition of the menu item is
+ */
+typedef enum { /*< prefix=GENERICMENUITEM_DISPOSITION >*/
+ GENERICMENUITEM_DISPOSITION_NORMAL,
+ GENERICMENUITEM_DISPOSITION_INFORMATIONAL,
+ GENERICMENUITEM_DISPOSITION_WARNING,
+ GENERICMENUITEM_DISPOSITION_ALERT
+} GenericmenuitemDisposition;
+
+GType genericmenuitem_get_type (void);
+void genericmenuitem_set_check_type (Genericmenuitem * item,
+ GenericmenuitemCheckType check_type);
+void genericmenuitem_set_state (Genericmenuitem * item,
+ GenericmenuitemState state);
+void genericmenuitem_set_image (Genericmenuitem * item,
+ GtkWidget * image);
+GtkWidget * genericmenuitem_get_image (Genericmenuitem * item);
+void genericmenuitem_set_disposition (Genericmenuitem * item,
+ GenericmenuitemDisposition disposition);
+GenericmenuitemDisposition genericmenuitem_get_disposition (Genericmenuitem * item);
G_END_DECLS
diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c
index 0b31069..236a596 100644
--- a/libdbusmenu-gtk/menu.c
+++ b/libdbusmenu-gtk/menu.c
@@ -329,6 +329,18 @@ remove_child_signals (gpointer data, gpointer user_data)
return;
}
+/* Handler for all of the menu items on a root change to ensure that
+ the menus are hidden before we start going and deleting things. */
+static void
+popdown_all (DbusmenuMenuitem * mi, gpointer user_data)
+{
+ GtkMenu * menu = dbusmenu_gtkclient_menuitem_get_submenu(DBUSMENU_GTKCLIENT(user_data), mi);
+ if (menu != NULL) {
+ gtk_menu_popdown(menu);
+ }
+ return;
+}
+
/* When the root menuitem changes we need to resetup things so that
we're back in the game. */
static void
@@ -344,6 +356,8 @@ root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGt
g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_moved, menu);
g_signal_handlers_disconnect_by_func(G_OBJECT(priv->root), root_child_delete, menu);
+ dbusmenu_menuitem_foreach(priv->root, popdown_all, client);
+
g_object_unref(priv->root);
priv->root = NULL;
}
diff --git a/libdbusmenu-gtk/parser.c b/libdbusmenu-gtk/parser.c
index c627854..e988c62 100644
--- a/libdbusmenu-gtk/parser.c
+++ b/libdbusmenu-gtk/parser.c
@@ -28,7 +28,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include "parser.h"
#include "menuitem.h"
-#include "serializablemenuitem.h"
+#include "client.h"
#define CACHED_MENUITEM "dbusmenu-gtk-parser-cached-item"
#define PARSER_DATA "dbusmenu-gtk-parser-data"
@@ -87,6 +87,9 @@ static gboolean item_handle_event (DbusmenuMenuitem * item,
static void widget_notify_cb (GtkWidget * widget,
GParamSpec * pspec,
gpointer data);
+static void widget_add_cb (GtkWidget * widget,
+ GtkWidget * child,
+ gpointer data);
static gboolean should_show_image (GtkImage * image);
static void menuitem_notify_cb (GtkWidget * widget,
GParamSpec * pspec,
@@ -169,6 +172,8 @@ parse_data_free (gpointer data)
g_signal_handlers_disconnect_matched(pdata->widget, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
0, 0, NULL, G_CALLBACK(widget_notify_cb), NULL);
g_signal_handlers_disconnect_matched(pdata->widget, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
+ 0, 0, NULL, G_CALLBACK(widget_add_cb), NULL);
+ g_signal_handlers_disconnect_matched(pdata->widget, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
0, 0, NULL, G_CALLBACK(accel_changed), NULL);
g_signal_handlers_disconnect_matched(pdata->widget, (GSignalMatchType)G_SIGNAL_MATCH_FUNC,
0, 0, NULL, G_CALLBACK(checkbox_toggled), NULL);
@@ -265,6 +270,71 @@ new_menuitem (GtkWidget * widget)
return item;
}
+static gboolean
+toggle_widget_visibility (GtkWidget * widget)
+{
+ gboolean vis = gtk_widget_get_visible (widget);
+ gtk_widget_set_visible (widget, !vis);
+ gtk_widget_set_visible (widget, vis);
+ g_object_unref (G_OBJECT (widget));
+ return FALSE;
+}
+
+static void
+watch_submenu(DbusmenuMenuitem * mi, GtkWidget * menu)
+{
+ g_return_if_fail(DBUSMENU_IS_MENUITEM(mi));
+ g_return_if_fail(GTK_IS_MENU_SHELL(menu));
+
+ ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(mi), PARSER_DATA);
+
+ pdata->shell = menu;
+ g_signal_connect (G_OBJECT (menu),
+ "child-added",
+ G_CALLBACK (child_added_cb),
+ mi);
+ g_signal_connect (G_OBJECT (menu),
+ "child-removed",
+ G_CALLBACK (child_removed_cb),
+ mi);
+ g_object_add_weak_pointer(G_OBJECT (menu), (gpointer*)&pdata->shell);
+
+ /* Some apps (notably Eclipse RCP apps) don't fill contents of submenus
+ until the menu is shown. So we fake that by toggling the visibility of
+ any submenus we come across. Further, these apps need it done with a
+ delay while they finish initializing, so we put the call in the idle
+ queue. */
+ g_idle_add((GSourceFunc)toggle_widget_visibility,
+ g_object_ref (G_OBJECT (menu)));
+}
+
+static void
+activate_toplevel_item (GtkWidget * item)
+{
+ /* Make sure that we have a menu item before we start calling
+ functions that depend on it. This should almost always be
+ the case. */
+ if (!GTK_IS_MENU_ITEM(item)) {
+ return;
+ }
+
+ /* If the item is not opening a submenu we don't want to activate
+ it as that'd cause an action. Like opening a preferences dialog
+ to the user. That's not a good idea. */
+ if (gtk_menu_item_get_submenu(GTK_MENU_ITEM(item)) == NULL) {
+ return;
+ }
+
+ GtkWidget * shell = gtk_widget_get_parent (item);
+ if (!GTK_IS_MENU_BAR (shell)) {
+ return;
+ }
+
+ gtk_menu_shell_activate_item (GTK_MENU_SHELL (shell),
+ item,
+ TRUE);
+}
+
static void
parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
{
@@ -281,33 +351,14 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse)
* Note that this will not force menuitems in submenus to be updated as well.
*/
if (recurse->parent == NULL && GTK_IS_MENU_BAR(widget)) {
- GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
- GList *iter;
-
- for (iter = children; iter != NULL; iter = iter->next) {
- gtk_menu_shell_activate_item (GTK_MENU_SHELL (widget),
- iter->data,
- TRUE);
- }
-
- g_list_free (children);
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ (GtkCallback)activate_toplevel_item,
+ NULL);
}
if (recurse->parent == NULL) {
recurse->parent = new_menuitem(widget);
-
- ParserData *pdata = (ParserData *)g_object_get_data(G_OBJECT(recurse->parent), PARSER_DATA);
-
- pdata->shell = widget;
- g_signal_connect (G_OBJECT (widget),
- "child-added",
- G_CALLBACK (child_added_cb),
- recurse->parent);
- g_signal_connect (G_OBJECT (widget),
- "child-removed",
- G_CALLBACK (child_removed_cb),
- recurse->parent);
- g_object_add_weak_pointer(G_OBJECT (widget), (gpointer*)&pdata->shell);
+ watch_submenu(recurse->parent, widget);
}
gtk_container_foreach (GTK_CONTAINER (widget),
@@ -443,13 +494,6 @@ sanitize_label (GtkLabel * label)
static DbusmenuMenuitem *
construct_dbusmenu_for_widget (GtkWidget * widget)
{
- /* If it's a subclass of our serializable menu item then we can
- use its own build function */
- if (DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(widget)) {
- DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(widget);
- return dbusmenu_gtk_serializable_menu_item_build_menuitem(smi);
- }
-
/* If it's a standard GTK Menu Item we need to do some of our own work */
if (GTK_IS_MENU_ITEM (widget))
{
@@ -462,8 +506,8 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
if (GTK_IS_SEPARATOR_MENU_ITEM (widget) || !find_menu_label (widget))
{
dbusmenu_menuitem_property_set (mi,
- "type",
- "separator");
+ DBUSMENU_MENUITEM_PROP_TYPE,
+ DBUSMENU_CLIENT_TYPES_SEPARATOR);
visible = gtk_widget_get_visible (widget);
sensitive = gtk_widget_get_sensitive (widget);
@@ -556,16 +600,7 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
GtkWidget *submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget));
if (submenu)
{
- pdata->shell = submenu;
- g_signal_connect (G_OBJECT (submenu),
- "child-added",
- G_CALLBACK (child_added_cb),
- mi);
- g_signal_connect (G_OBJECT (submenu),
- "child-removed",
- G_CALLBACK (child_removed_cb),
- mi);
- g_object_add_weak_pointer(G_OBJECT(submenu), (gpointer*)&pdata->shell);
+ watch_submenu(mi, submenu);
}
if (!g_object_get_data (G_OBJECT (widget), "gtk-empty-menu-item") && !GTK_IS_TEAROFF_MENU_ITEM (widget))
@@ -605,6 +640,11 @@ construct_dbusmenu_for_widget (GtkWidget * widget)
G_CALLBACK (widget_notify_cb),
mi);
+ g_signal_connect (widget,
+ "add",
+ G_CALLBACK (widget_add_cb),
+ mi);
+
return mi;
}
@@ -836,6 +876,9 @@ label_notify_cb (GtkWidget *widget,
g_idle_add ((GSourceFunc)recreate_menu_item_in_idle_cb, child);
}
}
+
+ g_value_unset(&prop_value);
+ return;
}
static void
@@ -962,6 +1005,26 @@ item_handle_event (DbusmenuMenuitem *item, const gchar *name,
return FALSE; // just pass through on everything
}
+static gboolean
+handle_first_label (DbusmenuMenuitem *mi)
+{
+ ParserData *pdata = g_object_get_data (G_OBJECT (mi), PARSER_DATA);
+ if (!pdata->label)
+ {
+ /* GtkMenuItem's can start life as a separator if they have no child
+ * GtkLabel. In this case, we need to convert the DbusmenuMenuitem from
+ * a separator to a normal menuitem if the application adds a label.
+ * As changing types isn't handled too well by the client, we delete
+ * this menuitem for now and then recreate it
+ */
+ DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (mi);
+ recreate_menu_item (parent, mi);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
widget_notify_cb (GtkWidget *widget,
GParamSpec *pspec,
@@ -981,20 +1044,11 @@ widget_notify_cb (GtkWidget *widget,
}
else if (pspec->name == g_intern_static_string ("label"))
{
- ParserData *pdata = g_object_get_data (G_OBJECT (child), PARSER_DATA);
- if (!pdata->label)
+ if (handle_first_label (child))
{
- /* GtkMenuItem's can start life as a separator if they have no child
- * GtkLabel. In this case, we need to convert the DbusmenuMenuitem from
- * a separator to a normal menuitem if the application adds a label.
- * As changing types isn't handled too well by the client, we delete
- * this menuitem for now and then recreate it
- */
- DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent (child);
- recreate_menu_item (parent, child);
return;
}
-
+
dbusmenu_menuitem_property_set (child,
DBUSMENU_MENUITEM_PROP_LABEL,
g_value_get_string (&prop_value));
@@ -1056,6 +1110,7 @@ widget_notify_cb (GtkWidget *widget,
if (item != NULL) {
GtkWidget * menu = GTK_WIDGET (g_value_get_object (&prop_value));
parse_menu_structure_helper(menu, &recurse);
+ watch_submenu(item, menu);
} else {
/* Note: it would be really odd that we wouldn't have a cached
item, but we should handle that appropriately. */
@@ -1066,6 +1121,15 @@ widget_notify_cb (GtkWidget *widget,
g_value_unset (&prop_value);
}
+static void
+widget_add_cb (GtkWidget *widget,
+ GtkWidget *child,
+ gpointer data)
+{
+ if (find_menu_label (child) != NULL)
+ handle_first_label (data);
+}
+
/* A child item was added to a menu we're watching. Let's try to integrate it. */
static void
child_added_cb (GtkContainer *menu, GtkWidget *widget, gpointer data)
@@ -1076,6 +1140,10 @@ child_added_cb (GtkContainer *menu, GtkWidget *widget, gpointer data)
recurse.toplevel = gtk_widget_get_toplevel(GTK_WIDGET(menu));
recurse.parent = menuitem;
+ if (GTK_IS_MENU_BAR(menu)) {
+ activate_toplevel_item (widget);
+ }
+
parse_menu_structure_helper(widget, &recurse);
}
diff --git a/libdbusmenu-gtk/serializablemenuitem.c b/libdbusmenu-gtk/serializablemenuitem.c
deleted file mode 100644
index b560fe3..0000000
--- a/libdbusmenu-gtk/serializablemenuitem.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
-An object to act as a base class for easy GTK widgets that can be
-transfered over dbusmenu.
-
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Ted Gould <ted@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
-Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
-the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-<http://www.gnu.org/licenses/>
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "client.h"
-#include "serializablemenuitem.h"
-
-/*
- DbusmenuGtkSerializableMenuItemPrivate:
- @mi: Menuitem to watch the property changes from
-*/
-struct _DbusmenuGtkSerializableMenuItemPrivate {
- DbusmenuMenuitem * mi;
-};
-
-/* Properties */
-enum {
- PROP_0,
- PROP_MENUITEM
-};
-
-/* Private macro, only used in object init */
-#define DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_GET_PRIVATE(o) \
-(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM, DbusmenuGtkSerializableMenuItemPrivate))
-
-/* Function prototypes */
-static void dbusmenu_gtk_serializable_menu_item_class_init (DbusmenuGtkSerializableMenuItemClass *klass);
-static void dbusmenu_gtk_serializable_menu_item_init (DbusmenuGtkSerializableMenuItem *self);
-static void dbusmenu_gtk_serializable_menu_item_dispose (GObject *object);
-static void dbusmenu_gtk_serializable_menu_item_finalize (GObject *object);
-static void set_property (GObject * obj,
- guint id,
- const GValue * value,
- GParamSpec * pspec);
-static void get_property (GObject * obj,
- guint id,
- GValue * value,
- GParamSpec * pspec);
-
-/* GObject boiler plate */
-G_DEFINE_TYPE (DbusmenuGtkSerializableMenuItem, dbusmenu_gtk_serializable_menu_item, GTK_TYPE_MENU_ITEM);
-
-/* Initialize the stuff in the class structure */
-static void
-dbusmenu_gtk_serializable_menu_item_class_init (DbusmenuGtkSerializableMenuItemClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (DbusmenuGtkSerializableMenuItemPrivate));
-
- object_class->dispose = dbusmenu_gtk_serializable_menu_item_dispose;
- object_class->finalize = dbusmenu_gtk_serializable_menu_item_finalize;
- object_class->set_property = set_property;
- object_class->get_property = get_property;
-
- g_object_class_install_property (object_class, PROP_MENUITEM,
- g_param_spec_object(DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_PROP_MENUITEM, "DBusmenu Menuitem attached to item",
- "A menuitem who's properties are being watched and where changes should be watched for updates. It is the responsibility of subclasses to set up the signal handlers for those property changes.",
- DBUSMENU_TYPE_MENUITEM,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- return;
-}
-
-/* Initialize the object structures and private structure */
-static void
-dbusmenu_gtk_serializable_menu_item_init (DbusmenuGtkSerializableMenuItem *self)
-{
- self->priv = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_GET_PRIVATE(self);
-
- self->priv->mi = NULL;
-
- return;
-}
-
-/* Free all references to objects */
-static void
-dbusmenu_gtk_serializable_menu_item_dispose (GObject *object)
-{
- DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(object);
- g_return_if_fail(smi != NULL);
-
- if (smi->priv->mi != NULL) {
- g_object_unref(G_OBJECT(smi->priv->mi));
- smi->priv->mi = NULL;
- }
-
-
- G_OBJECT_CLASS (dbusmenu_gtk_serializable_menu_item_parent_class)->dispose (object);
- return;
-}
-
-/* Free memory */
-static void
-dbusmenu_gtk_serializable_menu_item_finalize (GObject *object)
-{
-
-
-
- G_OBJECT_CLASS (dbusmenu_gtk_serializable_menu_item_parent_class)->finalize (object);
- return;
-}
-
-/* Set an object property */
-static void
-set_property (GObject * obj, guint id, const GValue * value, GParamSpec * pspec)
-{
- DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(obj);
-
- switch (id) {
- case PROP_MENUITEM:
- smi->priv->mi = g_value_get_object(value);
- break;
- default:
- g_return_if_reached();
- break;
- }
-
- return;
-}
-
-/* Get an object property */
-static void
-get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
-{
- DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(obj);
-
- switch (id) {
- case PROP_MENUITEM:
- g_value_set_object(value, smi->priv->mi);
- break;
- default:
- g_return_if_reached();
- break;
- }
-
- return;
-}
-
-/**
- * dbusmenu_gtk_serializable_menu_item_build_menuitem:
- * @smi: #DbusmenuGtkSerializableMenuItem to build a #DbusmenuMenuitem mirroring
- *
- * This function is for menu items that are instanciated from
- * GTK and have their properites set using GTK functions. This
- * builds a #DbusmenuMenuitem that then has the properties that
- * should be sent over the bus to create a new item of this
- * type on the other side.
- *
- * Return value: (transfer full): A #DbusmenuMenuitem who's values will be
- * set by this object.
- */
-DbusmenuMenuitem *
-dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi)
-{
- g_return_val_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi), NULL);
-
- DbusmenuGtkSerializableMenuItemClass * klass = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_GET_CLASS(smi);
- if (klass->build_dbusmenu_menuitem != NULL) {
- return klass->build_dbusmenu_menuitem(smi);
- }
-
- return NULL;
-}
-
-/* Callback to the generic type handler */
-typedef struct _type_handler_t type_handler_t;
-struct _type_handler_t {
- DbusmenuGtkSerializableMenuItemClass * class;
- GType type;
-};
-
-/* Handle the type with this item. */
-static gboolean
-type_handler (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
-{
- type_handler_t * th = (type_handler_t *)user_data;
-
- DbusmenuGtkSerializableMenuItem * smi = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(g_object_new(th->type, NULL));
- g_return_val_if_fail(smi != NULL, FALSE);
-
- dbusmenu_gtk_serializable_menu_item_set_menuitem(smi, newitem);
- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, GTK_MENU_ITEM(smi), parent);
-
- return TRUE;
-}
-
-/* Destruction is inevitable */
-static void
-type_destroy_handler (gpointer user_data)
-{
- g_return_if_fail(user_data != NULL);
- type_handler_t * th = (type_handler_t *)user_data;
- g_type_class_unref(th->class);
- g_free(user_data);
- return;
-}
-
-/**
- * dbusmenu_gtk_serializable_menu_item_register_to_client:
- * @client: #DbusmenuClient that we should register a type at.
- * @item_type: The #GType of a class that is a subclass of #DbusmenuGtkSerializableMenuItem
- *
- * Registers a generic handler for dealing with all subclasses of
- * #DbusmenuGtkSerializableMenuItem. This handler responds to the callback,
- * creates a new object and attaches it to the appropriate #DbusmenuMenuitem
- * object.
- */
-void
-dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client, GType item_type)
-{
- g_return_if_fail(g_type_is_a(item_type, DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM));
-
- gpointer type_class = g_type_class_ref(item_type);
- g_return_if_fail(type_class != NULL);
-
- DbusmenuGtkSerializableMenuItemClass * class = DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_CLASS(type_class);
-
- if (class->get_type_string == NULL) {
- g_type_class_unref(type_class);
- g_error("No 'get_type_string' in subclass of DbusmenuGtkSerializableMenuItem");
- return;
- }
-
- /* Register type */
- type_handler_t * th = g_new0(type_handler_t, 1);
- th->class = class;
- th->type = item_type;
- if (!dbusmenu_client_add_type_handler_full(client, class->get_type_string(), type_handler, th, type_destroy_handler)) {
- type_destroy_handler(th);
- }
-
- /* Register defaults */
- /* TODO: Need API on another branch */
-
- return;
-}
-
-/**
- * dbusmenu_gtk_serializable_menu_item_set_menuitem:
- * @smi: #DbusmenuGtkSerializableMenuItem to set the @DbusmenuGtkSerializableMenuItem::dbusmenu-menuitem of
- * @mi: Menuitem to get the properties from
- *
- * This function is used on the server side to signal to the object
- * that it should get its' property change events from @mi instead
- * of expecting calls to its' API. A call to this function sets the
- * property and subclasses should listen to the notify signal to
- * pick up this property being set.
- */
-void
-dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi)
-{
- g_return_if_fail(DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(smi));
- g_return_if_fail(mi != NULL);
-
- smi->priv->mi = mi;
- g_object_notify(G_OBJECT(smi), DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_PROP_MENUITEM);
-
- return;
-}
diff --git a/libdbusmenu-gtk/serializablemenuitem.h b/libdbusmenu-gtk/serializablemenuitem.h
deleted file mode 100644
index 9bea89f..0000000
--- a/libdbusmenu-gtk/serializablemenuitem.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-An object to act as a base class for easy GTK widgets that can be
-transfered over dbusmenu.
-
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Ted Gould <ted@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
-Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
-the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-<http://www.gnu.org/licenses/>
-*/
-
-#ifndef DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_H__
-#define DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_H__ 1
-
-#include <glib.h>
-#include <glib-object.h>
-#include <gtk/gtk.h>
-#include <libdbusmenu-glib/menuitem.h>
-#include <libdbusmenu-glib/client.h>
-
-G_BEGIN_DECLS
-
-#define DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM (dbusmenu_gtk_serializable_menu_item_get_type ())
-#define DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM, DbusmenuGtkSerializableMenuItem))
-#define DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM, DbusmenuGtkSerializableMenuItemClass))
-#define DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM))
-#define DBUSMENU_IS_GTK_SERIALIZABLE_MENU_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM))
-#define DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_TYPE_GTK_SERIALIZABLE_MENU_ITEM, DbusmenuGtkSerializableMenuItemClass))
-
-/**
- * DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_PROP_MENUITEM:
- *
- * String to access property #DbusmenuGtkSerializableMenuItem:dbusmenu-menuitem
- */
-#define DBUSMENU_GTK_SERIALIZABLE_MENU_ITEM_PROP_MENUITEM "dbusmenu-menuitem"
-
-typedef struct _DbusmenuGtkSerializableMenuItem DbusmenuGtkSerializableMenuItem;
-typedef struct _DbusmenuGtkSerializableMenuItemClass DbusmenuGtkSerializableMenuItemClass;
-typedef struct _DbusmenuGtkSerializableMenuItemPrivate DbusmenuGtkSerializableMenuItemPrivate;
-
-/**
- DbusmenuGtkSerializableMenuItemClass:
- @parent_class: Inherit from GtkMenuItem
- @get_type_string: Static function to get a string describing this type
- @get_default_properties: Return a hashtable of defaults for the menu item type
- @build_dbusmenu_menuitem: Build a menuitem that can be sent over dbus
- @_dbusmenu_gtk_serializable_menu_item_reserved1: Reserved for future use.
- @_dbusmenu_gtk_serializable_menu_item_reserved2: Reserved for future use.
- @_dbusmenu_gtk_serializable_menu_item_reserved3: Reserved for future use.
- @_dbusmenu_gtk_serializable_menu_item_reserved4: Reserved for future use.
- @_dbusmenu_gtk_serializable_menu_item_reserved5: Reserved for future use.
- @_dbusmenu_gtk_serializable_menu_item_reserved6: Reserved for future use.
-
- Signals and functions for #DbusmenuGtkSerializableMenuItem.
-*/
-struct _DbusmenuGtkSerializableMenuItemClass {
- GtkMenuItemClass parent_class;
-
- /* Subclassable functions */
- const gchar * (*get_type_string) (void);
- GHashTable * (*get_default_properties) (void);
-
- DbusmenuMenuitem * (*build_dbusmenu_menuitem) (DbusmenuGtkSerializableMenuItem * smi);
-
- /* Signals */
-
-
-
- /* Empty Space */
- /*< Private >*/
- void (*_dbusmenu_gtk_serializable_menu_item_reserved1) (void);
- void (*_dbusmenu_gtk_serializable_menu_item_reserved2) (void);
- void (*_dbusmenu_gtk_serializable_menu_item_reserved3) (void);
- void (*_dbusmenu_gtk_serializable_menu_item_reserved4) (void);
- void (*_dbusmenu_gtk_serializable_menu_item_reserved5) (void);
- void (*_dbusmenu_gtk_serializable_menu_item_reserved6) (void);
-};
-
-/**
- DbusmenuGtkSerializableMenuItem:
- @parent: Inherit from GtkMenuItem
- @priv: Blind structure of private variables
-
- The Serializable Menuitem provides a way for menu items to be created
- that can easily be picked up by the Dbusmenu GTK Parser. This way
- you can create custom items, and transport them across dbusmenu to
- your menus or the appmenu on the other side of the bus. By providing
- these function the parser has enough information to both serialize, and
- deserialize on the other side, the menuitem you've so carefully created.
-*/
-struct _DbusmenuGtkSerializableMenuItem {
- GtkMenuItem parent;
-
- DbusmenuGtkSerializableMenuItemPrivate * priv;
-};
-
-GType dbusmenu_gtk_serializable_menu_item_get_type (void);
-
-DbusmenuMenuitem * dbusmenu_gtk_serializable_menu_item_build_menuitem (DbusmenuGtkSerializableMenuItem * smi);
-void dbusmenu_gtk_serializable_menu_item_register_to_client (DbusmenuClient * client, GType item_type);
-void dbusmenu_gtk_serializable_menu_item_set_menuitem (DbusmenuGtkSerializableMenuItem * smi, DbusmenuMenuitem * mi);
-
-/**
- SECTION:serializablemenuitem
- @short_description: A way to build #GtkMenuItems that can be sent over Dbusmenu
- @stability: Unstable
- @include: libdbusmenu-gtk/serializablemenuitem.h
-
- Menuitems can subclass from this instead of #GtkMenuItem and
- by providing the appropriate functions Dbusmenu will be able
- to parse them and send them over the bus.
-*/
-
-G_END_DECLS
-
-#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a2c0716..a4e8682 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -12,14 +12,25 @@ TESTS = \
test-glib-properties \
test-glib-proxy \
test-glib-simple-items \
- test-glib-submenu \
- test-json \
+ test-glib-submenu
+
+if WANT_DBUSMENUDUMPER
+TESTS += \
+ test-json
+endif
+
+if WANT_LIBDBUSMENUGTK
+TESTS += \
test-gtk-objects-test \
test-gtk-label \
test-gtk-shortcut \
test-gtk-reorder \
test-gtk-submenu \
test-gtk-parser-test
+endif
+
+XFAIL_TESTS = \
+ test-glib-proxy
# The Python test only work on the system copy of
# dbusmenu, so while they can be usefule they're not
@@ -41,20 +52,28 @@ check_PROGRAMS = \
test-glib-proxy-client \
test-glib-proxy-server \
test-glib-proxy-proxy \
- test-gtk-objects \
test-glib-submenu-client \
test-glib-submenu-server \
+ test-glib-simple-items
+
+if WANT_DBUSMENUDUMPER
+check_PROGRAMS += \
+ test-json-client \
+ test-json-server
+endif
+
+if WANT_LIBDBUSMENUGTK
+check_PROGRAMS += \
+ test-gtk-objects \
test-gtk-label-client \
test-gtk-label-server \
test-gtk-shortcut-client \
test-gtk-shortcut-server \
- test-glib-simple-items \
test-gtk-reorder-server \
- test-json-client \
- test-json-server \
test-gtk-submenu-server \
test-gtk-submenu-client \
test-gtk-parser
+endif
XVFB_RUN=". $(srcdir)/run-xvfb.sh"
@@ -399,7 +418,7 @@ test_gtk_objects_CFLAGS = \
test_gtk_objects_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGLIB_LIBS) \
$(DBUSMENUGTK_LIBS)
@@ -429,7 +448,7 @@ test_gtk_parser_CFLAGS = \
test_gtk_parser_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGLIB_LIBS) \
$(DBUSMENUGTK_LIBS)
@@ -456,7 +475,7 @@ test_gtk_label_server_CFLAGS = \
test_gtk_label_server_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
libdbusmenu-jsonloader.la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -472,7 +491,7 @@ test_gtk_label_client_CFLAGS = \
test_gtk_label_client_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -497,7 +516,7 @@ test_gtk_shortcut_server_CFLAGS = \
test_gtk_shortcut_server_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -512,7 +531,7 @@ test_gtk_shortcut_client_CFLAGS = \
test_gtk_shortcut_client_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -550,7 +569,7 @@ test_gtk_reorder_server_CFLAGS = \
test_gtk_reorder_server_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -575,7 +594,7 @@ test_gtk_submenu_server_CFLAGS = \
test_gtk_submenu_server_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -590,7 +609,7 @@ test_gtk_submenu_client_CFLAGS = \
test_gtk_submenu_client_LDADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
- ../libdbusmenu-gtk/libdbusmenu-gtk.la \
+ ../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
$(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)
@@ -658,3 +677,8 @@ distclean-local:
DISTCLEANFILES += \
$(filter-out %.py, $(TESTS))
+if USE_GTK3
+VER=3
+else
+VER=
+endif
diff --git a/tests/test-gtk-label-client.c b/tests/test-gtk-label-client.c
index 14eb5bd..415c6b0 100644
--- a/tests/test-gtk-label-client.c
+++ b/tests/test-gtk-label-client.c
@@ -160,7 +160,7 @@ main (int argc, char ** argv)
GtkWidget * menuitem = gtk_menu_item_new_with_label("Test");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(dbusmenu_gtkmenu_new ("glib.label.test", "/org/test")));
gtk_widget_show(menuitem);
- gtk_menu_bar_append(menubar, menuitem);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
gtk_widget_show(menubar);
gtk_container_add(GTK_CONTAINER(window), menubar);
gtk_window_set_title(GTK_WINDOW(window), "libdbusmenu-gtk test");
diff --git a/tests/test-gtk-label.json b/tests/test-gtk-label.json
index 0189fbe..86d18e8 100644
--- a/tests/test-gtk-label.json
+++ b/tests/test-gtk-label.json
@@ -367,5 +367,58 @@ QmCC",
"toggle-state": -1
}
]
+ },
+ {"id": 1, "type": "standard",
+ "label": "value1",
+ "submenu": [
+ {"id": 60,
+ "label": "Disposition Normal",
+ "disposition": "normal"
+ },
+ {"id": 61,
+ "label": "Disposition Info",
+ "disposition": "informational"
+ },
+ {"id": 62,
+ "label": "Disposition Warning",
+ "disposition": "warning"
+ },
+ {"id": 63,
+ "label": "Disposition Alert",
+ "disposition": "alert"
+ }
+ ]
+ },
+ {"id": 1, "type": "standard",
+ "label": "value1",
+ "submenu": [
+ {"id": 70,
+ "label": "_Mnemonic"
+ },
+ {"id": 71,
+ "label": "M_nemonic"
+ },
+ {"id": 72,
+ "label": "Mn_emonic"
+ },
+ {"id": 73,
+ "label": "Mne_monic"
+ },
+ {"id": 74,
+ "label": "Mnem_onic"
+ },
+ {"id": 75,
+ "label": "Mnemo_nic"
+ },
+ {"id": 76,
+ "label": "Mnemon_ic"
+ },
+ {"id": 77,
+ "label": "Mnemoni_c"
+ },
+ {"id": 78,
+ "label": "__Underline__"
+ }
+ ]
}
]
diff --git a/tests/test-gtk-objects.c b/tests/test-gtk-objects.c
index 30fc022..4bd26d3 100644
--- a/tests/test-gtk-objects.c
+++ b/tests/test-gtk-objects.c
@@ -97,7 +97,11 @@ test_object_prop_shortcut (void)
g_assert(G_IS_OBJECT(item));
g_assert(DBUSMENU_IS_MENUITEM(item));
+#if GTK_CHECK_VERSION(3,0,0)
+ guint key = GDK_KEY_c;
+#else
guint key = GDK_c;
+#endif
GdkModifierType modifier = GDK_CONTROL_MASK;
/* Set a shortcut */
diff --git a/tests/test-gtk-parser.c b/tests/test-gtk-parser.c
index b66b46a..afd6194 100644
--- a/tests/test-gtk-parser.c
+++ b/tests/test-gtk-parser.c
@@ -28,6 +28,8 @@ test_parser_runs (void)
{
GtkWidget * gmi = gtk_menu_item_new_with_label("Test Item");
g_assert(gmi != NULL);
+ g_object_ref_sink(gmi);
+
DbusmenuMenuitem * mi = dbusmenu_gtk_parse_menu_structure(gmi);
g_assert(mi != NULL);
@@ -55,9 +57,23 @@ const gchar * test_parser_children_builder =
"</object>"
"</interface>";
+/* Checks the log level to let warnings not stop the program */
+static gboolean
+test_parser_children_log_handler (const gchar * domain, GLogLevelFlags level, const gchar * message, gpointer user_data)
+{
+ if (level & (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Ensure the parser can find children */
static void
test_parser_children (void) {
+ /* Hide GTK errors */
+ g_test_log_set_fatal_handler(test_parser_children_log_handler, NULL);
+
GtkBuilder * builder = gtk_builder_new();
g_assert(builder != NULL);
diff --git a/tests/test-gtk-shortcut-client.c b/tests/test-gtk-shortcut-client.c
index 003885c..259e177 100644
--- a/tests/test-gtk-shortcut-client.c
+++ b/tests/test-gtk-shortcut-client.c
@@ -53,7 +53,7 @@ main (int argc, char ** argv)
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(dmenu));
gtk_widget_show(menuitem);
- gtk_menu_bar_append(menubar, menuitem);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
gtk_widget_show(menubar);
gtk_container_add(GTK_CONTAINER(window), menubar);
gtk_window_set_title(GTK_WINDOW(window), "libdbusmenu-gtk test");
diff --git a/tests/test-gtk-shortcut-server.c b/tests/test-gtk-shortcut-server.c
index b205d03..5df4881 100644
--- a/tests/test-gtk-shortcut-server.c
+++ b/tests/test-gtk-shortcut-server.c
@@ -46,7 +46,11 @@ build_menu (void)
item = dbusmenu_menuitem_new();
dbusmenu_menuitem_property_set(item, DBUSMENU_MENUITEM_PROP_LABEL, "Control-L");
+#if GTK_CHECK_VERSION(3,0,0)
+ dbusmenu_menuitem_property_set_shortcut(item, GDK_KEY_l, GDK_CONTROL_MASK);
+#else
dbusmenu_menuitem_property_set_shortcut(item, GDK_l, GDK_CONTROL_MASK);
+#endif
dbusmenu_menuitem_child_append(root, item);
g_object_unref(item);
diff --git a/tests/test-gtk-submenu-client.c b/tests/test-gtk-submenu-client.c
index ec46122..81637f1 100644
--- a/tests/test-gtk-submenu-client.c
+++ b/tests/test-gtk-submenu-client.c
@@ -127,7 +127,7 @@ main (int argc, char ** argv)
GtkWidget * menuitem = gtk_menu_item_new_with_label("Test");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), GTK_WIDGET(dbusmenu_gtkmenu_new ("glib.label.test", "/org/test")));
gtk_widget_show(menuitem);
- gtk_menu_bar_append(menubar, menuitem);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
gtk_widget_show(menubar);
gtk_container_add(GTK_CONTAINER(window), menubar);
gtk_window_set_title(GTK_WINDOW(window), "libdbusmenu-gtk test");
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 48993f1..029b73e 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,7 +1,11 @@
SUBDIRS = testapp
-libexec_PROGRAMS = dbusmenu-dumper
+libexec_PROGRAMS =
+
+if WANT_DBUSMENUDUMPER
+libexec_PROGRAMS += dbusmenu-dumper
+endif
libexec_SCRIPTS = dbusmenu-bench
diff --git a/tools/testapp/Makefile.am b/tools/testapp/Makefile.am
index 39de532..e2bbde7 100644
--- a/tools/testapp/Makefile.am
+++ b/tools/testapp/Makefile.am
@@ -1,11 +1,9 @@
-if USE_GTK3
-VER=3
-else
-VER=
-endif
+libexec_PROGRAMS =
-libexec_PROGRAMS = dbusmenu-testapp
+if WANT_TESTS
+libexec_PROGRAMS += dbusmenu-testapp
+endif
dbusmenu_testapp_SOURCES = \
main.c
@@ -18,6 +16,4 @@ dbusmenu_testapp_CFLAGS = \
dbusmenu_testapp_LDADD = \
$(builddir)/../../libdbusmenu-glib/libdbusmenu-glib.la \
- $(builddir)/../../libdbusmenu-gtk/libdbusmenu-gtk$(VER).la \
- $(DBUSMENUGTK_LIBS) \
$(DBUSMENUTESTS_LIBS)