diff options
Diffstat (limited to 'libdbusmenu-glib')
-rw-r--r-- | libdbusmenu-glib/client.c | 66 | ||||
-rw-r--r-- | libdbusmenu-glib/client.h | 4 | ||||
-rw-r--r-- | libdbusmenu-glib/menuitem-marshal.list | 2 | ||||
-rw-r--r-- | libdbusmenu-glib/menuitem.c | 84 | ||||
-rw-r--r-- | libdbusmenu-glib/menuitem.h | 8 |
5 files changed, 147 insertions, 17 deletions
diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index d5e4334..7319a7f 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -47,6 +47,8 @@ enum { /* Signals */ enum { LAYOUT_UPDATED, + ROOT_CHANGED, + NEW_MENUITEM, LAST_SIGNAL }; @@ -84,7 +86,7 @@ static void id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gcha static void id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client); static void build_proxies (DbusmenuClient * client); static guint parse_node_get_id (xmlNodePtr node); -static DbusmenuMenuitem * parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy); +static DbusmenuMenuitem * parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy); static void parse_layout (DbusmenuClient * client, const gchar * layout); static void update_layout_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data); static void update_layout (DbusmenuClient * client); @@ -120,6 +122,39 @@ dbusmenu_client_class_init (DbusmenuClientClass *klass) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + DbusmenuClient::root-changed: + @arg0: The #DbusmenuClient object + @arg1: The new root #DbusmenuMenuitem + + The layout has changed in a way that can not be + represented by the individual items changing as the + root of this client has changed. + */ + signals[ROOT_CHANGED] = g_signal_new(DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED, + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (DbusmenuClientClass, root_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + /** + DbusmenuClient::new-menuitem: + @arg0: The #DbusmenuClient object + @arg1: The new #DbusmenuMenuitem created + + Signaled when the client creates a new menuitem. This + doesn't mean that it's placed anywhere. The parent that + it's applied to will signal #DbusmenuMenuitem::child-added + when it gets parented. + */ + signals[NEW_MENUITEM] = g_signal_new(DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM, + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (DbusmenuClientClass, new_menuitem), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); g_object_class_install_property (object_class, PROP_DBUSOBJECT, g_param_spec_string(DBUSMENU_CLIENT_PROP_DBUS_OBJECT, "DBus Object we represent", @@ -352,6 +387,7 @@ proxy_destroyed (GObject * gobj_proxy, gpointer userdata) if (priv->root != NULL) { g_object_unref(G_OBJECT(priv->root)); priv->root = NULL; + g_signal_emit(G_OBJECT(userdata), signals[ROOT_CHANGED], 0, NULL, TRUE); g_signal_emit(G_OBJECT(userdata), signals[LAYOUT_UPDATED], 0, TRUE); } @@ -388,7 +424,7 @@ build_proxies (DbusmenuClient * client) DBUS_INTERFACE_PROPERTIES, &error); if (error != NULL) { - g_error("Unable to get property proxy for %s on %s: %s", priv->dbus_name, priv->dbus_object, error->message); + g_warning("Unable to get property proxy for %s on %s: %s", priv->dbus_name, priv->dbus_object, error->message); g_error_free(error); return; } @@ -401,7 +437,7 @@ build_proxies (DbusmenuClient * client) "org.freedesktop.dbusmenu", &error); if (error != NULL) { - g_error("Unable to get dbusmenu proxy for %s on %s: %s", priv->dbus_name, priv->dbus_object, error->message); + g_warning("Unable to get dbusmenu proxy for %s on %s: %s", priv->dbus_name, priv->dbus_object, error->message); g_error_free(error); return; } @@ -424,6 +460,8 @@ build_proxies (DbusmenuClient * client) dbus_g_proxy_add_signal(priv->menuproxy, "IdUpdate", G_TYPE_UINT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(priv->menuproxy, "IdUpdate", G_CALLBACK(id_update), client, NULL); + update_layout(client); + return; } @@ -480,7 +518,7 @@ menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError /* Parse recursively through the XML and make it into objects as need be */ static DbusmenuMenuitem * -parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy) +parse_layout_xml(DbusmenuClient * client, xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy) { guint id = parse_node_get_id(node); /* g_debug("Looking at node with id: %d", id); */ @@ -500,6 +538,10 @@ parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * pa /* Build a new item */ item = dbusmenu_menuitem_new_with_id(id); + if (parent == NULL) { + dbusmenu_menuitem_set_root(item, TRUE); + } + 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); } @@ -524,7 +566,7 @@ parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * pa } } - childmi = parse_layout_xml(children, childmi, item, proxy); + childmi = parse_layout_xml(client, children, childmi, item, proxy); dbusmenu_menuitem_child_add_position(item, childmi, position); } @@ -553,12 +595,18 @@ parse_layout (DbusmenuClient * client, const gchar * layout) xmlNodePtr root = xmlDocGetRootElement(xmldoc); - priv->root = parse_layout_xml(root, priv->root, NULL, priv->menuproxy); + DbusmenuMenuitem * oldroot = priv->root; + priv->root = parse_layout_xml(client, root, priv->root, NULL, priv->menuproxy); + xmlFreeDoc(xmldoc); + if (priv->root == NULL) { g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, layout); } - xmlFreeDoc(xmldoc); + if (priv->root != oldroot) { + g_signal_emit(G_OBJECT(client), signals[ROOT_CHANGED], 0, priv->root, TRUE); + } + return; } @@ -572,9 +620,9 @@ update_layout_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data) GError * error = NULL; GValue value = {0}; + priv->layoutcall = NULL; if (!dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &value, G_TYPE_INVALID)) { g_warning("Getting layout failed on client %s object %s: %s", priv->dbus_name, priv->dbus_object, error->message); - priv->layoutcall = NULL; g_error_free(error); return; } @@ -583,7 +631,6 @@ update_layout_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data) /* g_debug("Got layout string: %s", xml); */ parse_layout(client, xml); - priv->layoutcall = NULL; /* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */ g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE); @@ -638,7 +685,6 @@ dbusmenu_client_new (const gchar * name, const gchar * object) DBUSMENU_CLIENT_PROP_DBUS_NAME, name, DBUSMENU_CLIENT_PROP_DBUS_OBJECT, object, NULL); - update_layout(self); return self; } diff --git a/libdbusmenu-glib/client.h b/libdbusmenu-glib/client.h index d591ebb..35f7122 100644 --- a/libdbusmenu-glib/client.h +++ b/libdbusmenu-glib/client.h @@ -44,6 +44,8 @@ G_BEGIN_DECLS #define DBUSMENU_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DBUSMENU_TYPE_CLIENT, DbusmenuClientClass)) #define DBUSMENU_CLIENT_SIGNAL_LAYOUT_UPDATED "layout-updated" +#define DBUSMENU_CLIENT_SIGNAL_ROOT_CHANGED "root-changed" +#define DBUSMENU_CLIENT_SIGNAL_NEW_MENUITEM "new-menuitem" #define DBUSMENU_CLIENT_PROP_DBUS_NAME "dbus-name" #define DBUSMENU_CLIENT_PROP_DBUS_OBJECT "dbus-object" @@ -66,6 +68,8 @@ struct _DbusmenuClientClass { GObjectClass parent_class; void (*layout_updated)(void); + void (*root_changed) (DbusmenuMenuitem * newroot); + void (*new_menuitem) (DbusmenuMenuitem * newitem); /* Reserved for future use */ void (*reserved1) (void); diff --git a/libdbusmenu-glib/menuitem-marshal.list b/libdbusmenu-glib/menuitem-marshal.list index fc0318f..a32e7e3 100644 --- a/libdbusmenu-glib/menuitem-marshal.list +++ b/libdbusmenu-glib/menuitem-marshal.list @@ -1,3 +1,5 @@ VOID: STRING, STRING +VOID: OBJECT, UINT, UINT +VOID: OBJECT, UINT VOID: OBJECT VOID: VOID diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c index 95391a4..aba1f64 100644 --- a/libdbusmenu-glib/menuitem.c +++ b/libdbusmenu-glib/menuitem.c @@ -39,6 +39,7 @@ License version 3 and version 2.1 along with this program. If not, see @children: A list of #DbusmenuMenuitem objects that are children to this one. @properties: All of the properties on this menu item. + @root: Whether this node is the root node These are the little secrets that we don't want getting out of data that we have. They can still be gotten using @@ -50,6 +51,7 @@ struct _DbusmenuMenuitemPrivate guint id; GList * children; GHashTable * properties; + gboolean root; }; /* Signals */ @@ -58,6 +60,7 @@ enum { ITEM_ACTIVATED, CHILD_ADDED, CHILD_REMOVED, + CHILD_MOVED, LAST_SIGNAL }; @@ -129,6 +132,7 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass) DbusmenuMenuitem::child-added: @arg0: The #DbusmenuMenuitem which is the parent. @arg1: The #DbusmenuMenuitem which is the child. + @arg2: The position that the child is being added in. Signaled when the child menuitem has been added to the parent. @@ -138,8 +142,8 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(DbusmenuMenuitemClass, child_added), NULL, NULL, - _dbusmenu_menuitem_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, G_TYPE_OBJECT); + _dbusmenu_menuitem_marshal_VOID__OBJECT_UINT, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_UINT); /** DbusmenuMenuitem::child-removed: @arg0: The #DbusmenuMenuitem which was the parent. @@ -157,6 +161,23 @@ dbusmenu_menuitem_class_init (DbusmenuMenuitemClass *klass) NULL, NULL, _dbusmenu_menuitem_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT); + /** + DbusmenuMenuitem::child-moved: + @arg0: The #DbusmenuMenuitem which is the parent. + @arg1: The #DbusmenuMenuitem which is the child. + @arg2: The position that the child is being moved to. + @arg3: The position that the child is was in. + + Signaled when the child menuitem has had it's location + in the list change. + */ + signals[CHILD_MOVED] = g_signal_new(DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(DbusmenuMenuitemClass, child_moved), + NULL, NULL, + _dbusmenu_menuitem_marshal_VOID__OBJECT_UINT_UINT, + G_TYPE_NONE, 3, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT); g_object_class_install_property (object_class, PROP_ID, g_param_spec_uint("id", "ID for the menu item", @@ -178,6 +199,8 @@ dbusmenu_menuitem_init (DbusmenuMenuitem *self) priv->children = NULL; priv->properties = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + + priv->root = FALSE; return; } @@ -201,7 +224,7 @@ dbusmenu_menuitem_dispose (GObject *object) static void dbusmenu_menuitem_finalize (GObject *object) { - g_debug("Menuitem dying"); + /* g_debug("Menuitem dying"); */ DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(object); if (priv->properties != NULL) { @@ -398,7 +421,7 @@ dbusmenu_menuitem_child_append (DbusmenuMenuitem * mi, DbusmenuMenuitem * child) DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); priv->children = g_list_append(priv->children, child); - g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, TRUE); + g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, g_list_length(priv->children) - 1, TRUE); return TRUE; } @@ -420,7 +443,7 @@ dbusmenu_menuitem_child_prepend (DbusmenuMenuitem * mi, DbusmenuMenuitem * child DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); priv->children = g_list_prepend(priv->children, child); - g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, TRUE); + g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, 0, TRUE); return TRUE; } @@ -467,7 +490,7 @@ dbusmenu_menuitem_child_add_position (DbusmenuMenuitem * mi, DbusmenuMenuitem * DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); priv->children = g_list_insert(priv->children, child, position); - g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, TRUE); + g_signal_emit(G_OBJECT(mi), signals[CHILD_ADDED], 0, child, position, TRUE); return TRUE; } @@ -490,9 +513,21 @@ dbusmenu_menuitem_child_reorder(DbusmenuMenuitem * mi, DbusmenuMenuitem * child, g_return_val_if_fail(DBUSMENU_IS_MENUITEM(child), FALSE); DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); + gint oldpos = g_list_index(priv->children, child); + + if (oldpos == -1) { + g_warning("Can not reorder child that isn't actually a child."); + return FALSE; + } + if (oldpos == position) { + return TRUE; + } + priv->children = g_list_remove(priv->children, child); priv->children = g_list_insert(priv->children, child, position); + g_signal_emit(G_OBJECT(mi), signals[CHILD_MOVED], 0, child, position, oldpos, TRUE); + return TRUE; } @@ -714,6 +749,43 @@ dbusmenu_menuitem_properties_copy (DbusmenuMenuitem * mi) } /** + dbusmenu_menuitem_set_root: + @mi: #DbusmenuMenuitem to set whether it's root + @root: Whether @mi is a root node or not + + This function sets the internal value of whether this is a + root node or not. + + Return value: None +*/ +void +dbusmenu_menuitem_set_root (DbusmenuMenuitem * mi, gboolean root) +{ + g_return_if_fail(DBUSMENU_IS_MENUITEM(mi)); + DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); + priv->root = root; + return; +} + +/** + dbusmenu_menuitem_get_root: + @mi: #DbusmenuMenuitem to see whether it's root + + This function returns the internal value of whether this is a + root node or not. + + Return value: #TRUE if this is a root node +*/ +gboolean +dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi) +{ + g_return_val_if_fail(DBUSMENU_IS_MENUITEM(mi), FALSE); + DbusmenuMenuitemPrivate * priv = DBUSMENU_MENUITEM_GET_PRIVATE(mi); + return priv->root; +} + + +/** dbusmenu_menuitem_buildxml: @mi: #DbusmenuMenuitem to represent in XML @array: A list of string that will be turned into an XML file diff --git a/libdbusmenu-glib/menuitem.h b/libdbusmenu-glib/menuitem.h index c4fcf73..29865c7 100644 --- a/libdbusmenu-glib/menuitem.h +++ b/libdbusmenu-glib/menuitem.h @@ -46,6 +46,7 @@ G_BEGIN_DECLS #define DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED "item-activated" #define DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED "child-added" #define DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED "child-removed" +#define DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED "child-moved" /** DbusmenuMenuitem: @@ -69,6 +70,7 @@ struct _DbusmenuMenuitem @item_activated: Slot for #DbusmenuMenuitem::item-activated. @child_added: Slot for #DbusmenuMenuitem::child-added. @child_removed: Slot for #DbusmenuMenuitem::child-removed. + @child_moved: Slot for #DbusmenuMenuitem::child-moved. @buildxml: Virtual function that appends the strings required to represent this menu item in the menu XML file. @reserved1: Reserved for future use. @@ -84,8 +86,9 @@ struct _DbusmenuMenuitemClass /* Signals */ void (*property_changed) (gchar * property, gchar * value); void (*item_activated) (void); - void (*child_added) (DbusmenuMenuitem * child); + void (*child_added) (DbusmenuMenuitem * child, guint position); void (*child_removed) (DbusmenuMenuitem * child); + void (*child_moved) (DbusmenuMenuitem * child, guint newpos, guint oldpos); /* Virtual functions */ void (*buildxml) (GPtrArray * stringarray); @@ -120,6 +123,9 @@ gboolean dbusmenu_menuitem_property_exist (DbusmenuMenuitem * mi, const gchar * GList * dbusmenu_menuitem_properties_list (DbusmenuMenuitem * mi) G_GNUC_WARN_UNUSED_RESULT; GHashTable * dbusmenu_menuitem_properties_copy (DbusmenuMenuitem * mi); +void dbusmenu_menuitem_set_root (DbusmenuMenuitem * mi, gboolean root); +gboolean dbusmenu_menuitem_get_root (DbusmenuMenuitem * mi); + void dbusmenu_menuitem_buildxml (DbusmenuMenuitem * mi, GPtrArray * array); void dbusmenu_menuitem_foreach (DbusmenuMenuitem * mi, void (*func) (DbusmenuMenuitem * mi, gpointer data), gpointer data); void dbusmenu_menuitem_activate (DbusmenuMenuitem * mi); |