Index: src/display.c
===================================================================
--- src/display.c	(revision 3127)
+++ src/display.c	(working copy)
@@ -333,7 +333,8 @@ meta_display_open (void)
     "_NET_DESKTOP_VIEWPORT",
     "_METACITY_VERSION",
     "_NET_WM_VISIBLE_NAME",
-    "_NET_WM_VISIBLE_ICON_NAME"
+    "_NET_WM_VISIBLE_ICON_NAME",
+    "_NET_WM_USER_TIME_WINDOW"
   };
   Atom atoms[G_N_ELEMENTS(atom_names)];
   
@@ -492,6 +493,7 @@ meta_display_open (void)
   display->atom_metacity_version = atoms[91];
   display->atom_net_wm_visible_name = atoms[92];
   display->atom_net_wm_visible_icon_name = atoms[93];
+  display->atom_net_wm_user_time_window = atoms[94];
 
   display->prop_hooks = NULL;
   meta_display_init_window_prop_hooks (display);
@@ -1457,6 +1459,7 @@ event_callback (XEvent   *event,
                 gpointer  data)
 {
   MetaWindow *window;
+  MetaWindow *property_for_window;
   MetaDisplay *display;
   Window modified;
   gboolean frame_was_receiver;
@@ -1510,6 +1513,18 @@ event_callback (XEvent   *event,
   else
     window = NULL;
 
+  /* We only want to respond to _NET_WM_USER_TIME property notify
+   * events on _NET_WM_USER_TIME_WINDOW windows; in particular,
+   * responding to UnmapNotify events is kind of bad.
+   */
+  property_for_window = NULL;
+  if (window && modified == window->user_time_window)
+    {
+      property_for_window = window;
+      window = NULL;
+    }
+    
+
   frame_was_receiver = FALSE;
   if (window &&
       window->frame &&
@@ -2173,6 +2188,8 @@ event_callback (XEvent   *event,
         
         if (window && !frame_was_receiver)
           meta_window_property_notify (window, event);
+        else if (property_for_window && !frame_was_receiver)
+          meta_window_property_notify (property_for_window, event);
 
         group = meta_display_lookup_group (display,
                                            event->xproperty.window);
Index: src/display.h
===================================================================
--- src/display.h	(revision 3127)
+++ src/display.h	(working copy)
@@ -180,6 +180,7 @@ struct _MetaDisplay
   Atom atom_metacity_version;
   Atom atom_net_wm_visible_name;
   Atom atom_net_wm_visible_icon_name;
+  Atom atom_net_wm_user_time_window;
 
   /* This is the actual window from focus events,
    * not the one we last set
Index: src/window-props.c
===================================================================
--- src/window-props.c	(revision 3127)
+++ src/window-props.c	(working copy)
@@ -200,6 +200,61 @@ reload_net_wm_user_time (MetaWindow    *
     }
 }
 
+static void
+init_net_wm_user_time_window (MetaDisplay   *display,
+                              Atom           property,
+                              MetaPropValue *value)
+{
+  value->type = META_PROP_VALUE_WINDOW;
+  value->atom = display->atom_net_wm_user_time_window;
+}
+
+static void
+reload_net_wm_user_time_window (MetaWindow    *window,
+                                MetaPropValue *value)
+{
+  if (value->type != META_PROP_VALUE_INVALID)
+    {
+      /* Unregister old NET_WM_USER_TIME_WINDOW */
+      if (window->user_time_window != None)
+        {
+          /* See the comment to the meta_display_register_x_window call below. */
+          meta_display_unregister_x_window (window->display,
+                                            window->user_time_window);
+          /* Don't get events on not-managed windows */
+          XSelectInput (window->display->xdisplay,
+                        window->user_time_window,
+                        NoEventMask);
+        }
+
+
+      /* Obtain the new NET_WM_USER_TIME_WINDOW and register it */
+      window->user_time_window = value->v.xwindow;
+      if (window->user_time_window != None)
+        {
+          /* Kind of a hack; display.c:event_callback() ignores events
+           * for unknown windows.  We make window->user_time_window
+           * known by registering it with window (despite the fact
+           * that window->xwindow is already registered with window).
+           * This basically means that property notifies to either the
+           * window->user_time_window or window->xwindow will be
+           * treated identically and will result in functions for
+           * window being called to update it.  Maybe we should ignore
+           * any property notifies to window->user_time_window other
+           * than atom_net_wm_user_time ones, but I just don't care
+           * and it's not specified in the spec anyway.
+           */
+          meta_display_register_x_window (window->display,
+                                          &window->user_time_window,
+                                          window);
+          /* Just listen for property notify events */
+          XSelectInput (window->display->xdisplay,
+                        window->user_time_window,
+                        PropertyChangeMask);
+        }
+    }
+}
+
 #define MAX_TITLE_LENGTH 512
 
 /**
@@ -1217,7 +1272,7 @@ reload_transient_for (MetaWindow    *win
     meta_window_queue_move_resize (window);
 }
 
-#define N_HOOKS 25
+#define N_HOOKS 26
 
 void
 meta_display_init_window_prop_hooks (MetaDisplay *display)
@@ -1357,6 +1412,11 @@ meta_display_init_window_prop_hooks (Met
   hooks[i].reload_func = reload_transient_for;
   ++i;
 
+  hooks[i].property = display->atom_net_wm_user_time_window;
+  hooks[i].init_func = init_net_wm_user_time_window;
+  hooks[i].reload_func = reload_net_wm_user_time_window;
+  ++i;
+
   if (i != N_HOOKS)
     g_error ("Initialized %d hooks should have been %d\n", i, N_HOOKS);
 }
Index: src/screen.c
===================================================================
--- src/screen.c	(revision 3127)
+++ src/screen.c	(working copy)
@@ -89,7 +89,7 @@ set_wm_check_hint (MetaScreen *screen)
 static int
 set_supported_hint (MetaScreen *screen)
 {
-#define N_SUPPORTED 58
+#define N_SUPPORTED 59
   Atom atoms[N_SUPPORTED];
   
   atoms[0] = screen->display->atom_net_wm_name;
@@ -150,6 +150,7 @@ set_supported_hint (MetaScreen *screen)
   atoms[55] = screen->display->atom_net_wm_state_demands_attention;
   atoms[56] = screen->display->atom_net_desktop_geometry;
   atoms[57] = screen->display->atom_net_desktop_viewport;
+  atoms[58] = screen->display->atom_net_wm_user_time_window;
   //atoms[58] = screen->display->atom_net_restack_window;
   //atoms[59] = screen->display->atom_net_moveresize_window;
   
Index: src/constraints.c
===================================================================
--- src/constraints.c	(revision 3127)
+++ src/constraints.c	(working copy)
@@ -350,7 +350,7 @@ setup_constraint_info (ConstraintInfo   
   else if (flags & META_IS_RESIZE_ACTION)
     info->action_type = ACTION_RESIZE;
   else if (flags & META_IS_MOVE_ACTION)
-    info->action_type = ACTION_MOVE_AND_RESIZE;
+    info->action_type = ACTION_MOVE;
   else
     g_error ("BAD, BAD developer!  No treat for you!  (Fix your calls to "
              "meta_window_move_resize_internal()).\n");
@@ -805,7 +805,11 @@ constrain_size_increments (MetaWindow   
     return constraint_already_satisfied;
 
   /*** Enforce constraint ***/
-  /* Shrink to base + N * inc */
+  /* Shrink to base + N * inc.  FIXME: This is an inappropriate fix if the
+   * window also has a minimum size hint.  vumeter is a good example.  We
+   * should probably also worry about maximum size hint (current solution
+   * works fine with that) and aspect ratio issues...
+   */
   meta_rectangle_resize_with_gravity (&info->orig,
                                       &info->current, 
                                       info->resize_gravity,
Index: src/window.c
===================================================================
--- src/window.c	(revision 3127)
+++ src/window.c	(working copy)
@@ -234,7 +234,7 @@ meta_window_new_with_attrs (MetaDisplay 
   gulong existing_wm_state;
   gulong event_mask;
   MetaMoveResizeFlags flags;
-#define N_INITIAL_PROPS 17
+#define N_INITIAL_PROPS 18
   Atom initial_props[N_INITIAL_PROPS];
   int i;
   gboolean has_shape;
@@ -478,6 +478,7 @@ meta_window_new_with_attrs (MetaDisplay 
   window->initial_workspace_set = FALSE;
   window->initial_timestamp_set = FALSE;
   window->net_wm_user_time_set = FALSE;
+  window->user_time_window = None;
   window->calc_placement = FALSE;
   window->shaken_loose = FALSE;
   window->have_focus_click_grab = FALSE;
@@ -577,6 +578,7 @@ meta_window_new_with_attrs (MetaDisplay 
   initial_props[i++] = display->atom_net_wm_state;
   initial_props[i++] = display->atom_motif_wm_hints;
   initial_props[i++] = XA_WM_TRANSIENT_FOR;
+  initial_props[i++] = display->atom_net_wm_user_time_window;
   g_assert (N_INITIAL_PROPS == i);
   
   meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS);
@@ -1103,6 +1105,17 @@ meta_window_free (MetaWindow  *window,
                 window->xwindow,
                 NoEventMask);
 
+  /* Stop getting events for the window's _NET_WM_USER_TIME_WINDOW too */
+  if (window->user_time_window != None)
+    {
+      meta_display_unregister_x_window (window->display,
+                                        window->user_time_window);
+      XSelectInput (window->display->xdisplay,
+                    window->user_time_window,
+                    NoEventMask);
+      window->user_time_window = None;
+    }
+
 #ifdef HAVE_SHAPE
   if (META_DISPLAY_HAS_SHAPE (window->display))
     XShapeSelectInput (window->display->xdisplay, window->xwindow, NoEventMask);
Index: src/window.h
===================================================================
--- src/window.h	(revision 3127)
+++ src/window.h	(working copy)
@@ -318,6 +318,9 @@ struct _MetaWindow
   /* set to the most recent user-interaction event timestamp that we
      know about for this window */
   guint32 net_wm_user_time;
+
+  /* window that gets updated net_wm_user_time values */
+  Window user_time_window;
   
   /* The size we set the window to last (i.e. what we believe
    * to be its actual size on the server). The x, y are
