2 * Copyright (C) 2012-2013 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
15 #include <glib/gstdio.h>
17 #include "seat-unity.h"
18 #include "configuration.h"
19 #include "unity-system-compositor.h"
20 #include "x-server-local.h"
21 #include "mir-server.h"
25 struct SeatUnityPrivate
27 /* System compositor */
28 UnitySystemCompositor *compositor;
30 /* Next Mir ID to use for a Mir sessions, X server and greeters */
32 gint next_x_server_id;
35 /* The currently visible session */
36 Session *active_session;
37 DisplayServer *active_display_server;
40 G_DEFINE_TYPE (SeatUnity, seat_unity, SEAT_TYPE);
43 seat_unity_get_start_local_sessions (Seat *seat)
45 return !seat_get_string_property (seat, "xdmcp-manager");
49 seat_unity_setup (Seat *seat)
51 seat_set_can_switch (seat, TRUE);
52 SEAT_CLASS (seat_unity_parent_class)->setup (seat);
56 compositor_ready_cb (UnitySystemCompositor *compositor, SeatUnity *seat)
58 l_debug (seat, "Compositor ready");
59 SEAT_CLASS (seat_unity_parent_class)->start (SEAT (seat));
63 compositor_stopped_cb (UnitySystemCompositor *compositor, SeatUnity *seat)
65 g_object_unref (seat->priv->compositor);
66 seat->priv->compositor = NULL;
68 if (seat_get_is_stopping (SEAT (seat)))
70 SEAT_CLASS (seat_unity_parent_class)->stop (SEAT (seat));
74 l_debug (seat, "Stopping Unity seat, compositor terminated");
76 seat_stop (SEAT (seat));
80 seat_unity_start (Seat *seat)
85 /* Replace Plymouth if it is running */
86 if (plymouth_get_is_active () && plymouth_has_active_vt ())
88 gint active_vt = vt_get_active ();
89 if (active_vt >= vt_get_min ())
95 l_debug (seat, "Plymouth is running on VT %d, but this is less than the configured minimum of %d so not replacing it", active_vt, vt_get_min ());
97 if (plymouth_get_is_active ())
98 plymouth_quit (FALSE);
100 vt = vt_can_multi_seat () ? vt_get_unused () : 0;
103 l_debug (seat, "Failed to get a VT to run on");
107 timeout = seat_get_integer_property (seat, "unity-compositor-timeout");
111 SEAT_UNITY (seat)->priv->compositor = unity_system_compositor_new ();
112 g_signal_connect (SEAT_UNITY (seat)->priv->compositor, "ready", G_CALLBACK (compositor_ready_cb), seat);
113 g_signal_connect (SEAT_UNITY (seat)->priv->compositor, "stopped", G_CALLBACK (compositor_stopped_cb), seat);
114 unity_system_compositor_set_command (SEAT_UNITY (seat)->priv->compositor, seat_get_string_property (seat, "unity-compositor-command"));
115 unity_system_compositor_set_vt (SEAT_UNITY (seat)->priv->compositor, vt);
116 unity_system_compositor_set_timeout (SEAT_UNITY (seat)->priv->compositor, timeout);
118 return display_server_start (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
121 static DisplayServer *
122 create_x_server (Seat *seat)
124 XServerLocal *x_server;
125 const gchar *command = NULL, *layout = NULL, *config_file = NULL, *xdmcp_manager = NULL, *key_name = NULL;
130 l_debug (seat, "Starting X server on Unity compositor");
132 x_server = x_server_local_new ();
134 command = seat_get_string_property (seat, "xserver-command");
136 x_server_local_set_command (x_server, command);
138 id = g_strdup_printf ("x-%d", SEAT_UNITY (seat)->priv->next_x_server_id);
139 SEAT_UNITY (seat)->priv->next_x_server_id++;
140 x_server_local_set_mir_id (x_server, id);
141 x_server_local_set_mir_socket (x_server, unity_system_compositor_get_socket (SEAT_UNITY (seat)->priv->compositor));
144 layout = seat_get_string_property (seat, "xserver-layout");
146 x_server_local_set_layout (x_server, layout);
148 x_server_local_set_xdg_seat (x_server, seat_get_name (seat));
150 config_file = seat_get_string_property (seat, "xserver-config");
152 x_server_local_set_config (x_server, config_file);
154 allow_tcp = seat_get_boolean_property (seat, "xserver-allow-tcp");
155 x_server_local_set_allow_tcp (x_server, allow_tcp);
157 xdmcp_manager = seat_get_string_property (seat, "xdmcp-manager");
159 x_server_local_set_xdmcp_server (x_server, xdmcp_manager);
161 port = seat_get_integer_property (seat, "xdmcp-port");
163 x_server_local_set_xdmcp_port (x_server, port);
165 key_name = seat_get_string_property (seat, "xdmcp-key");
171 GError *error = NULL;
173 dir = config_get_string (config_get_instance (), "LightDM", "config-directory");
174 path = g_build_filename (dir, "keys.conf", NULL);
177 keys = g_key_file_new ();
178 result = g_key_file_load_from_file (keys, path, G_KEY_FILE_NONE, &error);
180 l_debug (seat, "Error getting key %s", error->message);
181 g_clear_error (&error);
187 if (g_key_file_has_key (keys, "keyring", key_name, NULL))
188 key = g_key_file_get_string (keys, "keyring", key_name, NULL);
190 l_debug (seat, "Key %s not defined", key_name);
193 x_server_local_set_xdmcp_key (x_server, key);
198 g_key_file_free (keys);
201 return DISPLAY_SERVER (x_server);
204 static DisplayServer *
205 create_mir_server (Seat *seat)
207 MirServer *mir_server;
209 mir_server = mir_server_new ();
210 mir_server_set_parent_socket (mir_server, unity_system_compositor_get_socket (SEAT_UNITY (seat)->priv->compositor));
212 return DISPLAY_SERVER (mir_server);
215 static DisplayServer *
216 seat_unity_create_display_server (Seat *seat, const gchar *session_type)
218 if (strcmp (session_type, "x") == 0)
219 return create_x_server (seat);
220 else if (strcmp (session_type, "mir") == 0)
221 return create_mir_server (seat);
224 l_warning (seat, "Can't create unsupported display server '%s'", session_type);
230 seat_unity_create_greeter_session (Seat *seat)
232 Greeter *greeter_session;
236 greeter_session = SEAT_CLASS (seat_unity_parent_class)->create_greeter_session (seat);
237 session_set_env (SESSION (greeter_session), "XDG_SEAT", seat_get_name (seat));
239 id = g_strdup_printf ("greeter-%d", SEAT_UNITY (seat)->priv->next_greeter_id);
240 SEAT_UNITY (seat)->priv->next_greeter_id++;
241 session_set_env (SESSION (greeter_session), "MIR_SERVER_NAME", id);
244 vt = display_server_get_vt (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
247 gchar *value = g_strdup_printf ("%d", vt);
248 session_set_env (SESSION (greeter_session), "XDG_VTNR", value);
252 return greeter_session;
256 seat_unity_create_session (Seat *seat)
262 session = SEAT_CLASS (seat_unity_parent_class)->create_session (seat);
263 session_set_env (session, "XDG_SEAT", seat_get_name (seat));
265 id = g_strdup_printf ("session-%d", SEAT_UNITY (seat)->priv->next_session_id);
266 SEAT_UNITY (seat)->priv->next_session_id++;
267 session_set_env (session, "MIR_SERVER_NAME", id);
270 vt = display_server_get_vt (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
273 gchar *value = g_strdup_printf ("%d", vt);
274 session_set_env (SESSION (session), "XDG_VTNR", value);
282 seat_unity_set_active_session (Seat *seat, Session *session)
284 DisplayServer *display_server;
286 if (session == SEAT_UNITY (seat)->priv->active_session)
288 SEAT_UNITY (seat)->priv->active_session = g_object_ref (session);
290 display_server = session_get_display_server (session);
291 if (SEAT_UNITY (seat)->priv->active_display_server != display_server)
293 const gchar *id = NULL;
295 SEAT_UNITY (seat)->priv->active_display_server = g_object_ref (display_server);
297 if (IS_X_SERVER_LOCAL (display_server))
298 id = x_server_local_get_mir_id (X_SERVER_LOCAL (display_server));
300 id = session_get_env (session, "MIR_SERVER_NAME");
304 l_debug (seat, "Switching to Mir session %s", id);
305 unity_system_compositor_set_active_session (SEAT_UNITY (seat)->priv->compositor, id);
308 l_warning (seat, "Failed to work out session ID");
311 SEAT_CLASS (seat_unity_parent_class)->set_active_session (seat, session);
315 seat_unity_get_active_session (Seat *seat)
317 return SEAT_UNITY (seat)->priv->active_session;
321 seat_unity_set_next_session (Seat *seat, Session *session)
323 DisplayServer *display_server;
324 const gchar *id = NULL;
329 display_server = session_get_display_server (session);
331 if (IS_X_SERVER_LOCAL (display_server))
332 id = x_server_local_get_mir_id (X_SERVER_LOCAL (display_server));
334 id = session_get_env (session, "MIR_SERVER_NAME");
338 l_debug (seat, "Marking Mir session %s as the next session", id);
339 unity_system_compositor_set_next_session (SEAT_UNITY (seat)->priv->compositor, id);
343 l_debug (seat, "Failed to work out session ID to mark");
346 SEAT_CLASS (seat_unity_parent_class)->set_next_session (seat, session);
350 seat_unity_run_script (Seat *seat, DisplayServer *display_server, Process *script)
353 XServerLocal *x_server;
355 x_server = X_SERVER_LOCAL (display_server);
356 path = x_server_local_get_authority_file_path (x_server);
357 process_set_env (script, "DISPLAY", x_server_get_address (X_SERVER (x_server)));
358 process_set_env (script, "XAUTHORITY", path);
360 SEAT_CLASS (seat_unity_parent_class)->run_script (seat, display_server, script);
364 seat_unity_stop (Seat *seat)
366 /* Stop the compositor first */
367 if (SEAT_UNITY (seat)->priv->compositor)
369 display_server_stop (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
373 SEAT_CLASS (seat_unity_parent_class)->stop (seat);
377 seat_unity_init (SeatUnity *seat)
379 seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_UNITY_TYPE, SeatUnityPrivate);
383 seat_unity_finalize (GObject *object)
385 SeatUnity *seat = SEAT_UNITY (object);
387 if (seat->priv->compositor)
388 g_object_unref (seat->priv->compositor);
389 if (seat->priv->active_session)
390 g_object_unref (seat->priv->active_session);
391 if (seat->priv->active_display_server)
392 g_object_unref (seat->priv->active_display_server);
394 G_OBJECT_CLASS (seat_unity_parent_class)->finalize (object);
398 seat_unity_class_init (SeatUnityClass *klass)
400 GObjectClass *object_class = G_OBJECT_CLASS (klass);
401 SeatClass *seat_class = SEAT_CLASS (klass);
403 object_class->finalize = seat_unity_finalize;
404 seat_class->get_start_local_sessions = seat_unity_get_start_local_sessions;
405 seat_class->setup = seat_unity_setup;
406 seat_class->start = seat_unity_start;
407 seat_class->create_display_server = seat_unity_create_display_server;
408 seat_class->create_greeter_session = seat_unity_create_greeter_session;
409 seat_class->create_session = seat_unity_create_session;
410 seat_class->set_active_session = seat_unity_set_active_session;
411 seat_class->get_active_session = seat_unity_get_active_session;
412 seat_class->set_next_session = seat_unity_set_next_session;
413 seat_class->run_script = seat_unity_run_script;
414 seat_class->stop = seat_unity_stop;
416 g_type_class_add_private (klass, sizeof (SeatUnityPrivate));