window: Don't crash when moving across non-adjecent logical monitors

When moving a window between two non-adjecent logical monitors, don't
try to tile a window when the window position is outside of any logical
monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=783630
This commit is contained in:
Jonas Ådahl 2017-06-13 12:14:45 +08:00
parent 538e402d71
commit 7bd69f0b32

View File

@ -5592,6 +5592,60 @@ update_move_timeout (gpointer data)
return FALSE; return FALSE;
} }
static void
update_move_maybe_tile (MetaWindow *window,
int shake_threshold,
int x,
int y)
{
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaLogicalMonitor *logical_monitor;
MetaRectangle work_area;
/* For side-by-side tiling we are interested in the inside vertical
* edges of the work area of the monitor where the pointer is located,
* and in the outside top edge for maximized tiling.
*
* For maximized tiling we use the outside edge instead of the
* inside edge, because we don't want to force users to maximize
* windows they are placing near the top of their screens.
*
* The "current" idea of meta_window_get_work_area_current_monitor() and
* meta_screen_get_current_monitor() is slightly different: the former
* refers to the monitor which contains the largest part of the window,
* the latter to the one where the pointer is located.
*/
logical_monitor =
meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
if (!logical_monitor)
return;
meta_window_get_work_area_for_monitor (window,
logical_monitor->number,
&work_area);
/* Check if the cursor is in a position which triggers tiling
* and set tile_mode accordingly.
*/
if (meta_window_can_tile_side_by_side (window) &&
x >= logical_monitor->rect.x && x < (work_area.x + shake_threshold))
window->tile_mode = META_TILE_LEFT;
else if (meta_window_can_tile_side_by_side (window) &&
x >= work_area.x + work_area.width - shake_threshold &&
x < (logical_monitor->rect.x + logical_monitor->rect.width))
window->tile_mode = META_TILE_RIGHT;
else if (meta_window_can_tile_maximized (window) &&
y >= logical_monitor->rect.y && y <= work_area.y)
window->tile_mode = META_TILE_MAXIMIZED;
else
window->tile_mode = META_TILE_NONE;
if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = logical_monitor->number;
}
static void static void
update_move (MetaWindow *window, update_move (MetaWindow *window,
gboolean snap, gboolean snap,
@ -5647,49 +5701,7 @@ update_move (MetaWindow *window,
!META_WINDOW_MAXIMIZED (window) && !META_WINDOW_MAXIMIZED (window) &&
!META_WINDOW_TILED_SIDE_BY_SIDE (window)) !META_WINDOW_TILED_SIDE_BY_SIDE (window))
{ {
MetaBackend *backend = meta_get_backend (); update_move_maybe_tile (window, shake_threshold, x, y);
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
const MetaLogicalMonitor *monitor;
MetaRectangle work_area;
/* For side-by-side tiling we are interested in the inside vertical
* edges of the work area of the monitor where the pointer is located,
* and in the outside top edge for maximized tiling.
*
* For maximized tiling we use the outside edge instead of the
* inside edge, because we don't want to force users to maximize
* windows they are placing near the top of their screens.
*
* The "current" idea of meta_window_get_work_area_current_monitor() and
* meta_screen_get_current_monitor() is slightly different: the former
* refers to the monitor which contains the largest part of the window,
* the latter to the one where the pointer is located.
*/
monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager,
x, y);
meta_window_get_work_area_for_monitor (window,
monitor->number,
&work_area);
/* Check if the cursor is in a position which triggers tiling
* and set tile_mode accordingly.
*/
if (meta_window_can_tile_side_by_side (window) &&
x >= monitor->rect.x && x < (work_area.x + shake_threshold))
window->tile_mode = META_TILE_LEFT;
else if (meta_window_can_tile_side_by_side (window) &&
x >= work_area.x + work_area.width - shake_threshold &&
x < (monitor->rect.x + monitor->rect.width))
window->tile_mode = META_TILE_RIGHT;
else if (meta_window_can_tile_maximized (window) &&
y >= monitor->rect.y && y <= work_area.y)
window->tile_mode = META_TILE_MAXIMIZED;
else
window->tile_mode = META_TILE_NONE;
if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = monitor->number;
} }
/* shake loose (unmaximize) maximized or tiled window if dragged beyond /* shake loose (unmaximize) maximized or tiled window if dragged beyond