Index: src/screen.c
===================================================================
RCS file: /cvs/gnome/metacity/src/screen.c,v
retrieving revision 1.131
diff -p -u -r1.131 screen.c
--- src/screen.c	17 Oct 2004 04:28:29 -0000	1.131
+++ src/screen.c	19 Oct 2004 04:27:53 -0000
@@ -2182,10 +2182,14 @@ meta_screen_update_showing_desktop_hint 
 static void
 queue_windows_showing (MetaScreen *screen)
 {
-  GList *windows;
-  GList *tmp;
+  GSList *windows;
+  GSList *tmp;
 
-  windows = screen->active_workspace->windows;
+  /* Must operate on all windows on display instead of just on the
+   * active_workspace's window list, because the active_workspace's
+   * window list may not contain the on_all_workspace windows.
+   */
+  windows = meta_display_list_windows (screen->display);
 
   tmp = windows;
   while (tmp != NULL)
@@ -2197,6 +2201,8 @@ queue_windows_showing (MetaScreen *scree
       
       tmp = tmp->next;
     }
+
+  g_slist_free (windows);
 }
 
 void
Index: src/window.c
===================================================================
RCS file: /cvs/gnome/metacity/src/window.c,v
retrieving revision 1.350
diff -p -u -r1.350 window.c
--- src/window.c	17 Oct 2004 04:28:29 -0000	1.350
+++ src/window.c	19 Oct 2004 04:27:55 -0000
@@ -102,6 +102,9 @@ static void     ensure_mru_position_afte
 
 void meta_window_move_resize_now (MetaWindow  *window);
 
+static gboolean window_showing_on_its_workspace (MetaWindow *window);
+static gboolean window_should_be_showing  (MetaWindow  *window);
+
 /* FIXME we need an abstraction that covers all these queues. */   
 
 void meta_window_unqueue_calc_showing (MetaWindow *window);
@@ -1161,7 +1164,7 @@ set_net_wm_state (MetaWindow *window)
       data[i] = window->display->atom_net_wm_state_fullscreen;
       ++i;
     }
-  if (window->shaded || window->minimized)
+  if (!window_showing_on_its_workspace (window))
     {
       data[i] = window->display->atom_net_wm_state_hidden;
       ++i;
@@ -1227,37 +1230,19 @@ ancestor_is_minimized (MetaWindow *windo
 }
 
 static gboolean
-window_should_be_showing (MetaWindow  *window)
+window_showing_on_its_workspace (MetaWindow *window)
 {
-  gboolean showing, on_workspace;
+  gboolean showing;
   gboolean is_desktop_or_dock;
+  MetaWorkspace* workspace_of_window;
 
-  meta_verbose ("Should be showing for window %s\n", window->desc);
-
-  /* 1. See if we're on the workspace */
-  
-  on_workspace = meta_window_visible_on_workspace (window, 
-                                                   window->screen->active_workspace);
-
-  showing = on_workspace;
-  
-  if (!on_workspace)
-    meta_verbose ("Window %s is not on workspace %d\n",
-                  window->desc,
-                  meta_workspace_index (window->screen->active_workspace));
-  else
-    meta_verbose ("Window %s is on the active workspace %d\n",
-                  window->desc,
-                  meta_workspace_index (window->screen->active_workspace));
-
-  if (window->on_all_workspaces)
-    meta_verbose ("Window %s is on all workspaces\n", window->desc);
+  showing = TRUE;
 
-  /* 2. See if we're minimized */
+  /* 1. See if we're minimized */
   if (window->minimized)
     showing = FALSE;
   
-  /* 3. See if we're in "show desktop" mode */
+  /* 2. See if we're in "show desktop" mode */
   is_desktop_or_dock = FALSE;
   is_desktop_or_dock_foreach (window,
                               &is_desktop_or_dock);
@@ -1265,16 +1250,34 @@ window_should_be_showing (MetaWindow  *w
   meta_window_foreach_ancestor (window, is_desktop_or_dock_foreach,
                                 &is_desktop_or_dock);
 
+  if (window->on_all_workspaces)
+    /* Unless the behavior in bug 87531 is implemented, or else
+     * _NET_WM_STATE_HIDDEN can be made per-workspace instead of
+     * global, or else we get rid of on_all_workspaces windows
+     * altogether, then this will be just a hack that only sort of
+     * works.
+     */
+    workspace_of_window = window->screen->active_workspace;
+  else if (window->workspaces)
+    /* This is sort of hacky too; would like to guarantee that
+     * window->workspaces only contains a single workspace.  I believe
+     * that's currently true in Metacity, but it isn't guaranteed to
+     * remain true in the future.
+     */
+    workspace_of_window = window->workspaces->data;
+  else /* This only seems to be needed for startup */
+    workspace_of_window = NULL;
+
   if (showing &&      
-      window->screen->active_workspace->showing_desktop &&
+      workspace_of_window && workspace_of_window->showing_desktop &&
       !is_desktop_or_dock)
     {
-      meta_verbose ("Window %s is on current workspace, but we're showing the desktop\n",
+      meta_verbose ("We're showing the desktop on the workspace(s) that window %s is on\n",
                     window->desc);
       showing = FALSE;
     }
 
-  /* 4. See if an ancestor is minimized (note that
+  /* 3. See if an ancestor is minimized (note that
    *    ancestor's "mapped" field may not be up to date
    *    since it's being computed in this same idle queue)
    */
@@ -1286,14 +1289,40 @@ window_should_be_showing (MetaWindow  *w
     }
 
 #if 0
-  /* 5. See if we're drawing wireframe
+  /* 4. See if we're drawing wireframe
    */
   if (window->display->grab_window == window &&
       window->display->grab_wireframe_active)    
     showing = FALSE;
 #endif
-  
+
   return showing;
+}
+
+static gboolean
+window_should_be_showing (MetaWindow  *window)
+{
+  gboolean on_workspace;
+
+  meta_verbose ("Should be showing for window %s\n", window->desc);
+
+  /* See if we're on the workspace */
+  on_workspace = meta_window_visible_on_workspace (window, 
+                                                   window->screen->active_workspace);
+
+  if (!on_workspace)
+    meta_verbose ("Window %s is not on workspace %d\n",
+                  window->desc,
+                  meta_workspace_index (window->screen->active_workspace));
+  else
+    meta_verbose ("Window %s is on the active workspace %d\n",
+                  window->desc,
+                  meta_workspace_index (window->screen->active_workspace));
+
+  if (window->on_all_workspaces)
+    meta_verbose ("Window %s is on all workspaces\n", window->desc);
+
+  return on_workspace && window_showing_on_its_workspace (window);
 }
 
 static void
