ayatana-commits team mailing list archive
-
ayatana-commits team
-
Mailing list archive
-
Message #00545
[Merge] lp:~bratsche/dbusmenu/menubar into lp:dbusmenu
Cody Russell has proposed merging lp:~bratsche/dbusmenu/menubar into lp:dbusmenu.
Requested reviews:
DBus Menu Team (dbusmenu-team)
Related bugs:
#458732 Menubars ftw
https://bugs.launchpad.net/bugs/458732
--
https://code.launchpad.net/~bratsche/dbusmenu/menubar/+merge/13817
Your team ayatana-commits is subscribed to branch lp:dbusmenu.
=== modified file 'libdbusmenu-gtk/Makefile.am'
--- libdbusmenu-gtk/Makefile.am 2009-10-01 19:22:18 +0000
+++ libdbusmenu-gtk/Makefile.am 2009-10-23 03:40:22 +0000
@@ -10,6 +10,7 @@
libdbusmenu_gtkinclude_HEADERS = \
client.h \
menu.h \
+ menubar.h \
menuitem.h
libdbusmenu_gtk_la_SOURCES = \
@@ -17,6 +18,8 @@
client.c \
menu.h \
menu.c \
+ menubar.h \
+ menubar.c \
menuitem.h \
menuitem.c
=== added file 'libdbusmenu-gtk/menubar.c'
--- libdbusmenu-gtk/menubar.c 1970-01-01 00:00:00 +0000
+++ libdbusmenu-gtk/menubar.c 2009-10-23 03:40:22 +0000
@@ -0,0 +1,342 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Cody Russell <crussell@xxxxxxxxxxxxx>
+ Ted Gould <ted@xxxxxxxxxxxxx>
+
+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 "menubar.h"
+#include "libdbusmenu-glib/client.h"
+#include "client.h"
+
+/* Properties */
+enum {
+ PROP_0,
+ PROP_DBUSOBJECT,
+ PROP_DBUSNAME
+};
+
+/* Private */
+struct _DbusmenuGtkmenubarPrivate {
+ DbusmenuGtkClient *client;
+
+ gchar *dbus_object;
+ gchar *dbus_name;
+};
+
+#define DBUSMENU_GTKMENUBAR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_GTKMENUBAR_TYPE, DbusmenuGtkmenubarPrivate))
+
+/* Prototypes */
+static void dbusmenu_gtkmenubar_class_init (DbusmenuGtkmenubarClass *klass);
+static void dbusmenu_gtkmenubar_init (DbusmenuGtkmenubar *self);
+static void dbusmenu_gtkmenubar_dispose (GObject *object);
+static void dbusmenu_gtkmenubar_finalize (GObject *object);
+static void dbusmenu_gtkmenubar_set_property (GObject *obj,
+ guint id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void dbusmenu_gtkmenubar_get_property (GObject *obj,
+ guint id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void build_client (DbusmenuGtkmenubar *self);
+static void child_realized (DbusmenuMenuitem *child,
+ gpointer userdata);
+
+G_DEFINE_TYPE (DbusmenuGtkmenubar, dbusmenu_gtkmenubar, GTK_TYPE_MENU_BAR);
+
+static void
+dbusmenu_gtkmenubar_class_init (DbusmenuGtkmenubarClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (DbusmenuGtkmenubarPrivate));
+
+ object_class->dispose = dbusmenu_gtkmenubar_dispose;
+ object_class->finalize = dbusmenu_gtkmenubar_finalize;
+ object_class->set_property = dbusmenu_gtkmenubar_set_property;
+ object_class->get_property = dbusmenu_gtkmenubar_get_property;
+
+ g_object_class_install_property (object_class,
+ PROP_DBUSOBJECT,
+ g_param_spec_string (DBUSMENU_CLIENT_PROP_DBUS_OBJECT,
+ "DBus Object we represent",
+ "The Object on the client that we're getting our data from.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class,
+ PROP_DBUSNAME,
+ g_param_spec_string (DBUSMENU_CLIENT_PROP_DBUS_NAME,
+ "DBus Client we connect to",
+ "Name of the DBus client we're connecting to.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+dbusmenu_gtkmenubar_init (DbusmenuGtkmenubar *self)
+{
+ DbusmenuGtkmenubarPrivate *priv = self->priv = DBUSMENU_GTKMENUBAR_GET_PRIVATE (self);
+
+ priv->client = NULL;
+
+ priv->dbus_object = NULL;
+ priv->dbus_name = NULL;
+}
+
+static void
+dbusmenu_gtkmenubar_dispose (GObject *object)
+{
+ DbusmenuGtkmenubar *menubar = DBUSMENU_GTKMENUBAR (object);
+
+ if (menubar->priv->client != NULL) {
+ g_object_unref (G_OBJECT (menubar->priv->client));
+ menubar->priv->client = NULL;
+ }
+
+ G_OBJECT_CLASS (dbusmenu_gtkmenubar_parent_class)->dispose (object);
+}
+
+static void
+dbusmenu_gtkmenubar_finalize (GObject *object)
+{
+ DbusmenuGtkmenubar *menubar = DBUSMENU_GTKMENUBAR (object);
+
+ g_free (menubar->priv->dbus_object);
+ menubar->priv->dbus_object = NULL;
+
+ g_free (menubar->priv->dbus_name);
+ menubar->priv->dbus_name = NULL;
+
+ G_OBJECT_CLASS (dbusmenu_gtkmenubar_parent_class)->finalize (object);
+}
+
+static void
+dbusmenu_gtkmenubar_set_property (GObject *obj, guint id, const GValue *value, GParamSpec *pspec)
+{
+ DbusmenuGtkmenubar *menubar = DBUSMENU_GTKMENUBAR (obj);
+
+ switch (id) {
+ case PROP_DBUSNAME:
+ menubar->priv->dbus_name = g_value_dup_string (value);
+
+ if (menubar->priv->dbus_name != NULL && menubar->priv->dbus_object != NULL) {
+ build_client (menubar);
+ }
+
+ break;
+
+ case PROP_DBUSOBJECT:
+ menubar->priv->dbus_object = g_value_dup_string (value);
+
+ if (menubar->priv->dbus_name != NULL && menubar->priv->dbus_object != NULL) {
+ build_client (menubar);
+ }
+
+ break;
+
+ default:
+ g_warning ("Unknown property %d.", id);
+ return;
+ }
+}
+
+static void
+dbusmenu_gtkmenubar_get_property (GObject *obj, guint id, GValue *value, GParamSpec *pspec)
+{
+ DbusmenuGtkmenubar *menubar = DBUSMENU_GTKMENUBAR (obj);
+
+ switch (id) {
+ case PROP_DBUSNAME:
+ g_value_set_string (value, menubar->priv->dbus_name);
+ break;
+
+ case PROP_DBUSOBJECT:
+ g_value_set_string (value, menubar->priv->dbus_object);
+ break;
+
+ default:
+ g_warning("Unknown property %d.", id);
+ return;
+ }
+}
+
+static void
+root_child_added (DbusmenuMenuitem *root,
+ DbusmenuMenuitem *child,
+ guint position,
+ DbusmenuGtkmenubar *menubar)
+{
+ GtkMenuItem *mi;
+
+ g_signal_connect (G_OBJECT (child),
+ DBUSMENU_MENUITEM_SIGNAL_REALIZED,
+ G_CALLBACK (child_realized), menubar);
+
+ mi = dbusmenu_gtkclient_menuitem_get (menubar->priv->client, child);
+
+ if (mi != NULL) {
+ gtk_menu_insert (GTK_MENU_BAR (menubar),
+ GTK_WIDGET (mi),
+ position);
+ }
+}
+
+static void
+root_child_moved (DbusmenuMenuitem *root,
+ DbusmenuMenuitem *child,
+ guint newposition,
+ guint oldposition,
+ DbusmenuGtkmenubar *menubar)
+{
+ gtk_menu_reorder_child (GTK_MENU (menubar),
+ GTK_WIDGET (dbusmenu_gtkclient_menuitem_get (menubar->priv->client, child)), newposition);
+}
+
+static void
+root_child_delete (DbusmenuMenuitem *root,
+ DbusmenuMenuitem *child,
+ DbusmenuGtkmenubar *menubar)
+{
+ GtkWidget *item = GTK_WIDGET (dbusmenu_gtkclient_menuitem_get (menubar->priv->client, child));
+
+ if (item != NULL) {
+ gtk_container_remove (GTK_CONTAINER (menubar), item);
+ }
+
+ if (g_list_length (dbusmenu_menuitem_get_children (root)) == 0) {
+ gtk_widget_hide (GTK_WIDGET (menubar));
+ }
+}
+
+static void
+child_realized (DbusmenuMenuitem *child,
+ gpointer userdata)
+{
+ g_return_if_fail (DBUSMENU_IS_GTKMENUBAR (userdata));
+
+ DbusmenuGtkmenubar *menubar = DBUSMENU_GTKMENUBAR (userdata);
+
+ GtkWidget *child_widget = GTK_WIDGET (dbusmenu_gtkclient_menuitem_get (menubar->priv->client, child));
+
+ if (child_widget != NULL) {
+ gtk_menu_shell_insert (GTK_MENU_SHELL (menubar),
+ child_widget,
+ dbusmenu_menuitem_get_position (child, dbusmenu_client_get_root (DBUSMENU_CLIENT (menubar->priv->client))));
+ } else {
+ g_warning ("Child is realized, but doesn't have a GTK Widget!");
+ }
+}
+
+static void
+root_changed (DbusmenuGtkClient *client, DbusmenuMenuitem *newroot, DbusmenuGtkmenubar *menu) {
+ GList *child = NULL;
+ guint count = 0;
+
+ if (newroot == NULL) {
+ gtk_widget_hide (GTK_WIDGET (menu));
+
+ return;
+ }
+
+ 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);
+
+ 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))); */
+ g_signal_connect (G_OBJECT (child->data),
+ DBUSMENU_MENUITEM_SIGNAL_REALIZED,
+ G_CALLBACK (child_realized),
+ menu);
+ count++;
+ }
+
+ if (count > 0) {
+ gtk_widget_show (GTK_WIDGET (menu));
+ } else {
+ gtk_widget_hide (GTK_WIDGET (menu));
+ }
+}
+
+static void
+build_client (DbusmenuGtkmenubar *self)
+{
+ if (self->priv->client == NULL) {
+ self->priv->client = dbusmenu_gtkclient_new (self->priv->dbus_name,
+ self->priv->dbus_object);
+
+ g_signal_connect (G_OBJECT (self->priv->client),
+ DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED,
+ G_CALLBACK (root_changed),
+ self);
+ }
+}
+
+/* Public API */
+
+/**
+ dbusmenu_gtkmenubar_new:
+ @dbus_name: Name of the #DbusmenuServer on DBus
+ @dbus_name: Name of the object on the #DbusmenuServer
+
+ Creates a new #DbusmenuGtkmenubar object and creates a #DbusmenuClient
+ that connects across DBus to a #DbusmenuServer.
+
+ Return value: A new #DbusmenuGtkmenubar sync'd with a server
+*/
+DbusmenuGtkmenubar *
+dbusmenu_gtkmenubar_new (gchar *dbus_name, gchar *dbus_object)
+{
+ return g_object_new (DBUSMENU_GTKMENUBAR_TYPE,
+ DBUSMENU_CLIENT_PROP_DBUS_OBJECT, dbus_object,
+ DBUSMENU_CLIENT_PROP_DBUS_NAME, dbus_name,
+ NULL);
+}
+
+/**
+ dbusmenu_gtkmenubar_get_client:
+ @menu: The #DbusmenuGtkmenubar 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_gtkmenubar_get_client (DbusmenuGtkmenubar *menubar)
+{
+ g_return_val_if_fail (DBUSMENU_IS_GTKMENUBAR (menubar), NULL);
+
+ return menubar->priv->client;
+}
=== added file 'libdbusmenu-gtk/menubar.h'
--- libdbusmenu-gtk/menubar.h 1970-01-01 00:00:00 +0000
+++ libdbusmenu-gtk/menubar.h 2009-10-23 03:40:22 +0000
@@ -0,0 +1,96 @@
+/*
+A library to take the object model made consistent by libdbusmenu-glib
+and visualize it in GTK.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Cody Russell <crussell@xxxxxxxxxxxxx>
+ Ted Gould <ted@xxxxxxxxxxxxx>
+
+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_GTKMENUBAR_H__
+#define __DBUSMENU_GTKMENUBAR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include "client.h"
+
+G_BEGIN_DECLS
+
+typedef struct _DbusmenuGtkmenubar DbusmenuGtkmenubar;
+typedef struct _DbusmenuGtkmenubarClass DbusmenuGtkmenubarClass;
+typedef struct _DbusmenuGtkmenubarPrivate DbusmenuGtkmenubarPrivate;
+
+#define DBUSMENU_GTKMENUBAR_TYPE (dbusmenu_gtkmenubar_get_type ())
+#define DBUSMENU_GTKMENUBAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DBUSMENU_GTKMENUBAR_TYPE, DbusmenuGtkmenubar))
+#define DBUSMENU_GTKMENUBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DBUSMENU_GTKMENUBAR_TYPE, DbusmenuGtkmenubarClass))
+#define DBUSMENU_IS_GTKMENUBAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DBUSMENU_GTKMENUBAR_TYPE))
+#define DBUSMENU_IS_GTKMENUBAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DBUSMENU_GTKMENUBAR_TYPE))
+#define DBUSMENU_GTKMENUBAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_GTKMENUBAR_TYPE, DbusmenuGtkmenubarClass))
+
+struct _DbusmenuGtkmenubarClass {
+ GtkMenuBarClass parent_class;
+
+ /* Reserved */
+ void (*reserved1) (void);
+ void (*reserved2) (void);
+ void (*reserved3) (void);
+ void (*reserved4) (void);
+};
+
+struct _DbusmenuGtkmenubar {
+ GtkMenuBar parent;
+ DbusmenuGtkmenubarPrivate *priv;
+};
+
+GType dbusmenu_gtkmenubar_get_type (void) G_GNUC_CONST;
+DbusmenuGtkmenubar *dbusmenu_gtkmenubar_new (gchar *dbus_name, gchar *dbus_object);
+DbusmenuGtkClient *dbusmenu_gtkmenubar_get_client (DbusmenuGtkmenubar *menu);
+
+/**
+ SECTION:gtkmenubar
+ @short_description: A GTK Menubar Object that syncronizes over DBus
+ @stability: Unstable
+ @include: libdbusmenu-gtk/menubar.h
+
+ In general, this is just a #GtkMenuBar, 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_gtkmenubar_new(). They are then
+ stored on two properties #DbusmenuGtkmenubar:dbus-name and #DbusmenuGtkmenubar:dbus-object.
+
+ After creation the #DbusmenuGtkmenubar 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