X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgmenuexporter.c;h=89cc309173a0da9f0f8c53e3d681807aa4165182;hb=4482977238ae80f64c2fe318d1500f4662c73980;hp=791ce6e5812b936a1b8cd6a09c453a412254d4dd;hpb=4f2c2077457bcd59ff09b2829b9f25b45e37a515;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gmenuexporter.c b/gio/gmenuexporter.c index 791ce6e..89cc309 100644 --- a/gio/gmenuexporter.c +++ b/gio/gmenuexporter.c @@ -12,13 +12,13 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. + * License along with this library; if not, see . * * Author: Ryan Lortie */ +#include "config.h" + #include "gmenuexporter.h" #include "gdbusmethodinvocation.h" @@ -30,116 +30,21 @@ * SECTION:gmenuexporter * @title: GMenuModel exporter * @short_description: Export GMenuModels on D-Bus - * @see_also: #GMenuModel, #GMenuProxy + * @include: gio/gio.h + * @see_also: #GMenuModel, #GDBusMenuModel * * These functions support exporting a #GMenuModel on D-Bus. * The D-Bus interface that is used is a private implementation * detail. * * To access an exported #GMenuModel remotely, use - * g_menu_proxy_get() to obtain a #GMenuProxy. + * g_dbus_menu_model_get() to obtain a #GDBusMenuModel. */ /* {{{1 D-Bus Interface description */ -/* The org.gtk.Menus interface - * =========================== - * - * The interface is primarily concerned with three things: - * - * - communicating menus to the client - * - establishing links between menus and other menus - * - notifying clients of changes - * - * As a basic principle, it is recognised that the menu structure - * of an application is often large. It is also recognised that some - * menus are liable to frequently change without the user ever having - * opened the menu. For both of these reasons, the individual menus are - * arranged into subscription groups. Each subscription group is specified - * by an unsigned integer. The assignment of integers need not be consecutive. - * - * Within a subscription group there are multiple menus. Each menu is - * identified with an unsigned integer, unique to its subscription group. - * - * By convention, the primary menu is numbered 0 without subscription group 0. - * - * Actionable menu items (ie: those that produce some effect in the - * application when they are activated) have a related action, specified by - * a string. This string specifies the name of the action, according to the - * org.gtk.Actions interface, at the same object path as the menu. - * - * Methods - * ------- - * - * Start :: (au) → (a(uuaa{sv})) - * - * The Start method is used to indicate that a client is interested in - * tracking and displaying the content of the menus of a particular list - * of subscription groups. - * - * Most typically, the client will request subscription group 0 to start. - * - * The call has two effects. First, it replies with all menus defined - * within the requested subscription groups. The format of the reply is - * an array of tuples, where the items in each tuple are: - * - the subscription group of the menu - * - the number of the menu within that group - * - an array of menu items - * - * Each menu item is a dictionary of attributes (a{sv}). - * - * Secondly, this call has a side effect: it atomically requests that - * the Changed signal start to be emitted for the requested subscription - * group. Each group has a subscription count and only signals changes - * on itself when this count is greater than zero. - * - * If a group is specified multiple times then the result is that the - * contents of that group is only returned once, but the subscription - * count is increased multiple times. - * - * If a client disconnects from the bus while holding subscriptions then - * its subscriptions will be cancelled. This prevents "leaking" subscriptions - * in the case of crashes and is also useful for applications that want - * to exit without manually cleaning up. - * - * End :: (au) - * - * The End method reverses the previous effects of a call to Start. - * - * When clients are no longer interested in the contents of a subscription - * group, they should call the End method. - * - * The parameter lists the subscription groups. A subscription group - * needs to be cancelled the same number of times as it was requested. - * For this reason, it might make sense to specify the same subscription - * group multiple times (if multiple Start calls were made for this group). - * - * Signals - * ------- - * - * Changed :: (a(uuuuaa{sv})) - * - * The changed signal indicates changes to a particular menu. - * - * The changes come as an array of tuples where the items in each tuple are: - * - the subscription group of the menu - * - the number of the menu within that group - * - the position in the menu at which to make the change - * - the number of items to delete from that position - * - a list of new items to insert at that position - * - * Each new menu item is a dictionary of attributes (a{sv}). - * - * Attributes - * ---------- - * - * label (string): the label to display - * action (string): the name of the action - * target (variant): the parameter to pass when activating the action - * :section ((uu)): the menu to use to populate that section, specified - * as a pair of subscription group and menu within that group - * :submenu ((uu)): the menu to use as a submenu, specified - * as a pair of subscription group and menu within that group +/* For documentation of this interface, see + * https://wiki.gnome.org/Projects/GLib/GApplication/DBusAPI */ static GDBusInterfaceInfo * @@ -453,7 +358,15 @@ g_menu_exporter_group_subscribe (GMenuExporterGroup *group, group->prepared = TRUE; menu = g_hash_table_lookup (group->menus, 0); - g_menu_exporter_menu_prepare (menu); + + /* If the group was created by a subscription and does not yet + * exist, it won't have a root menu... + * + * That menu will be prepared if it is ever added (due to + * group->prepared == TRUE). + */ + if (menu) + g_menu_exporter_menu_prepare (menu); } group->subscribed++; @@ -564,6 +477,7 @@ g_menu_exporter_remote_subscribe (GMenuExporterRemote *remote, count = (gsize) g_hash_table_lookup (remote->watches, GINT_TO_POINTER (group_id)); g_hash_table_insert (remote->watches, GINT_TO_POINTER (group_id), GINT_TO_POINTER (count + 1)); + /* Group will be created (as empty/unsubscribed if it does not exist) */ group = g_menu_exporter_lookup_group (remote->exporter, group_id); g_menu_exporter_group_subscribe (group, builder); } @@ -652,7 +566,8 @@ g_menu_exporter_name_vanished (GDBusConnection *connection, { GMenuExporter *exporter = user_data; - g_assert (exporter->connection == connection); + /* connection == NULL when we get called because the connection closed */ + g_assert (exporter->connection == connection || connection == NULL); g_hash_table_remove (exporter->remotes, name); } @@ -770,12 +685,11 @@ g_menu_exporter_create_group (GMenuExporter *exporter) return group; } - -static GMenuExporter *g_menu_exporter_to_free; - static void -g_menu_exporter_actually_free (GMenuExporter *exporter) +g_menu_exporter_free (gpointer user_data) { + GMenuExporter *exporter = user_data; + g_menu_exporter_menu_free (exporter->root); g_hash_table_unref (exporter->remotes); g_hash_table_unref (exporter->groups); @@ -786,20 +700,6 @@ g_menu_exporter_actually_free (GMenuExporter *exporter) } static void -g_menu_exporter_free (gpointer user_data) -{ - /* XXX: hack - * - * GDBusConnection calls the destroy notify while holding its own lock - * which means that we get a deadlock on re-entering it. - * - * Work around this for now... - */ - g_assert (g_menu_exporter_to_free == NULL); - g_menu_exporter_to_free = user_data; -} - -static void g_menu_exporter_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, @@ -843,7 +743,7 @@ g_menu_exporter_method_call (GDBusConnection *connection, * The implemented D-Bus API should be considered private. * It is subject to change in the future. * - * An object path can only have one action group exported on it. If this + * An object path can only have one menu model exported on it. If this * constraint is violated, the export will fail and 0 will be * returned (with @error set accordingly). * @@ -852,6 +752,8 @@ g_menu_exporter_method_call (GDBusConnection *connection, * this function. * * Returns: the ID of the export (never zero), or 0 in case of failure + * + * Since: 2.32 */ guint g_dbus_connection_export_menu_model (GDBusConnection *connection, @@ -898,17 +800,12 @@ g_dbus_connection_export_menu_model (GDBusConnection *connection, * same ID more than once. * * Since: 2.32 - **/ + */ void g_dbus_connection_unexport_menu_model (GDBusConnection *connection, guint export_id) { - if (!g_dbus_connection_unregister_object (connection, export_id)) - return; - - g_assert (g_menu_exporter_to_free != NULL); - g_menu_exporter_actually_free (g_menu_exporter_to_free); - g_menu_exporter_to_free = NULL; + g_dbus_connection_unregister_object (connection, export_id); } /* {{{1 Epilogue */