Revert "window: Remove old tiling code"

This reverts commit 8bded7d497.
This commit is contained in:
Florian Müllner
2016-01-10 15:16:09 +01:00
parent 3aea8d8ce6
commit 46eb682c83
12 changed files with 530 additions and 31 deletions

View File

@@ -898,6 +898,8 @@ _meta_window_shared_new (MetaDisplay *display,
window->require_titlebar_visible = TRUE;
window->on_all_workspaces = FALSE;
window->on_all_workspaces_requested = FALSE;
window->tile_mode = META_TILE_NONE;
window->tile_monitor_number = -1;
window->shaded = FALSE;
window->initially_iconic = FALSE;
window->minimized = FALSE;
@@ -994,6 +996,8 @@ _meta_window_shared_new (MetaDisplay *display,
window);
window->preferred_output_winsys_id = window->monitor->winsys_id;
window->tile_match = NULL;
/* Assign this #MetaWindow a sequence number which can be used
* for sorting.
*/
@@ -2609,7 +2613,7 @@ ensure_size_hints_satisfied (MetaRectangle *rect,
static void
meta_window_save_rect (MetaWindow *window)
{
if (!(META_WINDOW_MAXIMIZED (window) || window->fullscreen))
if (!(META_WINDOW_MAXIMIZED (window) || META_WINDOW_TILED_SIDE_BY_SIDE (window) || window->fullscreen))
{
/* save size/pos as appropriate args for move_resize */
if (!window->maximized_horizontally)
@@ -2648,6 +2652,9 @@ meta_window_maximize_internal (MetaWindow *window,
else
meta_window_save_rect (window);
if (maximize_horizontally && maximize_vertically)
window->saved_maximize = TRUE;
window->maximized_horizontally =
window->maximized_horizontally || maximize_horizontally;
window->maximized_vertically =
@@ -2669,6 +2676,7 @@ void
meta_window_maximize (MetaWindow *window,
MetaMaximizeFlags directions)
{
MetaRectangle *saved_rect = NULL;
gboolean maximize_horizontally, maximize_vertically;
g_return_if_fail (!window->override_redirect);
@@ -2707,7 +2715,17 @@ meta_window_maximize (MetaWindow *window,
return;
}
meta_window_maximize_internal (window, directions, NULL);
if (window->tile_mode != META_TILE_NONE)
{
saved_rect = &window->saved_rect;
window->maximized_vertically = FALSE;
window->tile_mode = META_TILE_NONE;
}
meta_window_maximize_internal (window,
directions,
saved_rect);
MetaRectangle old_frame_rect, old_buffer_rect, new_rect;
@@ -2881,6 +2899,29 @@ meta_window_requested_dont_bypass_compositor (MetaWindow *window)
return window->bypass_compositor == _NET_WM_BYPASS_COMPOSITOR_HINT_OFF;
}
void
meta_window_tile (MetaWindow *window)
{
MetaMaximizeFlags directions;
/* Don't do anything if no tiling is requested */
if (window->tile_mode == META_TILE_NONE)
return;
if (window->tile_mode == META_TILE_MAXIMIZED)
directions = META_MAXIMIZE_BOTH;
else
directions = META_MAXIMIZE_VERTICAL;
meta_window_maximize_internal (window, directions, NULL);
meta_screen_update_tile_preview (window->screen, FALSE);
meta_window_move_resize_now (window);
if (window->frame)
meta_frame_queue_draw (window->frame);
}
static gboolean
meta_window_can_tile_maximized (MetaWindow *window)
{
@@ -2958,6 +2999,9 @@ meta_window_unmaximize (MetaWindow *window,
unmaximize_vertically = directions & META_MAXIMIZE_VERTICAL;
g_assert (unmaximize_horizontally || unmaximize_vertically);
if (unmaximize_horizontally && unmaximize_vertically)
window->saved_maximize = FALSE;
/* Only do something if the window isn't already maximized in the
* given direction(s).
*/
@@ -3511,6 +3555,9 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
if (!new)
new = &window->screen->monitor_infos[window->screen->primary_monitor_index];
if (window->tile_mode != META_TILE_NONE)
window->tile_monitor_number = new->number;
/* This will eventually reach meta_window_update_monitor that
* will send leave/enter-monitor events. The old != new monitor
* check will always fail (due to the new monitor_infos set) so
@@ -3692,6 +3739,9 @@ meta_window_move_resize_internal (MetaWindow *window,
}
meta_window_foreach_transient (window, maybe_move_attached_dialog, NULL);
meta_stack_update_window_tile_matches (window->screen->stack,
window->screen->active_workspace);
}
/**
@@ -3796,6 +3846,9 @@ meta_window_move_to_monitor (MetaWindow *window,
monitor,
&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;
@@ -5512,12 +5565,65 @@ update_move (MetaWindow *window,
shake_threshold = meta_prefs_get_drag_threshold () *
DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR;
if (snap)
{
/* We don't want to tile while snapping. Also, clear any previous tile
request. */
window->tile_mode = META_TILE_NONE;
window->tile_monitor_number = -1;
}
else if (meta_prefs_get_edge_tiling () &&
!META_WINDOW_MAXIMIZED (window) &&
!META_WINDOW_TILED_SIDE_BY_SIDE (window))
{
const MetaMonitorInfo *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_screen_get_current_monitor_info_for_pos (window->screen, 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
* the threshold in the Y direction. Tiled windows can also be pulled
* loose via X motion.
*/
if ((META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold))
if ((META_WINDOW_MAXIMIZED (window) && ABS (dy) >= shake_threshold) ||
(META_WINDOW_TILED_SIDE_BY_SIDE (window) && (MAX (ABS (dx), ABS (dy)) >= shake_threshold)))
{
double prop;
@@ -5526,6 +5632,7 @@ update_move (MetaWindow *window,
* is enabled, as top edge tiling can be used in that case
*/
window->shaken_loose = !meta_prefs_get_edge_tiling ();
window->tile_mode = META_TILE_NONE;
/* move the unmaximized window to the cursor */
prop =
@@ -5554,12 +5661,14 @@ update_move (MetaWindow *window,
/* remaximize window on another monitor if window has been shaken
* loose or it is still maximized (then move straight)
*/
else if (window->shaken_loose || META_WINDOW_MAXIMIZED (window))
else if ((window->shaken_loose || META_WINDOW_MAXIMIZED (window)) &&
window->tile_mode != META_TILE_LEFT && window->tile_mode != META_TILE_RIGHT)
{
const MetaMonitorInfo *wmonitor;
MetaRectangle work_area;
int monitor;
window->tile_mode = META_TILE_NONE;
wmonitor = window->monitor;
for (monitor = 0; monitor < window->screen->n_monitor_infos; monitor++)
@@ -5604,10 +5713,17 @@ update_move (MetaWindow *window,
}
}
/* Delay showing the tile preview slightly to make it more unlikely to
* trigger it unwittingly, e.g. when shaking loose the window or moving
* it to another monitor.
*/
meta_screen_update_tile_preview (window->screen,
window->tile_mode != META_TILE_NONE);
meta_window_get_frame_rect (window, &old);
/* Don't allow movement in the maximized directions */
if (window->maximized_horizontally)
/* Don't allow movement in the maximized directions or while tiled */
if (window->maximized_horizontally || META_WINDOW_TILED_SIDE_BY_SIDE (window))
new_x = old.x;
if (window->maximized_vertically)
new_y = old.y;
@@ -5768,6 +5884,23 @@ update_resize (MetaWindow *window,
g_get_current_time (&window->display->grab_last_moveresize_time);
}
static void
update_tile_mode (MetaWindow *window)
{
switch (window->tile_mode)
{
case META_TILE_LEFT:
case META_TILE_RIGHT:
if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
window->tile_mode = META_TILE_NONE;
break;
case META_TILE_MAXIMIZED:
if (!META_WINDOW_MAXIMIZED (window))
window->tile_mode = META_TILE_NONE;
break;
}
}
void
meta_window_update_resize (MetaWindow *window,
gboolean snap,
@@ -5798,9 +5931,12 @@ end_grab_op (MetaWindow *window,
{
if (meta_grab_op_is_moving (window->display->grab_op))
{
update_move (window,
modifiers & CLUTTER_SHIFT_MASK,
x, y);
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else
update_move (window,
modifiers & CLUTTER_SHIFT_MASK,
x, y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
@@ -5808,6 +5944,15 @@ end_grab_op (MetaWindow *window,
modifiers & CLUTTER_SHIFT_MASK,
x, y,
TRUE);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
}
}
meta_display_end_grab_op (window->display, clutter_event_get_time (event));
@@ -5992,6 +6137,40 @@ meta_window_get_work_area_all_monitors (MetaWindow *window,
window->desc, area->x, area->y, area->width, area->height);
}
int
meta_window_get_current_tile_monitor_number (MetaWindow *window)
{
int tile_monitor_number = window->tile_monitor_number;
if (tile_monitor_number < 0)
{
meta_warning ("%s called with an invalid monitor number; using 0 instead\n", G_STRFUNC);
tile_monitor_number = 0;
}
return tile_monitor_number;
}
void
meta_window_get_current_tile_area (MetaWindow *window,
MetaRectangle *tile_area)
{
int tile_monitor_number;
g_return_if_fail (window->tile_mode != META_TILE_NONE);
tile_monitor_number = meta_window_get_current_tile_monitor_number (window);
meta_window_get_work_area_for_monitor (window, tile_monitor_number, tile_area);
if (window->tile_mode == META_TILE_LEFT ||
window->tile_mode == META_TILE_RIGHT)
tile_area->width /= 2;
if (window->tile_mode == META_TILE_RIGHT)
tile_area->x += tile_area->width;
}
gboolean
meta_window_same_application (MetaWindow *window,
MetaWindow *other_window)
@@ -6995,7 +7174,8 @@ meta_window_get_frame_type (MetaWindow *window)
return META_FRAME_TYPE_LAST;
}
else if (window->border_only ||
(window->hide_titlebar_when_maximized && META_WINDOW_MAXIMIZED (window)))
(window->hide_titlebar_when_maximized && META_WINDOW_MAXIMIZED (window)) ||
(window->hide_titlebar_when_maximized && META_WINDOW_TILED_SIDE_BY_SIDE (window)))
{
/* override base frame type */
return META_FRAME_TYPE_BORDER;
@@ -7044,6 +7224,103 @@ meta_window_is_attached_dialog (MetaWindow *window)
return window->attached;
}
/**
* meta_window_get_tile_match:
* @window: a #MetaWindow
*
* Returns the matching tiled window on the same monitor as @window. This is
* the topmost tiled window in a complementary tile mode that is:
*
* - on the same monitor;
* - on the same workspace;
* - spanning the remaining monitor width;
* - there is no 3rd window stacked between both tiled windows that's
* partially visible in the common edge.
*
* Return value: (transfer none) (nullable): the matching tiled window or
* %NULL if it doesn't exist.
*/
MetaWindow *
meta_window_get_tile_match (MetaWindow *window)
{
return window->tile_match;
}
void
meta_window_compute_tile_match (MetaWindow *window)
{
MetaWindow *match;
MetaStack *stack;
MetaTileMode match_tile_mode = META_TILE_NONE;
window->tile_match = NULL;
if (window->shaded || window->minimized)
return;
if (META_WINDOW_TILED_LEFT (window))
match_tile_mode = META_TILE_RIGHT;
else if (META_WINDOW_TILED_RIGHT (window))
match_tile_mode = META_TILE_LEFT;
else
return;
stack = window->screen->stack;
for (match = meta_stack_get_top (stack);
match;
match = meta_stack_get_below (stack, match, FALSE))
{
if (!match->shaded &&
!match->minimized &&
match->tile_mode == match_tile_mode &&
match->monitor == window->monitor &&
meta_window_get_workspace (match) == meta_window_get_workspace (window))
break;
}
if (match)
{
MetaWindow *above, *bottommost, *topmost;
MetaRectangle above_rect, bottommost_rect, topmost_rect;
if (meta_stack_windows_cmp (window->screen->stack, match, window) > 0)
{
topmost = match;
bottommost = window;
}
else
{
topmost = window;
bottommost = match;
}
meta_window_get_frame_rect (bottommost, &bottommost_rect);
meta_window_get_frame_rect (topmost, &topmost_rect);
/*
* If there's a window stacked in between which is partially visible
* behind the topmost tile we don't consider the tiles to match.
*/
for (above = meta_stack_get_above (stack, bottommost, FALSE);
above && above != topmost;
above = meta_stack_get_above (stack, above, FALSE))
{
if (above->minimized ||
above->monitor != window->monitor ||
meta_window_get_workspace (above) != meta_window_get_workspace (window))
continue;
meta_window_get_frame_rect (above, &above_rect);
if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
meta_rectangle_overlap (&above_rect, &topmost_rect))
return;
}
window->tile_match = match;
}
}
void
meta_window_set_title (MetaWindow *window,
const char *title)