diff --git a/ChangeLog b/ChangeLog index 33052c9bc..cbb443817 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2005-08-03 Ray Strode + + 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 * src/metacity.schemas.in: Change default theme from "Simple" to diff --git a/src/effects.c b/src/effects.c index 122387b2c..d48b8bdd1 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 d39ee5292..c9af24046 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; - } - 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) + 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)) { - edge = meta_window_find_next_horizontal_edge (window, FALSE); - - if (smart_snap || ((edge < y) && ABS (edge - y) < height_inc)) - y = edge; + 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) + 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)) { - edge = meta_window_find_next_vertical_edge (window, FALSE); - - if (smart_snap || ((edge < x) && ABS (edge - x) < width_inc)) - x = edge; + 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 5bfd954f8..98631eacb 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); - - 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; - - g_assert (i == 4); + + 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); /* 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); - + 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_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); + /* 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_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); - g_assert (i == 4); - /* 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); - window_get_edges (window, &left_edge, &right_edge, NULL, NULL); - + /* Find next */ + 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; + 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 a628c5631..624ac8417 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 8ebb36ec7..c6b67690a 100644 --- a/src/window.c +++ b/src/window.c @@ -6498,27 +6498,22 @@ update_move (MetaWindow *window, if (window->maximized) return; + if (mask & ShiftMask) + { + /* 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) - { - /* 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); - } + 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)