[mutter/wip/gbsneto/edge-constraints: 35/45] window: Allow tiled windows be resized
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/gbsneto/edge-constraints: 35/45] window: Allow tiled windows be resized
- Date: Thu, 24 Aug 2017 17:29:05 +0000 (UTC)
commit 9ee09d0730e95afbf7af009c0df415524de202b5
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Sun Jun 11 14:58:21 2017 -0300
window: Allow tiled windows be resized
The current code forbids resizing tiled windows, and enforces that
side-by-side tiled windows cover half of the current screen's width.
This patch removes this restriction, and adds code to track the
tiled window size isolated from the actual window size, using the
following heuristics:
* If the window was not tiled, cover 1/2 of the screen.
* If the window was tiled, use the complement of the current width
to cover the "hole" in the screen.
* When resizing a tiled window to the oposite border, maximize the
window.
Windows with client-side decoration does not follow this behavior
for the moment, and patches for GTK+ shall be crafted to fix this
in the client side.
To make the current code work with the tile constraint, the constraint
had to ignore the width and x positions of the window, because now
these axis are not constrained.
Long term, the best way to handle it is using constrained edges rather
than tile modes themselves. Constrained edges are more generic and
are better suited to the future quarter tiling. With constrained edges,
we can isolate the tiling logic from the CSD implementations.
https://bugzilla.gnome.org/show_bug.cgi?id=645153
src/core/constraints.c | 14 +++-
src/core/keybindings.c | 32 ++++++--
src/core/screen.c | 13 +++-
src/core/window-private.h | 24 +++++-
src/core/window.c | 178 +++++++++++++++++++++++++++++++++------------
src/ui/frames.c | 7 +-
6 files changed, 203 insertions(+), 65 deletions(-)
---
diff --git a/src/core/constraints.c b/src/core/constraints.c
index 14044a9..1fa572d 100644
--- a/src/core/constraints.c
+++ b/src/core/constraints.c
@@ -943,7 +943,11 @@ constrain_maximization (MetaWindow *window,
/* Calculate target_size = maximized size of (window + frame) */
if (META_WINDOW_TILED_MAXIMIZED (window))
{
- meta_window_get_current_tile_area (window, &target_size);
+ meta_window_get_tile_area_for_mode (window,
+ META_TILE_MAXIMIZED,
+ window->tile_mode,
+ window->monitor->number,
+ &target_size);
}
else if (META_WINDOW_MAXIMIZED (window))
{
@@ -1030,7 +1034,11 @@ constrain_tiling (MetaWindow *window,
/* Calculate target_size - as the tile previews need this as well, we
* use an external function for the actual calculation
*/
- meta_window_get_current_tile_area (window, &target_size);
+ meta_window_get_tile_area_for_mode (window,
+ window->tile_mode,
+ window->tile_mode,
+ window->tile_monitor_number,
+ &target_size);
/* Check min size constraints; max size constraints are ignored as for
* maximized windows.
@@ -1051,8 +1059,6 @@ constrain_tiling (MetaWindow *window,
return constraint_already_satisfied;
/*** Enforce constraint ***/
- info->current.x = target_size.x;
- info->current.width = target_size.width;
info->current.y = target_size.y;
info->current.height = target_size.height;
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 26c7817..e76dae2 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -2045,12 +2045,15 @@ process_mouse_move_resize_grab (MetaDisplay *display,
if (event->keyval == CLUTTER_KEY_Escape)
{
+ MetaTileMode mode;
+
+ mode = display->grab_tile_mode;
+
/* Hide the tiling preview if necessary */
- if (window->tile_mode != META_TILE_NONE)
+ if (window->preview_tile_mode != META_TILE_NONE)
meta_screen_hide_tile_preview (screen);
/* Restore the original tile mode */
- window->tile_mode = display->grab_tile_mode;
window->tile_monitor_number = display->grab_tile_monitor_number;
/* End move or resize and restore to original state. If the
@@ -2058,10 +2061,24 @@ process_mouse_move_resize_grab (MetaDisplay *display,
* need to remaximize it. In normal cases, we need to do a
* moveresize now to get the position back to the original.
*/
- if (window->shaken_loose || window->tile_mode == META_TILE_MAXIMIZED)
+ if (window->shaken_loose || mode == META_TILE_MAXIMIZED)
meta_window_maximize (window, META_MAXIMIZE_BOTH);
- else if (window->tile_mode != META_TILE_NONE)
- meta_window_tile (window);
+ else if (mode != META_TILE_NONE)
+ {
+ /* If the window is tiled, the user resizes it and cancels, calling
+ * meta_window_tile() would break the window position. Thus, if the
+ * window was tiled and continues to be tiled, just resize it to the
+ * previous position and size.
+ */
+ if (window->tile_mode != mode)
+ meta_window_tile (window, mode);
+ else
+ meta_window_update_resize (window,
+ FALSE,
+ display->grab_initial_window_pos.x,
+ display->grab_initial_window_pos.y,
+ TRUE);
+ }
else
meta_window_move_resize_frame (display->grab_window,
TRUE,
@@ -2997,6 +3014,7 @@ handle_toggle_tiled (MetaDisplay *display,
{
window->tile_monitor_number = window->saved_maximize ? window->monitor->number
: -1;
+ window->previous_tile_mode = window->tile_mode;
window->tile_mode = window->saved_maximize ? META_TILE_MAXIMIZED
: META_TILE_NONE;
@@ -3008,7 +3026,7 @@ handle_toggle_tiled (MetaDisplay *display,
else if (meta_window_can_tile_side_by_side (window))
{
window->tile_monitor_number = window->monitor->number;
- window->tile_mode = mode;
+
/* Maximization constraints beat tiling constraints, so if the window
* is maximized, tiling won't have any effect unless we unmaximize it
* horizontally first; rather than calling meta_window_unmaximize(),
@@ -3016,7 +3034,7 @@ handle_toggle_tiled (MetaDisplay *display,
* save an additional roundtrip.
*/
window->maximized_horizontally = FALSE;
- meta_window_tile (window);
+ meta_window_tile (window, mode);
}
}
diff --git a/src/core/screen.c b/src/core/screen.c
index 503c201..155f1ff 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -1410,7 +1410,7 @@ meta_screen_update_tile_preview_timeout (gpointer data)
if (window)
{
- switch (window->tile_mode)
+ switch (window->preview_tile_mode)
{
case META_TILE_LEFT:
case META_TILE_RIGHT:
@@ -1435,7 +1435,11 @@ meta_screen_update_tile_preview_timeout (gpointer data)
int monitor;
monitor = meta_window_get_current_tile_monitor_number (window);
- meta_window_get_current_tile_area (window, &tile_rect);
+ meta_window_get_tile_area_for_mode (window,
+ window->preview_tile_mode,
+ window->tile_mode,
+ monitor,
+ &tile_rect);
meta_compositor_show_tile_preview (screen->display->compositor,
window, &tile_rect, monitor);
}
@@ -1475,10 +1479,15 @@ meta_screen_update_tile_preview (MetaScreen *screen,
void
meta_screen_hide_tile_preview (MetaScreen *screen)
{
+ MetaWindow *window = screen->display->grab_window;
+
if (screen->tile_preview_timeout_id > 0)
g_source_remove (screen->tile_preview_timeout_id);
meta_compositor_hide_tile_preview (screen->display->compositor);
+
+ if (window)
+ window->preview_tile_mode = META_TILE_NONE;
}
MetaWindow*
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 521682d..aa68ebe 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -207,6 +207,12 @@ struct _MetaWindow
* that to toggle between normal/tiled or maximized/tiled states. */
guint saved_maximize : 1;
int tile_monitor_number;
+
+ /* Keep track of the previous tile mode so when changing between left and
+ * right tiles we can resize the window with the complementary width */
+ guint previous_tile_mode : 2;
+ guint preview_tile_mode : 2;
+
int preferred_output_winsys_id;
/* Whether we're shaded */
@@ -559,12 +565,20 @@ struct _MetaWindowClass
#define META_WINDOW_TILED_MAXIMIZED(w)(META_WINDOW_MAXIMIZED(w) && \
(w)->tile_mode == META_TILE_MAXIMIZED)
#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen)
-#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) &&
!META_WINDOW_TILED_SIDE_BY_SIDE(w) && !(w)->fullscreen && !(w)->shaded)
+#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) &&
!(w)->fullscreen && !(w)->shaded)
#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \
(((w)->size_hints.min_width < (w)->size_hints.max_width) || \
((w)->size_hints.min_height < (w)->size_hints.max_height)))
#define META_WINDOW_ALLOWS_HORIZONTAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) &&
(w)->size_hints.min_width < (w)->size_hints.max_width)
#define META_WINDOW_ALLOWS_VERTICAL_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) &&
(w)->size_hints.min_height < (w)->size_hints.max_height)
+#define META_WINDOW_TILED_LEFT_RESIZING(w) \
+ ((w)->tile_mode == META_TILE_LEFT && \
+ ((w)->display->grab_op == META_GRAB_OP_RESIZING_E || \
+ (w)->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_E))
+#define META_WINDOW_TILED_RIGHT_RESIZING(w) \
+ ((w)->tile_mode == META_TILE_RIGHT && \
+ ((w)->display->grab_op == META_GRAB_OP_RESIZING_W || \
+ (w)->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_W))
MetaWindow * _meta_window_shared_new (MetaDisplay *display,
MetaScreen *screen,
@@ -579,7 +593,8 @@ void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_queue (MetaWindow *window,
guint queuebits);
-void meta_window_tile (MetaWindow *window);
+void meta_window_tile (MetaWindow *window,
+ MetaTileMode mode);
void meta_window_maximize_internal (MetaWindow *window,
MetaMaximizeFlags directions,
MetaRectangle *saved_rect);
@@ -648,7 +663,10 @@ void meta_window_get_work_area_for_logical_monitor (MetaWindow *window,
MetaRectangle *area);
int meta_window_get_current_tile_monitor_number (MetaWindow *window);
-void meta_window_get_current_tile_area (MetaWindow *window,
+void meta_window_get_tile_area_for_mode (MetaWindow *window,
+ MetaTileMode mode,
+ MetaTileMode previous_mode,
+ guint monitor_number,
MetaRectangle *tile_area);
diff --git a/src/core/window.c b/src/core/window.c
index ec3083f..c12a490 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -2726,6 +2726,12 @@ meta_window_maximize (MetaWindow *window,
meta_window_unshade (window, timestamp);
}
+ if (maximize_vertically && maximize_horizontally)
+ {
+ window->previous_tile_mode = window->tile_mode;
+ window->tile_mode = META_TILE_MAXIMIZED;
+ }
+
/* if the window hasn't been placed yet, we'll maximize it then
*/
if (!window->placed)
@@ -2886,24 +2892,88 @@ meta_window_requested_dont_bypass_compositor (MetaWindow *window)
return window->bypass_compositor == _NET_WM_BYPASS_COMPOSITOR_HINT_OFF;
}
+static void
+meta_window_calculate_area_for_tile_mode (MetaWindow *window,
+ MetaTileMode mode,
+ MetaTileMode previous_mode,
+ gint monitor_number,
+ MetaRectangle *rect)
+{
+ MetaRectangle monitor_area;
+ gboolean was_tiled;
+
+ meta_window_get_work_area_for_monitor (window, monitor_number, &monitor_area);
+
+ rect->x = monitor_area.x;
+ rect->y = monitor_area.y;
+ rect->height = monitor_area.height;
+
+ was_tiled = previous_mode == META_TILE_LEFT || previous_mode == META_TILE_RIGHT;
+
+ if (mode == META_TILE_MAXIMIZED)
+ /* When maximized, cover the entire width */
+ rect->width = monitor_area.width;
+ else if (mode == previous_mode)
+ /* When retrieving the size of the current tile mode, just use the current size */
+ rect->width = window->rect.width;
+ else if (was_tiled && (mode == META_TILE_LEFT || mode == META_TILE_RIGHT))
+ rect->width = monitor_area.width - window->rect.width;
+ else
+ /* Assume half of the work area of the current monitor */
+ rect->width = monitor_area.width / 2;
+
+ /* Update the horizontal position */
+ if (mode == META_TILE_RIGHT)
+ rect->x = monitor_area.x + monitor_area.width - rect->width;
+}
+
void
-meta_window_tile (MetaWindow *window)
+meta_window_tile (MetaWindow *window,
+ MetaTileMode mode)
{
MetaMaximizeFlags directions;
MetaRectangle old_frame_rect, old_buffer_rect;
+ MetaRectangle new_rect;
+ gint monitor_number;
- /* Don't do anything if no tiling is requested */
- if (window->tile_mode == META_TILE_NONE)
+ if (mode == window->tile_mode)
return;
- if (window->tile_mode == META_TILE_MAXIMIZED)
+ /* Don't do anything if no tiling is requested */
+ if (mode == META_TILE_NONE)
+ {
+ window->previous_tile_mode = window->tile_mode;
+ window->tile_mode = mode;
+ return;
+ }
+
+ if (mode == META_TILE_MAXIMIZED)
directions = META_MAXIMIZE_BOTH;
else
directions = META_MAXIMIZE_VERTICAL;
+ /* When moving the window around, we want to use the tile monitor
+ * number; otherwise, the current monitor number */
+ if (window->tile_monitor_number != -1)
+ monitor_number = window->tile_monitor_number;
+ else
+ monitor_number = window->monitor->number;
+
meta_window_maximize_internal (window, directions, NULL);
meta_screen_update_tile_preview (window->screen, FALSE);
+ /* Calculate the new area before updating the tile mode, so that the window is still
+ * able to track which is the current and the next tile mode */
+ meta_window_calculate_area_for_tile_mode (window,
+ mode,
+ window->tile_mode,
+ monitor_number,
+ &new_rect);
+
+ /* Track the previous mode */
+ window->previous_tile_mode = window->tile_mode;
+ window->tile_mode = mode;
+
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_rect);
@@ -2916,7 +2986,7 @@ meta_window_tile (MetaWindow *window)
META_MOVE_RESIZE_RESIZE_ACTION |
META_MOVE_RESIZE_STATE_CHANGED),
NorthWestGravity,
- window->unconstrained_rect);
+ new_rect);
if (window->frame)
meta_frame_queue_draw (window->frame);
@@ -3020,6 +3090,12 @@ meta_window_unmaximize (MetaWindow *window,
meta_window_get_frame_rect (window, &old_frame_rect);
meta_window_get_buffer_rect (window, &old_buffer_rect);
+ if (unmaximize_vertically)
+ {
+ window->previous_tile_mode = window->tile_mode;
+ window->tile_mode = META_TILE_NONE;
+ }
+
meta_topic (META_DEBUG_WINDOW_OPS,
"Unmaximizing %s%s\n",
window->desc,
@@ -3886,6 +3962,9 @@ meta_window_move_to_monitor (MetaWindow *window,
monitor,
&new_area);
+ if (window->tile_mode != META_TILE_NONE)
+ window->tile_monitor_number = monitor;
+
if (window->unconstrained_rect.width == 0 ||
window->unconstrained_rect.height == 0 ||
!meta_rectangle_overlap (&window->unconstrained_rect, &old_area))
@@ -3900,9 +3979,6 @@ meta_window_move_to_monitor (MetaWindow *window,
meta_window_move_between_rects (window, &old_area, &new_area);
}
- if (window->tile_mode != META_TILE_NONE)
- window->tile_monitor_number = monitor;
-
window->preferred_output_winsys_id = window->monitor->winsys_id;
if (window->fullscreen || window->override_redirect)
@@ -5631,22 +5707,22 @@ update_move_maybe_tile (MetaWindow *window,
&work_area);
/* Check if the cursor is in a position which triggers tiling
- * and set tile_mode accordingly.
+ * and set preview_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;
+ window->preview_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;
+ window->preview_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;
+ window->preview_tile_mode = META_TILE_MAXIMIZED;
else
- window->tile_mode = META_TILE_NONE;
+ window->preview_tile_mode = META_TILE_NONE;
- if (window->tile_mode != META_TILE_NONE)
+ if (window->preview_tile_mode != META_TILE_NONE)
window->tile_monitor_number = logical_monitor->number;
}
@@ -5698,7 +5774,7 @@ update_move (MetaWindow *window,
{
/* We don't want to tile while snapping. Also, clear any previous tile
request. */
- window->tile_mode = META_TILE_NONE;
+ window->preview_tile_mode = META_TILE_NONE;
window->tile_monitor_number = -1;
}
else if (meta_prefs_get_edge_tiling () &&
@@ -5815,7 +5891,7 @@ update_move (MetaWindow *window,
* it to another monitor.
*/
meta_screen_update_tile_preview (window->screen,
- window->tile_mode != META_TILE_NONE);
+ window->preview_tile_mode != META_TILE_NONE);
meta_window_get_frame_rect (window, &old);
@@ -5982,19 +6058,28 @@ update_resize (MetaWindow *window,
}
static void
-update_tile_mode (MetaWindow *window)
+update_tile_mode_after_resize (MetaWindow *window,
+ gint x,
+ gint y)
{
- switch (window->tile_mode)
+ const MetaLogicalMonitor *monitor;
+ MetaMonitorManager *monitor_manager;
+ MetaRectangle work_area;
+ MetaBackend *backend;
+ gint shake_threshold;
+
+ backend = meta_get_backend ();
+ shake_threshold = meta_prefs_get_drag_threshold ();
+ monitor_manager = meta_backend_get_monitor_manager (backend);
+ monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
+
+ meta_window_get_work_area_for_monitor (window, monitor->number, &work_area);
+
+ /* If the window is tiled and we reach the oposite edge, maximize the window */
+ if ((META_WINDOW_TILED_LEFT (window) && x >= work_area.x + work_area.width - shake_threshold) ||
+ (META_WINDOW_TILED_RIGHT (window) && x <= work_area.x + shake_threshold))
{
- 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;
+ meta_window_maximize (window, META_MAXIMIZE_BOTH);
}
}
@@ -6028,8 +6113,11 @@ end_grab_op (MetaWindow *window,
{
if (meta_grab_op_is_moving (window->display->grab_op))
{
- if (window->tile_mode != META_TILE_NONE)
- meta_window_tile (window);
+ if (window->preview_tile_mode != META_TILE_NONE)
+ {
+ meta_window_tile (window, window->preview_tile_mode);
+ meta_screen_hide_tile_preview (window->screen);
+ }
else
update_move (window,
modifiers & CLUTTER_SHIFT_MASK,
@@ -6049,7 +6137,7 @@ end_grab_op (MetaWindow *window,
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
- update_tile_mode (window);
+ update_tile_mode_after_resize (window, x, y);
}
}
meta_display_end_grab_op (window->display, clutter_event_get_time (event));
@@ -6255,23 +6343,19 @@ meta_window_get_current_tile_monitor_number (MetaWindow *window)
}
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;
+meta_window_get_tile_area_for_mode (MetaWindow *window,
+ MetaTileMode mode,
+ MetaTileMode previous_mode,
+ guint monitor_number,
+ MetaRectangle *tile_area)
+{
+ g_return_if_fail (mode != META_TILE_NONE);
+
+ meta_window_calculate_area_for_tile_mode (window,
+ mode,
+ previous_mode,
+ monitor_number,
+ tile_area);
}
gboolean
diff --git a/src/ui/frames.c b/src/ui/frames.c
index 2d86254..129a9e5 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -1621,6 +1621,9 @@ get_control (MetaUIFrame *frame, int root_x, int root_y)
has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0;
has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0;
+ if (flags & META_FRAME_TILED_LEFT || flags & META_FRAME_TILED_RIGHT)
+ has_vert = has_horiz = FALSE;
+
if (POINT_IN_RECT (x, y, fgeom.title_rect))
{
if (has_vert && y <= TOP_RESIZE_HEIGHT && has_north_resize)
@@ -1693,12 +1696,12 @@ get_control (MetaUIFrame *frame, int root_x, int root_y)
}
else if (x <= fgeom.borders.total.left)
{
- if (has_horiz)
+ if (has_horiz || flags & META_FRAME_TILED_RIGHT)
return META_FRAME_CONTROL_RESIZE_W;
}
else if (x >= (fgeom.width - fgeom.borders.total.right))
{
- if (has_horiz)
+ if (has_horiz || flags & META_FRAME_TILED_LEFT)
return META_FRAME_CONTROL_RESIZE_E;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]