[gnome-screensaver] Properly handle monitor configuration changes



commit 3616731382c69c148054c001c4625f5047a9630f
Author: William Jon McCann <jmccann redhat com>
Date:   Mon Jun 21 14:42:31 2010 -0400

    Properly handle monitor configuration changes
    
    The issue comes down to a few things.
    
     * When a monitor reconfiguration event occurs between the time we spawn a
    dialog process and the time a dialog window is mapped and its window id is
    communicated to the daemon we don't properly cancel the current unlock request.
    
     * The present unlock request cancellation code is not symmetric/consistent
    with the unlock request code.  In other words we aren't properly resetting
    state.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=619773

 src/gs-manager.c    |  163 +++++++++++++++++++++++++++-----------------------
 src/gs-window-x11.c |  122 +++++++++++++++++++++-----------------
 src/gs-window.h     |    1 +
 3 files changed, 157 insertions(+), 129 deletions(-)
---
diff --git a/src/gs-manager.c b/src/gs-manager.c
index aea72f3..34ff403 100644
--- a/src/gs-manager.c
+++ b/src/gs-manager.c
@@ -1069,75 +1069,6 @@ window_deactivated_cb (GSWindow  *window,
         g_idle_add ((GSourceFunc)window_deactivated_idle, manager);
 }
 
-static void
-window_dialog_up_cb (GSWindow  *window,
-                     GSManager *manager)
-{
-        GSList *l;
-
-        g_return_if_fail (manager != NULL);
-        g_return_if_fail (GS_IS_MANAGER (manager));
-
-        gs_debug ("Handling dialog up");
-
-        g_signal_emit (manager, signals [AUTH_REQUEST_BEGIN], 0);
-
-        manager->priv->dialog_up = TRUE;
-        /* Make all other windows insensitive so we don't get events */
-        for (l = manager->priv->windows; l; l = l->next) {
-                if (l->data != window) {
-                        gtk_widget_set_sensitive (GTK_WIDGET (l->data), FALSE);
-                }
-        }
-
-        /* Move keyboard and mouse grabs so dialog can be used */
-        gs_grab_move_to_window (manager->priv->grab,
-                                gs_window_get_gdk_window (window),
-                                gs_window_get_screen (window),
-                                FALSE);
-
-        /* Release the pointer grab while dialog is up so that
-           the dialog can be used.  We'll regrab it when the dialog goes down. */
-        gs_grab_release_mouse (manager->priv->grab);
-
-        if (! manager->priv->throttled) {
-                gs_debug ("Suspending jobs");
-
-                manager_suspend_jobs (manager);
-        }
-}
-
-static void
-window_dialog_down_cb (GSWindow  *window,
-                       GSManager *manager)
-{
-        GSList *l;
-
-        g_return_if_fail (manager != NULL);
-        g_return_if_fail (GS_IS_MANAGER (manager));
-
-        gs_debug ("Handling dialog down");
-
-        /* Regrab the mouse */
-        gs_grab_move_to_window (manager->priv->grab,
-                                gs_window_get_gdk_window (window),
-                                gs_window_get_screen (window),
-                                FALSE);
-
-        /* Make all windows sensitive so we get events */
-        for (l = manager->priv->windows; l; l = l->next) {
-                gtk_widget_set_sensitive (GTK_WIDGET (l->data), TRUE);
-        }
-
-        manager->priv->dialog_up = FALSE;
-
-        if (! manager->priv->throttled) {
-                manager_resume_jobs (manager);
-        }
-
-        g_signal_emit (manager, signals [AUTH_REQUEST_END], 0);
-}
-
 static GSWindow *
 find_window_at_pointer (GSManager *manager)
 {
@@ -1380,6 +1311,91 @@ window_obscured_cb (GSWindow   *window,
         }
 }
 
+static void
+handle_window_dialog_up (GSManager *manager,
+                         GSWindow  *window)
+{
+        GSList *l;
+
+        g_return_if_fail (manager != NULL);
+        g_return_if_fail (GS_IS_MANAGER (manager));
+
+        gs_debug ("Handling dialog up");
+
+        g_signal_emit (manager, signals [AUTH_REQUEST_BEGIN], 0);
+
+        manager->priv->dialog_up = TRUE;
+        /* Make all other windows insensitive so we don't get events */
+        for (l = manager->priv->windows; l; l = l->next) {
+                if (l->data != window) {
+                        gtk_widget_set_sensitive (GTK_WIDGET (l->data), FALSE);
+                }
+        }
+
+        /* Move keyboard and mouse grabs so dialog can be used */
+        gs_grab_move_to_window (manager->priv->grab,
+                                gs_window_get_gdk_window (window),
+                                gs_window_get_screen (window),
+                                FALSE);
+
+        /* Release the pointer grab while dialog is up so that
+           the dialog can be used.  We'll regrab it when the dialog goes down. */
+        gs_grab_release_mouse (manager->priv->grab);
+
+        if (! manager->priv->throttled) {
+                gs_debug ("Suspending jobs");
+
+                manager_suspend_jobs (manager);
+        }
+}
+
+static void
+handle_window_dialog_down (GSManager *manager,
+                           GSWindow  *window)
+{
+        GSList *l;
+
+        g_return_if_fail (manager != NULL);
+        g_return_if_fail (GS_IS_MANAGER (manager));
+
+        gs_debug ("Handling dialog down");
+
+        /* Regrab the mouse */
+        gs_grab_move_to_window (manager->priv->grab,
+                                gs_window_get_gdk_window (window),
+                                gs_window_get_screen (window),
+                                FALSE);
+
+        /* Make all windows sensitive so we get events */
+        for (l = manager->priv->windows; l; l = l->next) {
+                gtk_widget_set_sensitive (GTK_WIDGET (l->data), TRUE);
+        }
+
+        manager->priv->dialog_up = FALSE;
+
+        if (! manager->priv->throttled) {
+                manager_resume_jobs (manager);
+        }
+
+        g_signal_emit (manager, signals [AUTH_REQUEST_END], 0);
+}
+
+static void
+window_dialog_up_changed_cb (GSWindow   *window,
+                             GParamSpec *pspec,
+                             GSManager  *manager)
+{
+        gboolean up;
+
+        up = gs_window_is_dialog_up (window);
+        gs_debug ("Handling window dialog up changed: %s", up ? "up" : "down");
+        if (up) {
+                handle_window_dialog_up (manager, window);
+        } else {
+                handle_window_dialog_down (manager, window);
+        }
+}
+
 static gboolean
 window_activity_cb (GSWindow  *window,
                     GSManager *manager)
@@ -1397,12 +1413,11 @@ disconnect_window_signals (GSManager *manager,
 {
         g_signal_handlers_disconnect_by_func (window, window_deactivated_cb, manager);
         g_signal_handlers_disconnect_by_func (window, window_activity_cb, manager);
-        g_signal_handlers_disconnect_by_func (window, window_dialog_up_cb, manager);
-        g_signal_handlers_disconnect_by_func (window, window_dialog_down_cb, manager);
         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_dialog_up_changed_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);
 }
@@ -1424,10 +1439,6 @@ connect_window_signals (GSManager *manager,
                                  G_CALLBACK (window_activity_cb), manager, 0);
         g_signal_connect_object (window, "deactivated",
                                  G_CALLBACK (window_deactivated_cb), manager, 0);
-        g_signal_connect_object (window, "dialog-up",
-                                 G_CALLBACK (window_dialog_up_cb), manager, 0);
-        g_signal_connect_object (window, "dialog-down",
-                                 G_CALLBACK (window_dialog_down_cb), manager, 0);
         g_signal_connect_object (window, "show",
                                  G_CALLBACK (window_show_cb), manager, G_CONNECT_AFTER);
         g_signal_connect_object (window, "map",
@@ -1436,6 +1447,8 @@ connect_window_signals (GSManager *manager,
                                  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, "notify::dialog-up",
+                                 G_CALLBACK (window_dialog_up_changed_cb), manager, 0);
         g_signal_connect_object (window, "unmap",
                                  G_CALLBACK (window_unmap_cb), manager, G_CONNECT_AFTER);
         g_signal_connect_object (window, "grab_broken_event",
diff --git a/src/gs-window-x11.c b/src/gs-window-x11.c
index 53f59be..4216ea4 100644
--- a/src/gs-window-x11.c
+++ b/src/gs-window-x11.c
@@ -64,6 +64,7 @@ struct GSWindowPrivate
 
         GdkRectangle geometry;
         guint      obscured : 1;
+        guint      dialog_up : 1;
 
         guint      lock_enabled : 1;
         guint      user_switch_enabled : 1;
@@ -118,14 +119,13 @@ struct GSWindowPrivate
 enum {
         ACTIVITY,
         DEACTIVATED,
-        DIALOG_UP,
-        DIALOG_DOWN,
         LAST_SIGNAL
 };
 
 enum {
         PROP_0,
         PROP_OBSCURED,
+        PROP_DIALOG_UP,
         PROP_LOCK_ENABLED,
         PROP_LOGOUT_ENABLED,
         PROP_KEYBOARD_ENABLED,
@@ -1532,6 +1532,43 @@ shake_dialog (GSWindow *window)
         maybe_kill_dialog (window);
 }
 
+static void
+window_set_dialog_up (GSWindow *window,
+                      gboolean  dialog_up)
+{
+        if (window->priv->dialog_up == dialog_up) {
+                return;
+        }
+
+        window->priv->dialog_up = dialog_up;
+        g_object_notify (G_OBJECT (window), "dialog-up");
+}
+
+static void
+popdown_dialog (GSWindow *window)
+{
+        gs_window_dialog_finish (window);
+
+        gtk_widget_show (window->priv->drawing_area);
+
+        gs_window_clear (window);
+        set_invisible_cursor (GTK_WIDGET (window)->window, TRUE);
+
+        window_set_dialog_up (window, FALSE);
+
+        /* reset the pointer positions */
+        window->priv->last_x = -1;
+        window->priv->last_y = -1;
+
+        if (window->priv->lock_box != NULL) {
+                gtk_container_remove (GTK_CONTAINER (window->priv->vbox), GTK_WIDGET (window->priv->lock_box));
+                window->priv->lock_box = NULL;
+        }
+
+        remove_popup_dialog_idle (window);
+        remove_command_watches (window);
+}
+
 static gboolean
 lock_command_watch (GIOChannel   *source,
                     GIOCondition  condition,
@@ -1597,22 +1634,12 @@ lock_command_watch (GIOChannel   *source,
         }
 
         if (finished) {
-                gs_window_dialog_finish (window);
+                popdown_dialog (window);
 
                 if (window->priv->dialog_response == DIALOG_RESPONSE_OK) {
                         add_emit_deactivated_idle (window);
                 }
 
-                gtk_widget_show (window->priv->drawing_area);
-
-                gs_window_clear (window);
-                set_invisible_cursor (GTK_WIDGET (window)->window, TRUE);
-                g_signal_emit (window, signals [DIALOG_DOWN], 0);
-
-                /* reset the pointer positions */
-                window->priv->last_x = -1;
-                window->priv->last_y = -1;
-
                 window->priv->lock_watch_id = 0;
 
                 return FALSE;
@@ -1649,8 +1676,8 @@ is_user_switch_enabled (GSWindow *window)
         return window->priv->user_switch_enabled;
 }
 
-static gboolean
-popup_dialog_idle (GSWindow *window)
+static void
+popup_dialog (GSWindow *window)
 {
         gboolean  result;
         char     *tmp;
@@ -1703,6 +1730,12 @@ popup_dialog_idle (GSWindow *window)
         }
 
         g_string_free (command, TRUE);
+}
+
+static gboolean
+popup_dialog_idle (GSWindow *window)
+{
+        popup_dialog (window);
 
         window->priv->popup_dialog_idle_id = 0;
 
@@ -1735,7 +1768,7 @@ gs_window_request_unlock (GSWindow *window)
                 add_popup_dialog_idle (window);
         }
 
-        g_signal_emit (window, signals [DIALOG_UP], 0);
+        window_set_dialog_up (window, TRUE);
 }
 
 void
@@ -1747,24 +1780,7 @@ gs_window_cancel_unlock_request (GSWindow  *window)
 	 */
         g_return_if_fail (GS_IS_WINDOW (window));
 
-        if (window->priv->lock_socket == NULL) {
-                return;
-        }
-
-        if (window->priv->lock_pid > 0) {
-                gs_window_dialog_finish (window);
-        }
-
-        remove_popup_dialog_idle (window);
-        remove_command_watches (window);
-        remove_watchdog_timer (window);
-
-        if (window->priv->lock_box != NULL) {
-                gtk_container_remove (GTK_CONTAINER (window->priv->vbox), GTK_WIDGET (window->priv->lock_box));
-                window->priv->lock_box = NULL;
-
-                g_signal_emit (window, signals [DIALOG_DOWN], 0);
-        }
+        popdown_dialog (window);
 }
 
 void
@@ -1984,6 +2000,9 @@ gs_window_get_property (GObject    *object,
         case PROP_OBSCURED:
                 g_value_set_boolean (value, self->priv->obscured);
                 break;
+        case PROP_DIALOG_UP:
+                g_value_set_boolean (value, self->priv->dialog_up);
+                break;
         default:
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                 break;
@@ -2182,6 +2201,14 @@ gs_window_is_obscured (GSWindow *window)
         return window->priv->obscured;
 }
 
+gboolean
+gs_window_is_dialog_up (GSWindow *window)
+{
+        g_return_val_if_fail (GS_IS_WINDOW (window), FALSE);
+
+        return window->priv->dialog_up;
+}
+
 static void
 window_set_obscured (GSWindow *window,
                      gboolean  obscured)
@@ -2258,26 +2285,6 @@ gs_window_class_init (GSWindowClass *klass)
                               g_cclosure_marshal_VOID__VOID,
                               G_TYPE_NONE,
                               0);
-        signals [DIALOG_UP] =
-                g_signal_new ("dialog-up",
-                              G_TYPE_FROM_CLASS (object_class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GSWindowClass, dialog_up),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_VOID__VOID,
-                              G_TYPE_NONE,
-                              0);
-        signals [DIALOG_DOWN] =
-                g_signal_new ("dialog-down",
-                              G_TYPE_FROM_CLASS (object_class),
-                              G_SIGNAL_RUN_LAST,
-                              G_STRUCT_OFFSET (GSWindowClass, dialog_down),
-                              NULL,
-                              NULL,
-                              g_cclosure_marshal_VOID__VOID,
-                              G_TYPE_NONE,
-                              0);
 
         g_object_class_install_property (object_class,
                                          PROP_OBSCURED,
@@ -2287,6 +2294,13 @@ gs_window_class_init (GSWindowClass *klass)
                                                                FALSE,
                                                                G_PARAM_READABLE));
         g_object_class_install_property (object_class,
+                                         PROP_DIALOG_UP,
+                                         g_param_spec_boolean ("dialog-up",
+                                                               NULL,
+                                                               NULL,
+                                                               FALSE,
+                                                               G_PARAM_READABLE));
+        g_object_class_install_property (object_class,
                                          PROP_LOCK_ENABLED,
                                          g_param_spec_boolean ("lock-enabled",
                                                                NULL,
diff --git a/src/gs-window.h b/src/gs-window.h
index fc2287e..db76d72 100644
--- a/src/gs-window.h
+++ b/src/gs-window.h
@@ -57,6 +57,7 @@ typedef struct
 GType       gs_window_get_type           (void);
 
 gboolean    gs_window_is_obscured        (GSWindow  *window);
+gboolean    gs_window_is_dialog_up       (GSWindow  *window);
 
 void        gs_window_set_screen         (GSWindow  *window,
                                           GdkScreen *screen);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]