SERVER_MESSAGE_END_AUTHENTICATION,
SERVER_MESSAGE_SESSION_RESULT,
SERVER_MESSAGE_SHARED_DIR_RESULT,
+ SERVER_MESSAGE_IDLE,
+ SERVER_MESSAGE_RESET,
} ServerMessage;
+ /* Request sent to server */
+ typedef struct
+ {
+ GObject parent_instance;
+ gboolean complete;
+ guint32 return_code;
+ gchar *dir;
+ } Request;
+ typedef struct
+ {
+ GObjectClass parent_class;
+ } RequestClass;
+ GType request_get_type (void);
+ #define REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), request_get_type (), Request))
+ G_DEFINE_TYPE (Request, request, G_TYPE_OBJECT);
+
/**
* lightdm_greeter_new:
*
return g_object_new (LIGHTDM_TYPE_GREETER, NULL);
}
+/**
+ * lightdm_greeter_set_resettable:
+ * @greeter: A #LightDMGreeter
+ * @resettable: Whether the greeter wants to be reset instead of killed after the user logs in
+ *
+ * Set whether the greeter will be reset instead of killed after the user logs in.
+ * This must be called before lightdm_greeter_connect is called.
+ **/
+void
+lightdm_greeter_set_resettable (LightDMGreeter *greeter, gboolean resettable)
+{
+ LightDMGreeterPrivate *priv;
+
+ g_return_if_fail (LIGHTDM_IS_GREETER (greeter));
+
+ priv = GET_PRIVATE (greeter);
+
+ g_return_if_fail (!priv->connected);
+ priv->resettable = resettable;
+}
+
+ static Request *
+ request_new (void)
+ {
+ Request *request;
+
+ request = g_object_new (request_get_type (), NULL);
+
+ return request;
+ }
+
static gboolean
timed_login_cb (gpointer data)
{
g_signal_emit (G_OBJECT (greeter), signals[AUTHENTICATION_COMPLETE], 0);
}
++static void
++handle_idle (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
++{
++ g_signal_emit (G_OBJECT (greeter), signals[IDLE], 0);
++}
++
+static void
+handle_reset (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
+{
+ LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
+ GString *hint_string;
+
+ g_hash_table_remove_all (priv->hints);
+
+ hint_string = g_string_new ("");
+ while (*offset < message_length)
+ {
+ gchar *name, *value;
+
+ name = read_string (message, message_length, offset);
+ value = read_string (message, message_length, offset);
+ g_hash_table_insert (priv->hints, name, value);
+ g_string_append_printf (hint_string, " %s=%s", name, value);
+ }
+
+ g_debug ("Reset%s", hint_string->str);
+ g_string_free (hint_string, TRUE);
+
+ g_signal_emit (G_OBJECT (greeter), signals[RESET], 0);
+}
+
+ static void
+ handle_session_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
+ {
+ LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
+ Request *request;
+
+ request = g_list_nth_data (priv->start_session_requests, 0);
+ if (request)
+ {
+ request->return_code = read_int (message, message_length, offset);
+ request->complete = TRUE;
+ priv->start_session_requests = g_list_remove (priv->start_session_requests, request);
+ g_object_unref (request);
+ }
+ }
+
+ static void
+ handle_shared_dir_result (LightDMGreeter *greeter, guint8 *message, gsize message_length, gsize *offset)
+ {
+ LightDMGreeterPrivate *priv = GET_PRIVATE (greeter);
+ Request *request;
+
+ request = g_list_nth_data (priv->ensure_shared_data_dir_requests, 0);
+ if (request)
+ {
+ request->dir = read_string (message, message_length, offset);
+ /* Blank data dir means invalid user */
+ if (g_strcmp0 (request->dir, "") == 0)
+ {
+ g_free (request->dir);
+ request->dir = NULL;
+ }
+ request->complete = TRUE;
+ priv->ensure_shared_data_dir_requests = g_list_remove (priv->ensure_shared_data_dir_requests, request);
+ g_object_unref (request);
+ }
+ }
+
+ static void
+ handle_message (LightDMGreeter *greeter, guint8 *message, gsize message_length)
+ {
+ gsize offset = 0;
+ guint32 id;
+
+ id = read_int (message, message_length, &offset);
+ read_int (message, message_length, &offset);
+ switch (id)
+ {
+ case SERVER_MESSAGE_CONNECTED:
+ handle_connected (greeter, message, message_length, &offset);
+ break;
+ case SERVER_MESSAGE_PROMPT_AUTHENTICATION:
+ handle_prompt_authentication (greeter, message, message_length, &offset);
+ break;
+ case SERVER_MESSAGE_END_AUTHENTICATION:
+ handle_end_authentication (greeter, message, message_length, &offset);
+ break;
+ case SERVER_MESSAGE_SESSION_RESULT:
+ handle_session_result (greeter, message, message_length, &offset);
+ break;
+ case SERVER_MESSAGE_SHARED_DIR_RESULT:
+ handle_shared_dir_result (greeter, message, message_length, &offset);
+ break;
++ case SERVER_MESSAGE_IDLE:
++ handle_idle (greeter, message, message_length, &offset);
++ break;
++ case SERVER_MESSAGE_RESET:
++ handle_reset (greeter, message, message_length, &offset);
++ break;
+ default:
+ g_warning ("Unknown message from server: %d", id);
+ break;
+ }
+ }
+
static guint8 *
read_message (LightDMGreeter *greeter, gsize *length, gboolean block)
{
return TRUE;
}
-send_connect (LightDMGreeter *greeter)
+ static void
- write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION), &offset);
++send_connect (LightDMGreeter *greeter, gboolean resettable)
+ {
+ guint8 message[MAX_MESSAGE_LENGTH];
+ gsize offset = 0;
+
+ g_debug ("Connecting to display manager...");
++ write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset);
+ write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
++ write_int (message, MAX_MESSAGE_LENGTH, resettable ? 1 : 0, &offset);
+ write_message (greeter, message, offset);
+ }
+
+ static void
+ send_start_session (LightDMGreeter *greeter, const gchar *session)
+ {
+ guint8 message[MAX_MESSAGE_LENGTH];
+ gsize offset = 0;
+
+ if (session)
+ g_debug ("Starting session %s", session);
+ else
+ g_debug ("Starting default session");
+
+ write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_START_SESSION, string_length (session), &offset);
+ write_string (message, MAX_MESSAGE_LENGTH, session, &offset);
+ write_message (greeter, message, offset);
+ }
+
+ static void
+ send_ensure_shared_data_dir (LightDMGreeter *greeter, const gchar *username)
+ {
+ guint8 message[MAX_MESSAGE_LENGTH];
+ gsize offset = 0;
+
+ g_debug ("Ensuring data directory for user %s", username);
+
+ write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_ENSURE_SHARED_DIR, string_length (username), &offset);
+ write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
+ write_message (greeter, message, offset);
+ }
+
/**
* lightdm_greeter_connect_sync:
* @greeter: The greeter to connect
g_io_channel_set_encoding (priv->from_server_channel, NULL, NULL);
g_io_add_watch (priv->from_server_channel, G_IO_IN, from_server_cb, greeter);
- g_debug ("Connecting to display manager...");
- write_header (message, MAX_MESSAGE_LENGTH, GREETER_MESSAGE_CONNECT, string_length (VERSION) + int_length (), &offset);
- write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
- write_int (message, MAX_MESSAGE_LENGTH, priv->resettable ? 1 : 0, &offset);
- write_message (greeter, message, offset);
-
- response = read_message (greeter, &response_length, TRUE);
- if (!response)
- return FALSE;
-
- offset = 0;
- id = read_int (response, response_length, &offset);
- read_int (response, response_length, &offset);
- if (id == SERVER_MESSAGE_CONNECTED)
- handle_connected (greeter, response, response_length, &offset);
- g_free (response);
- if (id != SERVER_MESSAGE_CONNECTED)
+ /* Read until we are connected */
- send_connect (greeter);
++ send_connect (greeter, priv->resettable);
+ request = request_new ();
+ priv->connect_requests = g_list_append (priv->connect_requests, g_object_ref (request));
+ do
{
- g_warning ("Expected CONNECTED message, got %d", id);
- return FALSE;
- }
+ guint8 *message;
+ gsize message_length;
- priv->connected = TRUE;
+ message = read_message (greeter, &message_length, TRUE);
+ if (!message)
+ break;
+ handle_message (greeter, message, message_length);
+ g_free (message);
+ } while (!request->complete);
- return TRUE;
+ g_object_unref (request);
+
+ return request->complete;
}
/**
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
+
+ /**
+ * LightDMGreeter::idle:
+ * @greeter: A #LightDMGreeter
+ *
+ * The ::idle signal gets emitted when the user has logged in and the
+ * greeter is no longer needed.
+ *
+ * This signal only matters if the greeter has marked itself as
+ * resettable using lightdm_greeter_set_resettable().
+ **/
+ signals[IDLE] =
+ g_signal_new ("idle",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LightDMGreeterClass, idle),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
+
+ /**
+ * LightDMGreeter::reset:
+ * @greeter: A #LightDMGreeter
+ *
+ * The ::reset signal gets emitted when the user is returning to a greeter
+ * that was previously marked idle.
+ *
+ * This signal only matters if the greeter has marked itself as
+ * resettable using lightdm_greeter_set_resettable().
+ **/
+ signals[RESET] =
+ g_signal_new ("reset",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (LightDMGreeterClass, reset),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 0);
}
+
+ static void
+ request_init (Request *request)
+ {
+ }
+
+ static void
+ request_finalize (GObject *object)
+ {
+ Request *request = REQUEST (object);
+
+ g_free (request->dir);
+
+ G_OBJECT_CLASS (request_parent_class)->finalize (object);
+ }
+
+ static void
+ request_class_init (RequestClass *klass)
+ {
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = request_finalize;
+ }