autoWorkspaces: fix creation of new workspaces with application launchers

In the workspace-collecting code we add a check to avoid collecting a
workspace if any startup sequence is running there. Since the sequence
can take some time to load, an helper function is also added which keeps
the (empty) workspace around for a very short time, while waiting for the
sequence to start.

https://bugzilla.gnome.org/show_bug.cgi?id=664202
This commit is contained in:
Stefano Facchini 2012-02-17 15:57:27 +01:00
parent b2bc73c3fe
commit 3c6737f738
4 changed files with 43 additions and 6 deletions

View File

@ -171,9 +171,11 @@ function start() {
// and recalculate application associations, so to avoid
// races for now we initialize it here. It's better to
// be predictable anyways.
Shell.WindowTracker.get_default();
let tracker = Shell.WindowTracker.get_default();
Shell.AppUsage.get_default();
tracker.connect('startup-sequence-changed', _queueCheckWorkspaces);
// The stage is always covered so Clutter doesn't need to clear it; however
// the color is used as the default contents for the Mutter root background
// actor so set it anyways.
@ -286,15 +288,23 @@ function _checkWorkspaces() {
for (i = 0; i < _workspaces.length; i++) {
let lastRemoved = _workspaces[i]._lastRemovedWindow;
if (lastRemoved &&
(lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN ||
lastRemoved.get_window_type() == Meta.WindowType.DIALOG ||
lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG))
if ((lastRemoved &&
(lastRemoved.get_window_type() == Meta.WindowType.SPLASHSCREEN ||
lastRemoved.get_window_type() == Meta.WindowType.DIALOG ||
lastRemoved.get_window_type() == Meta.WindowType.MODAL_DIALOG)) ||
_workspaces[i]._keepAliveId)
emptyWorkspaces[i] = false;
else
emptyWorkspaces[i] = true;
}
let sequences = Shell.WindowTracker.get_default().get_startup_sequences();
for (i = 0; i < sequences.length; i++) {
let index = sequences[i].get_workspace();
if (index >= 0 && index <= global.screen.n_workspaces)
emptyWorkspaces[index] = false;
}
let windows = global.get_window_actors();
for (i = 0; i < windows.length; i++) {
let win = windows[i];
@ -342,6 +352,17 @@ function _checkWorkspaces() {
return false;
}
function keepWorkspaceAlive(workspace, duration) {
if (workspace._keepAliveId)
Mainloop.source_remove(workspace._keepAliveId);
workspace._keepAliveId = Mainloop.timeout_add(duration, function() {
workspace._keepAliveId = 0;
_queueCheckWorkspaces();
return false;
});
}
function _windowRemoved(workspace, window) {
workspace._lastRemovedWindow = window;
_queueCheckWorkspaces();

View File

@ -25,6 +25,8 @@ const SLIDE_ANIMATION_TIME = 0.2;
// placeholder exactly.
const WORKSPACE_CUT_SIZE = 10;
const WORKSPACE_KEEP_ALIVE_TIME = 100;
const WindowClone = new Lang.Class({
Name: 'WindowClone',
@ -684,9 +686,16 @@ const ThumbnailsBox = new Lang.Class({
// ... and bam, a workspace, good as new.
source.metaWindow.change_workspace_by_index(newWorkspaceIndex,
true, time);
else if (source.shellWorkspaceLaunch)
else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: newWorkspaceIndex,
timestamp: time });
// This new workspace will be automatically removed if the application fails
// to open its first window within some time, as tracked by Shell.WindowTracker.
// Here, we only add a very brief timeout to avoid the _immediate_ removal of the
// workspace while we wait for the startup sequence to load.
Main.keepWorkspaceAlive(global.screen.get_workspace_by_index(newWorkspaceIndex),
WORKSPACE_KEEP_ALIVE_TIME);
}
return true;
},

View File

@ -816,6 +816,12 @@ shell_startup_sequence_get_completed (ShellStartupSequence *sequence)
return sn_startup_sequence_get_completed ((SnStartupSequence*)sequence);
}
int
shell_startup_sequence_get_workspace (ShellStartupSequence *sequence)
{
return sn_startup_sequence_get_workspace ((SnStartupSequence*)sequence);
}
/**
* shell_startup_sequence_create_icon:
* @sequence:

View File

@ -50,6 +50,7 @@ const char *shell_startup_sequence_get_id (ShellStartupSequence *sequence);
ShellApp *shell_startup_sequence_get_app (ShellStartupSequence *sequence);
const char *shell_startup_sequence_get_name (ShellStartupSequence *sequence);
gboolean shell_startup_sequence_get_completed (ShellStartupSequence *sequence);
int shell_startup_sequence_get_workspace (ShellStartupSequence *sequence);
ClutterActor *shell_startup_sequence_create_icon (ShellStartupSequence *sequence, guint size);
G_END_DECLS