From 0d32017ffc6813546ba68c484c3902213df9bd84 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Sun, 30 Jan 2011 16:09:58 -0500 Subject: [PATCH] Don't switch to a workspace when dragging it to launch on that workspace With workspace thumbnails, we don't switch workspaces when dragging windows between workspaces or adding new workspaces, so we also shouldn't switch on launch. * Add workspace parameters to shell_doc_system_open(), shell_app_activate, shell_app_open_new_window() * Pass a 'params' object when activating items in the overview with two currently defined parameters: workspace and timestamp. (timestamp is only implemented where it is easy and doesn't require interface changes - using the global current timestamp for the shell is almost always right or at least good enough.) https://bugzilla.gnome.org/show_bug.cgi?id=640996 --- js/misc/docInfo.js | 4 +-- js/ui/appDisplay.js | 29 +++++++++++++-------- js/ui/docDisplay.js | 8 ++++-- js/ui/endSessionDialog.js | 2 +- js/ui/placeDisplay.js | 51 +++++++++++++++++++++++++++---------- js/ui/search.js | 2 +- js/ui/searchDisplay.js | 6 ++--- js/ui/workspace.js | 4 +-- js/ui/workspaceThumbnail.js | 4 +-- src/shell-app.c | 23 ++++++++++++++--- src/shell-app.h | 6 +++-- src/shell-doc-system.c | 16 ++++++++---- src/shell-doc-system.h | 3 ++- 13 files changed, 109 insertions(+), 49 deletions(-) diff --git a/js/misc/docInfo.js b/js/misc/docInfo.js index a9332d91c..8ec375aa9 100644 --- a/js/misc/docInfo.js +++ b/js/misc/docInfo.js @@ -29,8 +29,8 @@ DocInfo.prototype = { return St.TextureCache.get_default().load_recent_thumbnail(size, this.recentInfo); }, - launch : function() { - Shell.DocSystem.get_default().open(this.recentInfo); + launch : function(workspaceIndex) { + Shell.DocSystem.get_default().open(this.recentInfo, workspaceIndex); }, matchTerms: function(terms) { diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index 43720303d..3df634f76 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -223,14 +223,20 @@ BaseAppSearchProvider.prototype = { 'icon': app.create_icon_texture(Search.RESULT_ICON_SIZE)}; }, - activateResult: function(id) { + activateResult: function(id, params) { + params = Params.parse(params, { workspace: null, + timestamp: null }); + let app = this._appSys.get_app(id); - app.activate(); + app.activate(params.workspace ? params.workspace.index() : -1); }, - dragActivateResult: function(id) { + dragActivateResult: function(id, params) { + params = Params.parse(params, { workspace: null, + timestamp: null }); + let app = this._appSys.get_app(id); - app.open_new_window(); + app.open_new_window(params.workspace ? params.workspace.get_index() : -1); } }; @@ -401,7 +407,7 @@ AppWellIcon.prototype = { let launchWorkspace = global.screen.get_workspace_by_index(global.screen.n_workspaces - 1); launchWorkspace.activate(global.get_current_time()); this.emit('launching'); - this.app.open_new_window(); + this.app.open_new_window(-1); Main.overview.hide(); } return false; @@ -486,9 +492,9 @@ AppWellIcon.prototype = { if (modifiers & Clutter.ModifierType.CONTROL_MASK && this.app.state == Shell.AppState.RUNNING) { - this.app.open_new_window(); + this.app.open_new_window(-1); } else { - this.app.activate(); + this.app.activate(-1); } Main.overview.hide(); }, @@ -498,8 +504,11 @@ AppWellIcon.prototype = { return this._menu.menuEventFilter(event); }, - shellWorkspaceLaunch : function() { - this.app.open_new_window(); + shellWorkspaceLaunch : function(params) { + params = Params.parse(params, { workspace: null, + timestamp: null }); + + this.app.open_new_window(params.workspace ? params.workspace.index() : -1); }, getDragActor: function() { @@ -668,7 +677,7 @@ AppIconMenu.prototype = { let metaWindow = child._window; this.emit('activate-window', metaWindow); } else if (child == this._newWindowMenuItem) { - this._source.app.open_new_window(); + this._source.app.open_new_window(-1); this.emit('activate-window', null); } else if (child == this._toggleFavoriteMenuItem) { let favs = AppFavorites.getAppFavorites(); diff --git a/js/ui/docDisplay.js b/js/ui/docDisplay.js index d2afe04f6..2e77f8c77 100644 --- a/js/ui/docDisplay.js +++ b/js/ui/docDisplay.js @@ -4,6 +4,7 @@ const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; const DocInfo = imports.misc.docInfo; +const Params = imports.misc.params; const Search = imports.ui.search; @@ -28,9 +29,12 @@ DocSearchProvider.prototype = { 'icon': docInfo.createIcon(Search.RESULT_ICON_SIZE)}; }, - activateResult: function(id) { + activateResult: function(id, params) { + params = Params.parse(params, { workspace: null, + timestamp: null }); + let docInfo = this._docManager.lookupByUri(id); - docInfo.launch(); + docInfo.launch(params.workspace ? params.workspace.index() : -1); }, getInitialResultSet: function(terms) { diff --git a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js index 6b85bd87f..be64427e0 100644 --- a/js/ui/endSessionDialog.js +++ b/js/ui/endSessionDialog.js @@ -171,7 +171,7 @@ ListItem.prototype = { _onClicked: function() { this.emit('activate'); - this._app.activate(); + this._app.activate(-1); } }; Signals.addSignalMethods(ListItem.prototype); diff --git a/js/ui/placeDisplay.js b/js/ui/placeDisplay.js index b8745b21f..04ce63c62 100644 --- a/js/ui/placeDisplay.js +++ b/js/ui/placeDisplay.js @@ -12,6 +12,7 @@ const _ = Gettext.gettext; const DND = imports.ui.dnd; const Main = imports.ui.main; +const Params = imports.misc.params; const Search = imports.ui.search; const Util = imports.misc.util; @@ -58,6 +59,21 @@ PlaceInfo.prototype = { } }; +// Helper function to translate launch parameters into a GAppLaunchContext +function _makeLaunchContext(params) +{ + params = Params.parse(params, { workspace: null, + timestamp: null }); + + let launchContext = global.create_app_launch_context(); + if (params.workspace != null) + launchContext.set_desktop(params.workspace.index()); + if (params.timestamp != null) + launchContext.set_timestamp(params.timestamp); + + return launchContext; +} + function PlaceDeviceInfo(mount) { this._init(mount); } @@ -77,9 +93,9 @@ PlaceDeviceInfo.prototype = { return St.TextureCache.get_default().load_gicon(null, icon, size); }, - launch: function() { + launch: function(param) { Gio.app_info_launch_default_for_uri(this._mount.get_root().get_uri(), - global.create_app_launch_context()); + _makeLaunchContex(params)); }, isRemovable: function() { @@ -111,7 +127,6 @@ PlaceDeviceInfo.prototype = { } }; - function PlacesManager() { this._init(); } @@ -130,8 +145,8 @@ PlacesManager.prototype = { function(size) { return St.TextureCache.get_default().load_gicon(null, homeIcon, size); }, - function() { - Gio.app_info_launch_default_for_uri(homeUri, global.create_app_launch_context()); + function(params) { + Gio.app_info_launch_default_for_uri(homeUri, _makeLaunchContext(params)); }); let desktopPath = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_DESKTOP); @@ -143,8 +158,8 @@ PlacesManager.prototype = { function(size) { return St.TextureCache.get_default().load_gicon(null, desktopIcon, size); }, - function() { - Gio.app_info_launch_default_for_uri(desktopUri, global.create_app_launch_context()); + function(params) { + Gio.app_info_launch_default_for_uri(desktopUri, _makeLaunchContext(params)); }); this._connect = new PlaceInfo('special:connect', _("Connect to..."), @@ -153,7 +168,11 @@ PlacesManager.prototype = { icon_type: St.IconType.FULLCOLOR, icon_size: size }); }, - function () { + function (params) { + // BUG: nautilus-connect-server doesn't have a desktop file, so we can't + // launch it with the workspace from params. It's probably pretty rare + // and odd to drag this place onto a workspace in any case + Util.spawn(['nautilus-connect-server']); }); @@ -173,8 +192,12 @@ PlacesManager.prototype = { function(size) { return networkApp.create_icon_texture(size); }, - function () { - networkApp.launch(); + function (params) { + params = Params.parse(params, { workspace: null, + timestamp: 0 }); + + networkApp.launch_full(params.timestamp, [], + params.workspace ? params.workspace.index() : -1); }); } @@ -314,8 +337,8 @@ PlacesManager.prototype = { function(size) { return St.TextureCache.get_default().load_gicon(null, icon, size); }, - function() { - Gio.app_info_launch_default_for_uri(bookmark, global.create_app_launch_context()); + function(params) { + Gio.app_info_launch_default_for_uri(bookmark, _makeLaunchContext(params)); }); this._bookmarks.push(item); } @@ -395,9 +418,9 @@ PlaceSearchProvider.prototype = { 'icon': placeInfo.iconFactory(Search.RESULT_ICON_SIZE) }; }, - activateResult: function(id) { + activateResult: function(id, params) { let placeInfo = Main.placesManager.lookupPlaceById(id); - placeInfo.launch(); + placeInfo.launch(params); }, _compareResultMeta: function (idA, idB) { diff --git a/js/ui/search.js b/js/ui/search.js index 24b411ab6..d1fa925c8 100644 --- a/js/ui/search.js +++ b/js/ui/search.js @@ -267,7 +267,7 @@ OpenSearchSystem.prototype = { return lang != null; }, - activateResult: function(id) { + activateResult: function(id, params) { let searchTerms = this._terms.join(' '); let url = this._providers[id].url.replace('{searchTerms}', encodeURIComponent(searchTerms)); diff --git a/js/ui/searchDisplay.js b/js/ui/searchDisplay.js index 44794f6a9..7e9ba7a7d 100644 --- a/js/ui/searchDisplay.js +++ b/js/ui/searchDisplay.js @@ -81,11 +81,11 @@ SearchResult.prototype = { return new Clutter.Clone({ source: this.metaInfo['icon'] }); }, - shellWorkspaceLaunch: function() { + shellWorkspaceLaunch: function(params) { if (this.provider.dragActivateResult) - this.provider.dragActivateResult(this.metaInfo.id); + this.provider.dragActivateResult(this.metaInfo.id, params); else - this.provider.activateResult(this.metaInfo.id); + this.provider.activateResult(this.metaInfo.id, params); } }; diff --git a/js/ui/workspace.js b/js/ui/workspace.js index 0241213c1..3e76d717b 100644 --- a/js/ui/workspace.js +++ b/js/ui/workspace.js @@ -1431,8 +1431,8 @@ Workspace.prototype = { time); return true; } else if (source.shellWorkspaceLaunch) { - this.metaWorkspace.activate(time); - source.shellWorkspaceLaunch(); + source.shellWorkspaceLaunch({ workspace: this.metaWorkspace, + timestamp: time }); return true; } diff --git a/js/ui/workspaceThumbnail.js b/js/ui/workspaceThumbnail.js index 8f8586b9d..e4bd6bbff 100644 --- a/js/ui/workspaceThumbnail.js +++ b/js/ui/workspaceThumbnail.js @@ -283,8 +283,8 @@ WorkspaceThumbnail.prototype = { time); return true; } else if (source.shellWorkspaceLaunch) { - this.metaWorkspace.activate(time); - source.shellWorkspaceLaunch(); + source.shellWorkspaceLaunch({ workspace: this.metaWorkspace, + timestamp: time }); return true; } diff --git a/src/shell-app.c b/src/shell-app.c index 0f733a429..74b72fb33 100644 --- a/src/shell-app.c +++ b/src/shell-app.c @@ -411,6 +411,8 @@ shell_app_activate_window (ShellApp *app, /** * shell_app_activate: * @app: a #ShellApp + * @workspace: launch on this workspace, or -1 for default. Ignored if + * activating an existing window * * Perform an appropriate default action for operating on this application, * dependent on its current state. For example, if the application is not @@ -419,13 +421,19 @@ shell_app_activate_window (ShellApp *app, * recently used transient for that window). */ void -shell_app_activate (ShellApp *app) +shell_app_activate (ShellApp *app, + int workspace) { switch (app->state) { case SHELL_APP_STATE_STOPPED: /* TODO sensibly handle this error */ - shell_app_info_launch (app->info, NULL); + shell_app_info_launch_full (app->info, + 0, + NULL, + workspace, + NULL, + NULL); break; case SHELL_APP_STATE_STARTING: break; @@ -438,11 +446,13 @@ shell_app_activate (ShellApp *app) /** * shell_app_open_new_window: * @app: a #ShellApp + * @workspace: open on this workspace, or -1 for default * * Request that the application create a new window. */ void -shell_app_open_new_window (ShellApp *app) +shell_app_open_new_window (ShellApp *app, + int workspace) { /* Here we just always launch the application again, even if we know * it was already running. For most applications this @@ -452,7 +462,12 @@ shell_app_open_new_window (ShellApp *app) * as say Pidgin. Ideally, we have the application express to us * that it supports an explicit new-window action. */ - shell_app_info_launch (app->info, NULL); + shell_app_info_launch_full (app->info, + 0, + NULL, + workspace, + NULL, + NULL); } /** diff --git a/src/shell-app.h b/src/shell-app.h index ce222374b..78b61f5ad 100644 --- a/src/shell-app.h +++ b/src/shell-app.h @@ -44,9 +44,11 @@ gboolean shell_app_is_transient (ShellApp *app); void shell_app_activate_window (ShellApp *app, MetaWindow *window, guint32 timestamp); -void shell_app_activate (ShellApp *app); +void shell_app_activate (ShellApp *app, + int workspace); -void shell_app_open_new_window (ShellApp *app); +void shell_app_open_new_window (ShellApp *app, + int workspace); ShellAppState shell_app_get_state (ShellApp *app); diff --git a/src/shell-doc-system.c b/src/shell-doc-system.c index 3ee51e6ba..a80e816d0 100644 --- a/src/shell-doc-system.c +++ b/src/shell-doc-system.c @@ -227,17 +227,24 @@ shell_doc_system_on_recent_changed (GtkRecentManager *manager, * shell_doc_system_open: * @system: A #ShellDocSystem * @info: A #GtkRecentInfo + * @workspace: Open on this workspace, or -1 for default * * Launch the default application associated with the mime type of * @info, using its uri. */ void shell_doc_system_open (ShellDocSystem *system, - GtkRecentInfo *info) + GtkRecentInfo *info, + int workspace) { GFile *file; GAppInfo *app_info; gboolean needs_uri; + GAppLaunchContext *context; + + context = shell_global_create_app_launch_context (shell_global_get ()); + if (workspace != -1) + gdk_app_launch_context_set_desktop ((GdkAppLaunchContext *)context, workspace); file = g_file_new_for_uri (gtk_recent_info_get_uri (info)); needs_uri = g_file_get_path (file) == NULL; @@ -248,7 +255,7 @@ shell_doc_system_open (ShellDocSystem *system, { GList *uris; uris = g_list_prepend (NULL, (gpointer)gtk_recent_info_get_uri (info)); - g_app_info_launch_uris (app_info, uris, shell_global_create_app_launch_context (shell_global_get ()), NULL); + g_app_info_launch_uris (app_info, uris, context, NULL); g_list_free (uris); } else @@ -267,7 +274,6 @@ shell_doc_system_open (ShellDocSystem *system, if (gtk_recent_info_get_application_info (info, app_name, &app_exec, &count, &time)) { GRegex *regex; - GAppLaunchContext *context; /* TODO: Change this once better support for creating GAppInfo is added to GtkRecentInfo, as right now @@ -298,13 +304,13 @@ shell_doc_system_open (ShellDocSystem *system, despite passing the app launch context, no startup notification occurs. */ - context = shell_global_create_app_launch_context (shell_global_get ()); g_app_info_launch (app_info, NULL, context, NULL); - g_object_unref (context); } g_free (app_name); } + + g_object_unref (context); } static void diff --git a/src/shell-doc-system.h b/src/shell-doc-system.h index 95ffb6c2f..077bc1a6c 100644 --- a/src/shell-doc-system.h +++ b/src/shell-doc-system.h @@ -41,6 +41,7 @@ void shell_doc_system_queue_existence_check (ShellDocSystem *system, guint n_items); void shell_doc_system_open (ShellDocSystem *system, - GtkRecentInfo *info); + GtkRecentInfo *info, + int workspace); #endif /* __SHELL_DOC_SYSTEM_H__ */