Index: src/gs-job.c
===================================================================
RCS file: /cvs/gnome/gnome-screensaver/src/gs-job.c,v
retrieving revision 1.37
diff -p -u -r1.37 gs-job.c
--- src/gs-job.c	13 Feb 2006 20:56:52 -0000	1.37
+++ src/gs-job.c	11 Jul 2006 21:28:49 -0000
@@ -1,6 +1,6 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
  *
- * Copyright (C) 2004-2005 William Jon McCann <mccann@jhu.edu>
+ * Copyright (C) 2004-2006 William Jon McCann <mccann@jhu.edu>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -430,7 +430,8 @@ gs_job_died (GSJob *job)
 {
         if (job->priv->pid > 0) {
                 int exit_status;
-                        
+
+                gs_debug ("Waiting on process %d", job->priv->pid);
                 exit_status = wait_on_child (job->priv->pid);
 
                 job->priv->status = GS_JOB_DEAD;
@@ -443,6 +444,8 @@ gs_job_died (GSJob *job)
 
         g_spawn_close_pid (job->priv->pid);
         job->priv->pid = 0;
+
+        gs_debug ("Job died");
 }
 
 static void
@@ -751,6 +754,8 @@ gs_job_start (GSJob *job)
         g_return_val_if_fail (job != NULL, FALSE);
         g_return_val_if_fail (GS_IS_JOB (job), FALSE);
 
+        gs_debug ("starting job");
+
         if (job->priv->pid) {
                 g_warning ("Cannot restart active job.");
                 return FALSE;
@@ -805,6 +810,8 @@ gs_job_stop (GSJob *job)
         g_return_val_if_fail (job != NULL, FALSE);
         g_return_val_if_fail (GS_IS_JOB (job), FALSE);
 
+        gs_debug ("stopping job");
+
         if (! job->priv->pid) {
                 return FALSE;
         }
@@ -830,6 +837,8 @@ gs_job_suspend (GSJob   *job,
 {
         g_return_val_if_fail (job != NULL, FALSE);
         g_return_val_if_fail (GS_IS_JOB (job), FALSE);
+
+        gs_debug ("suspending job");
 
         if (! job->priv->pid) {
                 return FALSE;
Index: src/gs-manager.c
===================================================================
RCS file: /cvs/gnome/gnome-screensaver/src/gs-manager.c,v
retrieving revision 1.41.2.6
diff -p -u -r1.41.2.6 gs-manager.c
--- src/gs-manager.c	2 Jun 2006 00:17:10 -0000	1.41.2.6
+++ src/gs-manager.c	11 Jul 2006 21:28:49 -0000
@@ -138,6 +138,65 @@ select_theme (GSManager *manager)
         return theme;
 }
 
+
+static GSJob *
+lookup_job_for_window (GSManager *manager,
+                       GSWindow  *window)
+{
+        GSJob *job;
+
+        if (manager->priv->jobs == NULL) {
+                return NULL;
+        }
+
+        job = g_hash_table_lookup (manager->priv->jobs, window);
+
+        return job;
+}
+
+static void
+manager_maybe_stop_job_for_window (GSManager *manager,
+                                   GSWindow  *window)
+{
+        GSJob *job;
+
+        job = lookup_job_for_window (manager, window);
+
+        if (job == NULL) {
+                gs_debug ("Job not found for window");
+                return;
+        }
+
+        gs_job_stop (job);
+}
+
+static void
+manager_maybe_start_job_for_window (GSManager *manager,
+                                    GSWindow  *window)
+{
+        GSJob *job;
+
+        job = lookup_job_for_window (manager, window);
+
+        if (job == NULL) {
+                gs_debug ("Job not found for window");
+                return;
+        }
+
+        if (! manager->priv->dialog_up) {
+                if (! manager->priv->throttle_enabled) {
+                        if (! gs_job_is_running (job)) {
+                                if (! gs_window_is_obscured (window)) {
+                                        gs_debug ("Starting job for window");
+                                        gs_job_start (job);
+                                } else {
+                                        gs_debug ("Window is obscured deferring start of job");
+                                }
+                        }
+                }
+        }
+}
+
 static void
 cycle_job (GSWindow  *window,
            GSJob     *job,
@@ -149,7 +208,7 @@ cycle_job (GSWindow  *window,
 
         gs_job_stop (job);
         gs_job_set_theme (job, theme, NULL);
-        gs_job_start (job);
+        manager_maybe_start_job_for_window (manager, window);
 }
 
 static void
@@ -168,7 +227,7 @@ throttle_job (GSWindow  *window,
         if (manager->priv->throttle_enabled) {
                 gs_job_stop (job);
         } else {
-                gs_job_start (job);
+                manager_maybe_start_job_for_window (manager, window);
         }
 }
 
@@ -188,7 +247,7 @@ resume_job (GSWindow  *window,
         if (gs_job_is_running (job)) {
                 gs_job_suspend (job, FALSE);
         } else {
-                gs_job_start (job);
+                manager_maybe_start_job_for_window (manager, window);
         }
 }
 
@@ -444,6 +503,8 @@ gs_manager_cycle (GSManager *manager)
         g_return_val_if_fail (manager != NULL, FALSE);
         g_return_val_if_fail (GS_IS_MANAGER (manager), FALSE);
 
+        gs_debug ("cycling jobs");
+
         if (! manager->priv->active) {
                 return FALSE;
         }
@@ -846,33 +907,6 @@ window_dialog_down_cb (GSWindow  *window
         manager->priv->dialog_up = FALSE;
 }
 
-static void
-manager_maybe_start_job_for_window (GSManager *manager,
-                                    GSWindow  *window)
-{
-        GSJob *job;
-
-        if (manager->priv->jobs == NULL) {
-                return;
-        }
-
-        job = g_hash_table_lookup (manager->priv->jobs, window);
-
-        if (job == NULL) {
-                gs_debug ("Job not found for window");
-                return;
-        }
-
-        if (! manager->priv->dialog_up) {
-                if (! manager->priv->throttle_enabled) {
-                        if (! gs_job_is_running (job)) {
-                                gs_debug ("Starting job for window");
-                                gs_job_start (job);
-                        }
-                }
-        }
-}
-
 static gboolean
 manager_maybe_grab_window (GSManager *manager,
                            GSWindow  *window)
@@ -1014,6 +1048,35 @@ window_show_cb (GSWindow  *window,
 }
 
 static void
+maybe_set_window_throttle (GSManager *manager,
+                           GSWindow  *window,
+                           gboolean   throttled)
+{
+        if (throttled) {
+                manager_maybe_stop_job_for_window (manager, window);
+        } else {
+                manager_maybe_start_job_for_window (manager, window);
+        }
+}
+
+static void
+window_obscured_cb (GSWindow   *window,
+                    GParamSpec *pspec,
+                    GSManager  *manager)
+{
+        gboolean obscured;
+
+        obscured = gs_window_is_obscured (window);
+        gs_debug ("Handling window obscured: %s", obscured ? "obscured" : "unobscured");
+
+        maybe_set_window_throttle (manager, window, obscured);
+
+        if (! obscured) {
+                gs_manager_request_unlock (manager);
+        }
+}
+
+static void
 disconnect_window_signals (GSManager *manager,
                            GSWindow  *window)
 {
@@ -1023,6 +1086,7 @@ disconnect_window_signals (GSManager *ma
         g_signal_handlers_disconnect_by_func (window, window_show_cb, manager);
         g_signal_handlers_disconnect_by_func (window, window_map_cb, manager);
         g_signal_handlers_disconnect_by_func (window, window_map_event_cb, manager);
+        g_signal_handlers_disconnect_by_func (window, window_obscured_cb, manager);
         g_signal_handlers_disconnect_by_func (window, window_unmap_cb, manager);
         g_signal_handlers_disconnect_by_func (window, window_grab_broken_cb, manager);
 }
@@ -1052,6 +1116,8 @@ connect_window_signals (GSManager *manag
                                  G_CALLBACK (window_map_cb), manager, G_CONNECT_AFTER);
         g_signal_connect_object (window, "map_event",
                                  G_CALLBACK (window_map_event_cb), manager, G_CONNECT_AFTER);
+        g_signal_connect_object (window, "notify::obscured",
+                                 G_CALLBACK (window_obscured_cb), manager, G_CONNECT_AFTER);
         g_signal_connect_object (window, "unmap",
                                  G_CALLBACK (window_unmap_cb), manager, G_CONNECT_AFTER);
         g_signal_connect_object (window, "grab_broken_event",
@@ -1280,6 +1346,11 @@ gs_manager_request_unlock (GSManager *ma
 
         if (! manager->priv->active) {
                 gs_debug ("Request unlock but manager is not active");
+                return;
+        }
+
+        if (manager->priv->dialog_up) {
+                gs_debug ("Request unlock but dialog is already up");
                 return;
         }
 
Index: src/gs-window-x11.c
===================================================================
RCS file: /cvs/gnome/gnome-screensaver/src/gs-window-x11.c,v
retrieving revision 1.50.2.4
diff -p -u -r1.50.2.4 gs-window-x11.c
--- src/gs-window-x11.c	17 Jun 2006 01:42:38 -0000	1.50.2.4
+++ src/gs-window-x11.c	11 Jul 2006 21:28:49 -0000
@@ -54,6 +54,7 @@ struct GSWindowPrivate
         int        monitor;
 
         GdkRectangle geometry;
+        guint      obscured : 1;
 
         guint      lock_enabled : 1;
         guint      user_switch_enabled : 1;
@@ -94,6 +95,7 @@ enum {
 
 enum {
         PROP_0,
+        PROP_OBSCURED,
         PROP_LOCK_ENABLED,
         PROP_LOGOUT_ENABLED,
         PROP_LOGOUT_COMMAND,
@@ -1212,6 +1214,9 @@ gs_window_get_property (GObject    *obje
         case PROP_MONITOR:
                 g_value_set_int (value, self->priv->monitor);
                 break;
+        case PROP_OBSCURED:
+                g_value_set_boolean (value, self->priv->obscured);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -1407,6 +1412,46 @@ gs_window_real_grab_broken (GtkWidget   
         return FALSE;
 }
 
+gboolean
+gs_window_is_obscured (GSWindow *window)
+{
+        g_return_val_if_fail (GS_IS_WINDOW (window), FALSE);
+
+        return window->priv->obscured;
+}
+
+static void
+window_set_obscured (GSWindow *window,
+                     gboolean  obscured)
+{
+        if (window->priv->obscured == obscured) {
+                return;
+        }
+
+        window->priv->obscured = obscured;
+        g_object_notify (G_OBJECT (window), "obscured");
+}
+
+static gboolean
+gs_window_real_visibility_notify_event (GtkWidget          *widget,
+                                        GdkEventVisibility *event)
+{
+        switch (event->state) {
+        case GDK_VISIBILITY_FULLY_OBSCURED:
+                window_set_obscured (GS_WINDOW (widget), TRUE);
+                break;
+        case GDK_VISIBILITY_PARTIAL:
+                break;
+        case GDK_VISIBILITY_UNOBSCURED:
+                window_set_obscured (GS_WINDOW (widget), FALSE);
+                break;
+        default:
+                break;
+        }
+
+        return FALSE;
+}
+
 static void
 gs_window_class_init (GSWindowClass *klass)
 {
@@ -1429,6 +1474,7 @@ gs_window_class_init (GSWindowClass *kla
         widget_class->scroll_event        = gs_window_real_scroll_event;
         widget_class->size_request        = gs_window_real_size_request;
         widget_class->grab_broken_event   = gs_window_real_grab_broken;
+        widget_class->visibility_notify_event = gs_window_real_visibility_notify_event;
 
         g_type_class_add_private (klass, sizeof (GSWindowPrivate));
 
@@ -1464,6 +1510,13 @@ gs_window_class_init (GSWindowClass *kla
                               0);
 
         g_object_class_install_property (object_class,
+                                         PROP_OBSCURED,
+                                         g_param_spec_boolean ("obscured",
+                                                               NULL,
+                                                               NULL,
+                                                               FALSE,
+                                                               G_PARAM_READABLE));
+        g_object_class_install_property (object_class,
                                          PROP_LOCK_ENABLED,
                                          g_param_spec_boolean ("lock-enabled",
                                                                NULL,
@@ -1536,6 +1589,7 @@ gs_window_init (GSWindow *window)
                                | GDK_KEY_PRESS_MASK
                                | GDK_KEY_RELEASE_MASK
                                | GDK_EXPOSURE_MASK
+                               | GDK_VISIBILITY_NOTIFY_MASK
                                | GDK_ENTER_NOTIFY_MASK
                                | GDK_LEAVE_NOTIFY_MASK);
         force_no_pixmap_background (GTK_WIDGET (window));
Index: src/gs-window.h
===================================================================
RCS file: /cvs/gnome/gnome-screensaver/src/gs-window.h,v
retrieving revision 1.9
diff -p -u -r1.9 gs-window.h
--- src/gs-window.h	26 Oct 2005 20:54:41 -0000	1.9
+++ src/gs-window.h	11 Jul 2006 21:28:49 -0000
@@ -55,6 +55,8 @@ typedef struct
 
 GType       gs_window_get_type           (void);
 
+gboolean    gs_window_is_obscured        (GSWindow  *window);
+
 void        gs_window_set_screen         (GSWindow  *window,
                                           GdkScreen *screen);
 GdkScreen * gs_window_get_screen         (GSWindow  *window);
