From 4c6a10fb4330e7e6d6ce0e81931cacc359fdb4f1 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Thu, 24 Jun 2010 01:46:47 +0000 Subject: - Add patch to allow breaking out from maximization during mouse resize (gnome bz 622517) --- ...eaking-out-from-maximization-during-mouse.patch | 413 +++++++++++++++++++++ metacity.spec | 8 +- 2 files changed, 420 insertions(+), 1 deletion(-) create mode 100644 Allow-breaking-out-from-maximization-during-mouse.patch diff --git a/Allow-breaking-out-from-maximization-during-mouse.patch b/Allow-breaking-out-from-maximization-during-mouse.patch new file mode 100644 index 0000000..15005b6 --- /dev/null +++ b/Allow-breaking-out-from-maximization-during-mouse.patch @@ -0,0 +1,413 @@ +From 339710e884cfbab810382a63fafb3cdab8ee51e9 Mon Sep 17 00:00:00 2001 +From: Owen W. Taylor +Date: Wed, 23 Jun 2010 15:08:38 -0400 +Subject: [PATCH] Allow breaking out from maximization during a mouse resize + +A maximized window can't be resized from the screen edges (preserves +Fitts law goodness for the application), but it's still possible +to start a resize drag with alt-middle-button. Currently we just +don't let the user resize the window, while showing drag feedback; +it's more useful to let the user "break" out from the resize. + +This provides a fast way to get a window partially aligned with +the screen edges - maximize, then alt-drag it out from one edge. + +Behavior choices in this patch: + + - You can drag out a window out of maximization in both directions - + smaller and larger. This can be potentilaly useful in multihead. + + - Dragging a window in only one direction unmaximizes the window + fully, rather than leaving it in a horizontally/vertically + maximized state. This is done because the horizontally/vertically + maximzed states don't have clear visual representation and can + be confusing to the user. + + - If you drag back to the maximized state after breaking out, + maximization is restored, but you can't maximize a window by + dragging to the full size if it didn't start out that way. + +A new internal function meta_window_unmaximize_with_gravity() is +added for implementing this; it's a hybrid of +meta_window_unmaximize() and meta_window_resize_with_gravity(). + +https://bugzilla.gnome.org/show_bug.cgi?id=622517 +--- + src/core/display-private.h | 3 + + src/core/display.c | 20 +++- + src/core/window-private.h | 5 + + src/core/window.c | 224 ++++++++++++++++++++++++++++++++++++++++---- + 4 files changed, 228 insertions(+), 24 deletions(-) + +diff --git a/src/core/display-private.h b/src/core/display-private.h +index 19287f3..a19d1d8 100644 +--- a/src/core/display-private.h ++++ b/src/core/display-private.h +@@ -170,6 +170,9 @@ struct _MetaDisplay + guint grab_wireframe_active : 1; + guint grab_was_cancelled : 1; /* Only used in wireframe mode */ + guint grab_frame_action : 1; ++ /* During a resize operation, the directions in which we've broken ++ * out of the initial maximization state */ ++ guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */ + MetaRectangle grab_wireframe_rect; + MetaRectangle grab_wireframe_last_xor_rect; + MetaRectangle grab_initial_window_pos; +diff --git a/src/core/display.c b/src/core/display.c +index 4c7b4c0..2122851 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -3353,6 +3353,7 @@ meta_display_begin_grab_op (MetaDisplay *display, + #endif + display->grab_was_cancelled = FALSE; + display->grab_frame_action = frame_action; ++ display->grab_resize_unmaximize = 0; + + if (display->grab_resize_timeout_id) + { +@@ -3583,11 +3584,20 @@ meta_display_end_grab_op (MetaDisplay *display, + display->grab_wireframe_rect.x, + display->grab_wireframe_rect.y); + if (meta_grab_op_is_resizing (display->grab_op)) +- meta_window_resize_with_gravity (display->grab_window, +- TRUE, +- display->grab_wireframe_rect.width, +- display->grab_wireframe_rect.height, +- meta_resize_gravity_from_grab_op (display->grab_op)); ++ { ++ if (display->grab_resize_unmaximize != 0) ++ meta_window_unmaximize_with_gravity (display->grab_window, ++ display->grab_resize_unmaximize, ++ display->grab_wireframe_rect.width, ++ display->grab_wireframe_rect.height, ++ meta_resize_gravity_from_grab_op (display->grab_op)); ++ else ++ meta_window_resize_with_gravity (display->grab_window, ++ TRUE, ++ display->grab_wireframe_rect.width, ++ display->grab_wireframe_rect.height, ++ meta_resize_gravity_from_grab_op (display->grab_op)); ++ } + } + meta_window_calc_showing (display->grab_window); + } +diff --git a/src/core/window-private.h b/src/core/window-private.h +index da3fc52..65143ce 100644 +--- a/src/core/window-private.h ++++ b/src/core/window-private.h +@@ -412,6 +412,11 @@ void meta_window_maximize_internal (MetaWindow *window, + MetaRectangle *saved_rect); + void meta_window_unmaximize (MetaWindow *window, + MetaMaximizeFlags directions); ++void meta_window_unmaximize_with_gravity (MetaWindow *window, ++ MetaMaximizeFlags directions, ++ int new_width, ++ int new_height, ++ int gravity); + void meta_window_make_above (MetaWindow *window); + void meta_window_unmake_above (MetaWindow *window); + void meta_window_shade (MetaWindow *window, +diff --git a/src/core/window.c b/src/core/window.c +index 9af5283..6438540 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -2666,9 +2666,11 @@ unmaximize_window_before_freeing (MetaWindow *window) + } + } + +-void +-meta_window_unmaximize (MetaWindow *window, +- MetaMaximizeFlags directions) ++static void ++meta_window_unmaximize_internal (MetaWindow *window, ++ MetaMaximizeFlags directions, ++ MetaRectangle *desired_rect, ++ int gravity) + { + /* At least one of the two directions ought to be set */ + gboolean unmaximize_horizontally, unmaximize_vertically; +@@ -2702,13 +2704,13 @@ meta_window_unmaximize (MetaWindow *window, + meta_window_get_client_root_coords (window, &target_rect); + if (unmaximize_horizontally) + { +- target_rect.x = window->saved_rect.x; +- target_rect.width = window->saved_rect.width; ++ target_rect.x = desired_rect->x; ++ target_rect.width = desired_rect->width; + } + if (unmaximize_vertically) + { +- target_rect.y = window->saved_rect.y; +- target_rect.height = window->saved_rect.height; ++ target_rect.y = desired_rect->y; ++ target_rect.height = desired_rect->height; + } + + /* Window's size hints may have changed while maximized, making +@@ -2727,12 +2729,13 @@ meta_window_unmaximize (MetaWindow *window, + window->display->grab_anchor_window_pos = target_rect; + } + +- meta_window_move_resize (window, +- FALSE, +- target_rect.x, +- target_rect.y, +- target_rect.width, +- target_rect.height); ++ meta_window_move_resize_internal (window, ++ META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION, ++ gravity, ++ target_rect.x, ++ target_rect.y, ++ target_rect.width, ++ target_rect.height); + + /* Make sure user_rect is current. + */ +@@ -2749,6 +2752,36 @@ meta_window_unmaximize (MetaWindow *window, + } + + void ++meta_window_unmaximize (MetaWindow *window, ++ MetaMaximizeFlags directions) ++{ ++ meta_window_unmaximize_internal (window, directions, &window->saved_rect, ++ NorthWestGravity); ++} ++ ++/* Like meta_window_unmaximize(), but instead of unmaximizing to the ++ * saved position, we give the new desired size, and the gravity that ++ * determines the positioning relationship between the area occupied ++ * maximized and the new are. The arguments are similar to ++ * meta_window_resize_with_gravity(). ++ */ ++void ++meta_window_unmaximize_with_gravity (MetaWindow *window, ++ MetaMaximizeFlags directions, ++ int new_width, ++ int new_height, ++ int gravity) ++{ ++ MetaRectangle desired_rect; ++ ++ meta_window_get_position (window, &desired_rect.x, &desired_rect.y); ++ desired_rect.width = new_width; ++ desired_rect.height = new_height; ++ ++ meta_window_unmaximize_internal (window, directions, &desired_rect, gravity); ++} ++ ++void + meta_window_make_above (MetaWindow *window) + { + window->wm_state_above = TRUE; +@@ -7033,6 +7066,112 @@ update_resize_timeout (gpointer data) + return FALSE; + } + ++/* When resizing a maximized window by using alt-middle-drag (resizing ++ * with the grips or the menu for a maximized window is not enabled), ++ * the user can "break" out of the maximized state. This checks for ++ * that possibility. During such a break-out resize the user can also ++ * return to the previous maximization state by resizing back to near ++ * the original size. ++ */ ++static MetaMaximizeFlags ++check_resize_unmaximize(MetaWindow *window, ++ int dx, ++ int dy) ++{ ++ int threshold; ++ MetaMaximizeFlags new_unmaximize; ++ ++#define DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR 3 ++ ++ threshold = meta_ui_get_drag_threshold (window->screen->ui) * ++ DRAG_THRESHOLD_TO_RESIZE_THRESHOLD_FACTOR; ++ new_unmaximize = 0; ++ ++ if (window->maximized_horizontally || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) ++ { ++ int x_amount; ++ ++ /* We allow breaking out of maximization in either direction, to make ++ * the window larger than the monitor as well as smaller than the ++ * monitor. If we wanted to only allow resizing smaller than the ++ * monitor, we'd use - dx for NE/E/SE and dx for SW/W/NW. ++ */ ++ switch (window->display->grab_op) ++ { ++ case META_GRAB_OP_RESIZING_NE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NE: ++ case META_GRAB_OP_RESIZING_E: ++ case META_GRAB_OP_KEYBOARD_RESIZING_E: ++ case META_GRAB_OP_RESIZING_SE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SE: ++ case META_GRAB_OP_RESIZING_SW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SW: ++ case META_GRAB_OP_RESIZING_W: ++ case META_GRAB_OP_KEYBOARD_RESIZING_W: ++ case META_GRAB_OP_RESIZING_NW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NW: ++ x_amount = dx < 0 ? - dx : dx; ++ break; ++ default: ++ x_amount = 0; ++ break; ++ } ++ ++ if (x_amount > threshold) ++ new_unmaximize |= META_MAXIMIZE_HORIZONTAL; ++ } ++ ++ if (window->maximized_vertically || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) ++ { ++ int y_amount; ++ ++ switch (window->display->grab_op) ++ { ++ case META_GRAB_OP_RESIZING_N: ++ case META_GRAB_OP_KEYBOARD_RESIZING_N: ++ case META_GRAB_OP_RESIZING_NE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NE: ++ case META_GRAB_OP_RESIZING_NW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_NW: ++ case META_GRAB_OP_RESIZING_SE: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SE: ++ case META_GRAB_OP_RESIZING_S: ++ case META_GRAB_OP_KEYBOARD_RESIZING_S: ++ case META_GRAB_OP_RESIZING_SW: ++ case META_GRAB_OP_KEYBOARD_RESIZING_SW: ++ y_amount = dy < 0 ? - dy : dy; ++ break; ++ default: ++ y_amount = 0; ++ break; ++ } ++ ++ if (y_amount > threshold) ++ new_unmaximize |= META_MAXIMIZE_VERTICAL; ++ } ++ ++ /* Metacity doesn't have a full user interface for only horizontally or ++ * vertically maximized, so while only unmaximizing in the direction drags ++ * has some advantages, it will also confuse the user. So, we always ++ * unmaximize both ways if possible. ++ */ ++ if (new_unmaximize != 0) ++ { ++ new_unmaximize = 0; ++ ++ if (window->maximized_horizontally || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_HORIZONTAL) != 0) ++ new_unmaximize |= META_MAXIMIZE_HORIZONTAL; ++ if (window->maximized_vertically || ++ (window->display->grab_resize_unmaximize & META_MAXIMIZE_VERTICAL) != 0) ++ new_unmaximize |= META_MAXIMIZE_VERTICAL; ++ } ++ ++ return new_unmaximize; ++} ++ + static void + update_resize (MetaWindow *window, + gboolean snap, +@@ -7045,6 +7184,7 @@ update_resize (MetaWindow *window, + MetaRectangle old; + int new_x, new_y; + double remaining; ++ MetaMaximizeFlags new_unmaximize; + + window->display->grab_latest_motion_x = x; + window->display->grab_latest_motion_y = y; +@@ -7109,7 +7249,9 @@ update_resize (MetaWindow *window, + meta_window_update_keyboard_resize (window, TRUE); + } + } +- ++ ++ new_unmaximize = check_resize_unmaximize (window, dx, dy); ++ + /* FIXME: This stupidity only needed because of wireframe mode and + * the fact that wireframe isn't making use of + * meta_rectangle_resize_with_gravity(). If we were to use that, we +@@ -7233,6 +7375,8 @@ update_resize (MetaWindow *window, + + if (window->display->grab_wireframe_active) + { ++ MetaRectangle root_coords; ++ + if ((new_x + new_w <= new_x) || (new_y + new_h <= new_y)) + return; + +@@ -7242,18 +7386,60 @@ update_resize (MetaWindow *window, + * wireframe, but still resize it; however, that probably + * confuses broken clients that have problems with opaque + * resize, they probably don't track their visibility. ++ * ++ * We handle the basic constraints on maximized windows here ++ * to give the user feedback. + */ ++ ++ if (window->maximized_horizontally && (new_unmaximize & META_MAXIMIZE_HORIZONTAL) == 0) ++ { ++ meta_window_get_client_root_coords (window, &root_coords); ++ new_x = root_coords.x; ++ new_w = root_coords.width; ++ } ++ if (window->maximized_vertically && (new_unmaximize & META_MAXIMIZE_VERTICAL) == 0) ++ { ++ meta_window_get_client_root_coords (window, &root_coords); ++ new_y = root_coords.y; ++ new_h = root_coords.height; ++ } ++ + meta_window_update_wireframe (window, new_x, new_y, new_w, new_h); + } + else + { +- /* We don't need to update unless the specified width and height +- * are actually different from what we had before. +- */ +- if (old.width != new_w || old.height != new_h) +- meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); ++ if (new_unmaximize == window->display->grab_resize_unmaximize) ++ { ++ /* We don't need to update unless the specified width and height ++ * are actually different from what we had before. ++ */ ++ if (old.width != new_w || old.height != new_h) ++ { ++ if ((window->display->grab_resize_unmaximize == new_unmaximize)) ++ meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); ++ } ++ } ++ else ++ { ++ if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0) ++ { ++ meta_window_unmaximize_with_gravity (window, ++ (new_unmaximize & ~window->display->grab_resize_unmaximize), ++ new_w, new_h, gravity); ++ } ++ ++ if ((window->display->grab_resize_unmaximize & ~new_unmaximize)) ++ { ++ MetaRectangle saved_rect = window->saved_rect; ++ meta_window_maximize (window, ++ (window->display->grab_resize_unmaximize & ~new_unmaximize)); ++ window->saved_rect = saved_rect; ++ } ++ } + } + ++ window->display->grab_resize_unmaximize = new_unmaximize; ++ + /* Store the latest resize time, if we actually resized. */ + if (window->rect.width != old.width || window->rect.height != old.height) + g_get_current_time (&window->display->grab_last_moveresize_time); +-- +1.7.0.1 + diff --git a/metacity.spec b/metacity.spec index 9fb940b..3119e2a 100644 --- a/metacity.spec +++ b/metacity.spec @@ -3,7 +3,7 @@ Summary: Unobtrusive window manager Name: metacity Version: 2.30.0 -Release: 5%{?dist} +Release: 6%{?dist} URL: http://download.gnome.org/sources/metacity/ Source0: http://download.gnome.org/sources/metacity/2.30/metacity-%{version}.tar.bz2 # http://bugzilla.gnome.org/show_bug.cgi?id=558723 @@ -45,6 +45,8 @@ Patch26: libs.patch Patch27: title-click.patch # https://bugzilla.gnome.org/show_bug.cgi?id=599181 Patch28: Stop-confusing-GDK-s-grab-tracking.patch +# https://bugzilla.gnome.org/show_bug.cgi?id=622517 +Patch29: Allow-breaking-out-from-maximization-during-mouse.patch # default window icon: https://bugzilla.gnome.org/show_bug.cgi?id=616246 Patch30: default-window-icon.patch @@ -240,6 +242,10 @@ fi %{_mandir}/man1/metacity-window-demo.1.gz %changelog +* Wed Jun 23 2010 Owen Taylor - 2.30.0-6 +- Add patch to allow breaking out from maximization during mouse resize + (gnome bz 622517) + * Wed Jun 9 2010 Owen Taylor - 2.30.0-5 - Add a patch to fix confusion between windows (rhbz #533066) - Add additional tweeks no_focus_windows and new_windows_always_on_top -- cgit