From 6c4e9d23f20585fe84c77d3ab6ce0637b380a0e9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 15 Dec 2011 01:25:35 -0500 Subject: [PATCH] Add per-window actions GTK+ also exports window-specific actions, by putting the object path for the exported action group in the _DBUS_OBJECT_PATH X property. We add this action group to the app's muxer with a 'win' prefix, since that is what the exported menu expects. Whenever the focus window changes, we update the window-specific actions of its application, and emit notify::action-group to cause the app menu to be updated. --- js/ui/panel.js | 7 ++++++- src/shell-app.c | 27 ++++++++++++++++++++++++++- src/shell-app.h | 2 ++ src/shell-window-tracker.c | 3 +++ 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/js/ui/panel.js b/js/ui/panel.js index 3f3f74b56..3e583320f 100644 --- a/js/ui/panel.js +++ b/js/ui/panel.js @@ -244,6 +244,7 @@ const AppMenuButton = new Lang.Class({ this._menuManager = menuManager; this._targetApp = null; this._appMenuNotifyId = 0; + this._actionGroupNotifyId = 0; let bin = new St.Bin({ name: 'appMenu' }); this.actor.add_actor(bin); @@ -522,8 +523,12 @@ const AppMenuButton = new Lang.Class({ if (this._appMenuNotifyId) this._targetApp.disconnect(this._appMenuNotifyId); - if (targetApp) + if (this._actionGroupNotifyId) + this._targetApp.disconnect(this._actionGroupNotifyId); + if (targetApp) { this._appMenuNotifyId = targetApp.connect('notify::menu', Lang.bind(this, this._sync)); + this._actionGroupNotifyId = targetApp.connect('notify::action-group', Lang.bind(this, this._sync)); + } this._targetApp = targetApp; let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE); diff --git a/src/shell-app.c b/src/shell-app.c index 7d64e2a01..332d3f6e3 100644 --- a/src/shell-app.c +++ b/src/shell-app.c @@ -557,6 +557,31 @@ shell_app_activate_window (ShellApp *app, } } + +void +shell_app_update_window_actions (ShellApp *app, MetaWindow *window) +{ + const char *object_path; + + object_path = meta_window_get_dbus_object_path (window); + if (object_path != NULL) + { + GActionGroup *actions; + + actions = g_object_get_data (G_OBJECT (window), "actions"); + if (actions == NULL) + { + actions = G_ACTION_GROUP (g_dbus_action_group_get (g_dbus_proxy_get_connection (app->running_state->app_proxy), + meta_window_get_dbus_unique_name (window), + object_path)); + g_object_set_data_full (G_OBJECT (window), "actions", actions, g_object_unref); + } + + g_action_muxer_insert (app->running_state->muxer, "win", actions); + g_object_notify (G_OBJECT (app), "action-group"); + } +} + /** * shell_app_activate: * @app: a #ShellApp @@ -1081,7 +1106,7 @@ on_dbus_proxy_gotten (GObject *initable, 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->remote_menu = G_MENU_MODEL (g_dbus_menu_model_get (g_dbus_proxy_get_connection (state->app_proxy), state->dbus_name, object_path)); diff --git a/src/shell-app.h b/src/shell-app.h index 4aaf97513..4fa6686c8 100644 --- a/src/shell-app.h +++ b/src/shell-app.h @@ -83,6 +83,8 @@ int shell_app_compare_by_name (ShellApp *app, ShellApp *other); int shell_app_compare (ShellApp *app, ShellApp *other); +void shell_app_update_window_actions (ShellApp *app, MetaWindow *window); + G_END_DECLS #endif /* __SHELL_APP_H__ */ diff --git a/src/shell-window-tracker.c b/src/shell-window-tracker.c index adb7fb788..ecd3219b9 100644 --- a/src/shell-window-tracker.c +++ b/src/shell-window-tracker.c @@ -413,6 +413,9 @@ update_focus_app (ShellWindowTracker *self) new_focus_win = meta_display_get_focus_window (shell_global_get_display (shell_global_get ())); new_focus_app = new_focus_win ? shell_window_tracker_get_window_app (self, new_focus_win) : NULL; + if (new_focus_app) + shell_app_update_window_actions (new_focus_app, new_focus_win); + set_focus_app (self, new_focus_app); }