From e9434732d4d6ac204b2f72281e5e7a5c12b20e1b Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Thu, 8 Aug 2013 17:07:54 +0200 Subject: [PATCH] MetaWayland: implement spawning dbus and gnome-session If we launch gnome-session ourselves after setting up XWayland, we then get gnome-settings-daemon and all the required session stuff, which means we can run a full regular gnome session. --- src/core/monitor-private.h | 7 ++++ src/core/monitor.c | 28 ++++++++++--- src/core/screen.c | 5 +++ src/wayland/meta-wayland.c | 85 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 6 deletions(-) diff --git a/src/core/monitor-private.h b/src/core/monitor-private.h index b1dcc0e18..f3792b311 100644 --- a/src/core/monitor-private.h +++ b/src/core/monitor-private.h @@ -299,6 +299,13 @@ GType meta_monitor_manager_get_type (void); void meta_monitor_manager_initialize (void); MetaMonitorManager *meta_monitor_manager_get (void); +void meta_monitor_manager_init_dbus (MetaMonitorManager *manager, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean meta_monitor_manager_init_dbus_finish (MetaMonitorManager *manager, + GAsyncResult *result, + GError **error); + MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager, unsigned int *n_infos); diff --git a/src/core/monitor.c b/src/core/monitor.c index ea592c414..ecfb9d80d 100644 --- a/src/core/monitor.c +++ b/src/core/monitor.c @@ -61,7 +61,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaMonitorManager, meta_monitor_manager, META_DBUS_TYP static void free_output_array (MetaOutput *old_outputs, int n_old_outputs); static void invalidate_logical_config (MetaMonitorManager *manager); -static void initialize_dbus_interface (MetaMonitorManager *manager); static void read_current_dummy (MetaMonitorManager *manager) @@ -525,7 +524,6 @@ meta_monitor_manager_constructed (GObject *object) } make_logical_config (manager); - initialize_dbus_interface (manager); manager->in_init = FALSE; } @@ -1321,7 +1319,8 @@ on_bus_acquired (GDBusConnection *connection, const char *name, gpointer user_data) { - MetaMonitorManager *manager = user_data; + GTask *task = user_data; + MetaMonitorManager *manager = g_task_get_task_data (task); g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (manager), connection, @@ -1334,7 +1333,11 @@ on_name_acquired (GDBusConnection *connection, const char *name, gpointer user_data) { + GTask *task = user_data; + meta_topic (META_DEBUG_DBUS, "Acquired name %s\n", name); + + g_task_return_boolean (task, TRUE); } static void @@ -1345,9 +1348,14 @@ on_name_lost (GDBusConnection *connection, meta_topic (META_DEBUG_DBUS, "Lost or failed to acquire name %s\n", name); } -static void -initialize_dbus_interface (MetaMonitorManager *manager) +void +meta_monitor_manager_init_dbus (MetaMonitorManager *manager, + GAsyncReadyCallback callback, + gpointer user_data) { + GTask *task = g_task_new (manager, NULL, callback, user_data); + g_task_set_task_data (task, g_object_ref (manager), g_object_unref); + manager->dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION, "org.gnome.Mutter.DisplayConfig", G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | @@ -1356,10 +1364,18 @@ initialize_dbus_interface (MetaMonitorManager *manager) on_bus_acquired, on_name_acquired, on_name_lost, - g_object_ref (manager), + task, g_object_unref); } +gboolean +meta_monitor_manager_init_dbus_finish (MetaMonitorManager *manager, + GAsyncResult *result, + GError **error) +{ + return g_task_propagate_boolean (G_TASK (result), error); +} + static MetaMonitorManager *global_manager; void diff --git a/src/core/screen.c b/src/core/screen.c index dbcf76715..ddf756934 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -690,6 +690,11 @@ meta_screen_new (MetaDisplay *display, &screen->rect.width, &screen->rect.height); +#ifdef HAVE_WAYLAND + if (!meta_is_wayland_compositor ()) +#endif + meta_monitor_manager_init_dbus (manager, NULL, NULL); + screen->current_cursor = -1; /* invalid/unset */ screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen); screen->default_depth = DefaultDepthOfScreen (screen->xscreen); diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index 82e510218..9705da5ad 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include @@ -1255,6 +1257,55 @@ bind_shell (struct wl_client *client, wl_resource_set_implementation (resource, &meta_wayland_shell_interface, data, NULL); } +static void +gnome_session_died (GPid pid, + gint status, + gpointer user_data) +{ + if (!WIFEXITED (status)) + g_error ("gnome-session crashed; aborting"); + else + { + /* A clean exit of gnome-session implies a logout, exit cleanly */ + meta_quit (META_EXIT_SUCCESS); + } +} + +static void +start_gnome_session (MetaWaylandCompositor *compositor) +{ + GPid pid; + char *args[6]; + GError *error; + + args[0] = "setsid"; + args[1] = "gnome-session"; + args[2] = "--session"; + args[3] = "gnome-wayland"; + args[4] = "--debug"; + args[5] = NULL; + + error = NULL; + if (g_spawn_async (NULL, /* cwd */ + args, + NULL, + G_SPAWN_SEARCH_PATH | + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, + NULL, + &pid, + &error)) + { + g_message ("forked gnome-session, pid %d\n", pid); + + g_child_watch_add (pid, gnome_session_died, NULL); + } + else + { + g_error ("Failed to fork gnome-session server: %s", error->message); + } +} + static void stage_destroy_cb (void) { @@ -1565,6 +1616,21 @@ on_monitors_changed (MetaMonitorManager *monitors, compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors); } +static void +on_display_config_ready (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + gboolean ok; + + ok = meta_monitor_manager_init_dbus_finish (META_MONITOR_MANAGER (object), result, NULL); + g_assert (ok); + + /* Now we have X and DBus, and our stuff is on the bus. + The only thing missing is gnome-session! */ + start_gnome_session (user_data); +} + void meta_wayland_init (void) { @@ -1575,6 +1641,8 @@ meta_wayland_init (void) CoglRenderer *cogl_renderer; int weston_launch_fd; MetaMonitorManager *monitors; + GDBusConnection *session_bus; + char *session_bus_address; memset (compositor, 0, sizeof (MetaWaylandCompositor)); @@ -1728,6 +1796,23 @@ meta_wayland_init (void) g_error ("Failed to start X Wayland"); putenv (g_strdup_printf ("DISPLAY=:%d", compositor->xwayland_display_index)); + + /* Now xwayland is ready. Get ourselves a dbus daemon. This will autolaunch + if no bus is found. + */ + session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + if (!session_bus) + meta_fatal ("Could not connect to the session bus\n"); + + session_bus_address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, NULL, NULL); + putenv (g_strdup_printf ("DBUS_SESSION_BUS_ADDRESS=%s", session_bus_address)); + g_free (session_bus_address); + + /* Now get our interface on the dbus (or gnome-settings-daemon will refuse + to start, which in turn will stall gnome-session from launching the rest + of the session) + */ + meta_monitor_manager_init_dbus (monitors, on_display_config_ready, compositor); } void