aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--debian/changelog7
-rw-r--r--debian/watch2
-rw-r--r--libdbusmenu-glib/client.c114
-rw-r--r--libdbusmenu-glib/client.h17
-rw-r--r--libdbusmenu-glib/menuitem.c17
-rw-r--r--libdbusmenu-glib/menuitem.h11
-rw-r--r--libdbusmenu-gtk/client.c108
-rw-r--r--libdbusmenu-gtk/client.h2
-rw-r--r--libdbusmenu-gtk/menu.c36
-rw-r--r--libdbusmenu-gtk/menu.h2
-rw-r--r--po/Makefile.in.in2
-rw-r--r--tests/test-gtk-label.json134
13 files changed, 358 insertions, 98 deletions
diff --git a/configure.ac b/configure.ac
index 6a5ed9a..950724c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,7 +5,7 @@ AC_COPYRIGHT([Copyright 2009 Canonical])
AC_PREREQ(2.53)
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(libdbusmenu, 0.0.1)
+AM_INIT_AUTOMAKE(libdbusmenu, 0.0.2)
AM_MAINTAINER_MODE
@@ -19,6 +19,8 @@ AC_PROG_LIBTOOL
AC_SUBST(VERSION)
AC_CONFIG_MACRO_DIR([m4])
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
###########################
# Dependencies - GLib
###########################
diff --git a/debian/changelog b/debian/changelog
index d7af41b..e9f094a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+libdbusmenu (0.0.2-0ubuntu1~ppa6) karmic; urgency=low
+
+ * New upsream release 0.0.2
+ * debian/watch: Added for tarball
+
+ -- Ted Gould <ted@ubuntu.com> Thu, 27 Aug 2009 09:59:48 -0500
+
libdbusmenu (0.1~bzr5-0ubuntu1) karmic; urgency=low
* First version.
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..9f089a5
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://launchpad.net/dbusmenu/+download .*/libdbusmenu-([0-9.]+)\.tar\.gz
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c
index 212071b..dd2254e 100644
--- a/libdbusmenu-glib/client.c
+++ b/libdbusmenu-glib/client.c
@@ -68,6 +68,16 @@ struct _DbusmenuClientPrivate
DBusGProxyCall * layoutcall;
DBusGProxy * dbusproxy;
+
+ GHashTable * type_handlers;
+};
+
+typedef struct _newItemPropData newItemPropData;
+struct _newItemPropData
+{
+ DbusmenuClient * client;
+ DbusmenuMenuitem * item;
+ DbusmenuMenuitem * parent;
};
#define DBUSMENU_CLIENT_GET_PRIVATE(o) \
@@ -187,6 +197,9 @@ dbusmenu_client_init (DbusmenuClient *self)
priv->dbusproxy = NULL;
+ priv->type_handlers = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
return;
}
@@ -230,6 +243,10 @@ dbusmenu_client_finalize (GObject *object)
g_free(priv->dbus_name);
g_free(priv->dbus_object);
+ if (priv->type_handlers != NULL) {
+ g_hash_table_destroy(priv->type_handlers);
+ }
+
G_OBJECT_CLASS (dbusmenu_client_parent_class)->finalize (object);
return;
}
@@ -515,6 +532,45 @@ menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError
return;
}
+/* This is a different get properites call back that also sends
+ new signals. It basically is a small wrapper around the original. */
+static void
+menuitem_get_properties_new_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
+{
+ g_return_if_fail(data != NULL);
+
+ newItemPropData * propdata = (newItemPropData *)data;
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(propdata->client);
+
+ menuitem_get_properties_cb (proxy, properties, error, propdata->item);
+
+ gboolean handled = FALSE;
+
+ const gchar * type;
+ DbusmenuClientTypeHandler newfunc = NULL;
+
+ type = dbusmenu_menuitem_property_get(propdata->item, "type");
+ if (type != NULL) {
+ newfunc = g_hash_table_lookup(priv->type_handlers, type);
+ } else {
+ newfunc = g_hash_table_lookup(priv->type_handlers, DBUSMENU_CLIENT_TYPES_DEFAULT);
+ }
+
+ if (newfunc != NULL) {
+ handled = newfunc(propdata->item, propdata->parent, propdata->client);
+ }
+
+ g_signal_emit(G_OBJECT(propdata->item), DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID, 0, TRUE);
+
+ if (!handled) {
+ g_signal_emit(G_OBJECT(propdata->client), signals[NEW_MENUITEM], 0, propdata->item, TRUE);
+ }
+
+ g_free(propdata);
+
+ return;
+}
+
static void
menuitem_call_cb (DBusGProxy * proxy, GError * error, gpointer userdata)
{
@@ -562,9 +618,19 @@ parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * it
dbusmenu_menuitem_set_root(item, TRUE);
}
g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(menuitem_activate), client);
- g_signal_emit(G_OBJECT(client), signals[NEW_MENUITEM], 0, item, TRUE);
+
/* Get the properties queued up for this item */
- org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, item);
+ /* Not happy about this, but I need these :( */
+ newItemPropData * propdata = g_new0(newItemPropData, 1);
+ if (propdata != NULL) {
+ propdata->client = client;
+ propdata->item = item;
+ propdata->parent = parent;
+
+ org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_new_cb, propdata);
+ } else {
+ g_warning("Unable to allocate memory to get properties for menuitem. This menuitem will never be realized.");
+ }
}
xmlNodePtr children;
@@ -744,3 +810,47 @@ dbusmenu_client_get_root (DbusmenuClient * client)
return priv->root;
}
+
+/**
+ dbusmenu_client_add_type_handler:
+ @client: Client where we're getting types coming in
+ @type: A text string that will be matched with the 'type'
+ property on incoming menu items
+ @newfunc: The function that will be executed with those new
+ items when they come in.
+
+ This function connects into the type handling of the #DbusmenuClient.
+ Every new menuitem that comes in immediately gets asked for it's
+ properties. When we get those properties we check the 'type'
+ property and look to see if it matches a handler that is known
+ by the client. If so, the @newfunc function is executed on that
+ #DbusmenuMenuitem. If not, then the DbusmenuClient::new-menuitem
+ signal is sent.
+
+ In the future the known types will be sent to the server so that it
+ can make choices about the menu item types availble.
+
+ Return value: If registering the new type was successful.
+*/
+gboolean
+dbusmenu_client_add_type_handler (DbusmenuClient * client, const gchar * type, DbusmenuClientTypeHandler newfunc)
+{
+ g_return_val_if_fail(DBUSMENU_IS_CLIENT(client), FALSE);
+ g_return_val_if_fail(type != NULL, FALSE);
+
+ DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
+
+ if (priv->type_handlers == NULL) {
+ g_warning("Type handlers hashtable not built");
+ return FALSE;
+ }
+
+ gpointer value = g_hash_table_lookup(priv->type_handlers, type);
+ if (value != NULL) {
+ g_warning("Type '%s' already had a registered handler.", type);
+ return FALSE;
+ }
+
+ g_hash_table_insert(priv->type_handlers, g_strdup(type), newfunc);
+ return TRUE;
+}
diff --git a/libdbusmenu-glib/client.h b/libdbusmenu-glib/client.h
index 35f7122..fff9a6b 100644
--- a/libdbusmenu-glib/client.h
+++ b/libdbusmenu-glib/client.h
@@ -50,10 +50,15 @@ G_BEGIN_DECLS
#define DBUSMENU_CLIENT_PROP_DBUS_NAME "dbus-name"
#define DBUSMENU_CLIENT_PROP_DBUS_OBJECT "dbus-object"
+#define DBUSMENU_CLIENT_TYPES_DEFAULT "menuitem"
+#define DBUSMENU_CLIENT_TYPES_SEPARATOR "separator"
+#define DBUSMENU_CLIENT_TYPES_IMAGE "imageitem"
+
/**
DbusmenuClientClass:
@parent_class: #GObjectClass
@layout_updated: Slot for #DbusmenuClient::layout-updated.
+ @new_menuitem: Slot for #DbusmenuClient::new-menuitem.
@reserved1: Reserved for future use.
@reserved2: Reserved for future use.
@reserved3: Reserved for future use.
@@ -90,9 +95,15 @@ struct _DbusmenuClient {
GObject parent;
};
-GType dbusmenu_client_get_type (void);
-DbusmenuClient * dbusmenu_client_new (const gchar * name, const gchar * object);
-DbusmenuMenuitem * dbusmenu_client_get_root (DbusmenuClient * client);
+typedef gboolean (*DbusmenuClientTypeHandler) (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+
+GType dbusmenu_client_get_type (void);
+DbusmenuClient * dbusmenu_client_new (const gchar * name,
+ const gchar * object);
+DbusmenuMenuitem * dbusmenu_client_get_root (DbusmenuClient * client);
+gboolean dbusmenu_client_add_type_handler (DbusmenuClient * client,
+ const gchar * type,
+ DbusmenuClientTypeHandler newfunc);
/**
SECTION:client
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c
index aba1f64..41c48e2 100644
--- a/libdbusmenu-glib/menuitem.c
+++ b/libdbusmenu-glib/menuitem.c
@@ -61,6 +61,7 @@ enum {
CHILD_ADDED,
CHILD_REMOVED,
CHILD_MOVED,
+ REALIZED,
LAST_SIGNAL
};
@@ -178,6 +179,22 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass)
NULL, NULL,
_dbusmenu_menuitem_marshal_VOID__OBJECT_UINT_UINT,
G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT);
+ /**
+ DbusmenuMenuitem::realized:
+ @arg0: The #DbusmenuMenuitem object.
+
+ Emitted when the initial request for properties
+ is complete on the item. If there is a type
+ handler configured for the "type" parameter
+ that will be executed before this is signaled.
+ */
+ signals[REALIZED] = g_signal_new(DBUSMENU_MENUITEM_SIGNAL_REALIZED,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(DbusmenuMenuitemClass, realized),
+ NULL, NULL,
+ _dbusmenu_menuitem_marshal_VOID__VOID,
+ G_TYPE_NONE, 0, G_TYPE_NONE);
g_object_class_install_property (object_class, PROP_ID,
g_param_spec_uint("id", "ID for the menu item",
diff --git a/libdbusmenu-glib/menuitem.h b/libdbusmenu-glib/menuitem.h
index 29865c7..7806017 100644
--- a/libdbusmenu-glib/menuitem.h
+++ b/libdbusmenu-glib/menuitem.h
@@ -47,6 +47,13 @@ G_BEGIN_DECLS
#define DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED "child-added"
#define DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED "child-removed"
#define DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED "child-moved"
+#define DBUSMENU_MENUITEM_SIGNAL_REALIZED "realized"
+#define DBUSMENU_MENUITEM_SIGNAL_REALIZED_ID (g_signal_lookup(DBUSMENU_MENUITEM_SIGNAL_REALIZED, DBUSMENU_TYPE_MENUITEM))
+
+#define DBUSMENU_MENUITEM_PROP_VISIBLE "visible"
+#define DBUSMENU_MENUITEM_PROP_LABEL "label"
+#define DBUSMENU_MENUITEM_PROP_ICON "icon"
+#define DBUSMENU_MENUITEM_PROP_ICON_DATA "icon-data"
/**
DbusmenuMenuitem:
@@ -71,6 +78,7 @@ struct _DbusmenuMenuitem
@child_added: Slot for #DbusmenuMenuitem::child-added.
@child_removed: Slot for #DbusmenuMenuitem::child-removed.
@child_moved: Slot for #DbusmenuMenuitem::child-moved.
+ @realized: Slot for #DbusmenuMenuitem::realized.
@buildxml: Virtual function that appends the strings required
to represent this menu item in the menu XML file.
@reserved1: Reserved for future use.
@@ -89,6 +97,7 @@ struct _DbusmenuMenuitemClass
void (*child_added) (DbusmenuMenuitem * child, guint position);
void (*child_removed) (DbusmenuMenuitem * child);
void (*child_moved) (DbusmenuMenuitem * child, guint newpos, guint oldpos);
+ void (*realized) (void);
/* Virtual functions */
void (*buildxml) (GPtrArray * stringarray);
@@ -96,7 +105,7 @@ struct _DbusmenuMenuitemClass
void (*reserved1) (void);
void (*reserved2) (void);
void (*reserved3) (void);
- void (*reserved4) (void);
+ /* void (*reserved4) (void); -- realized, realloc when bumping lib version */
};
GType dbusmenu_menuitem_get_type (void);
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
index a236123..7271c37 100644
--- a/libdbusmenu-gtk/client.c
+++ b/libdbusmenu-gtk/client.c
@@ -44,6 +44,10 @@ static void new_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint po
static void delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, DbusmenuGtkClient * gtkclient);
static void move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint old, DbusmenuGtkClient * gtkclient);
+static gboolean new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+static gboolean new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+static gboolean new_item_image (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+
/* GObject Stuff */
G_DEFINE_TYPE (DbusmenuGtkClient, dbusmenu_gtkclient, DBUSMENU_TYPE_CLIENT);
@@ -61,7 +65,12 @@ dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass)
static void
dbusmenu_gtkclient_init (DbusmenuGtkClient *self)
{
+ dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_DEFAULT, new_item_normal);
+ dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_SEPARATOR, new_item_seperator);
+ dbusmenu_client_add_type_handler(DBUSMENU_CLIENT(self), DBUSMENU_CLIENT_TYPES_IMAGE, new_item_image);
+
g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM, G_CALLBACK(new_menuitem), NULL);
+
return;
}
@@ -95,14 +104,27 @@ menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
return TRUE;
}
+/* Process the visible property */
+static void
+process_visible (GtkMenuItem * gmi, const gchar * value)
+{
+ if (value == NULL || !g_strcmp0(value, "true")) {
+ gtk_widget_show(GTK_WIDGET(gmi));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(gmi));
+ }
+ return;
+}
+
/* Whenever we have a property change on a DbusmenuMenuitem
we need to be responsive to that. */
static void
menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, GtkMenuItem * gmi)
{
- if (!g_strcmp0(prop, "label")) {
+ if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_LABEL)) {
gtk_menu_item_set_label(gmi, value);
- gtk_widget_show(GTK_WIDGET(gmi));
+ } else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_VISIBLE)) {
+ process_visible(gmi, value);
}
return;
@@ -125,31 +147,34 @@ destoryed_dbusmenuitem_cb (gpointer udata, GObject * dbusmenuitem)
static void
new_menuitem (DbusmenuClient * client, DbusmenuMenuitem * mi, gpointer userdata)
{
- gpointer ann_mi = g_object_get_data(G_OBJECT(mi), data_menuitem);
- GtkMenuItem * gmi = GTK_MENU_ITEM(ann_mi);
+ g_warning("Got new menuitem signal, which means they want something");
+ g_warning(" that I simply don't have.");
- if (gmi != NULL) {
- /* It's possible we've already been looked at, that's
- okay, but we can just ignore this signal then. */
- return;
- }
-
- gmi = GTK_MENU_ITEM(gtk_menu_item_new());
+ return;
+}
+void
+dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * item, GtkMenuItem * gmi, DbusmenuMenuitem * parent)
+{
/* Attach these two */
- g_object_set_data(G_OBJECT(mi), data_menuitem, gmi);
+ g_object_set_data(G_OBJECT(item), data_menuitem, gmi);
/* DbusmenuMenuitem signals */
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi);
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(new_child), client);
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(delete_child), client);
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(move_child), client);
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi);
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(delete_child), client);
+ g_signal_connect(G_OBJECT(item), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(move_child), client);
/* GtkMenuitem signals */
- g_signal_connect(G_OBJECT(gmi), "activate", G_CALLBACK(menu_pressed_cb), mi);
+ g_signal_connect(G_OBJECT(gmi), "activate", G_CALLBACK(menu_pressed_cb), item);
/* Life insurance */
- g_object_weak_ref(G_OBJECT(mi), destoryed_dbusmenuitem_cb, gmi);
+ g_object_weak_ref(G_OBJECT(item), destoryed_dbusmenuitem_cb, gmi);
+
+ process_visible(gmi, dbusmenu_menuitem_property_get(item, DBUSMENU_MENUITEM_PROP_VISIBLE));
+
+ if (parent != NULL) {
+ new_child(parent, item, dbusmenu_menuitem_get_position(item, parent), DBUSMENU_GTKCLIENT(client));
+ }
return;
}
@@ -251,10 +276,55 @@ dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem *
GtkMenuItem * mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem));
if (mi == NULL) {
- new_menuitem(DBUSMENU_CLIENT(client), item, NULL);
+ // new_menuitem(DBUSMENU_CLIENT(client), item, NULL);
+ g_warning("GTK not updated");
mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem));
}
return mi;
}
+static gboolean
+new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
+ /* Note: not checking parent, it's reasonable for it to be NULL */
+
+ GtkMenuItem * gmi;
+ gmi = GTK_MENU_ITEM(gtk_menu_item_new_with_label(dbusmenu_menuitem_property_get(newitem, DBUSMENU_MENUITEM_PROP_LABEL)));
+
+ if (gmi != NULL) {
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
+ /* Note: not checking parent, it's reasonable for it to be NULL */
+
+ GtkMenuItem * gmi;
+ gmi = GTK_MENU_ITEM(gtk_separator_menu_item_new());
+
+ if (gmi != NULL) {
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+new_item_image (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+
+ return TRUE;
+}
diff --git a/libdbusmenu-gtk/client.h b/libdbusmenu-gtk/client.h
index a549fe0..b1d816f 100644
--- a/libdbusmenu-gtk/client.h
+++ b/libdbusmenu-gtk/client.h
@@ -79,6 +79,8 @@ GType dbusmenu_gtkclient_get_type (void);
DbusmenuGtkClient * dbusmenu_gtkclient_new (gchar * dbus_name, gchar * dbus_object);
GtkMenuItem * dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem * item);
+void dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * item, GtkMenuItem * gmi, DbusmenuMenuitem * parent);
+
/**
SECTION:gtkmenu
@short_description: A GTK Menu Object that syncronizes over DBus
diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c
index bc7458c..74e1bec 100644
--- a/libdbusmenu-gtk/menu.c
+++ b/libdbusmenu-gtk/menu.c
@@ -64,6 +64,7 @@ static void set_property (GObject * obj, guint id, const GValue * value, GParamS
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
/* Internal */
static void build_client (DbusmenuGtkMenu * self);
+static void child_realized (DbusmenuMenuitem * child, gpointer userdata);
/* GObject Stuff */
G_DEFINE_TYPE (DbusmenuGtkMenu, dbusmenu_gtkmenu, GTK_TYPE_MENU);
@@ -188,9 +189,7 @@ static void
root_child_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, DbusmenuGtkMenu * menu)
{
g_debug("Root new child");
- DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
- gtk_menu_shell_insert(GTK_MENU_SHELL(menu), GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)), position);
- gtk_widget_show(GTK_WIDGET(menu));
+ g_signal_connect(G_OBJECT(child), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(child_realized), menu);
return;
}
@@ -214,6 +213,18 @@ root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGt
}
static void
+child_realized (DbusmenuMenuitem * child, gpointer userdata)
+{
+ g_return_if_fail(DBUSMENU_IS_GTKMENU(userdata));
+
+ DbusmenuGtkMenu * menu = DBUSMENU_GTKMENU(userdata);
+ DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
+
+ gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)));
+ return;
+}
+
+static void
root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu) {
if (newroot == NULL) {
gtk_widget_hide(GTK_WIDGET(menu));
@@ -227,7 +238,8 @@ root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGt
GList * child = NULL;
guint count = 0;
for (child = dbusmenu_menuitem_get_children(newroot); child != NULL; child = g_list_next(child)) {
- gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(client, child->data)));
+ /* gtk_menu_append(menu, GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(client, child->data))); */
+ g_signal_connect(G_OBJECT(child->data), DBUSMENU_MENUITEM_SIGNAL_REALIZED, G_CALLBACK(child_realized), menu);
count++;
}
@@ -279,3 +291,19 @@ dbusmenu_gtkmenu_new (gchar * dbus_name, gchar * dbus_object)
NULL);
}
+/**
+ dbusmenu_gtkmenu_get_client:
+ @menu: The #DbusmenuGtkMenu to get the client from
+
+ An accessor for the client that this menu is using to
+ communicate with the server.
+
+ Return value: A valid #DbusmenuGtkClient or NULL on error.
+*/
+DbusmenuGtkClient *
+dbusmenu_gtkmenu_get_client (DbusmenuGtkMenu * menu)
+{
+ g_return_val_if_fail(DBUSMENU_IS_GTKMENU(menu), NULL);
+ DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
+ return priv->client;
+}
diff --git a/libdbusmenu-gtk/menu.h b/libdbusmenu-gtk/menu.h
index 73804c5..5147d30 100644
--- a/libdbusmenu-gtk/menu.h
+++ b/libdbusmenu-gtk/menu.h
@@ -31,6 +31,7 @@ License version 3 and version 2.1 along with this program. If not, see
#include <glib.h>
#include <glib-object.h>
+#include "client.h"
G_BEGIN_DECLS
@@ -71,6 +72,7 @@ struct _DbusmenuGtkMenu {
GType dbusmenu_gtkmenu_get_type (void);
DbusmenuGtkMenu * dbusmenu_gtkmenu_new (gchar * dbus_name, gchar * dbus_object);
+DbusmenuGtkClient * dbusmenu_gtkmenu_get_client (DbusmenuGtkMenu * menu);
/**
SECTION:gtkmenu
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
index c7e8302..402a25f 100644
--- a/po/Makefile.in.in
+++ b/po/Makefile.in.in
@@ -56,7 +56,7 @@ ALL_LINGUAS = @ALL_LINGUAS@
PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi)
-USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep '^$$lang$$' $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep '^$$lang$$'`"; then printf "$$lang "; fi; done; fi)
+USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi)
USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done)
diff --git a/tests/test-gtk-label.json b/tests/test-gtk-label.json
index 64c1386..19a6ca6 100644
--- a/tests/test-gtk-label.json
+++ b/tests/test-gtk-label.json
@@ -1,155 +1,155 @@
[
- {"id": 1,
+ {"id": 1, "type": "menuitem",
"label": "value1",
"submenu": [
- {"id": 30,
+ {"id": 30, "type": "menuitem",
"label": "value30"},
- {"id": 31,
+ {"id": 31, "type": "menuitem",
"label": "value31"},
- {"id": 32,
+ {"id": 32, "type": "menuitem",
"label": "value32"},
- {"id": 33,
+ {"id": 33, "type": "menuitem",
"label": "value33"},
- {"id": 34,
+ {"id": 34, "type": "menuitem",
"label": "value34"},
- {"id": 35,
+ {"id": 35, "type": "menuitem",
"label": "value35"},
- {"id": 36,
+ {"id": 36, "type": "menuitem",
"label": "value36"},
- {"id": 37,
+ {"id": 37, "type": "menuitem",
"label": "value37"},
- {"id": 38,
+ {"id": 38, "type": "menuitem",
"label": "value38"},
- {"id": 39,
+ {"id": 39, "type": "menuitem",
"label": "value39"}
]
},
- {"id": 2,
+ {"id": 2, "type": "menuitem",
"label": "value2",
"submenu": [
- {"id": 20,
+ {"id": 20, "type": "menuitem",
"label": "value20"},
- {"id": 21,
+ {"id": 21, "type": "separator",
"label": "value21"},
- {"id": 22,
+ {"id": 22, "type": "menuitem",
"label": "value22"},
- {"id": 23,
+ {"id": 23, "type": "separator",
"label": "value23"},
- {"id": 24,
+ {"id": 24, "type": "menuitem",
"label": "value24"},
- {"id": 25,
+ {"id": 25, "type": "separator",
"label": "value25"},
- {"id": 26,
+ {"id": 26, "type": "menuitem",
"label": "value26"},
- {"id": 27,
+ {"id": 27, "type": "separator",
"label": "value27"},
- {"id": 28,
+ {"id": 28, "type": "menuitem",
"label": "value28"},
- {"id": 29,
+ {"id": 29, "type": "menuitem", "visible": "false",
"label": "value29"}
]
},
- {"id": 3,
+ {"id": 3, "type": "menuitem",
"label": "a super long label that is really of unreasonable length but we should make sure it makes it across the bus",
"not.a.value": "A useless value",
"submenu": [
- {"id": 10,
+ {"id": 10, "type": "menuitem",
"label": "value10"},
- {"id": 11,
+ {"id": 11, "type": "menuitem",
"label": "value11"},
- {"id": 12,
+ {"id": 12, "type": "menuitem",
"label": "value12"},
- {"id": 13,
+ {"id": 13, "type": "menuitem",
"label": "value13"},
- {"id": 14,
+ {"id": 14, "type": "menuitem",
"label": "value14"},
- {"id": 15,
+ {"id": 15, "type": "menuitem",
"label": "value15"},
- {"id": 16,
+ {"id": 16, "type": "menuitem",
"label": "value16"},
- {"id": 17,
+ {"id": 17, "type": "menuitem",
"label": "value17"},
- {"id": 18,
+ {"id": 18, "type": "menuitem",
"label": "value18"},
- {"id": 19,
+ {"id": 19, "type": "menuitem",
"label": "value19"}
]
},
- {"id": 4,
+ {"id": 4, "type": "menuitem",
"label": "value2",
"submenu": [
- {"id": 5,
+ {"id": 5, "type": "menuitem",
"label": "value5",
"submenu": [
- {"id": 10,
+ {"id": 10, "type": "menuitem",
"label": "value10"},
- {"id": 11,
+ {"id": 11, "type": "menuitem",
"label": "value11"},
- {"id": 12,
+ {"id": 12, "type": "menuitem",
"label": "value12"},
- {"id": 13,
+ {"id": 13, "type": "menuitem",
"label": "value13"},
- {"id": 14,
+ {"id": 14, "type": "menuitem",
"label": "value14"},
- {"id": 15,
+ {"id": 15, "type": "menuitem",
"label": "value15"},
- {"id": 16,
+ {"id": 16, "type": "menuitem",
"label": "value16"},
- {"id": 17,
+ {"id": 17, "type": "menuitem",
"label": "value17"},
- {"id": 18,
+ {"id": 18, "type": "menuitem",
"label": "value18"},
- {"id": 19,
+ {"id": 19, "type": "menuitem",
"label": "value19"}
]
},
- {"id": 6,
+ {"id": 6, "type": "menuitem",
"label": "value6",
"submenu": [
- {"id": 20,
+ {"id": 20, "type": "menuitem",
"label": "value20"},
- {"id": 21,
+ {"id": 21, "type": "menuitem",
"label": "value21"},
- {"id": 22,
+ {"id": 22, "type": "menuitem",
"label": "value22"},
- {"id": 23,
+ {"id": 23, "type": "menuitem",
"label": "value23"},
- {"id": 24,
+ {"id": 24, "type": "menuitem",
"label": "value24"},
- {"id": 25,
+ {"id": 25, "type": "menuitem",
"label": "value25"},
- {"id": 26,
+ {"id": 26, "type": "menuitem",
"label": "value26"},
- {"id": 27,
+ {"id": 27, "type": "menuitem",
"label": "value27"},
- {"id": 28,
+ {"id": 28, "type": "menuitem",
"label": "value28"},
- {"id": 29,
+ {"id": 29, "type": "menuitem",
"label": "value29"}
]
},
- {"id": 7,
+ {"id": 7, "type": "menuitem",
"label": "value7",
"submenu": [
- {"id": 30,
+ {"id": 30, "type": "menuitem",
"label": "value30"},
- {"id": 31,
+ {"id": 31, "type": "menuitem",
"label": "value31"},
- {"id": 32,
+ {"id": 32, "type": "menuitem",
"label": "value32"},
- {"id": 33,
+ {"id": 33, "type": "menuitem",
"label": "value33"},
- {"id": 34,
+ {"id": 34, "type": "menuitem",
"label": "value34"},
- {"id": 35,
+ {"id": 35, "type": "menuitem",
"label": "value35"},
- {"id": 36,
+ {"id": 36, "type": "menuitem",
"label": "value36"},
- {"id": 37,
+ {"id": 37, "type": "menuitem",
"label": "value37"},
- {"id": 38,
+ {"id": 38, "type": "menuitem",
"label": "value38"},
- {"id": 39,
+ {"id": 39, "type": "menuitem",
"label": "value39"}
]
},