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
This commit is contained in:
Owen W. Taylor 2011-01-30 16:09:58 -05:00
parent 1b8bfda3b4
commit 0d32017ffc
13 changed files with 109 additions and 49 deletions

View File

@ -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) {

View File

@ -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();

View File

@ -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) {

View File

@ -171,7 +171,7 @@ ListItem.prototype = {
_onClicked: function() {
this.emit('activate');
this._app.activate();
this._app.activate(-1);
}
};
Signals.addSignalMethods(ListItem.prototype);

View File

@ -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) {

View File

@ -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));

View File

@ -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);
}
};

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
/**

View File

@ -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);

View File

@ -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

View File

@ -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__ */