77
78
static void get_property (GObject * obj, guint id, GValue * value, GParamSpec * pspec);
78
79
/* Private Funcs */
79
80
static void layout_update (DBusGProxy * proxy, DbusmenuClient * client);
81
static void id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client);
82
static void id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client);
80
83
static void build_proxies (DbusmenuClient * client);
81
84
static guint parse_node_get_id (xmlNodePtr node);
82
static DbusmenuMenuitem * parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent);
85
static DbusmenuMenuitem * parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy);
83
86
static void parse_layout (DbusmenuClient * client, const gchar * layout);
84
87
static void update_layout_cb (DBusGProxy * proxy, DBusGProxyCall * call, void * data);
85
88
static void update_layout (DbusmenuClient * client);
89
static void menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data);
88
92
G_DEFINE_TYPE (DbusmenuClient, dbusmenu_client, G_TYPE_OBJECT);
245
/* Signal from the server that a property has changed
246
on one of our menuitems */
248
id_prop_update (DBusGProxy * proxy, guint id, gchar * property, gchar * value, DbusmenuClient * client)
250
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
251
g_return_if_fail(priv->root != NULL);
253
DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
254
g_return_if_fail(menuitem != NULL);
256
dbusmenu_menuitem_property_set(menuitem, property, value);
260
/* Oh, lots of updates now. That silly server, they want
261
to change all kinds of stuff! */
263
id_update (DBusGProxy * proxy, guint id, DbusmenuClient * client)
265
DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client);
266
g_return_if_fail(priv->root != NULL);
268
DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id);
269
g_return_if_fail(menuitem != NULL);
271
org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, menuitem);
241
275
/* When we have a name and an object, build the two proxies and get the
242
276
first version of the layout */
281
315
dbus_g_proxy_add_signal(priv->menuproxy, "LayoutUpdate", G_TYPE_INVALID);
282
316
dbus_g_proxy_connect_signal(priv->menuproxy, "LayoutUpdate", G_CALLBACK(layout_update), client, NULL);
318
dbus_g_object_register_marshaller(_dbusmenu_server_marshal_VOID__UINT_STRING_STRING, G_TYPE_NONE, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
319
dbus_g_proxy_add_signal(priv->menuproxy, "IdPropUpdate", G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
320
dbus_g_proxy_connect_signal(priv->menuproxy, "IdPropUpdate", G_CALLBACK(id_prop_update), client, NULL);
322
dbus_g_proxy_add_signal(priv->menuproxy, "IdUpdate", G_TYPE_UINT, G_TYPE_INVALID);
323
dbus_g_proxy_connect_signal(priv->menuproxy, "IdUpdate", G_CALLBACK(id_update), client, NULL);
301
342
if (g_strcmp0((gchar *)attrib->name, "id") == 0) {
302
343
if (attrib->children != NULL) {
303
344
guint id = (guint)g_ascii_strtoull((gchar *)attrib->children->content, NULL, 10);
304
g_debug ("Found ID: %d", id);
345
/* g_debug ("Found ID: %d", id); */
356
/* A small helper that calls _property_set on each hash table
357
entry in the properties hash. */
359
get_properties_helper (gpointer key, gpointer value, gpointer data)
361
dbusmenu_menuitem_property_set((DbusmenuMenuitem *)data, (gchar *)key, (gchar *)value);
365
/* This is the callback for the properties on a menu item. There
366
should be all of them in the Hash, and they we use foreach to
367
copy them into the menuitem.
368
This isn't the most efficient way. We can optimize this by
369
somehow removing the foreach. But that is for later. */
371
menuitem_get_properties_cb (DBusGProxy * proxy, GHashTable * properties, GError * error, gpointer data)
373
g_hash_table_foreach(properties, get_properties_helper, data);
374
g_hash_table_destroy(properties);
315
378
/* Parse recursively through the XML and make it into
316
379
objects as need be */
317
380
static DbusmenuMenuitem *
318
parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent)
381
parse_layout_xml(xmlNodePtr node, DbusmenuMenuitem * item, DbusmenuMenuitem * parent, DBusGProxy * proxy)
320
383
guint id = parse_node_get_id(node);
321
g_debug("Looking at node with id: %d", id);
384
/* g_debug("Looking at node with id: %d", id); */
322
385
if (item == NULL || dbusmenu_menuitem_get_id(item) != id || id == 0) {
323
386
if (item != NULL) {
324
387
if (parent != NULL) {
335
398
/* Build a new item */
336
399
item = dbusmenu_menuitem_new_with_id(id);
400
/* Get the properties queued up for this item */
401
org_freedesktop_dbusmenu_get_properties_async(proxy, id, menuitem_get_properties_cb, item);
339
404
xmlNodePtr children;
341
406
GList * oldchildren = dbusmenu_menuitem_take_children(item);
343
408
for (children = node->children, position = 0; children != NULL; children = children->next, position++) {
344
g_debug("Looking at child: %d", position);
409
/* g_debug("Looking at child: %d", position); */
345
410
guint childid = parse_node_get_id(children);
346
411
DbusmenuMenuitem * childmi = NULL;
358
childmi = parse_layout_xml(children, childmi, item);
423
childmi = parse_layout_xml(children, childmi, item, proxy);
359
424
dbusmenu_menuitem_child_add_position(item, childmi, position);
383
448
xmlNodePtr root = xmlDocGetRootElement(xmldoc);
385
priv->root = parse_layout_xml(root, priv->root, NULL);
450
priv->root = parse_layout_xml(root, priv->root, NULL, priv->menuproxy);
386
451
if (priv->root == NULL) {
387
452
g_warning("Unable to parse layout on client %s object %s: %s", priv->dbus_name, priv->dbus_object, layout);
411
476
const gchar * xml = g_value_get_string(&value);
412
g_debug("Got layout string: %s", xml);
477
/* g_debug("Got layout string: %s", xml); */
413
478
parse_layout(client, xml);
415
480
priv->layoutcall = NULL;
416
g_debug("Root is now: 0x%X", (unsigned int)priv->root);
481
/* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */
417
482
g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE);