summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorRobert Ancell <robert.ancell@canonical.com>2011-08-17 15:49:16 +1000
committerRobert Ancell <robert.ancell@canonical.com>2011-08-17 15:49:16 +1000
commit4897357cfb1491d2e477ab40cf8dfe5e8eb77141 (patch)
tree1da4ae807747425cf5c9f8da8a5e7bc05e9d3b28 /utils
parent2ba06483232942ac2cbbed5c76f21bb9bad3f1c3 (diff)
downloadlightdm-git-4897357cfb1491d2e477ab40cf8dfe5e8eb77141.tar.gz
Add dm-tool command add-nested-seat
Diffstat (limited to 'utils')
-rw-r--r--utils/dm-tool.c101
1 files changed, 100 insertions, 1 deletions
diff --git a/utils/dm-tool.c b/utils/dm-tool.c
index a5b174b5..bf7b82f3 100644
--- a/utils/dm-tool.c
+++ b/utils/dm-tool.c
@@ -16,6 +16,11 @@
#include <glib/gi18n.h>
#include <gio/gio.h>
+static GDBusProxy *dm_proxy, *seat_proxy;
+
+static gint xephyr_display_number;
+static GPid xephyr_pid;
+
static void
usage ()
{
@@ -24,13 +29,58 @@ usage ()
g_printerr ("\n");
}
+static void
+xephyr_setup_cb (gpointer user_data)
+{
+ signal (SIGUSR1, SIG_IGN);
+}
+
+static void
+xephyr_signal_cb (int signum)
+{
+ gchar *display_number_string, *path;
+ GVariantBuilder *properties;
+ GVariant *result;
+ GError *error = NULL;
+
+ properties = g_variant_builder_new (G_VARIANT_TYPE ("a(ss)"));
+ display_number_string = g_strdup_printf ("%d", xephyr_display_number);
+ g_variant_builder_add_value (properties, g_variant_new ("(ss)", "xserver-display-number", display_number_string));
+ g_free (display_number_string);
+
+ result = g_dbus_proxy_call_sync (dm_proxy,
+ "AddSeat",
+ g_variant_new ("(sa(ss))", "xremote", properties),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ &error);
+ g_variant_builder_unref (properties);
+ if (!result)
+ {
+ g_printerr ("Unable to add seat: %s\n", error->message);
+ kill (xephyr_pid, SIGQUIT);
+ exit (EXIT_FAILURE);
+ }
+
+ if (!g_variant_is_of_type (result, G_VARIANT_TYPE ("(o)")))
+ {
+ g_printerr ("Unexpected response to AddSeat: %s\n", g_variant_get_type_string (result));
+ exit (EXIT_FAILURE);
+ }
+
+ g_variant_get (result, "(&o)", &path);
+ g_print ("%s\n", path);
+
+ exit (EXIT_SUCCESS);
+}
+
int
main (int argc, char **argv)
{
gchar *command;
gint n_options;
gchar **options;
- GDBusProxy *dm_proxy, *seat_proxy;
GError *error = NULL;
gint arg_index;
GBusType bus_type = G_BUS_TYPE_SYSTEM;
@@ -58,6 +108,7 @@ main (int argc, char **argv)
" switch-to-greeter Switch to the greeter\n"
" switch-to-user USERNAME [SESSION] Switch to a user session\n"
" switch-to-guest [SESSION] Switch to a guest session\n"
+ " add-nested-seat Start a nested display\n"
" add-seat TYPE [NAME=VALUE...] Add a dynamic seat\n");
return EXIT_SUCCESS;
}
@@ -195,6 +246,54 @@ main (int argc, char **argv)
}
return EXIT_SUCCESS;
}
+ else if (strcmp (command, "add-nested-seat") == 0)
+ {
+ gchar *path, *xephyr_command, **xephyr_argv;
+ GMainLoop *loop;
+
+ path = g_find_program_in_path ("Xephyr");
+ if (!path)
+ {
+ g_printerr ("Unable to find Xephry, please install it\n");
+ return EXIT_FAILURE;
+ }
+
+ /* Get a unique display number. It's racy, but the only reliable method to get one */
+ xephyr_display_number = 0;
+ while (TRUE)
+ {
+ gchar *lock_name;
+ gboolean has_lock;
+
+ lock_name = g_strdup_printf ("/tmp/.X%d-lock", xephyr_display_number);
+ has_lock = g_file_test (lock_name, G_FILE_TEST_EXISTS);
+ g_free (lock_name);
+
+ if (has_lock)
+ xephyr_display_number++;
+ else
+ break;
+ }
+
+ /* Wait for signal from Xephyr is ready */
+ signal (SIGUSR1, xephyr_signal_cb);
+
+ xephyr_command = g_strdup_printf ("Xephyr :%d", xephyr_display_number);
+ if (!g_shell_parse_argv (xephyr_command, NULL, &xephyr_argv, &error) ||
+ !g_spawn_async (NULL, xephyr_argv, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
+ xephyr_setup_cb, NULL,
+ &xephyr_pid, &error))
+ {
+ g_printerr ("Error running Xephyr: %s\n", error->message);
+ exit (EXIT_FAILURE);
+ }
+ g_clear_error (&error);
+
+ /* Block until ready */
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+ }
else if (strcmp (command, "add-seat") == 0)
{
GVariant *result;