diff --git a/ChangeLog b/ChangeLog
index ab710bfa8..012b09824 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2003-10-12  Havoc Pennington  <hp@redhat.com>
+
+        Merge reduced_resources mode patch from the branch. Offers
+	wireframe and no-animations.
+	
+	* src/window.c (implement_showing): no animation if we are 
+	in reduced resources mode
+
+	* src/prefs.c: add REDUCED_RESOURCES pref
+
+	* src/window.c (meta_window_update_keyboard_resize): fix to 
+	modify grab_anchor_window_pos to grab_wireframe_rect if 
+	appropriate instead of window->rect
+
+	* src/display.h (struct _MetaDisplay): add grab_start_serial used
+	to avoid responding to events that occurred prior to the grab
+	initialization.
+
+	Still broken in various ways, specifically EnterNotify that
+	occurred prior to XGrabPointer is processed as if it occurred
+	after.
+	
+	* src/window.c (meta_window_update_keyboard_move): add this
+	instead of meta_window_warp_pointer() crack
+
+	* src/effects.c (meta_effects_update_wireframe): draw a kind of
+	grid for the wireframe, instead of just a rectangle, like twm
+
+	* src/screen.c (meta_screen_new): line width of 3 for the XOR gc
+
+        "Reduced resources" mode based on wireframe patch from
+	Erwann Chenede. Still pretty buggy.
+	
+	* src/keybindings.c (process_keyboard_move_grab)
+	(process_keyboard_resize_grab): add gruesome wireframe hacks
+
+	* src/display.c (meta_display_end_grab_op): end wireframe
+	(meta_display_begin_grab_op): begin wireframe
+
+	* src/effects.c (meta_effects_end_wireframe) 
+	(meta_effects_update_wireframe, meta_effects_begin_wireframe): 
+	routines to draw the wireframe stuff
+
+	* src/window.c (window_should_be_showing): hide window when 
+	doing wireframe, commented out as it breaks grab
+	* src/window.c (meta_window_refresh_resize_popup): handle wireframe
+
+	* src/screen.c (meta_screen_new): create a screen->root_xor_gc 
+	for use in drawing wireframes
+	
+	* src/frames.c (meta_frames_push_delay_exposes): repaint
+	everything before we delay
+
 2003-10-11  Havoc Pennington  <hp@pobox.com>
 
 	* src/display.c (meta_display_begin_grab_op): initialize
diff --git a/README b/README
index 7d5716603..aacb0fb73 100644
--- a/README
+++ b/README
@@ -370,12 +370,11 @@ A: This one is also in rationales.txt. Because "ouija board" UI, where
      http://pobox.com/~hp/free-software-ui.html
      http://pobox.com/~hp/features.html   
 
-Q: Why no wireframe move/resize?
+Q: Why does wireframe move/resize suck?
 
-A: It's implemented in a patch that will be merged for GNOME 2.6
-   and is already in some vendor packages.
+A: You can turn it on with the reduced_resources setting.
 
-   But: Because it has low usability, and is a pain
+   But: it has low usability, and is a pain
    to implement, and there's no reason opaque move/resize should be a
    problem on any setup that can run a modern desktop worth a darn to
    begin with.
diff --git a/src/display.c b/src/display.c
index c09867692..719789c6a 100644
--- a/src/display.c
+++ b/src/display.c
@@ -35,6 +35,7 @@
 #include "resizepopup.h"
 #include "workspace.h"
 #include "bell.h"
+#include "effects.h"
 #include <X11/Xatom.h>
 #include <X11/cursorfont.h>
 #ifdef HAVE_SOLARIS_XINERAMA
@@ -1219,7 +1220,8 @@ event_callback (XEvent   *event,
        * goes to the frame.
        */
       frame_was_receiver = TRUE;
-      meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event\n");
+      meta_topic (META_DEBUG_EVENTS, "Frame was receiver of event for %s\n",
+                  window->desc);
     }
 
 #ifdef HAVE_XSYNC
@@ -1231,6 +1233,7 @@ event_callback (XEvent   *event,
       
       if (display->grab_op != META_GRAB_OP_NONE &&
           display->grab_window != NULL &&
+          event->xany.serial > display->grab_start_serial &&
           grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (display->grab_window, event);
     }
@@ -1296,7 +1299,8 @@ event_callback (XEvent   *event,
     case ButtonPress:
       if ((window &&
            grab_op_is_mouse (display->grab_op) &&
-           display->grab_button != (int) event->xbutton.button && 
+           display->grab_button != (int) event->xbutton.button &&
+           event->xany.serial > display->grab_start_serial &&
            display->grab_window == window) ||
           grab_op_is_keyboard (display->grab_op))
         {
@@ -1446,16 +1450,19 @@ event_callback (XEvent   *event,
       break;
     case ButtonRelease:
       if (display->grab_window == window &&
+          event->xany.serial > display->grab_start_serial &&
           grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       break;
     case MotionNotify:
       if (display->grab_window == window &&
+          event->xany.serial > display->grab_start_serial &&
           grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       break;
     case EnterNotify:
       if (display->grab_window == window &&
+          event->xany.serial > display->grab_start_serial &&
           grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       /* do this even if window->has_focus to avoid races */
@@ -1519,6 +1526,7 @@ event_callback (XEvent   *event,
       break;
     case LeaveNotify:
       if (display->grab_window == window &&
+          event->xany.serial > display->grab_start_serial &&
           grab_op_is_mouse (display->grab_op))
         meta_window_handle_mouse_grab_op_event (window, event);
       else if (window != NULL)
@@ -2797,8 +2805,9 @@ meta_display_begin_grab_op (MetaDisplay *display,
   Window grab_xwindow;
   
   meta_topic (META_DEBUG_WINDOW_OPS,
-              "Doing grab op %d on window %s button %d pointer already grabbed: %d\n",
-              op, window ? window->desc : "none", button, pointer_already_grabbed);
+              "Doing grab op %d on window %s button %d pointer already grabbed: %d pointer pos %d,%d\n",
+              op, window ? window->desc : "none", button, pointer_already_grabbed,
+              root_x, root_y);
   
   if (display->grab_op != META_GRAB_OP_NONE)
     {
@@ -2808,6 +2817,9 @@ meta_display_begin_grab_op (MetaDisplay *display,
       return FALSE;
     }
 
+  /* We'll ignore any events < this serial. */
+  display->grab_start_serial = XNextRequest (display->xdisplay);
+  
   /* FIXME:
    *   If we have no MetaWindow we do our best
    *   and try to do the grab on the RootWindow.
@@ -2823,7 +2835,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
   
   if (pointer_already_grabbed)
     display->grab_have_pointer = TRUE;
-      
+  
   meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow,
                                    timestamp);
 
@@ -2860,8 +2872,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
   display->grab_xwindow = grab_xwindow;
   display->grab_button = button;
   display->grab_mask = modmask;
-  display->grab_initial_root_x = root_x;
-  display->grab_initial_root_y = root_y;
+  display->grab_anchor_root_x = root_x;
+  display->grab_anchor_root_y = root_y;
   display->grab_latest_motion_x = root_x;
   display->grab_latest_motion_y = root_y;
   display->grab_last_moveresize_time.tv_sec = 0;
@@ -2870,6 +2882,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
 #ifdef HAVE_XSYNC
   display->grab_update_alarm = None;
 #endif
+  display->grab_was_cancelled = FALSE;
   
   if (display->grab_window)
     {
@@ -2877,9 +2890,34 @@ meta_display_begin_grab_op (MetaDisplay *display,
       meta_window_get_position (display->grab_window,
                                 &display->grab_initial_window_pos.x,
                                 &display->grab_initial_window_pos.y);
+      display->grab_anchor_window_pos = display->grab_initial_window_pos;
 
+      display->grab_wireframe_active =
+        meta_prefs_get_reduced_resources () && 
+        (meta_grab_op_is_resizing (display->grab_op) ||
+         meta_grab_op_is_moving (display->grab_op));
+      
+      if (display->grab_wireframe_active)
+        {
+          /* FIXME we should really display the outer frame rect,
+           * but that complicates all the move/resize code since
+           * it works in terms of window rect.
+           */
+          display->grab_wireframe_rect = window->rect;
+          if (window->frame)
+            {
+              display->grab_wireframe_rect.x += window->frame->rect.x;
+              display->grab_wireframe_rect.y += window->frame->rect.y;
+            }
+          
+          meta_window_calc_showing (display->grab_window);
+          meta_effects_begin_wireframe (display->grab_window->screen,
+                                        &display->grab_wireframe_rect);
+        }
+      
 #ifdef HAVE_XSYNC
-      if (meta_grab_op_is_resizing (display->grab_op) &&
+      if (!display->grab_wireframe_active &&
+          meta_grab_op_is_resizing (display->grab_op) &&
           display->grab_window->update_counter != None)
         {
           XSyncAlarmAttributes values;
@@ -3009,6 +3047,21 @@ meta_display_end_grab_op (MetaDisplay *display,
                          display->grab_update_alarm);
     }
 #endif /* HAVE_XSYNC */
+
+  if (display->grab_wireframe_active)
+    {
+      display->grab_wireframe_active = FALSE;
+      meta_effects_end_wireframe (display->grab_window->screen,
+                                  &display->grab_wireframe_rect);
+      if (!display->grab_was_cancelled)
+        meta_window_move_resize (display->grab_window,
+                                 TRUE,
+                                 display->grab_wireframe_rect.x,
+                                 display->grab_wireframe_rect.y,
+                                 display->grab_wireframe_rect.width,
+                                 display->grab_wireframe_rect.height);
+      meta_window_calc_showing (display->grab_window);
+    }
   
   display->grab_window = NULL;
   display->grab_screen = NULL;
diff --git a/src/display.h b/src/display.h
index f96253d61..d6d349542 100644
--- a/src/display.h
+++ b/src/display.h
@@ -225,19 +225,24 @@ struct _MetaDisplay
   MetaScreen *grab_screen;
   MetaWindow *grab_window;
   Window      grab_xwindow;
+  gulong      grab_start_serial;
   int         grab_button;
-  int         grab_initial_root_x;
-  int         grab_initial_root_y;
+  int         grab_anchor_root_x;
+  int         grab_anchor_root_y;
+  MetaRectangle grab_anchor_window_pos;
   int         grab_latest_motion_x;
   int         grab_latest_motion_y;
   gulong      grab_mask;
   guint       grab_have_pointer : 1;
   guint       grab_have_keyboard : 1;
+  guint       grab_wireframe_active : 1;
+  guint       grab_was_cancelled : 1;
+  MetaRectangle grab_wireframe_rect;
   MetaRectangle grab_initial_window_pos;
   MetaResizePopup *grab_resize_popup;
   GTimeVal    grab_last_moveresize_time;
   Time        grab_motion_notify_time;
-
+  
   /* we use property updates as sentinels for certain window focus events
    * to avoid some race conditions on EnterNotify events
    */
diff --git a/src/effects.c b/src/effects.c
index 18fa59475..dee152961 100644
--- a/src/effects.c
+++ b/src/effects.c
@@ -409,5 +409,108 @@ meta_effects_draw_box_animation (MetaScreen     *screen,
   XFlush (context->screen->display->xdisplay);  
 }
 
+void
+meta_effects_begin_wireframe (MetaScreen          *screen,
+                              const MetaRectangle *rect)
+{
+  /* Grab the X server to avoid screen dirt */
+  meta_display_grab (screen->display);
+  meta_ui_push_delay_exposes (screen->ui);  
 
+  meta_effects_update_wireframe (screen, NULL, rect);
+}
+
+static void
+draw_xor_rect (MetaScreen          *screen,
+               const MetaRectangle *rect)
+{
+  /* The lines in the center can't overlap the rectangle or each
+   * other, or the XOR gets reversed. So we have to draw things
+   * a bit oddly.
+   */
+  XSegment segments[8];
+  int i;
+  
+#define LINE_WIDTH META_WIREFRAME_XOR_LINE_WIDTH
+  
+  XDrawRectangle (screen->display->xdisplay,
+                  screen->xroot,
+                  screen->root_xor_gc,
+                  rect->x, rect->y,
+                  rect->width, 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))
+    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].x2 = segments[0].x1;
+  segments[0].y2 = rect->y + rect->height - LINE_WIDTH / 2;  
+
+  segments[1] = segments[0];
+  segments[1].x1 = rect->x + (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].x2 = segments[0].x1 - LINE_WIDTH / 2;
+  segments[2].y1 = rect->y + rect->height / 3;
+  segments[2].y2 = segments[2].y1;
+
+  segments[3] = segments[2];
+  segments[3].x1 = segments[2].x2 + LINE_WIDTH;
+  segments[3].x2 = segments[1].x1 - LINE_WIDTH / 2;
+  
+  segments[4] = segments[3];
+  segments[4].x1 = segments[3].x2 + LINE_WIDTH;
+  segments[4].x2 = rect->x + rect->width - LINE_WIDTH / 2;
+
+  /* Second horizontal line is just like the first, but
+   * shifted down
+   */
+  i = 5;
+  while (i < 8)
+    {
+      segments[i] = segments[i - 3];
+      segments[i].y1 = rect->y + (rect->height / 3) * 2;
+      segments[i].y2 = segments[i].y1;
+      ++i;
+    }
+  
+  XDrawSegments (screen->display->xdisplay,
+                 screen->xroot,
+                 screen->root_xor_gc,
+                 segments,
+                 G_N_ELEMENTS (segments));
+}
+
+void
+meta_effects_update_wireframe (MetaScreen          *screen,
+                               const MetaRectangle *old_rect,
+                               const MetaRectangle *new_rect)
+{
+  if (old_rect)
+    draw_xor_rect (screen, old_rect);
+    
+  if (new_rect)
+    draw_xor_rect (screen, new_rect);
+    
+  XFlush (screen->display->xdisplay);
+}
+
+void
+meta_effects_end_wireframe (MetaScreen          *screen,
+                            const MetaRectangle *old_rect)
+{
+  meta_effects_update_wireframe (screen, old_rect, NULL);
+  
+  meta_display_ungrab (screen->display);
+  meta_ui_pop_delay_exposes (screen->ui);
+}
 
diff --git a/src/effects.h b/src/effects.h
index 744ffc12e..82dc0c518 100644
--- a/src/effects.h
+++ b/src/effects.h
@@ -41,4 +41,12 @@ void meta_effects_draw_box_animation (MetaScreen     *screen,
                                       double          seconds_duration,
                                       MetaBoxAnimType anim_type);
 
+void meta_effects_begin_wireframe  (MetaScreen          *screen,
+                                    const MetaRectangle *rect);
+void meta_effects_update_wireframe (MetaScreen          *screen,
+                                    const MetaRectangle *old_rect,
+                                    const MetaRectangle *new_rect);
+void meta_effects_end_wireframe    (MetaScreen          *screen,
+                                    const MetaRectangle *old_rect);
+
 #endif /* META_EFFECTS_H */
diff --git a/src/frames.c b/src/frames.c
index a99c13aa4..3086837ef 100644
--- a/src/frames.c
+++ b/src/frames.c
@@ -2110,6 +2110,13 @@ get_control (MetaFrames *frames,
 void
 meta_frames_push_delay_exposes (MetaFrames *frames)
 {
+  if (frames->expose_delay_count == 0)
+    {
+      /* Make sure we've repainted things */
+      gdk_window_process_all_updates ();
+      XFlush (gdk_display);
+    }
+  
   frames->expose_delay_count += 1;
 }
 
diff --git a/src/keybindings.c b/src/keybindings.c
index 2d91fe2c5..3c50d390f 100644
--- a/src/keybindings.c
+++ b/src/keybindings.c
@@ -27,6 +27,7 @@
 #include "frame.h"
 #include "place.h"
 #include "prefs.h"
+#include "effects.h"
 
 #include <X11/keysym.h>
 #include <string.h>
@@ -1693,10 +1694,24 @@ process_keyboard_move_grab (MetaDisplay *display,
   if (is_modifier (display, event->xkey.keycode))
     return TRUE;
 
-  meta_window_get_position (window, &x, &y);
+  if (display->grab_wireframe_active)
+    {
+      x = display->grab_wireframe_rect.x;
+      y = display->grab_wireframe_rect.y;
+    }
+  else
+    {
+      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
 
@@ -1709,13 +1724,18 @@ process_keyboard_move_grab (MetaDisplay *display,
 
   if (keysym == XK_Escape)
     {
-      /* End move and restore to original position */
+      /* 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;
     }
   
   /* When moving by increments, we still snap to edges if the move
@@ -1729,11 +1749,14 @@ process_keyboard_move_grab (MetaDisplay *display,
     case XK_KP_Prior:
     case XK_Up:
     case XK_KP_Up:
-      edge = meta_window_find_next_horizontal_edge (window, FALSE);
       y -= incr;
-          
-      if (smart_snap || ((edge > y) && ABS (edge - y) < incr))
-        y = edge;
+
+      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;
+        }
           
       handled = TRUE;
       break;
@@ -1741,11 +1764,14 @@ process_keyboard_move_grab (MetaDisplay *display,
     case XK_KP_Next:
     case XK_Down:
     case XK_KP_Down:
-      edge = meta_window_find_next_horizontal_edge (window, TRUE);
       y += incr;
 
-      if (smart_snap || ((edge < y) && ABS (edge - y) < incr))
-        y = edge;
+      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;
+        }
           
       handled = TRUE;
       break;
@@ -1757,11 +1783,14 @@ process_keyboard_move_grab (MetaDisplay *display,
     case XK_KP_End:
     case XK_Left:
     case XK_KP_Left:
-      edge = meta_window_find_next_vertical_edge (window, FALSE);
       x -= incr;
-          
-      if (smart_snap || ((edge > x) && ABS (edge - x) < incr))
-        x = edge;
+
+      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;
+        }
 
       handled = TRUE;
       break;
@@ -1769,18 +1798,43 @@ process_keyboard_move_grab (MetaDisplay *display,
     case XK_KP_Next:
     case XK_Right:
     case XK_KP_Right:
-      edge = meta_window_find_next_vertical_edge (window, TRUE);
       x += incr;
-      if (smart_snap || ((edge < x) && ABS (edge - x) < incr))
-        x = edge;
+
+      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;
+        }
+      
       handled = TRUE;
       break;
     }
 
   if (handled)
     {
-      meta_window_move (window, TRUE, x, y);
-      meta_window_warp_pointer (window, display->grab_op);
+      meta_topic (META_DEBUG_KEYBINDINGS,
+                  "Computed new window location %d,%d due to keypress\n",
+                  x, y);
+      if (display->grab_wireframe_active)
+        {
+          MetaRectangle new_xor;
+
+          new_xor = display->grab_wireframe_rect;
+          new_xor.x = x;
+          new_xor.y = y;
+          
+          meta_effects_update_wireframe (window->screen,
+                                         &display->grab_wireframe_rect,
+                                         &new_xor);
+          display->grab_wireframe_rect = new_xor;
+        }
+      else
+        {
+          meta_window_move (window, TRUE, x, y);
+        }
+      
+      meta_window_update_keyboard_move (window);
     }
 
   return handled;
@@ -1815,13 +1869,18 @@ process_keyboard_resize_grab (MetaDisplay *display,
 
   if (keysym == XK_Escape)
     {
-      /* End resize and restore to original state */
+      /* 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;
     }
@@ -1931,20 +1990,38 @@ process_keyboard_resize_grab (MetaDisplay *display,
 
   if (handled)
     {
-      meta_window_update_resize_grab_op (window, TRUE);
+      meta_window_update_keyboard_resize (window, TRUE);
       return TRUE; 
-    } 
+    }
 
-  meta_window_get_position (window, &orig_x, &orig_y);
-  x = orig_x;
-  y = orig_y;
-  width = window->rect.width;
-  height = window->rect.height;
+  if (display->grab_wireframe_active)
+    {
+      x = display->grab_wireframe_rect.x;
+      y = display->grab_wireframe_rect.y;
+      orig_x = x;
+      orig_y = 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;
+    }
 
   gravity = meta_resize_gravity_from_grab_op (display->grab_op);
-  
-  smart_snap = (event->xkey.state & ShiftMask) != 0;
 
+  /* 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
 
@@ -1994,12 +2071,16 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case NorthWestGravity:
         case NorthEastGravity:
           /* Move bottom edge up */
-          edge = meta_window_find_next_horizontal_edge (window, TRUE);
           height -= height_inc;
           
-          if (smart_snap || ((edge > (y+height)) &&
-                             ABS (edge - (y+height)) < height_inc))
-            height = edge - y;
+          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;
           break;
@@ -2008,11 +2089,15 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case SouthWestGravity:
         case SouthEastGravity:
           /* Move top edge up */
-          edge = meta_window_find_next_horizontal_edge (window, FALSE);
           y -= height_inc;
-          
-          if (smart_snap || ((edge > y) && ABS (edge - y) < height_inc))
-            y = edge;
+
+          if (!display->grab_wireframe_active)
+            {
+              edge = meta_window_find_next_horizontal_edge (window, FALSE);          
+
+              if (smart_snap || ((edge > y) && ABS (edge - y) < height_inc))
+                y = edge;
+            }
           
           height += (orig_y - y);
           break;
@@ -2035,12 +2120,16 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case NorthWestGravity:
         case NorthEastGravity:
           /* Move bottom edge down */
-          edge = meta_window_find_next_horizontal_edge (window, TRUE);
           height += height_inc;
-          
-          if (smart_snap || ((edge < (y+height)) &&
-                             ABS (edge - (y+height)) < height_inc))
-            height = edge - y;
+
+          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;
           break;
@@ -2049,11 +2138,15 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case SouthWestGravity:
         case SouthEastGravity:
           /* Move top edge down */
-          edge = meta_window_find_next_horizontal_edge (window, FALSE);
           y += height_inc;
-          
-          if (smart_snap || ((edge < y) && ABS (edge - y) < height_inc))
-            y = edge;
+
+          if (!display->grab_wireframe_active)
+            {
+              edge = meta_window_find_next_horizontal_edge (window, FALSE);
+
+              if (smart_snap || ((edge < y) && ABS (edge - y) < height_inc))
+                y = edge;
+            }
           
           height -= (y - orig_y);
           break;
@@ -2076,11 +2169,15 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case SouthEastGravity:
         case NorthEastGravity:
           /* Move left edge left */
-          edge = meta_window_find_next_vertical_edge (window, TRUE);
           x -= width_inc;
           
-          if (smart_snap || ((edge > x) && ABS (edge - x) < width_inc))
-            x = edge;
+          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;
+            }
           
           width += (orig_x - x);
           break;
@@ -2089,12 +2186,16 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case SouthWestGravity:
         case NorthWestGravity:
           /* Move right edge left */
-          edge = meta_window_find_next_vertical_edge (window, FALSE);
           width -= width_inc;
           
-          if (smart_snap || ((edge > (x+width)) &&
-                             ABS (edge - (x+width)) < width_inc))
-            width = edge - x;
+          if (!display->grab_wireframe_active)
+            {
+              edge = meta_window_find_next_vertical_edge (window, FALSE);
+              
+              if (smart_snap || ((edge > (x+width)) &&
+                                 ABS (edge - (x+width)) < width_inc))
+                width = edge - x;
+            }
           
           handled = TRUE;
           break;
@@ -2117,11 +2218,15 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case SouthEastGravity:
         case NorthEastGravity:
           /* Move left edge right */
-          edge = meta_window_find_next_vertical_edge (window, FALSE);
           x += width_inc;
-          
-          if (smart_snap || ((edge < x) && ABS (edge - x) < width_inc))
-            x = edge;
+
+          if (!display->grab_wireframe_active)
+            {
+              edge = meta_window_find_next_vertical_edge (window, FALSE);
+
+              if (smart_snap || ((edge < x) && ABS (edge - x) < width_inc))
+                x = edge;
+            }
           
           width -= (x - orig_x);
           break;
@@ -2130,12 +2235,16 @@ process_keyboard_resize_grab (MetaDisplay *display,
         case SouthWestGravity:
         case NorthWestGravity:
           /* Move right edge right */
-          edge = meta_window_find_next_vertical_edge (window, TRUE);
           width += width_inc;
-          
-          if (smart_snap || ((edge > (x+width)) &&
-                             ABS (edge - (x+width)) < width_inc))
-            width = edge - x;
+
+          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;
+            }
           
           handled = TRUE;
           break;
@@ -2162,8 +2271,32 @@ process_keyboard_resize_grab (MetaDisplay *display,
   
   if (handled)
     {
-      meta_window_move_resize (window, TRUE, x, y, width, height);
-      meta_window_update_resize_grab_op (window, FALSE);
+      meta_topic (META_DEBUG_KEYBINDINGS,
+                  "Computed new window location %d,%d %dx%d due to keypress\n",
+                  x, y, width, height);
+      
+      if (display->grab_wireframe_active)
+        {
+          MetaRectangle new_xor;
+      
+          new_xor.x = x;
+          new_xor.y = y;
+          new_xor.width = width;
+          new_xor.height = height;
+
+          meta_effects_update_wireframe (window->screen,
+                                         &window->display->grab_wireframe_rect,
+                                         &new_xor);
+          window->display->grab_wireframe_rect = new_xor;
+
+          /* do this after drawing the wires, so we don't draw over it */
+          meta_window_refresh_resize_popup (window);
+        }
+      else
+        {
+          meta_window_move_resize (window, TRUE, x, y, width, height);
+        }
+      meta_window_update_keyboard_resize (window, FALSE);
     }
 
   return handled;
diff --git a/src/metacity.schemas.in b/src/metacity.schemas.in
index 4350b67a4..5cf9f103d 100644
--- a/src/metacity.schemas.in
+++ b/src/metacity.schemas.in
@@ -257,6 +257,25 @@
       </locale>
     </schema>
 
+    <schema>
+      <key>/schemas/apps/metacity/general/reduced_resources</key>
+      <applyto>/apps/metacity/general/reduced_resources</applyto>
+      <owner>metacity</owner>
+      <type>bool</type>
+      <default>false</default>
+      <locale name="C">
+         <short>If true, trade off usability for less resource usage</short>
+         <long>
+          If true, metacity will give the user less feedback and 
+        less sense of "direct manipulation", by using wireframes, 
+        avoiding animations, or other means. This is a significant 
+        reduction in usability for many users, but may allow 
+        legacy applications and terminal servers to function 
+        when they would otherwise be impractical.
+         </long>
+      </locale>
+    </schema>
+
     <!-- Window Keybindings -->
 
     <schema>
diff --git a/src/prefs.c b/src/prefs.c
index 9ed41bcd2..81af51e3e 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -51,6 +51,7 @@
 #define KEY_APPLICATION_BASED "/apps/metacity/general/application_based"
 #define KEY_DISABLE_WORKAROUNDS "/apps/metacity/general/disable_workarounds"
 #define KEY_BUTTON_LAYOUT "/apps/metacity/general/button_layout"
+#define KEY_REDUCED_RESOURCES "/apps/metacity/general/reduced_resources"
 
 #define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
 #define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
@@ -83,6 +84,8 @@ static gboolean auto_raise = FALSE;
 static gboolean auto_raise_delay = 500;
 static gboolean provide_visual_bell = TRUE;
 static gboolean bell_is_audible = TRUE;
+static gboolean reduced_resources = FALSE;
+
 static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_INVALID;
 static MetaButtonLayout button_layout = {
   {
@@ -129,6 +132,7 @@ static gboolean update_command            (const char  *name,
                                            const char  *value);
 static gboolean update_workspace_name     (const char  *name,
                                            const char  *value);
+static gboolean update_reduced_resources  (gboolean     value);
 
 static void change_notify (GConfClient    *client,
                            guint           cnxn_id,
@@ -372,7 +376,6 @@ meta_prefs_init (void)
   cleanup_error (&err);
   update_button_layout (str_val);
   g_free (str_val);
-#endif /* HAVE_GCONF */
   
   bool_val = gconf_client_get_bool (default_client, KEY_VISUAL_BELL,
                                     &err);
@@ -388,6 +391,12 @@ meta_prefs_init (void)
   update_visual_bell_type (str_val);
   g_free (str_val);
 
+  bool_val = gconf_client_get_bool (default_client, KEY_REDUCED_RESOURCES,
+				    &err);
+  cleanup_error (&err);
+  update_reduced_resources (bool_val);
+#endif /* HAVE_GCONF */
+  
   /* Load keybindings prefs */
   init_bindings ();
 
@@ -733,6 +742,22 @@ change_notify (GConfClient    *client,
       if (update_visual_bell_type (str))
 	queue_changed (META_PREF_VISUAL_BELL_TYPE);
     }
+  else if (strcmp (key, KEY_REDUCED_RESOURCES) == 0)
+    {
+      gboolean b;
+
+      if (value && value->type != GCONF_VALUE_BOOL)
+        {
+          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
+                        KEY_REDUCED_RESOURCES);
+          goto out;
+        }
+
+      b = value ? gconf_value_get_bool (value) : reduced_resources;
+
+      if (update_reduced_resources (b))
+        queue_changed (META_PREF_REDUCED_RESOURCES);
+    }
   else
     {
       meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n",
@@ -1239,6 +1264,16 @@ update_auto_raise_delay (int value)
 
   return old != auto_raise_delay;
 }
+
+static gboolean
+update_reduced_resources (gboolean value)
+{
+  gboolean old = reduced_resources;
+
+  reduced_resources = value;
+
+  return old != reduced_resources;
+}
 #endif /* HAVE_GCONF */
 
 #ifdef WITH_VERBOSE_MODE
@@ -1305,6 +1340,10 @@ meta_preference_to_string (MetaPreference pref)
     case META_PREF_VISUAL_BELL_TYPE:
       return "VISUAL_BELL_TYPE";
       break;
+
+    case META_PREF_REDUCED_RESOURCES:
+      return "REDUCED_RESOURCES";
+      break;
     }
 
   return "(unknown)";
@@ -1974,6 +2013,12 @@ meta_prefs_get_auto_raise_delay ()
   return auto_raise_delay;
 }
 
+gboolean
+meta_prefs_get_reduced_resources ()
+{
+  return reduced_resources;
+}
+
 MetaKeyBindingAction
 meta_prefs_get_keybinding_action (const char *name)
 {
diff --git a/src/prefs.h b/src/prefs.h
index 18a20df3f..c0a0bc667 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -45,7 +45,8 @@ typedef enum
   META_PREF_WORKSPACE_NAMES,
   META_PREF_VISUAL_BELL,
   META_PREF_AUDIBLE_BELL,
-  META_PREF_VISUAL_BELL_TYPE
+  META_PREF_VISUAL_BELL_TYPE,
+  META_PREF_REDUCED_RESOURCES
 } MetaPreference;
 
 typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -69,6 +70,7 @@ gboolean                    meta_prefs_get_application_based  (void);
 gboolean                    meta_prefs_get_disable_workarounds (void);
 gboolean                    meta_prefs_get_auto_raise         (void);
 int                         meta_prefs_get_auto_raise_delay   (void);
+gboolean                    meta_prefs_get_reduced_resources  (void);
 
 const char*                 meta_prefs_get_command            (int i);
 
diff --git a/src/run-metacity.sh b/src/run-metacity.sh
index 98ccbf74b..e0d9265ab 100755
--- a/src/run-metacity.sh
+++ b/src/run-metacity.sh
@@ -1,11 +1,11 @@
 #! /bin/bash
 
 if test -z "$XNEST_DISPLAY"; then
-  XNEST_DISPLAY=:1
+  XNEST_DISPLAY=:8
 fi
 
 if test -z "$CLIENT_DISPLAY"; then
-  CLIENT_DISPLAY=:1
+  CLIENT_DISPLAY=:8
 fi
 
 if test -z "$METACITY_DISPLAY"; then
diff --git a/src/screen.c b/src/screen.c
index 348d467bb..18647d3a5 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -538,10 +538,23 @@ meta_screen_new (MetaDisplay *display,
   screen->starting_corner = META_SCREEN_TOPLEFT;
 
   screen->showing_desktop = FALSE;
+
+  {
+    XGCValues gc_values;
+    
+    gc_values.subwindow_mode = IncludeInferiors;
+    gc_values.function = GXinvert;
+    gc_values.line_width = META_WIREFRAME_XOR_LINE_WIDTH;
+    
+    screen->root_xor_gc = XCreateGC (screen->display->xdisplay,
+                                     screen->xroot,
+                                     GCSubwindowMode | GCFunction | GCLineWidth,
+                                     &gc_values);
+  }
   
   screen->xinerama_infos = NULL;
   screen->n_xinerama_infos = 0;
-  screen->last_xinerama_index = 0;
+  screen->last_xinerama_index = 0;  
   
   reload_xinerama_infos (screen);
   
@@ -679,6 +692,9 @@ meta_screen_free (MetaScreen *screen)
   
   if (screen->work_area_idle != 0)
     g_source_remove (screen->work_area_idle);
+
+  XFreeGC (screen->display->xdisplay,
+           screen->root_xor_gc);
   
   g_free (screen->screen_name);
   g_free (screen);
diff --git a/src/screen.h b/src/screen.h
index 64fa4948c..24b29ab7e 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -56,6 +56,8 @@ typedef enum
   META_SCREEN_RIGHT
 } MetaScreenDirection;
 
+#define META_WIREFRAME_XOR_LINE_WIDTH 5
+
 struct _MetaScreen
 {
   MetaDisplay *display;
@@ -108,6 +110,9 @@ struct _MetaScreen
   guint showing_desktop : 1;
   
   int closing;
+
+  /* gc for XOR on root window */
+  GC root_xor_gc;
 };
 
 MetaScreen*   meta_screen_new                 (MetaDisplay                *display,
diff --git a/src/window.c b/src/window.c
index 9bb5b3e5c..edddc27e2 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1206,6 +1206,14 @@ window_should_be_showing (MetaWindow  *window)
         showing = FALSE;
     }
 
+#if 0
+  /* 5. See if we're drawing wireframe
+   */
+  if (window->display->grab_window == window &&
+      window->display->grab_wireframe_active)    
+    showing = FALSE;
+#endif
+  
   return showing;
 }
 
@@ -1230,7 +1238,8 @@ implement_showing (MetaWindow *window,
        * if we are mapped now, we are supposed to
        * be minimized, and we are on the current workspace.
        */
-      if (on_workspace && window->minimized && window->mapped)
+      if (on_workspace && window->minimized && window->mapped &&
+          !meta_prefs_get_reduced_resources ())
         {
 	  MetaRectangle icon_rect, window_rect;
 	  gboolean result;
@@ -1856,7 +1865,7 @@ meta_window_unmaximize (MetaWindow  *window)
       if (meta_grab_op_is_moving (window->display->grab_op) &&
           window->display->grab_window == window)
         {
-          window->display->grab_initial_window_pos = window->saved_rect;
+          window->display->grab_anchor_window_pos = window->saved_rect;
         }
 
       meta_window_move_resize (window,
@@ -5620,7 +5629,7 @@ check_moveresize_frequency (MetaWindow *window)
   window->display->grab_last_moveresize_time = current_time;
   
   meta_topic (META_DEBUG_RESIZING,
-              " Doing move/resize now (%g of %g seconds elapsed)\n",
+              " Checked moveresize freq, allowing move/resize now (%g of %g seconds elapsed)\n",
               elapsed / 1000.0, 1.0 / max_resizes_per_second);
   
   return TRUE;
@@ -5639,12 +5648,20 @@ update_move (MetaWindow  *window,
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
   
-  dx = x - window->display->grab_initial_root_x;
-  dy = y - window->display->grab_initial_root_y;
+  dx = x - window->display->grab_anchor_root_x;
+  dy = y - window->display->grab_anchor_root_y;
 
-  new_x = window->display->grab_initial_window_pos.x + dx;
-  new_y = window->display->grab_initial_window_pos.y + dy;
+  new_x = window->display->grab_anchor_window_pos.x + dx;
+  new_y = window->display->grab_anchor_window_pos.y + dy;
 
+  meta_verbose ("x,y = %d,%d anchor ptr %d,%d anchor pos %d,%d dx,dy %d,%d\n",
+                x, y,
+                window->display->grab_anchor_root_x,
+                window->display->grab_anchor_root_y,
+                window->display->grab_anchor_window_pos.x,
+                window->display->grab_anchor_window_pos.y,
+                dx, dy);
+  
   /* shake loose (unmaximize) maximized window if dragged beyond the threshold
    * in the Y direction. You can't pull a window loose via X motion.
    */
@@ -5733,14 +5750,33 @@ update_move (MetaWindow  *window,
   if (window->maximized)
     return;
 
-  if (mask & ShiftMask)
+  if (window->display->grab_wireframe_active)
     {
-      /* 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);
-    }
+      /* FIXME Horribly broken, does not honor position
+       * constraints
+       */
+      MetaRectangle new_xor;
+      new_xor = window->display->grab_wireframe_rect;
+      new_xor.x = new_x;
+      new_xor.y = new_y;
 
-  meta_window_move (window, TRUE, new_x, new_y);
+      meta_effects_update_wireframe (window->screen,
+                                     &window->display->grab_wireframe_rect,
+                                     &new_xor);
+      window->display->grab_wireframe_rect = new_xor;
+    }
+  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);
+    }
 }
 
 static void
@@ -5751,16 +5787,21 @@ update_resize (MetaWindow *window,
   int new_w, new_h;
   int gravity;
   MetaRectangle old;
+  int new_x, new_y;
   
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
   
-  dx = x - window->display->grab_initial_root_x;
-  dy = y - window->display->grab_initial_root_y;
+  dx = x - window->display->grab_anchor_root_x;
+  dy = y - window->display->grab_anchor_root_y;
 
-  new_w = window->display->grab_initial_window_pos.width;
-  new_h = window->display->grab_initial_window_pos.height;
+  new_w = window->display->grab_anchor_window_pos.width;
+  new_h = window->display->grab_anchor_window_pos.height;
 
+  /* 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;
+  
   switch (window->display->grab_op)
     {
     case META_GRAB_OP_RESIZING_SE:
@@ -5779,6 +5820,7 @@ update_resize (MetaWindow *window,
     case META_GRAB_OP_KEYBOARD_RESIZING_SW:
     case META_GRAB_OP_KEYBOARD_RESIZING_W:
       new_w -= dx;
+      new_x += dx;
       break;
       
     default:
@@ -5803,6 +5845,7 @@ update_resize (MetaWindow *window,
     case META_GRAB_OP_KEYBOARD_RESIZING_NE:
     case META_GRAB_OP_KEYBOARD_RESIZING_NW:
       new_h -= dy;
+      new_y += dy;
       break;
     default:
       break;
@@ -5812,12 +5855,42 @@ update_resize (MetaWindow *window,
     return;
   
   old = window->rect;
-  
+
   /* compute gravity of client during operation */
   gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
   g_assert (gravity >= 0);
   
-  meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
+  if (window->display->grab_wireframe_active)
+    {
+      /* FIXME This is crap. For example, the wireframe isn't
+       * constrained in the way that a real resize would be. An
+       * obvious elegant solution is to unmap the window during
+       * wireframe, but still resize it; however, that probably
+       * confuses broken clients that have problems with opaque
+       * resize, they probably don't track their visibility.
+       */
+      MetaRectangle new_xor;
+      
+      if ((new_x + new_w <= new_x) || (new_y + new_h <= new_y))
+        return;
+      
+      new_xor.x = new_x;
+      new_xor.y = new_y;
+      new_xor.width = new_w;
+      new_xor.height = new_h;
+
+      meta_effects_update_wireframe (window->screen,
+                                     &window->display->grab_wireframe_rect,
+                                     &new_xor);
+      window->display->grab_wireframe_rect = new_xor;
+
+      /* do this after drawing the wires, so we don't draw over it */
+      meta_window_refresh_resize_popup (window);
+    }
+  else
+    {
+      meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
+    }
 
   /* If we don't actually resize the window, we clear the timestamp,
    * so we'll quickly try again.  Otherwise you get "stuck" because
@@ -6219,6 +6292,13 @@ meta_window_refresh_resize_popup (MetaWindow *window)
   if (window->display->grab_window != window)
     return;
 
+  /* FIXME for now we bail out when doing wireframe, because our
+   * server grab keeps us from being able to redraw the stuff
+   * underneath the resize popup.
+   */
+  if (window->display->grab_wireframe_active)
+    return;
+  
   switch (window->display->grab_op)
     {
     case META_GRAB_OP_RESIZING_SE:
@@ -6257,7 +6337,7 @@ meta_window_refresh_resize_popup (MetaWindow *window)
   if (window->display->grab_resize_popup != NULL)
     {
       int gravity;
-      int x, y;
+      int x, y, width, height;
       MetaFrameGeometry fgeom;
 
       if (window->frame)
@@ -6273,13 +6353,24 @@ meta_window_refresh_resize_popup (MetaWindow *window)
       gravity = meta_resize_gravity_from_grab_op (window->display->grab_op);
       g_assert (gravity >= 0);
 
-      meta_window_get_position (window, &x, &y);
+      if (window->display->grab_wireframe_active)
+        {
+          x = window->display->grab_wireframe_rect.x;
+          y = window->display->grab_wireframe_rect.y;
+          width = window->display->grab_wireframe_rect.width;
+          height = window->display->grab_wireframe_rect.height;
+        }
+      else
+        {
+          meta_window_get_position (window, &x, &y);
+          width = window->rect.width;
+          height = window->rect.height;
+        }
       
       meta_ui_resize_popup_set (window->display->grab_resize_popup,
                                 gravity,
                                 x, y,
-                                window->rect.width,
-                                window->rect.height,
+                                width, height,
                                 window->size_hints.base_width,
                                 window->size_hints.base_height,
                                 window->size_hints.min_width,
@@ -6406,53 +6497,70 @@ meta_window_is_ancestor_of_transient (MetaWindow *window,
   return d.found;
 }
 
+/* Warp pointer to location appropriate for grab,
+ * return root coordinates where pointer ended up.
+ */
 static gboolean
-warp_pointer (MetaWindow *window,
-              MetaGrabOp  grab_op,
-              int        *x,
-              int        *y)
+warp_grab_pointer (MetaWindow          *window,
+                   MetaGrabOp           grab_op,
+                   int                 *x,
+                   int                 *y)
 {
+  MetaRectangle rect;
+
+  /* We may not have done begin_grab_op yet, i.e. may not be in a grab
+   */
+  
+  if (window == window->display->grab_window &&
+      window->display->grab_wireframe_active)
+    rect = window->display->grab_wireframe_rect;
+  else
+    {
+      rect = window->rect;
+      meta_window_get_position (window, &rect.x, &rect.y);
+    }
+  
   switch (grab_op)
     {
       case META_GRAB_OP_KEYBOARD_MOVING:
       case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
-        *x = window->rect.width / 2;
-        *y = window->rect.height / 2;
+        *x = rect.width / 2;
+        *y = rect.height / 2;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_S:
-        *x = window->rect.width / 2;
-        *y = window->rect.height;
+        *x = rect.width / 2;
+        *y = rect.height;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_N:
-        *x = window->rect.width / 2;
+        *x = rect.width / 2;
         *y = 0;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_W:
         *x = 0;
-        *y = window->rect.height / 2;
+        *y = rect.height / 2;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_E:
-        *x = window->rect.width;
-        *y = window->rect.height / 2;
+        *x = rect.width;
+        *y = rect.height / 2;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_SE:
-        *x = window->rect.width;
-        *y = window->rect.height;
+        *x = rect.width;
+        *y = rect.height;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_NE:
-        *x = window->rect.width;
+        *x = rect.width;
         *y = 0;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_SW:
         *x = 0;
-        *y = window->rect.height;
+        *y = rect.height;
         break;
 
       case META_GRAB_OP_KEYBOARD_RESIZING_NW:
@@ -6464,45 +6572,45 @@ warp_pointer (MetaWindow *window,
         return FALSE;
     }
 
+  *x += rect.x;
+  *y += rect.y;
+  
   meta_error_trap_push_with_return (window->display);
+
+  meta_topic (META_DEBUG_WINDOW_OPS,
+              "Warping pointer to %d,%d with window at %d,%d\n",
+              *x, *y, rect.x, rect.y);
   
   XWarpPointer (window->display->xdisplay,
                 None,
-                window->xwindow,
+                window->screen->xroot,
                 0, 0, 0, 0, 
-                *x,
-                *y);
+                *x, *y);
 
   if (meta_error_trap_pop_with_return (window->display, FALSE) != Success)
     {
-      meta_verbose ("Failed to warp pointer for window %s\n", window->desc);
+      meta_verbose ("Failed to warp pointer for window %s\n",
+                    window->desc);
       return FALSE;
     }
-
+  
   return TRUE;
 }
 
-gboolean
-meta_window_warp_pointer (MetaWindow *window,
-                          MetaGrabOp  grab_op)
-{
-  int x, y;
- 
-  return warp_pointer (window, grab_op, &x, &y); 
-}
-
 void
 meta_window_begin_grab_op (MetaWindow *window,
                            MetaGrabOp  op,
                            Time        timestamp)
 {
-  int x, y, x_offset, y_offset;
-
-  meta_window_get_position (window, &x, &y);
+  int x, y;
+  gulong grab_start_serial;
 
+  grab_start_serial = XNextRequest (window->display->xdisplay);
+  
   meta_window_raise (window);
 
-  warp_pointer (window, op, &x_offset, &y_offset);
+  warp_grab_pointer (window,
+                     op, &x, &y);
 
   meta_display_begin_grab_op (window->display,
                               window->screen,
@@ -6510,31 +6618,50 @@ meta_window_begin_grab_op (MetaWindow *window,
                               op,
                               FALSE, 0, 0,
                               timestamp,
-                              x + x_offset, 
-                              y + y_offset);
+                              x, y);
+
+  /* We override the one set in display_begin_grab_op since we
+   * did additional stuff as part of the grabbing process
+   */
+  window->display->grab_start_serial = grab_start_serial;
 }
 
 void
-meta_window_update_resize_grab_op (MetaWindow *window,
-                                   gboolean    update_cursor)
+meta_window_update_keyboard_resize (MetaWindow *window,
+                                    gboolean    update_cursor)
 {
-  int x, y, x_offset, y_offset;
-
-  meta_window_get_position (window, &x, &y);
+  int x, y;
   
-  warp_pointer (window, window->display->grab_op, &x_offset, &y_offset);
+  warp_grab_pointer (window,
+                     window->display->grab_op,
+                     &x, &y);
 
-  /* As we warped the pointer, we have to reset the apparent
-   * initial window state, since if the mouse moves we want
-   * to use those events to do the right thing.
-   */
-  if (window->display->grab_window == window)
-    {
-      window->display->grab_initial_root_x = x + x_offset;
-      window->display->grab_initial_root_y = y + y_offset;
-      
-      window->display->grab_initial_window_pos = window->rect;
-    }
+  {
+    /* As we warped the pointer, we have to reset the anchor state,
+     * since if the mouse moves we want to use those events to do the
+     * right thing. Also, this means that the motion notify
+     * from the pointer warp comes back as a no-op.
+     */
+    int dx, dy;
+
+    dx = x - window->display->grab_anchor_root_x;
+    dy = y - window->display->grab_anchor_root_y;
+    
+    window->display->grab_anchor_root_x += dx;
+    window->display->grab_anchor_root_y += dy;
+    if (window->display->grab_wireframe_active)
+      {
+        window->display->grab_anchor_window_pos =
+          window->display->grab_wireframe_rect;
+      }
+    else
+      {
+        window->display->grab_anchor_window_pos = window->rect;
+        meta_window_get_position (window,
+                                  &window->display->grab_anchor_window_pos.x,
+                                  &window->display->grab_anchor_window_pos.y);
+      }
+  }
   
   if (update_cursor)
     {
@@ -6547,6 +6674,16 @@ meta_window_update_resize_grab_op (MetaWindow *window,
     }
 }
 
+void
+meta_window_update_keyboard_move (MetaWindow *window)
+{
+  int x, y;
+  
+  warp_grab_pointer (window,
+                     window->display->grab_op,
+                     &x, &y);
+}
+
 void
 meta_window_update_layer (MetaWindow *window)
 {
diff --git a/src/window.h b/src/window.h
index 3b36872e8..91f3711c3 100644
--- a/src/window.h
+++ b/src/window.h
@@ -469,15 +469,13 @@ void     meta_window_foreach_ancestor         (MetaWindow            *window,
                                                MetaWindowForeachFunc  func,
                                                void                  *data);
 
-gboolean meta_window_warp_pointer (MetaWindow *window,
-                                   MetaGrabOp  grab_op);
-
 void meta_window_begin_grab_op (MetaWindow *window,
                                 MetaGrabOp  op,
                                 Time        timestamp);
 
-void meta_window_update_resize_grab_op (MetaWindow *window,
-                                        gboolean    update_cursor);
+void meta_window_update_keyboard_resize (MetaWindow *window,
+                                         gboolean    update_cursor);
+void meta_window_update_keyboard_move   (MetaWindow *window);
 
 void meta_window_update_layer (MetaWindow *window);