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 642580 - Tiled windows sometimes "jump" from one display to the other in a multi-head configuration
Tiled windows sometimes "jump" from one display to the other in a multi-head ...
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: general
git master
Other Linux
: Normal normal
: ---
Assigned To: Florian Müllner
mutter-maint
: 662001 662002 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2011-02-17 16:07 UTC by Rui Matos
Modified: 2011-10-18 01:41 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
tiling: keep track of a tile area for each window instead of computing it (7.70 KB, patch)
2011-06-14 16:54 UTC, Rui Matos
none Details | Review
tiling: keep track of a tile area for each window instead of computing it (7.70 KB, patch)
2011-08-10 14:35 UTC, Rui Matos
needs-work Details | Review
tiling: keep track of the monitor where a window was tiled (6.54 KB, patch)
2011-10-18 00:20 UTC, Rui Matos
needs-work Details | Review
tiling: keep track of the monitor where a window was tiled (7.16 KB, patch)
2011-10-18 01:27 UTC, Rui Matos
committed Details | Review

Description Rui Matos 2011-02-17 16:07:54 UTC
Tiled windows sometimes "jump" from one display to the other in a multi-head configuration.

I don't know of a way to trigger this as it seems to happen without any interaction with those windows at all. The "jump" occurs in the "background" while using other windows and the tiled windows don't get focus when they "jump".
Comment 1 JonRob 2011-04-19 14:01:04 UTC
I've seen the same problem. Agreed that it only seems to happen when Windows have been tiled (by this I assume you mean made to take up half the screen?), and agreed that it's difficult to reproduce. I think it might have something to do with where the mouse is located as the focus of a window switches? Although trying now, perhaps not.
Comment 2 JonRob 2011-04-19 15:14:07 UTC
I've just figured out how to reproduce this bug. 

Tiled windows switch display when any other window is closed on the other display. So, if I have gedit tiled on my left hand screen, and close a terminal in the right hand screen, the gedit windows will switch to the right hand screen. 

Hope this is useful to help fix.
Comment 3 Will Thompson 2011-05-04 15:58:04 UTC
I had some success reproducing this issue as follows:

• Have Empathy and a terminal (A) open on the secondary screen, non-maximized;
• Open a terminal (B) on the primary screen;
• Snap terminal A to the right-hand side of the secondary screen;
• Snap Empathy to the left-hand side of the secondary screen;
• Close terminal B.

Roughly every other attempt, this would make Empathy and terminal A jump to the primary screen, tiled as they were on the secondary screen. On other occasions, the dash was displayed (and hence the secondary screen zoomed out into I-can't-believe-it's-not-Exposé mode).
Comment 4 Martin Meyer 2011-06-03 14:45:02 UTC
I see this behavior too. It happens to me when I save a document in gedit (via ctrl+s) while gedit has focus but the mouse cursor is located on the other monitor. This behavior is very consistent. It will move the window to the same tile position on whichever screen has the mouse cursor.

Note that I also see this behavior in both Firefox and gitg when they are maximized, NOT tiled. I'm not sure if that's caused by the same bug or not. Should I file a separate bug for that, or is it likely to be the same issue as this?
Comment 5 Andy 2011-06-08 11:19:56 UTC
For me it's different, I cannot reproduce the bug with any of the above described methods.

A tiled window just jumps to the primary screen when it gets back the focus after some interaction with the notification panel.

F.e. when I close an application, that has an icon in the notification panel, and the window which had the focus last is tiled on the secondary screen, then it will jump to the primary screen as soon as it gets back the focus.
Comment 6 Rui Matos 2011-06-14 16:54:00 UTC
Created attachment 189927 [details] [review]
tiling: keep track of a tile area for each window instead of computing it

meta_window_get_current_tile_area() computes the area where the tiled window
should be based on the current pointer position but that's only meaningful
when the user is actually dragging the window.

Instead, we save the tile area on update_move() and use it later when applying
constraints or snapping back a canceled move.
Comment 7 Rui Matos 2011-06-14 17:10:03 UTC
This patch also fixes 2 other issues due to the same fundamental problem:

1. On the Overview, dragging all windows from the primary monitor's 1st workspace into the 2nd workspace (through the thumbnail) while having tiled windows on the secondary monitor of the 1st workspace would hit this assertion in mutter:

  • #0 raise
    from /lib64/libc.so.6
  • #1 abort
    from /lib64/libc.so.6
  • #2 meta_bug
    at core/util.c line 444
  • #3 meta_workspace_index
    at core/workspace.c line 699
  • #4 ffi_call_unix64
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #5 ffi_call
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #6 ??
    from /usr/lib64/libgjs-gi.so.0
  • #7 ??
    from /usr/lib64/libgjs-gi.so.0
  • #8 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #9 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #10 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #11 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #12 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #13 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #14 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #15 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #16 ??
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #17 JS_CallFunctionValue
    from /usr/lib64/xulrunner-2/libmozjs.so
  • #18 gjs_call_function_value
    from /usr/lib64/libgjs.so.0
  • #19 gjs_closure_invoke
    from /usr/lib64/libgjs-gi.so.0
  • #20 ??
    from /usr/lib64/libgjs-gi.so.0
  • #21 g_closure_invoke
    from /lib64/libgobject-2.0.so.0
  • #22 ??
    from /lib64/libgobject-2.0.so.0
  • #23 g_signal_emit_valist
    from /lib64/libgobject-2.0.so.0
  • #24 g_signal_emit_by_name
    from /lib64/libgobject-2.0.so.0
  • #25 meta_window_update_monitor
    at core/window.c line 4269
  • #26 meta_window_move_resize_internal
    at core/window.c line 4725
  • #27 meta_window_move_resize
    at core/window.c line 4892
  • #28 meta_window_move_resize_now
    at core/window.c line 4925
  • #29 idle_move_resize
    at core/window.c line 4960
  • #30 call_idle_later
    at core/util.c line 801
  • #31 g_main_context_dispatch
    from /lib64/libglib-2.0.so.0
  • #32 ??
    from /lib64/libglib-2.0.so.0
  • #33 g_main_loop_run
    from /lib64/libglib-2.0.so.0
  • #34 meta_run
    at core/main.c line 555
  • #35 main
    at main.c line 511


2. When canceling a window move with Escape of a tiled window while the mouse pointer was already dragging on the other monitor would snap the window to a tile on this other monitor instead of the original one.

Please review, thanks.
Comment 8 Owen Taylor 2011-07-11 15:47:21 UTC
Florian: ping - you were going to review this, right?
Comment 9 Florian Müllner 2011-07-11 16:00:52 UTC
(In reply to comment #8)
> Florian: ping - you were going to review this, right?

Yes, but in my opinion the validity of the per-window tile rect approach in this patch depends on the outcome of the design questions raised in bug 645153.
Comment 10 Rui Matos 2011-08-10 14:35:08 UTC
Created attachment 193552 [details] [review]
tiling: keep track of a tile area for each window instead of computing it

meta_window_get_current_tile_area() computes the area where the tiled window
should be based on the current pointer position but that's only meaningful
when the user is actually dragging the window.

Instead, we save the tile area on update_move() and use it later when applying
constraints or snapping back a canceled move.

--

- Rebased on master
Comment 11 Adam K Kirchhoff 2011-08-16 20:27:31 UTC
For me, all I have to do is rapidly move the mouse back and forth between the monitors and one of of the tiled windows will jump.  The first time this happened, I thought the application had crashed as the window ended up below other windows on the other monitor:

http://www.visualtech.com/shell-20110816-2.webm
Comment 12 Florian Müllner 2011-10-03 19:09:40 UTC
Review of attachment 193552 [details] [review]:

The code mostly works in testing, but I still don't like it ;-)

The semantics of the tile_mode variable are already tricky enough (e.g. depending on the maximization state it means either current tile state or requested tile state), and adding a second variable which follows the same semantics and mostly overlaps the first one complicates that further. Worse, we assume that both variables are kept in sync, but given that both are read and written externally, I don't feel very safe with that assumption :-)

Also, the patch introduces a small regression when not handling size changes of the work area (run and exit some dock application that adds to the struts, or kill gnome-panel in fallback mode while running mutter standalone).

So I see more or less the following options for fixing this bug:

 1. Figure out a smart way to determine the correct monitor dynamically (if possible at all, it's probably rather fragile, so it doesn't sound like a very good option)

 2. Add a tile_monitor variable to store the monitor; still adds a second variable, but at least it does not overlap with the existing one (and shouldn't regress on size changes)

 3. Replace tile_mode with tile_rect (or rather a pointer, so TILE_MODE_NONE can be expressed as tile_rect == NULL) - fixes the overlap, but there's no longer an easy way to check the actual tile mode (TILE_MODE_LEFT etc. could be replaced by macros which iterate over all monitors and compare "edges", but ... ugh ... ugly and expensive); it would also require some extra work to avoid the regression

 4. Use a rect, but make it an implementation detail of window.c (to be honest I'm not exactly sure how to do that or if it's even possible - at least when restoring a tile state after canceling a drag operation, we'll need the correct monitor number)


Unsurprisingly, I favor (2) ...

::: src/core/window.c
@@ +8362,3 @@
+      if (window->tile_mode == META_TILE_LEFT  ||
+          window->tile_mode == META_TILE_RIGHT)
+        window->tile_rect.width /= 2;

Moving that code into update_move() ties setting the state to the mechanism ("dragging the window"). We'll want to be able to set the tile state via keybindings as well, so it should be possible to implement this without duplicating this code snippet.
Comment 13 Florian Müllner 2011-10-17 13:57:10 UTC
*** Bug 662001 has been marked as a duplicate of this bug. ***
Comment 14 Florian Müllner 2011-10-17 14:09:53 UTC
*** Bug 662002 has been marked as a duplicate of this bug. ***
Comment 15 Rui Matos 2011-10-18 00:20:10 UTC
Created attachment 199288 [details] [review]
tiling: keep track of the monitor where a window was tiled

meta_window_get_current_tile_area() computes the area where the tiled window
should be based on the current pointer position but that's only meaningful
when the user is actually dragging the window.

When running the tiling constrain the pointer might be on other monitor and at
that point the window jumps to this other monitor.
Comment 16 Florian Müllner 2011-10-18 00:51:49 UTC
Review of attachment 199288 [details] [review]:

Thanks! I feel much better with this patch ...

Still one bug when moving tiled windows to another monitor (using the overview, e.g. without dragging the window free), but that's easy to fix (see comment below). Other than that, two minor style nits - the first one is pointed out below, the second one is that I'm not a big fan of the _idx suffix (I'd just go with window->tile_monitor, though that's inconsistent with window->monitor - maybe go with window->tile_monitor_number which matches winodw->monitor->number?)

::: src/core/display.c
@@ +3602,3 @@
+    {
+      display->grab_tile_mode = META_TILE_NONE;
+      display->grab_tile_monitor_idx = 0;

If tile_mode is META_TILE_NONE, the value of tile_monitor doesn't really matter; still, 0 is a perfectly fine monitor index, so I'd use -1 to indicate "unset" (here and everywhere else)

::: src/core/window.c
@@ +4359,3 @@
 
+  if (window->tile_mode != META_TILE_NONE)
+    window->tile_monitor_idx = new->number;

You'll need to do the same in meta_window_move_to_monitor()
Comment 17 Rui Matos 2011-10-18 01:27:02 UTC
Created attachment 199290 [details] [review]
tiling: keep track of the monitor where a window was tiled

Addressed all comments.
Comment 18 Florian Müllner 2011-10-18 01:38:54 UTC
Review of attachment 199290 [details] [review]:

LGTM
Comment 19 Rui Matos 2011-10-18 01:41:08 UTC
Attachment 199290 [details] pushed as 138eb1e - tiling: keep track of the monitor where a window was tiled