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_KEEP_COMMENTS, 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_KEEP_COMMENTS, &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);
424 layout = g_key_file_get_string (dmrc_file, "Desktop", "Layout", NULL);
426 g_signal_connect (G_OBJECT (display->priv->user_session), "exited", G_CALLBACK (user_session_exited_cb), display);
427 g_signal_connect (G_OBJECT (display->priv->user_session), "killed", G_CALLBACK (user_session_killed_cb), display);
428 session_set_env (display->priv->user_session, "DISPLAY", xserver_get_address (display->priv->xserver));
429 #ifdef HAVE_CONSOLE_KIT
430 session_set_env (display->priv->user_session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->user_ck_session));
432 session_set_env (display->priv->user_session, "DESKTOP_SESSION", session); // FIXME: Apparently deprecated?
433 session_set_env (display->priv->user_session, "GDMSESSION", session); // FIXME: Not cross-desktop
434 session_set_env (display->priv->user_session, "PATH", "/usr/local/bin:/usr/bin:/bin");
435 session_set_env (display->priv->user_session, "LANG", session_language);
436 session_set_env (display->priv->user_session, "GDM_LANG", session_language); // FIXME: Not cross-desktop
437 session_set_env (display->priv->user_session, "GDM_KEYBOARD_LAYOUT", layout); // FIXME: Not cross-desktop
439 g_signal_emit (display, signals[START_SESSION], 0, display->priv->user_session);
441 session_start (display->priv->user_session);
443 data = g_key_file_to_data (dmrc_file, &length, NULL);
445 /* Update the users .dmrc */
448 path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
449 g_file_set_contents (path, data, length, NULL);
453 /* Update the .dmrc cache */
454 path = g_build_filename (CACHE_DIR, "dmrc", NULL);
455 g_mkdir_with_parents (path, 0700);
457 filename = g_strdup_printf ("%s.dmrc", pam_session_get_username (display->priv->user_pam_session));
458 path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
459 g_file_set_contents (path, data, length, NULL);
463 g_free (session_language);
470 g_key_file_free (session_desktop_file);
471 g_key_file_free (dmrc_file);
475 start_default_session (Display *display, const gchar *session, const gchar *language)
477 /* Don't need to check authentication, just authorize */
478 if (display->priv->user_pam_session)
479 pam_session_end (display->priv->user_pam_session);
480 display->priv->user_pam_session = pam_session_new (display->priv->default_user);
481 pam_session_authorize (display->priv->user_pam_session);
483 #ifdef HAVE_CONSOLE_KIT
484 display->priv->user_ck_session = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
486 start_user_session (display, session, language);
490 end_greeter_session (Display *display, gboolean clean_exit)
492 gboolean greeter_connected;
494 if (display->priv->greeter_quit_timeout)
496 g_source_remove (display->priv->greeter_quit_timeout);
497 display->priv->greeter_quit_timeout = 0;
500 g_signal_emit (display, signals[END_GREETER], 0, display->priv->greeter_session);
502 greeter_connected = display->priv->greeter_connected;
504 g_object_unref (display->priv->greeter_session);
505 display->priv->greeter_session = NULL;
506 display->priv->greeter_connected = FALSE;
508 pam_session_end (display->priv->greeter_pam_session);
509 g_object_unref (display->priv->greeter_pam_session);
510 display->priv->greeter_pam_session = NULL;
512 #ifdef HAVE_CONSOLE_KIT
513 end_ck_session (display->priv->greeter_ck_session);
514 display->priv->greeter_ck_session = NULL;
518 g_warning ("Greeter failed");
519 else if (!greeter_connected)
520 g_warning ("Greeter quit before connecting");
521 else if (!display->priv->user_session)
522 g_warning ("Greeter quit before session started");
526 // FIXME: Issue with greeter, don't want to start a new one, report error to user
530 greeter_session_exited_cb (Session *session, gint status, Display *display)
532 end_greeter_session (display, status == 0);
536 greeter_session_killed_cb (Session *session, gint status, Display *display)
538 end_greeter_session (display, FALSE);
542 start_greeter (Display *display)
545 GError *error = NULL;
547 theme = load_theme (display->priv->greeter_theme, &error);
549 g_warning ("Failed to find theme %s: %s", display->priv->greeter_theme, error->message);
550 g_clear_error (&error);
556 g_debug ("Starting greeter %s as user %s", display->priv->greeter_theme,
557 display->priv->greeter_user ? display->priv->greeter_user : "<current>");
559 command = theme_get_command (theme);
561 display->priv->greeter_pam_session = pam_session_new (display->priv->greeter_user);
562 pam_session_authorize (display->priv->greeter_pam_session);
564 #ifdef HAVE_CONSOLE_KIT
565 display->priv->greeter_ck_session = start_ck_session (display,
567 display->priv->greeter_user ? display->priv->greeter_user : getenv ("USER"));
570 display->priv->greeter_connected = FALSE;
571 display->priv->greeter_session = session_new (display->priv->greeter_user, command);
572 g_signal_connect (G_OBJECT (display->priv->greeter_session), "exited", G_CALLBACK (greeter_session_exited_cb), display);
573 g_signal_connect (G_OBJECT (display->priv->greeter_session), "killed", G_CALLBACK (greeter_session_killed_cb), display);
574 session_set_env (display->priv->greeter_session, "DISPLAY", xserver_get_address (display->priv->xserver));
575 #ifdef HAVE_CONSOLE_KIT
576 session_set_env (display->priv->greeter_session, "XDG_SESSION_COOKIE", ck_connector_get_cookie (display->priv->greeter_ck_session));
579 g_signal_emit (display, signals[START_GREETER], 0, display->priv->greeter_session);
581 session_start (display->priv->greeter_session);
584 g_key_file_free (theme);
588 #define TYPE_MESSAGE dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, G_TYPE_INVALID)
591 pam_messages_cb (PAMSession *session, int num_msg, const struct pam_message **msg, Display *display)
595 DBusGMethodInvocation *context;
597 /* Respond to d-bus query with messages */
598 request = g_ptr_array_new ();
599 for (i = 0; i < num_msg; i++)
601 GValue value = { 0 };
603 g_value_init (&value, TYPE_MESSAGE);
604 g_value_take_boxed (&value, dbus_g_type_specialized_construct (TYPE_MESSAGE));
605 // FIXME: Need to convert to UTF-8
606 dbus_g_type_struct_set (&value, 0, msg[i]->msg_style, 1, msg[i]->msg, G_MAXUINT);
607 g_ptr_array_add (request, g_value_get_boxed (&value));
610 context = display->priv->dbus_context;
611 display->priv->dbus_context = NULL;
612 dbus_g_method_return (context, 0, request);
616 authenticate_result_cb (PAMSession *session, int result, Display *display)
619 DBusGMethodInvocation *context;
621 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));
623 /* Respond to D-Bus request */
624 request = g_ptr_array_new ();
625 context = display->priv->dbus_context;
626 display->priv->dbus_context = NULL;
628 dbus_g_method_return (context, result, request);
632 session_started_cb (PAMSession *session, Display *display)
634 #ifdef HAVE_CONSOLE_KIT
635 display->priv->user_ck_session = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
640 display_connect (Display *display,
642 const gchar **language, const gchar **layout, const gchar **session,
643 const gchar **username, gint *delay, GError *error)
645 if (!display->priv->greeter_connected)
647 display->priv->greeter_connected = TRUE;
648 g_debug ("Greeter connected");
651 *theme = g_build_filename (THEME_DIR, display->priv->greeter_theme, "index.theme", NULL);
652 *language = g_strdup (display->priv->default_language);
653 *layout = g_strdup (display->priv->default_layout);
654 *session = g_strdup (display->priv->default_session);
655 *username = g_strdup (display->priv->default_user);
656 *delay = display->priv->timeout;
662 display_start_authentication (Display *display, const gchar *username, DBusGMethodInvocation *context)
664 GError *error = NULL;
666 // FIXME: Only allow calls from the correct greeter
668 if (!display->priv->greeter_session || display->priv->user_session)
670 dbus_g_method_return_error (context, NULL);
674 /* Abort existing authentication */
675 if (display->priv->user_pam_session)
677 g_signal_handlers_disconnect_matched (display->priv->user_pam_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, display);
678 pam_session_end (display->priv->user_pam_session);
679 if (display->priv->dbus_context)
680 dbus_g_method_return_error (display->priv->dbus_context, NULL);
682 g_object_unref (display->priv->user_pam_session);
685 g_debug ("Greeter start authentication for %s", username);
687 /* Store D-Bus request to respond to */
688 display->priv->dbus_context = context;
690 display->priv->user_pam_session = pam_session_new (username);
691 g_signal_connect (G_OBJECT (display->priv->user_pam_session), "got-messages", G_CALLBACK (pam_messages_cb), display);
692 g_signal_connect (G_OBJECT (display->priv->user_pam_session), "authentication-result", G_CALLBACK (authenticate_result_cb), display);
693 g_signal_connect (G_OBJECT (display->priv->user_pam_session), "started", G_CALLBACK (session_started_cb), display);
695 if (!pam_session_start (display->priv->user_pam_session, &error))
697 g_warning ("Failed to start authentication: %s", error->message);
698 display->priv->dbus_context = NULL;
699 dbus_g_method_return_error (context, NULL);
702 g_clear_error (&error);
708 display_continue_authentication (Display *display, gchar **secrets, DBusGMethodInvocation *context)
711 const struct pam_message **messages;
712 struct pam_response *response;
713 int i, j, n_secrets = 0;
716 if (!display->priv->greeter_connected)
718 dbus_g_method_return_error (context, NULL);
722 /* Not in authorization */
723 if (display->priv->user_pam_session == NULL)
725 dbus_g_method_return_error (context, NULL);
729 /* Already in another call */
730 if (display->priv->dbus_context != NULL)
732 dbus_g_method_return_error (context, NULL);
736 // FIXME: Only allow calls from the correct greeter
738 num_messages = pam_session_get_num_messages (display->priv->user_pam_session);
739 messages = pam_session_get_messages (display->priv->user_pam_session);
741 /* Check correct number of responses */
742 for (i = 0; i < num_messages; i++)
744 int msg_style = messages[i]->msg_style;
745 if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
748 if (g_strv_length (secrets) != n_secrets)
750 pam_session_end (display->priv->user_pam_session);
751 // FIXME: Throw error
755 g_debug ("Continue authentication");
758 response = calloc (num_messages, sizeof (struct pam_response));
759 for (i = 0, j = 0; i < num_messages; i++)
761 int msg_style = messages[i]->msg_style;
762 if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
764 response[i].resp = strdup (secrets[j]); // FIXME: Need to convert from UTF-8
769 display->priv->dbus_context = context;
770 pam_session_respond (display->priv->user_pam_session, response);
776 quit_greeter_cb (gpointer data)
778 Display *display = data;
779 g_warning ("Greeter did not quit, sending kill signal");
780 session_stop (display->priv->greeter_session);
781 display->priv->greeter_quit_timeout = 0;
786 quit_greeter (Display *display)
788 g_signal_emit (display, signals[QUIT_GREETER], 0);
789 if (display->priv->greeter_quit_timeout)
790 g_source_remove (display->priv->greeter_quit_timeout);
791 display->priv->greeter_quit_timeout = g_timeout_add (GREETER_QUIT_TIMEOUT, quit_greeter_cb, display);
795 session_timeout_cb (Display *display)
797 g_warning ("Session has not indicated it is ready, stopping greeter anyway");
799 /* Stop the greeter */
800 quit_greeter (display);
802 display->priv->user_session_timer = 0;
807 display_login (Display *display, gchar *username, gchar *session, gchar *language, GError *error)
809 if (display->priv->user_session != NULL)
811 g_warning ("Ignoring request to log in when already logged in");
815 g_debug ("Greeter login for user %s on session %s", username, session);
817 /* Default session requested */
818 if (strcmp (session, "") == 0)
819 session = display->priv->default_session;
821 /* Default language requested */
822 if (strcmp (language, "") == 0)
825 if (display->priv->default_user && strcmp (username, display->priv->default_user) == 0)
826 start_default_session (display, session, language);
827 else if (display->priv->user_pam_session &&
828 pam_session_get_in_session (display->priv->user_pam_session) &&
829 strcmp (username, pam_session_get_username (display->priv->user_pam_session)) == 0)
830 start_user_session (display, session, language);
833 g_warning ("Ignoring request for login with unauthenticated user");
837 /* Stop session, waiting for user session to indicate it is ready (if supported) */
838 // FIXME: Hard-coded timeout
839 if (display->priv->supports_transitions)
840 display->priv->user_session_timer = g_timeout_add (USER_SESSION_TIMEOUT, (GSourceFunc) session_timeout_cb, display);
842 quit_greeter (display);
848 xserver_exit_cb (XServer *server, Display *display)
850 g_object_unref (display->priv->xserver);
851 display->priv->xserver = NULL;
852 g_signal_emit (display, signals[EXITED], 0);
856 xserver_ready_cb (XServer *xserver, Display *display)
858 /* Don't run any sessions on local terminals */
859 if (xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL_TERMINAL)
862 /* If have user then automatically login the first time */
863 if (display->priv->default_user && display->priv->timeout == 0 && display->priv->login_count == 0)
864 start_default_session (display, display->priv->default_session, NULL);
866 start_greeter (display);
870 display_start (Display *display)
872 g_return_val_if_fail (display->priv->xserver != NULL, FALSE);
873 g_signal_connect (G_OBJECT (display->priv->xserver), "ready", G_CALLBACK (xserver_ready_cb), display);
874 g_signal_connect (G_OBJECT (display->priv->xserver), "exited", G_CALLBACK (xserver_exit_cb), display);
875 return xserver_start (display->priv->xserver);
879 display_init (Display *display)
881 display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, DISPLAY_TYPE, DisplayPrivate);
882 display->priv->greeter_user = g_strdup (GREETER_USER);
883 display->priv->greeter_theme = g_strdup (GREETER_THEME);
884 display->priv->default_language = getenv ("LANG") ? g_strdup (getenv ("LANG")) : g_strdup ("C");
885 display->priv->default_layout = g_strdup ("us"); // FIXME: Is there a better default to get?
886 display->priv->default_session = g_strdup (DEFAULT_SESSION);
890 display_finalize (GObject *object)
894 self = DISPLAY (object);
896 if (self->priv->greeter_session)
897 g_object_unref (self->priv->greeter_session);
898 if (self->priv->user_session_timer)
899 g_source_remove (self->priv->user_session_timer);
900 if (self->priv->user_session)
901 g_object_unref (self->priv->user_session);
902 if (self->priv->user_pam_session)
903 g_object_unref (self->priv->user_pam_session);
904 #ifdef HAVE_CONSOLE_KIT
905 end_ck_session (self->priv->greeter_ck_session);
906 end_ck_session (self->priv->user_ck_session);
908 if (self->priv->xserver)
909 g_object_unref (self->priv->xserver);
910 g_free (self->priv->greeter_user);
911 g_free (self->priv->greeter_theme);
912 g_free (self->priv->default_user);
913 g_free (self->priv->default_language);
914 g_free (self->priv->default_layout);
915 g_free (self->priv->default_session);
919 display_class_init (DisplayClass *klass)
921 GObjectClass *object_class = G_OBJECT_CLASS (klass);
923 object_class->finalize = display_finalize;
925 g_type_class_add_private (klass, sizeof (DisplayPrivate));
927 signals[START_GREETER] =
928 g_signal_new ("start-greeter",
929 G_TYPE_FROM_CLASS (klass),
931 G_STRUCT_OFFSET (DisplayClass, start_greeter),
933 g_cclosure_marshal_VOID__OBJECT,
934 G_TYPE_NONE, 1, SESSION_TYPE);
936 signals[END_GREETER] =
937 g_signal_new ("end-greeter",
938 G_TYPE_FROM_CLASS (klass),
940 G_STRUCT_OFFSET (DisplayClass, end_greeter),
942 g_cclosure_marshal_VOID__OBJECT,
943 G_TYPE_NONE, 1, SESSION_TYPE);
945 signals[START_SESSION] =
946 g_signal_new ("start-session",
947 G_TYPE_FROM_CLASS (klass),
949 G_STRUCT_OFFSET (DisplayClass, start_session),
951 g_cclosure_marshal_VOID__OBJECT,
952 G_TYPE_NONE, 1, SESSION_TYPE);
954 signals[END_SESSION] =
955 g_signal_new ("end-session",
956 G_TYPE_FROM_CLASS (klass),
958 G_STRUCT_OFFSET (DisplayClass, end_session),
960 g_cclosure_marshal_VOID__OBJECT,
961 G_TYPE_NONE, 1, SESSION_TYPE);
964 g_signal_new ("exited",
965 G_TYPE_FROM_CLASS (klass),
967 G_STRUCT_OFFSET (DisplayClass, exited),
969 g_cclosure_marshal_VOID__VOID,
972 signals[QUIT_GREETER] =
973 g_signal_new ("quit_greeter",
974 G_TYPE_FROM_CLASS (klass),
976 G_STRUCT_OFFSET (DisplayClass, quit_greeter),
978 g_cclosure_marshal_VOID__VOID,
981 dbus_g_object_type_install_info (DISPLAY_TYPE, &dbus_glib_display_object_info);