benzea / rpms / gdm

Forked from rpms/gdm 4 years ago
Clone
Blob Blame History Raw
From 8f3588dcf2f1d7b5907c77bdf3d407e074f65b14 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 27 Aug 2010 17:57:18 -0400
Subject: [PATCH 1/7] Emit changed signal whenever we do a GetAll call

Previously we'd emit it after update_info, but at
that point no properties have been changed yet,
so its getting emitted prematurely.
---
 gui/simple-greeter/gdm-user.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c
index 037b7e7..de46329 100644
--- a/gui/simple-greeter/gdm-user.c
+++ b/gui/simple-greeter/gdm-user.c
@@ -877,6 +877,8 @@ on_get_all_finished (DBusGProxy     *proxy,
         g_hash_table_foreach (hash_table, (GHFunc) collect_props, user);
         g_hash_table_unref (hash_table);
 
+        g_signal_emit (user, signals[CHANGED], 0);
+
 out:
         g_object_unref (proxy);
 }
@@ -925,9 +927,7 @@ changed_handler (DBusGProxy *proxy,
 {
         GdmUser *user = GDM_USER (data);
 
-        if (update_info (user)) {
-                g_signal_emit (user, signals[CHANGED], 0);
-        }
+        update_info (user);
 }
 
 GdmUser *
-- 
1.7.2.2


From b02dd2f7a684e36de84dfec778d6c4e39836efde Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 30 Aug 2010 13:49:58 -0400
Subject: [PATCH 2/7] Add new 'is-loaded' property to user object

Since the user objects are loaded asynchronously,
there is a timeframe where they are incomplete.

This commit adds an "is-loaded" property to
GdmUser to mark when the user is fully loaded.
---
 gui/simple-greeter/gdm-user-manager.c |   40 +++++++++++++---
 gui/simple-greeter/gdm-user.c         |   78 +++++++++++++++++++++++++++++++++
 gui/simple-greeter/gdm-user.h         |    1 +
 3 files changed, 111 insertions(+), 8 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 40707b9..01117e2 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -758,27 +758,51 @@ remove_user (GdmUserManager *manager,
 }
 
 static void
-on_new_user_changed (GdmUser        *user,
-                     GdmUserManager *manager)
+on_new_user_loaded (GdmUser        *user,
+                    GParamSpec     *pspec,
+                    GdmUserManager *manager)
 {
         const char *username;
 
-        username = gdm_user_get_user_name (user);
-
-        if (username == NULL) {
+        if (!gdm_user_is_loaded (user)) {
                 return;
         }
 
-        g_signal_handlers_disconnect_by_func (user, on_new_user_changed, manager);
+        g_signal_handlers_disconnect_by_func (user, on_new_user_loaded, manager);
         manager->priv->new_users = g_slist_remove (manager->priv->new_users,
                                                    user);
 
+        username = gdm_user_get_user_name (user);
+
+        if (username == NULL) {
+                const char *object_path;
+
+                object_path = gdm_user_get_object_path (user);
+
+                if (object_path != NULL) {
+                        g_warning ("GdmUserManager: user has no username "
+                                   "(object path: %s, uid: %lu)",
+                                   object_path, gdm_user_get_uid (user));
+                } else {
+                        g_warning ("GdmUserManager: user has no username (uid: %lu)",
+                                   gdm_user_get_uid (user));
+                }
+                g_object_unref (user);
+                return;
+        }
+
         if (username_in_exclude_list (manager, username)) {
                 g_debug ("GdmUserManager: excluding user '%s'", username);
                 g_object_unref (user);
                 return;
         }
 
+        /* User added already through alternative, but less authoratative means.
+         */
+        if (g_hash_table_lookup (manager->priv->users_by_name, username) != NULL) {
+                g_hash_table_remove (manager->priv->users_by_name, username);
+        }
+
         add_user (manager, user);
         g_object_unref (user);
 }
@@ -800,7 +824,7 @@ add_new_user_for_object_path (const char     *object_path,
 
         manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user);
 
-        g_signal_connect (user, "changed", G_CALLBACK (on_new_user_changed), manager);
+        g_signal_connect (user, "notify::is-loaded", G_CALLBACK (on_new_user_loaded), manager);
 }
 
 static void
@@ -2734,7 +2758,7 @@ gdm_user_manager_finalize (GObject *object)
                 user = GDM_USER (node->data);
                 next_node = node->next;
 
-                g_signal_handlers_disconnect_by_func (user, on_new_user_changed, manager);
+                g_signal_handlers_disconnect_by_func (user, on_new_user_loaded, manager);
                 g_object_unref (user);
                 manager->priv->new_users = g_slist_delete_link (manager->priv->new_users, node);
                 node = next_node;
diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c
index de46329..25951ba 100644
--- a/gui/simple-greeter/gdm-user.c
+++ b/gui/simple-greeter/gdm-user.c
@@ -46,6 +46,11 @@
 #define USER_ACCOUNTS_INTERFACE "org.freedesktop.Accounts.User"
 
 enum {
+        PROP_0,
+        PROP_IS_LOADED
+};
+
+enum {
         CHANGED,
         SESSIONS_CHANGED,
         LAST_SIGNAL
@@ -66,6 +71,8 @@ struct _GdmUser {
         char           *icon_file;
         GList          *sessions;
         gulong          login_frequency;
+
+        guint           is_loaded : 1;
 };
 
 typedef struct _GdmUserClass
@@ -139,6 +146,43 @@ gdm_user_get_num_sessions (GdmUser    *user)
 }
 
 static void
+gdm_user_set_property (GObject        *object,
+                       guint           prop_id,
+                       const GValue   *value,
+                       GParamSpec     *pspec)
+{
+        GdmUser *user;
+
+        user = GDM_USER (object);
+
+        switch (prop_id) {
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
+gdm_user_get_property (GObject        *object,
+                       guint           prop_id,
+                       GValue         *value,
+                       GParamSpec     *pspec)
+{
+        GdmUser *user;
+
+        user = GDM_USER (object);
+
+        switch (prop_id) {
+        case PROP_IS_LOADED:
+                g_value_set_boolean (value, user->is_loaded);
+                break;
+        default:
+                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                break;
+        }
+}
+
+static void
 gdm_user_class_init (GdmUserClass *class)
 {
         GObjectClass *gobject_class;
@@ -146,6 +190,16 @@ gdm_user_class_init (GdmUserClass *class)
         gobject_class = G_OBJECT_CLASS (class);
 
         gobject_class->finalize = gdm_user_finalize;
+        gobject_class->set_property = gdm_user_set_property;
+        gobject_class->get_property = gdm_user_get_property;
+
+        g_object_class_install_property (gobject_class,
+                                         PROP_IS_LOADED,
+                                         g_param_spec_boolean ("is-loaded",
+                                                               NULL,
+                                                               NULL,
+                                                               FALSE,
+                                                               G_PARAM_READABLE));
 
         signals [CHANGED] =
                 g_signal_new ("changed",
@@ -209,6 +263,16 @@ gdm_user_finalize (GObject *object)
                 (*G_OBJECT_CLASS (gdm_user_parent_class)->finalize) (object);
 }
 
+static void
+set_is_loaded (GdmUser  *user,
+               gboolean  is_loaded)
+{
+        if (user->is_loaded != is_loaded) {
+                user->is_loaded = is_loaded;
+                g_object_notify (G_OBJECT (user), "is-loaded");
+        }
+}
+
 /**
  * _gdm_user_update_from_pwent:
  * @user: the user object to update.
@@ -297,6 +361,10 @@ _gdm_user_update_from_pwent (GdmUser             *user,
                 changed = TRUE;
         }
 
+        if (!user->is_loaded) {
+                set_is_loaded (user, TRUE);
+        }
+
         if (changed) {
                 g_signal_emit (user, signals[CHANGED], 0);
         }
@@ -877,6 +945,10 @@ on_get_all_finished (DBusGProxy     *proxy,
         g_hash_table_foreach (hash_table, (GHFunc) collect_props, user);
         g_hash_table_unref (hash_table);
 
+        if (!user->is_loaded) {
+                set_is_loaded (user, TRUE);
+        }
+
         g_signal_emit (user, signals[CHANGED], 0);
 
 out:
@@ -958,3 +1030,9 @@ gdm_user_new_from_object_path (const gchar *object_path)
         g_object_unref (user);
         return NULL;
 }
+
+gboolean
+gdm_user_is_loaded (GdmUser *user)
+{
+        return user->is_loaded;
+}
diff --git a/gui/simple-greeter/gdm-user.h b/gui/simple-greeter/gdm-user.h
index 2aee30a..4d6ced8 100644
--- a/gui/simple-greeter/gdm-user.h
+++ b/gui/simple-greeter/gdm-user.h
@@ -56,6 +56,7 @@ GdkPixbuf            *gdm_user_render_icon         (GdmUser   *user,
 
 gint                  gdm_user_collate             (GdmUser   *user1,
                                                     GdmUser   *user2);
+gboolean              gdm_user_is_loaded           (GdmUser *user);
 
 G_END_DECLS
 
-- 
1.7.2.2


From 658303e84af31a3b3d4cf2e6159dd2bb059881ed Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 30 Aug 2010 14:38:06 -0400
Subject: [PATCH 3/7] If a user added early, drop it from list

Since we support getting users from multiple sources,
we may end up with the same user getting added to the list
twice.  The accounts-service is the authoratative source,
so if another source adds a user first then "undo" that user.
---
 gui/simple-greeter/gdm-user-manager.c |   16 +++++++++++-----
 1 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 01117e2..1407458 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -197,6 +197,7 @@ static void     queue_load_seat_and_users   (GdmUserManager *manager);
 static void     monitor_local_users         (GdmUserManager *manager);
 
 static void     load_new_session_incrementally (GdmUserManagerNewSession *new_session);
+static void     set_is_loaded (GdmUserManager *manager, gboolean is_loaded);
 
 static gpointer user_manager_object = NULL;
 
@@ -763,6 +764,7 @@ on_new_user_loaded (GdmUser        *user,
                     GdmUserManager *manager)
 {
         const char *username;
+        GdmUser *old_user;
 
         if (!gdm_user_is_loaded (user)) {
                 return;
@@ -797,14 +799,20 @@ on_new_user_loaded (GdmUser        *user,
                 return;
         }
 
-        /* User added already through alternative, but less authoratative means.
+        old_user = g_hash_table_lookup (manager->priv->users_by_name, username);
+
+        /* If username got added earlier by a different means, trump it now.
          */
-        if (g_hash_table_lookup (manager->priv->users_by_name, username) != NULL) {
-                g_hash_table_remove (manager->priv->users_by_name, username);
+        if (old_user != NULL) {
+                remove_user (manager, old_user);
         }
 
         add_user (manager, user);
         g_object_unref (user);
+
+        if (manager->priv->new_users == NULL) {
+                set_is_loaded (manager, TRUE);
+        }
 }
 
 static void
@@ -1137,8 +1145,6 @@ on_list_cached_users_finished (DBusGProxy     *proxy,
                         }
                 }
         }
-
-        set_is_loaded (manager, TRUE);
 }
 
 static void
-- 
1.7.2.2


From 395854d36caa3e10699c512d4227b6bcdad572fa Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 30 Aug 2010 14:55:35 -0400
Subject: [PATCH 4/7] Don't mark list as loaded until accounts service chimes in

---
 gui/simple-greeter/gdm-user-manager.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 1407458..4ff850e 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -163,6 +163,7 @@ struct GdmUserManagerPrivate
 
         gboolean               is_loaded;
         gboolean               has_multiple_users;
+        gboolean               listing_cached_users;
 };
 
 enum {
@@ -854,6 +855,7 @@ on_user_removed_in_accounts_service (DBusGProxy *proxy,
         GdmUser        *user;
 
         user = g_hash_table_lookup (manager->priv->users_by_object_path, object_path);
+
         remove_user (manager, user);
 }
 
@@ -1106,6 +1108,7 @@ on_list_cached_users_finished (DBusGProxy     *proxy,
         GError *error = NULL;
         GPtrArray *paths;
 
+        manager->priv->listing_cached_users = FALSE;
         if (!dbus_g_proxy_end_call (proxy,
                                     call_id,
                                     &error,
@@ -1748,6 +1751,10 @@ maybe_set_is_loaded (GdmUserManager *manager)
                 return;
         }
 
+        if (manager->priv->listing_cached_users) {
+                return;
+        }
+
         /* Don't set is_loaded yet unless the seat is already loaded
          * or failed to load.
          */
@@ -2364,6 +2371,7 @@ load_users (GdmUserManager *manager)
                                  manager,
                                  NULL,
                                  G_TYPE_INVALID);
+        manager->priv->listing_cached_users = TRUE;
 }
 
 static void
-- 
1.7.2.2


From 91f8593e5d259f7e6b32f1afa29fa49dffa5f21a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 31 Aug 2010 14:07:46 -0400
Subject: [PATCH 5/7] Don't emit 'user-removed' if list isn't loaded

We don't want to emit add or removed signals before
loading.
---
 gui/simple-greeter/gdm-user-manager.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 4ff850e..ddb6070 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -750,7 +750,10 @@ remove_user (GdmUserManager *manager,
                 g_hash_table_remove (manager->priv->users_by_object_path, gdm_user_get_object_path (user));
         }
         g_hash_table_remove (manager->priv->users_by_name, gdm_user_get_user_name (user));
-        g_signal_emit (manager, signals[USER_REMOVED], 0, user);
+
+        if (manager->priv->is_loaded) {
+                g_signal_emit (manager, signals[USER_REMOVED], 0, user);
+        }
 
         g_object_unref (user);
 
-- 
1.7.2.2


From ea8538cac4c6f48bffe8a4cbf67ca2fb317838a5 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 31 Aug 2010 14:03:01 -0400
Subject: [PATCH 6/7] Remove user from new-users list if removed from accounts service

---
 gui/simple-greeter/gdm-user-manager.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index ddb6070..138fbb6 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -859,6 +859,8 @@ on_user_removed_in_accounts_service (DBusGProxy *proxy,
 
         user = g_hash_table_lookup (manager->priv->users_by_object_path, object_path);
 
+        manager->priv->new_users = g_slist_remove (manager->priv->new_users, user);
+
         remove_user (manager, user);
 }
 
-- 
1.7.2.2


From 0df669070bfa550af9830deb0c17273529743970 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 31 Aug 2010 13:36:20 -0400
Subject: [PATCH 7/7] Fire off loading user images after chooser is mapped

The update_visible_items function calls gtk_tree_view_get_visible_range
which seems to only work after the tree view is mapped.

This commit makes sure that we queue an update after the widget is
mapped.

(seems to a fix a problem where users face icons don't always show up)
---
 gui/simple-greeter/gdm-chooser-widget.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/gui/simple-greeter/gdm-chooser-widget.c b/gui/simple-greeter/gdm-chooser-widget.c
index 9e3ae73..043928d 100644
--- a/gui/simple-greeter/gdm-chooser-widget.c
+++ b/gui/simple-greeter/gdm-chooser-widget.c
@@ -1362,6 +1362,14 @@ gdm_chooser_widget_show (GtkWidget *widget)
 }
 
 static void
+gdm_chooser_widget_map (GtkWidget *widget)
+{
+        queue_update_visible_items (GDM_CHOOSER_WIDGET (widget));
+
+        GTK_WIDGET_CLASS (gdm_chooser_widget_parent_class)->map (widget);
+}
+
+static void
 gdm_chooser_widget_size_allocate (GtkWidget     *widget,
                                   GtkAllocation *allocation)
 {
@@ -1420,6 +1428,7 @@ gdm_chooser_widget_class_init (GdmChooserWidgetClass *klass)
         widget_class->size_allocate = gdm_chooser_widget_size_allocate;
         widget_class->hide = gdm_chooser_widget_hide;
         widget_class->show = gdm_chooser_widget_show;
+        widget_class->map = gdm_chooser_widget_map;
         widget_class->focus = gdm_chooser_widget_focus;
         widget_class->focus_in_event = gdm_chooser_widget_focus_in_event;
 
-- 
1.7.2.2

From 97b693497806e5436d832ba3a66c6810546d6478 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Sep 2010 17:04:51 -0400
Subject: [PATCH 1/3] Fix gdm_user_manager_get_user

Before it was assuming that as soon as a user was added, it would be
in the hash table of loaded users. That's no longer true, now that
the user is loaded asynchronously.
---
 gui/simple-greeter/gdm-user-manager.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 138fbb6..4382481 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -819,24 +819,27 @@ on_new_user_loaded (GdmUser        *user,
         }
 }
 
-static void
+static GdmUser *
 add_new_user_for_object_path (const char     *object_path,
                               GdmUserManager *manager)
 {
         GdmUser *user;
 
-        if (g_hash_table_lookup (manager->priv->users_by_object_path, object_path)) {
-                return;
+        user = g_hash_table_lookup (manager->priv->users_by_object_path, object_path); 
+
+        if (user != NULL) {
+                return user;
         }
         user = gdm_user_new_from_object_path (object_path);
 
         if (user == NULL) {
-                return;
+                return NULL;
         }
 
         manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user);
 
         g_signal_connect (user, "notify::is-loaded", G_CALLBACK (on_new_user_loaded), manager);
+        return user;
 }
 
 static void
@@ -1563,9 +1566,8 @@ gdm_user_manager_get_user (GdmUserManager *manager,
                         object_path = get_user_object_path_from_accounts_service (manager, username);
 
                         if (object_path != NULL) {
-                                add_new_user_for_object_path (object_path, manager);
+                                user = add_new_user_for_object_path (object_path, manager);
                                 g_free (object_path);
-                                user = g_hash_table_lookup (manager->priv->users_by_name, username);
                         }
                 } else {
                         struct passwd *pwent;
-- 
1.7.2.2


From eec3d265a53167f411eec9769851bebfabee3d1b Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Sep 2010 17:06:33 -0400
Subject: [PATCH 2/3] Show menu after adding children

This prevents a warning on the console
---
 gui/user-switch-applet/applet.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/gui/user-switch-applet/applet.c b/gui/user-switch-applet/applet.c
index a3e0881..66479fa 100644
--- a/gui/user-switch-applet/applet.c
+++ b/gui/user-switch-applet/applet.c
@@ -1062,7 +1062,6 @@ create_sub_menu (GdmAppletData *adata)
                           G_CALLBACK (menu_style_set_cb), adata);
         g_signal_connect (adata->menu, "show",
                           G_CALLBACK (menu_expose_cb), adata);
-        gtk_widget_show (adata->menu);
 
 #ifdef BUILD_PRESENSE_STUFF
         adata->user_item = gdm_entry_menu_item_new ();
@@ -1177,6 +1176,7 @@ create_sub_menu (GdmAppletData *adata)
         g_signal_connect (adata->quit_session_item, "activate",
                           G_CALLBACK (on_quit_session_activate), adata);
         gtk_widget_show (adata->quit_session_item);
+        gtk_widget_show (adata->menu);
 }
 
 static void
-- 
1.7.2.2


From c9c1269681e102dc8a5778f52c38bc4c7ef69fdf Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Sep 2010 17:07:43 -0400
Subject: [PATCH 3/3] Don't try to read users real name until user loaded

The user switcher puts the full name of the the currently
loaded user on the panel.  Now that the user is loaded
asynchronously, we need to defer putting that name up until
later in startup.
---
 gui/user-switch-applet/applet.c |   75 +++++++++++++++++++++++++++-----------
 1 files changed, 53 insertions(+), 22 deletions(-)

diff --git a/gui/user-switch-applet/applet.c b/gui/user-switch-applet/applet.c
index 66479fa..edb69e4 100644
--- a/gui/user-switch-applet/applet.c
+++ b/gui/user-switch-applet/applet.c
@@ -79,7 +79,8 @@ typedef struct _GdmAppletData
         guint           client_notify_lockdown_id;
 
         guint           current_status;
-        guint           user_notify_id;
+        guint           user_loaded_notify_id;
+        guint           user_changed_notify_id;
         gint8           pixel_size;
         gint            panel_size;
         GtkIconSize     icon_size;
@@ -479,7 +480,13 @@ gdm_applet_data_free (GdmAppletData *adata)
 {
         gconf_client_notify_remove (adata->client, adata->client_notify_lockdown_id);
 
-        g_signal_handler_disconnect (adata->user, adata->user_notify_id);
+        if (adata->user_loaded_notify_id != 0) {
+                g_signal_handler_disconnect (adata->user, adata->user_changed_notify_id);
+        }
+
+        if (adata->user_changed_notify_id != 0) {
+                g_signal_handler_disconnect (adata->user, adata->user_changed_notify_id);
+        }
 
 #ifdef BUILD_PRESENSE_STUFF
         if (adata->presence_proxy != NULL) {
@@ -1263,39 +1270,63 @@ reset_icon (GdmAppletData *adata)
 }
 
 static void
-setup_current_user (GdmAppletData *adata)
+setup_current_user_now (GdmAppletData *adata)
+{
+        g_assert (adata->user != NULL);
+
+        g_signal_handler_disconnect (adata->user, adata->user_loaded_notify_id);
+        adata->user_loaded_notify_id = 0;
+
+        update_label (adata);
+        reset_icon (adata);
+        adata->user_changed_notify_id =
+            g_signal_connect (adata->user,
+                              "changed",
+                              G_CALLBACK (on_user_changed),
+                              adata);
+}
+
+static void
+on_current_user_loaded (GdmUser       *user,
+                        GParamSpec    *pspec,
+                        GdmAppletData *adata)
 {
-        const char *name;
-        GtkWidget  *label;
+        if (!gdm_user_is_loaded (user)) {
+                return;
+        }
+
+        setup_current_user_now (adata);
+}
 
+static void
+setup_current_user (GdmAppletData *adata)
+{
         adata->user = gdm_user_manager_get_user_by_uid (adata->manager, getuid ());
-        if (adata->user != NULL) {
-                g_object_ref (adata->user);
-                name = gdm_user_get_real_name (adata->user);
-        } else {
-                name = _("Unknown");
+
+        if (adata->user == NULL) {
+                g_warning ("Could not setup current user");
+                return;
         }
 
-        adata->menuitem = gtk_image_menu_item_new_with_label (name);
+        g_object_ref (adata->user);
+
+        adata->menuitem = gtk_image_menu_item_new_with_label ("");
 #ifndef BUILD_PRESENSE_STUFF
         gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (adata->menuitem),
                                        gtk_image_new ());
 #endif
-        label = gtk_bin_get_child (GTK_BIN (adata->menuitem));
         gtk_menu_shell_append (GTK_MENU_SHELL (adata->menubar), adata->menuitem);
         gtk_widget_show (adata->menuitem);
 
-        update_label (adata);
-
-        if (adata->user != NULL) {
-                reset_icon (adata);
-
-                adata->user_notify_id =
-                        g_signal_connect (adata->user,
-                                          "changed",
-                                          G_CALLBACK (on_user_changed),
-                                          adata);
+        if (gdm_user_is_loaded (adata->user)) {
+                setup_current_user_now (adata);
+                return;
         }
+
+        adata->user_loaded_notify_id = g_signal_connect (adata->user,
+                                                         "notify::is-loaded",
+                                                         G_CALLBACK (on_current_user_loaded),
+                                                         adata);
 }
 
 #ifdef BUILD_PRESENSE_STUFF
-- 
1.7.2.2

From 752ec6de8a6e66ce002a89c52fb0308791b40bf7 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 10 Sep 2010 13:27:52 -0400
Subject: [PATCH 1/5] Fix typo when disconnecting signal handler

We were disconnecting the wrong one.
---
 gui/user-switch-applet/applet.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/gui/user-switch-applet/applet.c b/gui/user-switch-applet/applet.c
index edb69e4..4a4b41d 100644
--- a/gui/user-switch-applet/applet.c
+++ b/gui/user-switch-applet/applet.c
@@ -481,7 +481,7 @@ gdm_applet_data_free (GdmAppletData *adata)
         gconf_client_notify_remove (adata->client, adata->client_notify_lockdown_id);
 
         if (adata->user_loaded_notify_id != 0) {
-                g_signal_handler_disconnect (adata->user, adata->user_changed_notify_id);
+                g_signal_handler_disconnect (adata->user, adata->user_loaded_notify_id);
         }
 
         if (adata->user_changed_notify_id != 0) {
-- 
1.7.2.3


From ad1cd9c302d8dec51ae62bcf9ba4cc132b584364 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 10 Sep 2010 13:28:57 -0400
Subject: [PATCH 2/5] Only disconnect loaded handler if connected

---
 gui/user-switch-applet/applet.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/gui/user-switch-applet/applet.c b/gui/user-switch-applet/applet.c
index 4a4b41d..a0da74c 100644
--- a/gui/user-switch-applet/applet.c
+++ b/gui/user-switch-applet/applet.c
@@ -1274,7 +1274,9 @@ setup_current_user_now (GdmAppletData *adata)
 {
         g_assert (adata->user != NULL);
 
-        g_signal_handler_disconnect (adata->user, adata->user_loaded_notify_id);
+        if (adata->user_loaded_notify_id != 0) {
+                g_signal_handler_disconnect (adata->user, adata->user_loaded_notify_id);
+        }
         adata->user_loaded_notify_id = 0;
 
         update_label (adata);
-- 
1.7.2.3


From 48570e22f4893c7088abc51f1de9bacfb772b13c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 10 Sep 2010 09:57:30 -0400
Subject: [PATCH 3/5] Drop gdm_user_new_from_object_path for _gdm_user_update_from_object_path

This is how it works with pwent, and it has the advantage of letting us
create a stub user object destined to come from the accounts service
before we know its object path.
---
 gui/simple-greeter/gdm-user-manager.c |    7 ++-----
 gui/simple-greeter/gdm-user-private.h |    3 +++
 gui/simple-greeter/gdm-user.c         |   24 +++++++++++++++---------
 3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 4382481..eecf9dc 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -830,11 +830,8 @@ add_new_user_for_object_path (const char     *object_path,
         if (user != NULL) {
                 return user;
         }
-        user = gdm_user_new_from_object_path (object_path);
-
-        if (user == NULL) {
-                return NULL;
-        }
+        user = g_object_new (GDM_TYPE_USER, NULL);
+        _gdm_user_update_from_object_path (user, object_path);
 
         manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user);
 
diff --git a/gui/simple-greeter/gdm-user-private.h b/gui/simple-greeter/gdm-user-private.h
index 16ff415..a248532 100644
--- a/gui/simple-greeter/gdm-user-private.h
+++ b/gui/simple-greeter/gdm-user-private.h
@@ -30,6 +30,9 @@
 
 G_BEGIN_DECLS
 
+void _gdm_user_update_from_object_path (GdmUser    *user,
+                                        const char *object_path);
+
 void _gdm_user_update_from_pwent (GdmUser             *user,
                                   const struct passwd *pwent);
 
diff --git a/gui/simple-greeter/gdm-user.c b/gui/simple-greeter/gdm-user.c
index 25951ba..317b721 100644
--- a/gui/simple-greeter/gdm-user.c
+++ b/gui/simple-greeter/gdm-user.c
@@ -1002,12 +1002,22 @@ changed_handler (DBusGProxy *proxy,
         update_info (user);
 }
 
-GdmUser *
-gdm_user_new_from_object_path (const gchar *object_path)
+/**
+ * _gdm_user_update_from_object_path:
+ * @user: the user object to update.
+ * @object_path: the object path of the user to use.
+ *
+ * Updates the properties of @user from the accounts service via
+ * the object path in @object_path.
+ **/
+void
+_gdm_user_update_from_object_path (GdmUser    *user,
+                                   const char *object_path)
 {
-        GdmUser *user;
+        g_return_if_fail (GDM_IS_USER (user));
+        g_return_if_fail (object_path != NULL);
+        g_return_if_fail (user->object_path == NULL);
 
-        user = (GdmUser *)g_object_new (GDM_TYPE_USER, NULL);
         user->object_path = g_strdup (object_path);
 
         user->accounts_proxy = dbus_g_proxy_new_for_name (user->connection,
@@ -1021,14 +1031,10 @@ gdm_user_new_from_object_path (const gchar *object_path)
                                      G_CALLBACK (changed_handler), user, NULL);
 
         if (!update_info (user)) {
-                goto error;
+                g_warning ("Couldn't update info for user with object path %s", object_path);
         }
 
-        return user;
-
- error:
         g_object_unref (user);
-        return NULL;
 }
 
 gboolean
-- 
1.7.2.3


From 10d14fb3d057f5fa3ddecd43aaf68b73d1f68771 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 10 Sep 2010 10:23:53 -0400
Subject: [PATCH 4/5] Add create_new_user function

This function wraps g_object_new (GDM_TYPE_USER, NULL),
and sets up the signal handler to detect when the user is loaded.

This allows us to handle new users from pwent entries in the same
way we handle new users from object paths, via the
on_new_user_loaded function.
---
 gui/simple-greeter/gdm-user-manager.c |   37 +++++++++++++++++++++++++--------
 1 files changed, 28 insertions(+), 9 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index eecf9dc..6964415 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -200,6 +200,10 @@ static void     monitor_local_users         (GdmUserManager *manager);
 static void     load_new_session_incrementally (GdmUserManagerNewSession *new_session);
 static void     set_is_loaded (GdmUserManager *manager, gboolean is_loaded);
 
+static void     on_new_user_loaded (GdmUser        *user,
+                                    GParamSpec     *pspec,
+                                    GdmUserManager *manager);
+
 static gpointer user_manager_object = NULL;
 
 G_DEFINE_TYPE (GdmUserManager, gdm_user_manager, G_TYPE_OBJECT)
@@ -684,6 +688,27 @@ set_has_multiple_users (GdmUserManager *manager,
                 g_object_notify (G_OBJECT (manager), "has-multiple-users");
         }
 }
+static void
+on_new_user_destroyed (GdmUserManager *manager,
+                       GdmUser        *user)
+{
+        manager->priv->new_users = g_slist_remove (manager->priv->new_users, user);
+}
+
+static GdmUser *
+create_new_user (GdmUserManager *manager)
+{
+        GdmUser *user;
+
+        user = g_object_new (GDM_TYPE_USER, NULL);
+
+        manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user);
+        g_object_weak_ref (G_OBJECT (user), (GWeakNotify) on_new_user_destroyed, manager);
+
+        g_signal_connect (user, "notify::is-loaded", G_CALLBACK (on_new_user_loaded), manager);
+
+        return user;
+}
 
 static void
 add_user (GdmUserManager *manager,
@@ -728,13 +753,9 @@ add_new_user_for_pwent (GdmUserManager *manager,
 
         g_debug ("GdmUserManager: Creating new user from password entry: %s", pwent->pw_name);
 
-        user = g_object_new (GDM_TYPE_USER, NULL);
+        user = create_new_user (manager);
         _gdm_user_update_from_pwent (user, pwent);
 
-        /* increases ref count */
-        add_user (manager, user);
-        g_object_unref (user);
-
         return user;
 }
 
@@ -777,6 +798,7 @@ on_new_user_loaded (GdmUser        *user,
         g_signal_handlers_disconnect_by_func (user, on_new_user_loaded, manager);
         manager->priv->new_users = g_slist_remove (manager->priv->new_users,
                                                    user);
+        g_object_weak_unref (G_OBJECT (user), (GWeakNotify) on_new_user_destroyed, manager);
 
         username = gdm_user_get_user_name (user);
 
@@ -830,12 +852,9 @@ add_new_user_for_object_path (const char     *object_path,
         if (user != NULL) {
                 return user;
         }
-        user = g_object_new (GDM_TYPE_USER, NULL);
+        user = create_new_user (manager);
         _gdm_user_update_from_object_path (user, object_path);
 
-        manager->priv->new_users = g_slist_prepend (manager->priv->new_users, user);
-
-        g_signal_connect (user, "notify::is-loaded", G_CALLBACK (on_new_user_loaded), manager);
         return user;
 }
 
-- 
1.7.2.3


From 02f11f48cb6a22b330512c7264e4baea594e6e33 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 10 Sep 2010 10:40:49 -0400
Subject: [PATCH 5/5] Use create_new_user in get_user call

Previously, we would call two different constructors, depending
on whether or not the user was coming from the accounts service
or the nsswitch.  Now we create a new "unloaded" user immediately,
and just call the relevant update function to load the user.
---
 gui/simple-greeter/gdm-user-manager.c |   22 ++++++----------------
 1 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/gui/simple-greeter/gdm-user-manager.c b/gui/simple-greeter/gdm-user-manager.c
index 6964415..bd36380 100644
--- a/gui/simple-greeter/gdm-user-manager.c
+++ b/gui/simple-greeter/gdm-user-manager.c
@@ -745,20 +745,6 @@ add_user (GdmUserManager *manager,
         }
 }
 
-static GdmUser *
-add_new_user_for_pwent (GdmUserManager *manager,
-                        struct passwd  *pwent)
-{
-        GdmUser *user;
-
-        g_debug ("GdmUserManager: Creating new user from password entry: %s", pwent->pw_name);
-
-        user = create_new_user (manager);
-        _gdm_user_update_from_pwent (user, pwent);
-
-        return user;
-}
-
 static void
 remove_user (GdmUserManager *manager,
              GdmUser        *user)
@@ -1576,20 +1562,24 @@ gdm_user_manager_get_user (GdmUserManager *manager,
 
         /* if we don't have it loaded try to load it now */
         if (user == NULL) {
+                user = create_new_user (manager);
+
                 if (manager->priv->accounts_proxy != NULL) {
                         char *object_path;
 
                         object_path = get_user_object_path_from_accounts_service (manager, username);
 
                         if (object_path != NULL) {
-                                user = add_new_user_for_object_path (object_path, manager);
+                                _gdm_user_update_from_object_path (user, object_path);
                                 g_free (object_path);
                         }
                 } else {
                         struct passwd *pwent;
+
                         get_pwent_for_name (username, &pwent);
+
                         if (pwent != NULL) {
-                                user = add_new_user_for_pwent (manager, pwent);
+                                _gdm_user_update_from_pwent (user, pwent);
                         }
                 }
         }
-- 
1.7.2.3