mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 09:30:45 -05:00
xwayland: Do not block on Xwayland initialization
We artificially made Xwayland initialization synchronous, as we used to rely on MetaX11Display and other bits during meta_display_open(). With support for Xwayland on demand and --no-x11, this is certainly not the case. So drop the main loop surrounding Xwayland initialization, and turn it into an async operation called from meta_display_init_x11(). This function is turned then into the high-level entry point that will get you from no X server to having a MetaX11Display. The role of meta_init() in Xwayland initialization is thus reduced to setting up the sockets. Notably no processes are spawned from here, deferring that till there is a MetaDisplay to poke. https://gitlab.gnome.org/GNOME/mutter/merge_requests/944
This commit is contained in:
parent
649911b6b3
commit
25c9e66c73
@ -716,19 +716,40 @@ meta_display_init_x11_finish (MetaDisplay *display,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_xserver_started (MetaXWaylandManager *manager,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = user_data;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
retval = meta_xwayland_start_xserver_finish (manager, result, &error);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
else
|
||||||
|
g_task_return_boolean (task, retval);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_display_init_x11 (MetaDisplay *display,
|
meta_display_init_x11 (MetaDisplay *display,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
GAsyncReadyCallback callback,
|
GAsyncReadyCallback callback,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GTask *task;
|
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||||
|
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
|
|
||||||
task = g_task_new (display, cancellable, callback, user_data);
|
task = g_task_new (display, cancellable, callback, user_data);
|
||||||
g_task_set_source_tag (task, meta_display_init_x11);
|
g_task_set_source_tag (task, meta_display_init_x11);
|
||||||
|
|
||||||
g_task_return_boolean (task, TRUE);
|
meta_xwayland_start_xserver (&compositor->xwayland_manager,
|
||||||
g_object_unref (task);
|
cancellable,
|
||||||
|
(GAsyncReadyCallback) on_xserver_started,
|
||||||
|
g_steal_pointer (&task));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -57,7 +57,6 @@ typedef struct
|
|||||||
|
|
||||||
GCancellable *xserver_died_cancellable;
|
GCancellable *xserver_died_cancellable;
|
||||||
GSubprocess *proc;
|
GSubprocess *proc;
|
||||||
GMainLoop *init_loop;
|
|
||||||
|
|
||||||
GList *x11_windows;
|
GList *x11_windows;
|
||||||
|
|
||||||
|
@ -42,4 +42,12 @@ gboolean meta_xwayland_dnd_handle_event (XEvent *xevent);
|
|||||||
|
|
||||||
const MetaWaylandDragDestFuncs * meta_xwayland_selection_get_drag_dest_funcs (void);
|
const MetaWaylandDragDestFuncs * meta_xwayland_selection_get_drag_dest_funcs (void);
|
||||||
|
|
||||||
|
void meta_xwayland_start_xserver (MetaXWaylandManager *manager,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
gboolean meta_xwayland_start_xserver_finish (MetaXWaylandManager *manager,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
#endif /* META_XWAYLAND_PRIVATE_H */
|
#endif /* META_XWAYLAND_PRIVATE_H */
|
||||||
|
@ -534,17 +534,6 @@ add_local_user_to_xhost (Display *xdisplay)
|
|||||||
XAddHost (xdisplay, &host_entry);
|
XAddHost (xdisplay, &host_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
xserver_finished_init (MetaXWaylandManager *manager)
|
|
||||||
{
|
|
||||||
/* At this point xwayland is all setup to start accepting
|
|
||||||
* connections so we can quit the transient initialization mainloop
|
|
||||||
* and unblock meta_wayland_init() to continue initializing mutter.
|
|
||||||
* */
|
|
||||||
g_main_loop_quit (manager->init_loop);
|
|
||||||
g_clear_pointer (&manager->init_loop, g_main_loop_unref);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_init_x11_cb (MetaDisplay *display,
|
on_init_x11_cb (MetaDisplay *display,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
@ -561,45 +550,53 @@ on_displayfd_ready (int fd,
|
|||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaXWaylandManager *manager = user_data;
|
GTask *task = user_data;
|
||||||
MetaDisplay *display = meta_get_display ();
|
|
||||||
|
|
||||||
/* The server writes its display name to the displayfd
|
/* The server writes its display name to the displayfd
|
||||||
* socket when it's ready. We don't care about the data
|
* socket when it's ready. We don't care about the data
|
||||||
* in the socket, just that it wrote something, since
|
* in the socket, just that it wrote something, since
|
||||||
* that means it's ready. */
|
* that means it's ready. */
|
||||||
xserver_finished_init (manager);
|
g_task_return_boolean (task, TRUE);
|
||||||
|
g_object_unref (task);
|
||||||
if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
|
|
||||||
{
|
|
||||||
meta_display_init_x11 (display, NULL,
|
|
||||||
(GAsyncReadyCallback) on_init_x11_cb, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
void
|
||||||
meta_xwayland_start_xserver (MetaXWaylandManager *manager)
|
meta_xwayland_start_xserver (MetaXWaylandManager *manager,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
int xwayland_client_fd[2];
|
int xwayland_client_fd[2];
|
||||||
int displayfd[2];
|
int displayfd[2];
|
||||||
g_autoptr(GSubprocessLauncher) launcher = NULL;
|
g_autoptr(GSubprocessLauncher) launcher = NULL;
|
||||||
GSubprocessFlags flags;
|
GSubprocessFlags flags;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
|
|
||||||
|
task = g_task_new (NULL, cancellable, callback, user_data);
|
||||||
|
g_task_set_source_tag (task, meta_xwayland_start_xserver);
|
||||||
|
g_task_set_task_data (task, manager, NULL);
|
||||||
|
|
||||||
/* We want xwayland to be a wayland client so we make a socketpair to setup a
|
/* We want xwayland to be a wayland client so we make a socketpair to setup a
|
||||||
* wayland protocol connection. */
|
* wayland protocol connection. */
|
||||||
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
|
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
|
||||||
{
|
{
|
||||||
g_warning ("xwayland_client_fd socketpair failed\n");
|
g_task_return_new_error (task,
|
||||||
return FALSE;
|
G_IO_ERROR,
|
||||||
|
g_io_error_from_errno (errno),
|
||||||
|
"xwayland_client_fd socketpair failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
|
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, displayfd) < 0)
|
||||||
{
|
{
|
||||||
g_warning ("displayfd socketpair failed\n");
|
g_task_return_new_error (task,
|
||||||
return FALSE;
|
G_IO_ERROR,
|
||||||
|
g_io_error_from_errno (errno),
|
||||||
|
"displayfd socketpair failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xwayland, please. */
|
/* xwayland, please. */
|
||||||
@ -633,24 +630,28 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager)
|
|||||||
NULL);
|
NULL);
|
||||||
if (!manager->proc)
|
if (!manager->proc)
|
||||||
{
|
{
|
||||||
g_error ("Failed to spawn Xwayland: %s", error->message);
|
g_task_return_error (task, error);
|
||||||
return FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
manager->xserver_died_cancellable = g_cancellable_new ();
|
manager->xserver_died_cancellable = g_cancellable_new ();
|
||||||
g_subprocess_wait_async (manager->proc, manager->xserver_died_cancellable,
|
g_subprocess_wait_async (manager->proc, manager->xserver_died_cancellable,
|
||||||
xserver_died, NULL);
|
xserver_died, NULL);
|
||||||
g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready, manager);
|
g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready,
|
||||||
|
g_steal_pointer (&task));
|
||||||
manager->client = wl_client_create (manager->wayland_display,
|
manager->client = wl_client_create (manager->wayland_display,
|
||||||
xwayland_client_fd[0]);
|
xwayland_client_fd[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to run a mainloop until we know xwayland has a binding
|
gboolean
|
||||||
* for our xserver interface at which point we can assume it's
|
meta_xwayland_start_xserver_finish (MetaXWaylandManager *manager,
|
||||||
* ready to start accepting connections. */
|
GAsyncResult *result,
|
||||||
manager->init_loop = g_main_loop_new (NULL, FALSE);
|
GError **error)
|
||||||
g_main_loop_run (manager->init_loop);
|
{
|
||||||
|
g_assert (g_task_get_source_tag (G_TASK (result)) ==
|
||||||
|
meta_xwayland_start_xserver);
|
||||||
|
|
||||||
return TRUE;
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -658,10 +659,10 @@ xdisplay_connection_activity_cb (gint fd,
|
|||||||
GIOCondition cond,
|
GIOCondition cond,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaXWaylandManager *manager = user_data;
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
|
||||||
if (!meta_xwayland_start_xserver (manager))
|
meta_display_init_x11 (display, NULL,
|
||||||
g_critical ("Could not start Xserver");
|
(GAsyncReadyCallback) on_init_x11_cb, NULL);
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
@ -744,18 +745,13 @@ meta_xwayland_init (MetaXWaylandManager *manager,
|
|||||||
manager->wayland_display = wl_display;
|
manager->wayland_display = wl_display;
|
||||||
policy = meta_get_x11_display_policy ();
|
policy = meta_get_x11_display_policy ();
|
||||||
|
|
||||||
if (policy == META_DISPLAY_POLICY_MANDATORY)
|
if (policy == META_DISPLAY_POLICY_ON_DEMAND)
|
||||||
{
|
|
||||||
return meta_xwayland_start_xserver (manager);
|
|
||||||
}
|
|
||||||
else if (policy == META_DISPLAY_POLICY_ON_DEMAND)
|
|
||||||
{
|
{
|
||||||
g_unix_fd_add (manager->abstract_fd, G_IO_IN,
|
g_unix_fd_add (manager->abstract_fd, G_IO_IN,
|
||||||
xdisplay_connection_activity_cb, manager);
|
xdisplay_connection_activity_cb, manager);
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user