summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2005-08-03 02:22:00 +0000
committerRay Strode <halfline@src.gnome.org>2005-08-03 02:22:00 +0000
commit2972ab6df6f48a11bec8c21eb97b02e4336c1062 (patch)
treef1f7530099aaa1615ce8db90360bf3bab7aaf512
parent8e927fd300313d83525734f757649f81fab5132d (diff)
downloadmetacity-2972ab6df6f48a11bec8c21eb97b02e4336c1062.tar.gz
Improve the behavior of keyboard move/resize and edge snapping. Still not
2005-08-03 Ray Strode <rstrode@redhat.com> Improve the behavior of keyboard move/resize and edge snapping. Still not perfect, bug 310888. * src/effects.c (draw_xor_rect): Make the outside of a wireframe rectangle line up with the outside edge of its window, instead of centering the wireframe edges on the window edges. * src/keybindings.c (process_keyboard_move_grab): allow edge snapping in wireframe mode. Adjust code to take into account changed semantics of find_next_*_edge functions. (process_keyboard_resize_grab_op_change): new function to take some orthogonal logic out of process_keyboard_resize_grab_op. Only allow keyboard resize cursor to go to flat edges, not corners. (process_keyboard_resize_grab): allow edge snapping in wireframe mode. Fix up snapping logic. * src/place.c (get_{vertical,horizontal}_edges): use GArray instead of int *, since the number of output edges isn't known until the middle of the function now. Use xor rect extents instead of window extends if in wireframe mode. (meta_window_find_next_{vertical,horizontal}_edge: add new source_edge_position parameter to specify which edge on the active window to start from when looking for next edge on the screen. Return the coordinate of the edge found and not the coordinate of where the window should be moved to snap to where the edge was found. * src/window.c (update_move): all the user to specify an edge to resize with mouse in keyboard resize mode. window
-rw-r--r--ChangeLog37
-rw-r--r--src/effects.c50
-rw-r--r--src/keybindings.c419
-rw-r--r--src/place.c269
-rw-r--r--src/place.h27
-rw-r--r--src/window.c83
6 files changed, 552 insertions, 333 deletions
diff --git a/ChangeLog b/ChangeLog
index 33052c9b..cbb44381 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2005-08-03 Ray Strode <rstrode@redhat.com>
+
+ Improve the behavior of keyboard move/resize and edge
+ snapping. Still not perfect, bug 310888.
+
+ * src/effects.c (draw_xor_rect): Make the outside of a
+ wireframe rectangle line up with the outside edge of its
+ window, instead of centering the wireframe edges on the
+ window edges.
+
+ * src/keybindings.c (process_keyboard_move_grab): allow
+ edge snapping in wireframe mode. Adjust code to take
+ into account changed semantics of find_next_*_edge
+ functions.
+ (process_keyboard_resize_grab_op_change): new function
+ to take some orthogonal logic out of
+ process_keyboard_resize_grab_op. Only allow keyboard
+ resize cursor to go to flat edges, not corners.
+ (process_keyboard_resize_grab): allow edge snapping in
+ wireframe mode. Fix up snapping logic.
+
+ * src/place.c (get_{vertical,horizontal}_edges): use
+ GArray instead of int *, since the number of output
+ edges isn't known until the middle of the function now.
+ Use xor rect extents instead of window extends if in
+ wireframe mode.
+ (meta_window_find_next_{vertical,horizontal}_edge: add
+ new source_edge_position parameter to specify which edge
+ on the active window to start from when looking for next
+ edge on the screen. Return the coordinate of the edge
+ found and not the coordinate of where the window should be
+ moved to snap to where the edge was found.
+
+ * src/window.c (update_move): all the user to specify
+ an edge to resize with mouse in keyboard resize mode.
+ window
+
2005-08-01 Elijah Newren <newren@gmail.com>
* src/metacity.schemas.in: Change default theme from "Simple" to
diff --git a/src/effects.c b/src/effects.c
index 122387b2..d48b8bdd 100644
--- a/src/effects.c
+++ b/src/effects.c
@@ -455,19 +455,31 @@ draw_xor_rect (MetaScreen *screen,
* a bit oddly.
*/
XSegment segments[8];
+ MetaRectangle shrunk_rect;
int i;
#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH
-
+
+ /* We don't want the wireframe going outside the window area.
+ * It makes it harder for the user to position windows and it exposes other
+ * annoying bugs.
+ */
+ shrunk_rect = *rect;
+
+ shrunk_rect.x += LINE_WIDTH / 2 + LINE_WIDTH % 2;
+ shrunk_rect.y += LINE_WIDTH / 2 + LINE_WIDTH % 2;
+ shrunk_rect.width -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
+ shrunk_rect.height -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
+
XDrawRectangle (screen->display->xdisplay,
screen->xroot,
screen->root_xor_gc,
- rect->x, rect->y,
- rect->width, rect->height);
+ shrunk_rect.x, shrunk_rect.y,
+ shrunk_rect.width, shrunk_rect.height);
/* Don't put lines inside small rectangles where they won't fit */
- if (rect->width < (LINE_WIDTH * 4) ||
- rect->height < (LINE_WIDTH * 4))
+ if (shrunk_rect.width < (LINE_WIDTH * 4) ||
+ shrunk_rect.height < (LINE_WIDTH * 4))
return;
if ((width >= 0) && (height >= 0))
@@ -502,11 +514,11 @@ draw_xor_rect (MetaScreen *screen,
box_height = text_height + 2 * LINE_WIDTH;
- box_x = rect->x + (rect->width - box_width) / 2;
- box_y = rect->y + (rect->height - box_height) / 2;
+ box_x = shrunk_rect.x + (shrunk_rect.width - box_width) / 2;
+ box_y = shrunk_rect.y + (shrunk_rect.height - box_height) / 2;
- if ((box_width < rect->width) &&
- (box_height < rect->height))
+ if ((box_width < shrunk_rect.width) &&
+ (box_height < shrunk_rect.height))
{
XFillRectangle (screen->display->xdisplay,
screen->xroot,
@@ -525,32 +537,32 @@ draw_xor_rect (MetaScreen *screen,
XFreeFontInfo (NULL, font_struct, 1);
- if ((box_width + LINE_WIDTH) >= (rect->width / 3))
+ if ((box_width + LINE_WIDTH) >= (shrunk_rect.width / 3))
return;
- if ((box_height + LINE_WIDTH) >= (rect->height / 3))
+ if ((box_height + LINE_WIDTH) >= (shrunk_rect.height / 3))
return;
}
}
}
/* Two vertical lines at 1/3 and 2/3 */
- segments[0].x1 = rect->x + rect->width / 3;
- segments[0].y1 = rect->y + LINE_WIDTH / 2 + LINE_WIDTH % 2;
+ segments[0].x1 = shrunk_rect.x + shrunk_rect.width / 3;
+ segments[0].y1 = shrunk_rect.y + LINE_WIDTH / 2 + LINE_WIDTH % 2;
segments[0].x2 = segments[0].x1;
- segments[0].y2 = rect->y + rect->height - LINE_WIDTH / 2;
+ segments[0].y2 = shrunk_rect.y + shrunk_rect.height - LINE_WIDTH / 2;
segments[1] = segments[0];
- segments[1].x1 = rect->x + (rect->width / 3) * 2;
+ segments[1].x1 = shrunk_rect.x + (shrunk_rect.width / 3) * 2;
segments[1].x2 = segments[1].x1;
/* Now make two horizontal lines at 1/3 and 2/3, but not
* overlapping the verticals
*/
- segments[2].x1 = rect->x + LINE_WIDTH / 2 + LINE_WIDTH % 2;
+ segments[2].x1 = shrunk_rect.x + LINE_WIDTH / 2 + LINE_WIDTH % 2;
segments[2].x2 = segments[0].x1 - LINE_WIDTH / 2;
- segments[2].y1 = rect->y + rect->height / 3;
+ segments[2].y1 = shrunk_rect.y + shrunk_rect.height / 3;
segments[2].y2 = segments[2].y1;
segments[3] = segments[2];
@@ -559,7 +571,7 @@ draw_xor_rect (MetaScreen *screen,
segments[4] = segments[3];
segments[4].x1 = segments[3].x2 + LINE_WIDTH;
- segments[4].x2 = rect->x + rect->width - LINE_WIDTH / 2;
+ segments[4].x2 = shrunk_rect.x + shrunk_rect.width - LINE_WIDTH / 2;
/* Second horizontal line is just like the first, but
* shifted down
@@ -568,7 +580,7 @@ draw_xor_rect (MetaScreen *screen,
while (i < 8)
{
segments[i] = segments[i - 3];
- segments[i].y1 = rect->y + (rect->height / 3) * 2;
+ segments[i].y1 = shrunk_rect.y + (shrunk_rect.height / 3) * 2;
segments[i].y2 = segments[i].y1;
++i;
}
diff --git a/src/keybindings.c b/src/keybindings.c
index d39ee529..c9af2404 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -1690,6 +1690,7 @@ process_keyboard_move_grab (MetaDisplay *display,
int incr;
gboolean smart_snap;
int edge;
+ int candidate_position;
handled = FALSE;
@@ -1711,13 +1712,7 @@ process_keyboard_move_grab (MetaDisplay *display,
meta_window_get_position (window, &x, &y);
}
- /* FIXME in wireframe mode the edge snapping is all fucked up
- * since the edge-find routines use window->rect. Window
- * constraints are also broken with wireframe.
- */
smart_snap = (event->xkey.state & ShiftMask) != 0;
- if (display->grab_wireframe_active)
- smart_snap = FALSE;
#define SMALL_INCREMENT 1
#define NORMAL_INCREMENT 10
@@ -1736,12 +1731,13 @@ process_keyboard_move_grab (MetaDisplay *display,
* since in wireframe we always moveresize at the end
* of the grab only.
*/
- meta_window_move_resize (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
+ if (!display->grab_wireframe_active)
+ meta_window_move_resize (display->grab_window,
+ TRUE,
+ display->grab_initial_window_pos.x,
+ display->grab_initial_window_pos.y,
+ display->grab_initial_window_pos.width,
+ display->grab_initial_window_pos.height);
display->grab_was_cancelled = TRUE;
}
@@ -1758,13 +1754,17 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_KP_Up:
y -= incr;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_horizontal_edge (window, FALSE);
- if (smart_snap || ((edge > y) && ABS (edge - y) < incr))
- y = edge;
- }
-
+ 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:
@@ -1773,13 +1773,17 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_KP_Down:
y += incr;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_horizontal_edge (window, TRUE);
- if (smart_snap || ((edge < y) && ABS (edge - y) < incr))
- y = edge;
- }
-
+ 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;
}
@@ -1792,12 +1796,17 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_KP_Left:
x -= incr;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_vertical_edge (window, FALSE);
- if (smart_snap || ((edge > x) && ABS (edge - x) < incr))
- x = edge;
- }
+ 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;
@@ -1807,13 +1816,17 @@ process_keyboard_move_grab (MetaDisplay *display,
case XK_KP_Right:
x += incr;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_vertical_edge (window, TRUE);
- if (smart_snap || ((edge < x) && ABS (edge - x) < incr))
- x = edge;
- }
+ 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;
}
@@ -1841,50 +1854,15 @@ process_keyboard_move_grab (MetaDisplay *display,
}
static gboolean
-process_keyboard_resize_grab (MetaDisplay *display,
- MetaScreen *screen,
- MetaWindow *window,
- XEvent *event,
- KeySym keysym)
+process_keyboard_resize_grab_op_change (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaWindow *window,
+ XEvent *event,
+ KeySym keysym)
{
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;
-
- handled = FALSE;
- /* don't care about releases, but eat them, don't end grab */
- if (event->type == KeyRelease)
- return TRUE;
-
- /* don't end grab on modifier key presses */
- if (is_modifier (display, event->xkey.keycode))
- return TRUE;
-
- if (keysym == XK_Escape)
- {
- /* End resize and restore to original state.
- * The move_resize is only needed when !wireframe
- * since in wireframe we always moveresize at the end
- * of the grab only.
- */
- meta_window_move_resize (display->grab_window,
- TRUE,
- display->grab_initial_window_pos.x,
- display->grab_initial_window_pos.y,
- display->grab_initial_window_pos.width,
- display->grab_initial_window_pos.height);
- display->grab_was_cancelled = TRUE;
-
- return FALSE;
- }
-
+ handled = FALSE;
switch (display->grab_op)
{
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
@@ -1918,12 +1896,12 @@ process_keyboard_resize_grab (MetaDisplay *display,
{
case XK_Left:
case XK_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
handled = TRUE;
break;
case XK_Right:
case XK_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
handled = TRUE;
break;
}
@@ -1934,12 +1912,12 @@ process_keyboard_resize_grab (MetaDisplay *display,
{
case XK_Left:
case XK_KP_Left:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
handled = TRUE;
break;
case XK_Right:
case XK_KP_Right:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
handled = TRUE;
break;
}
@@ -1950,12 +1928,12 @@ process_keyboard_resize_grab (MetaDisplay *display,
{
case XK_Up:
case XK_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
handled = TRUE;
break;
case XK_Down:
case XK_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
handled = TRUE;
break;
}
@@ -1966,12 +1944,12 @@ process_keyboard_resize_grab (MetaDisplay *display,
{
case XK_Up:
case XK_KP_Up:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
handled = TRUE;
break;
case XK_Down:
case XK_KP_Down:
- display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE;
+ display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
handled = TRUE;
break;
}
@@ -1994,33 +1972,80 @@ process_keyboard_resize_grab (MetaDisplay *display,
return TRUE;
}
+ return FALSE;
+}
+
+static gboolean
+process_keyboard_resize_grab (MetaDisplay *display,
+ MetaScreen *screen,
+ MetaWindow *window,
+ XEvent *event,
+ KeySym keysym)
+{
+ 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;
+
+ /* don't care about releases, but eat them, don't end grab */
+ if (event->type == KeyRelease)
+ return TRUE;
+
+ /* don't end grab on modifier key presses */
+ if (is_modifier (display, event->xkey.keycode))
+ return TRUE;
+
+ if (keysym == XK_Escape)
+ {
+ /* End resize and restore to original state.
+ * The move_resize is only needed when !wireframe
+ * since in wireframe we always moveresize at the end
+ * of the grab only.
+ */
+ if (!display->grab_wireframe_active)
+ meta_window_move_resize (display->grab_window,
+ TRUE,
+ display->grab_initial_window_pos.x,
+ display->grab_initial_window_pos.y,
+ display->grab_initial_window_pos.width,
+ display->grab_initial_window_pos.height);
+ display->grab_was_cancelled = TRUE;
+
+ return FALSE;
+ }
+
+ if (process_keyboard_resize_grab_op_change (display, screen, window,
+ event, keysym))
+ return TRUE;
+
if (display->grab_wireframe_active)
{
- x = display->grab_wireframe_rect.x;
- y = display->grab_wireframe_rect.y;
- orig_x = x;
- orig_y = y;
+ 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);
- x = orig_x;
- y = 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);
- /* FIXME in wireframe mode the edge snapping is all fucked up
- * since the edge-find routines use window->rect. Window
- * constraints are also broken with wireframe.
- */
smart_snap = (event->xkey.state & ShiftMask) != 0;
- if (display->grab_wireframe_active)
- smart_snap = FALSE;
#define SMALL_INCREMENT 1
#define NORMAL_INCREMENT 10
@@ -2071,17 +2096,27 @@ process_keyboard_resize_grab (MetaDisplay *display,
case NorthWestGravity:
case NorthEastGravity:
/* Move bottom edge up */
- height -= height_inc;
-
- if (!display->grab_wireframe_active)
+ 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))
{
- edge = meta_window_find_next_horizontal_edge (window, TRUE);
-
- if (smart_snap || ((edge > (y+height)) &&
- ABS (edge - (y+height)) < height_inc))
- height = edge - y;
+ if (candidate_position - y > 0)
+ height = candidate_position - y;
}
-
+ else if (height - height_inc > 0)
+ {
+ height -= height_inc;
+ }
+
handled = TRUE;
break;
@@ -2091,14 +2126,18 @@ process_keyboard_resize_grab (MetaDisplay *display,
/* Move top edge up */
y -= height_inc;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_horizontal_edge (window, FALSE);
+ 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;
- if (smart_snap || ((edge > y) && ABS (edge - y) < height_inc))
- y = edge;
- }
-
height += (orig_y - y);
break;
@@ -2122,33 +2161,48 @@ process_keyboard_resize_grab (MetaDisplay *display,
/* Move bottom edge down */
height += height_inc;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_horizontal_edge (window, TRUE);
+ edge = meta_window_find_next_horizontal_edge (window,
+ META_WINDOW_EDGE_BOTTOM,
+ TRUE);
- if (smart_snap || ((edge < (y+height)) &&
- ABS (edge - (y+height)) < height_inc))
- height = edge - y;
- }
-
- handled = 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 */
- y += height_inc;
+ edge = meta_window_find_next_horizontal_edge (window,
+ META_WINDOW_EDGE_TOP,
+ TRUE);
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_horizontal_edge (window, FALSE);
+ if (window->frame)
+ candidate_position = edge + window->frame->child_y;
+ else
+ candidate_position = edge;
- if (smart_snap || ((edge < y) && ABS (edge - y) < height_inc))
- y = 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 -= (y - orig_y);
break;
case EastGravity:
@@ -2168,17 +2222,21 @@ process_keyboard_resize_grab (MetaDisplay *display,
case EastGravity:
case SouthEastGravity:
case NorthEastGravity:
- /* Move left edge left */
x -= width_inc;
-
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_vertical_edge (window, TRUE);
- if (smart_snap || ((edge > x) && ABS (edge - x) < width_inc))
- x = edge;
- }
-
+ /* 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);
break;
@@ -2186,17 +2244,27 @@ process_keyboard_resize_grab (MetaDisplay *display,
case SouthWestGravity:
case NorthWestGravity:
/* Move right edge left */
- width -= width_inc;
-
- if (!display->grab_wireframe_active)
+ 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))
{
- edge = meta_window_find_next_vertical_edge (window, FALSE);
-
- if (smart_snap || ((edge > (x+width)) &&
- ABS (edge - (x+width)) < width_inc))
- width = edge - x;
+ if (candidate_position - x > 0)
+ width = candidate_position - x;
}
-
+ else if (width - width_inc > 0)
+ {
+ width -= width_inc;
+ }
+
handled = TRUE;
break;
@@ -2218,17 +2286,30 @@ process_keyboard_resize_grab (MetaDisplay *display,
case SouthEastGravity:
case NorthEastGravity:
/* Move left edge right */
- x += width_inc;
+ edge = meta_window_find_next_vertical_edge (window,
+ META_WINDOW_EDGE_LEFT,
+ TRUE);
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_vertical_edge (window, FALSE);
+ if (window->frame)
+ candidate_position = edge + window->frame->child_x;
+ else
+ candidate_position = edge;
- if (smart_snap || ((edge < x) && ABS (edge - x) < width_inc))
- x = 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 -= (x - orig_x);
break;
case WestGravity:
@@ -2237,15 +2318,19 @@ process_keyboard_resize_grab (MetaDisplay *display,
/* Move right edge right */
width += width_inc;
- if (!display->grab_wireframe_active)
- {
- edge = meta_window_find_next_vertical_edge (window, TRUE);
-
- if (smart_snap || ((edge > (x+width)) &&
- ABS (edge - (x+width)) < width_inc))
- width = edge - x;
- }
-
+ 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;
diff --git a/src/place.c b/src/place.c
index 5bfd954f..98631eac 100644
--- a/src/place.c
+++ b/src/place.c
@@ -1126,43 +1126,53 @@ get_vertical_edges (MetaWindow *window,
GSList *windows;
GSList *tmp;
int n_windows;
- int *edges;
- int i, j;
- int n_edges;
+ GArray *edges;
+ int edge, i;
MetaRectangle rect;
MetaRectangle work_area;
windows = get_windows_on_same_workspace (window, &n_windows);
- i = 0;
- /* 4 = workspace/screen edges */
- n_edges = n_windows * 2 + 4 + window->screen->n_xinerama_infos - 1;
-
- edges = g_new (int, n_edges);
+ edges = g_array_sized_new (FALSE, FALSE, sizeof (int),
+ n_windows * 2 + 4 /* 4 = workspace/screen edges */
+ + window->screen->n_xinerama_infos - 1
+ + 2 /* active window edges when in wireframe mode */);
/* workspace/screen edges */
meta_window_get_work_area_current_xinerama (window, &work_area);
+
+ g_array_append_val (edges, work_area.x);
+ edge = work_area.x + work_area.width;
+ g_array_append_val (edges, edge);
+ edge = 0;
+ g_array_append_val (edges, edge);
+ g_array_append_val (edges, window->screen->width);
- edges[i] = work_area.x;
- ++i;
- edges[i] = work_area.x + work_area.width;
- ++i;
- edges[i] = 0;
- ++i;
- edges[i] = window->screen->width;
- ++i;
+ /* Now get the xinerama screen edges */
+ for (i = 0; i < window->screen->n_xinerama_infos - 1; i++)
+ {
+ edge = window->screen->xinerama_infos[i].x_origin +
+ window->screen->xinerama_infos[i].width;
- g_assert (i == 4);
+ g_array_append_val (edges, edge);
+ }
+
+ if (window->display->grab_wireframe_active)
+ {
+ int left_edge, right_edge, top_edge, bottom_edge;
+
+ meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect,
+ &rect);
+
+ window_get_edges (window, &left_edge, &right_edge,
+ &top_edge, &bottom_edge);
+
+ g_array_append_val (edges, left_edge);
+ g_array_append_val (edges, right_edge);
+ }
+ else
+ meta_window_get_outer_rect (window, &rect);
- /* Now get the xinerama screen edges */
- for (j = 0; j < window->screen->n_xinerama_infos - 1; j++) {
- edges[i] = window->screen->xinerama_infos[j].x_origin +
- window->screen->xinerama_infos[j].width;
- ++i;
- }
-
- meta_window_get_outer_rect (window, &rect);
-
/* get window edges */
tmp = windows;
while (tmp != NULL)
@@ -1174,22 +1184,21 @@ get_vertical_edges (MetaWindow *window,
if (rects_overlap_vertically (&rect, &w_rect))
{
- window_get_edges (w, &edges[i], &edges[i+1], NULL, NULL);
- i += 2;
+ g_array_append_val (edges, w_rect.x);
+ edge = w_rect.x + w_rect.width;
+ g_array_append_val (edges, edge);
}
tmp = tmp->next;
}
- n_edges = i;
-
g_slist_free (windows);
/* Sort */
- qsort (edges, n_edges, sizeof (int), intcmp);
+ qsort (edges->data, edges->len, sizeof (int), intcmp);
- *edges_p = edges;
- *n_edges_p = n_edges;
-}
+ *n_edges_p = edges->len;
+ *edges_p = (int *) g_array_free (edges, FALSE);
+}
static void
get_horizontal_edges (MetaWindow *window,
@@ -1199,41 +1208,52 @@ get_horizontal_edges (MetaWindow *window,
GSList *windows;
GSList *tmp;
int n_windows;
- int *edges;
- int i, j;
- int n_edges;
+ GArray *edges;
+ int edge, i;
MetaRectangle rect;
MetaRectangle work_area;
windows = get_windows_on_same_workspace (window, &n_windows);
- i = 0;
- n_edges = n_windows * 2 + 4 + window->screen->n_xinerama_infos - 1; /* 4 = workspace/screen edges */
- edges = g_new (int, n_edges);
+ edges = g_array_sized_new (FALSE, FALSE, sizeof (int),
+ n_windows * 2 + 4 /* 4 = workspace/screen edges */
+ + window->screen->n_xinerama_infos - 1
+ + 2 /* active window edges when in wireframe mode */);
/* workspace/screen edges */
meta_window_get_work_area_current_xinerama (window, &work_area);
- edges[i] = work_area.y;
- ++i;
- edges[i] = work_area.y + work_area.height;
- ++i;
- edges[i] = 0;
- ++i;
- edges[i] = window->screen->height;
- ++i;
-
- g_assert (i == 4);
-
+ g_array_append_val (edges, work_area.y);
+ edge = work_area.y + work_area.height;
+ g_array_append_val (edges, edge);
+ edge = 0;
+ g_array_append_val (edges, edge);
+ g_array_append_val (edges, window->screen->height);
+
/* Now get the xinerama screen edges */
- for (j = 0; j < window->screen->n_xinerama_infos - 1; j++) {
- edges[i] = window->screen->xinerama_infos[j].y_origin +
- window->screen->xinerama_infos[j].height;
- ++i;
- }
+ for (i = 0; i < window->screen->n_xinerama_infos - 1; i++)
+ {
+ edge = window->screen->xinerama_infos[i].y_origin +
+ window->screen->xinerama_infos[i].height;
+ g_array_append_val (edges, edge);
+ }
- meta_window_get_outer_rect (window, &rect);
-
+ if (window->display->grab_wireframe_active)
+ {
+ int left_edge, right_edge, top_edge, bottom_edge;
+
+ meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect,
+ &rect);
+
+ window_get_edges (window, &left_edge, &right_edge,
+ &top_edge, &bottom_edge);
+
+ g_array_append_val (edges, top_edge);
+ g_array_append_val (edges, bottom_edge);
+ }
+ else
+ meta_window_get_outer_rect (window, &rect);
+
/* get window edges */
tmp = windows;
while (tmp != NULL)
@@ -1245,60 +1265,75 @@ get_horizontal_edges (MetaWindow *window,
if (rects_overlap_horizontally (&rect, &w_rect))
{
- window_get_edges (w, NULL, NULL, &edges[i], &edges[i+1]);
- i += 2;
+ g_array_append_val (edges, w_rect.y);
+ edge = w_rect.y + w_rect.height;
+ g_array_append_val (edges, edge);
}
tmp = tmp->next;
}
- n_edges = i;
-
g_slist_free (windows);
/* Sort */
- qsort (edges, n_edges, sizeof (int), intcmp);
+ qsort (edges->data, edges->len, sizeof (int), intcmp);
- *edges_p = edges;
- *n_edges_p = n_edges;
+ *n_edges_p = edges->len;
+ *edges_p = (int *) g_array_free (edges, FALSE);
}
int
meta_window_find_next_vertical_edge (MetaWindow *window,
+ MetaWindowEdgePosition source_edge_position,
gboolean right)
{
- int left_edge, right_edge;
+ int left_edge, right_edge, source_edge;
int *edges;
int i;
int n_edges;
int retval;
get_vertical_edges (window, &edges, &n_edges);
-
+
/* Find next */
- meta_window_get_position (window, &retval, NULL);
+ if (window->display->grab_wireframe_active)
+ {
+ MetaRectangle rect;
+
+ meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect,
+ &rect);
+
+ left_edge = rect.x;
+ right_edge = left_edge + rect.width;
+ }
+ else
+ window_get_edges (window, &left_edge, &right_edge, NULL, NULL);
+
+ switch (source_edge_position)
+ {
+ case META_WINDOW_EDGE_LEFT:
+ source_edge = left_edge;
+ break;
+
+ case META_WINDOW_EDGE_RIGHT:
+ source_edge = right_edge;
+ break;
+
+ case META_WINDOW_EDGE_TOP:
+ case META_WINDOW_EDGE_BOTTOM:
+ default:
+ g_assert_not_reached ();
+ }
+
+ retval = source_edge;
- window_get_edges (window, &left_edge, &right_edge, NULL, NULL);
-
if (right)
{
i = 0;
while (i < n_edges)
{
- if (edges[i] > right_edge)
+ if (edges[i] > source_edge)
{
- /* This is the one we want, snap right
- * edge of window to edges[i]
- */
retval = edges[i];
- if (window->frame)
- {
- retval -= window->frame->rect.width;
- retval += window->frame->child_x;
- }
- else
- {
- retval -= window->rect.width;
- }
break;
}
@@ -1312,13 +1347,9 @@ meta_window_find_next_vertical_edge (MetaWindow *window,
{
--i;
- if (edges[i] < left_edge)
+ if (edges[i] < source_edge)
{
- /* This is the one we want */
retval = edges[i];
- if (window->frame)
- retval += window->frame->child_x;
-
break;
}
}
@@ -1332,9 +1363,10 @@ meta_window_find_next_vertical_edge (MetaWindow *window,
int
meta_window_find_next_horizontal_edge (MetaWindow *window,
+ MetaWindowEdgePosition source_edge_position,
gboolean down)
{
- int top_edge, bottom_edge;
+ int top_edge, bottom_edge, source_edge;
int *edges;
int i;
int n_edges;
@@ -1343,30 +1375,45 @@ meta_window_find_next_horizontal_edge (MetaWindow *window,
get_horizontal_edges (window, &edges, &n_edges);
/* Find next */
- meta_window_get_position (window, NULL, &retval);
+ if (window->display->grab_wireframe_active)
+ {
+ MetaRectangle rect;
+
+ meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect,
+ &rect);
+
+ top_edge = rect.y;
+ bottom_edge = top_edge + rect.height;
+ }
+ else
+ window_get_edges (window, NULL, NULL, &top_edge, &bottom_edge);
+
+ switch (source_edge_position)
+ {
+ case META_WINDOW_EDGE_TOP:
+ source_edge = top_edge;
+ break;
+
+ case META_WINDOW_EDGE_BOTTOM:
+ source_edge = bottom_edge;
+ break;
+
+ case META_WINDOW_EDGE_LEFT:
+ case META_WINDOW_EDGE_RIGHT:
+ default:
+ g_assert_not_reached ();
+ }
+
+ retval = source_edge;
- window_get_edges (window, NULL, NULL, &top_edge, &bottom_edge);
-
if (down)
{
i = 0;
while (i < n_edges)
{
- if (edges[i] > bottom_edge)
+ if (edges[i] > source_edge)
{
- /* This is the one we want, snap right
- * edge of window to edges[i]
- */
retval = edges[i];
- if (window->frame)
- {
- retval -= window->frame->rect.height;
- retval += window->frame->child_y;
- }
- else
- {
- retval -= window->rect.height;
- }
break;
}
@@ -1380,13 +1427,9 @@ meta_window_find_next_horizontal_edge (MetaWindow *window,
{
--i;
- if (edges[i] < top_edge)
+ if (edges[i] < source_edge)
{
- /* This is the one we want */
retval = edges[i];
- if (window->frame)
- retval += window->frame->child_y;
-
break;
}
}
@@ -1421,11 +1464,10 @@ meta_window_find_nearest_vertical_edge (MetaWindow *window,
int left_pos, right_pos;
left_pos = edges[i];
- if (window->frame)
- left_pos += window->frame->child_x;
if (window->frame)
{
+ left_pos += window->frame->child_x;
right_pos = edges[i] - window->frame->rect.width;
right_pos += window->frame->child_x;
}
@@ -1492,11 +1534,10 @@ meta_window_find_nearest_horizontal_edge (MetaWindow *window,
int top_pos, bottom_pos;
top_pos = edges[i];
- if (window->frame)
- top_pos += window->frame->child_y;
if (window->frame)
{
+ top_pos += window->frame->child_y;
bottom_pos = edges[i] - window->frame->rect.height;
bottom_pos += window->frame->child_y;
}
diff --git a/src/place.h b/src/place.h
index a628c563..624ac841 100644
--- a/src/place.h
+++ b/src/place.h
@@ -25,6 +25,16 @@
#include "window.h"
#include "frame.h"
+typedef enum _MetaWindowEdgePosition MetaWindowEdgePosition;
+
+enum _MetaWindowEdgePosition
+{
+ META_WINDOW_EDGE_TOP = 0,
+ META_WINDOW_EDGE_LEFT,
+ META_WINDOW_EDGE_RIGHT,
+ META_WINDOW_EDGE_BOTTOM
+};
+
void meta_window_place (MetaWindow *window,
MetaFrameGeometry *fgeom,
int x,
@@ -32,14 +42,16 @@ void meta_window_place (MetaWindow *window,
int *new_x,
int *new_y);
-/* Returns the position to move the window to in order
+/* Returns the position to move the specified window edge to in order
* to snap it to the next edge in the given direction,
* while moving.
*/
int meta_window_find_next_vertical_edge (MetaWindow *window,
- gboolean right);
-int meta_window_find_next_horizontal_edge (MetaWindow *window,
+ MetaWindowEdgePosition source_edge_position,
gboolean down);
+int meta_window_find_next_horizontal_edge (MetaWindow *window,
+ MetaWindowEdgePosition source_edge_position,
+ gboolean right);
/* Returns the position to move the window to in order
* to snap it to the nearest edge, while moving.
@@ -49,13 +61,4 @@ int meta_window_find_nearest_vertical_edge (MetaWindow *window,
int meta_window_find_nearest_horizontal_edge (MetaWindow *window,
int y_pos);
-
-/* FIXME need edge-snap functions for resizing as well, those
- * behave somewhat differently.
- */
-
#endif
-
-
-
-
diff --git a/src/window.c b/src/window.c
index 8ebb36ec..c6b67690 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6498,27 +6498,22 @@ update_move (MetaWindow *window,
if (window->maximized)
return;
- if (window->display->grab_wireframe_active)
+ if (mask & ShiftMask)
{
- /* FIXME Horribly broken, does not honor position
- * constraints
- */
- meta_window_update_wireframe (window, new_x, new_y,
- window->display->grab_wireframe_rect.width,
- window->display->grab_wireframe_rect.height);
+ /* snap to edges */
+ if (dy != 0)
+ new_x = meta_window_find_nearest_vertical_edge (window, new_x);
+
+ if (dx != 0)
+ new_y = meta_window_find_nearest_horizontal_edge (window, new_y);
}
+
+ if (window->display->grab_wireframe_active)
+ meta_window_update_wireframe (window, new_x, new_y,
+ window->display->grab_wireframe_rect.width,
+ window->display->grab_wireframe_rect.height);
else
- {
- /* FIXME, edge snapping broken in wireframe mode */
- if (mask & ShiftMask)
- {
- /* snap to edges */
- new_x = meta_window_find_nearest_vertical_edge (window, new_x);
- new_y = meta_window_find_nearest_horizontal_edge (window, new_y);
- }
-
- meta_window_move (window, TRUE, new_x, new_y);
- }
+ meta_window_move (window, TRUE, new_x, new_y);
}
static void update_resize (MetaWindow *window,
@@ -6562,6 +6557,50 @@ update_resize (MetaWindow *window,
/* FIXME this is only used in wireframe mode */
new_x = window->display->grab_anchor_window_pos.x;
new_y = window->display->grab_anchor_window_pos.y;
+
+ if (window->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN)
+ {
+ if ((dx > 0) && (dy > 0))
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if ((dx < 0) && (dy > 0))
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if ((dx > 0) && (dy < 0))
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if ((dx < 0) && (dy < 0))
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if (dx < 0)
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if (dx > 0)
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if (dy > 0)
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ else if (dy < 0)
+ {
+ window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N;
+ meta_window_update_keyboard_resize (window, TRUE);
+ }
+ }
switch (window->display->grab_op)
{
@@ -7270,11 +7309,13 @@ warp_grab_pointer (MetaWindow *window,
if (window == window->display->grab_window &&
window->display->grab_wireframe_active)
- rect = window->display->grab_wireframe_rect;
+ {
+ meta_window_get_xor_rect (window, &window->display->grab_wireframe_rect,
+ &rect);
+ }
else
{
- rect = window->rect;
- meta_window_get_position (window, &rect.x, &rect.y);
+ meta_window_get_outer_rect (window, &rect);
}
switch (grab_op)