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 616050 - alt-tab infrastructure patches
alt-tab infrastructure patches
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
Depends on:
Blocks: 616051
 
 
Reported: 2010-04-17 20:56 UTC by Colin Walters
Modified: 2010-05-05 21:31 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
[MetaDisplay] Export methods interact with user_time (4.29 KB, patch)
2010-04-17 20:56 UTC, Colin Walters
committed Details | Review
[MetaWindow] Export the functions to control demands_attention (1.73 KB, patch)
2010-04-17 20:56 UTC, Colin Walters
committed Details | Review
Add functionality for raising/activating a window, respecting transients (10.25 KB, patch)
2010-04-17 20:56 UTC, Colin Walters
reviewed Details | Review
meta_window_activate should respect transients (7.01 KB, patch)
2010-04-18 15:26 UTC, Colin Walters
none Details | Review
Export meta_window_raise and meta_window_lower (1.83 KB, patch)
2010-04-24 21:22 UTC, Colin Walters
committed Details | Review
Add public function to sort windows by stacking (1.81 KB, patch)
2010-04-24 21:22 UTC, Colin Walters
needs-work Details | Review
Export functions to iterate over window transients (2.81 KB, patch)
2010-04-24 21:22 UTC, Colin Walters
needs-work Details | Review
Export functions to iterate over window transients (5.43 KB, patch)
2010-04-27 18:32 UTC, Colin Walters
committed Details | Review
Add public function to sort windows by stacking (2.06 KB, patch)
2010-04-29 00:49 UTC, Colin Walters
committed Details | Review

Description Colin Walters 2010-04-17 20:56:47 UTC
See last patch
Comment 1 Colin Walters 2010-04-17 20:56:49 UTC
Created attachment 158976 [details] [review]
[MetaDisplay] Export methods interact with user_time

This is useful when calling some of the lower level mutter functions,
e.g. controlling window stacking.
Comment 2 Colin Walters 2010-04-17 20:56:51 UTC
Created attachment 158977 [details] [review]
[MetaWindow] Export the functions to control demands_attention

Plugins can want a finer grained control over this.
Comment 3 Colin Walters 2010-04-17 20:56:53 UTC
Created attachment 158978 [details] [review]
Add functionality for raising/activating a window, respecting transients

In an application-based system like GNOME Shell, we often transition
between applications, and not particular windows.  This patch adds
utility functions which allow raising a toplevel window, but
respecting its transients.

This fixes e.g. opening a file chooser, alt-tab'ing away, then tabbing
back.
Comment 4 Dan Winship 2010-04-17 22:29:19 UTC
Comment on attachment 158977 [details] [review]
[MetaWindow] Export the functions to control demands_attention

ok, but would it make more sense as a boolean gobject property?
Comment 5 Dan Winship 2010-04-17 22:46:22 UTC
Comment on attachment 158978 [details] [review]
Add functionality for raising/activating a window, respecting transients

>In an application-based system like GNOME Shell, we often transition
>between applications, and not particular windows.  This patch adds
>utility functions which allow raising a toplevel window, but
>respecting its transients.
>
>This fixes e.g. opening a file chooser, alt-tab'ing away, then tabbing
>back.

For me, with unpatched mutter, the file chooser is already kept above the main window, and raised along with it when the window is activated. The only problem is that it doesn't get keyboard focus when I Alt-Tab back to it (the main window does instead, although it remains stacked underneath the file chooser). But IMHO that's just a bug, and should be fixed in ordinary meta_window_activate().

Is that not the behavior you're seeing?

>+ * Returns: (transfer container): List of transients for this window, sorted by user time

Should say "sorted in stacking order, bottom to top", right?
Comment 6 Dan Winship 2010-04-17 22:47:36 UTC
Comment on attachment 158976 [details] [review]
[MetaDisplay] Export methods interact with user_time

this does what it says it does, though i wonder why this function hasn't been needed up to this point. is the existing code doing the comparison incorrectly? or is everything that has to compare timestamps in display.c, even if it doesn't logically belong there?
Comment 7 Colin Walters 2010-04-17 22:53:08 UTC
(In reply to comment #5)
> 
> 
> For me, with unpatched mutter, the file chooser is already kept above the main
> window, and raised along with it when the window is activated. The only problem
> is that it doesn't get keyboard focus when I Alt-Tab back to it (the main
> window does instead, although it remains stacked underneath the file chooser).
> But IMHO that's just a bug, and should be fixed in ordinary
> meta_window_activate().

Hmm, yes maybe you're right it's just a bug in meta_window_activate.  I sort of went to an elaborate workaround to not change that, but if we agree that's right then let's definitely fix it there.

> 
> Is that not the behavior you're seeing?
> 
> >+ * Returns: (transfer container): List of transients for this window, sorted by user time
> 
> Should say "sorted in stacking order, bottom to top", right?

Yes
Comment 8 Colin Walters 2010-04-17 22:53:40 UTC
(In reply to comment #6)
> (From update of attachment 158976 [details] [review])
> this does what it says it does, though i wonder why this function hasn't been
> needed up to this point. is the existing code doing the comparison incorrectly?
> or is everything that has to compare timestamps in display.c, even if it
> doesn't logically belong there?

It's to export it basically; it lived in display-private.h, now we can use it from both plugins and script.
Comment 9 Colin Walters 2010-04-18 15:26:10 UTC
Created attachment 159016 [details] [review]
meta_window_activate should respect transients

When e.g. using Alt-TAB to move between windows, we should by
default respect transients for the given window.

This fixes e.g. opening a file chooser in GEdit, alt-tab'ing
away, then tabbing back.
Comment 10 Tomas Frydrych 2010-04-19 08:20:20 UTC
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -3526,6 +3527,7 @@ window_activate (MetaWindow     *window,
   if (window->xtransient_for == None &&
       !meta_window_located_on_workspace (window, workspace))
     {
+      meta_window_set_user_time (window, timestamp);
       meta_window_set_demands_attention (window);
       /* We've marked it as demanding, don't need to do anything else. */
       return;

This is not right; the usertime should be the last time the user directly interacted with the window (e.g., typed into it or clicked on it). Since this window is not getting actually activated, we can't change the user time.

@@ -3534,22 +3536,51 @@ window_activate (MetaWindow     *window,
     {
       /* Move transients to current workspace - preference dialogs should appear over
          the source window.  */
-    meta_window_change_workspace (window, workspace);
+      meta_window_change_workspace (window, workspace);
+      meta_window_raise (window);

I think this will break things if the 'raise on click' preference is not set.

+      if (transients)
+        {
+          target = g_slist_last (transients)->data;

You seem to be assuming that if the window has transients, the focused window is one of the transients, and this assumption cannot be granted (e.g., a common reason for non-modal dialogs is to allow the user to interact with the main application while the dialog is visible above it).
 
+  for (iter = transients; iter; iter = iter->next)
+    {
+      MetaWindow *window = iter->data;
+      meta_window_raise (window);
+    }

Is the assumption that the usertime sequence represents the correct stacking order (e.g., as created by the application & user) valid ? If it is, then the transients should already be in that order so this would be superfluous. If this is not superfluous, the assumption is probably not correct.

IMO restacking all transients in window_activate() is not the correct thing to do; the window_activate() function should do what the name implies, activate the window it was given. Anything else will break things for applications that use non-modal dialogs in a sensible way and for external pagers.

I think the problem is basically with the paging algorithm rather than the actual activation (note this only happens when the dialog is not modal to the application; e.g., the GEdit FileSave dialog does not exhibit this problem, while the FileOpen does). Inside the pager, determining which window to activate based on the usertime might indeed be the right/best thing to do, though this needs to include not just the transients, but also the application window usertime to avoid stealing focus from the main window.

So, I think we need something like the new API proposed in comment 3, but the implementation should consider the usertime of the application window as well, so that the focus goes not go to the topmost window, but the one the user interacted with last.
Comment 11 Colin Walters 2010-04-24 21:22:14 UTC
Created attachment 159486 [details] [review]
Export meta_window_raise and meta_window_lower

For plugins that want fine grained control over window stacking.
Comment 12 Colin Walters 2010-04-24 21:22:19 UTC
Created attachment 159487 [details] [review]
Add public function to sort windows by stacking
Comment 13 Colin Walters 2010-04-24 21:22:22 UTC
Created attachment 159488 [details] [review]
Export functions to iterate over window transients
Comment 14 Colin Walters 2010-04-27 17:51:01 UTC
Note on these patches - rather than trying to handle this in meta_window_activate which is also used in other cases like click handling, I chose to keep mutter as a lower level library, and implement the handling inside the shell plugin.
Comment 15 Owen Taylor 2010-04-27 17:52:04 UTC
Review of attachment 159487 [details] [review]:

I'd like to see docs - see what you think this function and what it's good for before I dig into the stacking code again and try to figure out if that's what it actually does.
Comment 16 Owen Taylor 2010-04-27 17:52:42 UTC
Review of attachment 159486 [details] [review]:

Looks OK.
Comment 17 Owen Taylor 2010-04-27 17:53:18 UTC
Review of attachment 159488 [details] [review]:

Need to add function docs, these functions (especially foreach_ancestor) aren't obvious in what they do.
Comment 18 Colin Walters 2010-04-27 18:32:27 UTC
Review of attachment 159487 [details] [review]:

What I'm using this for is to sort the transient windows for a given window, so we can call meta_window_raise on them in the right order.
Comment 19 Colin Walters 2010-04-27 18:32:57 UTC
Created attachment 159710 [details] [review]
Export functions to iterate over window transients
Comment 20 Owen Taylor 2010-04-27 19:11:53 UTC
(In reply to comment #18)
> Review of attachment 159487 [details] [review]:
> 
> What I'm using this for is to sort the transient windows for a given window, so
> we can call meta_window_raise on them in the right order.

Can you write that down a doc comment, with that as an example use case and with a bit more detail? One important detail is that if override-redirect windows are included in the list of windows, the returned stacking order will be undefined.
Comment 21 Colin Walters 2010-04-29 00:49:34 UTC
Created attachment 159837 [details] [review]
Add public function to sort windows by stacking
Comment 22 Owen Taylor 2010-05-04 16:18:18 UTC
Review of attachment 159837 [details] [review]:

Rewrite of the doc comment below. I think it's important to specify the operation of the function fairly carefully. OK to commit with my rewrite.

::: src/core/display.c
@@ +5020,3 @@
+ * windows for another window, or to sort a set of toplevel windows.
+ * The ordering of this function is not defined if any override-redirect
+ * windows are in @windows.

Sorts a set of windows according to their current stacking order. If windows from multiple screens are present in the set of input windows, then all the windows on screen 0 are sorted below all the windows on screen 1, and so forth. Since the stacking order of override-redirect windows isn't controlled by Metacity, if override-redirect windows are in the input, the result may not correspond to the actual stacking order in the X server.

An example of using this would be to sort the list of transient dialogs for a window into their current stacking order.
Comment 23 Owen Taylor 2010-05-04 16:20:11 UTC
Review of attachment 159710 [details] [review]:

OK to commit with two tiny fixes

::: src/core/window.c
@@ +8253,3 @@
+ * @window: a #MetaWindow
+ * @func: (scope call): Called for each window which is a transient of @window (transitively)
+ * @data: (closure): User data

You renamed this to @user_data

@@ +8292,3 @@
+ * @window: a #MetaWindow
+ * @func: (scope call): Called for each window which is a transient parent of @window
+ * @data: (closure): User data

And this
Comment 24 Colin Walters 2010-05-05 21:31:02 UTC
Attachment 159486 [details] pushed as 4994087 - Export meta_window_raise and meta_window_lower
Attachment 159710 [details] pushed as 609aae6 - Export functions to iterate over window transients
Attachment 159837 [details] pushed as fd20059 - Add public function to sort windows by stacking