Index: metacity/COMPLIANCE
diff -u metacity/COMPLIANCE:1.4 metacity/COMPLIANCE:1.5
--- metacity/COMPLIANCE:1.4	Thu Jun 24 17:50:30 2004
+++ metacity/COMPLIANCE	Sat Jul 31 15:56:09 2004
@@ -1,6 +1,6 @@
 Metacity Standards Compliance
 =============================
-$Id: COMPLIANCE,v 1.4 2004/06/24 21:50:30 readams Exp $
+$Id: COMPLIANCE,v 1.5 2004/07/31 19:56:09 readams Exp $
 
 1) Introduction
 2) EWMH Compliance
@@ -48,15 +48,12 @@
 
 + _NET_NUMBER_OF_DESKTOPS (1.3)
 
-- _NET_DESKTOP_GEOMETRY (-)
-  Metacity does not implement large desktops.  Regardless, according
-  to the specification, metacity SHOULD set this property to the
-  screen size, and update it if the screen size changes because of a
-  RandR change.
-
-- _NET_DESKTOP_VIEWPORT (-)
-  Metacity does not implement viewports.  However, according to the
-  specification, metacity MUST set this property to (0,0)
++ _NET_DESKTOP_GEOMETRY (1.3)
+  Metacity does not implement large desktops, so this is kept set to
+  the screen size.
+
++ _NET_DESKTOP_VIEWPORT (1.3)
+  Metacity does not implement viewports, so this is a constant (0,0).
 
 + _NET_CURRENT_DESKTOP (1.3)
 
@@ -82,15 +79,16 @@
 
 + _NET_CLOSE_WINDOW (1.3)
 
-- _NET_MOVERESIZE_WINDOW (-)
-  Metacity does not support this message.  The specification states
-  that metacity should treat this message like a ConfigureRequest.
-  Not hard to implement; just hasn't been done.
+- _NET_MOVERESIZE_WINDOW (1.3)
+  Metacity supports this message, but the specification is unclear on
+  the layout of the detail value, and as such it is #if 0'd in the code
 
 + _NET_WM_MOVERESIZE (1.3)
 
-- _NET_RESTACK_WINDOW (-)
-  Metacity does not currently support this message.
+- _NET_RESTACK_WINDOW (1.3)
+  Metacity will raise or lower windows in response to this message,
+  but the sibling restack modes are not supported, and it is currently
+  #if 0'd in the code.
 
 + _NET_REQUEST_FRAME_EXTENTS (1.3)  
 
@@ -114,14 +112,14 @@
 + _NET_WM_WINDOW_TYPE (1.3)
 
 / _NET_WM_STATE (1.3)
+  This property is read and updated according to the specification,
+  but see caveat below.
   Metacity does not recognize separate vertical and horizontal
   maximization states.  Currently metacity will do a two-dimensional
   maximization if either property is set.
   See: http://bugzilla.gnome.org/show_bug.cgi?id=113601
   Metacity doesn't implement viewports so _NET_WM_STATE_STICKY is
   unimplemented.
-  _NET_WM_STATE_DEMANDS_ATTENTION is neither read nor updated by
-  metacity.  Metacity should unset it on window activation.
 
 + _NET_WM_ALLOWED_ACTIONS (1.3)
   Metacity keeps this hint up to date.  The code is somewhat crufty
@@ -141,7 +139,7 @@
 
 + _NET_WM_HANDLED_ICONS (1.3)
   Metacity does not read or set this property.  However, metacity
-  never managed iconified windows, and so has no need to do so.
+  never manages iconified windows, and so has no need to do so.
 
 + _NET_WM_USER_TIME (1.3)
   Metacity uses this property to prevent applications from stealing
Index: metacity/ChangeLog
diff -u metacity/ChangeLog:1.834 metacity/ChangeLog:1.835
--- metacity/ChangeLog:1.834	Thu Jul 22 19:27:51 2004
+++ metacity/ChangeLog	Sat Jul 31 15:56:09 2004
@@ -1,3 +1,39 @@
+2004-07-31  Rob Adams  <readams@readams.net>
+
+	Fix some support for EWMH hints, and fix USER_TIME support to
+	include the DEMANDS_ATTENTION hint.  Also includes some code for
+	implementing _NET_RESTACK_WINDOW and _NET_MOVERESIZE_WINDOW, but
+	this is disabled pending feature thaw.
+	
+	* COMPLIANCE: update with new information
+
+	* src/display.c (meta_display_open): add new hints to list
+
+	* src/display.h (_MetaDisplay): Add new atoms to struct
+
+	* src/screen.c (set_supported_hint): update the list of support
+	hints.
+	(set_desktop_viewport_hint): new function sets the viewport hint
+	to (0,0) as required by the spec for WMs with no viewport support.
+	(set_desktop_geometry_hint): new function to set the desktop size
+	hint to the size of the display, since we don't implement large
+	desktop support, as required by the spec.
+	(meta_screen_resize): update the geometry hint on screen resize
+
+	* src/window.c (meta_window_new_with_attrs): Initialize
+	demands_attention state
+	(set_net_wm_state): Set demands_attention hint in the window state
+	(meta_window_show): If we don't pop up a window because of
+	USER_TIME, set DEMANDS_ATTENTION on the window.
+	(meta_window_focus): When a window receives focus, remove
+	DEMANDS_ATTENTION hint
+	(meta_window_client_message): Allow other apps to set
+	DEMANDS_ATTENTION on a window.  Also, if the _NET_ACTIVE_WINDOW
+	hint includes a timestamp, use it.
+	(update_net_wm_state): Read DEMANDS_ATTENTION state also
+
+	* src/window.h (_MetaWindow): add wm_state_demands_attention bit.
+	
 2004-07-22  Rob Adams  <readams@readams.net>
 
 	* src/metacity.schemas.in: Add trailing quotes to keybinding
Index: metacity/src/display.c
diff -u metacity/src/display.c:1.217 metacity/src/display.c:1.218
--- metacity/src/display.c:1.217	Thu Jun 24 11:47:04 2004
+++ metacity/src/display.c	Sat Jul 31 15:56:10 2004
@@ -282,6 +282,11 @@
     "_NET_FRAME_EXTENTS",
     "_NET_REQUEST_FRAME_EXTENTS",
     "_NET_WM_USER_TIME",
+    "_NET_WM_STATE_DEMANDS_ATTENTION",
+    "_NET_RESTACK_WINDOW",
+    "_NET_MOVERESIZE_WINDOW",
+    "_NET_DESKTOP_GEOMETRY",
+    "_NET_DESKTOP_VIEWPORT"
   };
   Atom atoms[G_N_ELEMENTS(atom_names)];
   
@@ -429,6 +434,11 @@
   display->atom_net_frame_extents = atoms[83];
   display->atom_net_request_frame_extents = atoms[84];
   display->atom_net_wm_user_time = atoms[85];
+  display->atom_net_wm_state_demands_attention = atoms[86];
+  display->atom_net_restack_window = atoms[87];
+  display->atom_net_moveresize_window = atoms[88];
+  display->atom_net_desktop_geometry = atoms[89];
+  display->atom_net_desktop_viewport = atoms[90];
 
   display->prop_hooks = NULL;
   meta_display_init_window_prop_hooks (display);
@@ -1170,6 +1180,107 @@
   return meta_ui_get_double_click_timeout (screen->ui);
 }                                
 
+#if 0
+static void
+handle_net_moveresize_window (MetaDisplay* display,
+                              XEvent *event)
+{
+  MetaWindow *window;
+  int x, y, width, height;
+  gboolean only_resize;
+  unsigned int gravity;
+  unsigned int mode;
+
+  window = meta_display_lookup_x_window (display,
+                                         event->xclient.window);
+
+  /*
+   * FIXME: The specification seems to have serious endian issues
+   * here.  Does bits 8-11 mean the high-order byte, or the low-order
+   * byte?
+   */
+  gravity = (event->xclient.data.l[0] & ~0xff);
+  mode = (event->xclient.data.l[0] & ~0xff00) >> 8;
+
+  if (window)
+    {
+      meta_window_get_gravity_position (window, &x, &y);
+      width = window->rect.width;
+      height = window->rect.height;
+
+      if (mode & (CWX | CWY))
+        only_resize = FALSE;
+      else
+        only_resize = TRUE;
+
+      if (mode & CWX)
+        x = event->xclient.data.l[1];
+      if (mode & CWY)
+        y = event->xclient.data.l[2];
+      if (mode & CWWidth)
+        width = event->xclient.data.l[3];
+      if (mode & CWHeight)
+        height = event->xclient.data.l[4];
+
+      if (only_resize)
+        {
+          if (gravity)
+	    meta_window_resize_with_gravity (window,
+					     TRUE,
+					     width,
+					     height,
+					     gravity);
+          else
+            meta_window_resize (window,
+				TRUE,
+				width,
+				height);
+        }
+      else
+        {
+          meta_window_move_resize (window,
+                                   TRUE,
+                                   x,
+                                   y,
+                                   width,
+                                   height);
+        }
+    }
+}
+
+static void
+handle_net_restack_window (MetaDisplay* display,
+                           XEvent *event)
+{
+  MetaWindow *window;
+
+  window = meta_display_lookup_x_window (display,
+                                         event->xclient.window);
+
+  if (window)
+    {
+      /*
+       * The EWMH includes a sibling for the restack request, but we
+       * don't currently support these types of raises.
+       *
+       */
+      switch (event->xclient.data.l[2])
+        {
+        case Above:
+          meta_window_raise (window);
+          break;
+        case Below:
+          meta_window_lower (window);
+          break;
+        case TopIf:
+        case BottomIf:
+        case Opposite:
+          break;          
+        }
+    }
+}
+#endif
+
 static gboolean
 event_callback (XEvent   *event,
                 gpointer  data)
@@ -1873,10 +1984,18 @@
             else if (event->xproperty.atom ==
                      display->atom_net_desktop_names)
               meta_screen_update_workspace_names (screen);
+#if 0
+            else if (event->xproperty.atom ==
+                     display->atom_net_restack_window)
+              handle_net_restack_window (display, event);
+            else if (event->xproperty.atom ==
+                     display->atom_net_moveresize_window)
+              handle_net_moveresize_window (display, event);
+#endif
 
-	    /* we just use this property as a sentinel to avoid
-	     * certain race conditions.  See the comment for the
-	     * sentinel_counter variable declaration in display.h
+            /* we just use this property as a sentinel to avoid
+             * certain race conditions.  See the comment for the
+             * sentinel_counter variable declaration in display.h
 	     */
 	    if (event->xproperty.atom ==
 		display->atom_metacity_sentinel)
Index: metacity/src/display.h
diff -u metacity/src/display.h:1.118 metacity/src/display.h:1.119
--- metacity/src/display.h:1.118	Thu Jun 24 11:47:05 2004
+++ metacity/src/display.h	Sat Jul 31 15:56:10 2004
@@ -176,6 +176,11 @@
   Atom atom_net_frame_extents;
   Atom atom_net_request_frame_extents;
   Atom atom_net_wm_user_time;
+  Atom atom_net_wm_state_demands_attention;
+  Atom atom_net_restack_window;
+  Atom atom_net_moveresize_window;
+  Atom atom_net_desktop_geometry;
+  Atom atom_net_desktop_viewport;
 
   /* This is the actual window from focus events,
    * not the one we last set
Index: metacity/src/screen.c
diff -u metacity/src/screen.c:1.125 metacity/src/screen.c:1.126
--- metacity/src/screen.c:1.125	Thu Jun 24 16:02:46 2004
+++ metacity/src/screen.c	Sat Jul 31 15:56:10 2004
@@ -57,6 +57,9 @@
 static void prefs_changed_callback (MetaPreference pref,
                                     gpointer       data);
 
+static void set_desktop_geometry_hint (MetaScreen *screen);
+static void set_desktop_viewport_hint (MetaScreen *screen);
+
 #ifdef HAVE_STARTUP_NOTIFICATION
 static void meta_screen_sn_event   (SnMonitorEvent *event,
                                     void           *user_data);
@@ -82,7 +85,7 @@
 static int
 set_supported_hint (MetaScreen *screen)
 {
-#define N_SUPPORTED 54
+#define N_SUPPORTED 58
   Atom atoms[N_SUPPORTED];
   
   atoms[0] = screen->display->atom_net_wm_name;
@@ -139,6 +142,12 @@
   atoms[51] = screen->display->atom_net_wm_action_minimize;
   atoms[52] = screen->display->atom_net_frame_extents;
   atoms[53] = screen->display->atom_net_request_frame_extents;
+  atoms[54] = screen->display->atom_net_wm_user_time;
+  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_restack_window;
+  //atoms[59] = screen->display->atom_net_moveresize_window;
   
   XChangeProperty (screen->display->xdisplay, screen->xroot,
                    screen->display->atom_net_supported,
@@ -575,6 +584,10 @@
   
   set_wm_check_hint (screen);
 
+  set_desktop_viewport_hint (screen);
+
+  set_desktop_geometry_hint (screen);
+
   meta_screen_update_workspace_layout (screen);
 
   /* Get current workspace */
@@ -966,6 +979,51 @@
 }
 
 static void
+set_desktop_geometry_hint (MetaScreen *screen)
+{
+  unsigned long data[2];
+
+  if (screen->closing > 0)
+    return;
+
+  data[0] = screen->width;
+  data[1] = screen->height;
+
+  meta_verbose ("Setting _NET_DESKTOP_GEOMETRY to %ld, %ld\n", data[0], data[1]);
+
+  meta_error_trap_push (screen->display);
+  XChangeProperty (screen->display->xdisplay, screen->xroot,
+                   screen->display->atom_net_desktop_geometry,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 2);
+  meta_error_trap_pop (screen->display, FALSE);
+}
+
+static void
+set_desktop_viewport_hint (MetaScreen *screen)
+{
+  unsigned long data[2];
+
+  if (screen->closing > 0)
+    return;
+
+  /*
+   * Metacity does not implement viewports, so this is a fixed 0,0
+   */
+  data[0] = 0;
+  data[1] = 0;
+
+  meta_verbose ("Setting _NET_DESKTOP_VIEWPORT to 0, 0\n");
+
+  meta_error_trap_push (screen->display);
+  XChangeProperty (screen->display->xdisplay, screen->xroot,
+                   screen->display->atom_net_desktop_viewport,
+                   XA_CARDINAL,
+                   32, PropModeReplace, (guchar*) data, 2);
+  meta_error_trap_pop (screen->display, FALSE);
+}
+
+static void
 update_num_workspaces (MetaScreen *screen)
 {
   int new_num;
@@ -2101,6 +2159,7 @@
   screen->height = height;
 
   reload_xinerama_infos (screen);
+  set_desktop_geometry_hint (screen);
   
   /* Queue a resize on all the windows */
   meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
Index: metacity/src/window.c
diff -u metacity/src/window.c:1.331 metacity/src/window.c:1.332
--- metacity/src/window.c:1.331	Thu Jun 24 16:02:46 2004
+++ metacity/src/window.c	Sat Jul 31 15:56:10 2004
@@ -491,6 +491,7 @@
   window->wm_state_skip_pager = FALSE;
   window->wm_state_above = FALSE;
   window->wm_state_below = FALSE;
+  window->wm_state_demands_attention = FALSE;
   
   window->res_class = NULL;
   window->res_name = NULL;
@@ -1125,7 +1126,7 @@
 set_net_wm_state (MetaWindow *window)
 {
   int i;
-  unsigned long data[10];
+  unsigned long data[11];
   
   i = 0;
   if (window->shaded)
@@ -1175,7 +1176,12 @@
       data[i] = window->display->atom_net_wm_state_below;
       ++i;
     }
-  
+  if (window->wm_state_demands_attention)
+    {
+      data[i] = window->display->atom_net_wm_state_demands_attention;
+      ++i;
+    }
+
   meta_verbose ("Setting _NET_WM_STATE with %d atoms\n", i);
   
   meta_error_trap_push (window->display);
@@ -1810,12 +1816,14 @@
           meta_window_focus (window,
                              meta_display_get_current_time (window->display));
         }
+      else
+        window->wm_state_demands_attention = TRUE;
     }
 
   if (did_show)
     {
       set_net_wm_state (window);
-      
+
       if (window->struts)
         {
           meta_topic (META_DEBUG_WORKAREA,
@@ -3266,7 +3274,7 @@
                   window->desc);
       return;
     }
-  
+
   /* For output-only or shaded windows, focus the frame.
    * This seems to result in the client window getting key events
    * though, so I don't know if it's icccm-compliant.
@@ -3317,6 +3325,12 @@
       
       meta_error_trap_pop (window->display, FALSE);
     }
+
+  if (window->wm_state_demands_attention)
+    {
+      window->wm_state_demands_attention = FALSE;
+      set_net_wm_state (window);
+    }  
 }
 
 static void
@@ -3956,6 +3970,16 @@
           meta_window_update_layer (window);
           set_net_wm_state (window);
         }
+
+      if (first == display->atom_net_wm_state_demands_attention ||
+          second == display->atom_net_wm_state_demands_attention)
+        {
+          window->wm_state_demands_attention = 
+            (action == _NET_WM_STATE_ADD) ||
+            (action == _NET_WM_STATE_TOGGLE && !window->wm_state_demands_attention);
+
+          set_net_wm_state (window);
+        }
       
       return TRUE;
     }
@@ -4100,8 +4124,22 @@
       meta_verbose ("_NET_ACTIVE_WINDOW request for window '%s', activating",
                     window->desc);
 
-      meta_window_activate (window, meta_display_get_current_time (window->display));
-
+      if (event->xclient.data.l[0] != 0)
+        {
+          /* Client supports newer _NET_ACTIVE_WINDOW with a
+           * convenient timestamp
+           */
+          meta_window_activate (window,
+                                event->xclient.data.l[1]);
+          
+        }
+      else
+        {
+          /* Client using older EWMH _NET_ACTIVE_WINDOW without a
+           * timestamp
+           */
+          meta_window_activate (window, meta_display_get_current_time (window->display));
+        }
       return TRUE;
     }
   
@@ -4568,6 +4606,7 @@
   window->wm_state_skip_pager = FALSE;
   window->wm_state_above = FALSE;
   window->wm_state_below = FALSE;
+  window->wm_state_demands_attention = FALSE;
   
   if (meta_prop_get_atom_list (window->display, window->xwindow,
                                window->display->atom_net_wm_state,
@@ -4596,6 +4635,8 @@
             window->wm_state_above = TRUE;
           else if (atoms[i] == window->display->atom_net_wm_state_below)
             window->wm_state_below = TRUE;
+          else if (atoms[i] == window->display->atom_net_wm_state_demands_attention)
+            window->wm_state_demands_attention = TRUE;
           
           ++i;
         }
Index: metacity/src/window.h
diff -u metacity/src/window.h:1.103 metacity/src/window.h:1.104
--- metacity/src/window.h:1.103	Thu Jun 24 11:47:05 2004
+++ metacity/src/window.h	Sat Jul 31 15:56:10 2004
@@ -190,6 +190,9 @@
   /* TRUE if client set these */
   guint wm_state_above : 1;
   guint wm_state_below : 1;
+
+  /* EWHH demands attention flag */
+  guint wm_state_demands_attention : 1;
   
   /* this flag tracks receipt of focus_in focus_out and
    * determines whether we draw the focus
