After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 642188 - Auto-workspace closing is too aggressive
Auto-workspace closing is too aggressive
Status: RESOLVED FIXED
Product: gnome-shell
Classification: Core
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gnome-shell-maint
gnome-shell-maint
: 643132 643724 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2011-02-12 18:47 UTC by drago01
Modified: 2011-03-08 18:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
autoWorkspaces: Better handle apps that open a slashscreen or dialog at startup (2.60 KB, patch)
2011-02-16 16:53 UTC, drago01
needs-work Details | Review
windowManager: Add mechanism to block animations (1.53 KB, patch)
2011-02-16 20:14 UTC, drago01
needs-work Details | Review
autoWorkspaces: Merge empty workspaces with the always empty one (1.35 KB, patch)
2011-02-16 20:14 UTC, drago01
none Details | Review
shell_global: Use clutter_event_get_time rather then get_current_event_time (1.17 KB, patch)
2011-02-16 20:14 UTC, drago01
none Details | Review
shell_global: Use clutter_event_get_time rather then get_current_event_time (1.51 KB, patch)
2011-02-16 22:00 UTC, drago01
needs-work Details | Review
autoWorkspaces: Merge empty workspaces with the always empty one (2.05 KB, patch)
2011-02-18 12:17 UTC, drago01
needs-work Details | Review
shell_global: Use clutter_event_get_time rather then get_current_event_time (1.64 KB, patch)
2011-02-21 21:35 UTC, drago01
committed Details | Review
autoWorkspaces: Better handle apps that open a slashscreen or dialog at startup (2.67 KB, patch)
2011-02-23 21:44 UTC, drago01
needs-work Details | Review
autoWorkspaces: Better handle apps that open a slashscreen or dialog at startup (2.95 KB, patch)
2011-02-23 22:31 UTC, drago01
committed Details | Review
autoWorkspaces: Merge empty workspaces with the always empty one (1.69 KB, patch)
2011-03-07 23:17 UTC, Owen Taylor
committed Details | Review
windowManager: Add mechanism to block animations (1.56 KB, patch)
2011-03-08 08:59 UTC, drago01
committed Details | Review

Description drago01 2011-02-12 18:47:45 UTC
The current way where closing the last window on a workspace automatically removes it, is a bit to aggressive.

When opening an app like gimp which uses a splash screen it closes the workspace immediately after the splash screen window is unmapped and *before* the main window is shown which results into the app opening on the adjacent workspace.

Apps that open a "do you want to restore your last session" windows behave similar (you confirm the dialog, the workspace is removed and the main window ends up on the adjacent workspace).

We had a short discussion about this on IRC and the conclusion was that we probably should just add a timeout. I am not so sure this would be the best approach as a too long timeout can result into unexpected behavior "huh why did it suddenly vanish" (as compared to directly after issuing an action like closing a window), while a too short one might not work as expected when the system is under heavy (I/O) load.

Toughs / ideas?
Comment 1 Owen Taylor 2011-02-12 19:16:31 UTC
My idea was that we'd add the timeout only in cases where we think this is likely going on - might be as simple as when the last window on the workspace was a dialog window or splash screen.

(My guess is that most apps that put up an unsaved changse dialog will close that dialog *before* their main window. If that ends up being a problem we could add more heuristics about whether the window had been transient for another window, etc.)

Then you can probably make the timeout generous - 10 seconds or so.
Comment 2 Jonathan Strander 2011-02-12 22:32:14 UTC
One thing is that apps like firefox have occasional required restarts (modifying or updating extensions usually), and for example I always use it on its own workspace.
Comment 3 Guillaume Desmottes 2011-02-16 09:20:01 UTC
I agree, auto-closing is none sense. When I start gnome-shell from GNOME 2, all my gnome-terminal are moved to the same desktop and so most of my desktops are closed....
Comment 4 drago01 2011-02-16 16:53:31 UTC
Created attachment 181022 [details] [review]
autoWorkspaces: Better handle apps that open a slashscreen or dialog at startup

Currently we remove a workspace when last window on that workspace closes,
which turned out to be too agressive as some apps open either a splashscreen
or a "I have crashed last time" dialog at startup.

Try to detect such apps and give them a chance to open their "real window(s)"
on the workspace.
Comment 5 drago01 2011-02-16 20:14:04 UTC
Created attachment 181048 [details] [review]
windowManager: Add mechanism to block animations

Add an API to allow blocking animations in situations where
they aren't desireable.
Comment 6 drago01 2011-02-16 20:14:13 UTC
Created attachment 181049 [details] [review]
autoWorkspaces: Merge empty workspaces with the always empty one

When closing a workspace due to the last window on that workspace
closing, switch to the overview and show the always empty workspace
rather then just going to the adjacent workspace.
Comment 7 drago01 2011-02-16 20:14:20 UTC
Created attachment 181050 [details] [review]
shell_global: Use clutter_event_get_time rather then get_current_event_time

Using clutter_get_current_event_time can result into too old timestamps
in some situations like after a grab where the event has not been delivered
to clutter and hence being out of date.
Comment 8 drago01 2011-02-16 22:00:34 UTC
Created attachment 181064 [details] [review]
shell_global: Use clutter_event_get_time rather then get_current_event_time

Using clutter_get_current_event_time can result into too old timestamps
in some situations like after a grab where the event has not been delivered
to clutter and hence being out of date.

---

Add NULL check
Comment 9 drago01 2011-02-18 12:17:37 UTC
Created attachment 181204 [details] [review]
autoWorkspaces: Merge empty workspaces with the always empty one

When closing a workspace due to the last window on that workspace
closing, switch to the overview and show the always empty workspace
rather then just going to the adjacent workspace.

---

Handle the case where the user moves the window to another workspace.
i.e either in the overview using dnd or using ctrl-alt-shit-up/down

We do not want to switch to the empty workspace in that case.
Comment 10 Owen Taylor 2011-02-21 21:16:18 UTC
Review of attachment 181064 [details] [review]:

Body of commit message reads a bit odd - edit:

 Using clutter_get_current_event_time can result into too old timestamps
 when there is no current Clutter or Mutter event, since
 clutter_get_current_event_time() returns the timestamp of the last event
 delivered to Clutter. This can result in, for example, grabs failing. Use
 the event time of the current event (if any) and CurrentTime otherwise.

::: src/shell-global.c
@@ +1655,3 @@
+   * We don't use clutter_get_current_event_time as it can give us a
+   * too old timestamp shortly after grabs (as the event never got
+   * passed to clutter).

This also is confusing. Grabs really don't have anything to do with it

 it will give us a too old timestamp if there is no current event

@@ +1657,3 @@
+   * passed to clutter).
+   */
+  if ((clutter_event = clutter_get_current_event ()) != NULL)

Two lines
Comment 11 drago01 2011-02-21 21:35:26 UTC
Created attachment 181523 [details] [review]
shell_global: Use clutter_event_get_time rather then get_current_event_time

Using clutter_get_current_event_time can result into too old timestamps
when there is no current Clutter or Mutter event, since
clutter_get_current_event_time() returns the timestamp of the last event
delivered to Clutter. This can result in, for example, grabs failing. Use
the event time of the current event (if any) and CurrentTime otherwise.
Comment 12 Owen Taylor 2011-02-21 21:42:18 UTC
Review of attachment 181523 [details] [review]:

Looks good
Comment 13 drago01 2011-02-21 21:44:46 UTC
Comment on attachment 181523 [details] [review]
shell_global: Use clutter_event_get_time rather then get_current_event_time

Attachment 181523 [details] pushed as 8a22ea9 - shell_global: Use clutter_event_get_time rather then get_current_event_time
Comment 14 Owen Taylor 2011-02-23 20:56:39 UTC
Review of attachment 181022 [details] [review]:

::: js/ui/main.js
@@ +253,3 @@
+    let windowCount = global.get_window_actors().filter(function (win) {
+                        return !win.get_meta_window().is_on_all_workspaces() && win.get_workspace() == workspace.index();
+                      }).length;

Array.forEach() and Array.some() have the same compat considerations - both ECMAscript 5 additions.

So, you can write:

 let windowsOnWorkspace = global.get_window_actors().some(function(actor) { 
     /* check for window on workspace */
 });

@@ +256,3 @@
+
+    if (windowCount > 0)
+        return;

See below for why I'm not really that psyched about optimizing calls to queueCheckWorkspaces, but if this check is needed anyways to detect the "wait" case, it's pretty transparently OK.

@@ +269,3 @@
+    }
+    else
+        _queueCheckWorkspaces();

Here's the absolutely minimal code approach:

function _windowRemoved(workspace, window) {
  workspace._lastRemovedWindow = window;
  _queueCheckWorkspaces();
  Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, function() { 
      if (workspace._lastRemovedWindow == window) {
          workspace._lastRemovedWindow = null;
          _queueCheckWorkspaces();
      }
  });
}

And then do the obvious thing in checkWorkspaces.

@@ +272,3 @@
+}
+
+function _windowAdded(workspace, window) {

order them added/removed - removed/added is oddball.

@@ +274,3 @@
+function _windowAdded(workspace, window) {
+    if (workspace.index() != global.screen.n_workspaces - 1)
+        return;

I don't like this optimization ... I can't come up with a scenario where it is wrong, but I'd like the "check workspaces" step just to be fine to call whenever: reasonably cheap and does no harm. (The queue handling is meant to make sure that no matter how much changes we just run through all the windows once.)
Comment 15 drago01 2011-02-23 21:38:33 UTC
(In reply to comment #14)
> Review of attachment 181022 [details] [review]:
> 
> ::: js/ui/main.js
> @@ +253,3 @@
> +    let windowCount = global.get_window_actors().filter(function (win) {
> +                        return !win.get_meta_window().is_on_all_workspaces()
> && win.get_workspace() == workspace.index();
> +                      }).length;
> 
> Array.forEach() and Array.some() have the same compat considerations - both
> ECMAscript 5 additions.
> 
> So, you can write:
> 
>  let windowsOnWorkspace = global.get_window_actors().some(function(actor) { 
>      /* check for window on workspace */
>  });

OK, wasn't aware of Array.some() but sounds like handy for this kind of task.

> @@ +256,3 @@
> +
> +    if (windowCount > 0)
> +        return;
> 
> See below for why I'm not really that psyched about optimizing calls to
> queueCheckWorkspaces, but if this check is needed anyways to detect the "wait"
> case, it's pretty transparently OK.

This wasn't supposed to be an optimization, I can make it call _queueCheckWorkspaces in this case but it is pointless.

> @@ +269,3 @@
> +    }
> +    else
> +        _queueCheckWorkspaces();
> 
> Here's the absolutely minimal code approach:
> 
> function _windowRemoved(workspace, window) {
>   workspace._lastRemovedWindow = window;
>   _queueCheckWorkspaces();
>   Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, function() { 
>       if (workspace._lastRemovedWindow == window) {
>           workspace._lastRemovedWindow = null;
>           _queueCheckWorkspaces();
>       }
>   });
> }
> 
> And then do the obvious thing in checkWorkspaces.

OK.

> @@ +272,3 @@
> +}
> +
> +function _windowAdded(workspace, window) {
> 
> order them added/removed - removed/added is oddball.

OK, but when removing the optimization in _windowAdded it will be nothing but a wrapper around _queueCheckWorkspaces so we could as well call that directly.

> @@ +274,3 @@
> +function _windowAdded(workspace, window) {
> +    if (workspace.index() != global.screen.n_workspaces - 1)
> +        return;
> 
> I don't like this optimization ... I can't come up with a scenario where it is
> wrong, but I'd like the "check workspaces" step just to be fine to call
> whenever: reasonably cheap and does no harm. (The queue handling is meant to
> make sure that no matter how much changes we just run through all the windows
> once.)

I did it because it seemed like an obvious (micro) optimization (i.e when not on the last workspace there is nothing to do anyway) but yeah can just remove it.
Comment 16 drago01 2011-02-23 21:44:17 UTC
Created attachment 181754 [details] [review]
autoWorkspaces: Better handle apps that open a slashscreen or dialog at startup

Currently we remove a workspace when last window on that workspace closes,
which turned out to be too agressive as some apps open either a splashscreen
or a "I have crashed last time" dialog at startup.

Try to detect such apps and give them a chance to open their "real window(s)"
on the workspace.

---

Removed optimization and went with the simple approuch you proposed.
Comment 17 drago01 2011-02-23 22:10:34 UTC
*** Bug 643132 has been marked as a duplicate of this bug. ***
Comment 18 Owen Taylor 2011-02-23 22:13:06 UTC
Review of attachment 181754 [details] [review]:

I like this better. As you said, the optimization of checking on added windows whether they are on the last workspace seems pretty obvious, but it isn't *completely* obvious to me that there couldn't be some intermediate state with a empty workspace in the middle if we add the ability to reorder workspaces or something. Less code the better I think.

Just some minor stuff here.

::: js/ui/main.js
@@ +223,3 @@
 let _checkWorkspacesId = 0;
 
+const LAST_WINDOW_GRACE_TIME = 1000;

Can you add a comment here for what this is about?

@@ +230,3 @@
 
+    for (i = 0; i < _workspaces.length; i++) {
+        let window = _workspaces[i]._lastRemovedWindow;

let lastRemoved = ... - this variable isn't 'window' in the context of iterating through workspace

@@ +268,3 @@
 
+function _windowRemoved(workspace, window) {
+   workspace._lastRemovedWindow = window;

indentation wrong
Comment 19 drago01 2011-02-23 22:31:38 UTC
Created attachment 181760 [details] [review]
autoWorkspaces: Better handle apps that open a slashscreen or dialog at startup

Currently we remove a workspace when last window on that workspace closes,
which turned out to be too agressive as some apps open either a splashscreen
or a "I have crashed last time" dialog at startup.

Try to detect such apps and give them a chance to open their "real window(s)"
on the workspace.
Comment 20 drago01 2011-02-23 22:34:19 UTC
(In reply to comment #18)
> Review of attachment 181754 [details] [review]:
> 
> I like this better. As you said, the optimization of checking on added windows
> whether they are on the last workspace seems pretty obvious, but it isn't
> *completely* obvious to me that there couldn't be some intermediate state with
> a empty workspace in the middle if we add the ability to reorder workspaces or
> something. Less code the better I think.

Well I couldn't think of a case where it would be a problem but well we are talking about a non measurable optimization here, so I agree that we should stay on the safe side here (it even means less code).
Comment 21 david 2011-02-25 21:26:01 UTC
Here is the way I use workspaces: I have an app open on each of 10 workspaces and switch between them using shortcut key combinations. These are apps that I regular use in my work. I do much switching between them by switching workspaces. With the auto-remove feature this is what happens: My browser on workspace #1 crashes, leaves empty the workspace it was on and the workspace is removed and all the open applications effectively move to a new workspace and the keyboard shortcuts become useless for switching between applications. The auto-removing of empty workspaces in this case is a hindrance to my work.

There must at least be an option for "fixed" workspaces that are manually removed. Or, only the last empty workspace is auto-removed.

There are certainly many different ways workspaces get used.
Comment 22 LeDabe 2011-02-27 05:58:10 UTC
Auto-close and switching to another workspace can break confidentiality.
It may be some mails or files we don't wan't to show or view
but that will win the focus if the current application suddenly crashes or restart;
What do you think of an visible and short timeout which can be clicked to stay in the current workspace ?
Also, what about a button to "Lock" on the current workspace even if it becomes empty ?
With my own usage, there are a few workspace opened for mail, download or compilation and the last for my work's tasks.
I don't have tested the different patch, but I will try
Comment 23 Owen Taylor 2011-03-01 16:50:44 UTC
Review of attachment 181760 [details] [review]:

Good to commit, except for a suggestion about the comment.

::: js/ui/main.js
@@ +224,3 @@
 
+/*
+ * When an app starts with a dialog window or slash screen before mapping

splash screen not slash screen.

I think this comment is a little deceptive, because it implies we are paying attention to apps *starting*, and currently we aren't. Suggested alternative:

 When the last window closed on a workspace is a dialog or splash
 screen, we assume that it might be an initial window shown before
 the main window of an application, and give the app a grace period
 where it can map another window before we remove the workspace.
Comment 24 LeDabe 2011-03-03 05:35:08 UTC
I've tried the patch 181760
It's better for apps with splash screen
But what about application quick restarting, such as firefox in many case ?
Comment 25 drago01 2011-03-03 17:29:22 UTC
*** Bug 643724 has been marked as a duplicate of this bug. ***
Comment 26 Owen Taylor 2011-03-07 23:17:19 UTC
Created attachment 182788 [details] [review]
autoWorkspaces: Merge empty workspaces with the always empty one

OK, I don't understand the reason for the Meta.later_add(), and it seems
to work fine without it in this patch. I also don't see any reason for
the special casing of "user moved window"

Based on a patch from Adel Gadllah <adel.gadllah@gmail.com>.
Comment 27 Owen Taylor 2011-03-07 23:19:24 UTC
Review of attachment 181204 [details] [review]:

As noted in the comment on the version attached, don't really understand the reasoning for the complexity here - something simpler seems to work.
Comment 28 Owen Taylor 2011-03-07 23:20:49 UTC
Review of attachment 181048 [details] [review]:

Would like to see this._animationBlockCount rather than a boolean, to reduce risk of different code portions stepping on each other
Comment 29 drago01 2011-03-07 23:35:38 UTC
(In reply to comment #26)
> Created an attachment (id=182788) [details] [review]
> autoWorkspaces: Merge empty workspaces with the always empty one
> 
> OK, I don't understand the reason for the Meta.later_add(), and it seems
> to work fine without it in this patch.

Actually I don't know why I started off with the complicated approach without testing the simpler one first; the reason was to hide the fact that mutter switches to the adjacent workspace after remove (and we switch to the empty one directly after that) so I wanted to hide a possible artifact here (going to a workspace and back) by having BEFORE_REDRAW priority but it seems to be indeed not needed.

> I also don't see any reason for
> the special casing of "user moved window"

Because it is very weird otherwise lets say you do move a window from a workspace using ctrl-alt-shift-up (and this was the last window on that workspace) switching to the empty workspace in that case is not what the user wants, he clearly moved to the adjacent workspace on purpose and took the window with him, so a switch to the empty one is clearly not what the user expects here.

The other case would be that a user is rearranging windows in the overview dragging a window out of a workspace to place it elsewhere should not switch the active workspace (actually it should in case the user was on the workspace being removed which my patch didn't address), it is simply not what the user expects and is inconsistent with other workspaces where dragging windows around does not actually change workspaces.
Comment 30 drago01 2011-03-07 23:38:06 UTC
(In reply to comment #28)
> Review of attachment 181048 [details] [review]:
> 
> Would like to see this._animationBlockCount rather than a boolean, to reduce
> risk of different code portions stepping on each other

OK, makes sense.
Comment 31 Owen Taylor 2011-03-07 23:47:08 UTC
(In reply to comment #29)
> (In reply to comment #26)
> > Created an attachment (id=182788) [details] [review] [details] [review]
> > autoWorkspaces: Merge empty workspaces with the always empty one
> > 
> > OK, I don't understand the reason for the Meta.later_add(), and it seems
> > to work fine without it in this patch.
> 
> Actually I don't know why I started off with the complicated approach without
> testing the simpler one first; the reason was to hide the fact that mutter
> switches to the adjacent workspace after remove (and we switch to the empty one
> directly after that) so I wanted to hide a possible artifact here (going to a
> workspace and back) by having BEFORE_REDRAW priority but it seems to be indeed
> not needed.
> 
> > I also don't see any reason for
> > the special casing of "user moved window"
> 
> Because it is very weird otherwise lets say you do move a window from a
> workspace using ctrl-alt-shift-up (and this was the last window on that
> workspace) switching to the empty workspace in that case is not what the user
> wants, he clearly moved to the adjacent workspace on purpose and took the
> window with him, so a switch to the empty one is clearly not what the user
> expects here.
> 
> The other case would be that a user is rearranging windows in the overview
> dragging a window out of a workspace to place it elsewhere should not switch
> the active workspace (actually it should in case the user was on the workspace
> being removed which my patch didn't address), it is simply not what the user
> expects and is inconsistent with other workspaces where dragging windows around
> does not actually change workspaces.

Obviously, we shouldn't switch to the empty workspace in the control-alt-shift case, but I don't think that requires any special casing - by the time the workspace removing code is run the window has been moved and the active workspace switched, so we just need to check if we'll be removing the current workspace or not, as my patch does.
Comment 32 drago01 2011-03-08 08:59:57 UTC
Created attachment 182801 [details] [review]
windowManager: Add mechanism to block animations

Add an API to allow blocking animations in situations where
they aren't desireable.

---

Use a counter rather then a boolean.
Comment 33 drago01 2011-03-08 09:03:06 UTC
(In reply to comment #31)
> (In reply to comment #29)
> > (In reply to comment #26)
>
> Obviously, we shouldn't switch to the empty workspace in the control-alt-shift
> case, but I don't think that requires any special casing - by the time the
> workspace removing code is run the window has been moved and the active
> workspace switched, so we just need to check if we'll be removing the current
> workspace or not, as my patch does.

Indeed this makes sense and indeed works.
Comment 34 drago01 2011-03-08 09:07:42 UTC
Review of attachment 182788 [details] [review]:

Looks good and is much simpler than my original patch.
Comment 35 Owen Taylor 2011-03-08 15:11:07 UTC
Review of attachment 182801 [details] [review]:

Looks good. (Possibly should warn about mismatched block/unblock, but not really worth it.)
Comment 36 drago01 2011-03-08 18:47:02 UTC
Attachment 182788 [details] pushed as e054dd7 - autoWorkspaces: Merge empty workspaces with the always empty one
Attachment 182801 [details] pushed as 76d788a - windowManager: Add mechanism to block animations