summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElijah Newren <newren@gmail.com>2005-11-12 23:47:31 +0000
committerElijah Newren <newren@src.gnome.org>2005-11-12 23:47:31 +0000
commit330a2d1df6efe140a71801a25954bf2f970bd73b (patch)
tree850cfec6d1bc33266773506ecadc1720e3961ce9
parent98f561cc0029ea8fabcc42ce1bc2a6197741b167 (diff)
downloadmetacity-330a2d1df6efe140a71801a25954bf2f970bd73b.tar.gz
Get keyboard buildup edge resistance working, and convert old (and buggy)
2005-11-12 Elijah Newren <newren@gmail.com> 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
-rw-r--r--ChangeLog86
-rw-r--r--constraints-ideas.txt2
-rw-r--r--src/display.c157
-rw-r--r--src/display.h5
-rw-r--r--src/keybindings.c305
-rw-r--r--src/window.c236
-rw-r--r--src/window.h16
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 <newren@gmail.com>
+
+ 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 <newren@gmail.com>
* 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,