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
This commit is contained in:
Rui Matos 2016-11-15 14:10:05 +01:00
parent 1fe10f09d7
commit bb2e8ff09a

View File

@ -3790,10 +3790,17 @@ meta_window_move_between_rects (MetaWindow *window,
int rel_x, rel_y; int rel_x, rel_y;
double scale_x, scale_y; double scale_x, scale_y;
rel_x = window->unconstrained_rect.x - old_area->x; if (old_area)
rel_y = window->unconstrained_rect.y - old_area->y; {
scale_x = (double)new_area->width / old_area->width; rel_x = window->unconstrained_rect.x - old_area->x;
scale_y = (double)new_area->height / old_area->height; 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.x = new_area->x + rel_x * scale_x;
window->unconstrained_rect.y = new_area->y + rel_y * scale_y; 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; MetaRectangle old_area, new_area;
if (monitor == window->monitor->number)
return;
meta_window_get_work_area_for_monitor (window, meta_window_get_work_area_for_monitor (window,
window->monitor->number, window->monitor->number,
&old_area); &old_area);
@ -3857,10 +3861,23 @@ meta_window_move_to_monitor (MetaWindow *window,
monitor, monitor,
&new_area); &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) if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = monitor; window->tile_monitor_number = monitor;
meta_window_move_between_rects (window, &old_area, &new_area);
window->preferred_output_winsys_id = window->monitor->winsys_id; window->preferred_output_winsys_id = window->monitor->winsys_id;
if (window->fullscreen || window->override_redirect) if (window->fullscreen || window->override_redirect)