From 07c047190251e8e335119de8437ec09455cf3d58 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 24 Sep 2010 15:35:00 -0400 Subject: [PATCH] tiling: Add new "maximized" tile In addition to the existing side-by-side tiling modes, this commit adds a new "maximize" tiling mode. It allows the user to maximize their windows (in other words, tile with the edge panels) by dragging their window to the top edge of the monitor. https://bugzilla.gnome.org/show_bug.cgi?id=630548 --- src/core/screen.c | 26 +++++++++-- src/core/window-private.h | 3 +- src/core/window.c | 91 +++++++++++++++++++++++++++++++-------- 3 files changed, 98 insertions(+), 22 deletions(-) diff --git a/src/core/screen.c b/src/core/screen.c index c3a4f03c3..1dbd982fa 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -1758,6 +1758,7 @@ meta_screen_tile_preview_update_timeout (gpointer data) MetaScreen *screen = data; MetaWindow *window = screen->display->grab_window; gboolean composited = screen->display->compositor != NULL; + gboolean needs_preview = FALSE; screen->tile_preview_timeout_id = 0; @@ -1775,9 +1776,28 @@ meta_screen_tile_preview_update_timeout (gpointer data) create_serial); } - if (window - && !META_WINDOW_TILED_SIDE_BY_SIDE (window) - && window->tile_mode != META_TILE_NONE) + if (window) + { + switch (window->tile_mode) + { + case META_TILE_LEFT: + case META_TILE_RIGHT: + if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) + needs_preview = TRUE; + break; + + case META_TILE_MAXIMIZED: + if (!META_WINDOW_MAXIMIZED (window)) + needs_preview = TRUE; + break; + + default: + needs_preview = FALSE; + break; + } + } + + if (needs_preview) { MetaRectangle tile_rect; diff --git a/src/core/window-private.h b/src/core/window-private.h index cc8a3b308..0c6276e39 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -64,7 +64,8 @@ typedef enum { typedef enum { META_TILE_NONE, META_TILE_LEFT, - META_TILE_RIGHT + META_TILE_RIGHT, + META_TILE_MAXIMIZED } MetaTileMode; struct _MetaWindow diff --git a/src/core/window.c b/src/core/window.c index ec3dadd1a..f8d64e5cf 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -3187,11 +3187,18 @@ meta_window_is_fullscreen (MetaWindow *window) static 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; - meta_window_maximize_internal (window, META_MAXIMIZE_VERTICAL, NULL); + if (window->tile_mode == META_TILE_MAXIMIZED) + directions = META_MAXIMIZE_VERTICAL | META_MAXIMIZE_HORIZONTAL; + else + directions = META_MAXIMIZE_VERTICAL; + + meta_window_maximize_internal (window, directions, NULL); meta_screen_tile_preview_update (window->screen, FALSE); if (window->display->compositor) @@ -3249,6 +3256,18 @@ meta_window_can_tile_side_by_side (MetaWindow *window) tile_area.height >= window->size_hints.min_height; } +static gboolean +meta_window_can_tile_maximized (MetaWindow *window) +{ + if (!META_WINDOW_ALLOWS_RESIZE (window)) + return FALSE; + + if (!window->has_maximize_func) + return FALSE; + + return TRUE; +} + static void unmaximize_window_before_freeing (MetaWindow *window) { @@ -7799,14 +7818,13 @@ update_move (MetaWindow *window, shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) * DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; - if (meta_prefs_get_edge_tiling () && - meta_window_can_tile_side_by_side (window)) + if (meta_prefs_get_edge_tiling ()) { const MetaMonitorInfo *monitor; MetaRectangle work_area; - /* For tiling we are interested in the work area of the monitor where - * the pointer is located. + /* 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. * Also see comment in meta_window_get_current_tile_area() */ monitor = meta_screen_get_current_monitor (window->screen); @@ -7814,17 +7832,38 @@ update_move (MetaWindow *window, monitor->number, &work_area); - if (y >= monitor->rect.y && - y < (monitor->rect.y + monitor->rect.height)) + if (meta_window_can_tile_side_by_side (window)) { - /* check if cursor is near an edge of the work area */ - if (x >= monitor->rect.x && x < (work_area.x + shake_threshold)) - window->tile_mode = META_TILE_LEFT; - else if (x >= work_area.x + work_area.width - shake_threshold && - x < (monitor->rect.x + monitor->rect.width)) - window->tile_mode = META_TILE_RIGHT; - else - window->tile_mode = META_TILE_NONE; + if (y >= monitor->rect.y && + y < (monitor->rect.y + monitor->rect.height)) + { + /* check if cursor is near an edge of the work area */ + if (x >= monitor->rect.x && x < (work_area.x + shake_threshold)) + window->tile_mode = META_TILE_LEFT; + else if (x >= work_area.x + work_area.width - shake_threshold && + x < (monitor->rect.x + monitor->rect.width)) + window->tile_mode = META_TILE_RIGHT; + else + window->tile_mode = META_TILE_NONE; + } + } + + /* For maximized tiling we are interested in the outside top edge + * of the work area of the monitor where the pointer is located. + * + * 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. + */ + if (meta_window_can_tile_maximized (window)) + { + if (x >= monitor->rect.x && + x < (monitor->rect.x + monitor->rect.width)) + { + /* check if cursor is on the top edge of the monitor*/ + if (y >= monitor->rect.y && y < work_area.y) + window->tile_mode = META_TILE_MAXIMIZED; + } } } @@ -7872,12 +7911,13 @@ update_move (MetaWindow *window, * loose or it is still maximized (then move straight) */ else if ((window->shaken_loose || META_WINDOW_MAXIMIZED (window)) && - window->tile_mode == META_TILE_NONE) + 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 = meta_screen_get_monitor_for_window (window->screen, window); for (monitor = 0; monitor < window->screen->n_monitor_infos; monitor++) @@ -8372,6 +8412,22 @@ check_use_this_motion_notify (MetaWindow *window, } } +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; + case META_TILE_MAXIMIZED: + if (!META_WINDOW_MAXIMIZED (window)) + window->tile_mode = META_TILE_NONE; + break; + } +} + void meta_window_handle_mouse_grab_op_event (MetaWindow *window, XEvent *event) @@ -8464,8 +8520,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, * would break the ability to snap back to the tiled * state, so we wait until mouse release. */ - if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) - window->tile_mode = META_TILE_NONE; + update_tile_mode (window); } }