? rename_grab_vars.patch
? wireframe-backport.patch
? wireframe.patch
Index: src/display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.174.2.5
diff -u -p -u -r1.174.2.5 display.c
--- src/display.c	21 May 2003 03:45:41 -0000	1.174.2.5
+++ src/display.c	28 Jul 2003 15:11:16 -0000
@@ -34,6 +34,7 @@
 #include "prefs.h"
 #include "resizepopup.h"
 #include "workspace.h"
+#include "effects.h"
 #include <X11/Xatom.h>
 #include <X11/cursorfont.h>
 #ifdef HAVE_SOLARIS_XINERAMA
@@ -1197,7 +1198,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
@@ -1209,6 +1211,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);
     }
@@ -1273,7 +1276,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))
         {
@@ -1414,16 +1418,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 */
@@ -1486,6 +1493,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)
@@ -2727,8 +2735,9 @@ meta_display_begin_grab_op (MetaDisplay 
   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)
     {
@@ -2738,6 +2747,9 @@ meta_display_begin_grab_op (MetaDisplay 
       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.
@@ -2751,7 +2763,7 @@ meta_display_begin_grab_op (MetaDisplay 
   
   if (pointer_already_grabbed)
     display->grab_have_pointer = TRUE;
-      
+  
   meta_display_set_grab_op_cursor (display, screen, op, FALSE, grab_xwindow,
                                    timestamp);
 
@@ -2788,10 +2800,8 @@ meta_display_begin_grab_op (MetaDisplay 
   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_current_root_x = root_x;
-  display->grab_current_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;
@@ -2800,6 +2810,7 @@ meta_display_begin_grab_op (MetaDisplay 
 #ifdef HAVE_XSYNC
   display->grab_update_alarm = None;
 #endif
+  display->grab_was_cancelled = FALSE;
   
   if (display->grab_window)
     {
@@ -2807,10 +2818,34 @@ meta_display_begin_grab_op (MetaDisplay 
       meta_window_get_position (display->grab_window,
                                 &display->grab_initial_window_pos.x,
                                 &display->grab_initial_window_pos.y);
-      display->grab_current_window_pos = display->grab_initial_window_pos;
+      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;
@@ -2937,6 +2972,21 @@ meta_display_end_grab_op (MetaDisplay *d
                          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;
Index: src/display.h
===================================================================
RCS file: /cvs/gnome/metacity/src/display.h,v
retrieving revision 1.96.2.1
diff -u -p -u -r1.96.2.1 display.h
--- src/display.h	22 Jan 2003 04:54:26 -0000	1.96.2.1
+++ src/display.h	28 Jul 2003 15:11:16 -0000
@@ -231,18 +231,20 @@ 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_current_root_x;
-  int         grab_current_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;
-  MetaRectangle grab_current_window_pos;
   MetaResizePopup *grab_resize_popup;
   GTimeVal    grab_last_moveresize_time;
   Time        grab_motion_notify_time;
Index: src/effects.c
===================================================================
RCS file: /cvs/gnome/metacity/src/effects.c,v
retrieving revision 1.12
diff -u -p -u -r1.12 effects.c
--- src/effects.c	18 Oct 2002 22:46:37 -0000	1.12
+++ src/effects.c	28 Jul 2003 15:11:16 -0000
@@ -409,5 +409,108 @@ meta_effects_draw_box_animation (MetaScr
   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);
+}
 
Index: src/effects.h
===================================================================
RCS file: /cvs/gnome/metacity/src/effects.h,v
retrieving revision 1.6
diff -u -p -u -r1.6 effects.h
--- src/effects.h	30 Sep 2002 03:49:22 -0000	1.6
+++ src/effects.h	28 Jul 2003 15:11:16 -0000
@@ -41,4 +41,12 @@ void meta_effects_draw_box_animation (Me
                                       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 */
Index: src/frames.c
===================================================================
RCS file: /cvs/gnome/metacity/src/frames.c,v
retrieving revision 1.70
diff -u -p -u -r1.70 frames.c
--- src/frames.c	11 Jan 2003 18:09:12 -0000	1.70
+++ src/frames.c	28 Jul 2003 15:11:17 -0000
@@ -2085,6 +2085,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;
 }
 
Index: src/keybindings.c
===================================================================
RCS file: /cvs/gnome/metacity/src/keybindings.c,v
retrieving revision 1.75.2.3
diff -u -p -u -r1.75.2.3 keybindings.c
--- src/keybindings.c	21 May 2003 03:45:42 -0000	1.75.2.3
+++ src/keybindings.c	28 Jul 2003 15:11:17 -0000
@@ -27,6 +27,7 @@
 #include "frame.h"
 #include "place.h"
 #include "prefs.h"
+#include "effects.h"
 
 #include <X11/keysym.h>
 #include <string.h>
@@ -1604,10 +1605,24 @@ process_keyboard_move_grab (MetaDisplay 
   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
 
@@ -1628,51 +1643,69 @@ process_keyboard_move_grab (MetaDisplay 
     {
     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;
     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;
     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;
     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;
 
     case 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;
       break;
           
     default:
@@ -1681,10 +1714,30 @@ process_keyboard_move_grab (MetaDisplay 
 
   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;
 }
 
@@ -1717,13 +1770,18 @@ process_keyboard_resize_grab (MetaDispla
 
   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;
     }
@@ -1833,20 +1891,38 @@ process_keyboard_resize_grab (MetaDispla
 
   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
 
@@ -1896,12 +1972,16 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -1910,11 +1990,15 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -1937,12 +2021,16 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -1951,11 +2039,15 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -1978,11 +2070,15 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -1991,12 +2087,16 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -2019,11 +2119,15 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -2032,12 +2136,16 @@ process_keyboard_resize_grab (MetaDispla
         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;
@@ -2064,8 +2172,32 @@ process_keyboard_resize_grab (MetaDispla
   
   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;
Index: src/metacity.schemas.in
===================================================================
RCS file: /cvs/gnome/metacity/src/metacity.schemas.in,v
retrieving revision 1.24.2.1
diff -u -p -u -r1.24.2.1 metacity.schemas.in
--- src/metacity.schemas.in	5 Feb 2003 04:31:49 -0000	1.24.2.1
+++ src/metacity.schemas.in	28 Jul 2003 15:11:17 -0000
@@ -206,6 +206,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>
Index: src/prefs.c
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.c,v
retrieving revision 1.39
diff -u -p -u -r1.39 prefs.c
--- src/prefs.c	15 Jan 2003 02:39:07 -0000	1.39
+++ src/prefs.c	28 Jul 2003 15:11:17 -0000
@@ -47,6 +47,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"
@@ -73,6 +74,8 @@ static gboolean application_based = FALS
 static gboolean disable_workarounds = FALSE;
 static gboolean auto_raise = FALSE;
 static gboolean auto_raise_delay = 500;
+static gboolean reduced_resources = FALSE;
+ 
 static MetaButtonLayout button_layout = {
   {
     META_BUTTON_FUNCTION_MENU,
@@ -115,6 +118,7 @@ static gboolean update_command          
                                            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,
@@ -358,6 +362,11 @@ meta_prefs_init (void)
   cleanup_error (&err);
   update_button_layout (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 */
@@ -674,6 +683,22 @@ change_notify (GConfClient    *client,
       if (update_button_layout (str))
         queue_changed (META_PREF_BUTTON_LAYOUT);
     }
+  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",
@@ -1137,6 +1162,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
@@ -1191,6 +1226,10 @@ meta_preference_to_string (MetaPreferenc
     case META_PREF_WORKSPACE_NAMES:
       return "WORKSPACE_NAMES";
       break;
+
+    case META_PREF_REDUCED_RESOURCES:
+      return "REDUCED_RESOURCES";
+      break;
     }
 
   return "(unknown)";
@@ -1808,6 +1847,12 @@ int
 meta_prefs_get_auto_raise_delay ()
 {
   return auto_raise_delay;
+}
+
+gboolean
+meta_prefs_get_reduced_resources ()
+{
+  return reduced_resources;
 }
 
 MetaKeyBindingAction
Index: src/prefs.h
===================================================================
RCS file: /cvs/gnome/metacity/src/prefs.h,v
retrieving revision 1.28
diff -u -p -u -r1.28 prefs.h
--- src/prefs.h	15 Jan 2003 02:39:07 -0000	1.28
+++ src/prefs.h	28 Jul 2003 15:11:17 -0000
@@ -42,7 +42,8 @@ typedef enum
   META_PREF_DISABLE_WORKAROUNDS,
   META_PREF_COMMANDS,
   META_PREF_BUTTON_LAYOUT,
-  META_PREF_WORKSPACE_NAMES
+  META_PREF_WORKSPACE_NAMES,
+  META_PREF_REDUCED_RESOURCES
 } MetaPreference;
 
 typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@@ -66,6 +67,7 @@ gboolean                    meta_prefs_g
 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);
 
Index: src/run-metacity.sh
===================================================================
RCS file: /cvs/gnome/metacity/src/run-metacity.sh,v
retrieving revision 1.38
diff -u -p -u -r1.38 run-metacity.sh
--- src/run-metacity.sh	13 Nov 2002 04:11:52 -0000	1.38
+++ src/run-metacity.sh	28 Jul 2003 15:11:17 -0000
@@ -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
Index: src/screen.c
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.c,v
retrieving revision 1.98.2.3
diff -u -p -u -r1.98.2.3 screen.c
--- src/screen.c	14 Feb 2003 07:06:09 -0000	1.98.2.3
+++ src/screen.c	28 Jul 2003 15:11:17 -0000
@@ -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);
Index: src/screen.h
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.h,v
retrieving revision 1.44.2.1
diff -u -p -u -r1.44.2.1 screen.h
--- src/screen.h	22 Jan 2003 04:54:26 -0000	1.44.2.1
+++ src/screen.h	28 Jul 2003 15:11:17 -0000
@@ -48,6 +48,8 @@ typedef enum
   META_SCREEN_BOTTOMRIGHT
 } MetaScreenCorner;
 
+#define META_WIREFRAME_XOR_LINE_WIDTH 5
+
 struct _MetaScreen
 {
   MetaDisplay *display;
@@ -98,6 +100,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,
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.261.2.8
diff -u -p -u -r1.261.2.8 window.c
--- src/window.c	7 Jun 2003 05:06:48 -0000	1.261.2.8
+++ src/window.c	28 Jul 2003 15:11:17 -0000
@@ -1213,6 +1213,14 @@ window_should_be_showing (MetaWindow  *w
         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;
 }
 
@@ -1237,7 +1245,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;
@@ -6211,7 +6220,7 @@ check_moveresize_frequency (MetaWindow *
   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;
@@ -6228,21 +6237,48 @@ update_move (MetaWindow  *window,
 
   window->display->grab_latest_motion_x = x;
   window->display->grab_latest_motion_y = y;
-  
-  dx = x - window->display->grab_current_root_x;
-  dy = y - window->display->grab_current_root_y;
 
-  new_x = window->display->grab_current_window_pos.x + dx;
-  new_y = window->display->grab_current_window_pos.y + dy;
+  dx = x - window->display->grab_anchor_root_x;
+  dy = y - window->display->grab_anchor_root_y;
+
+  new_x = window->display->grab_anchor_window_pos.x + dx;
+  new_y = window->display->grab_anchor_window_pos.y + dy;
 
-  if (mask & ShiftMask)
+  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);
+  
+  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
@@ -6253,16 +6289,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_current_root_x;
-  dy = y - window->display->grab_current_root_y;
+  dx = x - window->display->grab_anchor_root_x;
+  dy = y - window->display->grab_anchor_root_y;
 
-  new_w = window->display->grab_current_window_pos.width;
-  new_h = window->display->grab_current_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:
@@ -6281,6 +6322,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:
@@ -6305,6 +6347,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;
@@ -6313,12 +6356,42 @@ update_resize (MetaWindow *window,
   check_moveresize_frequency (window);
   
   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
@@ -6640,6 +6713,13 @@ meta_window_refresh_resize_popup (MetaWi
   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:
@@ -6678,7 +6758,7 @@ meta_window_refresh_resize_popup (MetaWi
   if (window->display->grab_resize_popup != NULL)
     {
       int gravity;
-      int x, y;
+      int x, y, width, height;
       MetaFrameGeometry fgeom;
 
       if (window->frame)
@@ -6694,13 +6774,24 @@ meta_window_refresh_resize_popup (MetaWi
       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,
@@ -6827,53 +6918,70 @@ meta_window_is_ancestor_of_transient (Me
   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:
@@ -6885,45 +6993,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,
@@ -6931,25 +7039,50 @@ meta_window_begin_grab_op (MetaWindow *w
                               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);
-
-  warp_pointer (window, window->display->grab_op, &x_offset, &y_offset);
+  int x, y;
+  
+  warp_grab_pointer (window,
+                     window->display->grab_op,
+                     &x, &y);
 
-  window->display->grab_current_root_x = x + x_offset;
-  window->display->grab_current_root_y = y + y_offset;
+  {
+    /* 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;
 
-  if (window->display->grab_window)
-    window->display->grab_current_window_pos = window->rect;
+    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)
     {
@@ -6960,6 +7093,16 @@ meta_window_update_resize_grab_op (MetaW
                                        window->display->grab_xwindow,
                                        meta_display_get_current_time (window->display));
     }
+}
+
+void
+meta_window_update_keyboard_move (MetaWindow *window)
+{
+  int x, y;
+  
+  warp_grab_pointer (window,
+                     window->display->grab_op,
+                     &x, &y);
 }
 
 void
Index: src/window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.82.2.1
diff -u -p -u -r1.82.2.1 window.h
--- src/window.h	17 Mar 2003 06:36:34 -0000	1.82.2.1
+++ src/window.h	28 Jul 2003 15:11:17 -0000
@@ -441,15 +441,13 @@ void     meta_window_foreach_ancestor   
                                                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);
 
