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.
This commit is contained in:
Matthias Clasen 2011-12-15 01:25:35 -05:00
parent ab4a7c5237
commit 5290a9dd08
4 changed files with 37 additions and 2 deletions

View File

@ -244,6 +244,7 @@ const AppMenuButton = new Lang.Class({
this._menuManager = menuManager; this._menuManager = menuManager;
this._targetApp = null; this._targetApp = null;
this._appMenuNotifyId = 0; this._appMenuNotifyId = 0;
this._actionGroupNotifyId = 0;
let bin = new St.Bin({ name: 'appMenu' }); let bin = new St.Bin({ name: 'appMenu' });
this.actor.add_actor(bin); this.actor.add_actor(bin);
@ -522,8 +523,12 @@ const AppMenuButton = new Lang.Class({
if (this._appMenuNotifyId) if (this._appMenuNotifyId)
this._targetApp.disconnect(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._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; this._targetApp = targetApp;
let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE); let icon = targetApp.get_faded_icon(2 * PANEL_ICON_SIZE);

View File

@ -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: * shell_app_activate:
* @app: a #ShellApp * @app: a #ShellApp
@ -1081,7 +1106,7 @@ on_dbus_proxy_gotten (GObject *initable,
g_variant_get_child (menu_property, 0, "&o", &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->remote_menu = G_MENU_MODEL (g_dbus_menu_model_get (g_dbus_proxy_get_connection (state->app_proxy),
state->dbus_name, state->dbus_name,
object_path)); object_path));

View File

@ -83,6 +83,8 @@ int shell_app_compare_by_name (ShellApp *app, ShellApp *other);
int shell_app_compare (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 G_END_DECLS
#endif /* __SHELL_APP_H__ */ #endif /* __SHELL_APP_H__ */

View File

@ -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_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; 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); set_focus_app (self, new_focus_app);
} }