GNOME Bugzilla – Bug 642580
Tiled windows sometimes "jump" from one display to the other in a multi-head configuration
Last modified: 2011-10-18 01:41:12 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".
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.
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.
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).
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?
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.
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.
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:
+ Trace 227482
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.
Florian: ping - you were going to review this, right?
(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.
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
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
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.
*** Bug 662001 has been marked as a duplicate of this bug. ***
*** Bug 662002 has been marked as a duplicate of this bug. ***
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.
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()
Created attachment 199290 [details] [review] tiling: keep track of the monitor where a window was tiled Addressed all comments.
Review of attachment 199290 [details] [review]: LGTM
Attachment 199290 [details] pushed as 138eb1e - tiling: keep track of the monitor where a window was tiled