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
This commit is contained in:
Ray Strode 2010-09-24 15:35:00 -04:00
parent 5f4ee1b6e7
commit 07c0471902
3 changed files with 98 additions and 22 deletions

View File

@ -1758,6 +1758,7 @@ meta_screen_tile_preview_update_timeout (gpointer data)
MetaScreen *screen = data; MetaScreen *screen = data;
MetaWindow *window = screen->display->grab_window; MetaWindow *window = screen->display->grab_window;
gboolean composited = screen->display->compositor != NULL; gboolean composited = screen->display->compositor != NULL;
gboolean needs_preview = FALSE;
screen->tile_preview_timeout_id = 0; screen->tile_preview_timeout_id = 0;
@ -1775,9 +1776,28 @@ meta_screen_tile_preview_update_timeout (gpointer data)
create_serial); create_serial);
} }
if (window if (window)
&& !META_WINDOW_TILED_SIDE_BY_SIDE (window) {
&& window->tile_mode != META_TILE_NONE) 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; MetaRectangle tile_rect;

View File

@ -64,7 +64,8 @@ typedef enum {
typedef enum { typedef enum {
META_TILE_NONE, META_TILE_NONE,
META_TILE_LEFT, META_TILE_LEFT,
META_TILE_RIGHT META_TILE_RIGHT,
META_TILE_MAXIMIZED
} MetaTileMode; } MetaTileMode;
struct _MetaWindow struct _MetaWindow

View File

@ -3187,11 +3187,18 @@ meta_window_is_fullscreen (MetaWindow *window)
static void static void
meta_window_tile (MetaWindow *window) meta_window_tile (MetaWindow *window)
{ {
MetaMaximizeFlags directions;
/* Don't do anything if no tiling is requested */ /* Don't do anything if no tiling is requested */
if (window->tile_mode == META_TILE_NONE) if (window->tile_mode == META_TILE_NONE)
return; 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); meta_screen_tile_preview_update (window->screen, FALSE);
if (window->display->compositor) 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; 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 static void
unmaximize_window_before_freeing (MetaWindow *window) unmaximize_window_before_freeing (MetaWindow *window)
{ {
@ -7799,14 +7818,13 @@ update_move (MetaWindow *window,
shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) * shake_threshold = meta_ui_get_drag_threshold (window->screen->ui) *
DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR;
if (meta_prefs_get_edge_tiling () && if (meta_prefs_get_edge_tiling ())
meta_window_can_tile_side_by_side (window))
{ {
const MetaMonitorInfo *monitor; const MetaMonitorInfo *monitor;
MetaRectangle work_area; MetaRectangle work_area;
/* For tiling we are interested in the work area of the monitor where /* For side-by-side tiling we are interested in the inside vertical
* the pointer is located. * edges of the work area of the monitor where the pointer is located.
* Also see comment in meta_window_get_current_tile_area() * Also see comment in meta_window_get_current_tile_area()
*/ */
monitor = meta_screen_get_current_monitor (window->screen); monitor = meta_screen_get_current_monitor (window->screen);
@ -7814,17 +7832,38 @@ update_move (MetaWindow *window,
monitor->number, monitor->number,
&work_area); &work_area);
if (y >= monitor->rect.y && if (meta_window_can_tile_side_by_side (window))
y < (monitor->rect.y + monitor->rect.height))
{ {
/* check if cursor is near an edge of the work area */ if (y >= monitor->rect.y &&
if (x >= monitor->rect.x && x < (work_area.x + shake_threshold)) y < (monitor->rect.y + monitor->rect.height))
window->tile_mode = META_TILE_LEFT; {
else if (x >= work_area.x + work_area.width - shake_threshold && /* check if cursor is near an edge of the work area */
x < (monitor->rect.x + monitor->rect.width)) if (x >= monitor->rect.x && x < (work_area.x + shake_threshold))
window->tile_mode = META_TILE_RIGHT; window->tile_mode = META_TILE_LEFT;
else else if (x >= work_area.x + work_area.width - shake_threshold &&
window->tile_mode = META_TILE_NONE; 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) * loose or it is still maximized (then move straight)
*/ */
else if ((window->shaken_loose || META_WINDOW_MAXIMIZED (window)) && 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; const MetaMonitorInfo *wmonitor;
MetaRectangle work_area; MetaRectangle work_area;
int monitor; int monitor;
window->tile_mode = META_TILE_NONE;
wmonitor = meta_screen_get_monitor_for_window (window->screen, window); wmonitor = meta_screen_get_monitor_for_window (window->screen, window);
for (monitor = 0; monitor < window->screen->n_monitor_infos; monitor++) 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 void
meta_window_handle_mouse_grab_op_event (MetaWindow *window, meta_window_handle_mouse_grab_op_event (MetaWindow *window,
XEvent *event) 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 * would break the ability to snap back to the tiled
* state, so we wait until mouse release. * state, so we wait until mouse release.
*/ */
if (!META_WINDOW_TILED_SIDE_BY_SIDE (window)) update_tile_mode (window);
window->tile_mode = META_TILE_NONE;
} }
} }