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); } }