? foo.patch
? metacity-resize-fixup.patch
? snap.patch
? stamp-h1
? src/.frame.h.swo
? src/.keybindings.c.swo
? src/.keybindings.c.swp
? src/.place.c.swn
? src/.place.c.swo
? src/fix-resizing-and-moves.patch
? src/foo
? src/foo.patch
? src/gPlanarity
? src/wm-tester/bar
Index: src/effects.c
===================================================================
RCS file: /cvs/gnome/metacity/src/effects.c,v
retrieving revision 1.18
diff -u -p -r1.18 effects.c
--- src/effects.c	7 Jun 2005 15:52:56 -0000	1.18
+++ src/effects.c	28 Jul 2005 03:46:27 -0000
@@ -446,7 +446,7 @@ meta_effects_begin_wireframe (MetaScreen
 
 static void
 draw_xor_rect (MetaScreen          *screen,
-               const MetaRectangle *rect,
+               const MetaRectangle *unshrunk_rect,
                int                  width,
                int                  height)
 {
@@ -455,10 +455,23 @@ draw_xor_rect (MetaScreen          *scre
    * a bit oddly.
    */
   XSegment segments[8];
+  MetaRectangle *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.
+   */
+  rect = g_new0 (MetaRectangle, 1);
+  *rect = *unshrunk_rect;
+
+  rect->x += LINE_WIDTH / 2 + LINE_WIDTH % 2;
+  rect->y += LINE_WIDTH / 2 + LINE_WIDTH % 2;
+  rect->width -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
+  rect->height -= LINE_WIDTH + 2 * (LINE_WIDTH % 2);
+
   XDrawRectangle (screen->display->xdisplay,
                   screen->xroot,
                   screen->root_xor_gc,
@@ -468,7 +481,10 @@ draw_xor_rect (MetaScreen          *scre
   /* Don't put lines inside small rectangles where they won't fit */
   if (rect->width < (LINE_WIDTH * 4) ||
       rect->height < (LINE_WIDTH * 4))
-    return;
+    {
+      g_free (rect);
+      return;
+    }
 
   if ((width >= 0) && (height >= 0))
     {
@@ -526,10 +542,16 @@ draw_xor_rect (MetaScreen          *scre
               XFreeFontInfo (NULL, font_struct, 1);
 
               if ((box_width + LINE_WIDTH) >= (rect->width / 3))
-                return;
+                {
+                  g_free (rect);
+                  return;
+                }
 
               if ((box_height + LINE_WIDTH) >= (rect->height / 3))
-                return;
+                {
+                  g_free (rect);
+                  return;
+                }
             }
         }
     }
@@ -578,6 +600,7 @@ draw_xor_rect (MetaScreen          *scre
                  screen->root_xor_gc,
                  segments,
                  G_N_ELEMENTS (segments));
+  g_free (rect);
 }
 
 void
Index: src/keybindings.c
===================================================================
RCS file: /cvs/gnome/metacity/src/keybindings.c,v
retrieving revision 1.111
diff -u -p -r1.111 keybindings.c
--- src/keybindings.c	26 May 2005 19:58:17 -0000	1.111
+++ src/keybindings.c	28 Jul 2005 03:46:30 -0000
@@ -1690,6 +1690,7 @@ process_keyboard_move_grab (MetaDisplay 
   int incr;
   gboolean smart_snap;
   int edge;
+  int candidate_position;
   
   handled = FALSE;
 
@@ -1711,13 +1712,7 @@ process_keyboard_move_grab (MetaDisplay 
       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 
        * 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 
     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 
     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 
     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 
     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 
 }
 
 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 (MetaDispla
         {
         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 (MetaDispla
         {
         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 (MetaDispla
         {
         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 (MetaDispla
         {
         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 (MetaDispla
       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 (MetaDispla
         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))
+            {
+              if (candidate_position - y > 0)
+                height = candidate_position - y;
+            }
+          else if (height - height_inc > 0)
             {
-              edge = meta_window_find_next_horizontal_edge (window, TRUE);
-              
-              if (smart_snap || ((edge > (y+height)) &&
-                                 ABS (edge - (y+height)) < height_inc))
-                height = edge - y;
+              height -= height_inc;
             }
-          
+
           handled = TRUE;
           break;
 
@@ -2091,14 +2126,18 @@ process_keyboard_resize_grab (MetaDispla
           /* 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 (MetaDispla
           /* Move bottom edge down */
           height += height_inc;
 
-          if (!display->grab_wireframe_active)
-            {
-              edge = meta_window_find_next_horizontal_edge (window, TRUE);
-
-               if (smart_snap || ((edge < (y+height)) &&
-                                  ABS (edge - (y+height)) < height_inc))
-                 height = edge - y;
-            }
-          
-          handled = TRUE;
+          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 */
-          y += height_inc;
-
-          if (!display->grab_wireframe_active)
+          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))
             {
-              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 (MetaDispla
         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 (MetaDispla
         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))
+            {
+              if (candidate_position - x > 0)
+                width = candidate_position - x;
+            }
+          else if (width - width_inc > 0)
             {
-              edge = meta_window_find_next_vertical_edge (window, FALSE);
-              
-              if (smart_snap || ((edge > (x+width)) &&
-                                 ABS (edge - (x+width)) < width_inc))
-                width = edge - x;
+              width -= width_inc;
             }
-          
+
           handled = TRUE;
           break;
 
@@ -2218,17 +2286,30 @@ process_keyboard_resize_grab (MetaDispla
         case SouthEastGravity:
         case NorthEastGravity:
           /* Move left edge right */
-          x += width_inc;
-
-          if (!display->grab_wireframe_active)
+          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))
             {
-              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 (MetaDispla
           /* 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;
 
Index: src/place.c
===================================================================
RCS file: /cvs/gnome/metacity/src/place.c,v
retrieving revision 1.43
diff -u -p -r1.43 place.c
--- src/place.c	25 Jul 2005 02:12:58 -0000	1.43
+++ src/place.c	28 Jul 2005 03:46:31 -0000
@@ -1140,43 +1140,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)
@@ -1188,22 +1198,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,
@@ -1213,41 +1222,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)
@@ -1259,60 +1279,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;
             }
           
@@ -1326,13 +1361,9 @@ meta_window_find_next_vertical_edge (Met
         {
           --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;
             }
         }
@@ -1346,9 +1377,10 @@ meta_window_find_next_vertical_edge (Met
 
 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;
@@ -1357,30 +1389,45 @@ meta_window_find_next_horizontal_edge (M
   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;
             }
           
@@ -1394,13 +1441,9 @@ meta_window_find_next_horizontal_edge (M
         {
           --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;
             }
         }
@@ -1435,11 +1478,10 @@ meta_window_find_nearest_vertical_edge (
       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;
         }
@@ -1506,11 +1548,10 @@ meta_window_find_nearest_horizontal_edge
       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;
         }
Index: src/place.h
===================================================================
RCS file: /cvs/gnome/metacity/src/place.h,v
retrieving revision 1.3
diff -u -p -r1.3 place.h
--- src/place.h	26 Jul 2001 03:58:23 -0000	1.3
+++ src/place.h	28 Jul 2005 03:46:31 -0000
@@ -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 *wind
                         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_ed
 
 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
-
-
-
-
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.391
diff -u -p -r1.391 window.c
--- src/window.c	25 Jul 2005 01:52:50 -0000	1.391
+++ src/window.c	28 Jul 2005 03:46:36 -0000
@@ -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          *
   
   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)
