## Description: add some description ## Origin/Author: add some origin or author ## Bug: bug URL From 7e4878cea1504420911b7672f81f9221c6e1d65a Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 13 Jan 2010 16:30:49 +1100 Subject: [PATCH] Add SwitchToUser() method which automatically selects that user in the greeter or switches to an already open session Bug: https://bugzilla.gnome.org/show_bug.cgi?id=606923 diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-display.c gdm-2.30.0.new/daemon/gdm-display.c --- gdm-2.30.0/daemon/gdm-display.c 2010-04-13 15:41:16.724247508 +0800 +++ gdm-2.30.0.new/daemon/gdm-display.c 2010-04-13 15:41:18.906768605 +0800 @@ -60,6 +60,7 @@ time_t creation_time; GTimer *slave_timer; char *slave_command; + char *username; char *x11_cookie; gsize x11_cookie_size; @@ -85,6 +86,7 @@ PROP_X11_AUTHORITY_FILE, PROP_IS_LOCAL, PROP_SLAVE_COMMAND, + PROP_USERNAME, }; static void gdm_display_class_init (GdmDisplayClass *klass); @@ -574,9 +576,17 @@ gdm_slave_proxy_set_log_path (display->priv->slave_proxy, log_path); g_free (log_path); - command = g_strdup_printf ("%s --display-id %s", - display->priv->slave_command, - display->priv->id); + if (display->priv->username) { + command = g_strdup_printf ("%s --display-id %s --username %s", + display->priv->slave_command, + display->priv->id, + display->priv->username); + } else { + command = g_strdup_printf ("%s --display-id %s", + display->priv->slave_command, + display->priv->id); + } + gdm_slave_proxy_set_command (display->priv->slave_proxy, command); g_free (command); @@ -832,6 +842,14 @@ } static void +_gdm_display_set_username (GdmDisplay *display, + const char *username) +{ + g_free (display->priv->username); + display->priv->username = g_strdup (username); +} + +static void gdm_display_set_property (GObject *object, guint prop_id, const GValue *value, @@ -869,6 +887,9 @@ case PROP_SLAVE_COMMAND: _gdm_display_set_slave_command (self, g_value_get_string (value)); break; + case PROP_USERNAME: + _gdm_display_set_username (self, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -917,6 +938,9 @@ case PROP_SLAVE_COMMAND: g_value_set_string (value, self->priv->slave_command); break; + case PROP_USERNAME: + g_value_set_string (value, self->priv->username); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1093,6 +1117,13 @@ DEFAULT_SLAVE_COMMAND, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, + PROP_USERNAME, + g_param_spec_string ("username", + "username", + "username", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_STATUS, g_param_spec_int ("status", "status", diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-greeter-server.c gdm-2.30.0.new/daemon/gdm-greeter-server.c --- gdm-2.30.0/daemon/gdm-greeter-server.c 2010-04-13 15:41:16.724247508 +0800 +++ gdm-2.30.0.new/daemon/gdm-greeter-server.c 2010-04-13 15:41:18.916747038 +0800 @@ -281,6 +281,14 @@ } void +gdm_greeter_server_select_user(GdmGreeterServer *greeter_server, + const char *username) +{ + g_debug ("SelectUser(%s)", username); + send_dbus_string_signal (greeter_server, "SelectUser", username); +} + +void gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, const char *username, int delay) @@ -754,6 +762,9 @@ " \n" " \n" " \n" + " \n" + " \n" + " \n" " \n" " \n" " \n" @@ -1107,7 +1118,7 @@ "display id", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, + g_object_class_install_property (object_class, PROP_USER_NAME, g_param_spec_string ("user-name", "user name", diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-greeter-server.h gdm-2.30.0.new/daemon/gdm-greeter-server.h --- gdm-2.30.0/daemon/gdm-greeter-server.h 2010-04-13 15:41:16.724247508 +0800 +++ gdm-2.30.0.new/daemon/gdm-greeter-server.h 2010-04-13 15:41:18.916747038 +0800 @@ -95,6 +95,8 @@ void gdm_greeter_server_default_session_name_changed (GdmGreeterServer *greeter_server, const char *text); +void gdm_greeter_server_select_user (GdmGreeterServer *greeter_server, + const char *username); void gdm_greeter_server_request_timed_login (GdmGreeterServer *greeter_server, const char *username, int delay); diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-local-display-factory.c gdm-2.30.0.new/daemon/gdm-local-display-factory.c --- gdm-2.30.0/daemon/gdm-local-display-factory.c 2010-04-13 15:41:18.224255958 +0800 +++ gdm-2.30.0.new/daemon/gdm-local-display-factory.c 2010-04-13 15:41:18.916747038 +0800 @@ -495,6 +495,121 @@ } } +static gboolean +switch_to_user_display (GdmLocalDisplayFactory *factory, char *username) +{ + struct passwd *password; + DBusGProxy *proxy; + GPtrArray *sessions = NULL; + GError *error = NULL; + gboolean result = FALSE; + + password = getpwnam (username); + if (!password) { + return FALSE; + } + + proxy = dbus_g_proxy_new_for_name (factory->priv->connection, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager"); + + dbus_g_proxy_call (proxy, "GetSessionsForUnixUser", &error, + G_TYPE_UINT, password->pw_uid, G_TYPE_INVALID, + dbus_g_type_get_collection("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &sessions, G_TYPE_INVALID); + g_object_unref(proxy); + if (error != NULL) { + g_warning ("Error getting sessions for user %s: %s", username, error->message); + g_error_free (error); + } + + if (sessions && sessions->len > 0) { + gchar *session_id = sessions->pdata[0]; + + g_debug ("GdmLocalDisplayFactory: Switching to session %s (user %s)", session_id, username); + + proxy = dbus_g_proxy_new_for_name (factory->priv->connection, + "org.freedesktop.ConsoleKit", + session_id, + "org.freedesktop.ConsoleKit.Session"); + result = dbus_g_proxy_call (proxy, "Activate", &error, G_TYPE_INVALID, G_TYPE_INVALID); + g_object_unref (proxy); + if (error != NULL) + { + g_warning ("Error activating session for user %s: %s", username, error->message); + g_error_free (error); + } + } + + if (sessions != NULL) { + gint i; + for (i = 0; i < sessions->len; i++) { + g_free (sessions->pdata[i]); + } + g_ptr_array_free (sessions, TRUE); + } + + return result; +} + +gboolean +gdm_local_display_factory_switch_to_user (GdmLocalDisplayFactory *factory, + char *username, + char **id, + GError **error) +{ + gboolean ret; + GdmDisplay *display; + guint32 num; + + g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE); + + /* Switch to existing user display */ + if (switch_to_user_display (factory, username)) { + /* FIXME: How to return the ID of the user display? It should + * be easy but I can't find how to get it */ + /*if (id != NULL) { + *id = g_strdup ("FIXME"); + }*/ + + /* FIXME: We should return TRUE here but this causes GDM to go + * crazy. Luckily we can return FALSE as we don't need + * any values returned from this call */ + return FALSE; + } + + ret = FALSE; + + num = take_next_display_number (factory); + + g_debug ("GdmLocalDisplayFactory: Switching to user %s on display %d", username, num); + + display = gdm_transient_display_new (num); + + /* FIXME: don't hardcode seat1? */ + g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL); + g_object_set (display, "username", username, NULL); + + store_display (factory, num, display); + + if (! gdm_display_manage (display)) { + display = NULL; + goto out; + } + + if (! gdm_display_get_id (display, id, NULL)) { + display = NULL; + goto out; + } + + ret = TRUE; + out: + /* ref either held by store or not at all */ + g_object_unref (display); + + return ret; +} + gboolean gdm_local_display_factory_create_product_display (GdmLocalDisplayFactory *factory, const char *parent_display_id, diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-local-display-factory.h gdm-2.30.0.new/daemon/gdm-local-display-factory.h --- gdm-2.30.0/daemon/gdm-local-display-factory.h 2010-04-13 15:41:18.224255958 +0800 +++ gdm-2.30.0.new/daemon/gdm-local-display-factory.h 2010-04-13 15:41:18.916747038 +0800 @@ -64,6 +64,10 @@ gboolean gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory, char **id, GError **error); +gboolean gdm_local_display_factory_switch_to_user (GdmLocalDisplayFactory *factory, + char *username, + char **id, + GError **error); gboolean gdm_local_display_factory_start_guest_session (GdmLocalDisplayFactory *factory, char **id, diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-local-display-factory.xml gdm-2.30.0.new/daemon/gdm-local-display-factory.xml --- gdm-2.30.0/daemon/gdm-local-display-factory.xml 2010-04-13 15:41:18.224255958 +0800 +++ gdm-2.30.0.new/daemon/gdm-local-display-factory.xml 2010-04-13 15:41:18.916747038 +0800 @@ -12,5 +12,9 @@ + + + + diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-simple-slave.c gdm-2.30.0.new/daemon/gdm-simple-slave.c --- gdm-2.30.0/daemon/gdm-simple-slave.c 2010-04-13 15:41:18.354254949 +0800 +++ gdm-2.30.0.new/daemon/gdm-simple-slave.c 2010-04-13 15:41:18.916747038 +0800 @@ -85,10 +85,13 @@ guint start_session_when_ready : 1; guint waiting_to_start_session : 1; guint plymouth_is_running : 1; + + gchar *username; }; enum { PROP_0, + PROP_USERNAME, }; static void gdm_simple_slave_class_init (GdmSimpleSlaveClass *klass); @@ -518,6 +521,16 @@ } static void +gdm_simple_slave_set_username (GdmSimpleSlave *slave, + const char *username) +{ + g_return_if_fail (GDM_IS_SIMPLE_SLAVE (slave)); + + g_free (slave->priv->username); + slave->priv->username = g_strdup (username); +} + +static void on_session_conversation_started (GdmSession *session, GdmSimpleSlave *slave) { @@ -534,6 +547,19 @@ } } + g_object_get (slave, "username", &username, NULL); + if (username) { + g_debug ("GdmSimpleSlave: **user '%s'", username); + if (slave->priv->greeter_server != NULL) { + g_debug ("GdmSimpleSlave: begin login for user '%s'", username); + gdm_simple_slave_set_username (slave, NULL); + gdm_greeter_server_select_user (slave->priv->greeter_server, username); + } + g_free (username); + return; + } + g_debug ("GdmSimpleSlave: **nouser"); + enabled = FALSE; gdm_slave_get_timed_login_details (GDM_SLAVE (slave), &enabled, &username, &delay); if (! enabled) { @@ -1338,7 +1364,14 @@ const GValue *value, GParamSpec *pspec) { + GdmSimpleSlave *self; + + self = GDM_SIMPLE_SLAVE (object); + switch (prop_id) { + case PROP_USERNAME: + gdm_simple_slave_set_username (self, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1351,7 +1384,14 @@ GValue *value, GParamSpec *pspec) { + GdmSimpleSlave *self; + + self = GDM_SIMPLE_SLAVE (object); + switch (prop_id) { + case PROP_USERNAME: + g_value_set_string (value, self->priv->username); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1388,6 +1428,14 @@ g_type_class_add_private (klass, sizeof (GdmSimpleSlavePrivate)); + g_object_class_install_property (object_class, + PROP_USERNAME, + g_param_spec_string ("username", + "id", + "id", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + dbus_g_object_type_install_info (GDM_TYPE_SIMPLE_SLAVE, &dbus_glib_gdm_simple_slave_object_info); } @@ -1420,12 +1468,13 @@ } GdmSlave * -gdm_simple_slave_new (const char *id) +gdm_simple_slave_new (const char *id, const char *username) { GObject *object; object = g_object_new (GDM_TYPE_SIMPLE_SLAVE, "display-id", id, + "username", username, NULL); return GDM_SLAVE (object); diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/gdm-simple-slave.h gdm-2.30.0.new/daemon/gdm-simple-slave.h --- gdm-2.30.0/daemon/gdm-simple-slave.h 2010-04-13 15:41:16.724247508 +0800 +++ gdm-2.30.0.new/daemon/gdm-simple-slave.h 2010-04-13 15:41:18.916747038 +0800 @@ -48,7 +48,8 @@ } GdmSimpleSlaveClass; GType gdm_simple_slave_get_type (void); -GdmSlave * gdm_simple_slave_new (const char *id); +GdmSlave * gdm_simple_slave_new (const char *id, + const char *username); G_END_DECLS diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/daemon/simple-slave-main.c gdm-2.30.0.new/daemon/simple-slave-main.c --- gdm-2.30.0/daemon/simple-slave-main.c 2010-04-13 15:41:18.194248305 +0800 +++ gdm-2.30.0.new/daemon/simple-slave-main.c 2010-04-13 15:41:18.916747038 +0800 @@ -47,6 +47,7 @@ #include "gdm-settings-direct.h" #include "gdm-settings.h" +#include "gdm-settings-client.h" #include "gdm-settings-direct.h" #include "gdm-settings-keys.h" @@ -178,9 +179,11 @@ DBusGConnection *connection; GdmSlave *slave; static char *display_id = NULL; + static char *username = NULL; GdmSignalHandler *signal_handler; static GOptionEntry entries [] = { { "display-id", 0, 0, G_OPTION_ARG_STRING, &display_id, N_("Display ID"), N_("ID") }, + { "username", 0, 0, G_OPTION_ARG_STRING, &username, N_("Username"), N_("name") }, { NULL } }; @@ -248,7 +251,7 @@ gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL); gdm_signal_handler_add (signal_handler, SIGUSR2, signal_cb, NULL); - slave = gdm_simple_slave_new (display_id); + slave = gdm_simple_slave_new (display_id, username); if (slave == NULL) { goto out; } diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/data/gdm.conf.in gdm-2.30.0.new/data/gdm.conf.in --- gdm-2.30.0/data/gdm.conf.in 2010-04-13 15:41:18.254257675 +0800 +++ gdm-2.30.0.new/data/gdm.conf.in 2010-04-13 15:41:18.916747038 +0800 @@ -74,6 +74,9 @@ send_member="CreateTransientDisplay"/> + priv->username); + login_window->priv->username = g_strdup (username); + if (login_window->priv->user_chooser_loaded) { + g_debug ("GdmGreeterLoginWindow: activating user '%s'", login_window->priv->username); + gdm_chooser_widget_set_active_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser), username); + } +} + + void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, const char *username, @@ -836,6 +856,11 @@ adjust_other_login_visibility (login_window); gdm_chooser_widget_activate_if_one_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser)); + + if (login_window->priv->username) { + g_debug ("GdmGreeterLoginWindow: activating user '%s'", login_window->priv->username); + gdm_chooser_widget_set_active_item (GDM_CHOOSER_WIDGET (login_window->priv->user_chooser), login_window->priv->username); + } } static void diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/gui/simple-greeter/gdm-greeter-login-window.h gdm-2.30.0.new/gui/simple-greeter/gdm-greeter-login-window.h --- gdm-2.30.0/gui/simple-greeter/gdm-greeter-login-window.h 2010-04-13 15:41:16.734247730 +0800 +++ gdm-2.30.0.new/gui/simple-greeter/gdm-greeter-login-window.h 2010-04-13 15:41:18.916747038 +0800 @@ -76,6 +76,8 @@ gboolean gdm_greeter_login_window_problem (GdmGreeterLoginWindow *login_window, const char *text); +void gdm_greeter_login_window_select_user (GdmGreeterLoginWindow *login_window, + const char *username); void gdm_greeter_login_window_request_timed_login (GdmGreeterLoginWindow *login_window, const char *username, int delay); diff -Nur -x '*.orig' -x '*~' gdm-2.30.0/gui/simple-greeter/gdm-greeter-session.c gdm-2.30.0.new/gui/simple-greeter/gdm-greeter-session.c --- gdm-2.30.0/gui/simple-greeter/gdm-greeter-session.c 2010-04-13 15:41:18.184247662 +0800 +++ gdm-2.30.0.new/gui/simple-greeter/gdm-greeter-session.c 2010-04-13 15:41:18.916747038 +0800 @@ -153,6 +153,15 @@ } static void +on_server_select_user (GdmGreeterClient *client, + const char *username, + GdmGreeterSession *session) +{ + g_debug ("GdmGreeterSession: selecting user %s", username); + gdm_greeter_login_window_select_user (GDM_GREETER_LOGIN_WINDOW (session->priv->login_window), username); +} + +static void on_timed_login_requested (GdmGreeterClient *client, const char *text, int delay, @@ -603,6 +612,10 @@ G_CALLBACK (on_default_session_name_changed), session); g_signal_connect (session->priv->client, + "select-user", + G_CALLBACK (on_server_select_user), + session); + g_signal_connect (session->priv->client, "timed-login-requested", G_CALLBACK (on_timed_login_requested), session);