diff options
-rw-r--r-- | libdbusmenu-glib/menuitem.c | 2 | ||||
-rw-r--r-- | libdbusmenu-glib/server.c | 27 | ||||
-rw-r--r-- | libdbusmenu-gtk/Makefile.am | 5 | ||||
-rw-r--r-- | libdbusmenu-gtk/client.c | 35 | ||||
-rw-r--r-- | libdbusmenu-gtk/parser.c | 67 | ||||
-rw-r--r-- | tests/Makefile.am | 33 |
6 files changed, 149 insertions, 20 deletions
diff --git a/libdbusmenu-glib/menuitem.c b/libdbusmenu-glib/menuitem.c index 30ae277..18db4ef 100644 --- a/libdbusmenu-glib/menuitem.c +++ b/libdbusmenu-glib/menuitem.c @@ -1222,7 +1222,7 @@ dbusmenu_menuitem_property_set_variant (DbusmenuMenuitem * mi, const gchar * pro but we're actually replacing it no matter. This is so that the variant passed in sticks around which the caller may expect. They shouldn't, but it's low cost to remove bugs. */ - if (!inhash || !g_variant_equal(hash_variant, value)) { + if (!inhash || (hash_variant != NULL && !g_variant_equal(hash_variant, value))) { replaced = TRUE; } diff --git a/libdbusmenu-glib/server.c b/libdbusmenu-glib/server.c index 4890d37..4700d52 100644 --- a/libdbusmenu-glib/server.c +++ b/libdbusmenu-glib/server.c @@ -990,6 +990,7 @@ menuitem_property_idle (gpointer user_data) /* these are going to be standard references in all code paths and must be unrefed */ GVariant * megadata[2]; gboolean gotsomething = FALSE; + gboolean error_nosend = FALSE; if (item_init) { megadata[0] = g_variant_builder_end(&itembuilder); @@ -1002,6 +1003,10 @@ menuitem_property_idle (gpointer user_data) if (error != NULL) { g_warning("Unable to parse '[ ]' as a 'a(ia{sv})': %s", error->message); g_error_free(error); + megadata[0] = NULL; + error_nosend = TRUE; + } else { + g_variant_ref_sink(megadata[0]); } } @@ -1016,10 +1021,14 @@ menuitem_property_idle (gpointer user_data) if (error != NULL) { g_warning("Unable to parse '[ ]' as a 'a(ias)': %s", error->message); g_error_free(error); + megadata[1] = NULL; + error_nosend = TRUE; + } else { + g_variant_ref_sink(megadata[1]); } } - if (gotsomething && priv->dbusobject != NULL && priv->bus != NULL) { + if (gotsomething && !error_nosend && priv->dbusobject != NULL && priv->bus != NULL) { g_dbus_connection_emit_signal(priv->bus, NULL, priv->dbusobject, @@ -1029,8 +1038,13 @@ menuitem_property_idle (gpointer user_data) NULL); } - g_variant_unref(megadata[0]); - g_variant_unref(megadata[1]); + if (megadata[0] != NULL) { + g_variant_unref(megadata[0]); + } + + if (megadata[1] != NULL) { + g_variant_unref(megadata[1]); + } /* Clean everything up */ prop_array_teardown(priv->prop_array); @@ -1595,7 +1609,6 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i DbusmenuMenuitem * mi = dbusmenu_menuitem_find_id(priv->root, id); if (mi == NULL) { - g_dbus_method_invocation_return_error(invocation, error_quark(), INVALID_MENUITEM_ID, @@ -1605,17 +1618,17 @@ bus_event (DbusmenuServer * server, GVariant * params, GDBusMethodInvocation * i g_variant_unref(data); } else { - idle_event_t * event_data = g_new0(idle_event_t, 1); event_data->mi = g_object_ref(mi); - event_data->eventid = etype; + event_data->eventid = etype; /* give away our allocation */ event_data->timestamp = ts; event_data->variant = data; /* give away our reference */ g_timeout_add(0, event_local_handler, event_data); + + g_dbus_method_invocation_return_value(invocation, NULL); } - g_dbus_method_invocation_return_value(invocation, NULL); return; } diff --git a/libdbusmenu-gtk/Makefile.am b/libdbusmenu-gtk/Makefile.am index b1ee91a..fcebd04 100644 --- a/libdbusmenu-gtk/Makefile.am +++ b/libdbusmenu-gtk/Makefile.am @@ -68,7 +68,7 @@ libdbusmenu_gtk_la_CFLAGS = \ -DG_LOG_DOMAIN="\"LIBDBUSMENU-GTK\"" libdbusmenu_gtk_la_LIBADD = \ - ../libdbusmenu-glib/libdbusmenu-glib.la \ + $(top_builddir)/libdbusmenu-glib/libdbusmenu-glib.la \ $(DBUSMENUGTK_LIBS) # We duplicate these here because Automake won't let us use $(VER) on the left hand side. @@ -118,7 +118,8 @@ DbusmenuGtk_0_4_gir_INCLUDES = \ $(GTKGIR) \ Dbusmenu-0.4 DbusmenuGtk_0_4_gir_CFLAGS = $(DBUSMENUGTK_CFLAGS) -I$(top_srcdir) -DbusmenuGtk_0_4_gir_LIBS = libdbusmenu-gtk$(VER).la +DbusmenuGtk_0_4_gir_LIBS = libdbusmenu-gtk$(VER).la \ + $(top_builddir)/libdbusmenu-glib/libdbusmenu-glib.la DbusmenuGtk_0_4_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources)) DbusmenuGtk_0_4_gir_NAMESPACE = DbusmenuGtk$(VER) DbusmenuGtk_0_4_gir_EXPORT_PACKAGES = dbusmenu-gtk$(VER)-0.4 diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c index 9888cbe..830356a 100644 --- a/libdbusmenu-gtk/client.c +++ b/libdbusmenu-gtk/client.c @@ -725,6 +725,30 @@ process_disposition (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * varian return; } +/* Process the accessible description */ +static void +process_a11y_desc (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * variant, DbusmenuGtkClient * gtkclient) +{ + AtkObject * aobj = gtk_widget_get_accessible(GTK_WIDGET(gmi)); + + if (aobj == NULL) { + return; + } + + const gchar * setname = NULL; + + if (variant != NULL) { + setname = g_variant_get_string(variant, NULL); + } + + if (setname == NULL) { + setname = ""; + } + + atk_object_set_name(aobj, setname); + return; +} + /* Whenever we have a property change on a DbusmenuMenuitem we need to be responsive to that. */ static void @@ -747,8 +771,7 @@ menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * variant, Db } else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_DISPOSITION)) { process_disposition(mi, gmi, variant, gtkclient); } else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC)) { - atk_object_set_name(gtk_widget_get_accessible(GTK_WIDGET(gmi)), variant == NULL ? NULL : - g_variant_get_string(variant, NULL)); + process_a11y_desc(mi, gmi, variant, gtkclient); } return; @@ -894,6 +917,7 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem * process_toggle_state(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE)); process_submenu(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_CHILD_DISPLAY), client); process_disposition(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_DISPOSITION), client); + process_a11y_desc(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC), client); refresh_shortcut(client, item); const gchar * a11y_desc = dbusmenu_menuitem_property_get(item, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC); @@ -1128,12 +1152,7 @@ image_property_handle (DbusmenuMenuitem * item, const gchar * property, GVariant return; } - const gchar * value = NULL; - if (variant != NULL) { - value = g_variant_get_string(variant, NULL); - } - - if (value == NULL || value[0] == '\0') { + if (variant == NULL) { /* This means that we're unsetting a value. */ /* Try to use the other one */ if (g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON_NAME)) { diff --git a/libdbusmenu-gtk/parser.c b/libdbusmenu-gtk/parser.c index 0ecfa1e..ab3b77a 100644 --- a/libdbusmenu-gtk/parser.c +++ b/libdbusmenu-gtk/parser.c @@ -26,6 +26,8 @@ License version 3 and version 2.1 along with this program. If not, see <http://www.gnu.org/licenses/> */ +#include <atk/atk.h> + #include "parser.h" #include "menuitem.h" #include "client.h" @@ -41,6 +43,7 @@ typedef struct _ParserData GtkWidget *widget; GtkWidget *shell; GtkWidget *image; + AtkObject *accessible; } ParserData; typedef struct _RecurseContext @@ -67,6 +70,9 @@ static void image_notify_cb (GtkWidget * widget, static void action_notify_cb (GtkAction * action, GParamSpec * pspec, gpointer data); +static void a11y_name_notify_cb (AtkObject * accessible, + GParamSpec * pspec, + gpointer data); static void item_inserted_cb (GtkContainer * menu, GtkWidget * widget, #ifdef HAVE_GTK3 @@ -200,6 +206,12 @@ parse_data_free (gpointer data) g_object_remove_weak_pointer(G_OBJECT(pdata->image), (gpointer*)&pdata->image); } + if (pdata != NULL && pdata->accessible != NULL) { + g_signal_handlers_disconnect_matched(pdata->accessible, (GSignalMatchType)G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, G_CALLBACK(a11y_name_notify_cb), NULL); + g_object_remove_weak_pointer(G_OBJECT(pdata->accessible), (gpointer*)&pdata->accessible); + } + g_free(pdata); return; @@ -415,8 +427,11 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse) /* Oops, let's tell our parents about us */ if (peek == NULL) { - if (dbusmenu_menuitem_get_parent(thisitem) != NULL) { - dbusmenu_menuitem_unparent(thisitem); + g_object_ref(thisitem); + + DbusmenuMenuitem * parent = dbusmenu_menuitem_get_parent(thisitem); + if (parent != NULL) { + dbusmenu_menuitem_child_delete(parent, thisitem); } gint pos = get_child_position (widget); @@ -427,6 +442,8 @@ parse_menu_structure_helper (GtkWidget * widget, RecurseContext * recurse) else dbusmenu_menuitem_child_append (recurse->parent, thisitem); + + g_object_unref(thisitem); } } @@ -582,6 +599,27 @@ construct_dbusmenu_for_widget (GtkWidget * widget) mi); g_object_add_weak_pointer(G_OBJECT (label), (gpointer*)&pdata->label); + AtkObject *accessible = gtk_widget_get_accessible (widget); + if (accessible) + { + // Getting the accessible name of the Atk object retrieves the text + // of the menu item label, unless the application has set an alternate + // accessible name. + const gchar * label_text = gtk_label_get_text (GTK_LABEL (label)); + const gchar * a11y_name = atk_object_get_name (accessible); + if (g_strcmp0 (a11y_name, label_text)) + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC, a11y_name); + + // An application may set an alternate accessible name in the future, + // so we had better watch out for it. + pdata->accessible = accessible; + g_signal_connect (G_OBJECT (accessible), + "notify::accessible-name", + G_CALLBACK (a11y_name_notify_cb), + mi); + g_object_add_weak_pointer(G_OBJECT (accessible), (gpointer*)&pdata->accessible); + } + if (GTK_IS_ACTIVATABLE (widget)) { GtkActivatable *activatable = GTK_ACTIVATABLE (widget); @@ -948,6 +986,31 @@ action_notify_cb (GtkAction *action, } static void +a11y_name_notify_cb (AtkObject *accessible, + GParamSpec *pspec, + gpointer data) +{ + DbusmenuMenuitem *item = (DbusmenuMenuitem *)data; + GtkWidget *widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible)); + GtkWidget *label = find_menu_label (widget); + const gchar *label_text = gtk_label_get_text (GTK_LABEL (label)); + const gchar *name = atk_object_get_name (accessible); + + /* If an application sets the accessible name to NULL, then a subsequent + * call to get the accessible name from the Atk object should return the same + * string as the text of the menu item label, in which case, we want to clear + * the accessible description property of the dbusmenu item. + */ + if (pspec->name == g_intern_static_string ("accessible-name")) + { + if (!g_strcmp0 (name, label_text)) + dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC, NULL); + else + dbusmenu_menuitem_property_set (item, DBUSMENU_MENUITEM_PROP_ACCESSIBLE_DESC, name); + } +} + +static void item_activated (DbusmenuMenuitem *item, guint timestamp, gpointer user_data) { GtkWidget *child; diff --git a/tests/Makefile.am b/tests/Makefile.am index 532c14f..db2d469 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -135,6 +135,8 @@ glib_server_nomenu_LDADD = \ test-glib-layout: test-glib-layout-client test-glib-layout-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(DBUS_RUNNER) --task ./test-glib-layout-client --task-name Client --task ./test-glib-layout-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -168,6 +170,8 @@ test_glib_layout_client_LDADD = \ test-glib-events: test-glib-events-client test-glib-events-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(DBUS_RUNNER) --task ./test-glib-events-client --task-name Client --task ./test-glib-events-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -199,6 +203,8 @@ test_glib_events_client_LDADD = \ test-json: test-json-client test-json-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task ./test-json-client --task-name Client --parameter $(top_builddir)/tools/dbusmenu-dumper --parameter test-json-01.output.json --ignore-return --task ./test-json-server --task-name Server --parameter $(srcdir)/test-json-01.json --ignore-return >> $@ @echo diff $(srcdir)/test-json-01.json test-json-01.output.json \> /dev/null >> $@ @@ -240,6 +246,11 @@ test_json_client_LDADD = \ test-glib-submenu: test-glib-submenu-client test-glib-submenu-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ +# Removing the check for criticals here as there's one coming from GTK +# in the grabbing code on GTK3. Since we can't add events to the stack +# we can't remove this error from getting thrown :-( +# @echo export G_DEBUG=fatal_criticals >> $@ @echo $(DBUS_RUNNER) --task ./test-glib-submenu-client --task-name Client --task ./test-glib-submenu-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -275,6 +286,8 @@ OBJECT_XML_REPORT = test-glib-objects.xml test-glib-objects-test: test-glib-objects Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(DBUS_RUNNER) --task gtester --task-name test --parameter --verbose --parameter -k --parameter -o --parameter $(OBJECT_XML_REPORT) --parameter ./test-glib-objects >> $@ @chmod +x $@ @@ -297,6 +310,8 @@ DISTCLEANFILES += $(OBJECT_XML_REPORT) test-glib-properties: test-glib-properties-client test-glib-properties-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(DBUS_RUNNER) --task ./test-glib-properties-client --task-name Client --task ./test-glib-properties-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -330,6 +345,8 @@ test_glib_properties_client_LDADD = \ test-glib-proxy: test-glib-proxy-client test-glib-proxy-server test-glib-proxy-proxy Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(DBUS_RUNNER) --task ./test-glib-proxy-client --task-name Client --task ./test-glib-proxy-server --task-name Server --ignore-return \\ >> $@ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.first_proxy --parameter test.proxy.second_proxy --task-name Proxy01 --ignore-return \\ >> $@ @echo --task ./test-glib-proxy-proxy --parameter test.proxy.second_proxy --parameter test.proxy.third_proxy --task-name Proxy02 --ignore-return \\ >> $@ @@ -399,6 +416,8 @@ GTK_OBJECT_XML_REPORT = test-gtk-objects.xml test-gtk-objects-test: test-gtk-objects Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task gtester --task-name test --parameter --verbose --parameter -k --parameter -o --parameter $(GTK_OBJECT_XML_REPORT) --parameter ./test-gtk-objects >> $@ @chmod +x $@ @@ -429,6 +448,8 @@ GTK_PARSER_XML_REPORT = test-gtk-parser.xml test-gtk-parser-test: test-gtk-parser Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo gtester --verbose -k -o $(GTK_PARSER_XML_REPORT) ./test-gtk-parser >> $@ @chmod +x $@ @@ -457,6 +478,8 @@ DISTCLEANFILES += $(GTK_PARSER_XML_REPORT) test-gtk-label: test-gtk-label-client test-gtk-label-server test-gtk-label.json Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task ./test-gtk-label-client --task-name Client --task ./test-gtk-label-server --parameter $(srcdir)/test-gtk-label.json --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -498,6 +521,8 @@ test_gtk_label_client_LDADD = \ test-gtk-shortcut: test-gtk-shortcut-client test-gtk-shortcut-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task ./test-gtk-shortcut-client --task-name Client --task ./test-gtk-shortcut-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -538,6 +563,8 @@ test_gtk_shortcut_client_LDADD = \ test-gtk-shortcut-python: test-gtk-shortcut-server test-gtk-shortcut-client.py Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task $(srcdir)/test-gtk-shortcut-client.py --task-name Client --task ./test-gtk-shortcut-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -551,6 +578,8 @@ CLEANFILES += test-gtk-shortcut-client.pyc test-gtk-reorder: test-gtk-label-client test-gtk-reorder-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task ./test-gtk-label-client --task-name Client --task ./test-gtk-reorder-server --parameter $(srcdir)/test-gtk-label.json --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -576,6 +605,8 @@ test_gtk_reorder_server_LDADD = \ test-gtk-submenu: test-gtk-submenu-client test-gtk-submenu-server Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo $(DBUS_RUNNER) --task ./test-gtk-submenu-client --task-name Client --task ./test-gtk-submenu-server --task-name Server --ignore-return >> $@ @chmod +x $@ @@ -616,6 +647,8 @@ test_gtk_submenu_client_LDADD = \ test-mago: test-gtk-label-client test-gtk-label-server $(srcdir)/dbusmenu-gtk/mago_tests/dbusmenu.xml Makefile.am @echo "#!/bin/bash" > $@ + @echo export UBUNTU_MENUPROXY="" >> $@ + @echo export G_DEBUG=fatal_criticals >> $@ @echo $(XVFB_RUN) >> $@ @echo cd $(srcdir)/dbusmenu-gtk >> $@ @echo /usr/lib/at-spi/at-spi-registryd \& >> $@ |