[mutter/wip/gbsneto/tiling-improvements: 33/37] window: Tile and resize considering the tile match
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/gbsneto/tiling-improvements: 33/37] window: Tile and resize considering the tile match
- Date: Wed, 16 Aug 2017 22:56:04 +0000 (UTC)
commit 7f22ae017d01f7bdc77afbe4a49819e61c9a7dd2
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Sun Jun 11 22:13:03 2017 -0300
window: Tile and resize considering the tile match
After the introduction of the possibility to resize tiled windows,
it is a sensible decision to make windows aware of their tiling
match. A tiling match is another window that is tiled in such a
way that is the complement of the current window.
The newly introduced behavior attepts to make tiling as smooth as
possible, with the following rules:
* Windows now compute their tile match when tiling and, if there's
a match, they automatically complement the sibling's width.
* Resizing a window with a sibling automatically resizes the sibling
too to be the complement of the window's width.
* It is not possible to resize below windows' minimum widths.
https://bugzilla.gnome.org/show_bug.cgi?id=645153
src/core/stack.c | 6 ++-
src/core/window-private.h | 4 +-
src/core/window.c | 111 +++++++++++++++++++++++++++++++++++++--------
3 files changed, 99 insertions(+), 22 deletions(-)
---
diff --git a/src/core/stack.c b/src/core/stack.c
index 5895b89..01fdc4b 100644
--- a/src/core/stack.c
+++ b/src/core/stack.c
@@ -267,7 +267,11 @@ meta_stack_update_window_tile_matches (MetaStack *stack,
tmp = windows;
while (tmp)
{
- meta_window_compute_tile_match ((MetaWindow *) tmp->data);
+ MetaWindow *window = tmp->data;
+
+ window->tile_match = meta_window_compute_tile_match (window,
+ window->tile_mode,
+ window->monitor->number);
tmp = tmp->next;
}
diff --git a/src/core/window-private.h b/src/core/window-private.h
index aa68ebe..c96ddc9 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -709,7 +709,9 @@ void meta_window_on_all_workspaces_changed (MetaWindow *window);
gboolean meta_window_should_attach_to_parent (MetaWindow *window);
gboolean meta_window_can_tile_side_by_side (MetaWindow *window);
-void meta_window_compute_tile_match (MetaWindow *window);
+MetaWindow* meta_window_compute_tile_match (MetaWindow *window,
+ MetaTileMode current_mode,
+ gint target_monitor);
gboolean meta_window_updates_are_frozen (MetaWindow *window);
diff --git a/src/core/window.c b/src/core/window.c
index c12a490..c689a97 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -2900,8 +2900,14 @@ meta_window_calculate_area_for_tile_mode (MetaWindow *window,
MetaRectangle *rect)
{
MetaRectangle monitor_area;
+ MetaWindow *tile_match;
gboolean was_tiled;
+ /* When tiling a window, the new matching tile window is not yet synchronized,
+ * so we must do that now manually. It is not necessary to recompute all windows'
+ * tile matches, just the current one */
+ tile_match = meta_window_compute_tile_match (window, mode, monitor_number);
+
meta_window_get_work_area_for_monitor (window, monitor_number, &monitor_area);
rect->x = monitor_area.x;
@@ -2910,17 +2916,24 @@ meta_window_calculate_area_for_tile_mode (MetaWindow *window,
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;
+ if (tile_match)
+ {
+ rect->width = monitor_area.width - tile_match->rect.width;
+ }
else
- /* Assume half of the work area of the current monitor */
- rect->width = monitor_area.width / 2;
+ {
+ 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)
@@ -2970,6 +2983,8 @@ meta_window_tile (MetaWindow *window,
monitor_number,
&new_rect);
+ window->tile_match = meta_window_compute_tile_match (window, mode, monitor_number);
+
/* Track the previous mode */
window->previous_tile_mode = window->tile_mode;
window->tile_mode = mode;
@@ -5925,6 +5940,56 @@ update_resize_timeout (gpointer data)
return FALSE;
}
+static inline gint
+opposite_gravity (guint gravity)
+{
+ return StaticGravity - gravity;
+}
+
+static void
+resize_tile_match (MetaWindow *window,
+ int gravity,
+ int *out_new_w)
+{
+ MetaRectangle work_area;
+ MetaWindow *tile_match;
+ int new_w;
+
+ if (!META_WINDOW_TILED_SIDE_BY_SIDE (window) || !window->tile_match)
+ return;
+
+ new_w = *out_new_w;
+ tile_match = window->tile_match;
+
+ /* Make sure the resize does not break minimum sizes */
+ new_w = MAX (new_w, window->size_hints.min_width);
+
+ meta_window_get_work_area_for_monitor (window, window->tile_monitor_number, &work_area);
+
+ if (tile_match)
+ {
+ guint tile_width;
+
+ /* If there's a tile match window, we have to make sure we're not resizing
+ * the tile match below its min width */
+ if (work_area.width - new_w < tile_match->size_hints.min_width)
+ new_w = work_area.width - tile_match->size_hints.min_width;
+
+ tile_width = work_area.width - new_w;
+
+ /* The tile match window's new width is stored in tile_rect.width directly */
+ meta_window_resize_frame_with_gravity (window->tile_match,
+ TRUE,
+ tile_width,
+ work_area.height,
+ opposite_gravity (gravity));
+ }
+
+ /* We can potentially change the new width, so make sure update_resize() always
+ * has the most recent value */
+ *out_new_w = new_w;
+}
+
static void
update_resize (MetaWindow *window,
gboolean snap,
@@ -6050,6 +6115,10 @@ update_resize (MetaWindow *window,
snap,
FALSE);
+ /* If the window has a tile match, we have to respect the match's minimum
+ * width. */
+ resize_tile_match (window, gravity, &new_w);
+
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
/* Store the latest resize time, if we actually resized. */
@@ -7460,8 +7529,10 @@ meta_window_get_tile_match (MetaWindow *window)
return window->tile_match;
}
-void
-meta_window_compute_tile_match (MetaWindow *window)
+MetaWindow *
+meta_window_compute_tile_match (MetaWindow *window,
+ MetaTileMode current_mode,
+ gint target_monitor)
{
MetaWindow *match;
MetaStack *stack;
@@ -7470,14 +7541,14 @@ meta_window_compute_tile_match (MetaWindow *window)
window->tile_match = NULL;
if (window->shaded || window->minimized)
- return;
+ return NULL;
- if (META_WINDOW_TILED_LEFT (window))
+ if (current_mode == META_TILE_LEFT)
match_tile_mode = META_TILE_RIGHT;
- else if (META_WINDOW_TILED_RIGHT (window))
+ else if (current_mode == META_TILE_RIGHT)
match_tile_mode = META_TILE_LEFT;
else
- return;
+ return NULL;
stack = window->screen->stack;
@@ -7488,7 +7559,7 @@ meta_window_compute_tile_match (MetaWindow *window)
if (!match->shaded &&
!match->minimized &&
match->tile_mode == match_tile_mode &&
- match->monitor == window->monitor &&
+ match->monitor->number == target_monitor &&
meta_window_get_workspace (match) == meta_window_get_workspace (window))
break;
}
@@ -7528,11 +7599,11 @@ meta_window_compute_tile_match (MetaWindow *window)
if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
meta_rectangle_overlap (&above_rect, &topmost_rect))
- return;
+ return NULL;
}
-
- window->tile_match = match;
}
+
+ return match;
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]