From ff34e518263024f57dbd64bd9f9780f183f7df2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Wed, 27 Sep 2017 14:37:57 +0200 Subject: [PATCH] window: Allow resizing of tiled windows Currently tiled windows are not resizable and their size is fixed to half the screen width. Adjust the code to work with fractions other than half, and allow users to adjust the split by dragging the window edge that is not constrained by a monitor edge. Follow-up patches will improve on that by resizing neighboring tiled windows by a shared edge, and making the functionality available to client-side decorated windows implementing the new edge constraints protocol. --- src/core/keybindings.c | 5 +++- src/core/window-private.h | 8 ++++- src/core/window.c | 62 ++++++++++++++++++++++++++++++++++++--- src/ui/frames.c | 7 +++-- 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/src/core/keybindings.c b/src/core/keybindings.c index ef36cff77..f2ef07697 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -2239,7 +2239,10 @@ process_mouse_move_resize_grab (MetaDisplay *display, if (window->shaken_loose || tile_mode == META_TILE_MAXIMIZED) meta_window_maximize (window, META_MAXIMIZE_BOTH); else if (tile_mode != META_TILE_NONE) - meta_window_tile (window, tile_mode); + meta_window_restore_tile (window, + tile_mode, + display->grab_initial_window_pos.width, + display->grab_initial_window_pos.height); else meta_window_move_resize_frame (display->grab_window, TRUE, diff --git a/src/core/window-private.h b/src/core/window-private.h index 443bcf4d8..a4b03eae5 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -207,6 +207,8 @@ struct _MetaWindow int tile_monitor_number; int preferred_output_winsys_id; + double tile_hfraction; + /* Whether we're shaded */ guint shaded : 1; @@ -557,7 +559,7 @@ 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))) @@ -579,6 +581,10 @@ void meta_window_queue (MetaWindow *window, guint queuebits); void meta_window_tile (MetaWindow *window, MetaTileMode mode); +void meta_window_restore_tile (MetaWindow *window, + MetaTileMode mode, + int width, + int height); void meta_window_maximize_internal (MetaWindow *window, MetaMaximizeFlags directions, MetaRectangle *saved_rect); diff --git a/src/core/window.c b/src/core/window.c index d4fb40456..09f6fd3d0 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -1017,6 +1017,7 @@ _meta_window_shared_new (MetaDisplay *display, window->on_all_workspaces_requested = FALSE; window->tile_mode = META_TILE_NONE; window->tile_monitor_number = -1; + window->tile_hfraction = -1.; window->shaded = FALSE; window->initially_iconic = FALSE; window->minimized = FALSE; @@ -2968,6 +2969,42 @@ meta_window_requested_dont_bypass_compositor (MetaWindow *window) return window->bypass_compositor == _NET_WM_BYPASS_COMPOSITOR_HINT_OFF; } +static void +meta_window_get_tile_fraction (MetaWindow *window, + MetaTileMode tile_mode, + double *fraction) +{ + if (tile_mode == META_TILE_NONE) + *fraction = -1.; + else if (tile_mode == META_TILE_MAXIMIZED) + *fraction = 1.; + else if (META_WINDOW_TILED_SIDE_BY_SIDE (window)) + { + if (window->tile_mode != tile_mode) + *fraction = 1. - window->tile_hfraction; + else + *fraction = window->tile_hfraction; + } + else + *fraction = .5; +} + +static void +meta_window_update_tile_fraction (MetaWindow *window, + int new_w, + int new_h) +{ + MetaRectangle work_area; + + if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) + return; + + meta_window_get_work_area_for_monitor (window, + window->tile_monitor_number, + &work_area); + window->tile_hfraction = (double)new_w / work_area.width; +} + void meta_window_tile (MetaWindow *window, MetaTileMode tile_mode) @@ -2975,6 +3012,7 @@ meta_window_tile (MetaWindow *window, MetaMaximizeFlags directions; MetaRectangle old_frame_rect, old_buffer_rect; + meta_window_get_tile_fraction (window, tile_mode, &window->tile_hfraction); window->tile_mode = tile_mode; /* Don't do anything if no tiling is requested */ @@ -3007,6 +3045,16 @@ meta_window_tile (MetaWindow *window, meta_frame_queue_draw (window->frame); } +void +meta_window_restore_tile (MetaWindow *window, + MetaTileMode mode, + int width, + int height) +{ + meta_window_update_tile_fraction (window, width, height); + meta_window_tile (window, mode); +} + static gboolean meta_window_can_tile_maximized (MetaWindow *window) { @@ -4026,6 +4074,9 @@ meta_window_resize_frame_with_gravity (MetaWindow *window, rect.width = w; rect.height = h; + if (user_op) + meta_window_update_tile_fraction (window, w, h); + flags = (user_op ? META_MOVE_RESIZE_USER_ACTION : 0) | META_MOVE_RESIZE_RESIZE_ACTION; meta_window_move_resize_internal (window, flags, gravity, rect); } @@ -6349,19 +6400,22 @@ meta_window_get_tile_area (MetaWindow *window, MetaTileMode tile_mode, MetaRectangle *tile_area) { + MetaRectangle work_area; int tile_monitor_number; + double fraction; g_return_if_fail (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); + meta_window_get_work_area_for_monitor (window, tile_monitor_number, &work_area); + meta_window_get_tile_fraction (window, tile_mode, &fraction); - if (tile_mode == META_TILE_LEFT || tile_mode == META_TILE_RIGHT) - tile_area->width /= 2; + *tile_area = work_area; + tile_area->width = round (tile_area->width * fraction); if (tile_mode == META_TILE_RIGHT) - tile_area->x += tile_area->width; + tile_area->x += work_area.width - tile_area->width; } gboolean diff --git a/src/ui/frames.c b/src/ui/frames.c index 2d862545b..129a9e59b 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; }