aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-gtk
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-gtk')
-rw-r--r--libdbusmenu-gtk/Makefile.am6
-rw-r--r--libdbusmenu-gtk/client.c260
-rw-r--r--libdbusmenu-gtk/client.h109
-rw-r--r--libdbusmenu-gtk/menu.c143
-rw-r--r--libdbusmenu-gtk/menu.h28
5 files changed, 462 insertions, 84 deletions
diff --git a/libdbusmenu-gtk/Makefile.am b/libdbusmenu-gtk/Makefile.am
index 80e6058..c375428 100644
--- a/libdbusmenu-gtk/Makefile.am
+++ b/libdbusmenu-gtk/Makefile.am
@@ -8,9 +8,13 @@ lib_LTLIBRARIES = \
libdbusmenu_gtkincludedir=$(includedir)/libdbusmenu-0.1/libdbusmenu-gtk/
libdbusmenu_gtkinclude_HEADERS = \
+ client.h \
menu.h
libdbusmenu_gtk_la_SOURCES = \
+ client.h \
+ client.c \
+ menu.h \
menu.c
libdbusmenu_gtk_la_LDFLAGS = \
@@ -19,7 +23,7 @@ libdbusmenu_gtk_la_LDFLAGS = \
-export-symbols-regex "^[^_].*"
libdbusmenu_gtk_la_CFLAGS = \
- $(DBUSMENUGTK_CFLAGS) -Wall -Werror
+ $(DBUSMENUGTK_CFLAGS) -I$(srcdir)/.. -Wall -Werror
libdbusmenu_gtk_la_LIBADD = \
../libdbusmenu-glib/libdbusmenu-glib.la \
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
new file mode 100644
index 0000000..a236123
--- /dev/null
+++ b/libdbusmenu-gtk/client.c
@@ -0,0 +1,260 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 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 <gtk/gtk.h>
+
+#include "client.h"
+
+/* Prototypes */
+static void dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass);
+static void dbusmenu_gtkclient_init (DbusmenuGtkClient *self);
+static void dbusmenu_gtkclient_dispose (GObject *object);
+static void dbusmenu_gtkclient_finalize (GObject *object);
+static void new_menuitem (DbusmenuClient * client, DbusmenuMenuitem * mi, gpointer userdata);
+static void new_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint position, DbusmenuGtkClient * gtkclient);
+static void delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, DbusmenuGtkClient * gtkclient);
+static void move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint old, DbusmenuGtkClient * gtkclient);
+
+/* GObject Stuff */
+G_DEFINE_TYPE (DbusmenuGtkClient, dbusmenu_gtkclient, DBUSMENU_TYPE_CLIENT);
+
+static void
+dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = dbusmenu_gtkclient_dispose;
+ object_class->finalize = dbusmenu_gtkclient_finalize;
+
+ return;
+}
+
+static void
+dbusmenu_gtkclient_init (DbusmenuGtkClient *self)
+{
+ g_signal_connect(G_OBJECT(self), DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM, G_CALLBACK(new_menuitem), NULL);
+ return;
+}
+
+static void
+dbusmenu_gtkclient_dispose (GObject *object)
+{
+
+ G_OBJECT_CLASS (dbusmenu_gtkclient_parent_class)->dispose (object);
+ return;
+}
+
+static void
+dbusmenu_gtkclient_finalize (GObject *object)
+{
+
+ G_OBJECT_CLASS (dbusmenu_gtkclient_parent_class)->finalize (object);
+ return;
+}
+
+/* Internal Functions */
+
+static const gchar * data_menuitem = "dbusmenugtk-data-gtkmenuitem";
+static const gchar * data_menu = "dbusmenugtk-data-gtkmenu";
+
+/* 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. */
+static gboolean
+menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
+{
+ dbusmenu_menuitem_activate(mi);
+ return TRUE;
+}
+
+/* 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")) {
+ gtk_menu_item_set_label(gmi, value);
+ gtk_widget_show(GTK_WIDGET(gmi));
+ }
+
+ 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)
+{
+ /* g_debug("DbusmenuMenuitem was destroyed"); */
+ gtk_widget_destroy(GTK_WIDGET(udata));
+ return;
+}
+
+/* This takes a new DbusmenuMenuitem and attaches the
+ various things that we need to make it work in a
+ GTK World. */
+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);
+
+ 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());
+
+ /* Attach these two */
+ g_object_set_data(G_OBJECT(mi), 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);
+
+ /* GtkMenuitem signals */
+ g_signal_connect(G_OBJECT(gmi), "activate", G_CALLBACK(menu_pressed_cb), mi);
+
+ /* Life insurance */
+ g_object_weak_ref(G_OBJECT(mi), destoryed_dbusmenuitem_cb, gmi);
+
+ return;
+}
+
+static void
+new_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint position, DbusmenuGtkClient * gtkclient)
+{
+ if (dbusmenu_menuitem_get_root(mi)) { return; }
+
+ gpointer ann_menu = g_object_get_data(G_OBJECT(mi), data_menu);
+ GtkMenu * menu = GTK_MENU(ann_menu);
+ if (menu == NULL) {
+ /* Oh, we don't have a submenu, build one! */
+ menu = GTK_MENU(gtk_menu_new());
+ g_object_set_data(G_OBJECT(mi), data_menu, menu);
+
+ GtkMenuItem * parent = dbusmenu_gtkclient_menuitem_get(gtkclient, mi);
+ gtk_menu_item_set_submenu(parent, GTK_WIDGET(menu));
+ }
+
+ GtkMenuItem * childmi = dbusmenu_gtkclient_menuitem_get(gtkclient, child);
+ gtk_menu_shell_insert(GTK_MENU_SHELL(menu), GTK_WIDGET(childmi), position);
+ gtk_widget_show(GTK_WIDGET(menu));
+
+ return;
+}
+
+static void
+delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, DbusmenuGtkClient * gtkclient)
+{
+ if (dbusmenu_menuitem_get_root(mi)) { return; }
+
+ if (g_list_length(dbusmenu_menuitem_get_children(mi)) == 0) {
+ gpointer ann_menu = g_object_get_data(G_OBJECT(mi), data_menu);
+ GtkMenu * menu = GTK_MENU(ann_menu);
+
+ if (menu != NULL) {
+ gtk_widget_destroy(GTK_WIDGET(menu));
+ g_object_set_data(G_OBJECT(mi), data_menu, NULL);
+ }
+ }
+
+ return;
+}
+
+static void
+move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint old, DbusmenuGtkClient * gtkclient)
+{
+ if (dbusmenu_menuitem_get_root(mi)) { return; }
+
+ gpointer ann_menu = g_object_get_data(G_OBJECT(mi), data_menu);
+ if (ann_menu == NULL) {
+ g_warning("Moving a child when we don't have a submenu!");
+ return;
+ }
+
+ GtkMenuItem * childmi = dbusmenu_gtkclient_menuitem_get(gtkclient, child);
+ gtk_menu_reorder_child(GTK_MENU(ann_menu), GTK_WIDGET(childmi), new);
+
+ return;
+}
+
+/* Public API */
+
+/**
+ dbusmenu_gtkclient_new:
+ @dbus_name: Name of the #DbusmenuServer on DBus
+ @dbus_name: Name of the object on the #DbusmenuServer
+
+ Creates a new #DbusmenuGtkClient object and creates a #DbusmenuClient
+ that connects across DBus to a #DbusmenuServer.
+
+ Return value: A new #DbusmenuGtkClient sync'd with a server
+*/
+DbusmenuGtkClient *
+dbusmenu_gtkclient_new (gchar * dbus_name, gchar * dbus_object)
+{
+ return g_object_new(DBUSMENU_GTKCLIENT_TYPE,
+ DBUSMENU_CLIENT_PROP_DBUS_OBJECT, dbus_object,
+ DBUSMENU_CLIENT_PROP_DBUS_NAME, dbus_name,
+ NULL);
+}
+
+/**
+ dbusmenu_gtkclient_menuitem_get:
+ @client: A #DbusmenuGtkClient with the item in it.
+ @item: #DbusmenuMenuitem to get associated #GtkMenuItem on.
+
+ This grabs the #GtkMenuItem that is associated with the
+ #DbusmenuMenuitem.
+
+ Return value: The #GtkMenuItem that can be played with.
+*/
+GtkMenuItem *
+dbusmenu_gtkclient_menuitem_get (DbusmenuGtkClient * client, DbusmenuMenuitem * item)
+{
+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), NULL);
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(item), NULL);
+
+ GtkMenuItem * mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem));
+ if (mi == NULL) {
+ new_menuitem(DBUSMENU_CLIENT(client), item, NULL);
+ mi = GTK_MENU_ITEM(g_object_get_data(G_OBJECT(item), data_menuitem));
+ }
+
+ return mi;
+}
+
diff --git a/libdbusmenu-gtk/client.h b/libdbusmenu-gtk/client.h
new file mode 100644
index 0000000..a549fe0
--- /dev/null
+++ b/libdbusmenu-gtk/client.h
@@ -0,0 +1,109 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 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_GTKCLIENT_H__
+#define __DBUSMENU_GTKCLIENT_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <libdbusmenu-glib/client.h>
+
+G_BEGIN_DECLS
+
+#define DBUSMENU_GTKCLIENT_TYPE (dbusmenu_gtkclient_get_type ())
+#define DBUSMENU_GTKCLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUSMENU_GTKCLIENT_TYPE, DbusmenuGtkClient))
+#define DBUSMENU_GTKCLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUSMENU_GTKCLIENT_TYPE, DbusmenuGtkClientClass))
+#define DBUSMENU_IS_GTKCLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUSMENU_GTKCLIENT_TYPE))
+#define DBUSMENU_IS_GTKCLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUSMENU_GTKCLIENT_TYPE))
+#define DBUSMENU_GTKCLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_GTKCLIENT_TYPE, DbusmenuGtkClientClass))
+
+#define DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED
+
+/**
+ DbusmenuGtkClientClass:
+ @parent_class: #GtkMenuClass
+ @reserved1: Reserved for future use.
+ @reserved2: Reserved for future use.
+ @reserved3: Reserved for future use.
+ @reserved4: Reserved for future use.
+*/
+typedef struct _DbusmenuGtkClientClass DbusmenuGtkClientClass;
+struct _DbusmenuGtkClientClass {
+ DbusmenuClientClass parent_class;
+
+ /* Signals */
+ void (*root_changed) (DbusmenuMenuitem * newroot);
+
+ /* Reserved */
+ void (*reserved1) (void);
+ void (*reserved2) (void);
+ void (*reserved3) (void);
+ void (*reserved4) (void);
+};
+
+/**
+ DbusmenuGtkClient:
+ @parent: #GtkMenu
+*/
+typedef struct _DbusmenuGtkClient DbusmenuGtkClient;
+struct _DbusmenuGtkClient {
+ DbusmenuClient parent;
+};
+
+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);
+
+/**
+ SECTION:gtkmenu
+ @short_description: A GTK Menu Object that syncronizes over DBus
+ @stability: Unstable
+ @include: libdbusmenu-gtk/menu.h
+
+ In general, this is just a #GtkMenu, why else would you care? Oh,
+ because this menu is created by someone else on a server that exists
+ on the other side of DBus. You need a #DbusmenuServer to be able
+ push the data into this menu.
+
+ The first thing you need to know is how to find that #DbusmenuServer
+ on DBus. This involves both the DBus name and the DBus object that
+ the menu interface can be found on. Those two value should be set
+ when creating the object using dbusmenu_gtkmenu_new(). They are then
+ stored on two properties #DbusmenuGtkClient:dbus-name and #DbusmenuGtkClient:dbus-object.
+
+ After creation the #DbusmenuGtkClient it will continue to keep in
+ synchronization with the #DbusmenuServer object across Dbus. If the
+ number of entries change, the menus change, if they change thier
+ properties change, they update in the items. All of this should
+ be handled transparently to the user of this object.
+
+ TODO: Document properties.
+*/
+G_END_DECLS
+
+#endif
diff --git a/libdbusmenu-gtk/menu.c b/libdbusmenu-gtk/menu.c
index dd2df37..bc7458c 100644
--- a/libdbusmenu-gtk/menu.c
+++ b/libdbusmenu-gtk/menu.c
@@ -1,3 +1,31 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 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
@@ -6,6 +34,7 @@
#include "menu.h"
#include "libdbusmenu-glib/client.h"
+#include "client.h"
/* Properties */
enum {
@@ -17,7 +46,7 @@ enum {
/* Private */
typedef struct _DbusmenuGtkMenuPrivate DbusmenuGtkMenuPrivate;
struct _DbusmenuGtkMenuPrivate {
- DbusmenuClient * client;
+ DbusmenuGtkClient * client;
gchar * dbus_object;
gchar * dbus_name;
@@ -155,114 +184,62 @@ get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec)
/* Internal Functions */
-static const gchar * data_menuitem = "dbusmenugtk-data-gtkmenuitem";
-static const gchar * data_menu = "dbusmenugtk-data-gtkmenu";
-
-static gboolean
-menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
-{
- dbusmenu_menuitem_activate(mi);
- return TRUE;
-}
-
static void
-menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, gchar * value, GtkMenuItem * gmi)
+root_child_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, DbusmenuGtkMenu * menu)
{
- if (!g_strcmp0(prop, "label")) {
- gtk_menu_item_set_label(gmi, value);
- gtk_widget_show(GTK_WIDGET(gmi));
- }
-
+ 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));
return;
}
static void
-destoryed_dbusmenuitem_cb (gpointer udata, GObject * dbusmenuitem)
+root_child_moved (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint newposition, guint oldposition, DbusmenuGtkMenu * menu)
{
- /* g_debug("DbusmenuMenuitem was destroyed"); */
- gtk_widget_destroy(GTK_WIDGET(udata));
+ g_debug("Root child moved");
+ DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(menu);
+ gtk_menu_reorder_child(GTK_MENU(menu), GTK_WIDGET(dbusmenu_gtkclient_menuitem_get(priv->client, child)), newposition);
return;
}
static void
-connect_menuitem (DbusmenuMenuitem * mi, GtkMenuItem * gmi)
+root_child_delete (DbusmenuMenuitem * root, DbusmenuMenuitem * child, DbusmenuGtkMenu * menu)
{
- g_object_set_data(G_OBJECT(mi), data_menuitem, gmi);
-
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(menu_prop_change_cb), gmi);
- g_signal_connect(G_OBJECT(gmi), "activate", G_CALLBACK(menu_pressed_cb), mi);
-
- g_object_weak_ref(G_OBJECT(mi), destoryed_dbusmenuitem_cb, gmi);
-
+ g_debug("Root child deleted");
+ if (g_list_length(dbusmenu_menuitem_get_children(root)) == 0) {
+ gtk_widget_hide(GTK_WIDGET(menu));
+ }
return;
}
static void
-process_dbusmenu_menuitem (DbusmenuMenuitem * mi, GtkMenu * parentmenu)
-{
- gpointer unknown_menuitem = g_object_get_data(G_OBJECT(mi), data_menuitem);
- if (unknown_menuitem == NULL) {
- /* Oh, a virgin DbusmenuMenuitem, let's fix that. */
- GtkWidget * menuitem = gtk_menu_item_new();
- connect_menuitem(mi, GTK_MENU_ITEM(menuitem));
- unknown_menuitem = menuitem;
- gtk_menu_shell_append(GTK_MENU_SHELL(parentmenu), menuitem);
- }
-
- GList * children = dbusmenu_menuitem_get_children(mi);
- if (children == NULL) {
- /* If there are no children to process we are
- done and we can move along */
+root_changed (DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, DbusmenuGtkMenu * menu) {
+ if (newroot == NULL) {
+ gtk_widget_hide(GTK_WIDGET(menu));
return;
}
- /* Phase 0: Make a submenu if we don't have one */
- gpointer unknown_menu = g_object_get_data(G_OBJECT(mi), data_menu);
- if (unknown_menu == NULL) {
- GtkWidget * gtkmenu = gtk_menu_new();
- g_object_ref(gtkmenu);
- g_object_set_data_full(G_OBJECT(mi), data_menu, gtkmenu, g_object_unref);
- unknown_menu = gtkmenu;
- gtk_menu_item_set_submenu(GTK_MENU_ITEM(unknown_menuitem), gtkmenu);
- gtk_widget_show(gtkmenu);
- }
+ g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(root_child_added), menu);
+ g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(root_child_moved), menu);
+ g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(root_child_delete), menu);
- /* Phase 1: Add missing children */
GList * child = NULL;
- for (child = children; child != NULL; child = g_list_next(child)) {
- process_dbusmenu_menuitem(DBUSMENU_MENUITEM(child->data), GTK_MENU(unknown_menu));
+ 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)));
+ count++;
}
- /* Phase 2: Delete removed children */
- /* Actually, we don't need to do this because of the weak
- reference that we've added above. When the DbusmenuMenuitem
- gets destroyed it takes its GtkMenuItem with it. Bye bye. */
-
- /* Phase 3: Profit! */
- return;
-}
-
-/* Processing the layout being updated and handling
- that and making it into a menu */
-static void
-process_layout_change (DbusmenuClient * client, DbusmenuGtkMenu * gtkmenu)
-{
- DbusmenuMenuitem * root = dbusmenu_client_get_root(client);
-
- GList * children = dbusmenu_menuitem_get_children(root);
- if (children == NULL) {
- return;
- }
-
- GList * child = NULL;
- for (child = children; child != NULL; child = g_list_next(child)) {
- process_dbusmenu_menuitem(DBUSMENU_MENUITEM(child->data), GTK_MENU(gtkmenu));
+ if (count > 0) {
+ gtk_widget_show(GTK_WIDGET(menu));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(menu));
}
return;
}
-
/* Builds the client and connects all of the signals
up for it so that it's happy-happy */
static void
@@ -271,11 +248,11 @@ build_client (DbusmenuGtkMenu * self)
DbusmenuGtkMenuPrivate * priv = DBUSMENU_GTKMENU_GET_PRIVATE(self);
if (priv->client == NULL) {
- priv->client = dbusmenu_client_new(priv->dbus_name, priv->dbus_object);
+ priv->client = dbusmenu_gtkclient_new(priv->dbus_name, priv->dbus_object);
/* Register for layout changes, this should come after the
creation of the client pulls it from DBus */
- g_signal_connect(G_OBJECT(priv->client), DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED, G_CALLBACK(process_layout_change), self);
+ g_signal_connect(G_OBJECT(priv->client), DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(root_changed), self);
}
return;
diff --git a/libdbusmenu-gtk/menu.h b/libdbusmenu-gtk/menu.h
index dd5bdd1..73804c5 100644
--- a/libdbusmenu-gtk/menu.h
+++ b/libdbusmenu-gtk/menu.h
@@ -1,3 +1,31 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 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_GTKMENU_H__
#define __DBUSMENU_GTKMENU_H__