From bb2e8ff09a5461d3a87954d1b81ef94de324577a Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Tue, 15 Nov 2016 14:10:05 +0100 Subject: [PATCH] window: Make move_to_monitor work for zero sized and offscreen windows Wayland windows are initially zero sized until clients commit the first buffer. Despite being invisible, clients are allowed to request such windows to be fullscreened on a specific output before they attach the first buffer which means we need to be able to move them. meta_window_move_to_monitor() doesn't handle this case because these windows' initial monitor is a placeholder since their initial coordinates are 0,0+0+0, which results in us using a rectangle as old_area for meta_window_move_between_rects() that might be to the "right" of the window causing the move to go further out of the visible screen's coordinates. This is later "corrected" by the constraints system but the window might end up in the wrong monitor. To fix this, we can make meta_window_move_between_rects() accept a NULL old_area, meaning that we move the window to the new_area without trying to keep a relative position. https://bugzilla.gnome.org/show_bug.cgi?id=772525 --- src/core/window.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/core/window.c b/src/core/window.c index 82a8f852f..cd2bb90c4 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -3790,10 +3790,17 @@ meta_window_move_between_rects (MetaWindow *window, int rel_x, rel_y; double scale_x, scale_y; - rel_x = window->unconstrained_rect.x - old_area->x; - rel_y = window->unconstrained_rect.y - old_area->y; - scale_x = (double)new_area->width / old_area->width; - scale_y = (double)new_area->height / old_area->height; + if (old_area) + { + rel_x = window->unconstrained_rect.x - old_area->x; + rel_y = window->unconstrained_rect.y - old_area->y; + scale_x = (double)new_area->width / old_area->width; + scale_y = (double)new_area->height / old_area->height; + } + else + { + rel_x = rel_y = scale_x = scale_y = 0; + } window->unconstrained_rect.x = new_area->x + rel_x * scale_x; window->unconstrained_rect.y = new_area->y + rel_y * scale_y; @@ -3847,9 +3854,6 @@ meta_window_move_to_monitor (MetaWindow *window, { MetaRectangle old_area, new_area; - if (monitor == window->monitor->number) - return; - meta_window_get_work_area_for_monitor (window, window->monitor->number, &old_area); @@ -3857,10 +3861,23 @@ meta_window_move_to_monitor (MetaWindow *window, monitor, &new_area); + if (window->unconstrained_rect.width == 0 || + window->unconstrained_rect.height == 0 || + !meta_rectangle_overlap (&window->unconstrained_rect, &old_area)) + { + meta_window_move_between_rects (window, NULL, &new_area); + } + else + { + if (monitor == window->monitor->number) + return; + + meta_window_move_between_rects (window, &old_area, &new_area); + } + if (window->tile_mode != META_TILE_NONE) window->tile_monitor_number = monitor; - meta_window_move_between_rects (window, &old_area, &new_area); window->preferred_output_winsys_id = window->monitor->winsys_id; if (window->fullscreen || window->override_redirect)