Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/metacity/ChangeLog,v
retrieving revision 1.683
diff -p -u -r1.683 ChangeLog
--- ChangeLog	12 Jun 2003 07:22:44 -0000	1.683
+++ ChangeLog	12 Jun 2003 07:23:04 -0000
@@ -1,3 +1,68 @@
+2003-06-10  Rob Adams  <robadams@ucla.edu>
+
+	Update constraints code to support the new _NET_WM_STRUT_PARTIAL
+	EWMH draft specification.  See #86682.  Also, fix a bug involving
+	work area invalidation on metacity startup.  Fix for #108497.
+	Finally, some minor fixes for full screen windows.
+
+	* src/window.h: Add new MetaStruts structure to store strut rects
+	for a window.  Remove has_struts and do_not_cover flag, and
+	support new MetaStruts instead of the four ints.
+	
+	* src/window.c (meta_window_new): change initialization to work
+	with new struts.  Also, move meta_window_update_struts call to
+	after the workspaces are initialized to fix #108497.  Remove
+	do_not_cover and related code.
+	(process_property_notify): add strut_partial
+	(update_struts): change function name to meta_window_update_struts
+	and expose in external MetaWindow API.  Support partial width
+	struts and the new strut rects.
+
+	* src/workspace.h: add new GSLists containing pointers to all
+	relevant struts for this workspace.
+
+	* src/workspace.c (meta_workspace_new): initialize the list of
+	strut rects for this workspace.
+	(meta_workspace_free): free the strut rect lists
+	(ensure_work_areas_validated): support new struts and new strut
+	rect lists.  Unleash the per-xinerama work areas.
+
+	* src/constraints.c (get_outermost_onscreen_positions): Use the
+	current window position along with the new per-workspace strut
+	rects to compute the constraints that apply to a particular
+	window.
+	(constraint_hint_applies_func): don't do hints constraints on
+	fullscreen windows
+	(update_position_limits): for maximized windows use the work areas
+	to set the position limits; for other windows rely on the struts
+	constraints to be computed later in
+	get_outermost_onscreen_positions
+	(meta_window_constrain): don't apply aspect ratio hints to full
+	screen windows
+
+	* src/display.c (meta_display_open): add _NET_WM_STRUT_PARTIAL atom
+	(meta_rectangle_equal): new helper function for MetaRectangles
+	(event_queue_callback): #ifndef out if USE_GDK_DISPLAY not set to
+	avoid compiler warning
+
+	* src/display.h: add atom_net_wm_strut_partial, and add
+	meta_rectangle_equal.
+
+	* src/screen.c (meta_screen_rect_intersects_xinerama): change
+	_window_intersects_ to _rect_intersects_ which is more useful now.
+	(meta_screen_resize_func): update struts on windows with struts
+	since struts are relative to the screen size, and this function is
+	called when the screen size updates.
+
+	* src/screen.h (meta_screen_rect_intersects_xinerama): change
+	_window_intersects_ to _rect_intersects_ which is more useful now.
+
+	* src/window-props.c (meta_display_init_window_prop_hooks): add
+	hook for strut_partial
+
+	* src/tools/metacity-window-demo.c: Support partial-width struts
+	on the dock window tests for metacity testing purposes.
+ 
 2003-06-12  Rob Adams  <robadams@ucla.edu>
 
 	Remove legacy support for Gnome 1 hints, since we deem it unlikely
Index: src/constraints.c
===================================================================
RCS file: /cvs/gnome/metacity/src/constraints.c,v
retrieving revision 1.9
diff -p -u -r1.9 constraints.c
--- src/constraints.c	9 Jun 2003 23:49:01 -0000	1.9
+++ src/constraints.c	12 Jun 2003 07:23:06 -0000
@@ -21,6 +21,8 @@
 
 #include <config.h>
 #include "constraints.h"
+#include "window.h"
+#include "workspace.h"
 #include "place.h"
 
 /* The way this code works was suggested by Owen Taylor.
@@ -123,7 +125,7 @@ typedef struct
  * size of the menu control?).
  */
 
-#define TITLEBAR_LENGTH_ONSCREEN 36
+#define TITLEBAR_LENGTH_ONSCREEN 75
 
 typedef gboolean (* MetaConstraintAppliesFunc) (MetaWindow *window);
 
@@ -301,7 +303,7 @@ static const Constraint constraint_deskt
  * behavior, but not doing that for now.
  *
  * Top resize works the same as left resize. Right/bottom resize don't have a limit
- * because the constraint is designed to keep the top right corner of the
+ * because the constraint is designed to keep the top left corner of the
  * window or its titlebar on the screen, and right/bottom resize will never move that
  * area. Center resize is almost like left/top but dx has the opposite sign
  * and new_width = orig_width + 2dx.
@@ -347,31 +349,153 @@ static void
 get_outermost_onscreen_positions (MetaWindow           *window,
                                   const ConstraintInfo *info,
                                   const MetaRectangle  *orig,
+                                  int                  delta_x,
+                                  int                  delta_y,
                                   int                  *leftmost_x,
                                   int                  *rightmost_x,
                                   int                  *topmost_y,
                                   int                  *bottommost_y)
 {
-  if (leftmost_x)
-    *leftmost_x = info->nw_x  - orig->width +
-      MIN (TITLEBAR_LENGTH_ONSCREEN, orig->width);
+  GList *workspaces;
+  GList *tmp;
+  GSList *stmp;
+  MetaRectangle current;
+
+  /* to handle struts, we get the list of workspaces for the window
+   * and traverse all the struts in each of the cached strut lists for
+   * the workspaces.  Note that because the workarea has already been
+   * computed, these strut lists should already be up to date.  No
+   * memory allocation should take place in this function for
+   * performance.
+   */
+
+  current = *orig;
+  current.x += delta_x;
+  current.y += delta_y;
 
+  workspaces = meta_window_get_workspaces (window);
+  tmp = workspaces;
+
+  if (leftmost_x)
+    {
+      *leftmost_x = info->nw_x;
+      while (tmp)
+        {
+          stmp = ((MetaWorkspace*) tmp->data)->left_struts;
+          while (stmp)
+            {
+              MetaRectangle *rect = (MetaRectangle*) stmp->data;
+              /* the strut only matters if the title bar is
+               * overlapping the strut rect.
+               */
+              if (((current.y - info->fgeom.top_height >= rect->y) &&
+                   (current.y - info->fgeom.top_height <= rect->y + rect->height)) ||
+                  ((current.y >= rect->y) &&
+                   (current.y <= rect->y + rect->height)))
+                {
+                  *leftmost_x = MAX (*leftmost_x, rect->width);
+                }
+              
+              stmp = stmp->next;
+            }
+          
+          tmp = tmp->next;
+        }
+      
+      *leftmost_x = *leftmost_x - current.width + 
+        MIN (TITLEBAR_LENGTH_ONSCREEN, current.width);
+    }
+  
+  tmp = workspaces;
   if (rightmost_x)
-    *rightmost_x = info->se_x - MIN (TITLEBAR_LENGTH_ONSCREEN, orig->width);
+    {
+      *rightmost_x = info->se_x;
+      while (tmp)
+        {
+          stmp = ((MetaWorkspace*) tmp->data)->right_struts;
+          while (stmp)
+            {
+              MetaRectangle *rect = (MetaRectangle*) stmp->data;
+              /* the strut only matters if the title bar is
+               * overlapping the strut rect.
+               */
+              if (((current.y - info->fgeom.top_height >= rect->y) &&
+                   (current.y - info->fgeom.top_height <= rect->y + rect->height)) ||
+                  ((current.y >= rect->y) &&
+                   (current.y <= rect->y + rect->height)))
+                {
+                  *rightmost_x = MIN (*rightmost_x, rect->x);
+                }
+              
+              stmp = stmp->next;
+            }
+          
+          tmp = tmp->next;
+        }
+      
+      *rightmost_x = *rightmost_x - 
+        MIN (TITLEBAR_LENGTH_ONSCREEN, current.width);
+    }
 
+  tmp = workspaces;
   if (topmost_y)
-    *topmost_y = info->nw_y + info->fgeom.top_height;
+    {
+      *topmost_y = info->nw_y;
+      while (tmp)
+        {
+          stmp = ((MetaWorkspace*) tmp->data)->top_struts;
+          while (stmp)
+            {
+              MetaRectangle *rect = (MetaRectangle*) stmp->data;
+              /* here the strut matters if the titlebar is overlapping
+               * the window horizontally
+               */
+	      if ((current.x <= rect->x + rect->width) &&
+		  (current.x + current.width >= rect->x))
+                {
+                  *topmost_y = MAX (*topmost_y, rect->height);
+                }
+              
+              stmp = stmp->next;
+            }
+          
+          tmp = tmp->next;
+        }
+      
+      *topmost_y = *topmost_y + info->fgeom.top_height;
+    }
 
+  tmp = workspaces;
   if (bottommost_y)
     {
+      *bottommost_y = info->se_y;
+      while (tmp)
+        {
+          stmp = ((MetaWorkspace*) tmp->data)->bottom_struts;
+          while (stmp)
+            {
+              MetaRectangle *rect = (MetaRectangle*) stmp->data;
+              /* here the strut matters if the titlebar is overlapping
+               * the window horizontally
+               */
+	      if ((current.x <= rect->x + rect->width) &&
+		  (current.x + current.width >= rect->x))
+                {
+                  *bottommost_y = MIN (*bottommost_y, rect->y);
+                }
+              
+              stmp = stmp->next;
+            }
+          
+          tmp = tmp->next;
+        }
+      
       /* If no frame, keep random TITLEBAR_LENGTH_ONSCREEN pixels on the
        * screen.
        */
-      if (window->frame)
-        *bottommost_y = info->se_y;
-      else
-        *bottommost_y = info->se_y -
-	  MIN (TITLEBAR_LENGTH_ONSCREEN, orig->height);
+      if (!window->frame)
+        *bottommost_y = *bottommost_y -
+          MIN (TITLEBAR_LENGTH_ONSCREEN, current.height);
     }
 }
 
@@ -384,7 +508,7 @@ constraint_onscreen_top_func     (MetaWi
   int min_dy;
   int topmost_y;
 
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, 0, *y_delta,
                                     NULL, NULL, &topmost_y, NULL);
 
   min_dy = topmost_y - orig->y;
@@ -402,7 +526,7 @@ constraint_onscreen_bottom_func  (MetaWi
   int max_dy;
   int bottommost_y;
 
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, 0, *y_delta,
                                     NULL, NULL, NULL, &bottommost_y);
 
   max_dy = bottommost_y - orig->y;
@@ -420,7 +544,7 @@ constraint_onscreen_vcenter_func (MetaWi
   int max_dy;
   int topmost_y;
 
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, 0, *y_delta,
                                     NULL, NULL, &topmost_y, NULL);
 
   max_dy = orig->y - topmost_y;
@@ -438,7 +562,7 @@ constraint_onscreen_left_func    (MetaWi
   int min_dx;
   int leftmost_x;
 
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, *x_delta, 0,
                                     &leftmost_x, NULL, NULL, NULL);
 
   min_dx = leftmost_x - orig->x;
@@ -456,7 +580,7 @@ constraint_onscreen_right_func   (MetaWi
   int max_dx;
   int rightmost_x;
 
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, *x_delta, 0,
                                     NULL, &rightmost_x, NULL, NULL);
 
   max_dx = rightmost_x - orig->x;
@@ -474,7 +598,7 @@ constraint_onscreen_hcenter_func (MetaWi
   int max_dx;
   int leftmost_x;
   
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, *x_delta, 0,
                                     &leftmost_x, NULL, NULL, NULL);
 
   max_dx = orig->x - leftmost_x;
@@ -494,7 +618,7 @@ constraint_onscreen_move_func    (MetaWi
   int max_delta;
   int leftmost_x, rightmost_x, topmost_y, bottommost_y;
 
-  get_outermost_onscreen_positions (window, info, orig,
+  get_outermost_onscreen_positions (window, info, orig, *x_delta, *y_delta,
                                     &leftmost_x, &rightmost_x,
                                     &topmost_y, &bottommost_y);
 
@@ -560,7 +684,7 @@ static const Constraint constraint_onscr
 static gboolean
 constraint_hints_applies_func (MetaWindow *window)
 {
-  return TRUE;
+  return (!window->fullscreen);
 }
 
 static void
@@ -787,25 +911,32 @@ constrain_move (MetaWindow           *wi
                 MetaRectangle        *new)
 {
   const Constraint **cp;
+  int old_x, old_y;
 
-  cp = &all_constraints[0];
 
-  while (*cp)
-    {
-      meta_topic (META_DEBUG_GEOMETRY,
-                  "Before: %d %d (Move constraint '%s')\n",
-                  x_delta, y_delta, (*cp)->name);
-                  
-      if ((* (*cp)->applies_func) (window))
-        (* (*cp)->move_func) (window, info, orig,
-                              &x_delta, &y_delta);
+  do {
+    old_x = x_delta;
+    old_y = y_delta;
+    cp = &all_constraints[0];
 
-      meta_topic (META_DEBUG_GEOMETRY,
-                  "After:  %d %d (Move constraint '%s')\n",
-                  x_delta, y_delta, (*cp)->name);
+    while (*cp)
+      {
+        meta_topic (META_DEBUG_GEOMETRY,
+                    "Before: %d %d (Move constraint '%s')\n",
+                    x_delta, y_delta, (*cp)->name);
+
+        if ((* (*cp)->applies_func) (window))
+          (* (*cp)->move_func) (window, info, orig,
+                                &x_delta, &y_delta);
+
+        meta_topic (META_DEBUG_GEOMETRY,
+                    "After:  %d %d (Move constraint '%s')\n",
+                    x_delta, y_delta, (*cp)->name);
       
-      ++cp;
-    }
+        ++cp;
+      }
+
+  } while ((old_x != x_delta) || (old_y != y_delta));
 
   new->x = orig->x + x_delta;
   new->y = orig->y + y_delta;
@@ -1023,12 +1154,24 @@ update_position_limits (MetaWindow      
   int nw_x, nw_y;
   int se_x, se_y;
 
-  nw_x = info->work_area_screen.x;
-  nw_y = info->work_area_screen.y;
+  if (window->maximized)
+    {
+      nw_x = MIN (info->work_area_xinerama.x, info->work_area_screen.x);
+      nw_y = MIN (info->work_area_xinerama.y, info->work_area_screen.y);
 
-  /* find bottom-right corner of workarea */
-  se_x = info->work_area_screen.x + info->work_area_screen.width;
-  se_y = info->work_area_screen.y + info->work_area_screen.height;
+      /* find bottom-right corner of workarea */
+      se_x = MAX (info->work_area_xinerama.x + info->work_area_xinerama.width,
+		  info->work_area_screen.x + info->work_area_screen.width);
+      se_y = MAX (info->work_area_xinerama.y + info->work_area_xinerama.height,
+		  info->work_area_screen.y + info->work_area_screen.height);
+    }
+  else
+    {
+      nw_x = 0;
+      nw_y = 0;
+      se_x = window->screen->width;
+      se_y = window->screen->height;
+   }
 
   /* If we have a micro-screen or huge frames maybe nw/se got
    * swapped
@@ -1078,7 +1221,7 @@ meta_window_constrain (MetaWindow       
 
 #define OUTER_WIDTH(rect) ((rect).width + info.fgeom.left_width + info.fgeom.right_width)
 #define OUTER_HEIGHT(rect) ((rect).height + info.fgeom.top_height + info.fgeom.bottom_height)
-  
+
   meta_topic (META_DEBUG_GEOMETRY,
               "Constraining %s x_move_delta = %d y_move_delta = %d x_direction = %d y_direction = %d x_delta = %d y_delta = %d orig %d,%d %dx%d\n",
               window->desc, x_move_delta, y_move_delta,
@@ -1252,108 +1395,108 @@ meta_window_constrain (MetaWindow       
 
 #if 0
   /* Now we have to sort out the aspect ratio */
-  {
-    /*
-     *                width
-     * min_aspect <= -------- <= max_aspect
-     *                height
-     */
-    double min_aspect, max_aspect;
-    int width, height;
-
-    min_aspect = window->size_hints.min_aspect.x / (double) window->size_hints.min_aspect.y;
-    max_aspect = window->size_hints.max_aspect.x / (double) window->size_hints.max_aspect.y;
-
-    width = current.width;
-    height = current.height;
-
-    /* Use the standard cut-and-pasted-between-every-WM code: */
-    if (min_aspect * height > width)
-      {
-        int delta;
-
-        delta = FLOOR (height - width / min_aspect, window->size_hints.height_inc);
-        if (height - delta >= window->size_hints.min_height)
-          height -= delta;
-        else
-          {
-            delta = FLOOR (height * min_aspect - width, window->size_hints.width_inc);
-            if (width + delta <= window->size_hints.max_width)
-              width += delta;
-          }
-      }
-
-    if (max_aspect * height < width)
-      {
-        int delta;
-
-        delta = FLOOR (width - height * max_aspect, window->size_hints.width_inc);
-        if (width - delta >= window->size_hints.min_width)
-          width -= delta;
-        else
-          {
-            delta = FLOOR (width / max_aspect - height, window->size_hints.height_inc);
-            if (height + delta <= window->size_hints.max_height)
-              height += delta;
-          }
-      }
-
-    /* Convert into terms of the direction of resize and reapply the
-     * earlier constraints; this means aspect ratio becomes the
-     * least-important of the constraints. If we wanted aspect to be
-     * the most important, we could just not do this next bit.
-     */
+  if (!window->fullscreen)
+    {
+      /*
+       *                width
+       * min_aspect <= -------- <= max_aspect
+       *                height
+       */
+      double min_aspect, max_aspect;
+      int width, height;
+      
+      min_aspect = window->size_hints.min_aspect.x / (double) window->size_hints.min_aspect.y;
+      max_aspect = window->size_hints.max_aspect.x / (double) window->size_hints.max_aspect.y;
+      
+      width = current.width;
+      height = current.height;
 
-    if (current.width != width)
-      {
-        x_delta = width - current.width; /* positive delta to increase width */
-        switch (x_direction)
-          {
-          case META_RESIZE_LEFT_OR_TOP:
-            constrain_resize_left (window, &info, &current,
-                                   - x_delta, new);
-            break;
-          case META_RESIZE_CENTER:
-            constrain_resize_hcenter (window, &info, &current,
+      /* Use the standard cut-and-pasted-between-every-WM code: */
+      if (min_aspect * height > width)
+        {
+          int delta;
+          
+          delta = FLOOR (height - width / min_aspect, window->size_hints.height_inc);
+          if (height - delta >= window->size_hints.min_height)
+            height -= delta;
+          else
+            {
+              delta = FLOOR (height * min_aspect - width, window->size_hints.width_inc);
+              if (width + delta <= window->size_hints.max_width)
+                width += delta;
+            }
+        }
+      
+      if (max_aspect * height < width)
+        {
+          int delta;
+          
+          delta = FLOOR (width - height * max_aspect, window->size_hints.width_inc);
+          if (width - delta >= window->size_hints.min_width)
+            width -= delta;
+          else
+            {
+              delta = FLOOR (width / max_aspect - height, window->size_hints.height_inc);
+              if (height + delta <= window->size_hints.max_height)
+                height += delta;
+            }
+        }
+      
+      /* Convert into terms of the direction of resize and reapply the
+       * earlier constraints; this means aspect ratio becomes the
+       * least-important of the constraints. If we wanted aspect to be
+       * the most important, we could just not do this next bit.
+       */
+      
+      if (current.width != width)
+        {
+          x_delta = width - current.width; /* positive delta to increase width */
+          switch (x_direction)
+            {
+            case META_RESIZE_LEFT_OR_TOP:
+              constrain_resize_left (window, &info, &current,
+                                     - x_delta, new);
+              break;
+            case META_RESIZE_CENTER:
+              constrain_resize_hcenter (window, &info, &current,
+                                        x_delta, new);
+              break;
+            case META_RESIZE_RIGHT_OR_BOTTOM:
+              constrain_resize_right (window, &info, &current,
                                       x_delta, new);
-            break;
-          case META_RESIZE_RIGHT_OR_BOTTOM:
-            constrain_resize_right (window, &info, &current,
-                                    x_delta, new);
-            break;
-          }
-      }
-
-    if (current.height != height)
-      {
-        y_delta = height - current.height; /* positive to increase height */
-
-        switch (y_direction)
-          {
-          case META_RESIZE_LEFT_OR_TOP:
-            constrain_resize_top (window, &info, &current,
-                                  - y_delta, new);
-            break;
-          case META_RESIZE_CENTER:
-            constrain_resize_vcenter (window, &info, &current,
-                                      y_delta, new);
-            break;
-          case META_RESIZE_RIGHT_OR_BOTTOM:
-            constrain_resize_bottom (window, &info, &current,
-                                     y_delta, new);
-            break;
-          }
-      }
-
-    current = *new;
-  }
+              break;
+            }
+        }
+      
+      if (current.height != height)
+        {
+          y_delta = height - current.height; /* positive to increase height */
+          
+          switch (y_direction)
+            {
+            case META_RESIZE_LEFT_OR_TOP:
+              constrain_resize_top (window, &info, &current,
+                                    - y_delta, new);
+              break;
+            case META_RESIZE_CENTER:
+              constrain_resize_vcenter (window, &info, &current,
+                                        y_delta, new);
+              break;
+            case META_RESIZE_RIGHT_OR_BOTTOM:
+              constrain_resize_bottom (window, &info, &current,
+                                       y_delta, new);
+              break;
+            }
+        }
+      
+      current = *new;
 
+      g_print ("3 x_delta = %d y_delta = %d pos = %d,%d size = %dx%d\n",
+               x_delta, y_delta,
+               current.x, current.y, current.width, current.height);
+    }
 
-  g_print ("3 x_delta = %d y_delta = %d pos = %d,%d size = %dx%d\n",
-           x_delta, y_delta,
-           current.x, current.y, current.width, current.height);
 #endif
-
   meta_topic (META_DEBUG_GEOMETRY,
               "Constrained %s new %d,%d %dx%d old %d,%d %dx%d\n",
               window->desc,
Index: src/display.c
===================================================================
RCS file: /cvs/gnome/metacity/src/display.c,v
retrieving revision 1.189
diff -p -u -r1.189 display.c
--- src/display.c	12 Jun 2003 07:03:04 -0000	1.189
+++ src/display.c	12 Jun 2003 07:23:09 -0000
@@ -77,6 +77,11 @@ static GSList *all_displays = NULL;
 
 static void   meta_spew_event           (MetaDisplay    *display,
                                          XEvent         *event);
+#ifndef USE_GDK_DISPLAY
+static void   event_queue_callback      (XEvent         *event,
+                                         gpointer        data);
+#endif
+
 static gboolean event_callback          (XEvent         *event,
                                          gpointer        data);
 static Window event_get_modified_window (MetaDisplay    *display,
@@ -263,7 +268,8 @@ meta_display_open (const char *name)
     "_GNOME_PANEL_ACTION",
     "_GNOME_PANEL_ACTION_MAIN_MENU",
     "_GNOME_PANEL_ACTION_RUN_DIALOG",
-    "_METACITY_SENTINEL"
+    "_METACITY_SENTINEL",
+    "_NET_WM_STRUT_PARTIAL"
   };
   Atom atoms[G_N_ELEMENTS(atom_names)];
   
@@ -406,6 +412,7 @@ meta_display_open (const char *name)
   display->atom_gnome_panel_action_main_menu = atoms[77];
   display->atom_gnome_panel_action_run_dialog = atoms[78];
   display->atom_metacity_sentinel = atoms[79];
+  display->atom_net_wm_strut_partial = atoms[80];
   
   display->prop_hooks = NULL;
   meta_display_init_window_prop_hooks (display);
@@ -875,6 +882,15 @@ meta_display_is_double_click (MetaDispla
 
 static gboolean dump_events = TRUE;
 
+#ifndef USE_GDK_DISPLAY
+static void
+event_queue_callback (XEvent         *event,
+                      gpointer        data)
+{
+  event_callback (event, data);
+}
+#endif
+
 static gboolean
 grab_op_is_mouse (MetaGrabOp op)
 {
@@ -1252,6 +1268,7 @@ event_callback (XEvent   *event,
               if (window->frame)
                 {
                   window->frame->need_reapply_frame_shape = TRUE;
+		  meta_warning("from event callback\n");		  
                   meta_window_queue_move_resize (window);
                 }
             }
@@ -3201,6 +3218,7 @@ meta_display_queue_retheme_all_windows (
     {
       MetaWindow *window = tmp->data;
       
+      meta_warning("from retheme\n");
       meta_window_queue_move_resize (window);
       if (window->frame)
         {
@@ -3673,6 +3691,16 @@ meta_rectangle_intersect (MetaRectangle 
     }
 
   return return_val;
+}
+
+gboolean
+meta_rectangle_equal (const MetaRectangle *src1,
+                      const MetaRectangle *src2)
+{
+  return ((src1->x == src2->x) &&
+          (src1->y == src2->y) &&
+          (src1->width == src2->width) &&
+          (src1->height == src2->height));
 }
 
 static MetaScreen*
Index: src/display.h
===================================================================
RCS file: /cvs/gnome/metacity/src/display.h,v
retrieving revision 1.105
diff -p -u -r1.105 display.h
--- src/display.h	12 Jun 2003 07:03:04 -0000	1.105
+++ src/display.h	12 Jun 2003 07:23:10 -0000
@@ -168,6 +168,7 @@ struct _MetaDisplay
   Atom atom_gnome_panel_action_main_menu;
   Atom atom_gnome_panel_action_run_dialog;
   Atom atom_metacity_sentinel;
+  Atom atom_net_wm_strut_partial;
   
   /* This is the actual window from focus events,
    * not the one we last set
@@ -433,6 +434,8 @@ gboolean meta_grab_op_is_resizing (MetaG
 gboolean meta_rectangle_intersect (MetaRectangle *src1,
                                    MetaRectangle *src2,
                                    MetaRectangle *dest);
+gboolean meta_rectangle_equal (const MetaRectangle *src1,
+                               const MetaRectangle *src2);
 
 void meta_display_devirtualize_modifiers (MetaDisplay        *display,
                                           MetaVirtualModifier modifiers,
Index: src/screen.c
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.c,v
retrieving revision 1.107
diff -p -u -r1.107 screen.c
--- src/screen.c	12 Jun 2003 07:03:04 -0000	1.107
+++ src/screen.c	12 Jun 2003 07:23:12 -0000
@@ -1461,21 +1461,18 @@ meta_screen_get_natural_xinerama_list (M
 }
 
 gboolean
-meta_screen_window_intersects_xinerama (MetaScreen *screen,
-                                        MetaWindow *window,
-                                        int         which_xinerama)
+meta_screen_rect_intersects_xinerama (MetaScreen    *screen,
+                                      MetaRectangle *rect,
+                                      int            which_xinerama)
 {
-  MetaRectangle window_rect;
   MetaRectangle dest, screen_rect;
   
-  meta_window_get_outer_rect (window, &window_rect);
-  
   screen_rect.x = screen->xinerama_infos[which_xinerama].x_origin;
   screen_rect.y = screen->xinerama_infos[which_xinerama].y_origin;
   screen_rect.width = screen->xinerama_infos[which_xinerama].width;
   screen_rect.height = screen->xinerama_infos[which_xinerama].height;
   
-  if (meta_rectangle_intersect (&screen_rect, &window_rect, &dest))
+  if (meta_rectangle_intersect (&screen_rect, rect, &dest))
     return TRUE;
 
   return FALSE;
@@ -2105,6 +2102,10 @@ meta_screen_resize_func (MetaScreen *scr
                          MetaWindow *window,
                          void       *user_data)
 {
+  if (window->struts)
+    {
+      meta_window_update_struts (window);
+    }
   meta_window_queue_move_resize (window);
 }
 
Index: src/screen.h
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.h,v
retrieving revision 1.49
diff -p -u -r1.49 screen.h
--- src/screen.h	16 May 2003 21:59:08 -0000	1.49
+++ src/screen.h	12 Jun 2003 07:23:12 -0000
@@ -148,9 +148,9 @@ const MetaXineramaScreenInfo* meta_scree
 const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen    *screen,
                                                                    MetaWindow    *window);
 
-gboolean      meta_screen_window_intersects_xinerama (MetaScreen *screen, 
-                                                      MetaWindow *window,
-                                                      int         which_xinerama);
+gboolean      meta_screen_rect_intersects_xinerama (MetaScreen    *screen, 
+                                                    MetaRectangle *window,
+                                                    int            which_xinerama);
 
 const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen,
                                                                  int         which_xinerama,
Index: src/window-props.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window-props.c,v
retrieving revision 1.12
diff -p -u -r1.12 window-props.c
--- src/window-props.c	12 Jun 2003 07:03:04 -0000	1.12
+++ src/window-props.c	12 Jun 2003 07:23:13 -0000
@@ -814,7 +814,7 @@ reload_wm_hints (MetaWindow    *window,
 
 
 
-#define N_HOOKS 22
+#define N_HOOKS 23
 
 void
 meta_display_init_window_prop_hooks (MetaDisplay *display)
@@ -910,6 +910,11 @@ meta_display_init_window_prop_hooks (Met
   ++i;
 
   hooks[i].property = display->atom_net_wm_strut;
+  hooks[i].init_func = NULL;
+  hooks[i].reload_func = NULL;
+  ++i;
+
+  hooks[i].property = display->atom_net_wm_strut_partial;
   hooks[i].init_func = NULL;
   hooks[i].reload_func = NULL;
   ++i;
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.287
diff -p -u -r1.287 window.c
--- src/window.c	12 Jun 2003 07:03:04 -0000	1.287
+++ src/window.c	12 Jun 2003 07:23:18 -0000
@@ -64,7 +64,6 @@ static void     update_transient_for    
 static void     update_sm_hints           (MetaWindow     *window);
 static void     update_role               (MetaWindow     *window);
 static void     update_net_wm_type        (MetaWindow     *window);
-static void     update_struts             (MetaWindow     *window);
 static void     recalc_window_type        (MetaWindow     *window);
 static void     recalc_window_features    (MetaWindow     *window);
 static void     invalidate_work_areas     (MetaWindow     *window);
@@ -77,8 +76,6 @@ static gboolean process_property_notify 
 static void     meta_window_show          (MetaWindow     *window);
 static void     meta_window_hide          (MetaWindow     *window);
 
-static GList*   meta_window_get_workspaces (MetaWindow    *window);
-
 static void     meta_window_save_rect         (MetaWindow    *window);
 
 static void meta_window_move_resize_internal (MetaWindow         *window,
@@ -479,11 +476,7 @@ meta_window_new (MetaDisplay *display,
   window->type = META_WINDOW_NORMAL;
   window->type_atom = None;
 
-  window->has_struts = FALSE;
-  window->left_strut = 0;
-  window->right_strut = 0;
-  window->top_strut = 0;
-  window->bottom_strut = 0;
+  window->struts = NULL;
 
   window->using_net_wm_name = FALSE;
   window->using_net_wm_icon_name = FALSE;
@@ -516,8 +509,6 @@ meta_window_new (MetaDisplay *display,
   g_assert (N_INITIAL_PROPS == i);
   
   meta_window_reload_properties (window, initial_props, N_INITIAL_PROPS);
-  
-  update_struts (window);
 
   update_net_wm_state (window);
   
@@ -651,6 +642,8 @@ meta_window_new (MetaDisplay *display,
 
   /* for the various on_all_workspaces = TRUE possible above */
   meta_window_set_current_workspace_hint (window);
+  
+  meta_window_update_struts (window);
 
   /* Put our state back where it should be,
    * passing TRUE for is_configure_request, ICCCM says
@@ -907,8 +900,11 @@ meta_window_free (MetaWindow  *window)
                   window->desc);
     }
 
-  if (window->has_struts)
+  if (window->struts)
     {
+      g_free (window->struts);
+      window->struts = NULL;
+
       meta_topic (META_DEBUG_WORKAREA,
                   "Unmanaging window %s which has struts, so invalidating work areas\n",
                   window->desc);
@@ -1679,7 +1675,7 @@ meta_window_show (MetaWindow *window)
     {
       set_net_wm_state (window);
       
-      if (window->has_struts)
+      if (window->struts)
         {
           meta_topic (META_DEBUG_WORKAREA,
                       "Mapped window %s with struts, so invalidating work areas\n",
@@ -1732,7 +1728,7 @@ meta_window_hide (MetaWindow *window)
     {
       set_net_wm_state (window);
       
-      if (window->has_struts)
+      if (window->struts)
         {
           meta_topic (META_DEBUG_WORKAREA,
                       "Unmapped window %s with struts, so invalidating work areas\n",
@@ -2307,7 +2303,7 @@ meta_window_move_resize_internal (MetaWi
                          meta_y_direction_from_gravity (resize_gravity),
                          y_delta,
                          &new_rect);
-  
+
   w = new_rect.width;
   h = new_rect.height;
   root_x_nw = new_rect.x;
@@ -4118,10 +4114,11 @@ process_property_notify (MetaWindow     
                                         event->atom);
       meta_window_queue_update_icon (window);
     }
-  else if (event->atom == window->display->atom_net_wm_strut)
+  else if ((event->atom == window->display->atom_net_wm_strut) ||
+	   (event->atom == window->display->atom_net_wm_strut_partial))
     {
       meta_verbose ("Property notify on %s for _NET_WM_STRUT\n", window->desc);
-      update_struts (window);
+      meta_window_update_struts (window);
     }
   else if (event->atom == window->display->atom_net_startup_id)
     {
@@ -4788,7 +4785,7 @@ meta_window_queue_update_icon (MetaWindo
   update_icon_pending = g_slist_prepend (update_icon_pending, window);
 }
 
-static GList*
+GList*
 meta_window_get_workspaces (MetaWindow *window)
 {
   if (window->on_all_workspaces)
@@ -4811,68 +4808,102 @@ invalidate_work_areas (MetaWindow *windo
     }
 }
 
-static void
-update_struts (MetaWindow *window)
+void
+meta_window_update_struts (MetaWindow *window)
 {
   gulong *struts = NULL;
   int nitems;
   gboolean old_has_struts;
-  int old_left;
-  int old_right;
-  int old_top;
-  int old_bottom;
+  gboolean new_has_struts;
+
+  MetaRectangle old_left;
+  MetaRectangle old_right;
+  MetaRectangle old_top;
+  MetaRectangle old_bottom;
+
+  MetaRectangle new_left;
+  MetaRectangle new_right;
+  MetaRectangle new_top;
+  MetaRectangle new_bottom;
   
   meta_verbose ("Updating struts for %s\n", window->desc);
   
-  old_has_struts = window->has_struts;
-  old_left = window->left_strut;
-  old_right = window->right_strut;
-  old_top = window->top_strut;
-  old_bottom = window->bottom_strut;  
-  
-  window->has_struts = FALSE;
-  window->left_strut = 0;
-  window->right_strut = 0;
-  window->top_strut = 0;
-  window->bottom_strut = 0;
+  if (window->struts)
+    {
+      old_has_struts = TRUE;
+      old_left = window->struts->left;
+      old_right = window->struts->right;
+      old_top = window->struts->top;
+      old_bottom = window->struts->bottom;
+    }
+  else
+    {
+      old_has_struts = FALSE;
+    }
+
+  new_has_struts = FALSE;
+  new_left.width = 0;
+  new_left.x = 0;
+  new_left.y = 0;
+  new_left.height = window->screen->height;
+
+  new_right.width = 0;
+  new_right.x = window->screen->width;
+  new_right.y = 0;
+  new_right.height = window->screen->height;
+
+  new_top.height = 0;
+  new_top.y = 0;
+  new_top.x = 0;
+  new_top.width = window->screen->width;
+
+  new_bottom.height = 0;
+  new_bottom.y = window->screen->height;
+  new_bottom.x = 0;
+  new_bottom.width = window->screen->width;
   
   if (meta_prop_get_cardinal_list (window->display,
                                    window->xwindow,
-                                   window->display->atom_net_wm_strut,
+                                   window->display->atom_net_wm_strut_partial,
                                    &struts, &nitems))
     {
-      if (nitems != 4)
+      if (nitems != 12)
         {
-          meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n",
+          meta_verbose ("_NET_WM_STRUT_PARTIAL on %s has %d values instead of 12\n",
                         window->desc, nitems);
-          meta_XFree (struts);
         }
-      
-      window->has_struts = TRUE;
-      window->left_strut = struts[0];
-      window->right_strut = struts[1];
-      window->top_strut = struts[2];
-      window->bottom_strut = struts[3];
-
-      meta_verbose ("_NET_WM_STRUT struts %d %d %d %d for window %s\n",
-                    window->left_strut, window->right_strut,
-                    window->top_strut, window->bottom_strut,
-                    window->desc);
-      
-      if (window->left_strut < 0)
-        window->left_strut = 0;
-      if (window->right_strut < 0)
-        window->right_strut = 0;
-      if (window->top_strut < 0)
-        window->top_strut = 0;
-      if (window->bottom_strut < 0)
-        window->bottom_strut = 0;
-      
-      meta_verbose ("Using _NET_WM_STRUT struts %d %d %d %d for window %s\n",
-                    window->left_strut, window->right_strut,
-                    window->top_strut, window->bottom_strut,
-                    window->desc);
-      
+      else
+        {
+          new_has_struts = TRUE;
+          new_left.width = MIN ((int)struts[0], 
+                                window->screen->width/2 - 75);
+          new_right.width = MIN ((int)struts[1], 
+                                 window->screen->width/2 - 75);
+          new_top.height = MIN ((int)struts[2], 
+                                window->screen->height/2 - 75);
+          new_bottom.height = MIN ((int)struts[3], 
+                                   window->screen->height/2 - 75);
+          new_right.x = window->screen->width - 
+            new_right.width;
+          new_bottom.y = window->screen->height - 
+            new_bottom.height;
+          new_left.y = struts[4];
+          new_left.height = struts[5] - new_left.y;
+          new_right.y = struts[6];
+          new_right.height = struts[7] - new_right.y;
+          new_top.x = struts[8];
+          new_top.width = struts[9] - new_top.x;
+          new_bottom.x = struts[10];
+          new_bottom.width = struts[11] - new_bottom.x;
+          
+          meta_verbose ("_NET_WM_STRUT_PARTIAL struts %d %d %d %d for window %s\n",
+                        new_left.width,
+                        new_right.width,
+                        new_top.height,
+                        new_bottom.height,
+                        window->desc);
+          
+        }
       meta_XFree (struts);
     }
   else
@@ -4881,12 +4912,75 @@ update_struts (MetaWindow *window)
                     window->desc);
     }
 
-  if (old_has_struts != window->has_struts ||
-      old_left != window->left_strut ||
-      old_right != window->right_strut ||
-      old_top != window->top_strut ||
-      old_bottom != window->bottom_strut)
-    {  
+  if (!new_has_struts)
+    {
+      if (meta_prop_get_cardinal_list (window->display,
+                                       window->xwindow,
+                                       window->display->atom_net_wm_strut,
+                                       &struts, &nitems))
+        {
+          if (nitems != 4)
+            {
+              meta_verbose ("_NET_WM_STRUT on %s has %d values instead of 4\n",
+                            window->desc, nitems);
+            }
+          else
+            {
+              new_has_struts = TRUE;
+              new_left.width = MIN ((int)struts[0], 
+                                    window->screen->width/2 - 75);
+              new_right.width = MIN ((int)struts[1], 
+                                     window->screen->width/2 - 75);
+              new_top.height = MIN ((int)struts[2], 
+                                    window->screen->height/2 - 75);
+              new_bottom.height = MIN ((int)struts[3], 
+                                       window->screen->height/2 - 75);
+              new_left.x = 0;
+              new_right.x = window->screen->width - 
+                new_right.width;
+              new_top.y = 0;
+              new_bottom.y = window->screen->height -
+                new_bottom.height;
+          
+              meta_verbose ("_NET_WM_STRUT struts %d %d %d %d for window %s\n",
+                            new_left.width,
+                            new_right.width,
+                            new_top.height,
+                            new_bottom.height,
+                            window->desc);
+              
+            }
+          meta_XFree (struts);
+        }
+      else
+        {
+          meta_verbose ("No _NET_WM_STRUT property for %s\n",
+                        window->desc);
+        }
+    }
+ 
+  if (old_has_struts != new_has_struts ||
+      (new_has_struts && old_has_struts &&
+       (!meta_rectangle_equal(&old_left, &new_left) ||
+        !meta_rectangle_equal(&old_right, &new_right) ||
+        !meta_rectangle_equal(&old_top, &new_top) ||
+        !meta_rectangle_equal(&old_bottom, &new_bottom))))
+    {
+      if (new_has_struts)
+        {
+          if (!window->struts)
+            window->struts = g_new (MetaStruts, 1);
+              
+          window->struts->left = new_left;
+          window->struts->right = new_right;
+          window->struts->top = new_top;
+          window->struts->bottom = new_bottom;
+        }
+      else
+        {
+          g_free (window->struts);
+          window->struts = NULL;
+        }
       meta_topic (META_DEBUG_WORKAREA,
                   "Invalidating work areas of window %s due to struts update\n",
                   window->desc);
Index: src/window.h
===================================================================
RCS file: /cvs/gnome/metacity/src/window.h,v
retrieving revision 1.92
diff -p -u -r1.92 window.h
--- src/window.h	12 Jun 2003 07:03:04 -0000	1.92
+++ src/window.h	12 Jun 2003 07:23:19 -0000
@@ -32,6 +32,7 @@
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
 typedef struct _MetaGroup MetaGroup;
+typedef struct _MetaStruts MetaStruts;
 
 typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
                                            void       *data);
@@ -49,6 +50,15 @@ typedef enum
   META_WINDOW_SPLASHSCREEN
 } MetaWindowType;
 
+struct _MetaStruts
+{
+  /* struts */
+  MetaRectangle left;
+  MetaRectangle right;
+  MetaRectangle top;
+  MetaRectangle bottom;
+};
+
 struct _MetaWindow
 {
   MetaDisplay *display;
@@ -211,8 +221,8 @@ struct _MetaWindow
    */
   guint calc_placement : 1;
 
-  /* Has nonzero struts */
-  guint has_struts : 1; 
+  /* Note: can be NULL */
+  MetaStruts *struts;
 
   /* Transient parent is a root window */
   guint transient_parent_is_root_window : 1;
@@ -271,12 +281,6 @@ struct _MetaWindow
   /* x/y/w/h here get filled with ConfigureRequest values */
   XSizeHints size_hints;
 
-  /* struts */
-  int left_strut;
-  int right_strut;
-  int top_strut;
-  int bottom_strut;
-  
   /* Managed by stack.c */
   MetaStackLayer layer;
   int stack_position; /* see comment in stack.h */
@@ -355,6 +359,8 @@ void        meta_window_fill_vertical   
  */
 void        meta_window_queue_move_resize  (MetaWindow  *window);
 
+void        meta_window_update_struts      (MetaWindow  *window);
+
 /* this gets root coords */
 void        meta_window_get_position       (MetaWindow  *window,
                                             int         *x,
@@ -423,6 +429,8 @@ void meta_window_set_gravity (MetaWindow
 
 void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
                                              XEvent     *event);
+
+GList* meta_window_get_workspaces (MetaWindow *window);
 
 gboolean meta_window_visible_on_workspace (MetaWindow    *window,
                                            MetaWorkspace *workspace);
Index: src/workspace.c
===================================================================
RCS file: /cvs/gnome/metacity/src/workspace.c,v
retrieving revision 1.43
diff -p -u -r1.43 workspace.c
--- src/workspace.c	30 May 2003 20:24:00 -0000	1.43
+++ src/workspace.c	12 Jun 2003 07:23:19 -0000
@@ -48,6 +48,11 @@ meta_workspace_new (MetaScreen *screen)
   workspace->all_work_areas.y = 0;
   workspace->all_work_areas.width = 0;
   workspace->all_work_areas.height = 0;
+
+  workspace->left_struts = NULL;
+  workspace->right_struts = NULL;
+  workspace->top_struts = NULL;
+  workspace->bottom_struts = NULL;
   
   return workspace;
 }
@@ -86,6 +91,12 @@ meta_workspace_free (MetaWorkspace *work
     g_list_remove (workspace->screen->workspaces, workspace);
   
   g_free (workspace->work_areas);
+
+  g_slist_free (workspace->left_struts);
+  g_slist_free (workspace->right_struts);
+  g_slist_free (workspace->top_struts);
+  g_slist_free (workspace->bottom_struts);
+
   g_free (workspace);
 
   /* don't bother to reset names, pagers can just ignore
@@ -105,7 +116,7 @@ meta_workspace_add_window (MetaWorkspace
   meta_window_set_current_workspace_hint (window);
   
   meta_window_queue_calc_showing (window);
-  if (window->has_struts)
+  if (window->struts)
     {
       meta_topic (META_DEBUG_WORKAREA,
                   "Invalidating work area of workspace %d since we're adding window %s to it\n",
@@ -132,7 +143,7 @@ meta_workspace_remove_window (MetaWorksp
   
   meta_window_queue_calc_showing (window);
 
-  if (window->has_struts)
+  if (window->struts)
     {
       meta_topic (META_DEBUG_WORKAREA,
                   "Invalidating work area of workspace %d since we're removing window %s from it\n",
@@ -375,6 +386,15 @@ ensure_work_areas_validated (MetaWorkspa
   if (!workspace->work_areas_invalid)
     return;
       
+  g_slist_free (workspace->left_struts);
+  workspace->left_struts = NULL;
+  g_slist_free (workspace->right_struts);
+  workspace->right_struts = NULL;
+  g_slist_free (workspace->top_struts);
+  workspace->top_struts = NULL;
+  g_slist_free (workspace->bottom_struts);
+  workspace->bottom_struts = NULL;
+
   windows = meta_workspace_list_windows (workspace);
 
   g_free (workspace->work_areas);
@@ -394,33 +414,76 @@ ensure_work_areas_validated (MetaWorkspa
         {
           MetaWindow *w = tmp->data;
 
-          if (w->has_struts && 
-              (meta_screen_window_intersects_xinerama (w->screen, w, i)))
+          if (w->struts)
             {
               meta_topic (META_DEBUG_WORKAREA,
                           "Merging win %s with %d %d %d %d "
                           "with %d %d %d %d\n",
                           w->desc,
-                          w->left_strut, w->right_strut, 
-                          w->top_strut, w->bottom_strut,
+                          w->struts->left.width, w->struts->right.width, 
+                          w->struts->top.height, w->struts->bottom.height,
                           left_strut, right_strut, 
                           top_strut, bottom_strut);
 
-              left_strut = MAX (left_strut, 
-                                w->left_strut - 
-                                workspace->screen->xinerama_infos[i].x_origin);
-              all_left_strut = MAX (all_left_strut, w->left_strut);
-
-              right_strut = MAX (right_strut, w->right_strut);
-              all_right_strut = MAX (all_right_strut, w->right_strut);
-
-              top_strut = MAX (top_strut,
-                               w->top_strut - 
-                               workspace->screen->xinerama_infos[i].y_origin);
-              all_top_strut = MAX (all_top_strut, w->top_strut);
-
-              bottom_strut = MAX (bottom_strut, w->bottom_strut);
-              all_bottom_strut = MAX (all_bottom_strut, w->bottom_strut);
+              if ((i == 0) && (w->struts->left.width > 0))
+                {
+                  workspace->left_struts = g_slist_prepend (workspace->left_struts,
+                                                            &w->struts->left);
+                }
+
+              if (meta_screen_rect_intersects_xinerama (w->screen,
+                                                        &w->struts->left,
+                                                        i))
+                {
+                  left_strut = MAX (left_strut, 
+                                    w->struts->left.width - 
+                                    workspace->screen->xinerama_infos[i].x_origin);
+                  all_left_strut = MAX (all_left_strut, w->struts->left.width);
+                }
+
+              if ((i == 0) && (w->struts->right.width > 0))
+                {
+                  workspace->right_struts = g_slist_prepend (workspace->right_struts,
+							     &w->struts->right);
+                }
+
+              if (meta_screen_rect_intersects_xinerama (w->screen,
+                                                        &w->struts->right,
+                                                        i))
+                {
+                  right_strut = MAX (right_strut, w->struts->right.width);
+                  all_right_strut = MAX (all_right_strut, w->struts->right.width);
+                }
+
+              if ((i == 0) && (w->struts->top.height > 0))
+                {
+                  workspace->top_struts = g_slist_prepend (workspace->top_struts,
+                                                           &w->struts->top);
+                }
+
+              if (meta_screen_rect_intersects_xinerama (w->screen,
+                                                        &w->struts->top,
+                                                        i))
+                {
+                  top_strut = MAX (top_strut,
+                                   w->struts->top.height - 
+                                   workspace->screen->xinerama_infos[i].y_origin);
+                  all_top_strut = MAX (all_top_strut, w->struts->top.height);
+                }
+
+              if ((i == 0) && (w->struts->bottom.height > 0))
+                {
+                  workspace->bottom_struts = g_slist_prepend (workspace->bottom_struts,
+                                                              &w->struts->bottom);
+                }
+
+              if (meta_screen_rect_intersects_xinerama (w->screen,
+                                                        &w->struts->bottom,
+                                                        i))
+                {
+                  bottom_strut = MAX (bottom_strut, w->struts->bottom.height);
+                  all_bottom_strut = MAX (all_bottom_strut, w->struts->bottom.height);
+                }
             }
           
           tmp = tmp->next;
@@ -451,10 +514,6 @@ ensure_work_areas_validated (MetaWorkspa
           bottom_strut = top_strut;
         }
 
-      /* FIXME even if we take struts to apply only to xineramas
-       * that the strut-specifying window overlaps, is it right
-       * to make the struts *relative to* the xinerama?
-       */
       workspace->work_areas[i].x = 
         left_strut + workspace->screen->xinerama_infos[i].x_origin;
       workspace->work_areas[i].y = top_strut + 
@@ -467,7 +526,7 @@ ensure_work_areas_validated (MetaWorkspa
         top_strut - bottom_strut;
 
       meta_topic (META_DEBUG_WORKAREA,
-                  "Computed [unused] work area for workspace %d "
+                  "Computed work area for workspace %d "
                   "xinerama %d: %d,%d %d x %d\n",
                   meta_workspace_index (workspace),
                   i,
@@ -507,19 +566,6 @@ ensure_work_areas_validated (MetaWorkspa
     workspace->screen->width - all_left_strut - all_right_strut;
   workspace->all_work_areas.height = 
     workspace->screen->height - all_top_strut - all_bottom_strut;
-
-  /* FIXME Here we disable all the per-xinerama work done earlier,
-   * because we don't have a spec for how it should work yet.
-   * If we do rely on which windows overlap what, work areas
-   * will need to be invalidated when we change a strut-setting
-   * window's size/position in move_resize_internal
-   */
-  i = 0;
-  while (i < workspace->screen->n_xinerama_infos)
-    {
-      workspace->work_areas[i] = workspace->all_work_areas;
-      ++i;
-    }
   
   workspace->work_areas_invalid = FALSE;
 
Index: src/workspace.h
===================================================================
RCS file: /cvs/gnome/metacity/src/workspace.h,v
retrieving revision 1.15
diff -p -u -r1.15 workspace.h
--- src/workspace.h	30 May 2003 20:24:00 -0000	1.15
+++ src/workspace.h	12 Jun 2003 07:23:19 -0000
@@ -42,8 +42,11 @@ struct _MetaWorkspace
   GList *windows;
 
   MetaRectangle all_work_areas;
-  
   MetaRectangle *work_areas;
+  GSList *left_struts;
+  GSList *right_struts;
+  GSList *top_struts;
+  GSList *bottom_struts;
   guint work_areas_invalid : 1;
 };
 
Index: src/tools/metacity-window-demo.c
===================================================================
RCS file: /cvs/gnome/metacity/src/tools/metacity-window-demo.c,v
retrieving revision 1.14
diff -p -u -r1.14 metacity-window-demo.c
--- src/tools/metacity-window-demo.c	18 Oct 2002 06:05:09 -0000	1.14
+++ src/tools/metacity-window-demo.c	12 Jun 2003 07:23:20 -0000
@@ -33,19 +33,27 @@ set_gdk_window_struts (GdkWindow *window
                        int        top,
                        int        bottom)
 {
-  long vals[4];
+  long vals[12];
   
   vals[0] = left;
   vals[1] = right;
   vals[2] = top;
   vals[3] = bottom;
-  
+  vals[4] = 000;
+  vals[5] = 400;
+  vals[6] = 200;
+  vals[7] = 600;
+  vals[8] = 76;
+  vals[9] = 676;
+  vals[10] = 200;
+  vals[11] = 800;
+
   XChangeProperty (GDK_WINDOW_XDISPLAY (window),
                    GDK_WINDOW_XWINDOW (window),
                    XInternAtom (GDK_WINDOW_XDISPLAY (window),
-                                "_NET_WM_STRUT", False),
+                                "_NET_WM_STRUT_PARTIAL", False),
                    XA_CARDINAL, 32, PropModeReplace,
-                   (guchar *)vals, 4);
+                   (guchar *)vals, 12);
 }
 
 static void
@@ -441,6 +449,7 @@ border_only_cb (gpointer             cal
   gtk_widget_show_all (window);
 }
 
+#if 0
 static void
 changing_icon_cb (gpointer             callback_data,
                   guint                callback_action,
@@ -462,6 +471,7 @@ changing_icon_cb (gpointer             c
   
   gtk_widget_show_all (window);
 }
+#endif
 
 static gboolean
 focus_in_event_cb (GtkWidget *window,
@@ -473,6 +483,8 @@ focus_in_event_cb (GtkWidget *window,
   widget = GTK_WIDGET (data);
 
   gtk_label_set_text (GTK_LABEL (widget), "Has focus");
+
+  return TRUE;
 }
 
 
@@ -486,6 +498,8 @@ focus_out_event_cb (GtkWidget *window,
   widget = GTK_WIDGET (data);
 
   gtk_label_set_text (GTK_LABEL (widget), "Not focused");
+  
+  return TRUE;
 }
 
 static GtkWidget*
@@ -583,26 +597,26 @@ make_dock (int type)
   switch (type)
     {
     case DOCK_LEFT:
-      gtk_widget_set_size_request (window, DOCK_SIZE, gdk_screen_height ());
-      gtk_window_move (GTK_WINDOW (window), 0, 0);
+      gtk_widget_set_size_request (window, DOCK_SIZE, 400);
+      gtk_window_move (GTK_WINDOW (window), 0, 000);
       set_gtk_window_struts (window, DOCK_SIZE, 0, 0, 0);
       gtk_window_set_title (GTK_WINDOW (window), "LeftDock");
       break;
     case DOCK_RIGHT:      
-      gtk_widget_set_size_request (window, DOCK_SIZE, gdk_screen_height ());
-      gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 0);
+      gtk_widget_set_size_request (window, DOCK_SIZE, 400);
+      gtk_window_move (GTK_WINDOW (window), gdk_screen_width () - DOCK_SIZE, 200);
       set_gtk_window_struts (window, 0, DOCK_SIZE, 0, 0);
       gtk_window_set_title (GTK_WINDOW (window), "RightDock");
       break;
     case DOCK_TOP:
-      gtk_widget_set_size_request (window, gdk_screen_width (), DOCK_SIZE);
-      gtk_window_move (GTK_WINDOW (window), 0, 0);
+      gtk_widget_set_size_request (window, 600, DOCK_SIZE);
+      gtk_window_move (GTK_WINDOW (window), 76, 0);
       set_gtk_window_struts (window, 0, 0, DOCK_SIZE, 0);
       gtk_window_set_title (GTK_WINDOW (window), "TopDock");
       break;
     case DOCK_BOTTOM:
-      gtk_widget_set_size_request (window, gdk_screen_width (), DOCK_SIZE);
-      gtk_window_move (GTK_WINDOW (window), 0, gdk_screen_height () - DOCK_SIZE);
+      gtk_widget_set_size_request (window, 600, DOCK_SIZE);
+      gtk_window_move (GTK_WINDOW (window), 200, gdk_screen_height () - DOCK_SIZE);
       set_gtk_window_struts (window, 0, 0, 0, DOCK_SIZE);
       gtk_window_set_title (GTK_WINDOW (window), "BottomDock");
       break;
