From d4a35054867dfcb78c4ced2df7a63f34242f21c1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 12 Feb 2010 21:42:58 -0600 Subject: Creating the delayed array, and cleaning it up too. --- libdbusmenu-glib/client.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'libdbusmenu-glib/client.c') diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 2302110..f138b0b 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -75,6 +75,8 @@ struct _DbusmenuClientPrivate DBusGProxy * dbusproxy; GHashTable * type_handlers; + + GArray * delayed_properties; }; typedef struct _newItemPropData newItemPropData; @@ -85,6 +87,21 @@ struct _newItemPropData DbusmenuMenuitem * parent; }; +typedef struct _propertyDelay propertyDelay; +struct _propertyDelay +{ + guint revsion; + GArray * entries; +}; + +typedef struct _propertyDelayValue propertyDelayValue; +struct _propertyDelayValue +{ + gint id; + gchar * name; + GValue value; +}; + #define DBUSMENU_CLIENT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_TYPE_CLIENT, DbusmenuClientPrivate)) @@ -208,6 +225,8 @@ dbusmenu_client_init (DbusmenuClient *self) priv->type_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + priv->delayed_properties = g_array_new(FALSE, TRUE, sizeof(propertyDelay)); + return; } @@ -255,6 +274,23 @@ dbusmenu_client_finalize (GObject *object) g_hash_table_destroy(priv->type_handlers); } + if (priv->delayed_properties) { + gint i; + for (i = 0; i < priv->delayed_properties->len; i++) { + propertyDelay * delay = &g_array_index(priv->delayed_properties, propertyDelay, i); + gint j; + for (j = 0; j < delay->entries->len; j++) { + propertyDelayValue * value = &g_array_index(delay->entries, propertyDelayValue, j); + g_free(value->name); + g_value_unset(&value->value); + } + g_array_free(delay->entries, TRUE); + delay->entries = NULL; + } + g_array_free(priv->delayed_properties, TRUE); + priv->delayed_properties = NULL; + } + G_OBJECT_CLASS (dbusmenu_client_parent_class)->finalize (object); return; } -- cgit v1.2.3 From 618b94db5b21412385a84f65fb7636833a74fc23 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 12 Feb 2010 22:33:06 -0600 Subject: Start to delay ID updates that are gotten when we know we're out of sync. --- libdbusmenu-glib/client.c | 57 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'libdbusmenu-glib/client.c') diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index f138b0b..c53166b 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -90,7 +90,7 @@ struct _newItemPropData typedef struct _propertyDelay propertyDelay; struct _propertyDelay { - guint revsion; + guint revision; GArray * entries; }; @@ -355,6 +355,49 @@ layout_update (DBusGProxy * proxy, gint revision, guint parent, DbusmenuClient * return; } +/* Add an entry to the set of entries that are delayed until the + layout has been updated to this revision */ +static void +delay_prop_update (guint revision, GArray * delayarray, gint id, gchar * prop, GValue * value) +{ + propertyDelay * delay = NULL; + gint i; + + /* First look for something with this revision number. This + array should be really short, probably not more than an entry or + two so there is no reason to optimize this. */ + for (i = 0; i < delayarray->len; i++) { + propertyDelay * localdelay = &g_array_index(delayarray, propertyDelay, i); + if (localdelay->revision == revision) { + delay = localdelay; + break; + } + } + + /* If we don't have any entires for this revision number then we + need to create a new one with it's own array of entires. */ + if (delay == NULL) { + propertyDelay localdelay = {0}; + localdelay.revision = revision; + localdelay.entries = g_array_new(FALSE, TRUE, sizeof(propertyDelayValue)); + + g_array_append_val(delayarray, localdelay); + delay = &g_array_index(delayarray, propertyDelay, delayarray->len - 1); + } + + /* Build the actual entry and tack it on the end of the array + of entries */ + propertyDelayValue delayvalue = {0}; + delayvalue.id = id; + delayvalue.name = g_strdup(prop); + + g_value_init(&delayvalue.value, G_VALUE_TYPE(value)); + g_value_copy(value, &delayvalue.value); + + g_array_append_val(delay->entries, delayvalue); + return; +} + /* Signal from the server that a property has changed on one of our menuitems */ static void @@ -369,7 +412,17 @@ id_prop_update (DBusGProxy * proxy, gint id, gchar * property, GValue * value, D #endif DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); - g_return_if_fail(priv->root != NULL); + + /* If we're not on the right revision, we need to cache the property + changes as it could be that the menuitems don't exist yet. */ + if (priv->my_revision != priv->current_revision) { + delay_prop_update(priv->current_revision, priv->delayed_properties, id, property, value); + return; + } + + if (priv->root != NULL) { + return; + } DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id); g_return_if_fail(menuitem != NULL); -- cgit v1.2.3 From 285ee828ae89c5cc5bbf6e829c84d3980ac2f3c4 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 12 Feb 2010 22:52:37 -0600 Subject: Putting in code to undo the array as the layouts get updated. --- libdbusmenu-glib/client.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'libdbusmenu-glib/client.c') diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index c53166b..191ea03 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -885,16 +885,19 @@ update_layout_cb (DBusGProxy * proxy, guint rev, gchar * xml, GError * error, vo DbusmenuClient * client = DBUSMENU_CLIENT(data); DbusmenuClientPrivate * priv = DBUSMENU_CLIENT_GET_PRIVATE(client); + /* Check to make sure this isn't an issue */ if (error != NULL) { g_warning("Getting layout failed on client %s object %s: %s", priv->dbus_name, priv->dbus_object, error->message); return; } + /* Try to take in the layout that we got */ if (!parse_layout(client, xml)) { g_warning("Unable to parse layout!"); return; } + /* Success, so we need to update our local variables */ priv->my_revision = rev; /* g_debug("Root is now: 0x%X", (unsigned int)priv->root); */ priv->layoutcall = NULL; @@ -903,6 +906,41 @@ update_layout_cb (DBusGProxy * proxy, guint rev, gchar * xml, GError * error, vo #endif g_signal_emit(G_OBJECT(client), signals[LAYOUT_UPDATED], 0, TRUE); + /* Apply the delayed properties that were queued up while + we were waiting on this layout update. */ + if (G_LIKELY(priv->delayed_properties != NULL)) { + gint i; + for (i = 0; i < priv->delayed_properties->len; i++) { + propertyDelay * delay = &g_array_index(priv->delayed_properties, propertyDelay, i); + if (delay->revision > priv->my_revision) { + /* Check to see if this is for future revisions, which + is possible if there is a ton of updates. */ + break; + } + + gint j; + for (j = 0; j < delay->entries->len; j++) { + propertyDelayValue * value = &g_array_index(delay->entries, propertyDelayValue, j); + DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, value->id); + if (mi != NULL) { + dbusmenu_menuitem_property_set_value(mi, value->name, &value->value); + } + g_free(value->name); + g_value_unset(&value->value); + } + g_array_free(delay->entries, TRUE); + + /* We're removing the entry and moving the index down one + to ensure that we adjust for the shift in the array. The + reality is that i is always 0. You understood this loop + until you got here, didn't you :) */ + g_array_remove_index(priv->delayed_properties, i); + i--; + } + } + + /* Check to see if we got another update in the time this + one was issued. */ if (priv->my_revision < priv->current_revision) { update_layout(client); } -- cgit v1.2.3 From f7133702f0bec20aa4bebda08c7dd60431529b0b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 13 Feb 2010 00:03:36 -0600 Subject: Making it so that NULL roots also cause the items to get delayed until we have a root element. --- libdbusmenu-glib/client.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'libdbusmenu-glib/client.c') diff --git a/libdbusmenu-glib/client.c b/libdbusmenu-glib/client.c index 191ea03..edffb07 100644 --- a/libdbusmenu-glib/client.c +++ b/libdbusmenu-glib/client.c @@ -415,15 +415,14 @@ id_prop_update (DBusGProxy * proxy, gint id, gchar * property, GValue * value, D /* If we're not on the right revision, we need to cache the property changes as it could be that the menuitems don't exist yet. */ - if (priv->my_revision != priv->current_revision) { + if (priv->root == NULL || priv->my_revision != priv->current_revision) { + #ifdef MASSIVEDEBUGGING + g_debug("Delaying prop update until rev %d for id %d property %s", priv->current_revision, id, property); + #endif delay_prop_update(priv->current_revision, priv->delayed_properties, id, property, value); return; } - if (priv->root != NULL) { - return; - } - DbusmenuMenuitem * menuitem = dbusmenu_menuitem_find_id(priv->root, id); g_return_if_fail(menuitem != NULL); @@ -923,6 +922,9 @@ update_layout_cb (DBusGProxy * proxy, guint rev, gchar * xml, GError * error, vo propertyDelayValue * value = &g_array_index(delay->entries, propertyDelayValue, j); DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, value->id); if (mi != NULL) { + #ifdef MASSIVEDEBUGGING + g_debug("Applying delayed property id %d property %s", value->id, value->name); + #endif dbusmenu_menuitem_property_set_value(mi, value->name, &value->value); } g_free(value->name); -- cgit v1.2.3