2 * Copyright (C) 2010-2011 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>
21 #include "pam-session.h"
23 #include "ldm-marshal.h"
26 /* Length of time in milliseconds to wait for a session to load */
27 #define USER_SESSION_TIMEOUT 5000
37 static guint signals[LAST_SIGNAL] = { 0 };
42 SESSION_GREETER_PRE_CONNECT,
44 SESSION_GREETER_AUTHENTICATED,
55 /* Number of times have logged in */
58 /* Layout to use in greeter/sessions */
59 gchar *default_layout;
61 /* User to run greeter as */
67 /* Program to run sessions through */
68 gchar *session_wrapper;
70 /* PAM service to authenticate against */
73 /* Greeter session process */
74 Greeter *greeter_session;
75 PAMSession *greeter_pam_session;
76 gchar *greeter_ck_cookie;
78 /* TRUE if the greeter can stay active during the session */
79 gboolean supports_transitions;
81 /* User session process */
82 Session *user_session;
83 guint user_session_timer;
84 PAMSession *user_pam_session;
85 gchar *user_ck_cookie;
87 /* Default login hint */
92 gchar *default_session;
95 G_DEFINE_TYPE (Display, display, G_TYPE_OBJECT);
97 static void start_greeter (Display *display);
99 // FIXME: Remove the index, it is an external property
101 display_new (gint index)
103 Display *self = g_object_new (DISPLAY_TYPE, NULL);
105 self->priv->index = index;
106 self->priv->pam_service = g_strdup (DEFAULT_PAM_SERVICE);
112 display_get_index (Display *display)
114 return display->priv->index;
118 display_set_session_wrapper (Display *display, const gchar *session_wrapper)
120 g_free (display->priv->session_wrapper);
121 display->priv->session_wrapper = g_strdup (session_wrapper);
125 display_get_session_wrapper (Display *display)
127 return display->priv->session_wrapper;
131 display_set_default_user (Display *display, const gchar *username)
133 g_free (display->priv->default_user);
134 display->priv->default_user = g_strdup (username);
138 display_get_default_user (Display *display)
140 return display->priv->default_user;
144 display_set_default_user_timeout (Display *display, gint timeout)
146 display->priv->timeout = timeout;
150 display_get_default_user_timeout (Display *display)
152 return display->priv->timeout;
156 display_set_greeter_user (Display *display, const gchar *username)
158 g_free (display->priv->greeter_user);
159 if (username && username[0] != '\0')
160 display->priv->greeter_user = g_strdup (username);
162 display->priv->greeter_user = NULL;
166 display_get_greeter_user (Display *display)
168 return display->priv->greeter_user;
172 display_get_session_user (Display *display)
174 if (display->priv->user_session)
175 return pam_session_get_username (display->priv->user_pam_session);
181 display_set_greeter_theme (Display *display, const gchar *greeter_theme)
183 g_free (display->priv->greeter_theme);
184 display->priv->greeter_theme = g_strdup (greeter_theme);
188 display_get_greeter_theme (Display *display)
190 return display->priv->greeter_theme;
194 display_set_default_layout (Display *display, const gchar *layout)
196 g_free (display->priv->default_layout);
197 display->priv->default_layout = g_strdup (layout);
201 display_get_default_layout (Display *display)
203 return display->priv->default_layout;
207 display_set_default_session (Display *display, const gchar *session)
209 g_free (display->priv->default_session);
210 display->priv->default_session = g_strdup (session);
214 display_get_default_session (Display *display)
216 return display->priv->default_session;
220 display_set_pam_service (Display *display, const gchar *service)
222 g_free (display->priv->pam_service);
223 display->priv->pam_service = g_strdup (service);
227 display_get_pam_service (Display *display)
229 return display->priv->pam_service;
233 display_set_xserver (Display *display, XServer *xserver)
235 if (display->priv->xserver)
236 g_object_unref (display->priv->xserver);
237 display->priv->xserver = g_object_ref (xserver);
241 display_get_xserver (Display *display)
243 return display->priv->xserver;
246 static struct passwd *
247 get_user_info (const gchar *username)
249 struct passwd *user_info;
252 user_info = getpwnam (username);
256 g_warning ("Unable to get information on user %s: User does not exist", username);
258 g_warning ("Unable to get information on user %s: %s", username, strerror (errno));
265 start_ck_session (Display *display, const gchar *session_type, const gchar *username)
268 char *display_device = NULL;
269 const gchar *address, *hostname = "";
270 struct passwd *user_info;
271 GVariantBuilder arg_builder;
273 gchar *cookie = NULL;
274 GError *error = NULL;
276 user_info = get_user_info (username);
280 if (xserver_get_vt (display->priv->xserver) >= 0)
281 display_device = g_strdup_printf ("/dev/tty%d", xserver_get_vt (display->priv->xserver));
282 address = xserver_get_address (display->priv->xserver);
284 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
285 G_DBUS_PROXY_FLAGS_NONE,
287 "org.freedesktop.ConsoleKit",
288 "/org/freedesktop/ConsoleKit/Manager",
289 "org.freedesktop.ConsoleKit.Manager",
291 g_variant_builder_init (&arg_builder, G_VARIANT_TYPE ("(a(sv))"));
292 g_variant_builder_open (&arg_builder, G_VARIANT_TYPE ("a(sv)"));
293 g_variant_builder_add (&arg_builder, "(sv)", "unix-user", g_variant_new_int32 (user_info->pw_uid));
294 g_variant_builder_add (&arg_builder, "(sv)", "session-type", g_variant_new_string (session_type));
295 g_variant_builder_add (&arg_builder, "(sv)", "x11-display", g_variant_new_string (address));
297 g_variant_builder_add (&arg_builder, "(sv)", "x11-display-device", g_variant_new_string (display_device));
298 g_variant_builder_add (&arg_builder, "(sv)", "remote-host-name", g_variant_new_string (hostname));
299 g_variant_builder_add (&arg_builder, "(sv)", "is-local", g_variant_new_boolean (TRUE));
300 g_variant_builder_close (&arg_builder);
301 result = g_dbus_proxy_call_sync (proxy,
302 "OpenSessionWithParameters",
303 g_variant_builder_end (&arg_builder),
304 G_DBUS_CALL_FLAGS_NONE,
308 g_object_unref (proxy);
309 g_free (display_device);
311 g_warning ("Failed to open CK session: %s", error->message);
312 g_clear_error (&error);
316 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
317 g_variant_get (result, "(s)", &cookie);
319 g_warning ("Unexpected response from OpenSessionWithParameters: %s", g_variant_get_type_string (result));
320 g_variant_unref (result);
323 g_debug ("Opened ConsoleKit session %s", cookie);
329 end_ck_session (const gchar *cookie)
333 GError *error = NULL;
338 g_debug ("Ending ConsoleKit session %s", cookie);
340 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
341 G_DBUS_PROXY_FLAGS_NONE,
343 "org.freedesktop.ConsoleKit",
344 "/org/freedesktop/ConsoleKit/Manager",
345 "org.freedesktop.ConsoleKit.Manager",
347 result = g_dbus_proxy_call_sync (proxy,
349 g_variant_new ("(s)", cookie),
350 G_DBUS_CALL_FLAGS_NONE,
354 g_object_unref (proxy);
357 g_warning ("Error ending ConsoleKit session: %s", error->message);
358 g_clear_error (&error);
362 if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
365 g_variant_get (result, "(b)", &is_closed);
367 g_warning ("ConsoleKit.Manager.CloseSession() returned false");
370 g_warning ("Unexpected response from CloseSession: %s", g_variant_get_type_string (result));
372 g_variant_unref (result);
376 run_script (const gchar *script)
382 end_user_session (Display *display, gboolean clean_exit)
384 run_script ("PostSession");
386 g_signal_emit (display, signals[END_SESSION], 0, display->priv->user_session);
388 if (display->priv->user_session_timer)
390 g_source_remove (display->priv->user_session_timer);
391 display->priv->user_session_timer = 0;
394 g_object_unref (display->priv->user_session);
395 display->priv->user_session = NULL;
397 pam_session_end (display->priv->user_pam_session);
398 g_object_unref (display->priv->user_pam_session);
399 display->priv->user_pam_session = NULL;
401 end_ck_session (display->priv->user_ck_cookie);
402 g_free (display->priv->user_ck_cookie);
403 display->priv->user_ck_cookie = NULL;
406 g_warning ("Session exited unexpectedly");
408 xserver_disconnect_clients (display->priv->xserver);
412 user_session_exited_cb (Session *session, gint status, Display *display)
414 end_user_session (display, status == 0);
418 user_session_terminated_cb (Session *session, gint signum, Display *display)
420 end_user_session (display, FALSE);
424 set_env_from_pam_session (Session *session, PAMSession *pam_session)
428 pam_env = pam_session_get_envlist (pam_session);
434 env_string = g_strjoinv (" ", pam_env);
435 g_debug ("PAM returns environment %s", env_string);
438 for (i = 0; pam_env[i]; i++)
440 gchar **pam_env_vars = g_strsplit (pam_env[i], "=", 2);
441 if (pam_env_vars && pam_env_vars[0] && pam_env_vars[1])
442 child_process_set_env (CHILD_PROCESS (session), pam_env_vars[0], pam_env_vars[1]);
444 g_warning ("Can't parse PAM environment variable %s", pam_env[i]);
445 g_strfreev (pam_env_vars);
447 g_strfreev (pam_env);
452 set_env_from_keyfile (Session *session, const gchar *name, GKeyFile *key_file, const gchar *section, const gchar *key)
456 value = g_key_file_get_string (key_file, section, key, NULL);
460 child_process_set_env (CHILD_PROCESS (session), name, value);
465 start_user_session (Display *display, const gchar *session, const gchar *language)
467 gchar *filename, *path, *old_language;
468 struct passwd *user_info;
469 GKeyFile *dmrc_file, *session_desktop_file;
470 gboolean have_dmrc = FALSE, result;
471 GError *error = NULL;
473 run_script ("PreSession");
475 g_debug ("Launching '%s' session for user %s", session, pam_session_get_username (display->priv->user_pam_session));
476 display->priv->login_count++;
478 /* Load the users login settings (~/.dmrc) */
479 dmrc_file = g_key_file_new ();
480 user_info = get_user_info (pam_session_get_username (display->priv->user_pam_session));
483 /* Load from the user directory, if this fails (e.g. the user directory
484 * is not yet mounted) then load from the cache */
485 path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
486 have_dmrc = g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, NULL);
490 /* If no .dmrc, then load from the cache */
493 filename = g_strdup_printf ("%s.dmrc", user_info->pw_name);
494 path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
496 if (!g_key_file_load_from_file (dmrc_file, path, G_KEY_FILE_KEEP_COMMENTS, &error))
497 g_warning ("Failed to load .dmrc file %s: %s", path, error->message);
498 g_clear_error (&error);
502 /* Update the .dmrc with changed settings */
503 g_key_file_set_string (dmrc_file, "Desktop", "Session", session);
504 old_language = g_key_file_get_string (dmrc_file, "Desktop", "Language", NULL);
505 if (language && (!old_language || !g_str_equal(language, old_language)))
507 g_key_file_set_string (dmrc_file, "Desktop", "Language", language);
508 /* We don't have advanced language checking, so reset these variables */
509 g_key_file_remove_key (dmrc_file, "Desktop", "Langlist", NULL);
510 g_key_file_remove_key (dmrc_file, "Desktop", "LCMess", NULL);
512 g_free (old_language);
513 if (!g_key_file_has_key (dmrc_file, "Desktop", "Layout", NULL))
514 g_key_file_set_string (dmrc_file, "Desktop", "Layout", display->priv->default_layout);
516 filename = g_strdup_printf ("%s.desktop", session);
517 path = g_build_filename (XSESSIONS_DIR, filename, NULL);
520 session_desktop_file = g_key_file_new ();
521 result = g_key_file_load_from_file (session_desktop_file, path, G_KEY_FILE_NONE, &error);
525 g_warning ("Failed to load session file %s: %s:", path, error->message);
526 g_clear_error (&error);
530 gchar *session_command;
532 session_command = g_key_file_get_string (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL);
533 if (!session_command)
534 g_warning ("No command in session file %s", path);
536 display->priv->supports_transitions = g_key_file_get_boolean (session_desktop_file, G_KEY_FILE_DESKTOP_GROUP, "X-LightDM-Supports-Transitions", NULL);
543 if (display->priv->session_wrapper)
545 gchar *old_command = session_command;
546 session_command = g_strdup_printf ("%s '%s'", display->priv->session_wrapper, session_command);
547 g_free (old_command);
549 display->priv->user_session = session_new ();
550 session_set_username (display->priv->user_session, pam_session_get_username (display->priv->user_pam_session));
551 session_set_command (display->priv->user_session, session_command);
553 g_signal_connect (G_OBJECT (display->priv->user_session), "exited", G_CALLBACK (user_session_exited_cb), display);
554 g_signal_connect (G_OBJECT (display->priv->user_session), "terminated", G_CALLBACK (user_session_terminated_cb), display);
555 child_process_set_env (CHILD_PROCESS (display->priv->user_session), "DISPLAY", xserver_get_address (display->priv->xserver));
556 if (display->priv->user_ck_cookie)
557 child_process_set_env (CHILD_PROCESS (display->priv->user_session), "XDG_SESSION_COOKIE", display->priv->user_ck_cookie);
558 child_process_set_env (CHILD_PROCESS (display->priv->user_session), "DESKTOP_SESSION", session); // FIXME: Apparently deprecated?
559 child_process_set_env (CHILD_PROCESS (display->priv->user_session), "GDMSESSION", session); // FIXME: Not cross-desktop
560 set_env_from_keyfile (display->priv->user_session, "LANG", dmrc_file, "Desktop", "Language");
561 set_env_from_keyfile (display->priv->user_session, "LANGUAGE", dmrc_file, "Desktop", "Langlist");
562 set_env_from_keyfile (display->priv->user_session, "LC_MESSAGES", dmrc_file, "Desktop", "LCMess");
563 //child_process_set_env (CHILD_PROCESS (display->priv->user_session), "GDM_LANG", session_language); // FIXME: Not cross-desktop
564 set_env_from_keyfile (display->priv->user_session, "GDM_KEYBOARD_LAYOUT", dmrc_file, "Desktop", "Layout"); // FIXME: Not cross-desktop
565 set_env_from_pam_session (display->priv->user_session, display->priv->user_pam_session);
567 g_signal_emit (display, signals[START_SESSION], 0, display->priv->user_session);
569 if (display->priv->greeter_session == NULL || display->priv->supports_transitions)
570 session_start (display->priv->user_session, FALSE);
572 g_debug ("Waiting for greeter to quit before starting user session process");
574 data = g_key_file_to_data (dmrc_file, &length, NULL);
576 /* Update the users .dmrc */
579 path = g_build_filename (user_info->pw_dir, ".dmrc", NULL);
580 g_file_set_contents (path, data, length, NULL);
581 if (chown (path, user_info->pw_uid, user_info->pw_gid) < 0)
582 g_warning ("Error setting ownership on %s: %s", path, strerror (errno));
586 /* Update the .dmrc cache */
587 path = g_build_filename (CACHE_DIR, "dmrc", NULL);
588 g_mkdir_with_parents (path, 0700);
590 filename = g_strdup_printf ("%s.dmrc", pam_session_get_username (display->priv->user_pam_session));
591 path = g_build_filename (CACHE_DIR, "dmrc", filename, NULL);
592 g_file_set_contents (path, data, length, NULL);
598 g_free (session_command);
601 g_key_file_free (session_desktop_file);
602 g_key_file_free (dmrc_file);
606 start_default_session (Display *display, const gchar *session, const gchar *language)
608 /* Don't need to check authentication, just authorize */
609 // FIXME: Not correct, should use lightdm-autologin pam session
610 if (display->priv->user_pam_session)
611 pam_session_end (display->priv->user_pam_session);
612 display->priv->user_pam_session = pam_session_new (display->priv->pam_service, display->priv->default_user);
613 pam_session_authorize (display->priv->user_pam_session);
615 display->priv->user_ck_cookie = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
616 start_user_session (display, session, language);
620 session_timeout_cb (Display *display)
622 g_warning ("Session has not indicated it is ready, stopping greeter anyway");
624 /* Stop the greeter */
625 greeter_quit (display->priv->greeter_session);
627 display->priv->user_session_timer = 0;
632 greeter_start_session_cb (Greeter *greeter, const gchar *session, const gchar *language, Display *display)
634 /* Default session requested */
635 if (strcmp (session, "") == 0)
636 session = display->priv->default_session;
638 /* Default language requested */
639 if (strcmp (language, "") == 0)
642 display->priv->user_pam_session = greeter_get_pam_session (greeter);
643 display->priv->user_ck_cookie = start_ck_session (display, "", pam_session_get_username (display->priv->user_pam_session));
645 if (!display->priv->user_pam_session ||
646 !pam_session_get_in_session (display->priv->user_pam_session))
648 g_warning ("Ignoring request for login with unauthenticated user");
652 start_user_session (display, session, language);
654 /* Stop session, waiting for user session to indicate it is ready (if supported) */
655 // FIXME: Hard-coded timeout
656 // FIXME: Greeter quit timeout
657 if (display->priv->supports_transitions)
658 display->priv->user_session_timer = g_timeout_add (USER_SESSION_TIMEOUT, (GSourceFunc) session_timeout_cb, display);
660 greeter_quit (display->priv->greeter_session);
664 greeter_quit_cb (Greeter *greeter, Display *display)
666 g_debug ("Greeter quit");
668 g_signal_emit (display, signals[END_GREETER], 0, display->priv->greeter_session);
670 pam_session_end (display->priv->greeter_pam_session);
671 g_object_unref (display->priv->greeter_pam_session);
672 display->priv->greeter_pam_session = NULL;
674 g_object_unref (display->priv->greeter_session);
675 display->priv->greeter_session = NULL;
677 end_ck_session (display->priv->greeter_ck_cookie);
678 g_free (display->priv->greeter_ck_cookie);
679 display->priv->greeter_ck_cookie = NULL;
681 /* Start session if waiting for greeter to quit */
682 if (display->priv->user_session && child_process_get_pid (CHILD_PROCESS (display->priv->user_session)) == 0)
684 g_debug ("Starting user session");
685 session_start (display->priv->user_session, FALSE);
690 start_greeter (Display *display)
693 GError *error = NULL;
695 theme = load_theme (display->priv->greeter_theme, &error);
697 g_warning ("Failed to find theme %s: %s", display->priv->greeter_theme, error->message);
698 g_clear_error (&error);
703 gchar *username = NULL;
705 g_debug ("Starting greeter %s as user %s", display->priv->greeter_theme,
706 display->priv->greeter_user ? display->priv->greeter_user : "<current>");
708 command = theme_get_command (theme);
710 if (display->priv->greeter_user)
711 username = display->priv->greeter_user;
714 struct passwd *user_info;
715 user_info = getpwuid (getuid ());
718 g_warning ("Unable to determine current username: %s", strerror (errno));
721 username = user_info->pw_name;
724 display->priv->greeter_pam_session = pam_session_new (display->priv->pam_service, username);
725 pam_session_authorize (display->priv->greeter_pam_session);
727 display->priv->greeter_ck_cookie = start_ck_session (display,
731 display->priv->greeter_session = greeter_new ();
732 greeter_set_theme (display->priv->greeter_session, display->priv->greeter_theme);
733 greeter_set_default_user (display->priv->greeter_session, display->priv->default_user, display->priv->timeout);
734 greeter_set_layout (display->priv->greeter_session, display->priv->default_layout);
735 greeter_set_session (display->priv->greeter_session, display->priv->default_session);
736 g_signal_connect (G_OBJECT (display->priv->greeter_session), "start-session", G_CALLBACK (greeter_start_session_cb), display);
737 g_signal_connect (G_OBJECT (display->priv->greeter_session), "quit", G_CALLBACK (greeter_quit_cb), display);
738 session_set_username (SESSION (display->priv->greeter_session), username);
739 session_set_command (SESSION (display->priv->greeter_session), command);
740 child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "DISPLAY", xserver_get_address (display->priv->xserver));
741 if (display->priv->greeter_ck_cookie)
742 child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "XDG_SESSION_COOKIE", display->priv->greeter_ck_cookie);
743 set_env_from_pam_session (SESSION (display->priv->greeter_session), display->priv->greeter_pam_session);
745 g_signal_emit (display, signals[START_GREETER], 0, display->priv->greeter_session);
747 session_start (SESSION (display->priv->greeter_session), TRUE);
750 g_key_file_free (theme);
755 end_display (Display *display)
757 g_object_unref (display->priv->xserver);
758 display->priv->xserver = NULL;
759 g_signal_emit (display, signals[EXITED], 0);
763 xserver_exit_cb (XServer *server, int status, Display *display)
766 g_warning ("X server exited with value %d", status);
767 end_display (display);
771 xserver_terminate_cb (XServer *server, int signum, Display *display)
773 g_warning ("X server terminated with signal %d", signum);
774 end_display (display);
778 xserver_ready_cb (XServer *xserver, Display *display)
780 run_script ("Init"); // FIXME: Async
782 /* Don't run any sessions on local terminals */
783 if (xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL_TERMINAL)
786 /* If have user then automatically login the first time */
787 if (display->priv->default_user && display->priv->timeout == 0 && display->priv->login_count == 0)
788 start_default_session (display, display->priv->default_session, NULL);
790 start_greeter (display);
794 display_start (Display *display)
796 g_return_val_if_fail (display->priv->xserver != NULL, FALSE);
797 g_signal_connect (G_OBJECT (display->priv->xserver), "ready", G_CALLBACK (xserver_ready_cb), display);
798 g_signal_connect (G_OBJECT (display->priv->xserver), "exited", G_CALLBACK (xserver_exit_cb), display);
799 g_signal_connect (G_OBJECT (display->priv->xserver), "terminated", G_CALLBACK (xserver_terminate_cb), display);
800 return xserver_start (display->priv->xserver);
804 display_init (Display *display)
806 display->priv = G_TYPE_INSTANCE_GET_PRIVATE (display, DISPLAY_TYPE, DisplayPrivate);
807 if (strcmp (GREETER_USER, "") != 0)
808 display->priv->greeter_user = g_strdup (GREETER_USER);
809 display->priv->greeter_theme = g_strdup (GREETER_THEME);
810 display->priv->default_layout = g_strdup ("us"); // FIXME: Is there a better default to get?
811 display->priv->default_session = g_strdup (DEFAULT_SESSION);
815 display_finalize (GObject *object)
819 self = DISPLAY (object);
821 if (self->priv->greeter_session)
822 g_object_unref (self->priv->greeter_session);
823 if (self->priv->user_session_timer)
824 g_source_remove (self->priv->user_session_timer);
825 if (self->priv->user_session)
826 g_object_unref (self->priv->user_session);
827 if (self->priv->user_pam_session)
828 g_object_unref (self->priv->user_pam_session);
829 end_ck_session (self->priv->greeter_ck_cookie);
830 g_free (self->priv->greeter_ck_cookie);
831 end_ck_session (self->priv->user_ck_cookie);
832 g_free (self->priv->user_ck_cookie);
833 if (self->priv->xserver)
834 g_object_unref (self->priv->xserver);
835 g_free (self->priv->greeter_user);
836 g_free (self->priv->greeter_theme);
837 g_free (self->priv->default_user);
838 g_free (self->priv->default_layout);
839 g_free (self->priv->default_session);
841 G_OBJECT_CLASS (display_parent_class)->finalize (object);
845 display_class_init (DisplayClass *klass)
847 GObjectClass *object_class = G_OBJECT_CLASS (klass);
849 object_class->finalize = display_finalize;
851 g_type_class_add_private (klass, sizeof (DisplayPrivate));
853 signals[START_GREETER] =
854 g_signal_new ("start-greeter",
855 G_TYPE_FROM_CLASS (klass),
857 G_STRUCT_OFFSET (DisplayClass, start_greeter),
859 g_cclosure_marshal_VOID__OBJECT,
860 G_TYPE_NONE, 1, SESSION_TYPE);
862 signals[END_GREETER] =
863 g_signal_new ("end-greeter",
864 G_TYPE_FROM_CLASS (klass),
866 G_STRUCT_OFFSET (DisplayClass, end_greeter),
868 g_cclosure_marshal_VOID__OBJECT,
869 G_TYPE_NONE, 1, SESSION_TYPE);
871 signals[START_SESSION] =
872 g_signal_new ("start-session",
873 G_TYPE_FROM_CLASS (klass),
875 G_STRUCT_OFFSET (DisplayClass, start_session),
877 g_cclosure_marshal_VOID__OBJECT,
878 G_TYPE_NONE, 1, SESSION_TYPE);
880 signals[END_SESSION] =
881 g_signal_new ("end-session",
882 G_TYPE_FROM_CLASS (klass),
884 G_STRUCT_OFFSET (DisplayClass, end_session),
886 g_cclosure_marshal_VOID__OBJECT,
887 G_TYPE_NONE, 1, SESSION_TYPE);
890 g_signal_new ("exited",
891 G_TYPE_FROM_CLASS (klass),
893 G_STRUCT_OFFSET (DisplayClass, exited),
895 g_cclosure_marshal_VOID__VOID,