#include "seat-unity.h"
#include "configuration.h"
-#include "x-server-local.h"
-#include "mir-server.h"
+#include "unity-system-compositor.h"
+#include "x-server-xmir.h"
#include "vt.h"
#include "plymouth.h"
-typedef enum
-{
- USC_MESSAGE_PING = 0,
- USC_MESSAGE_PONG = 1,
- USC_MESSAGE_READY = 2,
- USC_MESSAGE_SESSION_CONNECTED = 3,
- USC_MESSAGE_SET_ACTIVE_SESSION = 4,
- USC_MESSAGE_SET_NEXT_SESSION = 5,
-} USCMessageID;
-
struct SeatUnityPrivate
{
- /* VT we are running on */
- gint vt;
-
- /* File to log to */
- gchar *log_file;
-
- /* Filename of Mir socket */
- gchar *mir_socket_filename;
-
- /* Pipes to communicate with compositor */
- int to_compositor_pipe[2];
- int from_compositor_pipe[2];
-
- /* IO channel listening on for messages from the compositor */
- GIOChannel *from_compositor_channel;
- guint from_compositor_watch;
-
- /* TRUE when the compositor indicates it is ready */
- gboolean compositor_ready;
-
- /* Buffer reading from channel */
- guint8 *read_buffer;
- gsize read_buffer_length;
- gsize read_buffer_n_used;
-
- /* Compositor process */
- Process *compositor_process;
+ /* System compositor */
+ UnitySystemCompositor *compositor;
- /* Timeout when waiting for compositor to start */
- guint compositor_timeout;
+ /* X server being used for XDMCP */
+ XServerXmir *xdmcp_x_server;
- /* Next Mir ID to use for a compositor client */
- gint next_id;
-
- /* TRUE if using VT switching fallback */
- gboolean use_vt_switching;
+ /* Next Mir ID to use for a Xmir servers */
+ gint next_x_server_id;
/* The currently visible session */
Session *active_session;
G_DEFINE_TYPE (SeatUnity, seat_unity, SEAT_TYPE);
-static gboolean
-seat_unity_get_start_local_sessions (Seat *seat)
-{
- return !seat_get_string_property (seat, "xdmcp-manager");
-}
+static XServerXmir *create_x_server (Seat *seat);
static void
seat_unity_setup (Seat *seat)
{
- seat_set_can_switch (seat, TRUE);
+ seat_set_supports_multi_session (seat, TRUE);
SEAT_CLASS (seat_unity_parent_class)->setup (seat);
}
static void
-compositor_stopped_cb (Process *process, SeatUnity *seat)
+check_stopped (SeatUnity *seat)
{
- if (seat->priv->compositor_timeout != 0)
- g_source_remove (seat->priv->compositor_timeout);
- seat->priv->compositor_timeout = 0;
-
- /* Finished with the VT */
- vt_unref (seat->priv->vt);
- seat->priv->vt = -1;
-
- if (seat_get_is_stopping (SEAT (seat)))
- {
+ if (!seat->priv->compositor && !seat->priv->xdmcp_x_server)
SEAT_CLASS (seat_unity_parent_class)->stop (SEAT (seat));
- return;
- }
-
- /* If stopped before it was ready, then revert to VT mode */
- if (!seat->priv->compositor_ready)
- {
- l_debug (seat, "Compositor failed to start, switching to VT mode");
- seat->priv->use_vt_switching = TRUE;
- SEAT_CLASS (seat_unity_parent_class)->start (SEAT (seat));
- return;
- }
-
- l_debug (seat, "Stopping Unity seat, compositor terminated");
-
- seat_stop (SEAT (seat));
}
static void
-compositor_run_cb (Process *process, SeatUnity *seat)
+xdmcp_x_server_stopped_cb (DisplayServer *display_server, Seat *seat)
{
- int fd;
+ l_debug (seat, "XDMCP X server stopped");
- /* Make input non-blocking */
- fd = open ("/dev/null", O_RDONLY);
- dup2 (fd, STDIN_FILENO);
- close (fd);
+ g_signal_handlers_disconnect_matched (SEAT_UNITY (seat)->priv->xdmcp_x_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
+ SEAT_UNITY (seat)->priv->xdmcp_x_server = NULL;
- /* Redirect output to logfile */
- if (seat->priv->log_file)
- {
- int fd;
- gchar *old_filename;
-
- /* Move old file out of the way */
- old_filename = g_strdup_printf ("%s.old", seat->priv->log_file);
- rename (seat->priv->log_file, old_filename);
- g_free (old_filename);
-
- /* Create new file and log to it */
- fd = g_open (seat->priv->log_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (fd < 0)
- l_warning (seat, "Failed to open log file %s: %s", seat->priv->log_file, g_strerror (errno));
- else
- {
- dup2 (fd, STDOUT_FILENO);
- dup2 (fd, STDERR_FILENO);
- close (fd);
- }
- }
+ g_object_unref (display_server);
+
+ if (seat_get_is_stopping (seat))
+ check_stopped (SEAT_UNITY (seat));
+ else
+ seat_stop (seat);
}
static void
-write_message (SeatUnity *seat, guint16 id, const guint8 *payload, guint16 payload_length)
+compositor_ready_cb (UnitySystemCompositor *compositor, SeatUnity *seat)
{
- guint8 *data;
- gsize data_length = 4 + payload_length;
-
- data = g_malloc (data_length);
- data[0] = id >> 8;
- data[1] = id & 0xFF;
- data[2] = payload_length >> 8;
- data[3] = payload_length & 0xFF;
- memcpy (data + 4, payload, payload_length);
-
- errno = 0;
- if (write (seat->priv->to_compositor_pipe[1], data, data_length) != data_length)
- l_warning (seat, "Failed to write to compositor: %s", strerror (errno));
-}
+ const gchar *xdmcp_manager = NULL;
-static gboolean
-read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
-{
- SeatUnity *seat = data;
- gsize n_to_read = 0;
- guint16 id, payload_length;
- /*guint8 *payload;*/
-
- if (condition == G_IO_HUP)
- {
- l_debug (seat, "Compositor closed communication channel");
- return FALSE;
- }
+ l_debug (seat, "Compositor ready");
- /* Work out how much required for a message */
- if (seat->priv->read_buffer_n_used < 4)
- n_to_read = 4 - seat->priv->read_buffer_n_used;
- else
- {
- payload_length = seat->priv->read_buffer[2] << 8 | seat->priv->read_buffer[3];
- n_to_read = 4 + payload_length - seat->priv->read_buffer_n_used;
- }
-
- /* Read from compositor */
- if (n_to_read > 0)
- {
- gsize n_total, n_read = 0;
- GIOStatus status;
- GError *error = NULL;
-
- n_total = seat->priv->read_buffer_n_used + n_to_read;
- if (seat->priv->read_buffer_length < n_total)
- seat->priv->read_buffer = g_realloc (seat->priv->read_buffer, n_total);
-
- status = g_io_channel_read_chars (source,
- (gchar *)seat->priv->read_buffer + seat->priv->read_buffer_n_used,
- n_to_read,
- &n_read,
- &error);
- if (error)
- l_warning (seat, "Failed to read from compositor: %s", error->message);
- if (status != G_IO_STATUS_NORMAL)
- return TRUE;
- g_clear_error (&error);
- seat->priv->read_buffer_n_used += n_read;
- }
-
- /* Read header */
- if (seat->priv->read_buffer_n_used < 4)
- return TRUE;
- id = seat->priv->read_buffer[0] << 8 | seat->priv->read_buffer[1];
- payload_length = seat->priv->read_buffer[2] << 8 | seat->priv->read_buffer[3];
-
- /* Read payload */
- if (seat->priv->read_buffer_n_used < 4 + payload_length)
- return TRUE;
- /*payload = seat->priv->read_buffer + 4;*/
-
- switch (id)
+ /* If running as an XDMCP client then just start an X server */
+ xdmcp_manager = seat_get_string_property (SEAT (seat), "xdmcp-manager");
+ if (xdmcp_manager)
{
- case USC_MESSAGE_PING:
- l_debug (seat, "PING!");
- write_message (seat, USC_MESSAGE_PONG, NULL, 0);
- break;
- case USC_MESSAGE_PONG:
- l_debug (seat, "PONG!");
- break;
- case USC_MESSAGE_READY:
- l_debug (seat, "READY");
- if (!seat->priv->compositor_ready)
+ const gchar *key_name = NULL;
+ gint port = 0;
+
+ seat->priv->xdmcp_x_server = create_x_server (SEAT (seat));
+ x_server_local_set_xdmcp_server (X_SERVER_LOCAL (seat->priv->xdmcp_x_server), xdmcp_manager);
+ port = seat_get_integer_property (SEAT (seat), "xdmcp-port");
+ if (port > 0)
+ x_server_local_set_xdmcp_port (X_SERVER_LOCAL (seat->priv->xdmcp_x_server), port);
+ key_name = seat_get_string_property (SEAT (seat), "xdmcp-key");
+ if (key_name)
{
- seat->priv->compositor_ready = TRUE;
- l_debug (seat, "Compositor ready");
- g_source_remove (seat->priv->compositor_timeout);
- seat->priv->compositor_timeout = 0;
- SEAT_CLASS (seat_unity_parent_class)->start (SEAT (seat));
+ gchar *path;
+ GKeyFile *keys;
+ gboolean result;
+ GError *error = NULL;
+
+ path = g_build_filename (config_get_directory (config_get_instance ()), "keys.conf", NULL);
+
+ keys = g_key_file_new ();
+ result = g_key_file_load_from_file (keys, path, G_KEY_FILE_NONE, &error);
+ if (error)
+ l_debug (seat, "Error getting key %s", error->message);
+ g_clear_error (&error);
+
+ if (result)
+ {
+ gchar *key = NULL;
+
+ if (g_key_file_has_key (keys, "keyring", key_name, NULL))
+ key = g_key_file_get_string (keys, "keyring", key_name, NULL);
+ else
+ l_debug (seat, "Key %s not defined", key_name);
+
+ if (key)
+ x_server_local_set_xdmcp_key (X_SERVER_LOCAL (seat->priv->xdmcp_x_server), key);
+ g_free (key);
+ }
+
+ g_free (path);
+ g_key_file_free (keys);
}
- break;
- case USC_MESSAGE_SESSION_CONNECTED:
- l_debug (seat, "SESSION CONNECTED");
- break;
- default:
- l_warning (seat, "Ignoring unknown message %d with %d octets from system compositor", id, payload_length);
- break;
- }
- /* Clear buffer */
- seat->priv->read_buffer_n_used = 0;
-
- return TRUE;
-}
-
-static gchar *
-get_absolute_command (const gchar *command)
-{
- gchar **tokens;
- gchar *absolute_binary, *absolute_command = NULL;
-
- tokens = g_strsplit (command, " ", 2);
-
- absolute_binary = g_find_program_in_path (tokens[0]);
- if (absolute_binary)
- {
- if (tokens[1])
- absolute_command = g_strjoin (" ", absolute_binary, tokens[1], NULL);
- else
- absolute_command = g_strdup (absolute_binary);
- g_free (absolute_binary);
+ g_signal_connect (seat->priv->xdmcp_x_server, DISPLAY_SERVER_SIGNAL_STOPPED, G_CALLBACK (xdmcp_x_server_stopped_cb), seat);
+ if (!display_server_start (DISPLAY_SERVER (seat->priv->xdmcp_x_server)))
+ seat_stop (SEAT (seat));
}
- else
- absolute_command = g_strdup (command);
- g_strfreev (tokens);
-
- return absolute_command;
+ SEAT_CLASS (seat_unity_parent_class)->start (SEAT (seat));
}
-static gboolean
-compositor_timeout_cb (gpointer data)
+static void
+compositor_stopped_cb (UnitySystemCompositor *compositor, SeatUnity *seat)
{
- SeatUnity *seat = data;
+ l_debug (seat, "Compositor stopped");
- /* Stop the compositor - it is not working */
- process_stop (seat->priv->compositor_process);
+ g_clear_object (&seat->priv->compositor);
- return TRUE;
+ if (seat_get_is_stopping (SEAT (seat)))
+ check_stopped (seat);
+ else
+ seat_stop (SEAT (seat));
}
static gboolean
seat_unity_start (Seat *seat)
{
- const gchar *compositor_command;
- gchar *command, *absolute_command, *dir, *value;
- gboolean result;
+ gint vt = -1;
int timeout;
/* Replace Plymouth if it is running */
gint active_vt = vt_get_active ();
if (active_vt >= vt_get_min ())
{
- SEAT_UNITY (seat)->priv->vt = active_vt;
+ vt = active_vt;
plymouth_quit (TRUE);
}
else
}
if (plymouth_get_is_active ())
plymouth_quit (FALSE);
- if (SEAT_UNITY (seat)->priv->vt < 0)
- SEAT_UNITY (seat)->priv->vt = vt_get_unused ();
- if (SEAT_UNITY (seat)->priv->vt < 0)
+ if (vt < 0)
+ vt = vt_can_multi_seat () ? vt_get_unused () : 0;
+ if (vt < 0)
{
l_debug (seat, "Failed to get a VT to run on");
return FALSE;
}
- vt_ref (SEAT_UNITY (seat)->priv->vt);
-
- /* Create pipes to talk to compositor */
- if (pipe (SEAT_UNITY (seat)->priv->to_compositor_pipe) < 0 || pipe (SEAT_UNITY (seat)->priv->from_compositor_pipe) < 0)
- {
- l_debug (seat, "Failed to create compositor pipes: %s", g_strerror (errno));
- return FALSE;
- }
-
- /* Don't allow the daemon end of the pipes to be accessed in the compositor */
- fcntl (SEAT_UNITY (seat)->priv->to_compositor_pipe[1], F_SETFD, FD_CLOEXEC);
- fcntl (SEAT_UNITY (seat)->priv->from_compositor_pipe[0], F_SETFD, FD_CLOEXEC);
-
- /* Listen for messages from the compositor */
- SEAT_UNITY (seat)->priv->from_compositor_channel = g_io_channel_unix_new (SEAT_UNITY (seat)->priv->from_compositor_pipe[0]);
- SEAT_UNITY (seat)->priv->from_compositor_watch = g_io_add_watch (SEAT_UNITY (seat)->priv->from_compositor_channel, G_IO_IN | G_IO_HUP, read_cb, seat);
-
- /* Setup logging */
- dir = config_get_string (config_get_instance (), "LightDM", "log-directory");
- SEAT_UNITY (seat)->priv->log_file = g_build_filename (dir, "unity-system-compositor.log", NULL);
- l_debug (seat, "Logging to %s", SEAT_UNITY (seat)->priv->log_file);
- g_free (dir);
-
- /* Setup environment */
- process_set_clear_environment (SEAT_UNITY (seat)->priv->compositor_process, TRUE);
- process_set_env (SEAT_UNITY (seat)->priv->compositor_process, "XDG_SEAT", "seat0");
- value = g_strdup_printf ("%d", SEAT_UNITY (seat)->priv->vt);
- process_set_env (SEAT_UNITY (seat)->priv->compositor_process, "XDG_VTNR", value);
- g_free (value);
- /* Variable required for regression tests */
- if (g_getenv ("LIGHTDM_TEST_ROOT"))
- {
- process_set_env (SEAT_UNITY (seat)->priv->compositor_process, "LIGHTDM_TEST_ROOT", g_getenv ("LIGHTDM_TEST_ROOT"));
- process_set_env (SEAT_UNITY (seat)->priv->compositor_process, "LD_PRELOAD", g_getenv ("LD_PRELOAD"));
- process_set_env (SEAT_UNITY (seat)->priv->compositor_process, "LD_LIBRARY_PATH", g_getenv ("LD_LIBRARY_PATH"));
- }
-
- SEAT_UNITY (seat)->priv->mir_socket_filename = g_strdup ("/tmp/mir_socket"); // FIXME: Use this socket by default as XMir is hardcoded to this
- timeout = seat_get_integer_property (seat, "unity-compositor-timeout");
- compositor_command = seat_get_string_property (seat, "unity-compositor-command");
- command = g_strdup_printf ("%s --from-dm-fd %d --to-dm-fd %d --vt %d", compositor_command, SEAT_UNITY (seat)->priv->to_compositor_pipe[0], SEAT_UNITY (seat)->priv->from_compositor_pipe[1], SEAT_UNITY (seat)->priv->vt);
-
- absolute_command = get_absolute_command (command);
- g_free (command);
-
- /* Start the compositor */
- process_set_command (SEAT_UNITY (seat)->priv->compositor_process, absolute_command);
- g_free (absolute_command);
- g_signal_connect (SEAT_UNITY (seat)->priv->compositor_process, "stopped", G_CALLBACK (compositor_stopped_cb), seat);
- g_signal_connect (SEAT_UNITY (seat)->priv->compositor_process, "run", G_CALLBACK (compositor_run_cb), seat);
- result = process_start (SEAT_UNITY (seat)->priv->compositor_process, FALSE);
-
- /* Close compostor ends of the pipes */
- close (SEAT_UNITY (seat)->priv->to_compositor_pipe[0]);
- SEAT_UNITY (seat)->priv->to_compositor_pipe[0] = 0;
- close (SEAT_UNITY (seat)->priv->from_compositor_pipe[1]);
- SEAT_UNITY (seat)->priv->from_compositor_pipe[1] = 0;
-
- if (!result)
- return FALSE;
- /* Connect to the compositor */
- timeout = seat_get_integer_property (seat, "unity-compositor-timeout");
+ timeout = seat_get_integer_property (SEAT (seat), "unity-compositor-timeout");
if (timeout <= 0)
timeout = 60;
- l_debug (seat, "Waiting for system compositor for %ds", timeout);
- SEAT_UNITY (seat)->priv->compositor_timeout = g_timeout_add (timeout * 1000, compositor_timeout_cb, seat);
- return TRUE;
+ SEAT_UNITY (seat)->priv->compositor = unity_system_compositor_new ();
+ g_signal_connect (SEAT_UNITY (seat)->priv->compositor, DISPLAY_SERVER_SIGNAL_READY, G_CALLBACK (compositor_ready_cb), seat);
+ g_signal_connect (SEAT_UNITY (seat)->priv->compositor, DISPLAY_SERVER_SIGNAL_STOPPED, G_CALLBACK (compositor_stopped_cb), seat);
+ unity_system_compositor_set_command (SEAT_UNITY (seat)->priv->compositor, seat_get_string_property (SEAT (seat), "unity-compositor-command"));
+ unity_system_compositor_set_vt (SEAT_UNITY (seat)->priv->compositor, vt);
+ unity_system_compositor_set_timeout (SEAT_UNITY (seat)->priv->compositor, timeout);
+
+ return display_server_start (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
}
-static DisplayServer *
+static XServerXmir *
create_x_server (Seat *seat)
{
- XServerLocal *x_server;
- const gchar *command = NULL, *layout = NULL, *config_file = NULL, *xdmcp_manager = NULL, *key_name = NULL, *xdg_seat = NULL;
+ XServerXmir *x_server;
+ gchar *number;
+ XAuthority *cookie;
+ const gchar *command = NULL, *layout = NULL, *config_file = NULL;
gboolean allow_tcp;
- gint port = 0;
+ gchar *id;
l_debug (seat, "Starting X server on Unity compositor");
- x_server = x_server_local_new ();
+ x_server = x_server_xmir_new (SEAT_UNITY (seat)->priv->compositor);
- command = seat_get_string_property (seat, "xserver-command");
- if (command)
- x_server_local_set_command (x_server, command);
+ command = seat_get_string_property (seat, "xmir-command");
+ x_server_local_set_command (X_SERVER_LOCAL (x_server), command);
- if (SEAT_UNITY (seat)->priv->use_vt_switching)
- x_server_local_set_vt (x_server, vt_get_unused ());
- else
- {
- gchar *id;
+ id = g_strdup_printf ("x-%d", SEAT_UNITY (seat)->priv->next_x_server_id);
+ SEAT_UNITY (seat)->priv->next_x_server_id++;
+ x_server_xmir_set_mir_id (x_server, id);
+ x_server_xmir_set_mir_socket (x_server, unity_system_compositor_get_socket (SEAT_UNITY (seat)->priv->compositor));
+ g_free (id);
- id = g_strdup_printf ("%d", SEAT_UNITY (seat)->priv->next_id);
- SEAT_UNITY (seat)->priv->next_id++;
- x_server_local_set_mir_id (x_server, id);
- x_server_local_set_mir_socket (x_server, SEAT_UNITY (seat)->priv->mir_socket_filename);
- g_free (id);
- }
+ number = g_strdup_printf ("%d", x_server_get_display_number (X_SERVER (x_server)));
+ cookie = x_authority_new_local_cookie (number);
+ x_server_set_authority (X_SERVER (x_server), cookie);
+ g_free (number);
+ g_object_unref (cookie);
layout = seat_get_string_property (seat, "xserver-layout");
if (layout)
- x_server_local_set_layout (x_server, layout);
-
- xdg_seat = seat_get_string_property (seat, "xdg-seat");
- if (xdg_seat)
- x_server_local_set_xdg_seat (x_server, xdg_seat);
+ x_server_local_set_layout (X_SERVER_LOCAL (x_server), layout);
+
+ x_server_local_set_xdg_seat (X_SERVER_LOCAL (x_server), seat_get_name (seat));
config_file = seat_get_string_property (seat, "xserver-config");
if (config_file)
- x_server_local_set_config (x_server, config_file);
+ x_server_local_set_config (X_SERVER_LOCAL (x_server), config_file);
allow_tcp = seat_get_boolean_property (seat, "xserver-allow-tcp");
- x_server_local_set_allow_tcp (x_server, allow_tcp);
-
- xdmcp_manager = seat_get_string_property (seat, "xdmcp-manager");
- if (xdmcp_manager)
- x_server_local_set_xdmcp_server (x_server, xdmcp_manager);
-
- port = seat_get_integer_property (seat, "xdmcp-port");
- if (port > 0)
- x_server_local_set_xdmcp_port (x_server, port);
+ x_server_local_set_allow_tcp (X_SERVER_LOCAL (x_server), allow_tcp);
- key_name = seat_get_string_property (seat, "xdmcp-key");
- if (key_name)
- {
- gchar *dir, *path;
- GKeyFile *keys;
- gboolean result;
- GError *error = NULL;
-
- dir = config_get_string (config_get_instance (), "LightDM", "config-directory");
- path = g_build_filename (dir, "keys.conf", NULL);
- g_free (dir);
-
- keys = g_key_file_new ();
- result = g_key_file_load_from_file (keys, path, G_KEY_FILE_NONE, &error);
- if (error)
- l_debug (seat, "Error getting key %s", error->message);
- g_clear_error (&error);
-
- if (result)
- {
- gchar *key = NULL;
-
- if (g_key_file_has_key (keys, "keyring", key_name, NULL))
- key = g_key_file_get_string (keys, "keyring", key_name, NULL);
- else
- l_debug (seat, "Key %s not defined", key_name);
-
- if (key)
- x_server_local_set_xdmcp_key (x_server, key);
- g_free (key);
- }
-
- g_free (path);
- g_key_file_free (keys);
- }
-
- return DISPLAY_SERVER (x_server);
+ return x_server;
}
static DisplayServer *
-create_mir_server (Seat *seat)
+seat_unity_create_display_server (Seat *seat, Session *session)
{
- MirServer *mir_server;
-
- mir_server = mir_server_new ();
- mir_server_set_parent_socket (mir_server, SEAT_UNITY (seat)->priv->mir_socket_filename);
+ const gchar *session_type;
- if (SEAT_UNITY (seat)->priv->use_vt_switching)
- mir_server_set_vt (mir_server, vt_get_unused ());
- else
- {
- gchar *id;
-
- id = g_strdup_printf ("%d", SEAT_UNITY (seat)->priv->next_id);
- SEAT_UNITY (seat)->priv->next_id++;
- mir_server_set_id (mir_server, id);
- mir_server_set_parent_socket (mir_server, SEAT_UNITY (seat)->priv->mir_socket_filename);
- g_free (id);
- }
-
- return DISPLAY_SERVER (mir_server);
-}
-
-static DisplayServer *
-seat_unity_create_display_server (Seat *seat, const gchar *session_type)
-{
+ session_type = session_get_session_type (session);
if (strcmp (session_type, "x") == 0)
- return create_x_server (seat);
+ return DISPLAY_SERVER (create_x_server (seat));
else if (strcmp (session_type, "mir") == 0)
- return create_mir_server (seat);
+ return g_object_ref (SEAT_UNITY (seat)->priv->compositor);
else
{
l_warning (seat, "Can't create unsupported display server '%s'", session_type);
}
}
-static Greeter *
+static gboolean
+seat_unity_display_server_is_used (Seat *seat, DisplayServer *display_server)
+{
+ if (display_server == DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor))
+ return TRUE;
+
+ return SEAT_CLASS (seat_unity_parent_class)->display_server_is_used (seat, display_server);
+}
+
+static GreeterSession *
seat_unity_create_greeter_session (Seat *seat)
{
- Greeter *greeter_session;
- const gchar *xdg_seat;
- gint vt = -1;
+ GreeterSession *greeter_session;
+ gint vt;
greeter_session = SEAT_CLASS (seat_unity_parent_class)->create_greeter_session (seat);
- xdg_seat = seat_get_string_property (seat, "xdg-seat");
- if (!xdg_seat)
- xdg_seat = "seat0";
- l_debug (seat, "Setting XDG_SEAT=%s", xdg_seat);
- session_set_env (SESSION (greeter_session), "XDG_SEAT", xdg_seat);
-
- if (!SEAT_UNITY (seat)->priv->use_vt_switching)
- vt = SEAT_UNITY (seat)->priv->vt;
- else if (vt_get_active () < 0)
- vt = 1; /* If even VTs aren't working, just fake it */
+ session_set_env (SESSION (greeter_session), "XDG_SEAT", seat_get_name (seat));
+ vt = display_server_get_vt (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
if (vt >= 0)
{
gchar *value = g_strdup_printf ("%d", vt);
- l_debug (seat, "Setting XDG_VTNR=%s", value);
session_set_env (SESSION (greeter_session), "XDG_VTNR", value);
g_free (value);
}
- else
- l_debug (seat, "Not setting XDG_VTNR");
return greeter_session;
}
seat_unity_create_session (Seat *seat)
{
Session *session;
- const gchar *xdg_seat;
- gint vt = -1;
+ gint vt;
session = SEAT_CLASS (seat_unity_parent_class)->create_session (seat);
- xdg_seat = seat_get_string_property (seat, "xdg-seat");
- if (!xdg_seat)
- xdg_seat = "seat0";
- l_debug (seat, "Setting XDG_SEAT=%s", xdg_seat);
- session_set_env (session, "XDG_SEAT", xdg_seat);
-
- if (!SEAT_UNITY (seat)->priv->use_vt_switching)
- vt = SEAT_UNITY (seat)->priv->vt;
- else if (vt_get_active () < 0)
- vt = 1; /* If even VTs aren't working, just fake it */
+ session_set_env (session, "XDG_SEAT", seat_get_name (seat));
+ vt = display_server_get_vt (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
if (vt >= 0)
{
gchar *value = g_strdup_printf ("%d", vt);
- l_debug (seat, "Setting XDG_VTNR=%s", value);
session_set_env (SESSION (session), "XDG_VTNR", value);
g_free (value);
}
- else
- l_debug (seat, "Not setting XDG_VTNR");
return session;
}
-static void
-seat_unity_set_active_session (Seat *seat, Session *session)
+static const gchar *
+get_mir_id (Session *session)
{
DisplayServer *display_server;
- /* If no compositor, have to use VT switching */
- if (SEAT_UNITY (seat)->priv->use_vt_switching)
- {
- gint vt = display_server_get_vt (session_get_display_server (session));
- if (vt >= 0)
- vt_set_active (vt);
+ if (!session)
+ return NULL;
- SEAT_CLASS (seat_unity_parent_class)->set_active_session (seat, session);
- return;
- }
+ display_server = session_get_display_server (session);
+ if (IS_UNITY_SYSTEM_COMPOSITOR (display_server))
+ return session_get_env (session, "MIR_SERVER_NAME");
+ if (IS_X_SERVER_XMIR (display_server))
+ return x_server_xmir_get_mir_id (X_SERVER_XMIR (display_server));
- if (session == SEAT_UNITY (seat)->priv->active_session)
- return;
- SEAT_UNITY (seat)->priv->active_session = g_object_ref (session);
+ return NULL;
+}
- display_server = session_get_display_server (session);
- if (SEAT_UNITY (seat)->priv->active_display_server != display_server)
- {
- const gchar *id = NULL;
+static void
+seat_unity_set_active_session (Seat *s, Session *session)
+{
+ SeatUnity *seat = SEAT_UNITY (s);
+ const gchar *old_id, *new_id;
- SEAT_UNITY (seat)->priv->active_display_server = g_object_ref (display_server);
+ old_id = get_mir_id (seat->priv->active_session);
+ new_id = get_mir_id (session);
- if (IS_X_SERVER_LOCAL (display_server))
- id = x_server_local_get_mir_id (X_SERVER_LOCAL (display_server));
- else if (IS_MIR_SERVER (display_server))
- id = mir_server_get_id (MIR_SERVER (display_server));
+ g_clear_object (&seat->priv->active_session);
+ seat->priv->active_session = g_object_ref (session);
- if (id)
- {
- l_debug (seat, "Switching to Mir session %s", id);
- write_message (SEAT_UNITY (seat), USC_MESSAGE_SET_ACTIVE_SESSION, (const guint8 *) id, strlen (id));
- }
- else
- l_warning (seat, "Failed to work out session ID");
- }
+ if (g_strcmp0 (old_id, new_id) != 0)
+ unity_system_compositor_set_active_session (seat->priv->compositor, new_id);
- SEAT_CLASS (seat_unity_parent_class)->set_active_session (seat, session);
+ SEAT_CLASS (seat_unity_parent_class)->set_active_session (s, session);
}
static Session *
seat_unity_get_active_session (Seat *seat)
{
- if (SEAT_UNITY (seat)->priv->use_vt_switching)
- {
- gint vt;
- GList *link;
- vt = vt_get_active ();
- if (vt < 0)
- return NULL;
-
- for (link = seat_get_sessions (seat); link; link = link->next)
- {
- Session *session = link->data;
- if (display_server_get_vt (session_get_display_server (session)) == vt)
- return session;
- }
-
- return NULL;
- }
-
return SEAT_UNITY (seat)->priv->active_session;
}
if (!session)
return;
- /* If no compositor, don't worry about it */
- if (SEAT_UNITY (seat)->priv->use_vt_switching)
- return;
-
display_server = session_get_display_server (session);
if (IS_X_SERVER_LOCAL (display_server))
- id = x_server_local_get_mir_id (X_SERVER_LOCAL (display_server));
- else if (IS_MIR_SERVER (display_server))
- id = mir_server_get_id (MIR_SERVER (display_server));
+ id = x_server_xmir_get_mir_id (X_SERVER_XMIR (display_server));
+ else
+ id = session_get_env (session, "MIR_SERVER_NAME");
if (id)
{
l_debug (seat, "Marking Mir session %s as the next session", id);
- write_message (SEAT_UNITY (seat), USC_MESSAGE_SET_NEXT_SESSION, (const guint8 *) id, strlen (id));
+ unity_system_compositor_set_next_session (SEAT_UNITY (seat)->priv->compositor, id);
}
else
{
static void
seat_unity_run_script (Seat *seat, DisplayServer *display_server, Process *script)
{
- const gchar *path;
- XServerLocal *x_server;
+ if (IS_X_SERVER_XMIR (display_server))
+ {
+ XServerXmir *x_server;
+ const gchar *path;
- x_server = X_SERVER_LOCAL (display_server);
- path = x_server_local_get_authority_file_path (x_server);
- process_set_env (script, "DISPLAY", x_server_get_address (X_SERVER (x_server)));
- process_set_env (script, "XAUTHORITY", path);
+ x_server = X_SERVER_XMIR (display_server);
+ path = x_server_local_get_authority_file_path (X_SERVER_LOCAL (x_server));
+ process_set_env (script, "DISPLAY", x_server_get_address (X_SERVER (x_server)));
+ process_set_env (script, "XAUTHORITY", path);
+ }
SEAT_CLASS (seat_unity_parent_class)->run_script (seat, display_server, script);
}
seat_unity_stop (Seat *seat)
{
/* Stop the compositor first */
- if (process_get_is_running (SEAT_UNITY (seat)->priv->compositor_process))
- {
- process_stop (SEAT_UNITY (seat)->priv->compositor_process);
- return;
- }
+ if (SEAT_UNITY (seat)->priv->compositor)
+ display_server_stop (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->compositor));
+
+ /* Stop the XDMCP X server first */
+ if (SEAT_UNITY (seat)->priv->xdmcp_x_server)
+ display_server_stop (DISPLAY_SERVER (SEAT_UNITY (seat)->priv->xdmcp_x_server));
- SEAT_CLASS (seat_unity_parent_class)->stop (seat);
+ check_stopped (SEAT_UNITY (seat));
}
static void
seat_unity_init (SeatUnity *seat)
{
seat->priv = G_TYPE_INSTANCE_GET_PRIVATE (seat, SEAT_UNITY_TYPE, SeatUnityPrivate);
- seat->priv->vt = -1;
- seat->priv->compositor_process = process_new ();
}
static void
{
SeatUnity *seat = SEAT_UNITY (object);
- if (seat->priv->vt >= 0)
- vt_unref (seat->priv->vt);
- g_free (seat->priv->log_file);
- g_free (seat->priv->mir_socket_filename);
- close (seat->priv->to_compositor_pipe[0]);
- close (seat->priv->to_compositor_pipe[1]);
- close (seat->priv->from_compositor_pipe[0]);
- close (seat->priv->from_compositor_pipe[1]);
- g_io_channel_unref (seat->priv->from_compositor_channel);
- g_source_remove (seat->priv->from_compositor_watch);
- g_free (seat->priv->read_buffer);
- g_object_unref (seat->priv->compositor_process);
- if (seat->priv->active_session)
- g_object_unref (seat->priv->active_session);
- if (seat->priv->active_display_server)
- g_object_unref (seat->priv->active_display_server);
+ g_clear_object (&seat->priv->compositor);
+ if (seat->priv->xdmcp_x_server)
+ {
+ g_signal_handlers_disconnect_matched (seat->priv->xdmcp_x_server, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, seat);
+ g_object_unref (seat->priv->xdmcp_x_server);
+ }
+ g_clear_object (&seat->priv->active_session);
+ g_clear_object (&seat->priv->active_display_server);
G_OBJECT_CLASS (seat_unity_parent_class)->finalize (object);
}
SeatClass *seat_class = SEAT_CLASS (klass);
object_class->finalize = seat_unity_finalize;
- seat_class->get_start_local_sessions = seat_unity_get_start_local_sessions;
seat_class->setup = seat_unity_setup;
seat_class->start = seat_unity_start;
seat_class->create_display_server = seat_unity_create_display_server;
+ seat_class->display_server_is_used = seat_unity_display_server_is_used;
seat_class->create_greeter_session = seat_unity_create_greeter_session;
seat_class->create_session = seat_unity_create_session;
seat_class->set_active_session = seat_unity_set_active_session;