[gnome-shell] Application Menu: update for latest GMenu changes



commit 5ad8080cb90dd3cfd247a85d5d68d29a1cf9c6ee
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Thu Dec 8 21:53:03 2011 +0100

    Application Menu: update for latest GMenu changes
    
    GMenuProxy has been replaced by GDBusMenuModel, and the object path
    has been moved (now needs to be retrieved from the AppMenu GApplication
    property).
    Update the test to prefix each action with "app." as documented,
    and use a GtkApplicationWindow instead of a plain GtkWindow.

 src/shell-app.c          |  104 +++++++++++++++++++++++++++++++++++++---------
 src/test-gapplication.js |   25 ++++++-----
 2 files changed, 97 insertions(+), 32 deletions(-)
---
diff --git a/src/shell-app.c b/src/shell-app.c
index f4abc5f..42d1165 100644
--- a/src/shell-app.c
+++ b/src/shell-app.c
@@ -39,10 +39,11 @@ typedef struct {
   gboolean window_sort_stale : 1;
 
   /* See GApplication documentation */
-  guint             name_watcher_id;
+  gint              name_watcher_id;
   gchar            *dbus_name;
+  GDBusProxy       *app_proxy;
   GDBusActionGroup *remote_actions;
-  GMenuProxy       *remote_menu;
+  GMenuModel       *remote_menu;
   GCancellable     *dbus_cancellable;
 } ShellAppRunningState;
 
@@ -1029,7 +1030,7 @@ on_action_group_acquired (GObject      *object,
   ShellApp *self = SHELL_APP (user_data);
   ShellAppRunningState *state = self->running_state;
   GError *error = NULL;
-  char *object_path;
+  GVariant *menu_property;
 
   state->remote_actions = g_dbus_action_group_new_finish (result,
                                                           &error);
@@ -1044,6 +1045,7 @@ on_action_group_acquired (GObject      *object,
 
       g_clear_error (&error);
       g_clear_object (&state->dbus_cancellable);
+      g_clear_object (&state->app_proxy);
 
       if (state->name_watcher_id)
         {
@@ -1058,19 +1060,73 @@ on_action_group_acquired (GObject      *object,
       return;
     }
 
-  object_path = g_strconcat ("/", state->dbus_name, NULL);
-  g_strdelimit (object_path, ".", '/');
+  g_object_notify (G_OBJECT (self), "action-group");
 
-  state->remote_menu = g_menu_proxy_get (g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL),
-                                         state->dbus_name,
-                                         object_path);
+  /* third step: the application menu */
 
-  g_object_notify (G_OBJECT (self), "dbus-id");
-  g_object_notify (G_OBJECT (self), "action-group");
-  g_object_notify (G_OBJECT (self), "menu");
+  menu_property = g_dbus_proxy_get_cached_property (state->app_proxy, "AppMenu");
+
+  if (menu_property && g_variant_n_children (menu_property) > 0)
+    {
+      const gchar *object_path;
+
+      g_variant_get_child (menu_property, 0, "&o", &object_path);
+
+      state->remote_menu = G_MENU_MODEL (g_dbus_menu_model_get (g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL),
+                                                                state->dbus_name,
+                                                                object_path));
+
+      g_object_notify (G_OBJECT (self), "menu");
+    }
 
   g_object_unref (self);
-  g_free (object_path);
+}
+
+static void
+on_dbus_proxy_gotten (GObject      *initable,
+                      GAsyncResult *result,
+                      gpointer      user_data)
+{
+  ShellApp *self = SHELL_APP (user_data);
+  ShellAppRunningState *state = self->running_state;
+  GError *error = NULL;
+
+  state->app_proxy = g_dbus_proxy_new_finish (result,
+                                              &error);
+
+  if (error)
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
+          !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD))
+        {
+          g_warning ("Unexpected error while creating application proxy: %s", error->message);
+        }
+
+      g_clear_error (&error);
+      g_clear_object (&state->dbus_cancellable);
+
+      if (state->name_watcher_id)
+        {
+          g_bus_unwatch_name (state->name_watcher_id);
+          state->name_watcher_id = 0;
+        }
+
+      g_free (state->dbus_name);
+      state->dbus_name = NULL;
+
+      g_object_unref (self);
+      return;
+    }
+
+  /* on to the second step, the primary action group */
+
+  g_dbus_action_group_new (g_dbus_proxy_get_connection (state->app_proxy),
+                           g_dbus_proxy_get_name (state->app_proxy),
+                           g_dbus_proxy_get_object_path (state->app_proxy),
+                           G_DBUS_ACTION_GROUP_FLAGS_NONE,
+                           state->dbus_cancellable,
+                           on_action_group_acquired,
+                           self);
 }
 
 static void
@@ -1091,13 +1147,19 @@ on_dbus_name_appeared (GDBusConnection *bus,
   if (!state->dbus_cancellable)
     state->dbus_cancellable = g_cancellable_new ();
 
-  g_dbus_action_group_new (bus,
-                           name,
-                           object_path,
-                           G_DBUS_ACTION_GROUP_FLAGS_NONE,
-                           state->dbus_cancellable,
-                           on_action_group_acquired,
-                           g_object_ref (self));
+  /* first step: the application proxy */
+
+  g_dbus_proxy_new (bus,
+                    G_DBUS_PROXY_FLAGS_NONE,
+                    NULL, /* interface info */
+                    name_owner,
+                    object_path,
+                    "org.gtk.Application",
+                    state->dbus_cancellable,
+                    on_dbus_proxy_gotten,
+                    g_object_ref (self));
+
+  g_object_notify (G_OBJECT (self), "dbus-id");
 
   g_free (object_path);
 }
@@ -1118,6 +1180,7 @@ on_dbus_name_disappeared (GDBusConnection *bus,
       g_clear_object (&state->dbus_cancellable);
     }
 
+  g_clear_object (&state->app_proxy);
   g_clear_object (&state->remote_actions);
   g_clear_object (&state->remote_menu);
 
@@ -1362,6 +1425,7 @@ unref_running_state (ShellAppRunningState *state)
       g_object_unref (state->dbus_cancellable);
     }
 
+  g_clear_object (&state->app_proxy);
   g_clear_object (&state->remote_actions);
   g_clear_object (&state->remote_menu);
   g_free (state->dbus_name);
@@ -1650,7 +1714,7 @@ shell_app_class_init(ShellAppClass *klass)
                                    g_param_spec_object ("menu",
                                                         "Application Menu",
                                                         "The primary menu exported by the remote application",
-                                                        G_TYPE_MENU_PROXY,
+                                                        G_TYPE_MENU_MODEL,
                                                         G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
 }
diff --git a/src/test-gapplication.js b/src/test-gapplication.js
index 7d10103..dfae2ab 100755
--- a/src/test-gapplication.js
+++ b/src/test-gapplication.js
@@ -19,7 +19,7 @@ function do_action_toggle(action) {
 }
 
 function do_action_state_change(action) {
-    print ("Action '" + action.name + "' has now state '" + action.state.deep_unpack() + "'");
+    print ("Action '" + action.name + "' has now state " + action.state.print(true));
 }
 
 function main() {
@@ -57,17 +57,17 @@ function main() {
     app.add_action(action);
 
     let menu = new Gio.Menu();
-    menu.append('An action', 'one');
+    menu.append('An action', 'app.one');
 
     let section = new Gio.Menu();
-    section.append('Another action', 'two');
-    section.append('Same as above', 'two');
+    section.append('Another action', 'app.two');
+    section.append('Same as above', 'app.two');
     menu.append_section(null, section);
 
     // another section, to check separators
     section = new Gio.Menu();
-    section.append('Checkbox', 'toggle');
-    section.append('Disabled', 'disable');
+    section.append('Checkbox', 'app.toggle');
+    section.append('Disabled', 'app.disable');
     menu.append_section(null, section);
 
     // empty sections or submenus should be invisible
@@ -75,25 +75,26 @@ function main() {
     menu.append_submenu('Empty submenu', new Gio.Menu());
 
     let submenu = new Gio.Menu();
-    submenu.append('Open c:\\', 'parameter-string::c:\\');
-    submenu.append('Open /home', 'parameter-string::/home');
+    submenu.append('Open c:\\', 'app.parameter-string::c:\\');
+    submenu.append('Open /home', 'app.parameter-string::/home');
     menu.append_submenu('Recent files', submenu);
 
     let item = Gio.MenuItem.new('Say 42', null);
-    item.set_action_and_target_value('parameter-int', GLib.Variant.new('u', 42));
+    item.set_action_and_target_value('app.parameter-int', GLib.Variant.new('u', 42));
     menu.append_item(item);
 
     let item = Gio.MenuItem.new('Say 43', null);
-    item.set_action_and_target_value('parameter-int', GLib.Variant.new('u', 43));
+    item.set_action_and_target_value('app.parameter-int', GLib.Variant.new('u', 43));
     menu.append_item(item);
 
     app.set_app_menu(menu);
 
     let window = null;
 
+    app.connect_after('startup', function(app) {
+	window = new Gtk.ApplicationWindow({ title: "Test Application", application: app });
+    });
     app.connect('activate', function(app) {
-	if (!window)
-	    window = new Gtk.Window({ title: "Test Application", application: app });
 	window.present();
     });
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]