Index: src/gs-lock-plug.c
===================================================================
--- src/gs-lock-plug.c	(revision 1096)
+++ src/gs-lock-plug.c	(working copy)
@@ -40,9 +40,6 @@
 #include <glade/glade-xml.h>
 #include <gconf/gconf-client.h>
 
-/* for fast user switching */
-#include <libgnomevfs/gnome-vfs-init.h>
-
 #ifdef WITH_KBD_LAYOUT_INDICATOR
 #include <libgnomekbd/gkbd-indicator.h>
 #endif
@@ -51,14 +48,11 @@
 
 #include "gs-debug.h"
 
-#include "fusa-manager.h"
-
 #define KEY_LOCK_DIALOG_THEME "/apps/gnome-screensaver/lock_dialog_theme"
-#define KEY_TRY_AUTH_FIRST    "/apps/gnome-screensaver/try_auth_first"
+#define GDM_FLEXISERVER_COMMAND "gdmflexiserver"
 
 enum {
         AUTH_PAGE = 0,
-        SWITCH_PAGE
 };
 
 #define FACE_ICON_SIZE 48
@@ -72,7 +66,6 @@ struct GSLockPlugPrivate
 {
         GtkWidget   *vbox;
         GtkWidget   *auth_action_area;
-        GtkWidget   *switch_action_area;
 
         GtkWidget   *notebook;
         GtkWidget   *auth_face_image;
@@ -89,13 +82,9 @@ struct GSLockPlugPrivate
         GtkWidget   *auth_switch_button;
         GtkWidget   *auth_cancel_button;
         GtkWidget   *auth_logout_button;
-        GtkWidget   *switch_cancel_button;
-        GtkWidget   *switch_switch_button;
 
         GtkWidget   *auth_prompt_kbd_layout_indicator;
 
-        FusaManager *fusa_manager;
-
         gboolean     caps_lock_on;
         gboolean     switch_enabled;
         gboolean     logout_enabled;
@@ -159,102 +148,20 @@ gs_lock_plug_style_set (GtkWidget *widge
 }
 
 static void
-manager_new_console_cb (FusaManager  *manager,
-			FusaDisplay  *display,
-			const GError *error,
-			gpointer      data)
+do_user_switch (GSLockPlug *plug)
 {
-        GSLockPlug *plug = data;
-        g_signal_emit (plug,
-                       lock_plug_signals [RESPONSE],
-                       0,
-                       GS_LOCK_PLUG_RESPONSE_CANCEL);
-}
-
-static void
-do_user_switch (GSLockPlug  *plug,
-                FusaDisplay *display,
-                FusaUser    *user)
-{
-        GdkScreen *screen;
-
-        if (gtk_widget_has_screen (plug->priv->switch_user_treeview)) {
-                screen = gtk_widget_get_screen (plug->priv->switch_user_treeview);
-        } else {
-                screen = gdk_screen_get_default ();
-        }
-
-        if (display) {
-                fusa_manager_activate_display (plug->priv->fusa_manager,
-                                               display,
-                                               screen,
-                                               manager_new_console_cb,
-                                               plug,
-                                               NULL);
-                return;
-        }
-
-        fusa_manager_new_console (plug->priv->fusa_manager,
-                                  screen,
-                                  user,
-                                  manager_new_console_cb,
-                                  plug,
-                                  NULL);
-}
+        GError  *error;
+        gboolean res;
 
-enum {
-        REAL_NAME_COLUMN,
-        USER_NAME_COLUMN,
-        DISPLAY_LABEL_COLUMN,
-        ACTIVE_COLUMN,
-        PIXBUF_COLUMN,
-        N_COLUMNS
-};
+        error = NULL;
 
-static void
-switch_user_response (GSLockPlug *plug)
-{
-        FusaDisplay      *display = NULL;
-        FusaUser         *user = NULL;
-        GtkTreeSelection *selection;
-        GtkTreeModel     *model;
-        GtkTreeIter       iter;
-        GSList           *displays;
-        char             *name;
-
-        selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (plug->priv->switch_user_treeview));
-        gtk_tree_selection_get_selected (selection,
-                                         &model,
-                                         &iter);
-        gtk_tree_model_get (model, &iter, USER_NAME_COLUMN, &name, -1);
-
-        gs_debug ("Switch user response user:'%s'", name);
-
-        if (name != NULL
-            && strcmp (name, "__new_user") != 0
-            && strcmp (name, "__separator") != 0) {
-                user = fusa_manager_get_user (plug->priv->fusa_manager, name);
-                displays = fusa_user_get_displays (user);
-
-                if (displays != NULL) {
-                        GSList *l;
-
-                        /* FIXME: just pick the first one for now */
-                        display = displays->data;
-
-                        l = displays;
-                        while (l != NULL) {
-                                gs_debug ("Display console %d", fusa_display_get_console (l->data));
-                                l = l->next;
-                        }
-
-                        g_slist_free (displays);
-                }
+        res = gdk_spawn_command_line_on_screen (gdk_screen_get_default (),
+                                                GDM_FLEXISERVER_COMMAND,
+                                                &error);
+        if (! res) {
+                gs_debug ("Unable to start GDM greeter: %s", error->message);
+                g_error_free (error);
         }
-
-        g_free (name);
-
-        do_user_switch (plug, display, user);
 }
 
 static void
@@ -317,20 +224,6 @@ gs_lock_plug_response (GSLockPlug *plug,
                 gtk_entry_set_text (GTK_ENTRY (plug->priv->auth_prompt_entry), "");
         }
 
-        if (response_id == GS_LOCK_PLUG_RESPONSE_OK) {
-                gint current_page = AUTH_PAGE;
-
-                if (plug->priv->notebook != NULL) {
-                        current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (plug->priv->notebook));
-                }
-
-                if (current_page != AUTH_PAGE) {
-                        /* switch user */
-                        switch_user_response (plug);
-                        return;
-                }
-        }
-
         g_signal_emit (plug,
                        lock_plug_signals [RESPONSE],
                        0,
@@ -690,6 +583,18 @@ gs_lock_plug_set_logout_command (GSLockP
         }
 }
 
+static gboolean
+is_program_in_path (const char *program)
+{
+        char *tmp = g_find_program_in_path (program);
+        if (tmp != NULL) {
+                g_free (tmp);
+                return TRUE;
+        } else {
+                return FALSE;
+        }
+}
+
 static void
 gs_lock_plug_set_switch_enabled (GSLockPlug *plug,
                                  gboolean    switch_enabled)
@@ -708,7 +613,14 @@ gs_lock_plug_set_switch_enabled (GSLockP
         }
 
         if (switch_enabled) {
-                gtk_widget_show (plug->priv->auth_switch_button);
+                gboolean found;
+                found = is_program_in_path (GDM_FLEXISERVER_COMMAND);
+                if (found) {
+                        gtk_widget_show (plug->priv->auth_switch_button);
+                } else {
+                        gs_debug ("Waring: GDM flexiserver command not found: %s", GDM_FLEXISERVER_COMMAND);
+                        gtk_widget_hide (plug->priv->auth_switch_button);
+                }
         } else {
                 gtk_widget_hide (plug->priv->auth_switch_button);
         }
@@ -847,24 +759,6 @@ gs_lock_plug_class_init (GSLockPlugClass
 }
 
 static void
-switch_page (GSLockPlug *plug,
-             GtkButton  *button)
-{
-        gint       current_page;
-        gint       next_page;
-
-        g_return_if_fail (plug != NULL);
-
-        current_page = gtk_notebook_get_current_page (GTK_NOTEBOOK (plug->priv->notebook));
-        next_page = (current_page == AUTH_PAGE) ? SWITCH_PAGE : AUTH_PAGE;
-
-        gtk_notebook_set_current_page (GTK_NOTEBOOK (plug->priv->notebook), next_page);
-
-        /* this counts as activity so restart the timer */
-        restart_cancel_timeout (plug);
-}
-
-static void
 logout_button_clicked (GtkButton  *button,
                        GSLockPlug *plug)
 {
@@ -1046,376 +940,6 @@ gs_lock_plug_add_button (GSLockPlug  *pl
         return button;
 }
 
-typedef struct
-{
-        GtkTreeIter iter;
-        GtkWidget  *tree;
-} DisplayChangedData;
-
-static char *
-get_user_display_label (FusaUser *user)
-{
-        char *label;
-
-        label = g_strdup_printf ("<big>%s</big>\n<small>%s</small>",
-                                 fusa_user_get_display_name (user),
-                                 fusa_user_get_user_name (user));
-
-        return label;
-}
-
-static void
-user_displays_changed_cb (FusaUser           *user,
-                          DisplayChangedData *data)
-{
-        const char   *name;
-        gboolean      is_active;
-        int           n_displays;
-        GdkPixbuf    *pixbuf;
-        int           icon_size = FACE_ICON_SIZE;
-        GtkTreeModel *filter_model;
-        GtkTreeModel *model;
-        char         *label;
-
-        name = fusa_user_get_user_name (user);
-        n_displays = fusa_user_get_n_displays (user);
-        is_active = n_displays > 0;
-        pixbuf = fusa_user_render_icon (user, data->tree, icon_size);
-        label = get_user_display_label (user);
-
-        filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (data->tree));
-        model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
-
-        gtk_list_store_set (GTK_LIST_STORE (model), &data->iter,
-                            USER_NAME_COLUMN, name,
-                            REAL_NAME_COLUMN, fusa_user_get_display_name (user),
-                            DISPLAY_LABEL_COLUMN, label,
-                            ACTIVE_COLUMN, is_active,
-                            PIXBUF_COLUMN, pixbuf,
-                            -1);
-        g_free (label);
-}
-
-static void
-plug_add_user (GSLockPlug *plug,
-               FusaUser   *user)
-{
-        gboolean            is_active;
-        guint               n_displays;
-        DisplayChangedData *ddata;
-        char               *label;
-        GtkTreeIter         iter;
-        GtkTreeModel       *filter_model;
-        GtkTreeModel       *model;
-        GdkPixbuf          *pixbuf;
-        int                 icon_size = FACE_ICON_SIZE;
-
-        filter_model = gtk_tree_view_get_model (GTK_TREE_VIEW (plug->priv->switch_user_treeview));
-        model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
-
-        /* skip the current user */
-        if (fusa_user_get_uid (user) == getuid ()) {
-                return;
-        }
-
-        n_displays = fusa_user_get_n_displays (user);
-        is_active = n_displays > 0;
-
-        pixbuf = fusa_user_render_icon (user, plug->priv->switch_user_treeview, icon_size);
-
-        label = get_user_display_label (user);
-
-        gtk_list_store_append (GTK_LIST_STORE (model), &iter);
-        gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                            USER_NAME_COLUMN, fusa_user_get_user_name (user),
-                            REAL_NAME_COLUMN, fusa_user_get_display_name (user),
-                            DISPLAY_LABEL_COLUMN, label,
-                            ACTIVE_COLUMN, is_active,
-                            PIXBUF_COLUMN, pixbuf,
-                            -1);
-
-        g_free (label);
-
-        ddata = g_new0 (DisplayChangedData, 1);
-        ddata->iter = iter;
-        ddata->tree = plug->priv->switch_user_treeview;
-
-        g_signal_connect_data (user, "displays-changed",
-                               G_CALLBACK (user_displays_changed_cb), ddata,
-                               (GClosureNotify) g_free, 0);
-}
-
-static void
-user_added_cb (FusaManager *manager,
-	       FusaUser    *user,
-               GSLockPlug  *plug)
-{
-        gs_debug ("User added: %d", fusa_user_get_uid (user));
-        plug_add_user (plug, user);
-}
-
-static void
-user_removed_cb (FusaManager *manager,
-                 FusaUser    *user,
-                 GSLockPlug  *plug)
-{
-        gs_debug ("User removed: %d", fusa_user_get_uid (user));
-}
-
-static void
-populate_model (GSLockPlug *plug)
-{
-        GSList *users;
-
-        gs_profile_start (NULL);
-
-        gs_profile_start ("FUSA list users");
-        if (! plug->priv->fusa_manager) {
-                gs_profile_start ("gnome_vfs_init");
-                gnome_vfs_init ();
-                gs_profile_end ("gnome_vfs_init");
-
-                gs_profile_start ("fusa_manager_ref_default");
-                plug->priv->fusa_manager = fusa_manager_ref_default ();
-                gs_profile_end ("fusa_manager_ref_default");
-        }
-
-        fusa_manager_request_update_displays (plug->priv->fusa_manager, NULL, NULL);
-
-        users = fusa_manager_list_users (plug->priv->fusa_manager);
-        gs_profile_end ("FUSA list users");
-
-        while (users != NULL) {
-                FusaUser *user;
-
-                user = users->data;
-
-                gs_debug ("Found user: %d", fusa_user_get_uid (user));
-
-                plug_add_user (plug, user);
-
-                users = g_slist_delete_link (users, users);
-        }
-
-        g_signal_connect (plug->priv->fusa_manager, "user-added",
-                          G_CALLBACK (user_added_cb), plug);
-        g_signal_connect (plug->priv->fusa_manager, "user-removed",
-                          G_CALLBACK (user_removed_cb), plug);
-
-        gs_profile_end (NULL);
-}
-
-static int
-compare_users (GtkTreeModel *model,
-               GtkTreeIter  *a,
-               GtkTreeIter  *b,
-               gpointer      user_data)
-{
-        char *name_a;
-        char *name_b;
-        char *label_a;
-        char *label_b;
-        int   result;
-
-        gtk_tree_model_get (model, a, USER_NAME_COLUMN, &name_a, -1);
-        gtk_tree_model_get (model, b, USER_NAME_COLUMN, &name_b, -1);
-        gtk_tree_model_get (model, a, REAL_NAME_COLUMN, &label_a, -1);
-        gtk_tree_model_get (model, b, REAL_NAME_COLUMN, &label_b, -1);
-
-        if (! name_a) {
-                return 1;
-        } else if (! name_b) {
-                return -1;
-        }
-
-        if (strcmp (name_a, "__new_user") == 0) {
-                return -1;
-        } else if (strcmp (name_b, "__new_user") == 0) {
-                return 1;
-        } else if (strcmp (name_a, "__separator") == 0) {
-                return -1;
-        } else if (strcmp (name_b, "__separator") == 0) {
-                return 1;
-        }
-
-        if (! label_a) {
-                return 1;
-        } else if (! label_b) {
-                return -1;
-        }
-
-        result = strcmp (label_a, label_b);
-
-        g_free (label_a);
-        g_free (label_b);
-        g_free (name_a);
-        g_free (name_b);
-
-        return result;
-}
-
-static gboolean
-separator_func (GtkTreeModel *model,
-                GtkTreeIter  *iter,
-                gpointer      data)
-{
-        int      column = GPOINTER_TO_INT (data);
-        char    *text;
-        gboolean is_separator;
-
-        gtk_tree_model_get (model, iter, column, &text, -1);
-
-        if (text && strcmp (text, "__separator") == 0) {
-                is_separator = TRUE;
-        } else {
-                is_separator = FALSE;
-        }
-
-        g_free (text);
-
-        return is_separator;
-}
-
-static gboolean
-filter_out_users (GtkTreeModel *model,
-                  GtkTreeIter  *iter,
-                  GSLockPlug   *plug)
-{
-        gboolean is_active;
-        gboolean visible;
-        char    *name;
-
-        gtk_tree_model_get (model, iter,
-                            USER_NAME_COLUMN, &name,
-                            ACTIVE_COLUMN, &is_active,
-                            -1);
-
-        if (name == NULL) {
-                return FALSE;
-        }
-
-        if (strcmp (name, "__new_user") == 0
-            || strcmp (name, "__separator") == 0) {
-                visible = TRUE;
-        } else {
-                /* FIXME: do we show all users or only active ones? */
-                visible = TRUE;
-                /*visible = is_active;*/
-        }
-
-        g_free (name);
-
-        return visible;
-}
-
-static gboolean
-row_activated_cb (GtkTreeView       *view,
-                  GtkTreePath       *path,
-                  GtkTreeViewColumn *column,
-                  GSLockPlug        *plug)
-{
-        GtkTreeModel *filter_model;
-        GtkTreeModel *model;
-        GtkTreeIter   iter;
-        GtkTreePath  *child_path;
-        char         *username;
-
-        filter_model = gtk_tree_view_get_model (view);
-        model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (filter_model));
-
-        child_path = gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (filter_model), path);
-
-        gtk_tree_model_get_iter (model, &iter, child_path);
-        gtk_tree_model_get (model, &iter, USER_NAME_COLUMN, &username, -1);
-
-        /* FIXME: do something with username? */
-
-        switch_user_response (plug);
-
-        g_free (username);
-        gtk_tree_path_free (child_path);
-
-        return TRUE;
-}
-
-static void
-setup_treeview (GSLockPlug *plug)
-{
-        GtkListStore      *store;
-        GtkTreeViewColumn *column;
-        GtkCellRenderer   *renderer;
-        GtkTreeModel      *filter;
-
-        /* if user switching is not enabled then do nothing */
-        if (! plug->priv->switch_enabled) {
-                return;
-        }
-
-        gs_profile_start (NULL);
-
-        store = gtk_list_store_new (N_COLUMNS,
-                                    G_TYPE_STRING,
-                                    G_TYPE_STRING,
-                                    G_TYPE_STRING,
-                                    G_TYPE_BOOLEAN,
-                                    GDK_TYPE_PIXBUF);
-
-        filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (store), NULL);
-
-        gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (filter),
-                                                (GtkTreeModelFilterVisibleFunc) filter_out_users,
-                                                plug,
-                                                NULL);
-
-        gtk_tree_view_set_model (GTK_TREE_VIEW (plug->priv->switch_user_treeview),
-                                 filter);
-
-        g_object_unref (store);
-        g_object_unref (filter);
-
-        renderer = gtk_cell_renderer_pixbuf_new ();
-        column = gtk_tree_view_column_new_with_attributes ("Image", renderer,
-                                                           "pixbuf", PIXBUF_COLUMN,
-                                                           NULL);
-        gtk_tree_view_append_column (GTK_TREE_VIEW (plug->priv->switch_user_treeview), column);
-
-        renderer = gtk_cell_renderer_text_new ();
-        column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
-                                                           "markup", DISPLAY_LABEL_COLUMN,
-                                                           NULL);
-        gtk_tree_view_append_column (GTK_TREE_VIEW (plug->priv->switch_user_treeview), column);
-
-        gtk_tree_view_set_row_separator_func (GTK_TREE_VIEW (plug->priv->switch_user_treeview),
-                                              separator_func,
-                                              GINT_TO_POINTER (USER_NAME_COLUMN),
-                                              NULL);
-
-        gtk_tree_view_column_set_sort_column_id (column, 0);
-        gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store),
-                                         0,
-                                         compare_users,
-                                         NULL, NULL);
-        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
-                                              0,
-                                              GTK_SORT_ASCENDING);
-
-        g_signal_connect (GTK_TREE_VIEW (plug->priv->switch_user_treeview),
-                          "row-activated",
-                          G_CALLBACK (row_activated_cb), plug);
-
-        populate_model (plug);
-
-        gs_profile_end (NULL);
-}
-
-static gboolean
-setup_treeview_idle (GSLockPlug *plug)
-{
-        setup_treeview (plug);
-
-        return FALSE;
-}
-
 static char *
 get_user_display_name (void)
 {
@@ -1548,11 +1072,13 @@ create_page_one_buttons (GSLockPlug *plu
                                             plug->priv->auth_switch_button,
                                             TRUE);
         gtk_button_set_focus_on_click (GTK_BUTTON (plug->priv->auth_switch_button), FALSE);
+        gtk_widget_set_no_show_all (plug->priv->auth_switch_button, TRUE);
 
         plug->priv->auth_logout_button =  gs_lock_plug_add_button (GS_LOCK_PLUG (plug),
-                                                              plug->priv->auth_action_area,
-                                                              _("Log _Out"));
+                                                                   plug->priv->auth_action_area,
+                                                                   _("Log _Out"));
         gtk_button_set_focus_on_click (GTK_BUTTON (plug->priv->auth_logout_button), FALSE);
+        gtk_widget_set_no_show_all (plug->priv->auth_logout_button, TRUE);
 
         plug->priv->auth_cancel_button =  gs_lock_plug_add_button (GS_LOCK_PLUG (plug),
                                                                    plug->priv->auth_action_area,
@@ -1569,22 +1095,6 @@ create_page_one_buttons (GSLockPlug *plu
         gs_profile_end ("page one buttons");
 }
 
-static void
-create_page_two_buttons (GSLockPlug *plug)
-{
-        gs_profile_start ("page two buttons");
-        plug->priv->switch_cancel_button =  gs_lock_plug_add_button (GS_LOCK_PLUG (plug),
-                                                                     plug->priv->switch_action_area,
-                                                                     GTK_STOCK_CANCEL);
-        gtk_button_set_focus_on_click (GTK_BUTTON (plug->priv->switch_cancel_button), FALSE);
-
-        plug->priv->switch_switch_button =  gs_lock_plug_add_button (GS_LOCK_PLUG (plug),
-                                                                     plug->priv->switch_action_area,
-                                                                     _("S_witch User..."));
-
-        gs_profile_end ("page two buttons");
-}
-
 /* adapted from GDM */
 static char *
 expand_string (const char *text)
@@ -1791,83 +1301,6 @@ create_page_one (GSLockPlug *plug)
 }
 
 static void
-constrain_list_size (GtkWidget      *widget,
-                     GtkRequisition *requisition,
-                     GSLockPlug     *plug)
-{
-        GtkRequisition req;
-        int            max_height;
-        int            page;
-
-        /* don't do anything if we are on the auth page */
-        page = gtk_notebook_get_current_page (GTK_NOTEBOOK (plug->priv->notebook));
-        if (page == AUTH_PAGE) {
-                return;
-        }
-
-        /* constrain height to be the tree height up to a max */
-        max_height = (gdk_screen_get_height (gtk_widget_get_screen (widget))) / 4;
-        gtk_widget_size_request (plug->priv->switch_user_treeview, &req);
-
-        requisition->height = MIN (req.height, max_height);
-}
-
-static void
-setup_list_size_constraint (GtkWidget  *widget,
-                            GSLockPlug *plug)
-{
-        g_signal_connect (widget, "size-request",
-                          G_CALLBACK (constrain_list_size), plug);
-}
-
-static void
-create_page_two (GSLockPlug *plug)
-{
-        GtkWidget            *header_label;
-        GtkWidget            *userlist_scroller;
-        GtkWidget            *vbox;
-
-        gs_profile_start ("page two");
-
-        vbox = gtk_vbox_new (FALSE, 6);
-        gtk_notebook_append_page (GTK_NOTEBOOK (plug->priv->notebook), vbox, NULL);
-
-        header_label = gtk_label_new_with_mnemonic (_("S_witch to user:"));
-        gtk_misc_set_alignment (GTK_MISC (header_label), 0, 0.5);
-        gtk_box_pack_start (GTK_BOX (vbox), header_label, FALSE, FALSE, 0);
-
-        userlist_scroller = gtk_scrolled_window_new (NULL, NULL);
-        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (userlist_scroller),
-                                             GTK_SHADOW_IN);
-        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (userlist_scroller),
-                                        GTK_POLICY_NEVER,
-                                        GTK_POLICY_AUTOMATIC);
-        gtk_box_pack_start (GTK_BOX (vbox), userlist_scroller, TRUE, TRUE, 0);
-
-        setup_list_size_constraint (userlist_scroller, plug);
-
-        plug->priv->switch_user_treeview = gtk_tree_view_new ();
-        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (plug->priv->switch_user_treeview), FALSE);
-        gtk_container_add (GTK_CONTAINER (userlist_scroller), plug->priv->switch_user_treeview);
-
-        gtk_label_set_mnemonic_widget (GTK_LABEL (header_label), plug->priv->switch_user_treeview);
-
-        /* Buttons */
-        plug->priv->switch_action_area = gtk_hbutton_box_new ();
-
-        gtk_button_box_set_layout (GTK_BUTTON_BOX (plug->priv->switch_action_area),
-                                   GTK_BUTTONBOX_END);
-
-        gtk_box_pack_end (GTK_BOX (vbox), plug->priv->switch_action_area,
-                          FALSE, TRUE, 0);
-        gtk_widget_show (plug->priv->switch_action_area);
-
-        create_page_two_buttons (plug);
-
-        gs_profile_end ("page two");
-}
-
-static void
 unlock_button_clicked (GtkButton  *button,
                        GSLockPlug *plug)
 {
@@ -1885,7 +1318,15 @@ static void
 switch_user_button_clicked (GtkButton  *button,
                             GSLockPlug *plug)
 {
-        gs_lock_plug_response (plug, GS_LOCK_PLUG_RESPONSE_OK);
+
+        remove_response_idle (plug);
+
+        plug->priv->response_idle_id = g_timeout_add (2000,
+                                                      (GSourceFunc)response_cancel_idle_cb,
+                                                      plug);
+
+        gs_lock_plug_set_busy (plug);
+        do_user_switch (plug);
 }
 
 static char *
@@ -1946,7 +1387,6 @@ load_theme (GSLockPlug *plug)
 
         lock_dialog = glade_xml_get_widget (xml, "lock-dialog");
         gtk_container_add (GTK_CONTAINER (plug), lock_dialog);
-        gtk_widget_show_all (lock_dialog);
 
         plug->priv->vbox = NULL;
         plug->priv->notebook = glade_xml_get_widget (xml, "notebook");
@@ -1965,13 +1405,16 @@ load_theme (GSLockPlug *plug)
         plug->priv->auth_logout_button = glade_xml_get_widget (xml, "auth-logout-button");
         plug->priv->auth_switch_button = glade_xml_get_widget (xml, "auth-switch-button");
 
-        plug->priv->switch_action_area = glade_xml_get_widget (xml, "switch-action-area");
-        plug->priv->switch_user_treeview = glade_xml_get_widget (xml, "switch-user-treeview");
-        plug->priv->switch_cancel_button = glade_xml_get_widget (xml, "switch-cancel-button");
-        plug->priv->switch_switch_button = glade_xml_get_widget (xml, "switch-switch-button");
-
         /* Placeholder for the keyboard indicator */
         plug->priv->auth_prompt_kbd_layout_indicator = glade_xml_get_widget (xml, "auth-prompt-kbd-layout-indicator");
+        if (plug->priv->auth_logout_button != NULL) {
+                gtk_widget_set_no_show_all (plug->priv->auth_logout_button, TRUE);
+        }
+        if (plug->priv->auth_switch_button != NULL) {
+                gtk_widget_set_no_show_all (plug->priv->auth_switch_button, TRUE);
+        }
+
+        gtk_widget_show_all (lock_dialog);
 
         return TRUE;
 }
@@ -2001,8 +1444,6 @@ gs_lock_plug_init (GSLockPlug *plug)
 
         plug->priv = GS_LOCK_PLUG_GET_PRIVATE (plug);
 
-        plug->priv->fusa_manager = NULL;
-
         if (! load_theme (plug)) {
                 gs_debug ("Unable to load theme!");
 
@@ -2021,10 +1462,6 @@ gs_lock_plug_init (GSLockPlug *plug)
 
                 create_page_one (plug);
 
-                /* Page 2 */
-
-                create_page_two (plug);
-
                 gtk_widget_show_all (plug->priv->vbox);
         }
 
@@ -2069,12 +1506,6 @@ gs_lock_plug_init (GSLockPlug *plug)
                 }
         }
 
-        if (! plug->priv->switch_enabled) {
-                if (plug->priv->auth_switch_button != NULL) {
-                        gtk_widget_hide (plug->priv->auth_switch_button);
-                }
-        }
-
         plug->priv->timeout = DIALOG_TIMEOUT_MSEC;
 
         g_signal_connect (plug, "key_press_event",
@@ -2099,8 +1530,8 @@ gs_lock_plug_init (GSLockPlug *plug)
                           G_CALLBACK (cancel_button_clicked), plug);
 
         if (plug->priv->auth_switch_button != NULL) {
-                g_signal_connect_swapped (plug->priv->auth_switch_button, "clicked",
-                                          G_CALLBACK (switch_page), plug);
+                g_signal_connect (plug->priv->auth_switch_button, "clicked",
+                                  G_CALLBACK (switch_user_button_clicked), plug);
         }
 
         if (plug->priv->auth_logout_button != NULL) {
@@ -2108,23 +1539,12 @@ gs_lock_plug_init (GSLockPlug *plug)
                                   G_CALLBACK (logout_button_clicked), plug);
         }
 
-        if (plug->priv->switch_cancel_button != NULL) {
-                g_signal_connect (plug->priv->switch_cancel_button, "clicked",
-                                  G_CALLBACK (cancel_button_clicked), plug);
-        }
-        if (plug->priv->switch_switch_button != NULL) {
-                g_signal_connect (plug->priv->switch_switch_button, "clicked",
-                                  G_CALLBACK (switch_user_button_clicked), plug);
-        }
-
         if (plug->priv->auth_face_image) {
                 set_face_image (plug);
         }
 
         g_signal_connect (plug, "delete_event", G_CALLBACK (delete_handler), NULL);
 
-        g_idle_add ((GSourceFunc)setup_treeview_idle, plug);
-
         gs_profile_end (NULL);
 }
 
@@ -2142,10 +1562,6 @@ gs_lock_plug_finalize (GObject *object)
 
         g_free (plug->priv->logout_command);
 
-        if (plug->priv->fusa_manager) {
-                g_object_unref (plug->priv->fusa_manager);
-        }
-
         remove_response_idle (plug);
         remove_cancel_timeout (plug);
 
Index: src/cut-n-paste/gdm-queue.h
===================================================================
--- src/cut-n-paste/gdm-queue.h	(revision 1096)
+++ src/cut-n-paste/gdm-queue.h	(working copy)
@@ -1,107 +0,0 @@
-/*
- *    gdm-queue.h
- *    (c) 2006 Thomas Thurman
- *    Based originally on GDMcommunication routines
- *    (c)2001 Queen of England, (c)2002 George Lebl
- *    
- *    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
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *   
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *   
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- * 
- */
-
-#ifndef __GDM_QUEUE_H__
-#define __GDM_QUEUE_H__ 1
-
-#include <gdk/gdkscreen.h>
-
-G_BEGIN_DECLS
-
-/* ***************************************************************** *
- *  Based on gdm2/daemon/gdm.h                                       *
- *  Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>  *
- * ***************************************************************** */
-
-#define GDM_CMD_VERSION			"VERSION"
-#define GDM_CMD_AUTH_LOCAL		"AUTH_LOCAL %s"
-#define GDM_CMD_FLEXI_XSERVER		"FLEXI_XSERVER"
-#define GDM_CMD_FLEXI_XNEST		"FLEXI_XNEST %s %d %s %s"
-#define GDM_CMD_FLEXI_XSERVER_USER	"FLEXI_XSERVER_USER %s"
-#define GDM_CMD_FLEXI_XNEST_USER	"FLEXI_XNEST_USER %s %s %d %s %s"
-#define GDM_CMD_CONSOLE_SERVERS		"CONSOLE_SERVERS"
-#define GDM_CMD_GET_CONFIG       	"GET_CONFIG %s" 
-#define GDM_CMD_GET_CONFIG_FILE		"GET_CONFIG_FILE"
-#define GDM_CMD_ALL_SERVERS		"ALL_SERVERS"
-#define GDM_CMD_UPDATE_CONFIG		"UPDATE_CONFIG %s"
-#define GDM_CMD_GREETERPIDS		"GREETERPIDS"
-#define GDM_CMD_QUERY_LOGOUT_ACTION	"QUERY_LOGOUT_ACTION"
-#define GDM_CMD_SET_LOGOUT_ACTION	"SET_LOGOUT_ACTION"
-#define GDM_CMD_SET_SAFE_LOGOUT_ACTION	"SET_SAFE_LOGOUT_ACTION"
-#define GDM_CMD_LOGOUT_ACTION_NONE	"NONE"
-#define GDM_CMD_LOGOUT_ACTION_HALT	"HALT"
-#define GDM_CMD_LOGOUT_ACTION_REBOOT	"REBOOT"
-#define GDM_CMD_LOGOUT_ACTION_SUSPEND	"SUSPEND"
-#define GDM_CMD_QUERY_VT       		"QUERY_VT"
-#define GDM_CMD_SET_VT			"SET_VT %d"
-#define GDM_CMD_CLOSE        		"CLOSE"
-
-typedef enum {
-  GDM_RESULT_OK,
-  GDM_RESULT_ERROR,
-  GDM_RESULT_BIZARRE,
-} GdmResultState;
-
-typedef void (GdmMessageCallback)(GdmResultState is_ok,
-    const gchar *answer, gpointer data);
-
-/* This is the main external entrance to this part of the program.
- * 
- * It is an instruction to (at some future point) possibly send a certain
- * string to GDM, and when an answer is received, possibly send the answer
- * to a certain function.
- *
- * |callback| is a callback to send the answer to, when we get it.
- * If this is NULL, any answer will be thrown away.
- * Otherwise, the function is passed:
- *  1) A status flag, for "ok", "error" or (for error conditions) "bizarre".
- *  2) The string received from GDM. The leading "OK" or "ERROR" plus a
- *     space will be removed (and turned into the status flag just
- *     mentioned). If the result from GDM is *only* "OK" or "ERROR",
- *     or if there was actually no GDM request because the query was NULL,
- *     this will be NULL.
- *  3) An arbitrary pointer-- see below.
- *
- * |data| is arbitrary data to pass to the callback.
- * 
- * |query| is the query to send to GDM. You can use printf-style formatting.
- * If this is NULL, GDM won't hear anything about this step, but the
- * callback (if any) will be called anyway, just as if GDM had returned "OK".
- */
-void ask_gdm (GdmMessageCallback *callback, gpointer data, gchar *query, ...);
-
-/* This is the other main entrance to this part of the program, as well as
- * ask_gdm. It adds an authorisation step to the gdm_queue, which may involve
- * trying many keys and seeing which one works; this is not the concern of the
- * caller. Once a good key is found, it will be remembered for next time.
- *
- * Note that if you want to test error handling, commenting out the body of
- * this function is a good way to test it.
- */
-void queue_authentication (GdkScreen *screen);
-
-/* This just gets a cookie of MIT-MAGIC-COOKIE-1 type */
-gchar *get_mit_magic_cookie (GdkScreen *screen, gboolean binary);
-
-G_END_DECLS
-
-#endif /* !__GDM_QUEUE_H__ */
Index: src/cut-n-paste/fusa-utils.h
===================================================================
--- src/cut-n-paste/fusa-utils.h	(revision 1096)
+++ src/cut-n-paste/fusa-utils.h	(working copy)
@@ -1,37 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-utils.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __FUSA_UTILS_H__
-#define __FUSA_UTILS_H__ 1
-
-#include <gtk/gtkwidget.h>
-
-G_BEGIN_DECLS
-
-void fusa_dialog_hig_fix           (GtkWidget   *dialog,
-				    GtkStyle    *old_style,
-				    gpointer     is_message_esque);
-void fusa_die_an_ignominious_death (const gchar *primary_markup,
-				    const gchar *secondary_markup,
-				    const gchar *details_text);
-
-G_END_DECLS
-
-#endif /* !__FUSA_UTILS_H__ */
Index: src/cut-n-paste/fusa-display.c
===================================================================
--- src/cut-n-paste/fusa-display.c	(revision 1096)
+++ src/cut-n-paste/fusa-display.c	(working copy)
@@ -1,388 +0,0 @@
-/*
- * Fast User Switch Applet: fusa-display.c
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <config.h>
-#include <glib/gi18n.h>
-
-#include "fusa-user-private.h"
-#include "fusa-manager.h"
-
-#include "fusa-display-private.h"
-
-/* **************** *
- *  Private Macros  *
- * **************** */
- 
-#define FUSA_DISPLAY_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), FUSA_TYPE_DISPLAY, FusaDisplayClass))
-#define FUSA_IS_DISPLAY_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), FUSA_TYPE_DISPLAY))
-#define FUSA_DISPLAY_GET_CLASS(object) \
-  (G_TYPE_INSTANCE_GET_CLASS ((object), FUSA_TYPE_DISPLAY, FusaDisplayClass))
-
-
-/* ********************** *
- *  Private Enumerations  *
- * ********************** */
-
-enum
-{
-  PROP_0,
-  PROP_MANAGER,
-  PROP_NAME,
-  PROP_USER,
-  PROP_CONSOLE,
-  PROP_NESTED
-};
-
-
-/* ******************** *
- *  Private Structures  *
- * ******************** */
-
-struct _FusaDisplay
-{
-  GObject parent;
-
-  FusaManager *manager;
-  gchar *name;
-  FusaUser *user;
-  gint console;
-  guint8 nested : 1;
-};
-
-typedef struct _FusaDisplayClass
-{
-  GObjectClass parent_class;
-}
-FusaDisplayClass;
-
-
-/* ********************* *
- *  Function Prototypes  *
- * ********************* */
-
-/* GObject Functions */
-static void fusa_display_set_property (GObject      *object,
-				       guint         param_id,
-				       const GValue *value,
-				       GParamSpec   *pspec);
-static void fusa_display_get_property (GObject      *object,
-				       guint         param_id,
-				       GValue       *value,
-				       GParamSpec   *pspec);
-static void fusa_display_finalize     (GObject      *object);
-
-
-/* ******************* *
- *  GType Declaration  *
- * ******************* */
-
-G_DEFINE_TYPE (FusaDisplay, fusa_display, G_TYPE_OBJECT);
-
-
-/* ********************** *
- *  GType Initialization  *
- * ********************** */
-
-static void
-fusa_display_class_init (FusaDisplayClass *class)
-{
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS (class);
-
-  gobject_class->set_property = fusa_display_set_property;
-  gobject_class->get_property = fusa_display_get_property;
-  gobject_class->finalize = fusa_display_finalize;
-
-  g_object_class_install_property (gobject_class,
-				   PROP_MANAGER,
-				   g_param_spec_object ("manager",
-							_("Manager"),
-							_("The manager which owns this object."),
-							FUSA_TYPE_MANAGER,
-							(G_PARAM_READWRITE |
-							 G_PARAM_CONSTRUCT_ONLY)));
-  g_object_class_install_property (gobject_class,
-				   PROP_NAME,
-				   g_param_spec_string ("name",
-							_("Name"),
-							_("The name of the X11 display this object refers to."),
-							NULL,
-							G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-				   PROP_USER,
-				   g_param_spec_object ("user",
-							_("User"),
-							_("The user currently logged in on this virtual terminal."),
-							FUSA_TYPE_USER,
-							G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-				   PROP_CONSOLE,
-				   g_param_spec_int ("console",
-						     _("Console"),
-						     _("The number of the virtual console this display can be found on, or %-1."),
-						     -1, G_MAXINT, -1,
-						     G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-				   PROP_NESTED,
-				   g_param_spec_boolean ("nested",
-							 _("Nested"),
-							 _("Whether or not this display is a windowed (Xnest) display."),
-							 FALSE,
-							 G_PARAM_READABLE));
-}
-
-static void
-fusa_display_init (FusaDisplay *display)
-{
-  display->console = -1;
-}
-
-
-/* ******************* *
- *  GObject Functions  *
- * ******************* */
-
-static void
-fusa_display_set_property (GObject      *object,
-			   guint         param_id,
-			   const GValue *value,
-			   GParamSpec   *pspec)
-{
-  FusaDisplay *display;
-
-  display = FUSA_DISPLAY (object);
-
-  switch (param_id)
-    {
-    case PROP_MANAGER:
-      display->manager = g_value_get_object (value);
-      g_object_add_weak_pointer (G_OBJECT (display->manager),
-				 (gpointer *) &display->manager);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    }
-}
-
-static void
-fusa_display_get_property (GObject    *object,
-			   guint       param_id,
-			   GValue     *value,
-			   GParamSpec *pspec)
-{
-  FusaDisplay *display;
-
-  display = FUSA_DISPLAY (object);
-
-  switch (param_id)
-    {
-    case PROP_NAME:
-      g_value_set_string (value, display->name);
-      break;
-    case PROP_USER:
-      g_value_set_object (value, display->user);
-      break;
-    case PROP_CONSOLE:
-      g_value_set_int (value, display->console);
-      break;
-    case PROP_NESTED:
-      g_value_set_boolean (value, display->nested);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    }
-}
-
-static void
-fusa_display_finalize (GObject *object)
-{
-  FusaDisplay *display;
-
-  display = FUSA_DISPLAY (object);
-
-  _fusa_display_set_user (display, NULL);
-  g_free (display->name);
-  g_object_remove_weak_pointer (G_OBJECT (display->manager),
-				(gpointer *) &display->manager);
-
-  if (G_OBJECT_CLASS (fusa_display_parent_class)->finalize)
-    (*G_OBJECT_CLASS (fusa_display_parent_class)->finalize) (object);
-}
-
-
-/* ******************* *
- *  Utility Functions  *
- * ******************* */
-
-static void
-user_weak_notify (gpointer  data,
-		  GObject  *user_ptr)
-{
-  FusaDisplay *display;
-
-  display = FUSA_DISPLAY (data);
-
-  display->user = NULL;
-  g_object_notify (G_OBJECT (data), "user");
-}
-
-
-/* ************************************************************************** *
- *  Semi-Private API                                                          *
- * ************************************************************************** */
-
-FusaDisplay *
-_fusa_display_new (FusaManager *manager,
-		   const gchar *name,
-		   FusaUser    *user,
-		   gint         console,
-		   gboolean     nested)
-{
-  FusaDisplay *display;
-
-  display = g_object_new (FUSA_TYPE_DISPLAY, "manager", manager, NULL);
-  display->name = g_strdup (name);
-  _fusa_display_set_user (display, user);
-  display->console = console;
-  display->nested = !!nested;
-
-  return display;
-}
-
-/**
- * _fusa_display_set_user:
- * @display: the virtual terminal object to modify.
- * @user: the user logged in on the terminal, or %NULL
- * 
- * Updates @display to know who (if anyone) is logged in on the session it
- * represents.
- * 
- * Since: 1.0
- **/
-void
-_fusa_display_set_user (FusaDisplay *display,
-			FusaUser    *user)
-{
-  g_return_if_fail (FUSA_IS_DISPLAY (display));
-  g_return_if_fail (user == NULL || FUSA_IS_USER (user));
-
-  if (display->user == user)
-    return;
-
-  if (display->user)
-    {
-      g_object_weak_unref (G_OBJECT (display->user), user_weak_notify, display);
-      _fusa_user_remove_display (display->user, display);
-    }
-
-  display->user = user;
-
-  if (user)
-    {
-      g_object_weak_ref (G_OBJECT (display->user), user_weak_notify, display);
-      _fusa_user_add_display (user, display);
-    }
-
-  g_object_notify (G_OBJECT (display), "user");
-}
-
-
-/* ************************************************************************** *
- *  Public API                                                                *
- * ************************************************************************** */
-
-/**
- * fusa_display_get_name:
- * @display: the display object to examine.
- * 
- * Retrieves the name for the X11 session on @display, e.g. ":0".
- * 
- * Returns: a constant character array which should not be modified or freed.
- * 
- * Since: 1.0
- **/
-G_CONST_RETURN gchar *
-fusa_display_get_name (FusaDisplay *display)
-{
-  g_return_val_if_fail (FUSA_IS_DISPLAY (display), NULL);
-
-  return display->name;
-}
-
-/**
- * fusa_display_get_user:
- * @display: the virtual terminal object to examine.
- * 
- * Retrieves the user currently logged in to the virtual terminal @display.
- * 
- * Returns: a pointer to a #FusaUser object which should not be unreferenced.
- * 
- * Since: 1.0
- **/
-FusaUser *
-fusa_display_get_user (FusaDisplay *display)
-{
-  g_return_val_if_fail (FUSA_IS_DISPLAY (display), NULL);
-
-  return display->user;
-}
-
-/**
- * fusa_display_get_console:
- * @display: the display to examine.
- * 
- * Retrieves the numeric ID of the virtual console used by @display. If
- * @display represents a nested session, this will be the console that @display
- * exists on.
- * 
- * Returns: an integer.
- * 
- * Since: 1.0
- **/
-gint
-fusa_display_get_console (FusaDisplay *display)
-{
-  g_return_val_if_fail (FUSA_IS_DISPLAY (display), -1);
-
-  return display->console;
-}
-
-/**
- * fusa_display_get_nested:
- * @display: the display to examine.
- * 
- * Retrieves whether or not @display is a nested (Xnest) session.
- * 
- * Returns: a boolean value.
- * 
- * Since: 1.0
- **/
-gboolean
-fusa_display_get_nested (FusaDisplay *display)
-{
-  g_return_val_if_fail (FUSA_IS_DISPLAY (display), FALSE);
-
-  return display->nested;
-}
Index: src/cut-n-paste/fusa-manager.c
===================================================================
--- src/cut-n-paste/fusa-manager.c	(revision 1096)
+++ src/cut-n-paste/fusa-manager.c	(working copy)
@@ -1,1874 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 2 -*-
- * 
- * Fast User Switch Applet: fusa-manager.c
- * 
- * Copyright (C) 2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <config.h>
-
-#include <glib/gi18n.h>
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <pwd.h>
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <X11/Xauth.h>
-#include <X11/Xlib.h>
-#ifdef WITH_XNEST
-#include <X11/Xmu/WinUtil.h>
-#endif
-
-#include <gdk/gdkx.h>
-
-#include <gtk/gtkicontheme.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtkstock.h>
-
-#include <libgnomevfs/gnome-vfs-ops.h>
-
-#include "gdm-queue.h"
-#include "fusa-utils.h"
-#include "fusa-display-private.h"
-#include "fusa-user-private.h"
-
-#include "fusa-manager-private.h"
-
-
-/* **************** *
- *  Private Macros  *
- * **************** */
-
-#define FUSA_MANAGER_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), FUSA_TYPE_MANAGER, FusaManagerClass))
-#define FUSA_IS_MANAGER_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), FUSA_TYPE_MANAGER))
-#define FUSA_MANAGER_GET_CLASS(object) \
-  (G_TYPE_INSTANCE_GET_CLASS ((object), FUSA_TYPE_MANAGER, FusaManagerClass))
-
-/* Prefs Defaults */
-#define DEFAULT_ALLOW_ROOT	TRUE
-#define DEFAULT_MAX_ICON_SIZE	128
-#define DEFAULT_USER_MAX_FILE	65536
-#define DEFAULT_MINIMAL_UID	100
-#define DEFAULT_GLOBAL_FACE_DIR	DATADIR "/faces"
-#define DEFAULT_USER_ICON	"stock_person"
-#define DEFAULT_EXCLUDE		{ "bin",	\
-				  "daemon",	\
-				  "adm",	\
-				  "lp",		\
-				  "sync",	\
-				  "shutdown",	\
-				  "halt",	\
-				  "mail",	\
-				  "news",	\
-				  "uucp",	\
-				  "operator",	\
-				  "nobody",	\
-				  "gdm",	\
-				  "postgres",	\
-				  "pvm",	\
-				  "rpm",	\
-				  "nfsnobody",	\
-				  "pcap",	\
-				  NULL }
-
-/* Magic */
-#define MINIMAL_GDM_VERSION	"2.8.0"
-
-
-/* ********************** *
- *  Private Enumerations  *
- * ********************** */
-
-enum
-{
-  USER_ADDED,
-  USER_REMOVED,
-  DISPLAY_ADDED,
-  DISPLAY_REMOVED,
-  LAST_SIGNAL
-};
-
-/* ******************** *
- *  Private Structures  *
- * ******************** */
-
-/* Class Structures */
-struct _FusaManager
-{
-  GObject parent;
-
-  /* Child Objects */
-  GHashTable *displays;
-  GHashTable *displays_by_console;
-  GHashTable *users;
-  GHashTable *users_by_uid;
-
-  /* Updaters */
-  GnomeVFSMonitorHandle *gdmconfig_monitor;
-  GnomeVFSMonitorHandle *passwd_monitor;
-  GnomeVFSMonitorHandle *shells_monitor;
-  guint results_pull_id;
-  guint update_displays_id;
-
-  GHashTable *shells;
-  GHashTable *exclusions;
-  gchar *global_face_dir;
-  uid_t minimal_uid;
-  gsize user_max_file;
-  gint max_icon_size;
-
-  guint8 allow_root  : 1;
-  guint8 relax_group : 1;
-  guint8 relax_other : 1;
-
-  /* Dirty flags */
-  guint8 users_dirty : 1;
-  guint8 icons_dirty : 1;
-};
-
-typedef struct _FusaManagerClass
-{
-  GObjectClass parent_class;
-
-  /* Signals */
-  void (*user_added)        (FusaManager *manager,
-			     FusaUser    *user);
-  void (*user_removed)      (FusaManager *manager,
-			     FusaUser    *user);
-  void (*display_added)     (FusaManager *manager,
-			     FusaDisplay *display);
-  void (*display_removed)   (FusaManager *manager,
-			     FusaDisplay *display);
-}
-FusaManagerClass;
-
-/* Thread Back-n-Forth Structures */
-typedef struct _DisplayUpdate
-{
-  gchar *name;
-  gchar *username;
-  gchar *location;
-}
-DisplayUpdate;
-
-typedef struct _CleanDisplaysData
-{
-  FusaManager *manager;
-  GSList *displays;
-}
-CleanDisplaysData;
-
-typedef struct _FusaManagerWithCallback
-{
-  FusaManager *manager;
-  FusaManagerDisplayCallback callback;
-  FusaDisplay *display_for_callback;
-  gchar *name_of_display;
-  gpointer data_for_callback;
-}
-FusaManagerWithCallback;
-
-
-/* ********************* *
- *  Function Prototypes  *
- * ********************* */
-
-/* GObject Functions */
-static void fusa_manager_finalize (GObject *object);
-
-/* GnomeVFSMonitor Callbacks */
-static void gdmconfig_monitor_cb (GnomeVFSMonitorHandle    *handle,
-				  const gchar              *text_uri,
-				  const gchar              *info_uri,
-				  GnomeVFSMonitorEventType  event_type,
-				  gpointer                  user_data);
-static void shells_monitor_cb    (GnomeVFSMonitorHandle    *handle,
-				  const gchar              *text_uri,
-				  const gchar              *info_uri,
-				  GnomeVFSMonitorEventType  event_type,
-				  gpointer                  user_data);
-static void passwd_monitor_cb    (GnomeVFSMonitorHandle    *handle,
-				  const gchar              *text_uri,
-				  const gchar              *info_uri,
-				  GnomeVFSMonitorEventType  event_type,
-				  gpointer                  user_data);
-
-/* User Functions */
-static gboolean        check_user_file                (const gchar  *filename,
-						       uid_t         uid,
-						       gssize        max_file_size,
-						       gboolean      relax_group,
-						       gboolean      relax_other);
-static void            emit_user_icon_changed_signals (gpointer      key,
-						       gpointer      value,
-						       gpointer      user_data);
-static inline gboolean strv_equals_string_table       (gchar       **strv,
-						       GHashTable   *table);
-static void            reload_gdm_config              (FusaManager  *manager,
-                                                       gboolean      force_reload);
-static void            reload_shells                  (FusaManager  *manager);
-static void            reload_passwd                  (FusaManager  *manager);
-
-static FusaManagerWithCallback* new_fusa_manager_with_callback(FusaManager *manager,
-    FusaManagerDisplayCallback callback,
-    FusaDisplay *display_for_callback,
-    gpointer data_for_callback);
-
-/* Displays - Main Thread Functions */
-static inline void process_display_updates   (FusaManager                *manager,
-                                              DisplayUpdate              *items,
-                                              guint                      n_items);
-
-/* Utility Functions */
-static void         listify_hash_values_hfunc (gpointer      key,
-					       gpointer      value,
-					       gpointer      data);
-static gboolean     clear_hash_table_hrfunc   (gpointer      key,
-					       gpointer      value,
-					       gpointer      data);
-static FusaDisplay *real_get_display          (FusaManager  *manager,
-					       const gchar  *name);
-
-static void
-gdm_callback_update_displays (GdmResultState is_ok,
-			      const gchar *answer, gpointer manager);
-
-/* ****************** *
- *  Global Variables  *
- * ****************** */
-
-static guint          signals[LAST_SIGNAL] = { 0 };
-static gpointer       default_manager = NULL;
-static gchar         *default_config_file = NULL;
-
-
-/* ******************* *
- *  GType Declaration  *
- * ******************* */
-
-G_DEFINE_TYPE (FusaManager, fusa_manager, G_TYPE_OBJECT);
-
-
-/* ********************** *
- *  GType Initialization  *
- * ********************** */
-static void gdm_callback_config_file(GdmResultState is_ok,
-    const gchar *answer, gpointer dummy)
-{
-  if (is_ok == GDM_RESULT_OK &&
-      (!default_config_file ||
-       strcmp (answer, default_config_file) != 0))
-    {
-    if (default_config_file)
-      g_free (default_config_file);
-
-    default_config_file = g_strdup (answer);
-    }
-}
-
-static void
-fusa_manager_class_init (FusaManagerClass *class)
-{
-  GObjectClass *gobject_class;
-#if 0
-  gchar *config_result;
-#endif
-
-  gobject_class = G_OBJECT_CLASS (class);
-
-  gobject_class->finalize = fusa_manager_finalize;
-
-  signals[USER_ADDED] =
-    g_signal_new ("user-added",
-		  G_TYPE_FROM_CLASS (class),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (FusaManagerClass, user_added),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__OBJECT,
-		  G_TYPE_NONE, 1, FUSA_TYPE_USER);
-  signals[USER_REMOVED] =
-    g_signal_new ("user-removed",
-		  G_TYPE_FROM_CLASS (class),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (FusaManagerClass, user_removed),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__OBJECT,
-		  G_TYPE_NONE, 1, FUSA_TYPE_USER);
-  signals[DISPLAY_ADDED] =
-    g_signal_new ("display-added",
-		  G_TYPE_FROM_CLASS (class),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (FusaManagerClass, display_added),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__OBJECT,
-		  G_TYPE_NONE, 1, FUSA_TYPE_DISPLAY);
-  signals[DISPLAY_REMOVED] =
-    g_signal_new ("display-removed",
-		  G_TYPE_FROM_CLASS (class),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (FusaManagerClass, display_removed),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__OBJECT,
-		  G_TYPE_NONE, 1, FUSA_TYPE_DISPLAY);
-
-  ask_gdm(gdm_callback_config_file, NULL, GDM_CMD_GET_CONFIG_FILE);
-}
-
-static void
-fusa_manager_init (FusaManager *manager)
-{
-  GError *error;
-  gchar *uri;
-  GnomeVFSResult result;
-
-  /* GDM config file */
-  manager->exclusions = g_hash_table_new_full (g_str_hash, g_str_equal,
-					       g_free, NULL);
-  reload_gdm_config (manager, FALSE);
-  error = NULL;
-  uri = g_filename_to_uri (GDMCONFIGFILE, NULL, &error);
-  if (!uri)
-    {
-      g_critical ("Could not create URI for GDM configuration file `%s': %s",
-		  GDMCONFIGFILE, error->message);
-      g_error_free (error);
-    }
-  else
-    {
-      result = gnome_vfs_monitor_add (&(manager->gdmconfig_monitor), uri,
-				      GNOME_VFS_MONITOR_FILE,
-				      gdmconfig_monitor_cb, manager);
-      g_free (uri);
-
-      if (result != GNOME_VFS_OK)
-	g_critical ("Could not install monitor for GDM configuration file `%s': %s",
-		    GDMCONFIGFILE, gnome_vfs_result_to_string (result));
-    }
-
-  /* /etc/shells */
-  manager->shells = g_hash_table_new_full (g_str_hash, g_str_equal,
-					   g_free, NULL);
-  reload_shells (manager);
-  error = NULL;
-  uri = g_filename_to_uri ("/etc/shells", NULL, &error);
-  if (!uri)
-    {
-      g_critical ("Could not create URI for shells file `/etc/shells': %s",
-		  error->message);
-      g_error_free (error);
-    }
-  else
-    {
-      result = gnome_vfs_monitor_add (&(manager->shells_monitor), uri,
-				      GNOME_VFS_MONITOR_FILE,
-				      shells_monitor_cb, manager);
-      g_free (uri);
-
-      if (result != GNOME_VFS_OK)
-	g_critical ("Could not install monitor for shells file `/etc/shells': %s",
-		    gnome_vfs_result_to_string (result));
-    }
-
-  /* /etc/passwd */
-  manager->users =
-    g_hash_table_new_full (g_str_hash, g_str_equal,
-			   g_free, (GDestroyNotify) g_object_run_dispose);
-  manager->users_by_uid = g_hash_table_new (NULL, NULL);
-  error = NULL;
-  uri = g_filename_to_uri ("/etc/passwd", NULL, &error);
-  if (!uri)
-    {
-      g_critical ("Could not create URI for password file `/etc/passwd': %s",
-		  error->message);
-      g_error_free (error);
-    }
-  else
-    {
-      result = gnome_vfs_monitor_add (&(manager->passwd_monitor), uri,
-				      GNOME_VFS_MONITOR_FILE,
-				      passwd_monitor_cb, manager);
-      g_free (uri);
-
-      if (result != GNOME_VFS_OK)
-	g_critical ("Could not install monitor for password file `/etc/passwd: %s",
-		    gnome_vfs_result_to_string (result));
-    }
-
-
-  /* Displays */
-  manager->displays =
-    g_hash_table_new_full (g_str_hash, g_str_equal,
-			   g_free, (GDestroyNotify) g_object_run_dispose);
-  manager->displays_by_console = g_hash_table_new (NULL, NULL);
-
-  manager->users_dirty = FALSE;
-  manager->icons_dirty = FALSE;
-}
-
-void
-fusa_manager_request_update_displays (FusaManager *manager,
-				      FusaManagerDisplayCallback callback,
-				      gpointer *data)
-{
-  ask_gdm (gdm_callback_update_displays,
-	   new_fusa_manager_with_callback (manager, callback, NULL, data),
-	   GDM_CMD_CONSOLE_SERVERS);
-}
-
-/* ******************* *
- *  GObject Functions  *
- * ******************* */
-
-static void
-fusa_manager_finalize (GObject *object)
-{
-  FusaManager *manager;
-
-  manager = FUSA_MANAGER (object);
-
-  if (manager->update_displays_id)
-    g_source_remove (manager->update_displays_id);
-
-  if (manager->results_pull_id)
-    g_source_remove (manager->results_pull_id);
-
-  g_hash_table_destroy (manager->displays);
-  g_hash_table_destroy (manager->displays_by_console);
-
-  gnome_vfs_monitor_cancel (manager->shells_monitor);
-  g_hash_table_destroy (manager->shells);
-
-  gnome_vfs_monitor_cancel (manager->gdmconfig_monitor);
-  g_hash_table_destroy (manager->exclusions);
-  g_free (manager->global_face_dir);
-
-  gnome_vfs_monitor_cancel (manager->passwd_monitor);
-  g_hash_table_destroy (manager->users);
-  g_hash_table_destroy (manager->users_by_uid);
-
-  if (G_OBJECT_CLASS (fusa_manager_parent_class)->finalize)
-    (*G_OBJECT_CLASS (fusa_manager_parent_class)->finalize) (object);
-}
-
-
-/* *************************** *
- *  GnomeVFSMonitor Callbacks  *
- * *************************** */
-
-static void
-gdmconfig_monitor_cb (GnomeVFSMonitorHandle    *handle,
-		      const gchar              *text_uri,
-		      const gchar              *info_uri,
-		      GnomeVFSMonitorEventType  event_type,
-		      gpointer                  data)
-{
-  FusaManager *manager = data;
-
-  if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED &&
-      event_type != GNOME_VFS_MONITOR_EVENT_CREATED)
-    return;
-  
-  manager->users_dirty = FALSE;
-  manager->icons_dirty = FALSE;
-
-  reload_gdm_config (data, TRUE);
-}
-
-static void
-shells_monitor_cb (GnomeVFSMonitorHandle    *handle,
-		   const gchar              *text_uri,
-		   const gchar              *info_uri,
-		   GnomeVFSMonitorEventType  event_type,
-		   gpointer                  data)
-{
-  if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED &&
-      event_type != GNOME_VFS_MONITOR_EVENT_CREATED)
-    return;
-
-  reload_shells (data);
-  reload_passwd (data);
-}
-
-static void
-passwd_monitor_cb (GnomeVFSMonitorHandle    *handle,
-		   const gchar              *text_uri,
-		   const gchar              *info_uri,
-		   GnomeVFSMonitorEventType  event_type,
-		   gpointer                  user_data)
-{
-  if (event_type != GNOME_VFS_MONITOR_EVENT_CHANGED &&
-      event_type != GNOME_VFS_MONITOR_EVENT_CREATED)
-    return;
-
-  reload_passwd (user_data);
-}
-
-static FusaManagerWithCallback*
-new_fusa_manager_with_callback(
-  FusaManager *manager,
-  FusaManagerDisplayCallback callback,
-  FusaDisplay *display_for_callback,
-  gpointer data_for_callback)
-{
-  FusaManagerWithCallback *result = g_new0(FusaManagerWithCallback, 1);
-
-  result->manager = manager;
-  result->callback = callback;
-  result->display_for_callback = display_for_callback;
-  result->name_of_display = NULL;
-  result->data_for_callback = data_for_callback;
-
-  return result;
-}
-
-/* ************************ *
- *  User Updates Functions  *
- * ************************ */
-
-static void
-emit_user_icon_changed_signals (gpointer key,
-			        gpointer value,
-			        gpointer user_data)
-{
-  _fusa_user_icon_changed (value);
-}
-
-static inline gboolean
-strv_equals_string_table (gchar      **strv,
-			  GHashTable  *table)
-{
-  guint i;
-
-  if (!strv)
-    return FALSE;
-
-  /* Ensure sizes are equal */
-  if (g_strv_length (strv) != g_hash_table_size (table))
-    return FALSE;
-
-  /* Ensure that everything in strv is also in table */
-  for (i = 0; strv[i] != NULL; i++)
-    {
-      if (!g_hash_table_lookup (table, strv[i]))
-	return FALSE;
-    }
-
-  return TRUE;
-}
-
-static gboolean
-check_user_file (const gchar *filename,
-		 uid_t        user,
-		 gssize       max_file_size,
-		 gboolean     relax_group,
-		 gboolean     relax_other)
-{
-  struct stat fileinfo;
-
-  if (max_file_size < 0)
-    max_file_size = G_MAXSIZE;
-
-  /* Exists/Readable? */
-  if (stat (filename, &fileinfo) < 0)
-    return FALSE;
-
-  /* Is a regular file */
-  if (G_UNLIKELY (!S_ISREG (fileinfo.st_mode)))
-    return FALSE;
-
-  /* Owned by user? */
-  if (G_UNLIKELY (fileinfo.st_uid != user))
-    return FALSE;
-
-  /* Group not writable or relax_group? */
-  if (G_UNLIKELY ((fileinfo.st_mode & S_IWGRP) == S_IWGRP && !relax_group))
-    return FALSE;
-
-  /* Other not writable or relax_other? */
-  if (G_UNLIKELY ((fileinfo.st_mode & S_IWOTH) == S_IWOTH && !relax_other))
-    return FALSE;
-
-  /* Size is kosher? */
-  if (G_UNLIKELY (fileinfo.st_size > max_file_size))
-    return FALSE;
-
-  return TRUE;
-}
-
-
-/* Returns TRUE if changed */
-static gboolean
-merge_gdm_exclusions (FusaManager  *manager,
-		      gchar       **excludev,
-		      const gchar  *exclude_default[])
-{
-  gint i;
-
-  if (strv_equals_string_table (excludev, manager->exclusions))
-    return FALSE;
-
-  g_hash_table_foreach_remove (manager->exclusions,
-			       clear_hash_table_hrfunc, NULL);
-
-  if (exclude_default)
-    {
-      for (i = 0; exclude_default[i] != NULL; i++)
-        g_hash_table_insert (manager->exclusions,
-			     g_strdup (exclude_default[i]),
-			     GUINT_TO_POINTER (TRUE));
-    }
-
-  if (excludev)
-    {
-      for (i = 0; excludev[i] != NULL; i++)
-        g_hash_table_insert (manager->exclusions,
-			     g_strdup (excludev[i]), GUINT_TO_POINTER (TRUE));
-    }
-
-  return TRUE;
-}
-
-static void resolve_dirty_flags(GdmResultState dummy1, const gchar *dummy2, gpointer data)
-{
-  FusaManager *manager = data;
-
-  if (manager->users_dirty)
-    reload_passwd (data);
-
-  if (manager->icons_dirty)
-    g_hash_table_foreach (FUSA_MANAGER (data)->users,
-			  emit_user_icon_changed_signals, NULL);
-
-  manager->users_dirty = FALSE;
-  manager->icons_dirty = FALSE;
-}
-
-/* We need to pull in settings from the gdm daemon. When we ask it
- * about something, it sends us back a string. So we need a set of
- * functions which can parse these strings and do useful things with
- * the information...
- */
-
-static void handler_MinimalUID(GdmResultState is_ok, const gchar *value, gpointer data)
-{
-  FusaManager *manager = data;
-  uid_t tmp_minimal_uid = strtoul (value, NULL, 10);
-
-  if (tmp_minimal_uid != ULONG_MAX) {
-    manager->minimal_uid = tmp_minimal_uid;
-    manager->users_dirty = TRUE;
-  }
-}
-
-static void handler_Exclude(GdmResultState is_ok, const gchar *value, gpointer data)
-{
-  FusaManager *manager = data;
-  const gchar *exclude_default[] = DEFAULT_EXCLUDE;
-  gchar** excludev = g_strsplit (value, ",", G_MAXINT);
-  
-  if (merge_gdm_exclusions (manager, excludev, exclude_default))
-    manager->users_dirty = TRUE;
-}
-
-static void handler_GlobalFaceDir(GdmResultState is_ok, const gchar *value, gpointer data)
-{
-  FusaManager *manager = data;
-  if (!manager->global_face_dir ||
-      strcmp (value, manager->global_face_dir) != 0)
-    {
-      g_free (manager->global_face_dir);
-      manager->global_face_dir = g_strdup (value);
-      manager->icons_dirty = TRUE;
-    }
-}
-
-static void handler_UserMaxFile(GdmResultState is_ok, const gchar *value, gpointer data)
-{
-  FusaManager *manager = data;
-  gsize tmp_user_max_file = strtol (value, NULL, 10);
-
-  if (tmp_user_max_file != ULONG_MAX && tmp_user_max_file != manager->user_max_file)
-    {
-      manager->user_max_file = tmp_user_max_file;
-      manager->icons_dirty = TRUE;
-    }
-}
-
-static void handler_AllowRoot(GdmResultState is_ok, const gchar *value, gpointer data)
-{
-  FusaManager *manager = data;
-  gboolean tmp_allow_root = strcasecmp(value, "false") != 0;
-  
-  if (tmp_allow_root != manager->allow_root)
-    {
-      manager->allow_root = tmp_allow_root;
-      manager->users_dirty = TRUE;
-    }
-}
-
-static void handler_MaxIconSize(GdmResultState is_ok, const gchar *value, gpointer data)
-{
-  FusaManager *manager = data;
-  gint tmp_max_icon_size = strtol (value, NULL, 10);
-
-  if (tmp_max_icon_size > manager->max_icon_size)
-    {
-      manager->max_icon_size = tmp_max_icon_size;
-      manager->icons_dirty = TRUE;
-    }
-}
-
-/* ...and we need a table mapping the strings which identify settings to
- * these functions.
- */
-struct SettingsHandler {
-        gchar *key;
-        GdmMessageCallback *handler;
-} settings_handlers[] = {
-  { "greeter/MinimalUID", handler_MinimalUID },
-  { "greeter/Exclude", handler_Exclude },
-  { "greeter/GlobalFaceDir", handler_GlobalFaceDir },
-  { "security/UserMaxFile", handler_UserMaxFile },
-  { "security/AllowRoot", handler_AllowRoot },
-  { "gui/MaxIconWidth", handler_MaxIconSize },
-  { "gui/MaxIconHeight", handler_MaxIconSize },
-  { 0, 0 },
-};
-
-/* Now we just walk through the table, asking the daemon about each
- * entry and calling the handler when we hear an answer.
- */
-static void
-reload_gdm_config (FusaManager *manager,
-                   gboolean    force_reload)
-{
-  struct SettingsHandler *handler;
-
-  for (handler=settings_handlers; handler->key != NULL; handler++) {
-
-    /* If we're here because the file has been updated, then *we* know the
-     * value might have changed (because gnome-vfs told us), but gdm is most
-     * probably still unaware. Therefore, we must tell it to go and look.
-     * Unfortunately, there's no way of telling gdm over the socket to go
-     * and reload the file in toto, but we can tell it to reload those
-     * fields we're checking, and that's probably good enough.
-     */
-
-    if (force_reload) {
-      ask_gdm (NULL, NULL, GDM_CMD_UPDATE_CONFIG, handler->key);
-    }
-
-    ask_gdm (handler->handler, manager, GDM_CMD_GET_CONFIG, handler->key);
-  }
-
-  ask_gdm (resolve_dirty_flags, manager, NULL);
-}
-
-static void
-reload_shells (FusaManager *manager)
-{
-  gchar *shell;
-
-  setusershell();
-
-  g_hash_table_foreach_remove (manager->shells, clear_hash_table_hrfunc, NULL);
-  for (shell = getusershell (); shell; shell = getusershell ())
-    {
-      g_hash_table_insert (manager->shells, g_strdup (shell),
-			   GUINT_TO_POINTER (TRUE));
-    }
-
-  endusershell ();
-}
-
-static void
-reload_passwd (FusaManager *manager)
-{
-  struct passwd *pwent;
-  GSList *old_users, *new_users, *list;
-  
-  old_users = NULL;
-  new_users = NULL;
-
-  g_hash_table_foreach (manager->users, listify_hash_values_hfunc, &old_users);
-  g_slist_foreach (old_users, (GFunc) g_object_ref, NULL);
-
-  /* Make sure we keep users who are logged in no matter what. */
-  for (list = old_users; list; list = list->next)
-    {
-      if (fusa_user_get_n_displays (list->data))
-	{
-	  g_object_freeze_notify (G_OBJECT (list->data));
-	  new_users = g_slist_prepend (new_users, g_object_ref (list->data));
-	}
-    }
-
-  setpwent ();
-
-  for (pwent = getpwent (); pwent; pwent = getpwent ())
-    {
-      FusaUser *user;
-
-      user = NULL;
-
-      /* Skip users below MinimalUID... */
-      if (pwent->pw_uid < manager->minimal_uid)
-	continue;
-
-      /* ...And users w/ invalid shells... */
-      if (!pwent->pw_shell ||
-	  !g_hash_table_lookup (manager->shells, pwent->pw_shell))
-	continue;
-
-      /* ...And explicitly excluded users */
-      if (g_hash_table_lookup (manager->exclusions, pwent->pw_name))
-	continue;
-
-      user = g_hash_table_lookup (manager->users, pwent->pw_name);
-
-      /* Update users already in the *new* list */
-      if (g_slist_find (new_users, user))
-	{
-	  _fusa_user_update (user, pwent);
-	  continue;
-	}
-
-      if (!user)
-	user = g_object_new (FUSA_TYPE_USER, "manager", manager, NULL);
-      else
-	g_object_ref (user);
-
-      /* Freeze & update users not already in the new list */
-      g_object_freeze_notify (G_OBJECT (user));
-      _fusa_user_update (user, pwent);
-
-      new_users = g_slist_prepend (new_users, user);
-    }
-  
-  endpwent ();
-
-  /* Go through and handle added users */
-  for (list = new_users; list; list = list->next)
-    {
-      if (!g_slist_find (old_users, list->data))
-	{
-	  g_hash_table_insert (manager->users,
-			       g_strdup (fusa_user_get_user_name (list->data)),
-			       g_object_ref (list->data));
-	  g_hash_table_insert (manager->users_by_uid,
-			       GINT_TO_POINTER (fusa_user_get_uid (list->data)),
-			       list->data);
-	  g_signal_emit (manager, signals[USER_ADDED], 0, list->data);
-	}
-    }
-
-  /* Go through and handle removed users */
-  for (list = old_users; list; list = list->next)
-    {
-      if (!g_slist_find (new_users, list->data))
-	{
-	  g_signal_emit (manager, signals[USER_REMOVED], 0, list->data);
-	  g_hash_table_remove (manager->users_by_uid,
-			       GINT_TO_POINTER (fusa_user_get_uid (list->data)));
-	  g_hash_table_remove (manager->users,
-			       fusa_user_get_user_name (list->data));
-          /* FIXME: signals[USER_REMOVED]??? Why not? */
-	}
-    }
-
-  /* Cleanup */
-  g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL);
-  g_slist_foreach (new_users, (GFunc) g_object_unref, NULL);
-  g_slist_free (new_users);
-
-  g_slist_foreach (old_users, (GFunc) g_object_unref, NULL);
-  g_slist_free (old_users);
-}
-
-
-/* ********************************** *
- *  Displays - Main Thread Functions  *
- * ********************************** */
-
-static gboolean
-clean_displays_table (gpointer key,
-		      gpointer value,
-		      gpointer data)
-{
-  CleanDisplaysData *clean;
-  GSList *li;
-
-  clean = data;
-
-  li = g_slist_find (clean->displays, value);
-
-  if (!li)
-    {
-      g_signal_emit (clean->manager, signals[DISPLAY_REMOVED], 0, value);
-      g_hash_table_remove (clean->manager->displays_by_console,
-			   GINT_TO_POINTER (fusa_display_get_console (value)));
-      return TRUE;
-    }
-  else
-    {
-      g_object_unref (li->data);
-      clean->displays = g_slist_delete_link (clean->displays, li);
-    }
-
-  return FALSE;
-}
-
-static void
-process_display_updates (FusaManager *manager,
-                         DisplayUpdate *items,
-                         guint n_items)
-{
-  CleanDisplaysData clean_data;
-  FusaDisplay *display;
-  FusaUser *user;
-  guint i;
-
-  clean_data.manager = manager;
-  clean_data.displays = NULL;
-
-  for (i = 0; i < n_items; i++)
-    {
-      if (items[i].username != NULL)
-	{
-	  user = fusa_manager_get_user (manager,
-					items[i].username);
-	}
-      else
-	user = NULL;
-
-      display = real_get_display (manager, items[i].name);
-
-      if (display)
-	{
-	  _fusa_display_set_user (display, user);
-	  g_object_ref (display);
-	}
-      else
-	{
-	  gint console;
-	  gboolean nested;
-
-	  console = -1;
-	  nested = (items[i].location[0] == ':');
-
-	  /* Xnest: We don't need to loop to get around Xnest-in-Xnest insanity
-	   * becase all existing FusaDisplays will have a console set from their
-	   * insert -- plus that's just crackish anyways. */
-	  if (nested)
-	    {
-	      FusaDisplay *display;
-	      gchar *ptr;
-
-	      /* Strip the ".0" */
-	      ptr = strchr (items[i].location, '.');
-	      if (ptr)
-		*ptr = '\0';
-
-	      display = real_get_display (manager,
-					  items[i].location);
-
-	      if (display)
-		console = fusa_display_get_console (display);
-	    }
-	  /* Console */
-	  else if (sscanf (items[i].location, "%d",
-			   &console) != 1)
-	    {
-	      g_critical ("Invalid display location returned from GDM: `%s'.",
-			  items[i].location);
-	    }
-
-	  display = _fusa_display_new (manager,
-				       items[i].name, user,
-				       console, nested);
-
-	  g_hash_table_insert (manager->displays,
-			       g_strdup (items[i].name),
-			       g_object_ref (display));
-	  g_hash_table_insert (manager->displays_by_console,
-			       GINT_TO_POINTER (console), display);
-
-	  g_signal_emit (manager, signals[DISPLAY_ADDED], 0, display);
-	}
-
-      clean_data.displays = g_slist_prepend (clean_data.displays, display);
-    }
-
-  g_hash_table_foreach_remove (manager->displays, clean_displays_table,
-			       &clean_data);
-}
-
-static GError*
-g_error_from_gdm_answer (GdmResultState is_ok,
-    const gchar *answer)
-{
-  gint code;
-  const gchar *message;
- 
-  g_assert (is_ok != GDM_RESULT_OK);
-  
-  if (is_ok == GDM_RESULT_BIZARRE || answer == NULL || sscanf (answer, "%d", &code) != 1)
-    {
-      code = FUSA_MANAGER_DM_ERROR_UNKNOWN;
-      message = _("The display manager could not be contacted for unknown reasons.");
-    }
-  else
-    {
-      switch (code)
-	{
-	case FUSA_MANAGER_DM_ERROR_NOT_RUNNING:
-	  message = _("The display manager is not running or too old.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_FLEXI_LIMIT_REACHED:
-	  message = _("The configured limit of flexible servers has been reached.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_X_ERROR:
-	  message = _("There was an unknown error starting X.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_X_FAILED:
-	  message = _("The X server failed to finish starting.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_X_LIMIT_REACHED:
-	  message = _("There are too many X sessions running.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_XNEST_AUTH_ERROR:
-	  message = _("The nested X server (Xnest) cannot connect to your current X server.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_X_NOT_FOUND:
-	  message = _("The X server in the GDM configuration could not be found.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_LOGOUT_ACTION:
-	  message = _("Trying to set an unknown logout action, or trying to set a logout action which is not available.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_CONSOLES_UNSUPPORTED:
-	  message = _("Virtual terminals not supported.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_INVALID_CONSOLE:
-	  message = _("Invalid virtual terminal number.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_UNKNOWN_CONFIG:
-	  message = _("Trying to update an unsupported configuration key.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_PERMISSIONS:
-	  message = _("~/.Xauthority file badly configured or missing.");
-	  break;
-	case FUSA_MANAGER_DM_ERROR_TOO_MANY_MESSAGES:
-	  message = _("Too many messages were sent to the display manager, and it hung up.");
-	  break;
-	default:
-	  code = FUSA_MANAGER_DM_ERROR_OTHER;
-	  message = _("The display manager sent an unknown error message.");
-	  break;
-	}
-    }
-  return g_error_new (FUSA_MANAGER_DM_ERROR, code,
-	"%s\n%s", message, answer);
- 
-}
-
-static void
-gdm_callback_update_displays (GdmResultState is_ok,
-    const gchar *answer, gpointer data)
-{
-  FusaManagerWithCallback *manager_with_callback = (FusaManagerWithCallback *) data;
-  gchar **displays;
-  DisplayUpdate *items;
-  guint n_items;  
-
-  if (is_ok == GDM_RESULT_OK) {
-    displays = g_strsplit (answer, ";", -1);
-
-    if (displays)
-      {
-      guint i;
-
-      i = g_strv_length (displays);
-      if (i)
-        {
-        items = g_new0 (DisplayUpdate, i);
-        n_items = i;
-
-        while (i > 0)
-          {
-          gchar **args;
-
-          i--;
-
-          args = g_strsplit (displays[i], ",", 3);
-
-          /* Display name (e.g. :0) */
-          items[i].name = args[0];
-
-          /* Username */
-          if (args[1] != NULL && args[1][0] != '\0')
-            items[i].username = args[1];
-          else
-            {
-            items[i].username = NULL;
-            g_free (args[1]);
-            }
-
-          /* VT or display name Location (e.g "7" or ":0.0") */
-          items[i].location = args[2];
-
-          g_free (args);
-
-          }
-
-        /* FIXME: This is the only place p_d_u is called. Merge it in here. */
-        process_display_updates (manager_with_callback->manager,
-            items,
-            n_items);
-        }
-
-      g_strfreev (displays);
-      }
-
-    /* Now that we know which displays have what names, we can look up to see
-     * whether we stashed away the name of a display earlier before we could
-     * look it up.
-     */
-
-    if (manager_with_callback->name_of_display != NULL &&
-        manager_with_callback->display_for_callback == NULL) {
-
-      manager_with_callback->display_for_callback =
-        real_get_display (manager_with_callback->manager,
-            manager_with_callback->name_of_display);
-
-      g_free (manager_with_callback->name_of_display);
- 
-    }
-
-    if (manager_with_callback->callback)
-    manager_with_callback->callback(
-        manager_with_callback->manager,
-        manager_with_callback->display_for_callback,
-        NULL,
-        manager_with_callback->data_for_callback
-        );
-  } else if (manager_with_callback->callback) {
-    GError *error = g_error_from_gdm_answer (is_ok, answer);
-    manager_with_callback->callback(
-        manager_with_callback->manager,
-        manager_with_callback->display_for_callback,
-        error,
-        manager_with_callback->data_for_callback
-        );
-    g_error_free (error);
-  }
-
-  g_free (manager_with_callback);
-}
-
-static void
-gdm_callback_activate_display (GdmResultState is_ok,
-    const gchar *answer, gpointer data)
-{
-  FusaManagerWithCallback *manager_with_callback = (FusaManagerWithCallback *) data;
-
-  g_assert (manager_with_callback != NULL);
-
-  if (is_ok == GDM_RESULT_OK) {
-
-    /* Yay, we updated the display. We need to make a note of
-     * where the new display is.
-     */
-
-    if (manager_with_callback->name_of_display == NULL) {
-      manager_with_callback->name_of_display = g_strdup (answer);
-    }
-    
-    /* Better re-check the display list. */
-    ask_gdm (gdm_callback_update_displays,
-        manager_with_callback, 
-        GDM_CMD_CONSOLE_SERVERS);
-
-    /* But... do not free manager_with_callback because we're passing it
-     * straight through to gdm_callback_update_displays.
-     */
-
-  } else if (manager_with_callback->callback) {
-    GError *error = g_error_from_gdm_answer (is_ok, answer);
-    manager_with_callback->callback(
-        manager_with_callback->manager,
-        manager_with_callback->display_for_callback,
-        error,
-        manager_with_callback->data_for_callback
-        );
-    g_free (manager_with_callback);
-  }
-}
-
-/* ******************* *
- *  Utility Functions  *
- * ******************* */
-
-static void
-listify_hash_values_hfunc (gpointer key,
-			   gpointer value,
-			   gpointer user_data)
-{
-  GSList **list = user_data;
-
-  *list = g_slist_prepend (*list, value);
-}
-
-static gboolean
-clear_hash_table_hrfunc (gpointer key,
-			 gpointer value,
-			 gpointer user_data)
-{
-  return TRUE;
-}
-
-static FusaDisplay *
-real_get_display (FusaManager *manager,
-		  const gchar *name)
-{
-  FusaDisplay *display;
-  gchar *ptr, *key;
-
-  ptr = strchr (name, '.');
-  if (ptr)
-    key = g_strndup (name, ptr - name);
-  else
-    key = g_strdup (name);
-
-  display = g_hash_table_lookup (manager->displays, key);
-  g_free (key);
-
-  return display;
-}
-
-
-/* ************************************************************************** *
- *  Semi-Private API                                                          *
- * ************************************************************************** */
-
-static GdkPixbuf *
-render_icon_from_home (FusaManager  *manager,
-		       FusaUser     *user,
-		       GtkWidget    *widget,
-		       gint          icon_size)
-{
-  GdkPixbuf *retval;
-  const gchar *homedir, *username;
-  uid_t uid;
-  gchar *path;
-  GnomeVFSURI *uri;
-  gboolean is_local;
-
-  homedir = fusa_user_get_home_directory (user);
-  uid = fusa_user_get_uid (user);
-  username = NULL;
-
-  /* special case: look at parent of home to detect autofs
-     this is so we don't try to trigger an automount */
-  path = g_path_get_dirname (homedir);
-  uri = gnome_vfs_uri_new (path);
-  is_local = gnome_vfs_uri_is_local (uri);
-  gnome_vfs_uri_unref (uri);
-  g_free (path);
-
-  /* now check that home dir itself is local */
-  if (is_local)
-    {
-      uri = gnome_vfs_uri_new (homedir);
-      is_local = gnome_vfs_uri_is_local (uri);
-      gnome_vfs_uri_unref (uri);
-    }
-
-  /* only look at local home directories so we don't try to
-     read from remote (e.g. NFS) volumes */
-  if (!is_local)
-    return NULL;
-
-  /* First, try "~/.face" */
-  path = g_build_filename (homedir, ".face", NULL);
-  if (check_user_file (path, uid, manager->user_max_file,
-		       manager->relax_group, manager->relax_other))
-    retval = gdk_pixbuf_new_from_file_at_size (path, icon_size, icon_size, NULL);
-  else
-    retval = NULL;
-  g_free (path);
-
-  /* Next, try "~/.face.icon" */
-  if (!retval)
-    {
-      path = g_build_filename (homedir, ".face.icon", NULL);
-      if (check_user_file (path, uid, manager->user_max_file,
-			   manager->relax_group, manager->relax_other))
-	retval = gdk_pixbuf_new_from_file_at_size (path, icon_size, icon_size,
-						   NULL);
-      else
-	retval = NULL;
-
-      g_free (path);
-    }
-
-  /* Still nothing, try the user's personal GDM config */
-  if (!retval)
-    {
-      path = g_build_filename (homedir, ".gnome", "gdm", NULL);
-      if (check_user_file (path, uid, manager->user_max_file,
-			   manager->relax_group, manager->relax_other))
-	{
-	  GKeyFile *keyfile;
-	  gchar *icon_path;
-
-	  keyfile = g_key_file_new ();
-	  g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL);
-
-	  icon_path = g_key_file_get_string (keyfile, "face", "picture", NULL);
-	  if (icon_path &&
-	      check_user_file (icon_path, uid, manager->user_max_file,
-			       manager->relax_group, manager->relax_other))
-	    retval = gdk_pixbuf_new_from_file_at_size (path, icon_size,
-						       icon_size, NULL);
-	  else
-	    retval = NULL;
-
-	  g_free (icon_path);
-	  g_key_file_free (keyfile);
-	}
-      else
-	retval = NULL;
-
-      g_free (path);
-    }
-
-  /* Still nothing, try "~/.gnome/photo" */
-  if (!retval)
-    {
-      path = g_build_filename (homedir, ".gnome", "photo", NULL);
-      if (check_user_file (path, uid, manager->user_max_file,
-			   manager->relax_group, manager->relax_other))
-	retval = gdk_pixbuf_new_from_file_at_size (path, icon_size, icon_size,
-						   NULL);
-      else
-	retval = NULL;
-
-      g_free (path);
-    }
-
-  return retval;
-}
-
-GdkPixbuf *
-_fusa_manager_render_icon (FusaManager  *manager,
-			   FusaUser     *user,
-			   GtkWidget    *widget,
-			   gint          icon_size)
-{
-  GdkPixbuf *retval;
-  uid_t uid;
-  const gchar *username;
-  gchar *path;
-  gchar *tmp;
-  GtkIconTheme *theme;
-
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-  g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL);
-  g_return_val_if_fail (icon_size > 12, NULL);
-
-  retval = render_icon_from_home (manager, user, widget, icon_size);
-
-  if (retval)
-    return retval;
-
-  uid = fusa_user_get_uid (user);
-  username = fusa_user_get_user_name (user);
-
-  /* Try ${GlobalFaceDir}/${username} */
-  path = g_build_filename (manager->global_face_dir, username, NULL);
-  if (check_user_file (path, uid, manager->user_max_file,
-		       manager->relax_group, manager->relax_other))
-    retval = gdk_pixbuf_new_from_file_at_size (path, icon_size, icon_size,
-					       NULL);
-  else
-    retval = NULL;
-
-  g_free (path);
-  if (retval)
-    return retval;
-
-  /* Finally, ${GlobalFaceDir}/${username}.png */
-  tmp = g_strconcat (username, ".png", NULL);
-  path = g_build_filename (manager->global_face_dir, tmp, NULL);
-  g_free (tmp);
-  if (check_user_file (path, uid, manager->user_max_file,
-		       manager->relax_group, manager->relax_other))
-    retval = gdk_pixbuf_new_from_file_at_size (path, icon_size, icon_size,
-					       NULL);
-  else
-    retval = NULL;
-
-  g_free (path);
-  if (retval)
-    return retval;
-
-  /* Nothing yet, use stock icon */
-  if (widget && gtk_widget_has_screen (widget))
-    theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (widget));
-  else
-    theme = gtk_icon_theme_get_default ();
-
-  retval = gtk_icon_theme_load_icon (theme, DEFAULT_USER_ICON, icon_size,
-				     0, NULL);
-
-  if (!retval)
-    retval = gtk_icon_theme_load_icon (theme, GTK_STOCK_MISSING_IMAGE,
-				       icon_size, 0, NULL);
-
-  return retval;
-}
-
-/* ************************************************************************** *
- *  Public API                                                                *
- * ************************************************************************** */
-
-/**
- * fusa_manager_ref_default:
- * 
- * Retrieves a reference to the default manager object. This reference must be
- * released with g_object_unref() when no longer needed.
- * 
- * Returns: a reference to a #FusaManager object.
- **/
-FusaManager *
-fusa_manager_ref_default (void)
-{
-  if (default_manager)
-    g_object_ref (default_manager);
-  else
-    {
-      default_manager = g_object_new (FUSA_TYPE_MANAGER, NULL);
-      g_object_add_weak_pointer (G_OBJECT (default_manager),
-				 (gpointer *) &default_manager);
-    }
-
-  return default_manager;
-}
-
-/**
- * fusa_manager_get_display:
- * @manager: the manager to query.
- * @name: the name of the X11 display to retrieve (e.g. ":0").
- * 
- * Retrieves a pointer to the #FusaDisplay object from @manager which
- * corresponds to the @name display. The returned value is not a reference, and
- * should not be released.
- * 
- * Returns: a pointer to a #FusaDisplay object.
- **/
-FusaDisplay *
-fusa_manager_get_display (FusaManager *manager,
-			  const gchar *name)
-{
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-  g_return_val_if_fail (name != NULL && name[0] == ':', NULL);
-
-  return real_get_display (manager, name);
-}
-
-/**
- * fusa_manager_get_display_by_screen:
- * @manager: the manager to query.
- * @screen: the GDK representation of a screen.
- * 
- * Convenience function which retrieves a pointer to the #FusaDisplay object
- * from @manager which corresponds to the @screen display. The returned value is
- * not a reference, and should not be released.
- * 
- * Returns: a pointer to a #FusaDisplay object.
- **/
-FusaDisplay *
-fusa_manager_get_display_by_screen (FusaManager *manager,
-				    GdkScreen   *screen)
-{
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-
-  return real_get_display (manager,
-			   gdk_display_get_name (gdk_screen_get_display (screen)));
-}
-
-/**
- * fusa_manager_list_displays:
- * @manager: the manager to query.
- * 
- * Retrieves a newly-allocated list of pointers to #FusaDisplay objects known to
- * @manager. This list must be freed with g_slist_free() when no longer needed,
- * but the list items themselves are not references and should not be released.
- * 
- * Returns: a singly-linked list of pointers to #FusaDisplay objects.
- **/
-GSList *
-fusa_manager_list_displays (FusaManager *manager)
-{
-  GSList *retval;
-
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-
-  retval = NULL;
-  g_hash_table_foreach (manager->displays, listify_hash_values_hfunc, &retval);
-
-  return retval;
-}
-
-/**
- * fusa_manager_activate_display:
- * @manager: the manager to query.
- * @display: the display to switch to.
- * @screen: the screen which the application is running on.
- * 
- * Attempts to asynchronously change the current display to @display from
- * @screen using @manager. If @display is a console-backed display, the display
- * will switch. If @display is a nested (Xnest) display, the window will be
- * activated. If this action was successful, the "display-activated" signal will
- * be emitted.
- **/
-void
-fusa_manager_activate_display (FusaManager                *manager,
-			       FusaDisplay                *display,
-			       GdkScreen                  *screen,
-			       FusaManagerDisplayCallback  func,
-			       gpointer                    data,
-			       GDestroyNotify              notify)
-{
-  FusaDisplay *this_display;
-  gint console;
-
-  this_display =
-    real_get_display (manager,
-		      gdk_display_get_name (gdk_screen_get_display (screen)));
-
-  if (display == this_display)
-    return;
-
-  console = fusa_display_get_console (display);
-
-  if (console != fusa_display_get_console (this_display))
-    {
-    /* Switch to another console. Easy. */
-    queue_authentication (screen);
-    ask_gdm (gdm_callback_activate_display,
-        new_fusa_manager_with_callback(manager, func, display, data),
-        GDM_CMD_SET_VT, console);
-    }
-  else 
-    {
-#ifdef WITH_XNEST
-    /* Xnest on this console, find & activate it. */
-      Display *xdisplay;
-      Screen *xscreen;
-      Window xrootwin, dummy, client;
-      Window *children;
-      unsigned int n_children;
-
-      /* Modified from xc/programs/xlsclients/xlsclients.c
-       * Copyright 1989, 1998  The Open Group */
-      xscreen = gdk_x11_screen_get_xscreen (screen);
-      xdisplay = DisplayOfScreen (xscreen);
-      xrootwin = RootWindowOfScreen (xscreen);
-
-      if (XQueryTree (xdisplay, xrootwin, &dummy, &dummy,
-		      &children, &n_children))
-	{
-	  guint i;
-	  const gchar *display_name;
-	  gboolean found;
-
-	  display_name = fusa_display_get_name (display);
-	  found = FALSE;
-
-	  for (i = 0; !found && i < n_children; i++)
-	    {
-	      XTextProperty tp;
-	      char *wmname;
-	      char **client_argv;
-	      int client_argc;
-
-	      client_argv = NULL;
-	      client_argc = 0;
-	      wmname = NULL;
-	      tp.value = NULL;
-	      tp.encoding = None;
-	      client = XmuClientWindow (xdisplay, children[i]);
-
-	      /* We intentionally don't strip any trailing dots here because
-	       * GDM doesn't use them in it's exec'ing of Xnest -- anyways, if
-	       * client is Xnest and argv[1] == display_name, activate it. */
-	      if (!client || !XGetWMName (xdisplay, client, &tp) || !tp.value)
-		continue;
-	      
-	      if (strcmp ("Xnest", (const char *) tp.value) == 0 &&
-		  XGetCommand (xdisplay, client, &client_argv, &client_argc) &&
-		  client_argc > 1 &&
-		  strcmp (display_name, client_argv[1]) == 0)
-		{
-		  XEvent xev;
-
-		  /* Modified from libwnck/libwnck/xutils.c
-		   * Copyright 2001-2003 Havoc Pennington.
-		   * Copyright 2002 Anders Carlson
-		   * Copyright 2004-2005 Elijah Newren */
-		  xev.xclient.type = ClientMessage;
-		  xev.xclient.serial = 0;
-		  xev.xclient.send_event = True;
-		  xev.xclient.display = xdisplay;
-		  xev.xclient.window = client;
-		  xev.xclient.message_type = XInternAtom (xdisplay,
-							  "_NET_ACTIVE_WINDOW",
-							  FALSE);
-		  xev.xclient.format = 32;
-		  xev.xclient.data.l[0] = 2;
-		  xev.xclient.data.l[1] = gtk_get_current_event_time ();
-		  xev.xclient.data.l[2] = 0;
-		  xev.xclient.data.l[3] = 0;
-		  xev.xclient.data.l[4] = 0;
-
-		  XSendEvent (xdisplay, xrootwin, False,
-			      SubstructureRedirectMask | SubstructureNotifyMask,
-			      &xev);
-		  found = TRUE;
-		}
-
-	      if (client_argv)
-		XFreeStringList (client_argv);
-
-	      if (tp.value)
-		XFree (tp.value);
-	    }
-
-	  XFree (children);
-
-	  if (func)
-	    (*func) (manager, display, NULL, data);
-
-	  if (data && notify)
-	    (*notify) (data);
-	}
-#endif /* WITH_XNEST */
-    }
-}
-
-/**
- * fusa_manager_new_console:
- * @manager: the manager to query.
- * @screen: the screen which the application is running on.
- * 
- * Attempts to asynchronously create a new console-backed display. If the action
- * was successful, the "display-opened" signal will be emitted.
- **/
-void
-fusa_manager_new_console (FusaManager                *manager,
-			  GdkScreen                  *screen,
-			  FusaUser                   *user,
-			  FusaManagerDisplayCallback  func,
-			  gpointer                    data,
-			  GDestroyNotify              notify)
-{
-  g_return_if_fail (FUSA_IS_MANAGER (manager));
-
-  queue_authentication (screen);
-
-  if (user)
-    ask_gdm (gdm_callback_activate_display,
-        new_fusa_manager_with_callback (manager, func, NULL, data),
-        GDM_CMD_FLEXI_XSERVER_USER, fusa_user_get_user_name (user));
-  else
-    ask_gdm (gdm_callback_activate_display,
-        new_fusa_manager_with_callback (manager, func, NULL, data),
-        GDM_CMD_FLEXI_XSERVER);
-}
-
-/**
- * fusa_manager_new_xnest:
- * @manager: the manager to query.
- * @screen: the screen which the application is running on.
- * 
- * Attempts to asynchronously create a new nested (Xnest) display. If the action
- * was successful, the "display-opened" signal will be emitted.
- **/
-void
-fusa_manager_new_xnest (FusaManager                *manager,
-			GdkScreen                  *screen,
-			FusaUser                   *user,
-			FusaManagerDisplayCallback  func,
-			gpointer                    data,
-			GDestroyNotify              notify)
-{
-  gchar *mit_cookie;
-
-  g_return_if_fail (FUSA_IS_MANAGER (manager));
-
-  mit_cookie = get_mit_magic_cookie (screen, FALSE);
-  
-  queue_authentication (screen);
-
-  if (user)
-    ask_gdm (gdm_callback_update_displays,
-        new_fusa_manager_with_callback (manager, func, NULL, data),
-        GDM_CMD_FLEXI_XNEST_USER,
-	fusa_user_get_user_name (user),
-        gdk_display_get_name (gdk_screen_get_display (screen)),
-        (int) getuid (),
-        mit_cookie,
-        XauFileName ());
-  else
-    ask_gdm (gdm_callback_update_displays,
-        new_fusa_manager_with_callback (manager, func, NULL, data),
-        GDM_CMD_FLEXI_XNEST,
-        gdk_display_get_name (gdk_screen_get_display (screen)),
-        (int) getuid (),
-        mit_cookie,
-        XauFileName ());
-
-  g_free (mit_cookie);
-
-}
-
-/**
- * fusa_manager_get_user:
- * @manager: the manager to query.
- * @username: the login name of the user to get.
- * 
- * Retrieves a pointer to the #FusaUser object for the login named @username
- * from @manager. This pointer is not a reference, and should not be released.
- * 
- * Returns: a pointer to a #FusaUser object.
- **/
-FusaUser *
-fusa_manager_get_user (FusaManager *manager,
-		       const gchar *username)
-{
-  FusaUser *user;
-
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-  g_return_val_if_fail (username != NULL && username[0] != '\0', NULL);
-
-  user = g_hash_table_lookup (manager->users, username);
-
-  if (!user)
-    {
-      struct passwd *pwent;
-
-      pwent = getpwnam (username);
-
-      if (pwent)
-	{
-	  user = g_object_new (FUSA_TYPE_USER, "manager", manager, NULL);
-	  _fusa_user_update (user, pwent);
-	  g_hash_table_insert (manager->users, g_strdup (pwent->pw_name), user);
-	  g_hash_table_insert (manager->users_by_uid,
-			       GINT_TO_POINTER (pwent->pw_uid), user);
-	  g_signal_emit (manager, signals[USER_ADDED], 0, user);
-	}
-    }
-
-  return user;
-}
-
-/**
- * fusa_manager_get_user_by_uid:
- * @manager: the manager to query.
- * @uid: the ID of the user to get.
- * 
- * Retrieves a pointer to the #FusaUser object for the @uid login from @manager.
- * This pointer is not a reference, and should not be released.
- * 
- * Returns: a pointer to a #FusaUser object.
- **/
-FusaUser *
-fusa_manager_get_user_by_uid (FusaManager *manager,
-			      uid_t        uid)
-{
-  FusaUser *user;
-
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-  g_return_val_if_fail (uid >= 0, NULL);
-
-  user = g_hash_table_lookup (manager->users_by_uid, GINT_TO_POINTER (uid));
-
-  if (!user)
-    {
-      struct passwd *pwent;
-
-      pwent = getpwuid (uid);
-
-      if (pwent)
-	{
-	  user = g_object_new (FUSA_TYPE_USER, "manager", manager, NULL);
-	  _fusa_user_update (user, pwent);
-	  g_hash_table_insert (manager->users, g_strdup (pwent->pw_name), user);
-	  g_hash_table_insert (manager->users_by_uid,
-			       GINT_TO_POINTER (pwent->pw_uid), user);
-	  g_signal_emit (manager, signals[USER_ADDED], 0, user);
-	}
-    }
-
-  return user;
-}
-
-/**
- * fusa_manager_list_displays:
- * @manager: the manager to query.
- * 
- * Retrieves a newly-allocated list of pointers to #FusaUser objects known to
- * @manager. This list will contain all user who would ordinarily show up in the
- * GDM face browser, as well as any other users currently logged into managed X
- * displays. This list must be freed with g_slist_free() when no longer needed,
- * but the list items themselves are not references and should not be released.
- * 
- * Returns: a singly-linked list of pointers to #FusaUser objects.
- **/
-GSList *
-fusa_manager_list_users (FusaManager *manager)
-{
-  GSList *retval;
-
-  g_return_val_if_fail (FUSA_IS_MANAGER (manager), NULL);
-
-  retval = NULL;
-  g_hash_table_foreach (manager->users, listify_hash_values_hfunc, &retval);
-
-  return g_slist_sort (retval, (GCompareFunc) fusa_user_collate);
-}
-
-GQuark
-fusa_manager_dm_error_get_quark (void)
-{
-  static GQuark quark = 0;
-
-  if (G_UNLIKELY (quark == 0))
-    quark = g_quark_from_static_string ("fusa-manager-dm-error");
-
-  return quark;
-}
Index: src/cut-n-paste/fusa-display.h
===================================================================
--- src/cut-n-paste/fusa-display.h	(revision 1096)
+++ src/cut-n-paste/fusa-display.h	(working copy)
@@ -1,53 +0,0 @@
-/*
- * Fast User Switch Applet: fusa-display.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* 
- * Facade object used to represent an open VT or Xnest window, managed by FusaDisplayManager
- */
-
-#ifndef __FUSA_DISPLAY__
-#define __FUSA_DISPLAY__ 1
-
-#include "fusa-user.h"
-
-G_BEGIN_DECLS
-
-#define FUSA_TYPE_DISPLAY \
-  (fusa_display_get_type ())
-#define FUSA_DISPLAY(object) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((object), FUSA_TYPE_DISPLAY, FusaDisplay))
-#define FUSA_IS_DISPLAY(object) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((object), FUSA_TYPE_DISPLAY))
-
-typedef struct _FusaDisplay FusaDisplay;
-
-GType                 fusa_display_get_type      (void) G_GNUC_CONST;
-
-G_CONST_RETURN gchar *fusa_display_get_name      (FusaDisplay *display);
-FusaUser             *fusa_display_get_user      (FusaDisplay *display);
-gint                  fusa_display_get_console   (FusaDisplay *display);
-gboolean              fusa_display_get_nested    (FusaDisplay *display);
-
-void                  fusa_display_switch_to     (FusaDisplay *display,
-						  GdkScreen   *screen);
-
-G_END_DECLS
-
-#endif /* !__FUSA_DISPLAY__ */
Index: src/cut-n-paste/fusa-user-menu-item.c
===================================================================
--- src/cut-n-paste/fusa-user-menu-item.c	(revision 1096)
+++ src/cut-n-paste/fusa-user-menu-item.c	(working copy)
@@ -1,552 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-user-menu-item.c
- * 
- * Copyright (C) 2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <config.h>
-
-#include <glib/gi18n.h>
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <string.h>
-
-#include <gtk/gtkbutton.h>
-#include <gtk/gtkdialog.h>
-#include <gtk/gtkhbox.h>
-#include <gtk/gtkiconfactory.h>
-#include <gtk/gtkicontheme.h>
-#include <gtk/gtkimage.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkradiobutton.h>
-#include <gtk/gtkstock.h>
-#include <gtk/gtkvbox.h>
-
-#include "fusa-user-menu-item.h"
-
-
-/* **************** *
- *  Private Macros  *
- * **************** */
-
-#define DEFAULT_ICON_SIZE		24
-#define CLOSE_ENOUGH_SIZE		2
-
-
-/* ********************** *
- *  Private Enumerations  *
- * ********************** */
-
-enum
-{
-  PROP_0,
-  PROP_USER,
-  PROP_ICON_SIZE
-};
-
-
-/* ******************** *
- *  Private Structures  *
- * ******************** */
-  
-struct _FusaUserMenuItem
-{
-  GtkImageMenuItem parent;
-
-  FusaUser *user;
-
-  GtkWidget *image;
-  GtkWidget *label;
-
-  gulong user_notify_id;
-  gulong user_icon_changed_id;
-  gulong user_displays_changed_id;
-  gint icon_size;
-};
-
-struct _FusaUserMenuItemClass
-{
-  GtkImageMenuItemClass parent_class;
-};
-
-
-/* ********************* *
- *  Function Prototypes  *
- * ********************* */
-
-/* GObject Functions */
-static void     fusa_user_menu_item_set_property  (GObject        *object,
-						   guint           param_id,
-						   const GValue   *value,
-						   GParamSpec     *pspec);
-static void     fusa_user_menu_item_get_property  (GObject        *object,
-						   guint           param_id,
-						   GValue         *value,
-						   GParamSpec     *pspec);
-static void     fusa_user_menu_item_finalize      (GObject        *object);
-
-static gboolean fusa_user_menu_item_expose_event  (GtkWidget      *widget,
-						   GdkEventExpose *event);
-static void     fusa_user_menu_item_size_request  (GtkWidget      *widget,
-						   GtkRequisition *req);
-
-/* FusaUser Callbacks */
-static void user_notify_cb            (GObject    *object,
-				       GParamSpec *pspec,
-				       gpointer    data);
-static void user_icon_changed_cb      (FusaUser   *user,
-				       gpointer    data);
-static void user_displays_changed_cb  (FusaUser   *user,
-				       gpointer    data);
-static void user_weak_notify          (gpointer    data,
-				       GObject    *user_ptr);
-
-/* Widget Callbacks */
-static void image_style_set_cb (GtkWidget *widget,
-				GtkStyle  *old_style,
-				gpointer   data);
-static void label_style_set_cb (GtkWidget *widget,
-				GtkStyle  *old_style,
-				gpointer   data);
-
-/* Utility Functions */
-static void reset_label     (FusaUserMenuItem *item);
-static void reset_icon      (FusaUserMenuItem *item);
-
-
-/* ******************* *
- *  GType Declaration  *
- * ******************* */
-
-G_DEFINE_TYPE (FusaUserMenuItem, fusa_user_menu_item, GTK_TYPE_IMAGE_MENU_ITEM);
-
-
-/* ***************** *
- *  GType Functions  *
- * ***************** */
-
-static void
-fusa_user_menu_item_class_init (FusaUserMenuItemClass *class)
-{
-  GObjectClass *gobject_class;
-  GtkWidgetClass *widget_class;
-
-  gobject_class = G_OBJECT_CLASS (class);
-  widget_class = GTK_WIDGET_CLASS (class);
-
-  gobject_class->set_property = fusa_user_menu_item_set_property;
-  gobject_class->get_property = fusa_user_menu_item_get_property;
-  gobject_class->finalize = fusa_user_menu_item_finalize;
-
-  widget_class->size_request = fusa_user_menu_item_size_request;
-  widget_class->expose_event = fusa_user_menu_item_expose_event;
-
-  g_object_class_install_property (gobject_class,
-				   PROP_USER,
-				   g_param_spec_object ("user",
-							_("User"),
-							_("The user this menu item represents."),
-							FUSA_TYPE_USER,
-							(G_PARAM_READWRITE |
-							 G_PARAM_CONSTRUCT_ONLY)));
-  g_object_class_install_property (gobject_class,
-				   PROP_ICON_SIZE,
-				   g_param_spec_int ("icon-size",
-						     _("Icon Size"),
-						     _("The size of the icon to use."),
-						     12, G_MAXINT, DEFAULT_ICON_SIZE,
-						     G_PARAM_READWRITE));
-
-  gtk_widget_class_install_style_property (widget_class,
-                                           g_param_spec_int ("indicator-size",
-                                                             _("Indicator Size"),
-                                                             _("Size of check indicator"),
-                                                             0, G_MAXINT, 12,
-                                                             G_PARAM_READABLE));
-  gtk_widget_class_install_style_property (widget_class,
-                                           g_param_spec_int ("indicator-spacing",
-                                                             _("Indicator Spacing"),
-                                                             _("Space between the username and the indicator"),
-                                                             0, G_MAXINT, 8,
-                                                             G_PARAM_READABLE));
-}
-
-static void
-fusa_user_menu_item_init (FusaUserMenuItem *item)
-{
-  GtkWidget *box;
-
-  item->icon_size = DEFAULT_ICON_SIZE;
-
-  item->image = gtk_image_new ();
-  g_signal_connect (item->image, "style-set",
-		    G_CALLBACK (image_style_set_cb), item);
-  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
-				 item->image);
-  gtk_widget_show (item->image);
-
-  box = gtk_hbox_new (FALSE, 12);
-  gtk_container_add (GTK_CONTAINER (item), box);
-  gtk_widget_show (box);
-
-  item->label = gtk_label_new (NULL);
-  gtk_label_set_use_markup (GTK_LABEL (item->label), TRUE);
-  gtk_misc_set_alignment (GTK_MISC (item->label), 0.0, 0.5);
-  g_signal_connect (item->label, "style-set",
-		    G_CALLBACK (label_style_set_cb), item);
-  gtk_container_add (GTK_CONTAINER (box), item->label);
-  gtk_widget_show (item->label);
-}
-
-
-/* ******************* *
- *  GObject Functions  *
- * ******************* */
-
-static void
-fusa_user_menu_item_set_property (GObject      *object,
-				  guint         param_id,
-				  const GValue *value,
-				  GParamSpec   *pspec)
-{
-  FusaUserMenuItem *item;
-
-  item = FUSA_USER_MENU_ITEM (object);
-
-  switch (param_id)
-    {
-    case PROP_USER:
-      item->user = g_value_get_object (value);
-      g_object_weak_ref (G_OBJECT (item->user), user_weak_notify, item);
-      item->user_notify_id =
-	g_signal_connect (item->user, "notify",
-			  G_CALLBACK (user_notify_cb), item);
-      item->user_icon_changed_id =
-	g_signal_connect (item->user, "icon-changed",
-			  G_CALLBACK (user_icon_changed_cb), item);
-      item->user_displays_changed_id =
-	g_signal_connect (item->user, "displays-changed",
-			  G_CALLBACK (user_displays_changed_cb), item);
-
-      if (gtk_widget_get_style (GTK_WIDGET (object)))
-	{
-	  reset_icon (item);
-	  reset_label (item);
-	}
-      break;
-    case PROP_ICON_SIZE:
-      fusa_user_menu_item_set_icon_size (item, g_value_get_int (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    }
-}
-
-static void
-fusa_user_menu_item_get_property (GObject    *object,
-				  guint       param_id,
-				  GValue     *value,
-				  GParamSpec *pspec)
-{
-  FusaUserMenuItem *item;
-
-  item = FUSA_USER_MENU_ITEM (object);
-
-  switch (param_id)
-    {
-    case PROP_USER:
-      g_value_set_object (value, item->user);
-      break;
-    case PROP_ICON_SIZE:
-      g_value_set_int (value, item->icon_size);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    }
-}
-
-static void
-fusa_user_menu_item_finalize (GObject *object)
-{
-  FusaUserMenuItem *item;
-
-  item = FUSA_USER_MENU_ITEM (object);
-
-  if (item->user)
-    {
-      g_signal_handler_disconnect (item->user, item->user_notify_id);
-      g_signal_handler_disconnect (item->user, item->user_icon_changed_id);
-      g_signal_handler_disconnect (item->user, item->user_displays_changed_id);
-      g_object_weak_unref (G_OBJECT (item->user), user_weak_notify, object);
-    }
-
-  if (G_OBJECT_CLASS (fusa_user_menu_item_parent_class)->finalize)
-    (*G_OBJECT_CLASS (fusa_user_menu_item_parent_class)->finalize) (object);
-}
-
-
-static gboolean
-fusa_user_menu_item_expose_event (GtkWidget      *widget,
-				  GdkEventExpose *event)
-{
-  gboolean retval;
-
-  if (GTK_WIDGET_CLASS (fusa_user_menu_item_parent_class)->expose_event)
-    retval = (*GTK_WIDGET_CLASS (fusa_user_menu_item_parent_class)->expose_event) (widget,
-										   event);
-  else
-    retval = TRUE;
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      gint horizontal_padding,
-           indicator_size,
-           indicator_spacing,
-	   offset,
-	   x,
-	   y;
-      GtkShadowType shadow_type;
-
-      horizontal_padding = 0;
-      indicator_size = 0;
-      indicator_spacing = 0;
-      gtk_widget_style_get (widget,
- 			    "horizontal-padding", &horizontal_padding,
-			    "indicator-size", &indicator_size,
-			    "indicator-spacing", &indicator_spacing,
-			    NULL);
-
-      offset = GTK_CONTAINER (widget)->border_width + widget->style->xthickness + 2; 
-
-      if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
-	{
-	  x = widget->allocation.x + widget->allocation.width -
-	    offset - horizontal_padding - indicator_size + indicator_spacing +
-	    (indicator_size - indicator_spacing - indicator_size) / 2;
-	}
-      else 
-	{
-	  x = widget->allocation.x + offset + horizontal_padding +
-	    (indicator_size - indicator_spacing - indicator_size) / 2;
-	}
-      
-      y = widget->allocation.y + (widget->allocation.height - indicator_size) / 2;
-
-      if (fusa_user_get_n_displays (FUSA_USER_MENU_ITEM (widget)->user) > 0)
-        shadow_type = GTK_SHADOW_IN; /* they have displays, so mark it checked */
-      else
-        shadow_type = GTK_SHADOW_OUT; /* they haave no displays, so no check */
-
-      gtk_paint_check (widget->style, widget->window, GTK_WIDGET_STATE (widget),
-		       shadow_type, &(event->area), widget, "check",
-		       x, y, indicator_size, indicator_size);
-    }
-
-  return TRUE;
-}
-
-static void
-fusa_user_menu_item_size_request (GtkWidget      *widget,
-				  GtkRequisition *req)
-{
-  gint indicator_size,
-       indicator_spacing;
-
-  if (GTK_WIDGET_CLASS (fusa_user_menu_item_parent_class)->size_request)
-    (*GTK_WIDGET_CLASS (fusa_user_menu_item_parent_class)->size_request) (widget,
-									  req);
-
-  indicator_size = 0;
-  indicator_spacing = 0;
-  gtk_widget_style_get (widget,
-		        "indicator-size", &indicator_size,
-			"indicator-spacing", &indicator_spacing,
-			NULL);
-  req->width += indicator_size + indicator_spacing;
-}
-
-
-/* ******************** *
- *  FusaUser Callbacks  *
- * ******************** */
-
-static void
-user_notify_cb (GObject    *object,
-		GParamSpec *pspec,
-		gpointer    data)
-{
-  if (!pspec || !pspec->name)
-    return;
-
-  if (strcmp (pspec->name, "user-name") == 0 ||
-      strcmp (pspec->name, "display-name") == 0)
-    reset_label (data);
-}
-
-static void
-user_icon_changed_cb (FusaUser *user,
-		      gpointer  data)
-{
-  if (gtk_widget_has_screen (data))
-    reset_icon (data);
-}
-
-static void
-user_displays_changed_cb (FusaUser *user,
-			  gpointer  data)
-{
-  if (fusa_user_get_uid (user) == getuid ())
-    gtk_widget_set_sensitive (data, (fusa_user_get_n_displays (user) > 1));
-}
-
-static void
-user_weak_notify (gpointer  data,
-		  GObject  *user_ptr)
-{
-  FUSA_USER_MENU_ITEM (data)->user = NULL;
-
-  gtk_widget_destroy (data);
-}
-
-
-/* ****************** *
- *  Widget Callbacks  *
- * ****************** */
-
-static void
-image_style_set_cb (GtkWidget *widget,
-		    GtkStyle  *old_style,
-		    gpointer   data)
-{
-  reset_icon (data);
-}
-
-static void
-label_style_set_cb (GtkWidget *widget,
-		    GtkStyle  *old_style,
-		    gpointer   data)
-{
-  reset_label (data);
-}
-
-
-/* ******************* *
- *  Utility Functions  *
- * ******************* */
-
-static void
-reset_label (FusaUserMenuItem *item)
-{
-#if 0
-  gchar *text;
-  PangoLayout *layout;
-  gint height;
-#endif
-
-  if (!item->user)
-    return;
-
-#if 0
-  text = g_strconcat ("<b>",
-		      fusa_user_get_display_name (item->user),
-		      "</b>\n",
-		      "<small>",
-		      fusa_user_get_user_name (item->user),
-		      "</small>",
-		      NULL);
-
-  gtk_label_set_markup (GTK_LABEL (item->label), text);
-  g_free (text);
-
-  /* This next bit accounts for 20% of the memorytime.
-   * I have therefore commented out this whole part for now. */
-  layout = gtk_label_get_layout (GTK_LABEL (item->label));
-  pango_layout_get_pixel_size (layout, NULL, &height);
-
-  if (height > (item->icon_size + CLOSE_ENOUGH_SIZE))
-#endif
-    gtk_label_set_markup (GTK_LABEL (item->label),
-			  fusa_user_get_display_name (item->user));
-}
-
-static void
-reset_icon (FusaUserMenuItem *item)
-{
-  GdkPixbuf *pixbuf;
-
-  if (!item->user || !gtk_widget_has_screen (GTK_WIDGET (item)))
-    return;
-
-  g_assert (item->icon_size != 0);
-
-  pixbuf = fusa_user_render_icon (item->user, GTK_WIDGET (item),
-				  item->icon_size);
-  gtk_image_set_from_pixbuf (GTK_IMAGE (item->image), pixbuf);
-  g_object_unref (pixbuf);
-}
-
-
-/* ************************************************************************** *
- *  Public API                                                                *
- * ************************************************************************** */
-
-GtkWidget *
-fusa_user_menu_item_new (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-
-  return g_object_new (FUSA_TYPE_USER_MENU_ITEM, "user", user, NULL);
-}
-
-FusaUser *
-fusa_user_menu_item_get_user (FusaUserMenuItem *item)
-{
-  g_return_val_if_fail (FUSA_IS_USER_MENU_ITEM (item), NULL);
-
-  return item->user;
-}
-
-gint
-fusa_user_menu_item_get_icon_size (FusaUserMenuItem *item)
-{
-  g_return_val_if_fail (FUSA_IS_USER_MENU_ITEM (item), -1);
-
-  return item->icon_size;
-}
-
-void
-fusa_user_menu_item_set_icon_size (FusaUserMenuItem *item,
-				   gint              pixel_size)
-{
-  g_return_if_fail (FUSA_IS_USER_MENU_ITEM (item));
-  g_return_if_fail (pixel_size != 0);
-
-  if (pixel_size < 0)
-    item->icon_size = DEFAULT_ICON_SIZE;
-  else
-    item->icon_size = pixel_size;
-
-  if (gtk_widget_get_style (GTK_WIDGET (item)))
-    {
-      reset_icon (item);
-      reset_label (item);
-    }
-  g_object_notify (G_OBJECT (item), "icon-size");
-}
Index: src/cut-n-paste/fusa-user.c
===================================================================
--- src/cut-n-paste/fusa-user.c	(revision 1096)
+++ src/cut-n-paste/fusa-user.c	(working copy)
@@ -1,725 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-user.c
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <config.h>
-
-#include <glib/gi18n.h>
-
-#include <string.h>
-
-#include <gtk/gtkicontheme.h>
-
-#include "fusa-manager-private.h"
-#include "fusa-user-private.h"
-
-
-/* **************** *
- *  Private Macros  *
- * **************** */
-
-#define FUSA_USER_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), FUSA_TYPE_USER, FusaUserClass))
-#define FUSA_IS_USER_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), FUSA_TYPE_USER))
-#define FUSA_USER_GET_CLASS(object) \
-  (G_TYPE_INSTANCE_GET_CLASS ((object), FUSA_TYPE_USER, FusaUserClass))
-
-
-/* ********************** *
- *  Private Enumerations  *
- * ********************** */
-
-enum
-{
-  PROP_0,
-  PROP_MANAGER,
-  PROP_DISPLAY_NAME,
-  PROP_USER_NAME,
-  PROP_UID,
-  PROP_HOME_DIR,
-  PROP_SHELL,
-  PROP_DISPLAYS
-};
-
-enum
-{
-  ICON_CHANGED,
-  DISPLAYS_CHANGED,
-  LAST_SIGNAL
-};
-
-
-/* ******************** *
- *  Private Structures  *
- * ******************** */
-
-struct _FusaUser
-{
-  GObject parent;
-
-  FusaManager *manager;
-
-  uid_t uid;
-  gchar *username;
-  gchar *display_name;
-  gchar *home_dir;
-  gchar *shell;
-
-  GSList *displays;
-};
-
-typedef struct _FusaUserClass
-{
-  GObjectClass parent_class;
-
-  void (*icon_changed)     (FusaUser *user);
-  void (*displays_changed) (FusaUser *user);
-}
-FusaUserClass;
-
-
-/* ********************* *
- *  Function Prototypes  *
- * ********************* */
-
-/* GObject Functions */
-static void fusa_user_set_property (GObject      *object,
-				    guint         param_id,
-				    const GValue *value,
-				    GParamSpec   *pspec);
-static void fusa_user_get_property (GObject      *object,
-				    guint         param_id,
-				    GValue       *value,
-				    GParamSpec   *pspec);
-static void fusa_user_finalize     (GObject      *object);
-
-/* Utility Functions */
-static void display_weak_notify (gpointer  data,
-				 GObject  *old_display);
-
-
-/* ****************** *
- *  Global Variables  *
- * ****************** */
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-
-/* ******************* *
- *  GType Declaration  *
- * ******************* */
-
-G_DEFINE_TYPE (FusaUser, fusa_user, G_TYPE_OBJECT);
-
-
-/* ********************** *
- *  GType Initialization  *
- * ********************** */
-
-static void
-fusa_user_class_init (FusaUserClass *class)
-{
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS (class);
-
-  gobject_class->set_property = fusa_user_set_property;
-  gobject_class->get_property = fusa_user_get_property;
-  gobject_class->finalize = fusa_user_finalize;
-
-  g_object_class_install_property (gobject_class,
-				   PROP_MANAGER,
-				   g_param_spec_object ("manager",
-							_("Manager"),
-							_("The user manager object this user is controlled by."),
-							FUSA_TYPE_MANAGER,
-							(G_PARAM_READWRITE |
-							 G_PARAM_CONSTRUCT_ONLY)));
-
-  g_object_class_install_property (gobject_class,
-				   PROP_DISPLAY_NAME,
-				   g_param_spec_string ("display-name",
-							"Display Name",
-							"The user-friendly name to display for this user.",
-							NULL,
-							G_PARAM_READABLE));
-
-  g_object_class_install_property (gobject_class,
-				   PROP_UID,
-				   g_param_spec_ulong ("uid",
-						       "User ID",
-						       "The UID for this user.",
-						       0, G_MAXULONG, 0,
-						       G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-				   PROP_USER_NAME,
-				   g_param_spec_string ("user-name",
-							"User Name",
-							"The login name for this user.",
-							NULL,
-							G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-				   PROP_HOME_DIR,
-				   g_param_spec_string ("home-directory",
-							"Home Directory",
-							"The home directory for this user.",
-							NULL,
-							G_PARAM_READABLE));
-  g_object_class_install_property (gobject_class,
-				   PROP_SHELL,
-				   g_param_spec_string ("shell",
-							"Shell",
-							"The shell for this user.",
-							NULL,
-							G_PARAM_READABLE));
-
-  signals[ICON_CHANGED] =
-    g_signal_new ("icon-changed",
-		  G_TYPE_FROM_CLASS (class),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (FusaUserClass, icon_changed),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
-  signals[DISPLAYS_CHANGED] =
-    g_signal_new ("displays-changed",
-		  G_TYPE_FROM_CLASS (class),
-		  G_SIGNAL_RUN_LAST,
-		  G_STRUCT_OFFSET (FusaUserClass, displays_changed),
-		  NULL, NULL,
-		  g_cclosure_marshal_VOID__VOID,
-		  G_TYPE_NONE, 0);
-}
-
-static void
-fusa_user_init (FusaUser *user)
-{
-  user->manager = NULL;
-  user->username = NULL;
-  user->display_name = NULL;
-  user->displays = NULL;
-}
-
-
-/* ******************* *
- *  GObject Functions  *
- * ******************* */
-
-static void
-fusa_user_set_property (GObject      *object,
-			guint         param_id,
-			const GValue *value,
-			GParamSpec   *pspec)
-{
-  FusaUser *user;
-
-  user = FUSA_USER (object);
-
-  switch (param_id)
-    {
-    case PROP_MANAGER:
-      user->manager = g_value_get_object (value);
-      g_assert (user->manager);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    }
-}
-
-static void
-fusa_user_get_property (GObject    *object,
-			guint       param_id,
-			GValue     *value,
-			GParamSpec *pspec)
-{
-  FusaUser *user;
-
-  user = FUSA_USER (object);
-
-  switch (param_id)
-    {
-    case PROP_MANAGER:
-      g_value_set_object (value, user->manager);
-      break;
-    case PROP_USER_NAME:
-      g_value_set_string (value, user->username);
-      break;
-    case PROP_DISPLAY_NAME:
-      g_value_set_string (value, user->display_name);
-      break;
-    case PROP_HOME_DIR:
-      g_value_set_string (value, user->home_dir);
-      break;
-    case PROP_UID:
-      g_value_set_ulong (value, user->uid);
-      break;
-    case PROP_SHELL:
-      g_value_set_string (value, user->shell);
-      break;
-    case PROP_DISPLAYS:
-      if (user->displays)
-	{
-	  GValueArray *ar;
-	  GSList *list;
-	  GValue tmp = { 0 };
-
-	  ar = g_value_array_new (g_slist_length (user->displays));
-	  g_value_init (&tmp, FUSA_TYPE_DISPLAY);
-	  for (list = user->displays; list; list = list->next)
-	    {
-	      g_value_set_object (&tmp, list->data);
-	      g_value_array_append (ar, &tmp);
-	      g_value_reset (&tmp);
-	    }
-
-	  g_value_take_boxed (value, ar);
-	}
-      else
-	g_value_set_boxed (value, NULL);
-      break;
-
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-    }
-}
-
-static void
-fusa_user_finalize (GObject *object)
-{
-  FusaUser *user;
-
-  user = FUSA_USER (object);
-
-  g_free (user->username);
-  g_free (user->display_name);
-
-  while (user->displays)
-    {
-      g_object_weak_unref (G_OBJECT (user->displays->data), display_weak_notify,
-			   user);
-      user->displays = g_slist_delete_link (user->displays, user->displays);
-    }
-
-
-  if (G_OBJECT_CLASS (fusa_user_parent_class)->finalize)
-    (*G_OBJECT_CLASS (fusa_user_parent_class)->finalize) (object);
-}
-
-/* ******************* *
- *  Utility Functions  *
- * ******************* */
-
-static void
-display_weak_notify (gpointer  user_data,
-		     GObject  *old_display)
-{
-  FusaUser *user;
-
-  user = FUSA_USER (user_data);
-
-  user->displays = g_slist_delete_link (user->displays,
-					g_slist_find (user->displays,
-						      old_display));
-  g_signal_emit (user, signals[DISPLAYS_CHANGED], 0);
-}
-
-
-/* ************************************************************************** *
- *  Semi-Private API                                                          *
- * ************************************************************************** */
-
-/**
- * _fusa_user_update:
- * @user: the user object to update.
- * @pwent: the user data to use.
- * 
- * Updates the properties of @user using the data in @pwent.
- * 
- * Since: 1.0
- **/
-void
-_fusa_user_update (FusaUser            *user,
-		   const struct passwd *pwent)
-{
-  gchar *display_name;
-
-  g_return_if_fail (FUSA_IS_USER (user));
-  g_return_if_fail (pwent != NULL);
-
-  g_object_freeze_notify (G_OBJECT (user));
-
-  /* Display Name */
-  if (pwent->pw_gecos && pwent->pw_gecos[0] != '\0')
-    {
-      gchar *first_comma;
-
-      first_comma = strchr (pwent->pw_gecos, ',');
-      if (first_comma)
-	display_name = g_strndup (pwent->pw_gecos,
-				  (first_comma - pwent->pw_gecos));
-      else
-	display_name = g_strdup (pwent->pw_gecos);
-
-      if (display_name[0] == '\0')
-	{
-	  g_free (display_name);
-	  display_name = NULL;
-	}
-    }
-  else
-    display_name = NULL;
-
-  if ((display_name && !user->display_name) ||
-      (!display_name && user->display_name) ||
-      (display_name &&
-       user->display_name &&
-       strcmp (display_name, user->display_name) != 0))
-    {
-      g_free (user->display_name);
-      user->display_name = display_name;
-      g_object_notify (G_OBJECT (user), "display-name");
-    }
-  else
-    g_free (display_name);
-
-  /* UID */
-  if (pwent->pw_uid != user->uid)
-    {
-      user->uid = pwent->pw_uid;
-      g_object_notify (G_OBJECT (user), "uid");
-    }
-
-  /* Username */
-  if ((pwent->pw_name && !user->username) ||
-      (!pwent->pw_name && user->username) ||
-      (pwent->pw_name &&
-       user->username &&
-       strcmp (user->username, pwent->pw_name) != 0))
-    {
-      g_free (user->username);
-      user->username = g_strdup (pwent->pw_name);
-      g_object_notify (G_OBJECT (user), "user-name");
-    }
-
-  /* Home Directory */
-  if ((pwent->pw_dir && !user->home_dir) ||
-      (!pwent->pw_dir && user->home_dir) ||
-      strcmp (user->home_dir, pwent->pw_dir) != 0)
-    {
-      g_free (user->home_dir);
-      user->home_dir = g_strdup (pwent->pw_dir);
-      g_object_notify (G_OBJECT (user), "home-directory");
-      g_signal_emit (user, signals[ICON_CHANGED], 0);
-    }
-
-  /* Shell */
-  if ((pwent->pw_shell && !user->shell) ||
-      (!pwent->pw_shell && user->shell) ||
-      (pwent->pw_shell &&
-       user->shell &&
-       strcmp (user->shell, pwent->pw_shell) != 0))
-    {
-      g_free (user->shell);
-      user->shell = g_strdup (pwent->pw_shell);
-      g_object_notify (G_OBJECT (user), "shell");
-    }
-
-  g_object_thaw_notify (G_OBJECT (user));
-}
-
-/**
- * _fusa_user_add_display:
- * @user: the user to modify.
- * @display: the virtual terminal to add.
- * 
- * Adds @display to the list of terminals @user is logged in on, and emits the
- * "displays-changed" signal, if necessary.
- * 
- * Since: 1.0
- **/
-void
-_fusa_user_add_display (FusaUser *user,
-		        FusaDisplay   *display)
-{
-  g_return_if_fail (FUSA_IS_USER (user));
-  g_return_if_fail (FUSA_IS_DISPLAY (display));
-
-  if (!g_slist_find (user->displays, display))
-    {
-      g_object_weak_ref (G_OBJECT (display), display_weak_notify, user);
-      user->displays = g_slist_append (user->displays, display);
-      g_signal_emit (user, signals[DISPLAYS_CHANGED], 0);
-    }
-}
-
-/**
- * _fusa_user_remove_display:
- * @user: the user to modify.
- * @display: the virtual terminal to remove.
- * 
- * Removes @display from the list of terminals @user is logged in on, and emits the
- * "displays-changed" signal, if necessary.
- * 
- * Since: 1.0
- **/
-void
-_fusa_user_remove_display (FusaUser *user,
-			   FusaDisplay   *display)
-{
-  GSList *li;
-
-  g_return_if_fail (FUSA_IS_USER (user));
-  g_return_if_fail (FUSA_IS_DISPLAY (display));
-
-  li = g_slist_find (user->displays, display);
-  if (li)
-    {
-      g_object_weak_unref (G_OBJECT (display), display_weak_notify, user);
-      user->displays = g_slist_delete_link (user->displays, li);
-      g_signal_emit (user, signals[DISPLAYS_CHANGED], 0);
-    }
-}
-
-/**
- * _fusa_user_icon_changed:
- * @user: the user to emit the signal for.
- * 
- * Emits the "icon-changed" signal for @user.
- * 
- * Since: 1.0
- **/
-void
-_fusa_user_icon_changed (FusaUser *user)
-{
-  g_return_if_fail (FUSA_IS_USER (user));
-
-  g_signal_emit (user, signals[ICON_CHANGED], 0);
-}
-
-
-/* ************************************************************************** *
- *  Public API                                                                *
- * ************************************************************************** */
-
-/**
- * fusa_user_get_uid:
- * @user: the user object to examine.
- * 
- * Retrieves the ID of @user.
- * 
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- * 
- * Since: 1.0
- **/
-
-uid_t
-fusa_user_get_uid (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), -1);
-
-  return user->uid;
-}
-
-/**
- * fusa_user_get_display_name:
- * @user: the user object to examine.
- * 
- * Retrieves the display name of @user.
- * 
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- * 
- * Since: 1.0
- **/
-G_CONST_RETURN gchar *
-fusa_user_get_display_name (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-
-  return (user->display_name ? user->display_name : user->username);
-}
-
-/**
- * fusa_user_get_user_name:
- * @user: the user object to examine.
- * 
- * Retrieves the login name of @user.
- * 
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- * 
- * Since: 1.0
- **/
-
-G_CONST_RETURN gchar *
-fusa_user_get_user_name (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-
-  return user->username;
-}
-
-/**
- * fusa_user_get_home_directory:
- * @user: the user object to examine.
- * 
- * Retrieves the home directory of @user.
- * 
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- * 
- * Since: 1.0
- **/
-
-G_CONST_RETURN gchar *
-fusa_user_get_home_directory (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-
-  return user->home_dir;
-}
-
-/**
- * fusa_user_get_shell:
- * @user: the user object to examine.
- * 
- * Retrieves the login shell of @user.
- * 
- * Returns: a pointer to an array of characters which must not be modified or
- *  freed, or %NULL.
- * 
- * Since: 1.0
- **/
-
-G_CONST_RETURN gchar *
-fusa_user_get_shell (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-
-  return user->shell;
-}
-
-/**
- * fusa_user_get_displays:
- * @user: the user object to examine.
- * 
- * Retrieves a new list of the displays that @user is logged in on. The list
- * itself must be freed with g_slist_free() when no longer needed.
- * 
- * Returns: a list of #FusaDisplay objects which must be freed with
- *  g_slist_free().
- * 
- * Since: 1.0
- **/
-GSList *
-fusa_user_get_displays (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-
-  return g_slist_copy (user->displays);
-}
-
-/**
- * fusa_user_get_n_displays:
- * @user: the user object to examine.
- * 
- * Retrieves the number of displays that @user is logged into.
- * 
- * Returns: an unsigned integer.
- * 
- * Since: 1.0
- **/
-guint
-fusa_user_get_n_displays (FusaUser *user)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), FALSE);
-
-  return g_slist_length (user->displays);
-}
-
-/**
- * fusa_user_render_icon:
- * @user: the user object to examine.
- * @widget: the intended destination widget.
- * @icon_size: the desired icon size.
- * @error: a pointer to a location to store errors while reading the icon.
- * 
- * Loads a copy of the face pixbuf for @user at @icon_size. If an error occurs,
- * %NULL will be returned and @error will be set, if @error is not %NULL.
- * 
- * Returns: a newly allocated #GdkPixbuf object, or %NULL.
- * 
- * Since: 1.0
- **/
-GdkPixbuf *
-fusa_user_render_icon (FusaUser  *user,
-		       GtkWidget *widget,
-		       gint       icon_size)
-{
-  g_return_val_if_fail (FUSA_IS_USER (user), NULL);
-  g_return_val_if_fail (widget == NULL || GTK_IS_WIDGET (widget), NULL);
-  g_return_val_if_fail (icon_size > 0, NULL);
-
-  return _fusa_manager_render_icon (user->manager, user, widget, icon_size);
-}
-
-gint
-fusa_user_collate (FusaUser *user1,
-		   FusaUser *user2)
-{
-  const gchar *str1, *str2;
-
-  g_return_val_if_fail (user1 == NULL || FUSA_IS_USER (user1), 0);
-  g_return_val_if_fail (user2 == NULL || FUSA_IS_USER (user2), 0);
-
-  if (!user1 && user2)
-    return -1;
-
-  if (user1 && !user2)
-    return 1;
-
-  if (!user1 && !user2)
-    return 0;
-
-  if (user1->display_name)
-    str1 = user1->display_name;
-  else
-    str1 = user1->username;
-
-  if (user2->display_name)
-    str2 = user2->display_name;
-  else
-    str2 = user2->username;
-
-  if (!str1 && str2)
-    return -1;
-
-  if (str1 && !str2)
-    return 1;
-
-  if (!str1 && !str2)
-    return 0;
-
-  return g_utf8_collate (str1, str2);
-}
Index: src/cut-n-paste/fusa-manager.h
===================================================================
--- src/cut-n-paste/fusa-manager.h	(revision 1096)
+++ src/cut-n-paste/fusa-manager.h	(working copy)
@@ -1,132 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-manager.h
- * 
- * Copyright (C) 2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Singleton object to manage FusaDisplay and FusaUser objects, and handle GDM
- * interaction/configs.
- */
-
-#ifndef __FUSA_MANAGER_H__
-#define __FUSA_MANAGER_H__ 1
-
-#include <gdk/gdkscreen.h>
-
-#include "fusa-display.h"
-#include "fusa-user.h"
-
-G_BEGIN_DECLS
-
-#define FUSA_TYPE_MANAGER \
-  (fusa_manager_get_type ())
-#define FUSA_MANAGER(object) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((object), FUSA_TYPE_MANAGER, FusaManager))
-#define FUSA_IS_MANAGER(object) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((object), FUSA_TYPE_MANAGER))
-
-#define FUSA_MANAGER_DM_ERROR \
-  (fusa_manager_dm_error_get_quark ())
-
-#define FUSA_MANAGER_SIGNAL_USER_ADDED \
-  "user-added"
-#define FUSA_MANAGER_SIGNAL_USER_REMOVED \
-  "user-removed"
-#define FUSA_MANAGER_SIGNAL_DISPLAY_ADDED \
-  "display-added"
-#define FUSA_MANAGER_SIGNAL_DISPLAY_REMOVED \
-  "display-removed"
-
-
-typedef enum
-{
-  FUSA_MANAGER_DM_ERROR_UNKNOWN               = -1,
-  FUSA_MANAGER_DM_ERROR_NOT_RUNNING           =  0,
-  FUSA_MANAGER_DM_ERROR_FLEXI_LIMIT_REACHED   =  1,
-  FUSA_MANAGER_DM_ERROR_X_ERROR               =  2,
-  FUSA_MANAGER_DM_ERROR_X_FAILED              =  3,
-  FUSA_MANAGER_DM_ERROR_X_LIMIT_REACHED       =  4,
-  FUSA_MANAGER_DM_ERROR_XNEST_AUTH_ERROR      =  5,
-  FUSA_MANAGER_DM_ERROR_X_NOT_FOUND           =  6,
-  FUSA_MANAGER_DM_ERROR_LOGOUT_ACTION         =  7,
-  FUSA_MANAGER_DM_ERROR_CONSOLES_UNSUPPORTED  =  8,
-  FUSA_MANAGER_DM_ERROR_INVALID_CONSOLE       =  9,
-  FUSA_MANAGER_DM_ERROR_UNKNOWN_CONFIG        =  50,
-  FUSA_MANAGER_DM_ERROR_PERMISSIONS           =  100,
-  FUSA_MANAGER_DM_ERROR_TOO_MANY_MESSAGES     =  200,
-  FUSA_MANAGER_DM_ERROR_OTHER                 = -2
-}
-FusaManagerDmError;
-
-typedef struct _FusaManager FusaManager;
-  
-typedef void (*FusaManagerDisplayCallback)      (FusaManager  *manager,
-						 FusaDisplay  *display,
-						 const GError *error,
-						 gpointer      data);
-
-GType        fusa_manager_get_type              (void) G_GNUC_CONST;
-
-FusaManager *fusa_manager_ref_default           (void);
-
-/* Users */
-GSList      *fusa_manager_list_users            (FusaManager *manager);
-FusaUser    *fusa_manager_get_user              (FusaManager *manager,
-						 const gchar *name);
-FusaUser    *fusa_manager_get_user_by_uid       (FusaManager *manager,
-						 uid_t        uid);
-
-/* Displays */
-GSList      *fusa_manager_list_displays         (FusaManager *manager);
-FusaDisplay *fusa_manager_get_display           (FusaManager *manager,
-						 const gchar *name);
-FusaDisplay *fusa_manager_get_display_by_screen (FusaManager *manager,
-						 GdkScreen   *screen);
-
-/* Methods */
-void         fusa_manager_activate_display      (FusaManager                *manager,
-						 FusaDisplay                *display,
-						 GdkScreen                  *screen,
-						 FusaManagerDisplayCallback  func,
-						 gpointer                    data,
-						 GDestroyNotify              notify);
-void         fusa_manager_new_console           (FusaManager                *manager,
-						 GdkScreen                  *screen,
-						 FusaUser                   *user,
-						 FusaManagerDisplayCallback  func,
-						 gpointer                    data,
-						 GDestroyNotify              notify);
-void         fusa_manager_new_xnest             (FusaManager                *manager,
-						 GdkScreen                  *screen,
-						 FusaUser                   *user,
-						 FusaManagerDisplayCallback  func,
-						 gpointer                    data,
-						 GDestroyNotify              notify);
-
-/* Errors */
-GQuark       fusa_manager_dm_error_get_quark    (void) G_GNUC_CONST;
-
-/* Class methods */
-void
-fusa_manager_request_update_displays (FusaManager *manager,
-    FusaManagerDisplayCallback callback,
-    gpointer *data);
-
-G_END_DECLS
-
-#endif /* !__FUSA_MANAGER_H__ */
Index: src/cut-n-paste/fusa-user-menu-item.h
===================================================================
--- src/cut-n-paste/fusa-user-menu-item.h	(revision 1096)
+++ src/cut-n-paste/fusa-user-menu-item.h	(working copy)
@@ -1,62 +0,0 @@
-/*
- * Fast User Switch Applet: fusa-user-menu-item.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * A menu item bound to a FusaUser.
- */
-
-#ifndef __FUSA_USER_MENU_ITEM__
-#define __FUSA_USER_MENU_ITEM__ 1
-
-#include <gtk/gtkimagemenuitem.h>
-
-#include "fusa-user.h"
-
-G_BEGIN_DECLS
-
-#define FUSA_TYPE_USER_MENU_ITEM \
-  (fusa_user_menu_item_get_type ())
-#define FUSA_USER_MENU_ITEM(object) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((object), FUSA_TYPE_USER_MENU_ITEM, FusaUserMenuItem))
-#define FUSA_USER_MENU_ITEM_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_CAST ((klass), FUSA_TYPE_USER_MENU_ITEM, FusaUserMenuItemClass))
-#define FUSA_IS_USER_MENU_ITEM(object) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((object), FUSA_TYPE_USER_MENU_ITEM))
-#define FUSA_IS_USER_MENU_ITEM_CLASS(klass) \
-  (G_TYPE_CHECK_CLASS_TYPE ((klass), FUSA_TYPE_USER_MENU_ITEM))
-#define FUSA_USER_MENU_ITEM_GET_CLASS(object) \
-  (G_TYPE_INSTANCE_GET_CLASS ((object), FUSA_TYPE_USER_MENU_ITEM, FusaUserMenuItemClass))
-
-typedef struct _FusaUserMenuItem FusaUserMenuItem;
-typedef struct _FusaUserMenuItemClass FusaUserMenuItemClass;
-
-GType      fusa_user_menu_item_get_type      (void) G_GNUC_CONST;
-
-GtkWidget *fusa_user_menu_item_new           (FusaUser         *user);
-
-FusaUser  *fusa_user_menu_item_get_user      (FusaUserMenuItem *item);
-
-gint       fusa_user_menu_item_get_icon_size (FusaUserMenuItem *item);
-void       fusa_user_menu_item_set_icon_size (FusaUserMenuItem *item,
-					      gint              pixel_size);
-
-G_END_DECLS
-
-#endif /* !__FUSA_USER_MENU_ITEM__ */
Index: src/cut-n-paste/fusa-display-private.h
===================================================================
--- src/cut-n-paste/fusa-display-private.h	(revision 1096)
+++ src/cut-n-paste/fusa-display-private.h	(working copy)
@@ -1,42 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-display-private.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Private Interfaces to the FusaDisplay object
- */
-
-#ifndef __FUSA_DISPLAY_PRIVATE_H__
-#define __FUSA_DISPLAY_PRIVATE_H__ 1
-
-#include "fusa-manager.h"
-
-G_BEGIN_DECLS
-
-FusaDisplay *_fusa_display_new      (FusaManager *manager,
-				     const gchar *name,
-				     FusaUser    *user,
-				     gint         console,
-				     gboolean     nested);
-void         _fusa_display_set_user (FusaDisplay *display,
-				     FusaUser    *user);
-
-G_END_DECLS
-
-#endif /* !__FUSA_DISPLAY_PRIVATE_H__ */
Index: src/cut-n-paste/fusa-user.h
===================================================================
--- src/cut-n-paste/fusa-user.h	(revision 1096)
+++ src/cut-n-paste/fusa-user.h	(working copy)
@@ -1,63 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-user.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Facade object for user data, owned by FusaUserManager and updated by FusaVt
- */
-
-#ifndef __FUSA_USER__
-#define __FUSA_USER__ 1
-
-#include <sys/types.h>
-#include <gtk/gtkwidget.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-G_BEGIN_DECLS
-
-#define FUSA_TYPE_USER \
-  (fusa_user_get_type ())
-#define FUSA_USER(object) \
-  (G_TYPE_CHECK_INSTANCE_CAST ((object), FUSA_TYPE_USER, FusaUser))
-#define FUSA_IS_USER(object) \
-  (G_TYPE_CHECK_INSTANCE_TYPE ((object), FUSA_TYPE_USER))
-
-typedef struct _FusaUser FusaUser;
-
-GType                 fusa_user_get_type         (void) G_GNUC_CONST;
-
-uid_t		      fusa_user_get_uid            (FusaUser   *user);
-G_CONST_RETURN gchar *fusa_user_get_user_name      (FusaUser   *user);
-G_CONST_RETURN gchar *fusa_user_get_display_name   (FusaUser   *user);
-G_CONST_RETURN gchar *fusa_user_get_home_directory (FusaUser   *user);
-G_CONST_RETURN gchar *fusa_user_get_shell          (FusaUser   *user);
-
-GSList               *fusa_user_get_displays       (FusaUser   *user);
-guint                 fusa_user_get_n_displays     (FusaUser   *user);
-
-GdkPixbuf            *fusa_user_render_icon        (FusaUser   *user,
-						    GtkWidget  *widget,
-						    gint        icon_size);
-
-gint                  fusa_user_collate            (FusaUser   *user1,
-						    FusaUser   *user2);
-
-G_END_DECLS
-
-#endif /* !__FUSA_USER_MENU_ITEM__ */
Index: src/cut-n-paste/fusa-manager-private.h
===================================================================
--- src/cut-n-paste/fusa-manager-private.h	(revision 1096)
+++ src/cut-n-paste/fusa-manager-private.h	(working copy)
@@ -1,44 +0,0 @@
-/* 
- * Fast User-Switching Applet: fusa-manager-private.h
- * 
- * Copyright (C) 2004 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Private interfaces to the FusaManager object
- */
-
-#ifndef __FUSA_MANAGER_PRIVATE_H__
-#define __FUSA_MANAGER_PRIVATE_H__ 1
-
-#include <gdk-pixbuf/gdk-pixbuf.h>
-
-#include "fusa-manager.h"
-
-G_BEGIN_DECLS
-
-void       _fusa_manager_set_display (FusaManager *manager,
-				      FusaDisplay *display,
-				      GdkScreen   *screen);
-GdkPixbuf *_fusa_manager_render_icon (FusaManager *manager,
-				      FusaUser    *user,
-				      GtkWidget   *widget,
-				      gint         icon_size);
-
-G_END_DECLS
-
-#endif /* !__FUSA_MANAGER_PRIVATE_H__ */
Index: src/cut-n-paste/fusa-user-private.h
===================================================================
--- src/cut-n-paste/fusa-user-private.h	(revision 1096)
+++ src/cut-n-paste/fusa-user-private.h	(working copy)
@@ -1,47 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-user-private.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/*
- * Private interfaces to the FusaUser object
- */
-
-#ifndef __FUSA_USER_PRIVATE__
-#define __FUSA_USER_PRIVATE__ 1
-
-#include <pwd.h>
-
-#include "fusa-display.h"
-#include "fusa-user.h"
-
-G_BEGIN_DECLS
-
-void _fusa_user_update         (FusaUser            *user,
-				const struct passwd *pwent);
-
-void _fusa_user_add_display    (FusaUser            *user,
-				FusaDisplay         *display);
-void _fusa_user_remove_display (FusaUser            *user,
-				FusaDisplay         *display);
-
-void _fusa_user_icon_changed   (FusaUser            *user);
-
-G_END_DECLS
-
-#endif /* !__FUSA_USER_PRIVATE__ */
Index: src/cut-n-paste/Makefile.am
===================================================================
--- src/cut-n-paste/Makefile.am	(revision 1096)
+++ src/cut-n-paste/Makefile.am	(working copy)
@@ -1,35 +0,0 @@
-## Process this file with automake to produce makefile.in
-
-AUTOMAKE_OPTIONS = 1.7
-
-AM_CFLAGS =				\
-	$(WARNING_CFLAGS)
-
-MAINTAINERCLEANFILES =                  \
-	*~				\
-        Makefile.in
-
-noinst_LIBRARIES =			\
-	libfast-user-switch.a
-
-libfast_user_switch_a_CPPFLAGS =				\
-	-DDATADIR=\""$(datadir)"\"				\
-	-DG_LOG_DOMAIN=\""Screensaver-Fast-User-Switch"\"	\
-	$(FAST_USER_SWITCH_CFLAGS)
-
-libfast_user_switch_a_SOURCES =		\
-        fusa-user.h                     \
-        fusa-user-menu-item.h           \
-        fusa-user-private.h             \
-        fusa-display.h                  \
-        fusa-display-private.h          \
-	fusa-display.c			\
-        fusa-manager.h                  \
-        fusa-manager-private.h          \
-	fusa-manager.c			\
-	fusa-user.c			\
-	fusa-user-menu-item.c		\
-        fusa-utils.h                    \
-	fusa-utils.c			\
-        gdm-queue.h			\
-	gdm-queue.c
Index: src/cut-n-paste/gdm-queue.c
===================================================================
--- src/cut-n-paste/gdm-queue.c	(revision 1096)
+++ src/cut-n-paste/gdm-queue.c	(working copy)
@@ -1,624 +0,0 @@
-/*
- *    gdm-queue.h
- *    (c) 2006 Thomas Thurman
- *    Based originally on GDMcommunication routines
- *    (c)2001 Queen of England, (c)2002 George Lebl
- *    (c)2005 James M. Cape.
- *
- *    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
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <errno.h>
-#include <stdio.h>
-
-#include "gdm-queue.h"
-
-#include <X11/Xauth.h>
-
-/* You might have thought that we communicated with GDM using dbus or
- * bonobo or something spiffy like that. You'd be wrong! Instead, we
- * use a text-based command-response protocol over a Unix domain socket
- * which lives at a well-known position in the /tmp directory.
- * At some point, it will make sense to switch to something dbus-based.
- */
-#define GDM_SOCKET_FILENAME "/tmp/.gdm_socket"
-
-/* The old gdmcomm routines used to have individual minimum versions
- * for every particular GDM command, but then you have to deal with
- * the problem of what to do if you're running a version earlier than
- * the one you wanted. So we just have a blanket minimum for everything.
- */
-#define MINIMAL_GDM_VERSION      "2.8.0"
-
-/* Here's a useful macro to keep doing something even if we get EINTR
- * back (because the read or whatever was interrupted).
- *
- * From gdm2/vicious-extensions/ve-misc.h
- * Copyright (c) 2000 Eazel, Inc., (c) 2001,2002 George Lebl
- */
-#define VE_IGNORE_EINTR(expr) \
-  do {          \
-    errno = 0;  \
-    expr;               \
-  } while G_UNLIKELY (errno == EINTR);
-
-/* This is rather a one-off enum. ask_gdm() needs to keep track of
- * its current state, and these are the states it can be in:
- */
-typedef enum {
-  /* The socket is closed. */
-  GDM_SOCKET_CLOSED,
-  /* The socket is open, and we just sent the VERSION command
-   * (so we are expecting to get "GDM xxxx" back).
-   */
-  GDM_SOCKET_WAITING_FOR_VERSION,
-  /* The socket is open, and we just sent anything else. */
-  GDM_SOCKET_RUNNING_QUEUE,
-} GdmSocketStatus;
-
-/* This is one entry in the queue. */
-typedef struct {
-  /* The string to send to GDM.
-   * If this is NULL, GDM won't hear anything about this step, but the
-   * callback will be called anyway, just as if GDM had returned "OK"
-   * to something.
-   */
-  gchar *query;
-  /* The function to call with the result.
-   * If this is NULL, the result will be thrown away.
-  */
-  GdmMessageCallback *callback;
-  /* Arbitrary data to pass to the callback. */
-  gpointer data;
-} GdmRequest;
-
-/* The actual queue of instructions. */
-static GQueue *gdm_queue = NULL;
-/* The file descriptor of socket open on GDM_SOCKET_FILENAME. */
-static int gdm_socket = 0;
-/* The status, as described above. */
-static GdmSocketStatus gdm_socket_status = GDM_SOCKET_CLOSED;
-
-static void gdm_request_free (GdmRequest *victim);
-static gboolean gdm_run_queue (void *dummy);
-static int gdm_send_command (const gchar *command);
-static gboolean gdm_send_next_command (void);
-
-/* True if gdm_run_queue is set to be called by glib.
- * FIXME: Actually, isn't this pretty similar to GDM_SOCKET_CLOSED?
- */
-static gboolean queue_runner_is_running = FALSE;
-
-/* See the description in the header file. */
-void
-ask_gdm(GdmMessageCallback *callback, gpointer data, gchar *query, ...)
-{
-  GdmRequest *new_request;
-  gboolean queue_was_empty;
-  va_list args;
-
-  queue_was_empty = gdm_queue==NULL || g_queue_is_empty (gdm_queue);
-
-  va_start (args, query);
-
-  new_request = g_malloc(sizeof(GdmRequest));
-  new_request->callback = callback;
-  new_request->data = data;
-  
-  if (query==NULL)
-    new_request->query = NULL;
-  else
-    new_request->query = g_strdup_vprintf (query, args);
-
-  va_end (args);
-
-  if (gdm_queue == NULL)
-    gdm_queue = g_queue_new();
-
-  g_queue_push_tail(gdm_queue, new_request);
-
-  if (!queue_runner_is_running) {
-    g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, gdm_run_queue, NULL, NULL);
-    queue_runner_is_running = TRUE;
-  }
-}
-
-/* Cleans up a GdmRequest*. */
-
-void
-gdm_request_free (GdmRequest *victim)
-{
-  g_free (victim->query);
-  /* Don't free victim->data: that's the callback's job */
-  g_free (victim);
-}
-
-/* Returns TRUE iff the version represented by |version| is greater or equal
- * to the version represented by |min_version|.
- */
-static gboolean
-version_ok_p (const char *version,
-    const char *min_version)
-{
-  int a = 0, b = 0, c = 0, d = 0;
-  int mina = 0, minb = 0, minc = 0, mind = 0;
-
-  /* Note that if some fields in the version don't exist, then
-   * we don't mind, they are zero */
-  sscanf (version, "%d.%d.%d.%d", &a, &b, &c, &d);
-  sscanf (min_version, "%d.%d.%d.%d", &mina, &minb, &minc, &mind);
-
-  if ((a > mina) ||
-      (a == mina && b > minb) ||
-      (a == mina && b == minb && c > minc) ||
-      (a == mina && b == minb && c == minc && d >= mind))
-    return TRUE;
-  else
-    return FALSE;
-}
-
-/* Closes the GDM socket gracefully, and sets the state accordingly. */
-static void
-close_gdm_socket ()
-{
-  gdm_send_command("CLOSE");
-  VE_IGNORE_EINTR (close (gdm_socket));
-  gdm_socket_status = GDM_SOCKET_CLOSED;
-}
-
-/* This is the function which gets called repeatedly while we're idle
- * to remove messages from the queue and send them to GDM.
- */
-gboolean gdm_run_queue (void *dummy)
-{
-  static GString *incoming = NULL;
-
-  /* Firstly, unless the socket is closed, we left
-   * because we were waiting for a response from
-   * GDM. Let's see what it's sent us.
-   */
-  if (gdm_socket_status != GDM_SOCKET_CLOSED) {
-    char buf[1] = "";
-
-    if (incoming == NULL)
-      incoming = g_string_sized_new (10);
-
-    while (read (gdm_socket, buf, 1) == 1 &&
-        buf[0] != '\n') {
-      g_string_append_c (incoming, buf[0]);
-    }
-
-    if (buf[0] != '\n') {
-      /* We haven't received the CR yet, so let's go around
-       * again.
-       */
-
-      return TRUE;
-    }
-  }
-
-  /* So if we get here, either the socket is closed and we want to
-   * begin a conversation, or we've just received an answer that we
-   * were expecting.
-   */
-
-  switch (gdm_socket_status) {
-    case GDM_SOCKET_CLOSED:
-        {
-        struct sockaddr_un addr;
-
-        /* Okay, so open the socket and let's try talking to gdm. */
-        gdm_socket = socket (PF_LOCAL, SOCK_STREAM, 0);
-        strcpy (addr.sun_path, GDM_SOCKET_FILENAME);
-        addr.sun_family = AF_UNIX;
-
-        if (fcntl (gdm_socket, F_SETFL, O_NONBLOCK) < 0) {
-          VE_IGNORE_EINTR (close (gdm_socket));
-          return FALSE;
-        }
-
-        if (connect (gdm_socket, (struct sockaddr *)&addr, sizeof (addr)) < 0) {
-          g_warning ("Unable to connect to GDM socket: %s", GDM_SOCKET_FILENAME);
-          VE_IGNORE_EINTR (close (gdm_socket));
-          return FALSE;
-        }
-
-        gdm_send_command("VERSION");
-
-        if (incoming) {
-          g_string_free (incoming, TRUE);
-          incoming = NULL;
-        }
-        gdm_socket_status = GDM_SOCKET_WAITING_FOR_VERSION;
-
-        return TRUE;
-        }             
-      break;
-    case GDM_SOCKET_WAITING_FOR_VERSION:
-        {
-        if (strncmp (incoming->str, "GDM ", 4) != 0) {
-          g_string_free (incoming, TRUE);
-          incoming = NULL;
-          close_gdm_socket ();
-          return TRUE;
-        }
-        if ( ! version_ok_p (&incoming->str[4], MINIMAL_GDM_VERSION)) {
-          g_string_free (incoming, TRUE);
-          incoming = NULL;
-          close_gdm_socket ();
-          return TRUE;
-        }
-
-        g_string_free (incoming, TRUE);
-        incoming = NULL;
-
-        gdm_send_next_command ();
-        gdm_socket_status = GDM_SOCKET_RUNNING_QUEUE;        
-
-        return TRUE;
-        }
-      break;
-    case GDM_SOCKET_RUNNING_QUEUE:
-        {
-        GdmRequest *request;
-
-        if (g_queue_is_empty (gdm_queue)) {
-          queue_runner_is_running = FALSE;
-          return FALSE;
-        }
-
-        request = (GdmRequest*) g_queue_pop_head (gdm_queue);
-
-#if 0
-        /* Uncomment this if you want to see who's saying what to whom. */
-        g_warning ("%s -> %s", request->query, incoming->str);
-#endif
-        
-        if (request->callback) {
-          if (strncmp (incoming->str, "OK", 2) == 0) {
-            if (incoming->str[2] == ' ')
-              request->callback (GDM_RESULT_OK, incoming->str+3, request->data);
-            else
-              request->callback (GDM_RESULT_OK, NULL, request->data);
-          } else if (strncmp (incoming->str, "ERROR", 5) == 0) {
-            if (incoming->str[5] == ' ')
-              request->callback (GDM_RESULT_ERROR, incoming->str+6, request->data);
-            else
-              request->callback (GDM_RESULT_ERROR, NULL, request->data);
-          } else {
-            g_warning("Bizarre message from GDM: %s", incoming->str);
-            request->callback (GDM_RESULT_BIZARRE, incoming->str, request->data);
-          }
-        }
-
-        gdm_request_free (request);
-
-        g_string_free (incoming, TRUE);
-        incoming = NULL;
-
-        if (gdm_send_next_command ()) {
-          return TRUE;
-        } else {
-          /* Queue is empty, so close the socket... */
-          close_gdm_socket ();
-          /* ...and don't go round again. */
-          queue_runner_is_running = FALSE;
-          return FALSE;
-        }
-        }
-  }
-
-  g_assert_not_reached ();
-}
-
-/* This sends the query given by the next command, i.e. the one on the
- * top of the queue. While there are entries on the top of the queue
- * with *no* commands to send, this function will pop them and execute
- * their callbacks. However, that is the only time when this function
- * modifies the queue.
- *
- * The function returns FALSE if the queue is (now) empty and TRUE
- * otherwise.
- */
-static gboolean gdm_send_next_command ()
-{
-  GdmRequest *request;
-
-  if (g_queue_is_empty (gdm_queue)) {
-    return FALSE;
-  } else {
-    request  = (GdmRequest*) g_queue_peek_head (gdm_queue);
-
-    while (!g_queue_is_empty (gdm_queue) && request->query == NULL) {
-      /* The query can be NULL, in which case we just call the
-       * callback and pop it.
-       * 
-       * (This pops the request that "request" points at
-       * off the top of the stack.)
-       */
-      g_queue_pop_head (gdm_queue);
-
-      /* Check that nobody has been daft enough to ask for no query
-       * and no callback. Why anyone would do that, I don't know.
-       */
-      if (request->callback)
-        /* So we call it... */
-        request->callback (GDM_RESULT_OK, NULL, request->data);
-
-      if (!g_queue_is_empty (gdm_queue)) {
-
-        /* Throw that one away... */
-        gdm_request_free (request);
-
-        /* and get another. */
-        request = (GdmRequest*) g_queue_peek_head (gdm_queue);
-      }
-    }
-
-    if (g_queue_is_empty (gdm_queue)) {
-      return FALSE;
-    } else {
-      gdm_send_command (request->query);
-      return TRUE;
-    }
-  }
-}
- 
-/* This sends the command |command| to GDM. */
-static int gdm_send_command (const gchar *command)
-{
-  int ret;
-  gchar *command_with_newline;
-#ifndef MSG_NOSIGNAL
-  void (*old_handler)(int);
-#endif
-
-  command_with_newline = g_strdup_printf ("%s\n", command);
-
-#ifdef MSG_NOSIGNAL
-  ret = send (gdm_socket, command_with_newline, strlen (command_with_newline), MSG_NOSIGNAL);
-#else
-  old_handler = signal (SIGPIPE, SIG_IGN);
-  ret = send (gdm_socket, command_with_newline, strlen (command_with_newline), 0);
-  signal (SIGPIPE, old_handler);
-#endif
-
-  g_free (command_with_newline);
-
-  if (ret == -1)
-    g_warning ("Bad result in gdm_send_command: %s", command);
-
-  return ret;
-}
-
-/* Returns a pointer to a string representing the X display number which
- * |screen| is on. It's the callers responsibility to free the pointer.
- */
-static gchar *
-get_dispnum (GdkScreen *screen)
-{
-  gchar *tmp, *retval;
-
-  tmp = g_strdup (gdk_display_get_name (gdk_screen_get_display (screen)));
-  if (tmp)
-    {
-    gchar *ptr;
-
-    ptr = strchr (tmp, '.');
-    if (ptr)
-      *ptr = '\0';
-
-    ptr = strchr (tmp, ':');
-    if (ptr)
-      {
-      while (*ptr == ':')
-        ptr++;
-
-      retval = g_strdup (ptr);
-      }
-    else
-      retval = g_strdup (tmp);
-
-    g_free (tmp);
-    }
-  else
-    retval = g_strdup ("0");
-
-  return retval;
-}
-
-/* This is a strange special case. The first time we need to authenticate,
- * we might find several cookies which could do. We have no way of knowing
- * without trying them which ones might solve the problem. So we send all
- * of them; the first one which succeeds stores the winning cookie so that
- * we can send only that one next time. However, there's then no point in
- * sending all the others, so we call this function to save ourselves the
- * bother.
- */
-static void
-chop_all_auths_off_gdm_queue ()
-{
-  GdmRequest *head;
-  
-  if (g_queue_is_empty (gdm_queue))
-    return;
-  
-  head = (GdmRequest*) g_queue_peek_head (gdm_queue);
-
-  while (!g_queue_is_empty (gdm_queue) &&
-      strncmp (head->query, "AUTH_", 5)==0) {
-
-      gdm_request_free (g_queue_pop_head (gdm_queue));
-      head = (GdmRequest*) g_queue_peek_head (gdm_queue);
-  }
-}
-
-static gboolean cookie_tried = FALSE;
-static char *cookie = NULL;
-
-/* The callback which calls chop_all_auths_off_gdm_queue, q.v. */
-static void
-gdm_callback_perhaps_set_official_cookie (GdmResultState is_ok,
-      const gchar *dummy, gpointer candidate_cookie)
-{
-  if (is_ok == GDM_RESULT_OK) {
-    cookie = candidate_cookie;
-    cookie_tried = TRUE;
-    chop_all_auths_off_gdm_queue ();
-  } else {
-    g_free (candidate_cookie);
-  }
-}
-
-/* See the description in the header file. */
-void
-queue_authentication (GdkScreen *screen)
-{
-  FILE *fp;
-  char *number;
-  Xauth *xau;
-
-  if (cookie_tried) {
-    /* Been there, done that. */
-    if (cookie)
-      ask_gdm (NULL, NULL, GDM_CMD_AUTH_LOCAL, cookie);
-    return;
-  }
-
-  VE_IGNORE_EINTR (fp = fopen (XauFileName (), "r"));
-
-  if (fp == NULL) {
-    /* Oops, no xauthority file! */
-    cookie = NULL;
-    cookie_tried = TRUE;
-    return;
-  }
-
-  number = get_dispnum (screen);
-
-  cookie = NULL;
-
-  while ((xau = XauReadAuth (fp)) != NULL) {
-    int i;
-    char buffer[40 /* 2*16 == 32, so 40 is enough */];
-
-    /* Only Family local things are considered, all console
-     * logins DO have this family (and even some local xdmcp
-     * logins, though those will not pass by gdm itself of
-     * course) */
-    if (xau->family != FamilyLocal ||
-        xau->number_length != strlen (number) ||
-        strncmp (xau->number, number, xau->number_length) != 0 ||
-        /* gdm sends MIT-MAGIC-COOKIE-1 cookies of length 16,
-         * so just do those */
-        xau->data_length != 16 ||
-        xau->name_length != strlen ("MIT-MAGIC-COOKIE-1") ||
-        strncmp (xau->name, "MIT-MAGIC-COOKIE-1",
-          xau->name_length) != 0 ||
-        xau->data_length != 16) {
-      /* so, not what we want; throw it away and continue */
-      XauDisposeAuth (xau);
-      continue;
-    }
-
-    buffer[0] = '\0';
-    for (i = 0; i < 16; i++) {
-      char sub[3];
-      g_snprintf (sub, sizeof (sub), "%02x",
-          (guint)(guchar)xau->data[i]);
-      strcat (buffer, sub);
-    }
-
-    XauDisposeAuth (xau);
-
-    ask_gdm (gdm_callback_perhaps_set_official_cookie,
-        g_strdup (buffer),
-        GDM_CMD_AUTH_LOCAL, buffer);
-  }
-
-  VE_IGNORE_EINTR (fclose (fp));
-
-  g_free (number);
-}
-
-/* See the description in the header file. */
-gchar *
-get_mit_magic_cookie (GdkScreen *screen,
-		      gboolean   binary)
-{
-	FILE *fp;
-	char *number;
-	char *cookie = NULL;
-	Xauth *xau;
-
-	VE_IGNORE_EINTR (fp = fopen (XauFileName (), "r"));
-	if (fp == NULL) {
-		return NULL;
-	}
-
-	number = get_dispnum (screen);
-
-	cookie = NULL;
-
-	while ((xau = XauReadAuth (fp)) != NULL) {
-		/* Just find the FIRST magic cookie, that's what gdm uses */
-		if (xau->number_length != strlen (number) ||
-		    strncmp (xau->number, number, xau->number_length) != 0 ||
-		    /* gdm sends MIT-MAGIC-COOKIE-1 cookies of length 16,
-		     * so just do those */
-		    xau->data_length != 16 ||
-		    xau->name_length != strlen ("MIT-MAGIC-COOKIE-1") ||
-		    strncmp (xau->name, "MIT-MAGIC-COOKIE-1",
-			     xau->name_length) != 0) {
-			XauDisposeAuth (xau);
-			continue;
-		}
-
-		if (binary) {
-			cookie = g_new0 (char, 16);
-			memcpy (cookie, xau->data, 16);
-		} else {
-			int i;
-			GString *str;
-
-			str = g_string_new (NULL);
-
-			for (i = 0; i < xau->data_length; i++) {
-				g_string_append_printf
-					(str, "%02x",
-					 (guint)(guchar)xau->data[i]);
-			}
-			cookie = g_string_free (str, FALSE);
-		}
-
-		XauDisposeAuth (xau);
-
-		break;
-	}
-	VE_IGNORE_EINTR (fclose (fp));
-
-	return cookie;
-}
-
Index: src/cut-n-paste/fusa-utils.c
===================================================================
--- src/cut-n-paste/fusa-utils.c	(revision 1096)
+++ src/cut-n-paste/fusa-utils.c	(working copy)
@@ -1,99 +0,0 @@
-/* 
- * Fast User Switch Applet: fusa-vt-manager.h
- * 
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <config.h>
-#include <glib/gi18n.h>
-
-#include <gtk/gtkalignment.h>
-#include <gtk/gtkexpander.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtkmessagedialog.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtkstock.h>
-#include <gtk/gtkvbox.h>
-
-#include "fusa-utils.h"
-
-
-void
-fusa_dialog_hig_fix (GtkWidget *dialog,
-		     GtkStyle  *old_style,
-		     gpointer   is_message_esque)
-{
-  gtk_container_set_border_width (GTK_CONTAINER (dialog), 12);
-  gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area),
-				  0);
-  gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->action_area), 6);
-  gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 0);
-
-  if (is_message_esque)
-    gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 24);
-  else
-    gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12);
-}
-
-void
-fusa_die_an_ignominious_death (const gchar *primary_markup,
-			       const gchar *secondary_markup,
-			       const gchar *details_text)
-{
-  GtkWidget *dialog;
-
-  GDK_THREADS_ENTER ();
-
-  dialog = gtk_message_dialog_new (NULL, 0,
-				   GTK_MESSAGE_ERROR,
-				   GTK_BUTTONS_NONE,
-				   primary_markup);
-  gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog),
-					      secondary_markup);
-  gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_QUIT,
-				     GTK_RESPONSE_CLOSE);
-
-  if (details_text)
-    {
-      GtkWidget *expander, *alignment, *label;
-    
-      alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
-      gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 12, 12, 0, 12);
-      gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
-			  alignment, TRUE, TRUE, 0);
-      gtk_widget_show (alignment);
-
-      expander = gtk_expander_new (_("Show Details"));
-      gtk_container_add (GTK_CONTAINER (alignment), expander);
-      gtk_widget_show (expander);
-
-      alignment = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
-      gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 12, 0);
-      gtk_container_add (GTK_CONTAINER (expander), alignment);
-      gtk_widget_show (alignment);
-
-      label = gtk_label_new (details_text);
-      gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
-      gtk_container_add (GTK_CONTAINER (alignment), label);
-      gtk_widget_show (label);
-    }
-
-  gtk_dialog_run (GTK_DIALOG (dialog));
-  gtk_main_quit ();
-
-  GDK_THREADS_LEAVE ();
-}
Index: src/cut-n-paste/.cvsignore
===================================================================
--- src/cut-n-paste/.cvsignore	(revision 1096)
+++ src/cut-n-paste/.cvsignore	(working copy)
@@ -1,7 +0,0 @@
-*.la
-*.lo
-*.o
-.deps
-.libs
-Makefile
-Makefile.in
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 1096)
+++ src/Makefile.am	(working copy)
@@ -3,17 +3,12 @@ AUTOMAKE_OPTIONS = 1.7
 
 NULL =
 
-SUBDIRS = \
-	cut-n-paste	\
-	$(NULL)
-
 saverdir = $(libexecdir)/gnome-screensaver
 themesdir = $(pkgdatadir)/themes
 
 INCLUDES =							\
 	-I.							\
 	-I$(srcdir)						\
-	-I$(top_srcdir)/src/cut-n-paste				\
 	-DGMENU_I_KNOW_THIS_IS_UNSTABLE				\
 	$(GNOME_SCREENSAVER_CFLAGS)				\
 	$(GNOME_SCREENSAVER_DIALOG_CFLAGS)			\
@@ -34,7 +29,6 @@ INCLUDES =							\
 	$(AUTH_CFLAGS)						\
 	$(DEBUG_CFLAGS)						\
 	$(DBUS_CFLAGS)						\
-	$(FAST_USER_SWITCH_CFLAGS)				\
 	$(LIBGNOMEKBDUI_CFLAGS)					\
 	$(NULL)
 
@@ -148,10 +142,8 @@ EXTRA_gnome_screensaver_dialog_SOURCES =
 	$(NULL)
 
 gnome_screensaver_dialog_LDADD =	\
-	$(top_builddir)/src/cut-n-paste/libfast-user-switch.a \
 	$(GNOME_SCREENSAVER_DIALOG_LIBS)\
 	$(SAVER_LIBS)			\
-	$(FAST_USER_SWITCH_LIBS)	\
 	$(AUTH_LIBS)			\
 	$(LIBGNOMEKBDUI_LIBS)		\
 	$(NULL)
Index: configure.ac
===================================================================
--- configure.ac	(revision 1096)
+++ configure.ac	(working copy)
@@ -170,15 +170,6 @@ fi
 PAM_PREFIX=`eval echo $PAM_PREFIX_UNEXPANDED`
 AC_SUBST(PAM_PREFIX)
 
-# Fast User Switching
-
-PKG_CHECK_MODULES(FAST_USER_SWITCH,
-        gtk+-2.0 >= $GTK_REQUIRED_VERSION
-        gnome-vfs-2.0 >= $GNOME_VFS_REQUIRED_VERSION)
-
-AC_SUBST(FAST_USER_SWITCH_CFLAGS)
-AC_SUBST(FAST_USER_SWITCH_LIBS)
-
 # Desktop entry handling
 
 PKG_CHECK_MODULES(LIB_GNOME_MENU,
@@ -1112,7 +1103,6 @@ AC_OUTPUT([
 Makefile
 po/Makefile.in
 src/Makefile
-src/cut-n-paste/Makefile
 data/Makefile
 data/gnome-screensavers.menu
 data/gnome-screensaver.pc
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(revision 1096)
+++ po/POTFILES.in	(working copy)
@@ -11,11 +11,6 @@ savers/personal-slideshow.desktop.in
 savers/popsquares.desktop.in
 savers/floaters.c
 savers/slideshow.c
-src/cut-n-paste/fusa-display.c
-src/cut-n-paste/fusa-manager.c
-src/cut-n-paste/fusa-user-menu-item.c
-src/cut-n-paste/fusa-user.c
-src/cut-n-paste/fusa-utils.c
 src/file-transfer-dialog.c
 src/gnome-screensaver-command.c
 src/gnome-screensaver-dialog.c
