From 330a2d1df6efe140a71801a25954bf2f970bd73b Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Sat, 12 Nov 2005 23:47:31 +0000 Subject: Get keyboard buildup edge resistance working, and convert old (and buggy) 2005-11-12 Elijah Newren Get keyboard buildup edge resistance working, and convert old (and buggy) edge resistance for keyboard move/resize to new framework. Despite this being a large increase in functionality, I almost removed as many lines as I added from the cleanups that were made possible (388 lines added, 328 removed). * src/constraints-ideas.txt: Mark edge resistance as done (there may be a few bugs left, and I'm sure I'll need to tweak some of the parameters but there's nothing big left) * src/display.[hc]: (struct MetaDisplay): rename grab_last_used_state_for_resize field to grab_last_user_action_was_snap (meta_display_apply_edge_resistance): take a keyboard_op parameter and pass it on to apply_edge_resistance() and apply_edge_snapping() * src/display.c: (struct EdgeResistanceTimeoutData): add a keyboard_buildup field (meta_display_begin_grab_op): handle rename of grab_last_used_state_for_resize to grab_last_user_action_was_snap (points_on_same_side): new function (find_nearest_position): take an only_forward parameter and if true, only look for the nearest position in the direction away from old_postion towards (or past) position. (apply_edge_resistance): take a keyboard_op parameter, don't do timeout for keyboard op, add special case for keyboard op that does keyboard energy buildup resistance, explain the pixel distance mouse resistance better (apply_edge_snapping): take a keyboard_op parameter, add some comments, make sure that the snapping is in the right direction for keyboard ops (compute_resistance_and_snapping_edges): initialize the keyboard_buildup field of the edge resistance data * src/keybindings.c: (process_keyboard_move_grab, process_keyboard_resize_grab): SIMPLIFY MASSIVELY by using the new edge resistance and snapping functionality. * src/window.[ch]: (meta_window_edge_resistance_for_move, meta_window_edge_resistance_for_resize): new functions needed for handling common operations for both mouse and keyboard moves and resizes; most of the work is handled by meta_display_apply_edge_resistance() but these functions prepare the necessary input parameters and correctly interpret the output as needed. * src/window.c: (update_move, update_resize, meta_window_handle_mouse_grab_op_event): have update_move() and update_resize() take a snap boolean parameter instead of a mask unsigned int parameter since we don't really know the keystate in some places where these functions need to be called and don't really need that much info anyway (update_move, update_resize): move common functionality needed by keyboard move/resize into meta_window_edge_resistance_for_move() and meta_window_edge_resistance_for_resize() (update_move_timeout, update_resize_timeout, meta_window_handle_mouse_grab_op_event): handle rename of grab_last_used_state_for_resize to grab_last_user_action_was_snap --- ChangeLog | 86 ++++++++++++++ constraints-ideas.txt | 2 +- src/display.c | 157 +++++++++++++++++++------- src/display.h | 5 +- src/keybindings.c | 305 +++++++++++--------------------------------------- src/window.c | 236 +++++++++++++++++++++++--------------- src/window.h | 16 +++ 7 files changed, 430 insertions(+), 377 deletions(-) diff --git a/ChangeLog b/ChangeLog index a4c84428..3db5da19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,89 @@ +2005-11-12 Elijah Newren + + Get keyboard buildup edge resistance working, and convert old (and + buggy) edge resistance for keyboard move/resize to new framework. + Despite this being a large increase in functionality, I almost + removed as many lines as I added from the cleanups that were + made possible (388 lines added, 328 removed). + + * src/constraints-ideas.txt: Mark edge resistance as done (there + may be a few bugs left, and I'm sure I'll need to tweak some of + the parameters but there's nothing big left) + + * src/display.[hc]: + + (struct MetaDisplay): + rename grab_last_used_state_for_resize field to + grab_last_user_action_was_snap + + (meta_display_apply_edge_resistance): + take a keyboard_op parameter and pass it on to + apply_edge_resistance() and apply_edge_snapping() + + * src/display.c: + + (struct EdgeResistanceTimeoutData): + add a keyboard_buildup field + + (meta_display_begin_grab_op): + handle rename of grab_last_used_state_for_resize to + grab_last_user_action_was_snap + + (points_on_same_side): + new function + + (find_nearest_position): + take an only_forward parameter and if true, only look for the + nearest position in the direction away from old_postion towards + (or past) position. + + (apply_edge_resistance): + take a keyboard_op parameter, don't do timeout for keyboard op, + add special case for keyboard op that does keyboard energy buildup + resistance, explain the pixel distance mouse resistance better + + (apply_edge_snapping): + take a keyboard_op parameter, add some comments, make sure that + the snapping is in the right direction for keyboard ops + + (compute_resistance_and_snapping_edges): + initialize the keyboard_buildup field of the edge resistance data + + * src/keybindings.c: + + (process_keyboard_move_grab, process_keyboard_resize_grab): + SIMPLIFY MASSIVELY by using the new edge resistance and snapping + functionality. + + * src/window.[ch]: + + (meta_window_edge_resistance_for_move, + meta_window_edge_resistance_for_resize): + new functions needed for handling common operations for both mouse + and keyboard moves and resizes; most of the work is handled by + meta_display_apply_edge_resistance() but these functions prepare + the necessary input parameters and correctly interpret the output + as needed. + + * src/window.c: + + (update_move, update_resize, + meta_window_handle_mouse_grab_op_event): + have update_move() and update_resize() take a snap boolean + parameter instead of a mask unsigned int parameter since we don't + really know the keystate in some places where these functions need + to be called and don't really need that much info anyway + + (update_move, update_resize): + move common functionality needed by keyboard move/resize into + meta_window_edge_resistance_for_move() and + meta_window_edge_resistance_for_resize() + + (update_move_timeout, update_resize_timeout, + meta_window_handle_mouse_grab_op_event): + handle rename of grab_last_used_state_for_resize to + grab_last_user_action_was_snap + 2005-11-09 Elijah Newren * src/constraints-ideas.txt: Add a bunch of questions that I want diff --git a/constraints-ideas.txt b/constraints-ideas.txt index 4905901e..b51e52e7 100644 --- a/constraints-ideas.txt +++ b/constraints-ideas.txt @@ -78,7 +78,7 @@ Short-term (I hope...) TODO list/reminders: X change edges_overlap() to not depend on type (allow undefined type; just check thicknesses) - - Important edge resistance points + X Important edge resistance points - Both moving and resizing - Real edges, not workarea - Screen vs. xinerama vs. window edges diff --git a/src/display.c b/src/display.c index d12d2ada..2081d310 100644 --- a/src/display.c +++ b/src/display.c @@ -108,6 +108,7 @@ struct EdgeResistanceTimeoutData gboolean over; GSourceFunc real_func; MetaWindow *window; + int keyboard_buildup; }; typedef struct EdgeResistanceTimeoutData EdgeResistanceTimeoutData; @@ -3319,7 +3320,7 @@ meta_display_begin_grab_op (MetaDisplay *display, display->grab_old_window_stacking = NULL; #ifdef HAVE_XSYNC display->grab_sync_request_alarm = None; - display->grab_last_used_state_for_resize = 0; + display->grab_last_user_action_was_snap = FALSE; #endif display->grab_was_cancelled = FALSE; @@ -3890,12 +3891,19 @@ find_index_of_edge_near_position (const GArray *edges, } } +static gboolean +points_on_same_side (int ref, int pt1, int pt2) +{ + return (pt1 - ref) * (pt2 - ref) > 0; +} + static int find_nearest_position (const GArray *edges, int position, int old_position, const MetaRectangle *new_rect, - gboolean horizontal) + gboolean horizontal, + gboolean only_forward) { /* This is basically just a binary search except that we're looking * for the value closest to position, rather than finding that @@ -3945,7 +3953,8 @@ find_nearest_position (const GArray *edges, gboolean edges_align = horizontal ? meta_rectangle_vert_overlap (&edge->rect, new_rect) : meta_rectangle_horiz_overlap (&edge->rect, new_rect); - if (edges_align) + if (edges_align && + (!only_forward || !points_on_same_side (position, compare, old_position))) { int dist = ABS (compare - position); if (dist < best_dist) @@ -3965,7 +3974,9 @@ find_nearest_position (const GArray *edges, meta_rectangle_vert_overlap (&edge->rect, new_rect) : meta_rectangle_horiz_overlap (&edge->rect, new_rect); - if (edges_align) + if (edges_align && + (!only_forward || + !points_on_same_side (position, compare, old_position))) { int dist = ABS (compare - position); if (dist < best_dist) @@ -3987,7 +3998,9 @@ find_nearest_position (const GArray *edges, meta_rectangle_vert_overlap (&edge->rect, new_rect) : meta_rectangle_horiz_overlap (&edge->rect, new_rect); - if (edges_align) + if (edges_align && + (!only_forward || + !points_on_same_side (position, compare, old_position))) { int dist = ABS (compare - position); if (dist < best_dist) @@ -4039,7 +4052,8 @@ apply_edge_resistance (MetaWindow *window, GArray *edges, EdgeResistanceTimeoutData *timeout, GSourceFunc timeout_func, - gboolean xdir) + gboolean xdir, + gboolean keyboard_op) { int i, begin, end; gboolean increasing = new_pos > old_pos; @@ -4083,11 +4097,13 @@ apply_edge_resistance (MetaWindow *window, meta_rectangle_vert_overlap (&edge->rect, new_rect) : meta_rectangle_horiz_overlap (&edge->rect, new_rect); - /* If the edge is relevant and we haven't moved at least - * EDGE_RESISTANCE_THRESHOLD pixels past this edge, stop movement at - * this edge. + /* TIMEOUT RESISTANCE for screen/xinerama edges: If the edge is + * relevant and we're moving towards it and it's a screen/xinerama + * edge, then we may want to have some kind of time delay before the + * user can move past this edge. */ - if (edges_align && movement_towards_edge (edge->side_type, increment) && + if (edges_align && !keyboard_op && + movement_towards_edge (edge->side_type, increment) && ((window->require_fully_onscreen && edge->edge_type == META_EDGE_ONSCREEN) || (window->require_on_single_xinerama && @@ -4107,22 +4123,51 @@ apply_edge_resistance (MetaWindow *window, if (!timeout->over) return compare; } -#if 0 - FIXME: Do I want the following code? In the case that the window isn't - required to be fully onscreen, this would give a resistance to screen - edges when moving more offscreen that is different from the normal - threshold used for normal windows. (If I do use this, I should - probably do something similar for xinerama, and should stick the 100 - somewhere else as a const or #define instead of hard coding it...) - - if (edges_align && edge->edge_type == META_EDGE_ONSCREEN && - movement_towards_edge (edge->side_type, increment) && - ABS (compare - new_pos) < 100) - return compare; -#endif - if (edges_align && - ABS (compare - new_pos) < EDGE_RESISTANCE_THRESHOLD) - return compare; + + /* Rest is easier to read if we split on keyboard vs. mouse op */ + if (keyboard_op) + { + /* KEYBOARD ENERGY BUILDUP RESISTANCE: If the user has is moving + * fast enough or has already built up enough "energy", then let + * the user past the edge, otherwise stop at this edge. If the + * user was previously stopped at this edge, add movement amount + * to the built up energy. + */ + int threshold = EDGE_RESISTANCE_THRESHOLD + - timeout->keyboard_buildup; + if (edges_align && + ABS (compare - new_pos) < threshold) + { + if (timeout->keyboard_buildup != 0) + timeout->keyboard_buildup += ABS (new_pos - compare); + else + timeout->keyboard_buildup = 1; /* Can't be 0 or stuck forever */ + return compare; + } + else + { + /* Let the user past the edge; remove any built up energy + * from this edge (note that there better not be any left + * over from previous edges either...) + */ + timeout->keyboard_buildup = 0; + } + } + else + { + /* PIXEL DISTANCE MOUSE RESISTANCE: If the edge matters and the + * user hasn't moved at least EDGE_RESISTANCE_THRESHOLD pixels + * past this edge, stop movement at this edge. (Note that this + * is different from keyboard resistance precisely because + * keyboard move ops are relative to previous positions, whereas + * mouse move ops are relative to differences in mouse position + * and mouse position is an absolute quantity rather than a + * relative quantity) + */ + if (edges_align && + ABS (compare - new_pos) < EDGE_RESISTANCE_THRESHOLD) + return compare; + } /* Go to the next edge in the range */ i += increment; @@ -4137,24 +4182,43 @@ apply_edge_snapping (int old_pos, const MetaRectangle *new_rect, GArray *edges1, GArray *edges2, - gboolean xdir) + gboolean xdir, + gboolean keyboard_op) { int pos1, pos2; if (old_pos == new_pos) return new_pos; + /* We look at two sets of edges (e.g. left and right) individually + * finding the nearest position among each set of edges and then later + * finding the better of these two bests. + */ pos1 = find_nearest_position (edges1, new_pos, old_pos, new_rect, - xdir); + xdir, + keyboard_op); pos2 = find_nearest_position (edges2, new_pos, old_pos, new_rect, - xdir); + xdir, + keyboard_op); + + /* For keyboard snapping, ignore either pos1 or pos2 if they aren't in the + * right direction. + */ + if (keyboard_op) + { + if (!points_on_same_side (old_pos, pos1, new_pos)) + return pos2; + if (!points_on_same_side (old_pos, pos2, new_pos)) + return pos1; + } + /* Find the better of pos1 and pos2 and return it */ if (ABS (pos1 - new_pos) < ABS (pos2 - new_pos)) return pos1; else @@ -4175,7 +4239,8 @@ meta_display_apply_edge_resistance (MetaDisplay *display, const MetaRectangle *old_outer, MetaRectangle *new_outer, GSourceFunc timeout_func, - gboolean auto_snap) + gboolean auto_snap, + gboolean keyboard_op) { MetaEdgeResistanceData *edge_data; MetaRectangle modified_rect; @@ -4197,29 +4262,32 @@ meta_display_apply_edge_resistance (MetaDisplay *display, new_outer, edge_data->left_edges, edge_data->right_edges, - TRUE); + TRUE, + keyboard_op); new_right = apply_edge_snapping (BOX_RIGHT (*old_outer), BOX_RIGHT (*new_outer), new_outer, edge_data->left_edges, edge_data->right_edges, - TRUE); + TRUE, + keyboard_op); new_top = apply_edge_snapping (BOX_TOP (*old_outer), BOX_TOP (*new_outer), new_outer, edge_data->top_edges, edge_data->bottom_edges, - FALSE); + FALSE, + keyboard_op); new_bottom = apply_edge_snapping (BOX_BOTTOM (*old_outer), BOX_BOTTOM (*new_outer), new_outer, edge_data->top_edges, edge_data->bottom_edges, - FALSE); - + FALSE, + keyboard_op); } else { @@ -4231,7 +4299,8 @@ meta_display_apply_edge_resistance (MetaDisplay *display, edge_data->left_edges, &edge_data->left_timeout, timeout_func, - TRUE); + TRUE, + keyboard_op); new_right = apply_edge_resistance (window, BOX_RIGHT (*old_outer), BOX_RIGHT (*new_outer), @@ -4239,7 +4308,8 @@ meta_display_apply_edge_resistance (MetaDisplay *display, edge_data->right_edges, &edge_data->right_timeout, timeout_func, - TRUE); + TRUE, + keyboard_op); new_top = apply_edge_resistance (window, BOX_TOP (*old_outer), BOX_TOP (*new_outer), @@ -4247,7 +4317,8 @@ meta_display_apply_edge_resistance (MetaDisplay *display, edge_data->top_edges, &edge_data->top_timeout, timeout_func, - FALSE); + FALSE, + keyboard_op); new_bottom = apply_edge_resistance (window, BOX_BOTTOM (*old_outer), BOX_BOTTOM (*new_outer), @@ -4255,7 +4326,8 @@ meta_display_apply_edge_resistance (MetaDisplay *display, edge_data->bottom_edges, &edge_data->bottom_timeout, timeout_func, - FALSE); + FALSE, + keyboard_op); } /* Determine whether anything changed, and save the changes */ @@ -4657,12 +4729,17 @@ compute_resistance_and_snapping_edges (MetaDisplay *display) g_list_free (edges); /* - * 6th: Initialize the timeouts + * 6th: Initialize the resistance timeouts and buildups */ display->grab_edge_resistance_data->left_timeout.setup = FALSE; display->grab_edge_resistance_data->right_timeout.setup = FALSE; display->grab_edge_resistance_data->top_timeout.setup = FALSE; display->grab_edge_resistance_data->bottom_timeout.setup = FALSE; + + display->grab_edge_resistance_data->left_timeout.keyboard_buildup = 0; + display->grab_edge_resistance_data->right_timeout.keyboard_buildup = 0; + display->grab_edge_resistance_data->top_timeout.keyboard_buildup = 0; + display->grab_edge_resistance_data->bottom_timeout.keyboard_buildup = 0; } /***** End gobs of edge_resistance functions *****/ diff --git a/src/display.h b/src/display.h index c10c9305..2424cf9c 100644 --- a/src/display.h +++ b/src/display.h @@ -340,7 +340,7 @@ struct _MetaDisplay int render_error_base; #endif #ifdef HAVE_XSYNC - unsigned int grab_last_used_state_for_resize; + unsigned int grab_last_user_action_was_snap; unsigned int have_xsync : 1; #define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync) #else @@ -455,7 +455,8 @@ gboolean meta_display_apply_edge_resistance (MetaDisplay *display, const MetaRectangle *old_outer, MetaRectangle *new_outer, GSourceFunc timeout_func, - gboolean auto_snap); + gboolean auto_snap, + gboolean keyboard_op); /* make a request to ensure the event serial has changed */ void meta_display_increment_event_serial (MetaDisplay *display); diff --git a/src/keybindings.c b/src/keybindings.c index d2990efa..c4342d91 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -1689,8 +1689,6 @@ process_keyboard_move_grab (MetaDisplay *display, int x, y; int incr; gboolean smart_snap; - int edge; - int candidate_position; handled = FALSE; @@ -1718,7 +1716,7 @@ process_keyboard_move_grab (MetaDisplay *display, #define NORMAL_INCREMENT 10 if (smart_snap) - incr = 0; + incr = 1; else if (event->xkey.state & ControlMask) incr = SMALL_INCREMENT; else @@ -1753,18 +1751,6 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_Up: case XK_KP_Up: y -= incr; - - edge = meta_window_find_next_horizontal_edge (window, - META_WINDOW_EDGE_TOP, - FALSE); - if (window->frame) - candidate_position = edge + window->frame->child_y; - else - candidate_position = edge; - - if (smart_snap || ((candidate_position > y) && ABS (candidate_position - y) < incr)) - y = candidate_position; - handled = TRUE; break; case XK_KP_End: @@ -1772,18 +1758,6 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_Down: case XK_KP_Down: y += incr; - - edge = meta_window_find_next_horizontal_edge (window, - META_WINDOW_EDGE_BOTTOM, - TRUE); - if (window->frame) - candidate_position = edge - window->frame->bottom_height - window->rect.height; - else - candidate_position = edge - window->rect.height; - - if (smart_snap || ((candidate_position < y) && ABS (candidate_position - y) < incr)) - y = candidate_position; - handled = TRUE; break; } @@ -1795,19 +1769,6 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_Left: case XK_KP_Left: x -= incr; - - edge = meta_window_find_next_vertical_edge (window, - META_WINDOW_EDGE_LEFT, - FALSE); - if (window->frame) - candidate_position = edge + window->frame->child_x; - else - candidate_position = edge; - - if (smart_snap || - ((candidate_position > x) && ABS (candidate_position - x) < incr)) - x = candidate_position; - handled = TRUE; break; case XK_KP_Prior: @@ -1815,18 +1776,6 @@ process_keyboard_move_grab (MetaDisplay *display, case XK_Right: case XK_KP_Right: x += incr; - - edge = meta_window_find_next_vertical_edge (window, - META_WINDOW_EDGE_RIGHT, - TRUE); - if (window->frame) - candidate_position = edge - window->frame->right_width - window->rect.width; - else - candidate_position = edge - window->rect.width; - - if (smart_snap || ((candidate_position < x) && ABS (candidate_position - x) < incr)) - x = candidate_position; - handled = TRUE; break; } @@ -1844,6 +1793,15 @@ process_keyboard_move_grab (MetaDisplay *display, } else { + int old_x, old_y; + meta_window_get_position (window, &old_x, &old_y); + meta_window_edge_resistance_for_move (window, + old_x, + old_y, + &x, + &y, + smart_snap, + TRUE); meta_window_move (window, TRUE, x, y); } @@ -1985,13 +1943,9 @@ process_keyboard_resize_grab (MetaDisplay *display, gboolean handled; int height_inc; int width_inc; - int x, y; - int orig_x, orig_y; int width, height; gboolean smart_snap; - int edge; int gravity; - int candidate_position; handled = FALSE; @@ -2028,21 +1982,15 @@ process_keyboard_resize_grab (MetaDisplay *display, if (display->grab_wireframe_active) { - orig_x = display->grab_wireframe_rect.x; - orig_y = display->grab_wireframe_rect.y; width = display->grab_wireframe_rect.width; height = display->grab_wireframe_rect.height; } else { - meta_window_get_position (window, &orig_x, &orig_y); width = window->rect.width; height = window->rect.height; } - x = orig_x; - y = orig_y; - gravity = meta_resize_gravity_from_grab_op (display->grab_op); smart_snap = (event->xkey.state & ShiftMask) != 0; @@ -2052,40 +2000,28 @@ process_keyboard_resize_grab (MetaDisplay *display, if (smart_snap) { - height_inc = 0; - width_inc = 0; + height_inc = 1; + width_inc = 1; } else if (event->xkey.state & ControlMask) { - if (window->size_hints.width_inc > 1) - width_inc = window->size_hints.width_inc; - else - width_inc = SMALL_INCREMENT; - - if (window->size_hints.height_inc > 1) - height_inc = window->size_hints.height_inc; - else - height_inc = SMALL_INCREMENT; + width_inc = SMALL_INCREMENT; + height_inc = SMALL_INCREMENT; } else { - if (window->size_hints.width_inc > 1) - width_inc = window->size_hints.width_inc; - else - width_inc = NORMAL_INCREMENT; - - if (window->size_hints.height_inc > 1) - height_inc = window->size_hints.height_inc; - else - height_inc = NORMAL_INCREMENT; + width_inc = NORMAL_INCREMENT; + height_inc = NORMAL_INCREMENT; } - - /* When moving by increments, we still snap to edges if the move - * to the edge is smaller than the increment. This is because - * Shift + arrow to snap is sort of a hidden feature. This way - * people using just arrows shouldn't get too frustrated. + + /* If this is a resize increment window, make the amount we resize + * the window by match that amount (well, unless snap resizing...) */ - + if (window->size_hints.width_inc > 1) + width_inc = window->size_hints.width_inc; + if (window->size_hints.height_inc > 1) + height_inc = window->size_hints.height_inc; + switch (keysym) { case XK_Up: @@ -2096,49 +2032,14 @@ process_keyboard_resize_grab (MetaDisplay *display, case NorthWestGravity: case NorthEastGravity: /* Move bottom edge up */ - edge = meta_window_find_next_horizontal_edge (window, - META_WINDOW_EDGE_BOTTOM, - FALSE); - - if (window->frame) - candidate_position = edge - window->frame->bottom_height; - else - candidate_position = edge; - - if (smart_snap || - ((candidate_position > (y + (height - height_inc))) && - ABS (candidate_position - (y + (height - height_inc))) < height_inc)) - { - if (candidate_position - y > 0) - height = candidate_position - y; - } - else if (height - height_inc > 0) - { - height -= height_inc; - } - - handled = TRUE; + height -= height_inc; break; case SouthGravity: case SouthWestGravity: case SouthEastGravity: /* Move top edge up */ - y -= height_inc; - - edge = meta_window_find_next_horizontal_edge (window, - META_WINDOW_EDGE_TOP, - FALSE); - - if (window->frame) - candidate_position = edge + window->frame->child_y; - else - candidate_position = edge; - - if (smart_snap || ((candidate_position > y) && ABS (candidate_position - y) < height_inc)) - y = candidate_position; - - height += (orig_y - y); + height += height_inc; break; case EastGravity: @@ -2160,49 +2061,13 @@ process_keyboard_resize_grab (MetaDisplay *display, case NorthEastGravity: /* Move bottom edge down */ height += height_inc; - - edge = meta_window_find_next_horizontal_edge (window, - META_WINDOW_EDGE_BOTTOM, - TRUE); - - if (window->frame) - candidate_position = edge - window->frame->bottom_height; - else - candidate_position = edge; - - if (smart_snap || ((candidate_position < (y+height)) && - ABS (candidate_position - (y+height)) < height_inc)) - height = candidate_position - y; break; case SouthGravity: case SouthWestGravity: case SouthEastGravity: /* Move top edge down */ - edge = meta_window_find_next_horizontal_edge (window, - META_WINDOW_EDGE_TOP, - TRUE); - - if (window->frame) - candidate_position = edge + window->frame->child_y; - else - candidate_position = edge; - - if (smart_snap || - ((candidate_position < (y + height_inc)) && - ABS (candidate_position - (y + height_inc)) < height_inc)) - { - if (height - (candidate_position - orig_y) > 0) - { - y = candidate_position; - height -= (y - orig_y); - } - } - else if (height - ((y + height_inc) - orig_y) > 0) - { - y += height_inc; - height -= (y - orig_y); - } + height -= height_inc; break; case EastGravity: @@ -2222,50 +2087,15 @@ process_keyboard_resize_grab (MetaDisplay *display, case EastGravity: case SouthEastGravity: case NorthEastGravity: - x -= width_inc; - /* Move left edge left */ - edge = meta_window_find_next_vertical_edge (window, - META_WINDOW_EDGE_LEFT, - FALSE); - - if (window->frame) - candidate_position = edge + window->frame->child_x; - else - candidate_position = edge; - - if (smart_snap || ((candidate_position > x) && ABS (candidate_position - x) < width_inc)) - x = candidate_position; - - width += (orig_x - x); + width += width_inc; break; case WestGravity: case SouthWestGravity: case NorthWestGravity: /* Move right edge left */ - edge = meta_window_find_next_vertical_edge (window, - META_WINDOW_EDGE_RIGHT, - FALSE); - - if (window->frame) - candidate_position = edge - window->frame->right_width; - else - candidate_position = edge; - - if (smart_snap || - ((candidate_position > (x + (width - width_inc))) && - ABS (candidate_position - (x + (width - width_inc))) < width_inc)) - { - if (candidate_position - x > 0) - width = candidate_position - x; - } - else if (width - width_inc > 0) - { - width -= width_inc; - } - - handled = TRUE; + width -= width_inc; break; case NorthGravity: @@ -2286,30 +2116,7 @@ process_keyboard_resize_grab (MetaDisplay *display, case SouthEastGravity: case NorthEastGravity: /* Move left edge right */ - edge = meta_window_find_next_vertical_edge (window, - META_WINDOW_EDGE_LEFT, - TRUE); - - if (window->frame) - candidate_position = edge + window->frame->child_x; - else - candidate_position = edge; - - if (smart_snap || - ((candidate_position < (x + width_inc)) && - ABS (candidate_position - (x + width_inc)) < width_inc)) - { - if (width - (candidate_position - orig_x) > 0) - { - x = candidate_position; - width -= (x - orig_x); - } - } - else if (width - ((x + width_inc) - orig_x) > 0) - { - x += width_inc; - width -= (x - orig_x); - } + width -= width_inc; break; case WestGravity: @@ -2317,21 +2124,6 @@ process_keyboard_resize_grab (MetaDisplay *display, case NorthWestGravity: /* Move right edge right */ width += width_inc; - - edge = meta_window_find_next_vertical_edge (window, - META_WINDOW_EDGE_RIGHT, - TRUE); - - if (window->frame) - candidate_position = edge - window->frame->right_width; - else - candidate_position = edge; - - if (smart_snap || ((candidate_position > (x+width)) && - ABS (candidate_position - (x+width)) < width_inc)) - width = candidate_position - x; - - handled = TRUE; break; case NorthGravity: @@ -2357,16 +2149,45 @@ process_keyboard_resize_grab (MetaDisplay *display, if (handled) { meta_topic (META_DEBUG_KEYBINDINGS, - "Computed new window location %d,%d %dx%d due to keypress\n", - x, y, width, height); + "Computed new window size due to keypress: " + "%dx%d, gravity %s\n", + width, height, meta_gravity_to_string (gravity)); if (display->grab_wireframe_active) { - meta_window_update_wireframe (window, x, y, width, height); + MetaRectangle new_position; + meta_rectangle_resize_with_gravity (&display->grab_wireframe_rect, + &new_position, + gravity, + width, + height); + meta_window_update_wireframe (window, + new_position.x, + new_position.y, + new_position.width, + new_position.height); } else { - meta_window_resize_with_gravity (window, TRUE, width, height, gravity); + /* Do any edge resistance/snapping */ + meta_window_edge_resistance_for_resize (window, + window->rect.width, + window->rect.height, + &width, + &height, + gravity, + smart_snap, + TRUE); + + /* We don't need to update unless the specified width and height + * are actually different from what we had before. + */ + if (window->rect.width != width || window->rect.height != height) + meta_window_resize_with_gravity (window, + TRUE, + width, + height, + gravity); } meta_window_update_keyboard_resize (window, FALSE); } diff --git a/src/window.c b/src/window.c index bc303af3..ebc83091 100644 --- a/src/window.c +++ b/src/window.c @@ -87,6 +87,19 @@ static void ensure_mru_position_after (MetaWindow *window, void meta_window_move_resize_now (MetaWindow *window); +static void update_move (MetaWindow *window, + gboolean snap, + int x, + int y); +static gboolean update_move_timeout (gpointer data); +static void update_resize (MetaWindow *window, + gboolean snap, + int x, + int y, + gboolean force); +static gboolean update_resize_timeout (gpointer data); + + /* FIXME we need an abstraction that covers all these queues. */ void meta_window_unqueue_calc_showing (MetaWindow *window); @@ -6368,10 +6381,111 @@ check_moveresize_frequency (MetaWindow *window, } } -static void update_move (MetaWindow *window, - unsigned int mask, - int x, - int y); +void +meta_window_edge_resistance_for_move (MetaWindow *window, + int old_x, + int old_y, + int *new_x, + int *new_y, + gboolean snap, + gboolean is_keyboard_op) +{ + MetaRectangle old_outer, proposed_outer, new_outer; + + meta_window_get_outer_rect (window, &old_outer); + proposed_outer = old_outer; + proposed_outer.x += (*new_x - old_x); + proposed_outer.y += (*new_y - old_y); + new_outer = proposed_outer; + + window->display->grab_last_user_action_was_snap = snap; + if (meta_display_apply_edge_resistance (window->display, + window, + &old_outer, + &new_outer, + update_move_timeout, + snap, + is_keyboard_op)) + { + /* meta_display_apply_edge_resistance independently applies + * resistance to both the right and left edges of new_outer as both + * could meet areas of resistance. But we don't want a resize, so we + * just have both edges move according to the stricter of the + * resistances. Same thing goes for top & bottom edges. + */ + MetaRectangle *reference; + int left_change, right_change, smaller_x_change; + int top_change, bottom_change, smaller_y_change; + + if (snap && !is_keyboard_op) + reference = &proposed_outer; + else + reference = &old_outer; + + left_change = BOX_LEFT (new_outer) - BOX_LEFT (*reference); + right_change = BOX_RIGHT (new_outer) - BOX_RIGHT (*reference); + if ( snap && is_keyboard_op && left_change == 0) + smaller_x_change = right_change; + else if (snap && is_keyboard_op && right_change == 0) + smaller_x_change = left_change; + else if (ABS (left_change) < ABS (right_change)) + smaller_x_change = left_change; + else + smaller_x_change = right_change; + + top_change = BOX_TOP (new_outer) - BOX_TOP (*reference); + bottom_change = BOX_BOTTOM (new_outer) - BOX_BOTTOM (*reference); + if ( snap && is_keyboard_op && top_change == 0) + smaller_y_change = bottom_change; + else if (snap && is_keyboard_op && bottom_change == 0) + smaller_y_change = top_change; + else if (ABS (top_change) < ABS (bottom_change)) + smaller_y_change = top_change; + else + smaller_y_change = bottom_change; + + *new_x = old_x + smaller_x_change + + (BOX_LEFT (*reference) - BOX_LEFT (old_outer)); + *new_y = old_y + smaller_y_change + + (BOX_TOP (*reference) - BOX_TOP (old_outer)); + } +} + +void +meta_window_edge_resistance_for_resize (MetaWindow *window, + int old_width, + int old_height, + int *new_width, + int *new_height, + int gravity, + gboolean snap, + gboolean is_keyboard_op) +{ + MetaRectangle old_outer, new_outer; + int new_outer_width, new_outer_height; + + meta_window_get_outer_rect (window, &old_outer); + new_outer_width = old_outer.width + (*new_width - old_width); + new_outer_height = old_outer.height + (*new_height - old_height); + meta_rectangle_resize_with_gravity (&old_outer, + &new_outer, + gravity, + new_outer_width, + new_outer_height); + + window->display->grab_last_user_action_was_snap = snap; + if (meta_display_apply_edge_resistance (window->display, + window, + &old_outer, + &new_outer, + update_resize_timeout, + snap, + is_keyboard_op)) + { + *new_width = old_width + (new_outer.width - old_outer.width); + *new_height = old_height + (new_outer.height - old_outer.height); + } +} static gboolean update_move_timeout (gpointer data) @@ -6379,7 +6493,7 @@ update_move_timeout (gpointer data) MetaWindow *window = data; update_move (window, - window->display->grab_last_used_state_for_resize, + window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y); @@ -6389,14 +6503,13 @@ update_move_timeout (gpointer data) static void update_move (MetaWindow *window, - unsigned int mask, + gboolean snap, int x, int y) { int dx, dy; int new_x, new_y; int old_x, old_y; - MetaRectangle old_outer, proposed_outer, new_outer; int shake_threshold; window->display->grab_latest_motion_x = x; @@ -6513,53 +6626,13 @@ update_move (MetaWindow *window, new_y = old_y; /* Do any edge resistance/snapping */ - meta_window_get_outer_rect (window, &old_outer); - proposed_outer = old_outer; - proposed_outer.x += (new_x - old_x); - proposed_outer.y += (new_y - old_y); - new_outer = proposed_outer; - - if (meta_display_apply_edge_resistance (window->display, - window, - &old_outer, - &new_outer, - update_move_timeout, - mask & ShiftMask)) - { - /* meta_display_apply_edge_resistance independently applies - * resistance to both the right and left edges of new_outer as both - * could meet areas of resistance. But we don't want a resize, so we - * just have both edges move according to the stricter of the - * resistances. Same thing goes for top & bottom edges. - */ - MetaRectangle *reference; - int left_change, right_change, smaller_x_change; - int top_change, bottom_change, smaller_y_change; - - if (mask & ShiftMask) - reference = &proposed_outer; - else - reference = &old_outer; - - left_change = BOX_LEFT (new_outer) - BOX_LEFT (*reference); - right_change = BOX_RIGHT (new_outer) - BOX_RIGHT (*reference); - if (ABS (left_change) < ABS (right_change)) - smaller_x_change = left_change; - else - smaller_x_change = right_change; - - top_change = BOX_TOP (new_outer) - BOX_TOP (*reference); - bottom_change = BOX_BOTTOM (new_outer) - BOX_BOTTOM (*reference); - if (ABS (top_change) < ABS (bottom_change)) - smaller_y_change = top_change; - else - smaller_y_change = bottom_change; - - new_x = old_x + smaller_x_change + - (BOX_LEFT (*reference) - BOX_LEFT (old_outer)); - new_y = old_y + smaller_y_change + - (BOX_TOP (*reference) - BOX_TOP (old_outer)); - } + meta_window_edge_resistance_for_move (window, + old_x, + old_y, + &new_x, + &new_y, + snap, + FALSE); if (window->display->grab_wireframe_active) meta_window_update_wireframe (window, new_x, new_y, @@ -6569,19 +6642,13 @@ update_move (MetaWindow *window, meta_window_move (window, TRUE, new_x, new_y); } -static void update_resize (MetaWindow *window, - unsigned int mask, - int x, - int y, - gboolean force); - static gboolean update_resize_timeout (gpointer data) { MetaWindow *window = data; update_resize (window, - window->display->grab_last_used_state_for_resize, + window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, TRUE); @@ -6590,7 +6657,7 @@ update_resize_timeout (gpointer data) static void update_resize (MetaWindow *window, - unsigned int mask, + gboolean snap, int x, int y, gboolean force) { @@ -6777,30 +6844,15 @@ update_resize (MetaWindow *window, } else { - MetaRectangle old_outer, new_outer; - int new_outer_width, new_outer_height; - /* Do any edge resistance/snapping */ - meta_window_get_outer_rect (window, &old_outer); - new_outer_width = old_outer.width + (new_w - old.width); - new_outer_height = old_outer.height + (new_h - old.height); - meta_rectangle_resize_with_gravity (&old_outer, - &new_outer, - gravity, - new_outer_width, - new_outer_height); - - window->display->grab_last_used_state_for_resize = mask; - if (meta_display_apply_edge_resistance (window->display, - window, - &old_outer, - &new_outer, - update_resize_timeout, - mask & ShiftMask)) - { - new_w = old.width + (new_outer.width - old_outer.width); - new_h = old.height + (new_outer.height - old_outer.height); - } + meta_window_edge_resistance_for_resize (window, + old.width, + old.height, + &new_w, + &new_h, + gravity, + snap, + FALSE); /* We don't need to update unless the specified width and height * are actually different from what we had before. @@ -6935,7 +6987,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_NW: /* no pointer round trip here, to keep in sync */ update_resize (window, - window->display->grab_last_used_state_for_resize, + window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, TRUE); @@ -6953,14 +7005,14 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, if (meta_grab_op_is_moving (window->display->grab_op)) { if (event->xbutton.root == window->screen->xroot) - update_move (window, event->xbutton.state, + update_move (window, event->xbutton.state & ShiftMask, event->xbutton.x_root, event->xbutton.y_root); } else if (meta_grab_op_is_resizing (window->display->grab_op)) { if (event->xbutton.root == window->screen->xroot) update_resize (window, - event->xbutton.state, + event->xbutton.state & ShiftMask, event->xbutton.x_root, event->xbutton.y_root, TRUE); @@ -6977,7 +7029,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, if (check_use_this_motion_notify (window, event)) update_move (window, - event->xmotion.state, + event->xmotion.state & ShiftMask, event->xmotion.x_root, event->xmotion.y_root); } @@ -6989,7 +7041,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, if (check_use_this_motion_notify (window, event)) update_resize (window, - event->xmotion.state, + event->xmotion.state & ShiftMask, event->xmotion.x_root, event->xmotion.y_root, FALSE); @@ -7004,7 +7056,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, { if (event->xcrossing.root == window->screen->xroot) update_move (window, - event->xcrossing.state, + event->xcrossing.state & ShiftMask, event->xcrossing.x_root, event->xcrossing.y_root); } @@ -7012,7 +7064,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, { if (event->xcrossing.root == window->screen->xroot) update_resize (window, - event->xcrossing.state, + event->xcrossing.state & ShiftMask, event->xcrossing.x_root, event->xcrossing.y_root, FALSE); diff --git a/src/window.h b/src/window.h index a39c96b6..c9077f91 100644 --- a/src/window.h +++ b/src/window.h @@ -390,6 +390,22 @@ void meta_window_activate (MetaWindow *window, void meta_window_make_fullscreen (MetaWindow *window); void meta_window_unmake_fullscreen (MetaWindow *window); +void meta_window_edge_resistance_for_move (MetaWindow *window, + int old_x, + int old_y, + int *new_x, + int *new_y, + gboolean snap, + gboolean is_keyboard_op); +void meta_window_edge_resistance_for_resize (MetaWindow *window, + int old_width, + int old_height, + int *new_width, + int *new_height, + int gravity, + gboolean snap, + gboolean is_keyboard_op); + /* args to move are window pos, not frame pos */ void meta_window_move (MetaWindow *window, gboolean user_op, -- cgit v1.2.1