2 * Copyright (C) 2010 Robert Ancell.
3 * Author: Robert Ancell <robert.ancell@canonical.com>
5 * This program is free software: you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option) any later
8 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
18 #include <gio/gdesktopappinfo.h>
20 #ifdef HAVE_CONSOLE_KIT
21 #include <ck-connector.h>
25 #include "display-glue.h"
26 #include "pam-session.h"
28 #include "ldm-marshal.h"
30 /* Length of time in milliseconds to wait for a session to load */
31 #define USER_SESSION_TIMEOUT 5000
33 /* Length of time in milliseconds to wait for a greeter to quit */
34 #define GREETER_QUIT_TIMEOUT 1000
45 static guint signals[LAST_SIGNAL] = { 0 };
50 SESSION_GREETER_PRE_CONNECT,
52 SESSION_GREETER_AUTHENTICATED,
63 /* Number of times have logged in */
66 /* Language to use in greeter/sessions */
67 gchar *default_language;
69 /* Layout to use in greeter/sessions */
70 gchar *default_layout;
72 /* User to run greeter as */
78 /* Greeter session process */
79 Session *greeter_session;
80 gboolean greeter_connected;
81 guint greeter_quit_timeout;
82 PAMSession *greeter_pam_session;
83 #ifdef HAVE_CONSOLE_KIT
84 CkConnector *greeter_ck_session;
87 gboolean supports_transitions;
89 /* User session process */
90 Session *user_session;
91 guint user_session_timer;
92 PAMSession *user_pam_session;
93 #ifdef HAVE_CONSOLE_KIT
94 CkConnector *user_ck_session;
97 /* Current D-Bus call context */
98 DBusGMethodInvocation *dbus_context;
100 /* Default login hint */
104 /* Default session */
105 gchar *default_session;
108 G_DEFINE_TYPE (Display, display, G_TYPE_OBJECT);
110 static void start_greeter (Display *display);
112 // FIXME: Remove the index, it is an external property
114 display_new (gint index)
116 Display *self = g_object_new (DISPLAY_TYPE, NULL);
118 self->priv->index = index;
124 display_get_index (Display *display)
126 return display->priv->index;
130 display_set_default_user (Display *display, const gchar *username)
132 g_free (display->priv->default_user);
133 display->priv->default_user = g_strdup (username);
137 display_get_default_user (Display *display)
139 return display->priv->default_user;
143 display_set_default_user_timeout (Display *display, gint timeout)
145 display->priv->timeout = timeout;
149 display_get_default_user_timeout (Display *display)
151 return display->priv->timeout;
155 display_set_greeter_user (Display *display, const gchar *username)
157 g_free (display->priv->greeter_user);
158 display->priv->greeter_user = g_strdup (username);
162 display_get_greeter_user (Display *display)
164 return display->priv->greeter_user;
168 display_get_session_user (Display *display)
170 if (display->priv->user_session)
171 return pam_session_get_username (display->priv->user_pam_session);
177 display_set_greeter_theme (Display *display, const gchar *greeter_theme)
179 g_free (display->priv->greeter_theme);
180 display->priv->greeter_theme = g_strdup (greeter_theme);
184 display_get_greeter_theme (Display *display)
186 return display->priv->greeter_theme;
190 display_set_default_language (Display *display, const gchar *language)
192 g_free (display->priv->default_language);
193 display->priv->default_language = g_strdup (language);
197 display_get_default_language (Display *display)
199 return display->priv->default_language;
203 display_set_default_layout (Display *display, const gchar *layout)
205 g_free (display->priv->default_layout);
206 display->priv->default_layout = g_strdup (layout);
210 display_get_default_layout (Display *display)
212 return display->priv->default_layout;
216 display_set_default_session (Display *display, const gchar *session)
218 g_free (display->priv->default_session);
219 display->priv->default_session = g_strdup (session);
223 display_get_default_session (Display *display)
225 return display->priv->default_session;
229 display_set_xserver (Display *display, XServer *xserver)
231 if (display->priv->xserver)
232 g_object_unref (display->priv->xserver);
233 display->priv->xserver = g_object_ref (xserver);
237 display_get_xserver (Display *display)
239 return display->priv->xserver;
242 static struct passwd *
243 get_user_info (const gchar *username)
245 struct passwd *user_info;
248 user_info = getpwnam (username);
252 g_warning ("Unable to get information on user %s: User does not exist", username);
254 g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
260 #ifdef HAVE_CONSOLE_KIT
262 start_ck_session (Display *display, const gchar *session_type, const gchar *username)
264 CkConnector *session;
266 const gchar *address, *hostname = "";
267 struct passwd *user_info;
268 gboolean is_local = TRUE;
270 session = ck_connector_new ();
272 user_info = get_user_info (username);
276 dbus_error_init (&error);
277 address = xserver_get_address (display->priv->xserver);
278 if (!ck_connector_open_session_with_parameters (session, &error,
279 "session-type", &session_type,
280 "unix-user", &user_info->pw_uid,
281 //"display-device", &display->priv->display_device,
282 //"x11-display-device", &display->priv->x11_display_device,
283 "remote-host-name", &hostname,
284 "x11-display", &address,
285 "is-local", &is_local,
287 g_warning ("Failed to open CK session: %s: %s", error.name, error.message);
293 end_ck_session (CkConnector *session)
297 ck_connector_close_session (session, NULL); // FIXME: Handle errors
298 ck_connector_unref (session);
304 end_user_session (Display *display, gboolean clean_exit)
306 g_signal_emit (display, signals[END_SESSION], 0, display->priv->user_session);
308 if (display->priv->user_session_timer)
310 g_source_remove (display->priv->user_session_timer);
311 display->priv->user_session_timer = 0;
314 g_object_unref (display->priv->user_session);
315 display->priv->user_session = NULL;
317 pam_session_end (display->priv->user_pam_session);
318 g_object_unref (display->priv->user_pam_session);
319 display->priv->user_pam_session = NULL;
321 #ifdef HAVE_CONSOLE_KIT
322 end_ck_session (display->priv->user_ck_session);
323 display->priv->user_ck_session = NULL;
327 g_warning ("Session exited unexpectedly");
329 xserver_disconnect_clients (display->priv->xserver);
333 user_session_exited_cb (Session *session, gint status, Display *display)
335 end_user_session (display, status == 0);
339 user_session_killed_cb (Session *session, gint status, Display *display)
341 end_user_session (display, FALSE);
345 start_user_session (Display *display, const gchar *session, const gchar *language)
347 gchar *filename, *path;
348 struct passwd *user_info;
349 GKeyFile *dmrc_file, *session_desktop_file;
350 gboolean have_dmrc = FALSE, result;
351 GError *error = NULL;
353 g_debug ("Launching '%s' session for user %s", session, pam_session_get_username (display->priv->user_pam_session));
354 display->priv->login_count++;
356 /* Load the users login settings (~/.dmrc) */
357 dmrc_file = g_key_file_new ();
358 user_info = get_user_info (pam_session_get_username (display->priv->user_pam_session));
361 /* Load from the user directory, if this fails (e.g. the user directory
362 * is not yet mounted) then load from the cache */
363 path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
364 have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, NULL);
368 /* If no .dmrc, then load from the cache */
371 filename = g_strdup_printf ("%s.dmrc", user_info->pw_name);
372 path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
374 if (!g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_NONE, &error))
375 g_warning ("Failed to load .dmrc file %s: %s", path, error->message);
376 g_clear_error (&error);
380 /* Update the .dmrc with changed settings */
381 g_key_file_set_string (dmrc_file, "Desktop", "Session", session);
383 g_key_file_set_string (dmrc_file, "Desktop", "Language", language);
384 else if (!g_key_file_has_key (dmrc_file, "Desktop", "Language", NULL))
385 g_key_file_set_string (dmrc_file, "Desktop", "Language", display->priv->default_language);
386 if (!g_key_file_has_key (dmrc_file, "Desktop", "Layout", NULL))
387 g_key_file_set_string (dmrc_file, "Desktop", "Layout", display->priv->default_layout);
389 filename = g_strdup_printf ("%s.desktop", session);
390 path = g_build_filename (XSESSIONS_DIR, filename, NULL);
393 session_desktop_file = g_key_file_new ();
394 result = g_key_file_load_from_file (session_desktop_file, path, G_KEY_FILE_NONE, &error);
398 g_warning ("Failed to load session file %s: %s:", path, error->message);
399 g_clear_error (&error);
403 gchar *session_command, *command = NULL;
405 session_command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
406 if (!session_command)
407 g_warning ("No command in session file %s", path);
409 command = g_strdup_printf ("/etc/X11/Xsession %s", session_command);
410 g_free (session_command);
412 display->priv->supports_transitions = g_key_file_get_boolean (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, "X-LightDM-Supports-Transitions", NULL);
416 gchar *session_language, *layout;
420 display->priv->user_session = session_new (pam_session_get_username (display->priv->user_pam_session), command);
422 session_language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
423 g_debug ("session_language='%s'", session_language);
425 layout = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
427 g_signal_connect (G_OBJECT (display->priv->user_session), "exited", G_CALLBACK (user_session_exited_cb), display);
428 g_signal_connect (G_OBJECT (display->priv->user_session), "killed", G_CALLBACK (user_session_killed_cb), display);
429 session_set_env (display->priv->user_session, "DISPLAY", xserver_get_address (display->priv->xserver));
430 #ifdef HAVE_CONSOLE_KIT
431 session_set_env (display->priv->user_session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->user_ck_session));
433 session_set_env (display->priv->user_session, "DESKTOP_SESSION", session); // FIXME: Apparently deprecated?
434 session_set_env (display->priv->user_session, "GDMSESSION", session); // FIXME: Not cross-desktop
435 session_set_env (display->priv->user_session, "PATH", "/usr/local/bin:/usr/bin:/bin");
436 session_set_env (display->priv->user_session, "LANG", session_language);
437 session_set_env (display->priv->user_session, "GDM_LANG", session_language); // FIXME: Not cross-desktop
438 session_set_env (display->priv->user_session, "GDM_KEYBOARD_LAYOUT", layout); // FIXME: Not cross-desktop
440 g_signal_emit (display, signals[START_SESSION], 0, display->priv->user_session);
442 session_start (display->priv->user_session);
444 data = g_key_file_to_data (dmrc_file, &length, NULL);
446 /* Update the users .dmrc */
449 path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
450 g_file_set_contents (path, data, length, NULL);
454 /* Update the .dmrc cache */
455 filename = g_strdup_printf ("%s.dmrc", pam_session_get_username (display->priv->user_pam_session));
456 path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
457 g_file_set_contents (path, data, length, NULL);
461 g_free (session_language);
468 g_key_file_free (session_desktop_file);
469 g_key_file_free (dmrc_file);
473 start_default_session (Display *display, const gchar *session, const gchar *language)
475 /* Don't need to check authentication, just authorize */
476 if (display->priv->user_pam_session)
477 pam_session_end (display->priv->user_pam_session);
478 display->priv->user_pam_session = pam_session_new (display->priv->default_user);
479 pam_session_authorize (display->priv->user_pam_session);
481 #ifdef HAVE_CONSOLE_KIT
482 display->priv->user_ck_session = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
484 start_user_session (display, session, language);
488 end_greeter_session (Display *display, gboolean clean_exit)
490 gboolean greeter_connected;
492 if (display->priv->greeter_quit_timeout)
494 g_source_remove (display->priv->greeter_quit_timeout);
495 display->priv->greeter_quit_timeout = 0;
498 g_signal_emit (display, signals[END_GREETER], 0, display->priv->greeter_session);
500 greeter_connected = display->priv->greeter_connected;
502 g_object_unref (display->priv->greeter_session);
503 display->priv->greeter_session = NULL;
504 display->priv->greeter_connected = FALSE;
506 pam_session_end (display->priv->greeter_pam_session);
507 g_object_unref (display->priv->greeter_pam_session);
508 display->priv->greeter_pam_session = NULL;
510 #ifdef HAVE_CONSOLE_KIT
511 end_ck_session (display->priv->greeter_ck_session);
512 display->priv->greeter_ck_session = NULL;
516 g_warning ("Greeter failed");
517 else if (!greeter_connected)
518 g_warning ("Greeter quit before connecting");
519 else if (!display->priv->user_session)
520 g_warning ("Greeter quit before session started");
524 // FIXME: Issue with greeter, don't want to start a new one, report error to user
528 greeter_session_exited_cb (Session *session, gint status, Display *display)
530 end_greeter_session (display, status == 0);
534 greeter_session_killed_cb (Session *session, gint status, Display *display)
536 end_greeter_session (display, FALSE);
540 start_greeter (Display *display)
543 GError *error = NULL;
545 theme = load_theme (display->priv->greeter_theme, &error);
547 g_warning ("Failed to find theme %s: %s", display->priv->greeter_theme, error->message);
548 g_clear_error (&error);
554 g_debug ("Starting greeter %s as user %s", display->priv->greeter_theme,
555 display->priv->greeter_user ? display->priv->greeter_user : "<current>");
557 command = theme_get_command (theme);
559 display->priv->greeter_pam_session = pam_session_new (display->priv->greeter_user);
560 pam_session_authorize (display->priv->greeter_pam_session);
562 #ifdef HAVE_CONSOLE_KIT
563 display->priv->greeter_ck_session = start_ck_session (display,
565 display->priv->greeter_user ? display->priv->greeter_user : getenv ("USER"));
568 display->priv->greeter_connected = FALSE;
569 display->priv->greeter_session = session_new (display->priv->greeter_user, command);
570 g_signal_connect (G_OBJECT (display->priv->greeter_session), "exited", G_CALLBACK (greeter_session_exited_cb), display);
571 g_signal_connect (G_OBJECT (display->priv->greeter_session), "killed", G_CALLBACK (greeter_session_killed_cb), display);
572 session_set_env (display->priv->greeter_session, "DISPLAY", xserver_get_address (display->priv->xserver));
573 #ifdef HAVE_CONSOLE_KIT
574 session_set_env (display->priv->greeter_session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->greeter_ck_session));
577 g_signal_emit (display, signals[START_GREETER], 0, display->priv->greeter_session);
579 session_start (display->priv->greeter_session);
582 g_key_file_free (theme);
586 #define TYPE_MESSAGE dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID)
589 pam_messages_cb (PAMSession *session, int num_msg, const struct pam_message **msg, Display *display)
593 DBusGMethodInvocation *context;
595 /* Respond to d-bus query with messages */
596 request = g_ptr_array_new ();
597 for (i = 0; i < num_msg; i++)
599 GValue value = { 0 };
601 g_value_init (&value, TYPE_MESSAGE);
602 g_value_take_boxed (&value, dbus_g_type_specialized_construct (TYPE_MESSAGE));
603 // FIXME: Need to convert to UTF-8
604 dbus_g_type_struct_set (&value, 0, msg[i]->msg_style, 1, msg[i]->msg, G_MAXUINT);
605 g_ptr_array_add (request, g_value_get_boxed (&value));
608 context = display->priv->dbus_context;
609 display->priv->dbus_context = NULL;
610 dbus_g_method_return (context, 0, request);
614 authenticate_result_cb (PAMSession *session, int result, Display *display)
617 DBusGMethodInvocation *context;
619 g_debug ("Authenticate result for user %s: %s", pam_session_get_username (display->priv->user_pam_session), pam_session_strerror (display->priv->user_pam_session, result));
621 /* Respond to D-Bus request */
622 request = g_ptr_array_new ();
623 context = display->priv->dbus_context;
624 display->priv->dbus_context = NULL;
626 dbus_g_method_return (context, result, request);
630 session_started_cb (PAMSession *session, Display *display)
632 #ifdef HAVE_CONSOLE_KIT
633 display->priv->user_ck_session = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
638 display_connect (Display *display,
640 const gchar **language, const gchar **layout, const gchar **session,
641 const gchar **username, gint *delay, GError *error)
643 if (!display->priv->greeter_connected)
645 display->priv->greeter_connected = TRUE;
646 g_debug ("Greeter connected");
649 *theme = g_build_filename (THEME_DIR, display->priv->greeter_theme, "index.theme", NULL);
650 *language = g_strdup (display->priv->default_language);
651 *layout = g_strdup (display->priv->default_layout);
652 *session = g_strdup (display->priv->default_session);
653 *username = g_strdup (display->priv->default_user);
654 *delay = display->priv->timeout;
660 display_start_authentication (Display *display, const gchar *username, DBusGMethodInvocation *context)
662 GError *error = NULL;
664 // FIXME: Only allow calls from the correct greeter
666 if (!display->priv->greeter_session || display->priv->user_session)
668 dbus_g_method_return_error (context, NULL);
672 /* Abort existing authentication */
673 if (display->priv->user_pam_session)
675 g_signal_handlers_disconnect_matched (display->priv->user_pam_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
676 pam_session_end (display->priv->user_pam_session);
677 if (display->priv->dbus_context)
678 dbus_g_method_return_error (display->priv->dbus_context, NULL);
680 g_object_unref (display->priv->user_pam_session);
683 g_debug ("Greeter start authentication for %s", username);
685 /* Store D-Bus request to respond to */
686 display->priv->dbus_context = context;
688 display->priv->user_pam_session = pam_session_new (username);
689 g_signal_connect (G_OBJECT (display->priv->user_pam_session), "got-messages", G_CALLBACK (pam_messages_cb), display);
690 g_signal_connect (G_OBJECT (display->priv->user_pam_session), "authentication-result", G_CALLBACK (authenticate_result_cb), display);
691 g_signal_connect (G_OBJECT (display->priv->user_pam_session), "started", G_CALLBACK (session_started_cb), display);
693 if (!pam_session_start (display->priv->user_pam_session, &error))
695 g_warning ("Failed to start authentication: %s", error->message);
696 display->priv->dbus_context = NULL;
697 dbus_g_method_return_error (context, NULL);
700 g_clear_error (&error);
706 display_continue_authentication (Display *display, gchar **secrets, DBusGMethodInvocation *context)
709 const struct pam_message **messages;
710 struct pam_response *response;
711 int i, j, n_secrets = 0;
714 if (!display->priv->greeter_connected)
716 dbus_g_method_return_error (context, NULL);
720 /* Not in authorization */
721 if (display->priv->user_pam_session == NULL)
723 dbus_g_method_return_error (context, NULL);
727 /* Already in another call */
728 if (display->priv->dbus_context != NULL)
730 dbus_g_method_return_error (context, NULL);
734 // FIXME: Only allow calls from the correct greeter
736 num_messages = pam_session_get_num_messages (display->priv->user_pam_session);
737 messages = pam_session_get_messages (display->priv->user_pam_session);
739 /* Check correct number of responses */
740 for (i = 0; i < num_messages; i++)
742 int msg_style = messages[i]->msg_style;
743 if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
746 if (g_strv_length (secrets) != n_secrets)
748 pam_session_end (display->priv->user_pam_session);
749 // FIXME: Throw error
753 g_debug ("Continue authentication");
756 response = calloc (num_messages, sizeof (struct pam_response));
757 for (i = 0, j = 0; i < num_messages; i++)
759 int msg_style = messages[i]->msg_style;
760 if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
762 response[i].resp = strdup (secrets[j]); // FIXME: Need to convert from UTF-8
767 display->priv->dbus_context = context;
768 pam_session_respond (display->priv->user_pam_session, response);
774 quit_greeter_cb (gpointer data)
776 Display *display = data;
777 g_warning ("Greeter did not quit, sending kill signal");
778 session_stop (display->priv->greeter_session);
779 display->priv->greeter_quit_timeout = 0;
784 quit_greeter (Display *display)
786 g_signal_emit (display, signals[QUIT_GREETER], 0);
787 if (display->priv->greeter_quit_timeout)
788 g_source_remove (display->priv->greeter_quit_timeout);
789 display->priv->greeter_quit_timeout = g_timeout_add (GREETER_QUIT_TIMEOUT, quit_greeter_cb, display);
793 session_timeout_cb (Display *display)
795 g_warning ("Session has not indicated it is ready, stopping greeter anyway");
797 /* Stop the greeter */
798 quit_greeter (display);
800 display->priv->user_session_timer = 0;
805 display_login (Display *display, gchar *username, gchar *session, gchar *language, GError *error)
807 if (display->priv->user_session != NULL)
809 g_warning ("Ignoring request to log in when already logged in");
813 g_debug ("Greeter login for user %s on session %s", username, session);
815 /* Default session requested */
816 if (strcmp (session, "") == 0)
817 session = display->priv->default_session;
819 /* Default language requested */
820 if (strcmp (language, "") == 0)
823 if (display->priv->default_user && strcmp (username, display->priv->default_user) == 0)
824 start_default_session (display, session, language);
825 else if (display->priv->user_pam_session &&
826 pam_session_get_in_session (display->priv->user_pam_session) &&
827 strcmp (username, pam_session_get_username (display->priv->user_pam_session)) == 0)
828 start_user_session (display, session, language);
831 g_warning ("Ignoring request for login with unauthenticated user");
835 /* Stop session, waiting for user session to indicate it is ready (if supported) */
836 // FIXME: Hard-coded timeout
837 if (display->priv->supports_transitions)
838 display->priv->user_session_timer = g_timeout_add (USER_SESSION_TIMEOUT, (GSourceFunc) session_timeout_cb, display);
840 quit_greeter (display);
846 xserver_exit_cb (XServer *server, Display *display)
848 g_object_unref (display->priv->xserver);
849 display->priv->xserver = NULL;
850 g_signal_emit (display, signals[EXITED], 0);
854 xserver_ready_cb (XServer *xserver, Display *display)
856 /* Don't run any sessions on local terminals */
857 if (xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL_TERMINAL)
860 /* If have user then automatically login the first time */
861 if (display->priv->default_user && display->priv->timeout == 0 && display->priv->login_count == 0)
862 start_default_session (display, display->priv->default_session, NULL);
864 start_greeter (display);
868 display_start (Display *display)
870 g_return_val_if_fail (display->priv->xserver != NULL, FALSE);
871 g_signal_connect (G_OBJECT (display->priv->xserver), "ready", G_CALLBACK (xserver_ready_cb), display);
872 g_signal_connect (G_OBJECT (display->priv->xserver), "exited", G_CALLBACK (xserver_exit_cb), display);
873 return xserver_start (display->priv->xserver);
877 display_init (Display *display)
879 display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, DISPLAY_TYPE, DisplayPrivate);
880 display->priv->greeter_user = g_strdup (GREETER_USER);
881 display->priv->greeter_theme = g_strdup (GREETER_THEME);
882 display->priv->default_language = getenv ("LANG") ? getenv ("LANG") : g_strdup ("C");
883 display->priv->default_layout = g_strdup ("us"); // FIXME: Is there a better default to get?
884 display->priv->default_session = g_strdup (DEFAULT_SESSION);
888 display_finalize (GObject *object)
892 self = DISPLAY (object);
894 if (self->priv->greeter_session)
895 g_object_unref (self->priv->greeter_session);
896 if (self->priv->user_session_timer)
897 g_source_remove (self->priv->user_session_timer);
898 if (self->priv->user_session)
899 g_object_unref (self->priv->user_session);
900 if (self->priv->user_pam_session)
901 g_object_unref (self->priv->user_pam_session);
902 #ifdef HAVE_CONSOLE_KIT
903 end_ck_session (self->priv->greeter_ck_session);
904 end_ck_session (self->priv->user_ck_session);
906 if (self->priv->xserver)
907 g_object_unref (self->priv->xserver);
908 g_free (self->priv->greeter_user);
909 g_free (self->priv->greeter_theme);
910 g_free (self->priv->default_user);
911 g_free (self->priv->default_language);
912 g_free (self->priv->default_layout);
913 g_free (self->priv->default_session);
917 display_class_init (DisplayClass *klass)
919 GObjectClass *object_class = G_OBJECT_CLASS (klass);
921 object_class->finalize = display_finalize;
923 g_type_class_add_private (klass, sizeof (DisplayPrivate));
925 signals[START_GREETER] =
926 g_signal_new ("start-greeter",
927 G_TYPE_FROM_CLASS (klass),
929 G_STRUCT_OFFSET (DisplayClass, start_greeter),
931 g_cclosure_marshal_VOID__OBJECT,
932 G_TYPE_NONE, 1, SESSION_TYPE);
934 signals[END_GREETER] =
935 g_signal_new ("end-greeter",
936 G_TYPE_FROM_CLASS (klass),
938 G_STRUCT_OFFSET (DisplayClass, end_greeter),
940 g_cclosure_marshal_VOID__OBJECT,
941 G_TYPE_NONE, 1, SESSION_TYPE);
943 signals[START_SESSION] =
944 g_signal_new ("start-session",
945 G_TYPE_FROM_CLASS (klass),
947 G_STRUCT_OFFSET (DisplayClass, start_session),
949 g_cclosure_marshal_VOID__OBJECT,
950 G_TYPE_NONE, 1, SESSION_TYPE);
952 signals[END_SESSION] =
953 g_signal_new ("end-session",
954 G_TYPE_FROM_CLASS (klass),
956 G_STRUCT_OFFSET (DisplayClass, end_session),
958 g_cclosure_marshal_VOID__OBJECT,
959 G_TYPE_NONE, 1, SESSION_TYPE);
962 g_signal_new ("exited",
963 G_TYPE_FROM_CLASS (klass),
965 G_STRUCT_OFFSET (DisplayClass, exited),
967 g_cclosure_marshal_VOID__VOID,
970 signals[QUIT_GREETER] =
971 g_signal_new ("quit_greeter",
972 G_TYPE_FROM_CLASS (klass),
974 G_STRUCT_OFFSET (DisplayClass, quit_greeter),
976 g_cclosure_marshal_VOID__VOID,
979 dbus_g_object_type_install_info (DISPLAY_TYPE, &dbus_glib_display_object_info);