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
17 #include "configuration.h"
18 #include "guest-account.h"
20 #include "session-config.h"
29 static guint signals[LAST_SIGNAL] = { 0 };
33 /* XDG name for this seat */
36 /* Configuration for this seat */
37 GHashTable *properties;
39 /* TRUE if this seat can run multiple sessions at once */
40 gboolean supports_multi_session;
42 /* TRUE if display server can be shared for sessions */
43 gboolean share_display_server;
45 /* The display servers on this seat */
46 GList *display_servers;
48 /* The sessions on this seat */
51 /* The last session set to active */
52 Session *active_session;
54 /* The session belonging to the active greeter user */
55 Session *next_session;
57 /* The session to set active when it starts */
58 Session *session_to_activate;
60 /* TRUE once we have started */
63 /* TRUE if stopping this seat (waiting for displays to stop) */
70 static void seat_logger_iface_init (LoggerInterface *iface);
72 G_DEFINE_TYPE_WITH_CODE (Seat, seat, G_TYPE_OBJECT,
73 G_IMPLEMENT_INTERFACE (
74 LOGGER_TYPE, seat_logger_iface_init));
81 static GHashTable *seat_modules = NULL;
83 // FIXME: Make a get_display_server() that re-uses display servers if supported
84 static DisplayServer *create_display_server (Seat *seat, Session *session);
85 static Greeter *create_greeter_session (Seat *seat);
86 static void start_session (Seat *seat, Session *session);
89 seat_register_module (const gchar *name, GType type)
94 seat_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
96 g_debug ("Registered seat module %s", name);
98 module = g_malloc0 (sizeof (SeatModule));
99 module->name = g_strdup (name);
101 g_hash_table_insert (seat_modules, g_strdup (name), module);
105 seat_new (const gchar *module_name, const gchar *name)
108 SeatModule *m = NULL;
110 g_return_val_if_fail (module_name != NULL, NULL);
113 m = g_hash_table_lookup (seat_modules, module_name);
117 seat = g_object_new (m->type, NULL);
118 seat->priv->name = g_strdup (name);
124 seat_set_property (Seat *seat, const gchar *name, const gchar *value)
126 g_return_if_fail (seat != NULL);
127 g_hash_table_insert (seat->priv->properties, g_strdup (name), g_strdup (value));
131 seat_get_string_property (Seat *seat, const gchar *name)
133 g_return_val_if_fail (seat != NULL, NULL);
134 return g_hash_table_lookup (seat->priv->properties, name);
138 seat_get_string_list_property (Seat *seat, const gchar *name)
140 g_return_val_if_fail (seat != NULL, NULL);
141 return g_strsplit (g_hash_table_lookup (seat->priv->properties, name), ";", 0);
145 seat_get_boolean_property (Seat *seat, const gchar *name)
147 return g_strcmp0 (seat_get_string_property (seat, name), "true") == 0;
151 seat_get_integer_property (Seat *seat, const gchar *name)
155 value = seat_get_string_property (seat, name);
156 return value ? atoi (value) : 0;
160 seat_get_name (Seat *seat)
162 return seat->priv->name;
166 seat_set_supports_multi_session (Seat *seat, gboolean supports_multi_session)
168 g_return_if_fail (seat != NULL);
169 seat->priv->supports_multi_session = supports_multi_session;
173 seat_set_share_display_server (Seat *seat, gboolean share_display_server)
175 g_return_if_fail (seat != NULL);
176 seat->priv->share_display_server = share_display_server;
180 seat_start (Seat *seat)
182 g_return_val_if_fail (seat != NULL, FALSE);
184 l_debug (seat, "Starting");
186 SEAT_GET_CLASS (seat)->setup (seat);
187 seat->priv->started = SEAT_GET_CLASS (seat)->start (seat);
189 return seat->priv->started;
193 seat_get_sessions (Seat *seat)
195 g_return_val_if_fail (seat != NULL, NULL);
196 return seat->priv->sessions;
200 set_greeter_idle (gpointer greeter)
202 greeter_idle (GREETER (greeter));
207 seat_set_active_session (Seat *seat, Session *session)
211 g_return_if_fail (seat != NULL);
213 SEAT_GET_CLASS (seat)->set_active_session (seat, session);
215 /* Stop any greeters */
216 for (link = seat->priv->sessions; link; link = link->next)
218 Session *s = link->data;
220 if (s == session || session_get_is_stopping (s))
225 Greeter *greeter = GREETER (s);
226 if (greeter_get_resettable (greeter))
228 if (seat->priv->active_session == SESSION (greeter))
230 l_debug (seat, "Idling greeter");
231 /* Do this in an idle callback, because we might very well
232 be in the middle of responding to a START_SESSION
233 request by a greeter. So they won't expect an IDLE
234 call during that. Plus, this isn't time-sensitive. */
235 g_idle_add (set_greeter_idle, greeter);
240 l_debug (seat, "Stopping greeter");
246 /* Lock previous sessions */
247 if (seat->priv->active_session)
249 if (session != seat->priv->active_session && !IS_GREETER (seat->priv->active_session))
250 session_lock (seat->priv->active_session);
251 g_object_unref (seat->priv->active_session);
254 session_activate (session);
255 seat->priv->active_session = g_object_ref (session);
259 seat_get_active_session (Seat *seat)
261 g_return_val_if_fail (seat != NULL, NULL);
262 return SEAT_GET_CLASS (seat)->get_active_session (seat);
266 seat_get_next_session (Seat *seat)
268 g_return_val_if_fail (seat != NULL, NULL);
269 return seat->priv->next_session;
273 seat_get_can_switch (Seat *seat)
275 g_return_val_if_fail (seat != NULL, FALSE);
276 return seat_get_boolean_property (seat, "allow-user-switching") && seat->priv->supports_multi_session;
280 seat_get_allow_guest (Seat *seat)
282 g_return_val_if_fail (seat != NULL, FALSE);
283 return seat_get_boolean_property (seat, "allow-guest") && guest_account_is_installed ();
287 run_script (Seat *seat, DisplayServer *display_server, const gchar *script_name, User *user)
290 gboolean result = FALSE;
292 script = process_new (NULL, NULL);
294 process_set_command (script, script_name);
296 /* Set POSIX variables */
297 process_set_clear_environment (script, TRUE);
298 process_set_env (script, "SHELL", "/bin/sh");
300 /* Variables required for regression tests */
301 if (g_getenv ("LIGHTDM_TEST_ROOT"))
303 process_set_env (script, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
304 process_set_env (script, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
305 process_set_env (script, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
306 process_set_env (script, "PATH", g_getenv ("PATH"));
309 process_set_env (script, "PATH", "/usr/local/bin:/usr/bin:/bin");
313 process_set_env (script, "USER", user_get_name (user));
314 process_set_env (script, "LOGNAME", user_get_name (user));
315 process_set_env (script, "HOME", user_get_home_directory (user));
318 process_set_env (script, "HOME", "/");
320 SEAT_GET_CLASS (seat)->run_script (seat, display_server, script);
322 if (process_start (script, TRUE))
326 exit_status = process_get_exit_status (script);
327 if (WIFEXITED (exit_status))
329 l_debug (seat, "Exit status of %s: %d", script_name, WEXITSTATUS (exit_status));
330 result = WEXITSTATUS (exit_status) == EXIT_SUCCESS;
334 g_object_unref (script);
340 seat_real_run_script (Seat *seat, DisplayServer *display_server, Process *process)
345 emit_upstart_signal (const gchar *signal)
347 g_return_if_fail (signal != NULL);
348 g_return_if_fail (signal[0] != 0);
353 gchar *cmd = g_strdup_printf ("initctl -q emit %s DISPLAY_MANAGER=lightdm", signal);
354 g_spawn_command_line_async (cmd, NULL); /* OK if it fails, probably not installed */
359 check_stopped (Seat *seat)
361 if (seat->priv->stopping &&
362 !seat->priv->stopped &&
363 g_list_length (seat->priv->display_servers) == 0 &&
364 g_list_length (seat->priv->sessions) == 0)
366 seat->priv->stopped = TRUE;
367 l_debug (seat, "Stopped");
368 g_signal_emit (seat, signals[STOPPED], 0);
373 display_server_stopped_cb (DisplayServer *display_server, Seat *seat)
377 Session *active_session;
379 l_debug (seat, "Display server stopped");
381 /* Run a script right after stopping the display server */
382 script = seat_get_string_property (seat, "display-stopped-script");
384 run_script (seat, NULL, script, NULL);
386 g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
387 seat->priv->display_servers = g_list_remove (seat->priv->display_servers, display_server);
389 if (seat->priv->stopping || !seat->priv->started)
391 check_stopped (seat);
392 g_object_unref (display_server);
396 /* Stop all sessions on this display server */
397 list = g_list_copy (seat->priv->sessions);
398 for (link = list; link; link = link->next)
399 g_object_ref (link->data);
400 for (link = list; link; link = link->next)
402 Session *session = link->data;
404 if (session_get_display_server (session) != display_server || session_get_is_stopping (session))
407 /* Stop seat if this is the only display server and it failed to start a greeter */
408 if (IS_GREETER (session) &&
409 !session_get_is_started (session) &&
410 g_list_length (seat->priv->display_servers) == 0)
412 l_debug (seat, "Stopping; greeter display server failed to start");
416 l_debug (seat, "Stopping session");
417 session_stop (session);
419 g_list_free_full (list, g_object_unref);
421 if (!seat->priv->stopping)
423 /* If we were the active session, switch to a greeter */
424 active_session = seat_get_active_session (seat);
425 if (!active_session || session_get_display_server (active_session) == display_server)
427 l_debug (seat, "Active display server stopped, starting greeter");
428 if (!seat_switch_to_greeter (seat))
430 l_debug (seat, "Stopping; failed to start a greeter");
436 g_object_unref (display_server);
440 can_share_display_server (Seat *seat, DisplayServer *display_server)
442 return seat->priv->share_display_server && display_server_get_can_share (display_server);
446 find_greeter_session (Seat *seat)
450 for (link = seat->priv->sessions; link; link = link->next)
452 Session *session = link->data;
453 if (!session_get_is_stopping (session) && IS_GREETER (session))
454 return GREETER (session);
461 find_resettable_greeter (Seat *seat)
465 for (link = seat->priv->sessions; link; link = link->next)
467 Session *session = link->data;
468 if (!session_get_is_stopping (session) && IS_GREETER (session) &&
469 greeter_get_resettable (GREETER (session)))
470 return GREETER (session);
477 set_greeter_hints (Seat *seat, Greeter *greeter_session)
479 greeter_clear_hints (greeter_session);
480 greeter_set_hint (greeter_session, "default-session", seat_get_string_property (seat, "user-session"));
481 greeter_set_hint (greeter_session, "hide-users", seat_get_boolean_property (seat, "greeter-hide-users") ? "true" : "false");
482 greeter_set_hint (greeter_session, "show-manual-login", seat_get_boolean_property (seat, "greeter-show-manual-login") ? "true" : "false");
483 greeter_set_hint (greeter_session, "show-remote-login", seat_get_boolean_property (seat, "greeter-show-remote-login") ? "true" : "false");
484 greeter_set_hint (greeter_session, "has-guest-account", seat_get_allow_guest (seat) && seat_get_boolean_property (seat, "greeter-allow-guest") ? "true" : "false");
488 switch_to_greeter_from_failed_session (Seat *seat, Session *session)
490 Greeter *greeter_session;
491 gboolean existing = FALSE;
493 /* Switch to greeter if one open */
494 greeter_session = find_resettable_greeter (seat);
497 l_debug (seat, "Switching to existing greeter");
498 set_greeter_hints (seat, greeter_session);
503 greeter_session = create_greeter_session (seat);
506 if (session_get_is_guest (session))
507 greeter_set_hint (greeter_session, "select-guest", "true");
509 greeter_set_hint (greeter_session, "select-user", session_get_username (session));
513 greeter_reset (greeter_session);
514 seat_set_active_session (seat, SESSION (greeter_session));
518 if (seat->priv->session_to_activate)
519 g_object_unref (seat->priv->session_to_activate);
520 seat->priv->session_to_activate = g_object_ref (greeter_session);
522 if (can_share_display_server (seat, session_get_display_server (session)))
523 session_set_display_server (SESSION (greeter_session), session_get_display_server (session));
526 DisplayServer *display_server;
528 display_server = create_display_server (seat, session);
529 session_set_display_server (session, display_server);
530 if (!display_server_start (display_server))
532 l_debug (seat, "Failed to start display server for greeter");
537 start_session (seat, SESSION (greeter_session));
540 /* Stop failed session */
541 session_stop (session);
545 start_session (Seat *seat, Session *session)
547 /* Use system location for greeter log file */
548 if (IS_GREETER (session))
550 gchar *log_dir, *filename, *log_filename;
552 log_dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
553 filename = g_strdup_printf ("%s-greeter.log", display_server_get_name (session_get_display_server (session)));
554 log_filename = g_build_filename (log_dir, filename, NULL);
557 session_set_log_file (session, log_filename);
558 g_free (log_filename);
561 if (session_start (session))
564 if (IS_GREETER (session))
566 l_debug (seat, "Failed to start greeter");
567 display_server_stop (session_get_display_server (session));
571 l_debug (seat, "Failed to start session, starting greeter");
572 switch_to_greeter_from_failed_session (seat, session);
576 run_session (Seat *seat, Session *session)
580 if (IS_GREETER (session))
581 script = seat_get_string_property (seat, "greeter-setup-script");
583 script = seat_get_string_property (seat, "session-setup-script");
584 if (script && !run_script (seat, session_get_display_server (session), script, session_get_user (session)))
586 l_debug (seat, "Switching to greeter due to failed setup script");
587 switch_to_greeter_from_failed_session (seat, session);
591 if (!IS_GREETER (session))
593 g_signal_emit (seat, signals[RUNNING_USER_SESSION], 0, session);
594 emit_upstart_signal ("desktop-session-start");
597 session_run (session);
599 // FIXME: Wait until the session is ready
601 if (session == seat->priv->session_to_activate)
603 seat_set_active_session (seat, session);
604 g_object_unref (seat->priv->session_to_activate);
605 seat->priv->session_to_activate = NULL;
607 else if (seat->priv->active_session)
609 /* Multiple sessions can theoretically be on the same VT (especially
610 if using Mir). If a new session appears on an existing active VT,
611 logind will mark it as active which may not be the
612 session that we want to be active. So let's be explicit and
613 re-activate the correct session whenever a new session starts.
614 There's no harm to do this in seats that enforce separate VTs. */
615 session_activate (seat->priv->active_session);
620 find_user_session (Seat *seat, const gchar *username, Session *ignore_session)
627 for (link = seat->priv->sessions; link; link = link->next)
629 Session *session = link->data;
631 if (session == ignore_session)
634 if (!session_get_is_stopping (session) && g_strcmp0 (session_get_username (session), username) == 0)
642 greeter_active_username_changed_cb (Greeter *greeter, GParamSpec *pspec, Seat *seat)
646 session = find_user_session (seat, greeter_get_active_username (greeter), seat->priv->active_session);
648 if (seat->priv->next_session)
649 g_object_unref (seat->priv->next_session);
650 seat->priv->next_session = session ? g_object_ref (session) : NULL;
652 SEAT_GET_CLASS (seat)->set_next_session (seat, session);
656 session_authentication_complete_cb (Session *session, Seat *seat)
658 if (session_get_is_authenticated (session))
662 s = find_user_session (seat, session_get_username (session), session);
665 l_debug (seat, "Session authenticated, switching to existing user session");
666 seat_set_active_session (seat, s);
667 session_stop (session);
671 l_debug (seat, "Session authenticated, running command");
672 run_session (seat, session);
675 else if (!IS_GREETER (session))
677 l_debug (seat, "Switching to greeter due to failed authentication");
678 switch_to_greeter_from_failed_session (seat, session);
682 l_debug (seat, "Stopping session that failed authentication");
683 session_stop (session);
688 session_stopped_cb (Session *session, Seat *seat)
690 DisplayServer *display_server;
692 l_debug (seat, "Session stopped");
694 g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
695 seat->priv->sessions = g_list_remove (seat->priv->sessions, session);
696 if (session == seat->priv->active_session)
698 g_object_unref (seat->priv->active_session);
699 seat->priv->active_session = NULL;
701 if (session == seat->priv->next_session)
703 g_object_unref (seat->priv->next_session);
704 seat->priv->next_session = NULL;
706 if (session == seat->priv->session_to_activate)
708 g_object_unref (seat->priv->session_to_activate);
709 seat->priv->session_to_activate = NULL;
712 display_server = session_get_display_server (session);
715 g_object_unref (session);
720 if (!IS_GREETER (session))
723 script = seat_get_string_property (seat, "session-cleanup-script");
725 run_script (seat, display_server, script, session_get_user (session));
728 /* We were waiting for this session, but it didn't start :( */
729 // FIXME: Start a greeter on this?
730 if (session == seat->priv->session_to_activate)
732 g_object_unref (seat->priv->session_to_activate);
733 seat->priv->session_to_activate = NULL;
736 if (seat->priv->stopping)
738 check_stopped (seat);
739 g_object_unref (session);
743 /* If this is the greeter session then re-use this display server */
744 if (IS_GREETER (session) &&
745 can_share_display_server (seat, display_server) &&
746 greeter_get_start_session (GREETER (session)))
750 for (link = seat->priv->sessions; link; link = link->next)
752 Session *s = link->data;
754 /* Skip this session and sessions on other display servers */
755 if (s == session || session_get_display_server (s) != display_server || session_get_is_stopping (s))
758 if (session_get_is_authenticated (s))
760 l_debug (seat, "Greeter stopped, running session");
761 run_session (seat, s);
765 l_debug (seat, "Greeter stopped, starting session authentication");
766 start_session (seat, s);
771 /* If this is the greeter and nothing else is running then stop the seat */
772 else if (IS_GREETER (session) &&
773 !greeter_get_start_session (GREETER (session)) &&
774 g_list_length (seat->priv->display_servers) == 1 &&
775 g_list_nth_data (seat->priv->display_servers, 0) == display_server)
777 l_debug (seat, "Stopping; failed to start a greeter");
780 /* If we were the active session, switch to a greeter */
781 else if (!IS_GREETER (session) && session == seat_get_active_session (seat))
783 l_debug (seat, "Active session stopped, starting greeter");
784 if (!seat_switch_to_greeter (seat))
786 l_debug (seat, "Stopping; failed to start a greeter");
791 /* Stop the display server if no-longer required */
792 if (display_server && !display_server_get_is_stopping (display_server))
797 for (link = seat->priv->sessions; link; link = link->next)
799 Session *s = link->data;
802 if (session_get_display_server (s) == display_server)
807 l_debug (seat, "Stopping display server, no sessions require it");
808 display_server_stop (display_server);
812 g_signal_emit (seat, signals[SESSION_REMOVED], 0, session);
813 g_object_unref (session);
817 set_session_env (Session *session)
819 /* Connect using the session bus */
822 if (g_getenv ("DBUS_SESSION_BUS_ADDRESS"))
823 session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
824 session_set_env (session, "LDM_BUS", "SESSION");
825 if (g_getenv ("LD_PRELOAD"))
826 session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
827 if (g_getenv ("LD_LIBRARY_PATH"))
828 session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
829 if (g_getenv ("PATH"))
830 session_set_env (session, "PATH", g_getenv ("PATH"));
833 /* Variables required for regression tests */
834 if (g_getenv ("LIGHTDM_TEST_ROOT"))
836 session_set_env (session, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
837 session_set_env (session, "DBUS_SYSTEM_BUS_ADDRESS", g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
838 session_set_env (session, "DBUS_SESSION_BUS_ADDRESS", g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
839 session_set_env (session, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
840 session_set_env (session, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
841 session_set_env (session, "GI_TYPELIB_PATH", g_getenv ("GI_TYPELIB_PATH"));
846 create_session (Seat *seat, gboolean autostart)
850 session = SEAT_GET_CLASS (seat)->create_session (seat);
851 seat->priv->sessions = g_list_append (seat->priv->sessions, session);
853 g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (session_authentication_complete_cb), seat);
854 g_signal_connect (session, SESSION_SIGNAL_STOPPED, G_CALLBACK (session_stopped_cb), seat);
856 set_session_env (session);
858 g_signal_emit (seat, signals[SESSION_ADDED], 0, session);
864 get_session_argv (Seat *seat, SessionConfig *session_config, const gchar *session_wrapper)
869 GError *error = NULL;
871 /* If configured, run sessions through a wrapper */
874 argv = g_malloc (sizeof (gchar *) * 3);
875 path = g_find_program_in_path (session_wrapper);
876 argv[0] = path ? path : g_strdup (session_wrapper);
877 argv[1] = g_strdup (session_config_get_command (session_config));
882 /* Split command into an array listing and make command absolute */
883 result = g_shell_parse_argv (session_config_get_command (session_config), &argc, &argv, &error);
885 l_debug (seat, "Invalid session command '%s': %s", session_config_get_command (session_config), error->message);
886 g_clear_error (&error);
889 path = g_find_program_in_path (argv[0]);
899 static SessionConfig *
900 find_session_config (Seat *seat, const gchar *sessions_dir, const gchar *session_name)
903 SessionConfig *session_config = NULL;
905 GError *error = NULL;
907 g_return_val_if_fail (sessions_dir != NULL, NULL);
908 g_return_val_if_fail (session_name != NULL, NULL);
910 dirs = g_strsplit (sessions_dir, ":", -1);
911 for (i = 0; dirs[i]; i++)
913 gchar *filename, *path;
915 filename = g_strdup_printf ("%s.desktop", session_name);
916 path = g_build_filename (dirs[i], filename, NULL);
918 session_config = session_config_new_from_file (path, &error);
923 if (dirs[i+1] == NULL)
924 l_debug (seat, "Failed to find session configuration %s", session_name);
925 g_clear_error (&error);
929 return session_config;
933 configure_session (Session *session, SessionConfig *config, const gchar *session_name, const gchar *language)
935 const gchar *desktop_name;
937 session_set_config (session, config);
938 session_set_env (session, "XDG_SESSION_DESKTOP", session_name);
939 session_set_env (session, "DESKTOP_SESSION", session_name);
940 session_set_env (session, "GDMSESSION", session_name);
941 desktop_name = session_config_get_desktop_name (config);
943 session_set_env (session, "XDG_CURRENT_DESKTOP", desktop_name);
944 if (language && language[0] != '\0')
946 session_set_env (session, "LANG", language);
947 session_set_env (session, "GDM_LANG", language);
952 create_user_session (Seat *seat, const gchar *username, gboolean autostart)
956 const gchar *session_name, *language;
957 SessionConfig *session_config;
958 Session *session = NULL;
960 l_debug (seat, "Creating user session");
962 /* Load user preferences */
963 user = accounts_get_user_by_name (username);
966 l_debug (seat, "Can't login unknown user '%s'", username);
969 session_name = user_get_xsession (user);
970 language = user_get_language (user);
973 session_name = seat_get_string_property (seat, "user-session");
974 sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
975 session_config = find_session_config (seat, sessions_dir, session_name);
976 g_free (sessions_dir);
981 session = create_session (seat, autostart);
982 configure_session (session, session_config, session_name, language);
983 session_set_username (session, username);
984 session_set_do_authenticate (session, TRUE);
985 argv = get_session_argv (seat, session_config, seat_get_string_property (seat, "session-wrapper"));
986 session_set_argv (session, argv);
988 g_object_unref (session_config);
991 l_debug (seat, "Can't find session '%s'", session_name);
993 g_object_unref (user);
999 prepend_argv (gchar ***argv, const gchar *value)
1001 gchar **old_argv, **new_argv;
1005 new_argv = g_malloc (sizeof (gchar *) * (g_strv_length (*argv) + 2));
1006 new_argv[0] = g_strdup (value);
1007 for (i = 0; old_argv[i]; i++)
1008 new_argv[i + 1] = old_argv[i];
1009 new_argv[i + 1] = NULL;
1016 create_guest_session (Seat *seat, const gchar *session_name)
1018 const gchar *guest_wrapper;
1019 gchar *sessions_dir, **argv;
1020 SessionConfig *session_config;
1024 session_name = seat_get_string_property (seat, "guest-session");
1026 session_name = seat_get_string_property (seat, "user-session");
1027 sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
1028 session_config = find_session_config (seat, sessions_dir, session_name);
1029 g_free (sessions_dir);
1030 if (!session_config)
1032 l_debug (seat, "Can't find session '%s'", session_name);
1036 session = create_session (seat, TRUE);
1037 configure_session (session, session_config, session_name, NULL);
1038 session_set_do_authenticate (session, TRUE);
1039 session_set_is_guest (session, TRUE);
1040 argv = get_session_argv (seat, session_config, seat_get_string_property (seat, "session-wrapper"));
1041 guest_wrapper = seat_get_string_property (seat, "guest-wrapper");
1045 path = g_find_program_in_path (guest_wrapper);
1046 prepend_argv (&argv, path ? path : guest_wrapper);
1050 session_set_argv (session, argv);
1052 g_object_unref (session_config);
1058 greeter_create_session_cb (Greeter *greeter, Seat *seat)
1062 session = create_session (seat, FALSE);
1063 session_set_config (session, session_get_config (SESSION (greeter)));
1064 session_set_display_server (session, session_get_display_server (SESSION (greeter)));
1066 return g_object_ref (session);
1070 greeter_start_session_cb (Greeter *greeter, SessionType type, const gchar *session_name, Seat *seat)
1072 Session *session, *existing_session;
1073 const gchar *username;
1074 DisplayServer *display_server;
1076 /* Get the session to use */
1077 if (greeter_get_guest_authenticated (greeter))
1079 session = create_guest_session (seat, session_name);
1082 session_set_pam_service (session, seat_get_string_property (seat, "pam-autologin-service"));
1086 const gchar *language = NULL;
1087 SessionConfig *session_config;
1089 gchar *sessions_dir = NULL;
1092 session = greeter_get_authentication_session (greeter);
1094 /* Get session command to run */
1097 case SESSION_TYPE_LOCAL:
1098 sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
1100 case SESSION_TYPE_REMOTE:
1101 sessions_dir = config_get_string (config_get_instance (), "LightDM", "remote-sessions-directory");
1105 /* Load user preferences */
1106 user = session_get_user (session);
1110 session_name = user_get_xsession (user);
1111 language = user_get_language (user);
1115 session_name = seat_get_string_property (seat, "user-session");
1117 user_set_xsession (session_get_user (session), session_name);
1119 session_config = find_session_config (seat, sessions_dir, session_name);
1120 g_free (sessions_dir);
1121 if (!session_config)
1123 l_debug (seat, "Can't find session '%s'", session_name);
1127 configure_session (session, session_config, session_name, language);
1128 argv = get_session_argv (seat, session_config, seat_get_string_property (seat, "session-wrapper"));
1129 session_set_argv (session, argv);
1131 g_object_unref (session_config);
1134 /* Switch to this session when it is ready */
1135 if (seat->priv->session_to_activate)
1136 g_object_unref (seat->priv->session_to_activate);
1137 seat->priv->session_to_activate = g_object_ref (session);
1139 /* Return to existing session if it is open */
1140 username = session_get_username (session);
1141 existing_session = find_user_session (seat, username, NULL);
1142 if (existing_session && session != existing_session)
1144 l_debug (seat, "Returning to existing user session %s", username);
1145 session_stop (session);
1146 session_unlock (existing_session);
1147 seat_set_active_session (seat, existing_session);
1151 /* If can re-use the display server, stop the greeter first */
1152 display_server = session_get_display_server (SESSION (greeter));
1153 if (!greeter_get_resettable (greeter) &&
1154 can_share_display_server (seat, display_server) &&
1155 strcmp (display_server_get_session_type (display_server), session_get_session_type (session)) == 0)
1157 l_debug (seat, "Stopping greeter; display server will be re-used for user session");
1159 /* Run on the same display server after the greeter has stopped */
1160 session_set_display_server (session, display_server);
1162 /* Stop the greeter */
1163 session_stop (SESSION (greeter));
1167 /* Otherwise start a new display server for this session */
1170 display_server = create_display_server (seat, session);
1171 session_set_display_server (session, display_server);
1172 if (!display_server_start (display_server))
1174 l_debug (seat, "Failed to start display server for new session");
1183 create_greeter_session (Seat *seat)
1185 gchar *sessions_dir, **argv;
1186 SessionConfig *session_config;
1187 Greeter *greeter_session;
1188 const gchar *greeter_wrapper;
1189 const gchar *autologin_username;
1190 int autologin_timeout;
1191 gboolean autologin_guest;
1193 l_debug (seat, "Creating greeter session");
1195 sessions_dir = config_get_string (config_get_instance (), "LightDM", "greeters-directory");
1196 session_config = find_session_config (seat, sessions_dir, seat_get_string_property (seat, "greeter-session"));
1197 g_free (sessions_dir);
1198 if (!session_config)
1201 argv = get_session_argv (seat, session_config, NULL);
1202 greeter_wrapper = seat_get_string_property (seat, "greeter-wrapper");
1203 if (greeter_wrapper)
1206 path = g_find_program_in_path (greeter_wrapper);
1207 prepend_argv (&argv, path ? path : greeter_wrapper);
1211 greeter_session = SEAT_GET_CLASS (seat)->create_greeter_session (seat);
1212 session_set_config (SESSION (greeter_session), session_config);
1213 seat->priv->sessions = g_list_append (seat->priv->sessions, SESSION (greeter_session));
1214 g_signal_connect (greeter_session, GREETER_SIGNAL_ACTIVE_USERNAME_CHANGED, G_CALLBACK (greeter_active_username_changed_cb), seat);
1215 g_signal_connect (greeter_session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (session_authentication_complete_cb), seat);
1216 g_signal_connect (greeter_session, SESSION_SIGNAL_STOPPED, G_CALLBACK (session_stopped_cb), seat);
1218 set_session_env (SESSION (greeter_session));
1219 session_set_env (SESSION (greeter_session), "XDG_SESSION_CLASS", "greeter");
1221 session_set_pam_service (SESSION (greeter_session), seat_get_string_property (seat, "pam-greeter-service"));
1224 gchar *greeter_user;
1225 greeter_user = config_get_string (config_get_instance (), "LightDM", "greeter-user");
1226 session_set_username (SESSION (greeter_session), greeter_user);
1227 g_free (greeter_user);
1231 /* In test mode run the greeter as ourself */
1232 session_set_username (SESSION (greeter_session), user_get_name (accounts_get_current_user ()));
1234 session_set_argv (SESSION (greeter_session), argv);
1237 greeter_set_pam_services (greeter_session,
1238 seat_get_string_property (seat, "pam-service"),
1239 seat_get_string_property (seat, "pam-autologin-service"));
1240 g_signal_connect (greeter_session, GREETER_SIGNAL_CREATE_SESSION, G_CALLBACK (greeter_create_session_cb), seat);
1241 g_signal_connect (greeter_session, GREETER_SIGNAL_START_SESSION, G_CALLBACK (greeter_start_session_cb), seat);
1243 /* Set hints to greeter */
1244 greeter_set_allow_guest (greeter_session, seat_get_allow_guest (seat));
1245 set_greeter_hints (seat, greeter_session);
1247 /* Configure for automatic login */
1248 autologin_username = seat_get_string_property (seat, "autologin-user");
1249 if (g_strcmp0 (autologin_username, "") == 0)
1250 autologin_username = NULL;
1251 autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
1252 autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
1253 if (autologin_timeout > 0)
1257 value = g_strdup_printf ("%d", autologin_timeout);
1258 greeter_set_hint (greeter_session, "autologin-timeout", value);
1260 if (autologin_username)
1261 greeter_set_hint (greeter_session, "autologin-user", autologin_username);
1262 if (autologin_guest)
1263 greeter_set_hint (greeter_session, "autologin-guest", "true");
1266 g_object_unref (session_config);
1268 return greeter_session;
1272 find_session_for_display_server (Seat *seat, DisplayServer *display_server)
1276 for (link = seat->priv->sessions; link; link = link->next)
1278 Session *session = link->data;
1279 if (session_get_display_server (session) == display_server && !session_get_is_stopping (session))
1287 display_server_ready_cb (DisplayServer *display_server, Seat *seat)
1289 const gchar *script;
1292 /* Run setup script */
1293 script = seat_get_string_property (seat, "display-setup-script");
1294 if (script && !run_script (seat, display_server, script, NULL))
1296 l_debug (seat, "Stopping display server due to failed setup script");
1297 display_server_stop (display_server);
1301 emit_upstart_signal ("login-session-start");
1303 /* Start the session waiting for this display server */
1304 session = find_session_for_display_server (seat, display_server);
1307 if (session_get_is_authenticated (session))
1309 l_debug (seat, "Display server ready, running session");
1310 run_session (seat, session);
1314 l_debug (seat, "Display server ready, starting session authentication");
1315 start_session (seat, session);
1320 l_debug (seat, "Stopping not required display server");
1321 display_server_stop (display_server);
1325 static DisplayServer *
1326 create_display_server (Seat *seat, Session *session)
1328 DisplayServer *display_server;
1330 l_debug (seat, "Creating display server of type %s", session_get_session_type (session));
1332 display_server = SEAT_GET_CLASS (seat)->create_display_server (seat, session);
1333 if (!display_server)
1336 seat->priv->display_servers = g_list_append (seat->priv->display_servers, display_server);
1337 g_signal_connect (display_server, DISPLAY_SERVER_SIGNAL_READY, G_CALLBACK (display_server_ready_cb), seat);
1338 g_signal_connect (display_server, DISPLAY_SERVER_SIGNAL_STOPPED, G_CALLBACK (display_server_stopped_cb), seat);
1340 return display_server;
1344 seat_switch_to_greeter (Seat *seat)
1346 Greeter *greeter_session;
1347 DisplayServer *display_server;
1349 g_return_val_if_fail (seat != NULL, FALSE);
1351 if (!seat_get_can_switch (seat))
1354 /* Switch to greeter if one open */
1355 greeter_session = find_greeter_session (seat);
1356 if (greeter_session)
1358 l_debug (seat, "Switching to existing greeter");
1359 seat_set_active_session (seat, SESSION (greeter_session));
1363 greeter_session = create_greeter_session (seat);
1364 if (!greeter_session)
1367 if (seat->priv->session_to_activate)
1368 g_object_unref (seat->priv->session_to_activate);
1369 seat->priv->session_to_activate = g_object_ref (greeter_session);
1371 display_server = create_display_server (seat, SESSION (greeter_session));
1372 session_set_display_server (SESSION (greeter_session), display_server);
1374 return display_server_start (display_server);
1378 switch_authentication_complete_cb (Session *session, Seat *seat)
1380 Greeter *greeter_session;
1381 DisplayServer *display_server;
1382 gboolean existing = FALSE;
1384 /* If authenticated, then unlock existing session or start new one */
1385 if (session_get_is_authenticated (session))
1389 s = find_user_session (seat, session_get_username (session), session);
1392 l_debug (seat, "Session authenticated, switching to existing user session");
1394 seat_set_active_session (seat, s);
1395 session_stop (session);
1399 l_debug (seat, "Session authenticated, starting display server");
1400 if (seat->priv->session_to_activate)
1401 g_object_unref (seat->priv->session_to_activate);
1402 seat->priv->session_to_activate = g_object_ref (session);
1403 display_server = create_display_server (seat, session);
1404 session_set_display_server (session, display_server);
1405 display_server_start (display_server);
1411 session_stop (session);
1413 /* See if we already have a greeter up and reuse it if so */
1414 greeter_session = find_resettable_greeter (seat);
1415 if (greeter_session)
1417 l_debug (seat, "Switching to existing greeter to authenticate session");
1418 set_greeter_hints (seat, greeter_session);
1423 l_debug (seat, "Starting greeter to authenticate session");
1424 greeter_session = create_greeter_session (seat);
1427 if (session_get_is_guest (session))
1428 greeter_set_hint (greeter_session, "select-guest", "true");
1430 greeter_set_hint (greeter_session, "select-user", session_get_username (session));
1434 greeter_reset (greeter_session);
1435 seat_set_active_session (seat, SESSION (greeter_session));
1439 if (seat->priv->session_to_activate)
1440 g_object_unref (seat->priv->session_to_activate);
1441 seat->priv->session_to_activate = g_object_ref (greeter_session);
1443 display_server = create_display_server (seat, SESSION (greeter_session));
1444 session_set_display_server (SESSION (greeter_session), display_server);
1445 display_server_start (display_server);
1450 seat_switch_to_user (Seat *seat, const gchar *username, const gchar *session_name)
1454 g_return_val_if_fail (seat != NULL, FALSE);
1455 g_return_val_if_fail (username != NULL, FALSE);
1457 if (!seat_get_can_switch (seat))
1460 /* If we're already on this session, then ignore */
1461 session = find_user_session (seat, username, NULL);
1462 if (session && session == seat->priv->active_session)
1465 l_debug (seat, "Switching to user %s", username);
1467 /* Attempt to authenticate them */
1468 session = create_user_session (seat, username, FALSE);
1469 g_signal_connect (session, SESSION_SIGNAL_AUTHENTICATION_COMPLETE, G_CALLBACK (switch_authentication_complete_cb), seat);
1470 session_set_pam_service (session, seat_get_string_property (seat, "pam-service"));
1472 return session_start (session);
1476 find_guest_session (Seat *seat)
1480 for (link = seat->priv->sessions; link; link = link->next)
1482 Session *session = link->data;
1483 if (!session_get_is_stopping (session) && session_get_is_guest (session))
1491 seat_switch_to_guest (Seat *seat, const gchar *session_name)
1494 DisplayServer *display_server;
1496 g_return_val_if_fail (seat != NULL, FALSE);
1498 if (!seat_get_can_switch (seat) || !seat_get_allow_guest (seat))
1501 /* Switch to session if one open */
1502 session = find_guest_session (seat);
1505 l_debug (seat, "Switching to existing guest account %s", session_get_username (session));
1506 seat_set_active_session (seat, session);
1510 session = create_guest_session (seat, session_name);
1514 display_server = create_display_server (seat, session);
1516 if (seat->priv->session_to_activate)
1517 g_object_unref (seat->priv->session_to_activate);
1518 seat->priv->session_to_activate = g_object_ref (session);
1519 session_set_pam_service (session, seat_get_string_property (seat, "pam-autologin-service"));
1520 session_set_display_server (session, display_server);
1522 return display_server_start (display_server);
1526 seat_lock (Seat *seat, const gchar *username)
1528 Greeter *greeter_session;
1529 DisplayServer *display_server;
1530 gboolean existing = FALSE;
1532 g_return_val_if_fail (seat != NULL, FALSE);
1534 if (!seat_get_can_switch (seat))
1537 l_debug (seat, "Locking");
1539 /* Switch to greeter we can reuse */
1540 greeter_session = find_resettable_greeter (seat);
1541 if (greeter_session)
1543 l_debug (seat, "Switching to existing greeter");
1544 set_greeter_hints (seat, greeter_session);
1549 greeter_session = create_greeter_session (seat);
1550 if (!greeter_session)
1554 greeter_set_hint (greeter_session, "lock-screen", "true");
1556 greeter_set_hint (greeter_session, "select-user", username);
1560 greeter_reset (greeter_session);
1561 seat_set_active_session (seat, SESSION (greeter_session));
1566 display_server = create_display_server (seat, SESSION (greeter_session));
1568 if (seat->priv->session_to_activate)
1569 g_object_unref (seat->priv->session_to_activate);
1570 seat->priv->session_to_activate = g_object_ref (greeter_session);
1571 session_set_display_server (SESSION (greeter_session), display_server);
1573 return display_server_start (display_server);
1578 seat_stop (Seat *seat)
1580 g_return_if_fail (seat != NULL);
1582 if (seat->priv->stopping)
1585 l_debug (seat, "Stopping");
1586 seat->priv->stopping = TRUE;
1587 SEAT_GET_CLASS (seat)->stop (seat);
1591 seat_get_is_stopping (Seat *seat)
1593 g_return_val_if_fail (seat != NULL, FALSE);
1594 return seat->priv->stopping;
1598 seat_real_setup (Seat *seat)
1603 seat_real_start (Seat *seat)
1605 const gchar *autologin_username;
1606 int autologin_timeout;
1607 gboolean autologin_guest;
1608 gboolean autologin_in_background;
1609 Session *session = NULL, *background_session = NULL;
1611 /* Get autologin settings */
1612 autologin_username = seat_get_string_property (seat, "autologin-user");
1613 if (g_strcmp0 (autologin_username, "") == 0)
1614 autologin_username = NULL;
1615 autologin_timeout = seat_get_integer_property (seat, "autologin-user-timeout");
1616 autologin_guest = seat_get_boolean_property (seat, "autologin-guest");
1617 autologin_in_background = seat_get_boolean_property (seat, "autologin-in-background");
1619 /* Autologin if configured */
1620 if (autologin_timeout == 0 || autologin_in_background)
1622 if (autologin_guest)
1623 session = create_guest_session (seat, NULL);
1624 else if (autologin_username != NULL)
1625 session = create_user_session (seat, autologin_username, TRUE);
1628 session_set_pam_service (session, seat_get_string_property (seat, "pam-autologin-service"));
1630 /* Load in background if required */
1631 if (autologin_in_background && session)
1633 background_session = session;
1639 DisplayServer *display_server;
1641 if (seat->priv->session_to_activate)
1642 g_object_unref (seat->priv->session_to_activate);
1643 seat->priv->session_to_activate = g_object_ref (session);
1645 display_server = create_display_server (seat, session);
1646 session_set_display_server (session, display_server);
1647 if (!display_server || !display_server_start (display_server))
1649 l_debug (seat, "Can't create display server for automatic login");
1650 session_stop (session);
1652 display_server_stop (display_server);
1658 /* Fallback to a greeter */
1661 Greeter *greeter_session;
1662 DisplayServer *display_server;
1664 greeter_session = create_greeter_session (seat);
1665 if (!greeter_session)
1667 l_debug (seat, "Failed to create greeter session");
1671 if (seat->priv->session_to_activate)
1672 g_object_unref (seat->priv->session_to_activate);
1673 seat->priv->session_to_activate = g_object_ref (greeter_session);
1674 session = SESSION (greeter_session);
1676 display_server = create_display_server (seat, session);
1677 session_set_display_server (session, display_server);
1678 if (!display_server || !display_server_start (display_server))
1680 l_debug (seat, "Can't create display server for greeter");
1681 session_stop (session);
1683 display_server_stop (display_server);
1688 /* Fail if can't start a session */
1695 /* Start background session */
1696 if (background_session)
1698 DisplayServer *background_display_server;
1700 background_display_server = create_display_server (seat, background_session);
1701 session_set_display_server (background_session, background_display_server);
1702 if (!display_server_start (background_display_server))
1703 l_warning (seat, "Failed to start display server for background session");
1710 seat_real_create_greeter_session (Seat *seat)
1712 return greeter_new ();
1716 seat_real_create_session (Seat *seat)
1718 return session_new ();
1722 seat_real_set_active_session (Seat *seat, Session *session)
1727 seat_real_set_next_session (Seat *seat, Session *session)
1732 seat_real_get_active_session (Seat *seat)
1738 seat_real_stop (Seat *seat)
1742 check_stopped (seat);
1743 if (seat->priv->stopped)
1746 /* Stop all the display servers and sessions on the seat. Copy the list as
1747 * it might be modified if a display server / session stops during this loop */
1748 list = g_list_copy (seat->priv->display_servers);
1749 for (link = list; link; link = link->next)
1750 g_object_ref (link->data);
1751 for (link = list; link; link = link->next)
1753 DisplayServer *display_server = link->data;
1754 if (!display_server_get_is_stopping (display_server))
1756 l_debug (seat, "Stopping display server");
1757 display_server_stop (display_server);
1760 g_list_free_full (list, g_object_unref);
1761 list = g_list_copy (seat->priv->sessions);
1762 for (link = list; link; link = link->next)
1763 g_object_ref (link->data);
1764 for (link = list; link; link = link->next)
1766 Session *session = link->data;
1767 if (!session_get_is_stopping (session))
1769 l_debug (seat, "Stopping session");
1770 session_stop (session);
1773 g_list_free_full (list, g_object_unref);
1777 seat_init (Seat *seat)
1779 seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_TYPE, SeatPrivate);
1780 seat->priv->properties = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
1781 seat->priv->share_display_server = TRUE;
1785 seat_finalize (GObject *object)
1790 self = SEAT (object);
1792 g_free (self->priv->name);
1793 g_hash_table_unref (self->priv->properties);
1794 for (link = self->priv->display_servers; link; link = link->next)
1796 DisplayServer *display_server = link->data;
1797 g_signal_handlers_disconnect_matched (display_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1799 g_list_free_full (self->priv->display_servers, g_object_unref);
1800 for (link = self->priv->sessions; link; link = link->next)
1802 Session *session = link->data;
1803 g_signal_handlers_disconnect_matched (session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
1805 g_list_free_full (self->priv->sessions, g_object_unref);
1806 if (self->priv->active_session)
1807 g_object_unref (self->priv->active_session);
1808 if (self->priv->next_session)
1809 g_object_unref (self->priv->next_session);
1810 if (self->priv->session_to_activate)
1811 g_object_unref (self->priv->session_to_activate);
1813 G_OBJECT_CLASS (seat_parent_class)->finalize (object);
1817 seat_class_init (SeatClass *klass)
1819 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1821 klass->setup = seat_real_setup;
1822 klass->start = seat_real_start;
1823 klass->create_greeter_session = seat_real_create_greeter_session;
1824 klass->create_session = seat_real_create_session;
1825 klass->set_active_session = seat_real_set_active_session;
1826 klass->get_active_session = seat_real_get_active_session;
1827 klass->set_next_session = seat_real_set_next_session;
1828 klass->run_script = seat_real_run_script;
1829 klass->stop = seat_real_stop;
1831 object_class->finalize = seat_finalize;
1833 g_type_class_add_private (klass, sizeof (SeatPrivate));
1835 signals[SESSION_ADDED] =
1836 g_signal_new (SEAT_SIGNAL_SESSION_ADDED,
1837 G_TYPE_FROM_CLASS (klass),
1839 G_STRUCT_OFFSET (SeatClass, session_added),
1842 G_TYPE_NONE, 1, SESSION_TYPE);
1843 signals[RUNNING_USER_SESSION] =
1844 g_signal_new (SEAT_SIGNAL_RUNNING_USER_SESSION,
1845 G_TYPE_FROM_CLASS (klass),
1847 G_STRUCT_OFFSET (SeatClass, running_user_session),
1850 G_TYPE_NONE, 1, SESSION_TYPE);
1851 signals[SESSION_REMOVED] =
1852 g_signal_new (SEAT_SIGNAL_SESSION_REMOVED,
1853 G_TYPE_FROM_CLASS (klass),
1855 G_STRUCT_OFFSET (SeatClass, session_removed),
1858 G_TYPE_NONE, 1, SESSION_TYPE);
1860 g_signal_new (SEAT_SIGNAL_STOPPED,
1861 G_TYPE_FROM_CLASS (klass),
1863 G_STRUCT_OFFSET (SeatClass, stopped),
1870 seat_real_logprefix (Logger *self, gchar *buf, gulong buflen)
1872 return g_snprintf (buf, buflen, "Seat %s: ", SEAT (self)->priv->name);
1876 seat_logger_iface_init (LoggerInterface *iface)
1878 iface->logprefix = &seat_real_logprefix;