[mutter/wip/carlosg/xwayland-on-demand] wayland: Launch Xwayland on demand
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/carlosg/xwayland-on-demand] wayland: Launch Xwayland on demand
- Date: Mon, 7 Jan 2019 12:55:19 +0000 (UTC)
commit 74db0632ebf8c2c48b056ec6fc024c8307675877
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Jan 7 13:46:33 2019 +0100
wayland: Launch Xwayland on demand
data/org.gnome.mutter.gschema.xml.in | 2 +
src/backends/meta-backend-private.h | 3 +
src/backends/meta-backend.c | 16 ++++
src/backends/meta-settings-private.h | 1 +
src/backends/meta-settings.c | 2 +
src/compositor/compositor-private.h | 2 +
src/compositor/compositor.c | 9 ++
src/core/display-private.h | 7 --
src/core/display.c | 14 ++-
src/core/keybindings.c | 13 ++-
src/core/main-private.h | 9 +-
src/core/main.c | 22 +++--
src/core/meta-launch-context.c | 3 +-
src/core/stack-tracker.c | 41 +++++++++
src/meson.build | 7 ++
src/meta/display.h | 7 ++
src/meta/meta-x11-display.h | 21 -----
src/org.gnome.Mutter.Windowing.xml | 47 ++++++++++
src/wayland/meta-wayland-private.h | 2 +
src/wayland/meta-wayland.c | 16 ++--
src/wayland/meta-xwayland-private.h | 3 +
src/wayland/meta-xwayland.c | 169 ++++++++++++++++++++++++++++++++---
src/x11/meta-x11-display-private.h | 2 +
src/x11/meta-x11-display.c | 32 ++++++-
24 files changed, 388 insertions(+), 62 deletions(-)
---
diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in
index 6cbd9c1b5..e6a3719cf 100644
--- a/data/org.gnome.mutter.gschema.xml.in
+++ b/data/org.gnome.mutter.gschema.xml.in
@@ -120,6 +120,8 @@
framebuffers instead of window content,
to manage HiDPI monitors. Does not
require a restart.
+ • “autostart-xwayland” — initializes Xwayland lazily if there are
+ X11 clients. Requires restart.
</description>
</key>
diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
index 7c3d912be..b8573faba 100644
--- a/src/backends/meta-backend-private.h
+++ b/src/backends/meta-backend-private.h
@@ -31,6 +31,7 @@
#include "meta/meta-backend.h"
#include "meta/meta-idle-monitor.h"
+#include "meta-dbus-windowing.h"
#include "backends/meta-backend-types.h"
#include "backends/meta-cursor-renderer.h"
#include "backends/meta-egl.h"
@@ -180,4 +181,6 @@ void meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend,
void meta_backend_notify_ui_scaling_factor_changed (MetaBackend *backend);
+MetaDBusWindowing * meta_backend_get_windowing (MetaBackend *backend);
+
#endif /* META_BACKEND_PRIVATE_H */
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 709d4194c..cdd5d95c8 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -40,6 +40,7 @@
#include "meta/main.h"
#include "meta/meta-backend.h"
#include "meta/util.h"
+#include "meta-dbus-windowing.h"
#ifdef HAVE_REMOTE_DESKTOP
#include "backends/meta-dbus-session-watcher.h"
@@ -101,6 +102,7 @@ struct _MetaBackendPrivate
MetaScreenCast *screen_cast;
MetaRemoteDesktop *remote_desktop;
#endif
+ MetaDBusWindowing *windowing;
ClutterBackend *clutter_backend;
ClutterActor *stage;
@@ -483,6 +485,12 @@ meta_backend_real_post_init (MetaBackend *backend)
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
#endif /* HAVE_REMOTE_DESKTOP */
+ priv->windowing = meta_dbus_windowing_skeleton_new ();
+ g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->windowing),
+ g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL),
+ "/org/gnome/Mutter/Windowing",
+ NULL);
+
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
{
reset_pointer_position (backend);
@@ -1322,3 +1330,11 @@ meta_backend_notify_keymap_layout_group_changed (MetaBackend *backend,
g_signal_emit (backend, signals[KEYMAP_LAYOUT_GROUP_CHANGED], 0,
locked_group);
}
+
+MetaDBusWindowing *
+meta_backend_get_windowing (MetaBackend *backend)
+{
+ MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
+
+ return priv->windowing;
+}
diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h
index 90bfb439f..eb640e07e 100644
--- a/src/backends/meta-settings-private.h
+++ b/src/backends/meta-settings-private.h
@@ -32,6 +32,7 @@ typedef enum _MetaExperimentalFeature
META_EXPERIMENTAL_FEATURE_NONE = 0,
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0),
META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1),
+ META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND = (1 << 2),
} MetaExperimentalFeature;
#define META_TYPE_SETTINGS (meta_settings_get_type ())
diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c
index 34d49b3ed..5c720b2db 100644
--- a/src/backends/meta-settings.c
+++ b/src/backends/meta-settings.c
@@ -264,6 +264,8 @@ experimental_features_handler (GVariant *features_variant,
features |= META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER;
else if (g_str_equal (feature, "kms-modifiers"))
features |= META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS;
+ else if (g_str_equal (feature, "autostart-xwayland"))
+ features |= META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND;
else
g_info ("Unknown experimental feature '%s'\n", feature);
}
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
index 0f92d42da..2038a1228 100644
--- a/src/compositor/compositor-private.h
+++ b/src/compositor/compositor-private.h
@@ -69,4 +69,6 @@ MetaCloseDialog * meta_compositor_create_close_dialog (MetaCompositor *composito
MetaInhibitShortcutsDialog * meta_compositor_create_inhibit_shortcuts_dialog (MetaCompositor *compositor,
MetaWindow *window);
+void meta_compositor_redirect_x11_windows (MetaCompositor *compositor);
+
#endif /* META_COMPOSITOR_PRIVATE_H */
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index a378ed805..7a8cfc9e3 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -486,6 +486,15 @@ redirect_windows (MetaX11Display *x11_display)
}
}
+void
+meta_compositor_redirect_x11_windows (MetaCompositor *compositor)
+{
+ MetaDisplay *display = compositor->display;
+
+ if (display->x11_display)
+ redirect_windows (display->x11_display);
+}
+
void
meta_compositor_manage (MetaCompositor *compositor)
{
diff --git a/src/core/display-private.h b/src/core/display-private.h
index 8b158d440..bfa781b2f 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -357,13 +357,6 @@ void meta_display_sync_wayland_input_focus (MetaDisplay *display);
void meta_display_update_focus_window (MetaDisplay *display,
MetaWindow *window);
-void meta_display_set_input_focus (MetaDisplay *display,
- MetaWindow *window,
- gboolean focus_frame,
- guint32 timestamp);
-void meta_display_unset_input_focus (MetaDisplay *display,
- guint32 timestamp);
-
void meta_display_sanity_check_timestamps (MetaDisplay *display,
guint32 timestamp);
gboolean meta_display_timestamp_too_old (MetaDisplay *display,
diff --git a/src/core/display.c b/src/core/display.c
index 0412a9841..92209a5d4 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -50,6 +50,7 @@
#include "backends/meta-stage-private.h"
#include "backends/x11/meta-backend-x11.h"
#include "clutter/x11/clutter-x11.h"
+#include "compositor/compositor-private.h"
#include "core/bell.h"
#include "core/boxes-private.h"
#include "core/display-private.h"
@@ -643,8 +644,14 @@ meta_display_init_x11 (MetaDisplay *display,
display->x11_display = x11_display;
g_signal_emit (display, display_signals[X11_DISPLAY_OPENED], 0);
- meta_x11_display_create_guard_window (x11_display);
- meta_display_manage_all_windows (display);
+
+ if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
+ {
+ meta_x11_display_create_guard_window (x11_display);
+ meta_display_manage_all_windows (display);
+ meta_compositor_redirect_x11_windows (display->compositor);
+ }
+
return TRUE;
}
@@ -674,7 +681,6 @@ meta_display_open (void)
{
GError *error = NULL;
MetaDisplay *display;
- MetaX11Display *x11_display;
int i;
guint32 timestamp;
Window old_active_xwindow = None;
@@ -756,7 +762,7 @@ meta_display_open (void)
display->selection = meta_selection_new (display);
meta_clipboard_manager_init (display);
- if (meta_should_autostart_x11_display ())
+ if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
{
if (!meta_display_init_x11 (display, &error))
g_error ("Failed to start Xwayland: %s", error->message);
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 3830492a9..1fda18003 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -1622,7 +1622,11 @@ meta_display_grab_accelerator (MetaDisplay *display,
return META_KEYBINDING_ACTION_NONE;
}
- meta_change_keygrab (keys, display->x11_display->xroot, TRUE, &resolved_combo);
+ if (display->x11_display)
+ {
+ meta_change_keygrab (keys, display->x11_display->xroot,
+ TRUE, &resolved_combo);
+ }
grab = g_new0 (MetaKeyGrab, 1);
grab->action = next_dynamic_keybinding_action ();
@@ -1666,8 +1670,11 @@ meta_display_ungrab_accelerator (MetaDisplay *display,
{
int i;
- meta_change_keygrab (keys, display->x11_display->xroot,
- FALSE, &binding->resolved_combo);
+ if (display->x11_display)
+ {
+ meta_change_keygrab (keys, display->x11_display->xroot,
+ FALSE, &binding->resolved_combo);
+ }
for (i = 0; i < binding->resolved_combo.len; i++)
{
diff --git a/src/core/main-private.h b/src/core/main-private.h
index e59b76608..f6626b16f 100644
--- a/src/core/main-private.h
+++ b/src/core/main-private.h
@@ -28,9 +28,16 @@ typedef enum _MetaCompositorType
META_COMPOSITOR_TYPE_X11,
} MetaCompositorType;
+typedef enum _MetaDisplayPolicy
+{
+ META_DISPLAY_POLICY_MANDATORY,
+ META_DISPLAY_POLICY_ON_DEMAND,
+ META_DISPLAY_POLICY_DISABLED,
+} MetaDisplayPolicy;
+
void meta_override_compositor_configuration (MetaCompositorType compositor_type,
GType backend_gtype);
-gboolean meta_should_autostart_x11_display (void);
+MetaDisplayPolicy meta_get_x11_display_policy (void);
#endif /* META_MAIN_PRIVATE_H */
diff --git a/src/core/main.c b/src/core/main.c
index 492c74a9d..b0d50d47b 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -717,15 +717,27 @@ prefs_changed_callback (MetaPreference pref,
}
}
-gboolean
-meta_should_autostart_x11_display (void)
+MetaDisplayPolicy
+meta_get_x11_display_policy (void)
{
MetaBackend *backend = meta_get_backend ();
- gboolean wants_x11 = TRUE;
+
+ if (META_IS_BACKEND_X11_CM (backend))
+ return META_DISPLAY_POLICY_MANDATORY;
#ifdef HAVE_WAYLAND
- wants_x11 = !opt_no_x11;
+ if (meta_is_wayland_compositor ())
+ {
+ MetaSettings *settings = meta_backend_get_settings (backend);
+
+ if (opt_no_x11)
+ return META_DISPLAY_POLICY_DISABLED;
+
+ if (meta_settings_is_experimental_feature_enabled (settings,
+ META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND))
+ return META_DISPLAY_POLICY_ON_DEMAND;
+ }
#endif
- return META_IS_BACKEND_X11_CM (backend) || wants_x11;
+ return META_DISPLAY_POLICY_MANDATORY;
}
diff --git a/src/core/meta-launch-context.c b/src/core/meta-launch-context.c
index 05fc7152f..3be850f7b 100644
--- a/src/core/meta-launch-context.c
+++ b/src/core/meta-launch-context.c
@@ -113,7 +113,8 @@ meta_launch_context_constructed (GObject *object)
G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object);
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
- "DISPLAY", getenv ("DISPLAY"));
+ "DISPLAY",
+ meta_x11_get_display_name ());
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
"WAYLAND_DISPLAY", getenv ("WAYLAND_DISPLAY"));
}
diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c
index 34e4698cd..4c4465a2d 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -506,6 +506,43 @@ query_xserver_stack (MetaDisplay *display,
XFree (children);
}
+static void
+drop_x11_windows (MetaDisplay *display,
+ MetaStackTracker *tracker)
+{
+ GArray *new_stack;
+ GList *l;
+ int i;
+
+ tracker->xserver_serial = 0;
+
+ new_stack = g_array_new (FALSE, FALSE, sizeof (guint64));
+
+ for (i = 0; i < tracker->verified_stack->len; i++)
+ {
+ guint64 window = g_array_index (tracker->verified_stack, guint64, i);
+
+ if (!META_STACK_ID_IS_X11 (window))
+ g_array_append_val (new_stack, window);
+ }
+
+ g_array_unref (tracker->verified_stack);
+ tracker->verified_stack = new_stack;
+
+ l = tracker->unverified_predictions->head;
+
+ while (l)
+ {
+ MetaStackOp *op = l->data;
+ GList *next = l->next;
+
+ if (META_STACK_ID_IS_X11 (op->any.window))
+ g_queue_remove (tracker->unverified_predictions, op);
+
+ l = next;
+ }
+}
+
MetaStackTracker *
meta_stack_tracker_new (MetaDisplay *display)
{
@@ -521,6 +558,10 @@ meta_stack_tracker_new (MetaDisplay *display)
"x11-display-opened",
G_CALLBACK (query_xserver_stack),
tracker);
+ g_signal_connect (display,
+ "x11-display-closing",
+ G_CALLBACK (drop_x11_windows),
+ tracker);
meta_stack_tracker_dump (tracker);
diff --git a/src/meson.build b/src/meson.build
index c835b06f8..4fa327a21 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -601,6 +601,13 @@ dbus_idle_monitor_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor',
)
mutter_built_sources += dbus_idle_monitor_built_sources
+dbus_windowing_built_sources = gnome.gdbus_codegen('meta-dbus-windowing',
+ 'org.gnome.Mutter.Windowing.xml',
+ interface_prefix: 'org.gnome.Mutter.',
+ namespace: 'MetaDBus',
+ )
+mutter_built_sources += dbus_windowing_built_sources
+
if have_native_backend
cvt = find_program('cvt')
diff --git a/src/meta/display.h b/src/meta/display.h
index 6f80567bd..daa716959 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -86,6 +86,13 @@ MetaX11Display *meta_display_get_x11_display (MetaDisplay *display);
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
+void meta_display_set_input_focus (MetaDisplay *display,
+ MetaWindow *window,
+ gboolean focus_frame,
+ guint32 timestamp);
+void meta_display_unset_input_focus (MetaDisplay *display,
+ guint32 timestamp);
+
gboolean meta_display_xserver_time_is_before (MetaDisplay *display,
guint32 time1,
guint32 time2);
diff --git a/src/meta/meta-x11-display.h b/src/meta/meta-x11-display.h
index 352ceb675..6c4a60943 100644
--- a/src/meta/meta-x11-display.h
+++ b/src/meta/meta-x11-display.h
@@ -46,25 +46,4 @@ void meta_x11_display_set_cm_selection (MetaX11Display *x11_display);
gboolean meta_x11_display_xwindow_is_a_no_focus_window (MetaX11Display *x11_display,
Window xwindow);
-/* meta_x11_display_set_input_focus_window is like XSetInputFocus, except
- * that (a) it can't detect timestamps later than the current time,
- * since Mutter isn't part of the XServer, and thus gives erroneous
- * behavior in this circumstance (so don't do it), (b) it uses
- * display->last_focus_time since we don't have access to the true
- * Xserver one, (c) it makes use of display->user_time since checking
- * whether a window should be allowed to be focused should depend
- * on user_time events (see bug 167358, comment 15 in particular)
- */
-void meta_x11_display_set_input_focus_window (MetaX11Display *x11_display,
- MetaWindow *window,
- gboolean focus_frame,
- guint32 timestamp);
-
-/* meta_x11_display_focus_the_no_focus_window is called when the
- * designated no_focus_window should be focused, but is otherwise the
- * same as meta_display_set_input_focus_window
- */
-void meta_x11_display_focus_the_no_focus_window (MetaX11Display *x11_display,
- guint32 timestamp);
-
#endif /* META_X11_DISPLAY_H */
diff --git a/src/org.gnome.Mutter.Windowing.xml b/src/org.gnome.Mutter.Windowing.xml
new file mode 100644
index 000000000..1ea4c48df
--- /dev/null
+++ b/src/org.gnome.Mutter.Windowing.xml
@@ -0,0 +1,47 @@
+<!DOCTYPE node PUBLIC
+'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
+'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
+<node>
+ <!--
+ org.gnome.Mutter.Windowing:
+ @short_description: Windowing availability
+
+ This interface announces availability of the windowing
+ systems and their features.
+ -->
+ <interface name="org.gnome.Mutter.Windowing">
+ <!--
+ X11Available:
+
+ Says whether there is a X display server running for this
+ session.
+ -->
+ <property name="X11Available" type="b" access="read" />
+
+ <!--
+ X11Started:
+
+ The signal is emitted after a X11 display server has been
+ started for this session.
+ -->
+ <signal name="X11Started" />
+
+ <!--
+ X11PreShutdown:
+
+ The signal is emitted before the compositor intends to
+ shut the X11 display server down. Normally a grace period
+ would be given, applications might want to react to this
+ as quickly as possible.
+ -->
+ <signal name="X11PreShutdown" />
+
+ <!--
+ X11Shutdown:
+
+ The signal is emitted after the compositor did shut down
+ the X11 display server.
+ -->
+ <signal name="X11Shutdown" />
+ </interface>
+</node>
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index f2410be4c..85b127e75 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -57,6 +57,8 @@ typedef struct
GSubprocess *proc;
GMainLoop *init_loop;
+ GList *x11_windows;
+
MetaXWaylandDnd *dnd;
} MetaXWaylandManager;
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index a06d2d7d8..4f69497d5 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -263,12 +263,14 @@ meta_wayland_compositor_destroy_frame_callbacks (MetaWaylandCompositor *composit
static void
set_gnome_env (const char *name,
- const char *value)
+ const char *value,
+ gboolean set_env_on_self)
{
GDBusConnection *session_bus;
GError *error = NULL;
- setenv (name, value, TRUE);
+ if (set_env_on_self)
+ setenv (name, value, TRUE);
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
g_assert (session_bus);
@@ -413,7 +415,7 @@ meta_wayland_init (void)
meta_wayland_eglstream_controller_init (compositor);
#endif
- if (meta_should_autostart_x11_display ())
+ if (meta_get_x11_display_policy () != META_DISPLAY_POLICY_DISABLED)
{
if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
g_error ("Failed to start X Wayland");
@@ -438,10 +440,10 @@ meta_wayland_init (void)
compositor->display_name = g_strdup (display_name);
}
- if (meta_should_autostart_x11_display ())
- set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor));
+ if (meta_get_x11_display_policy () != META_DISPLAY_POLICY_DISABLED)
+ set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor), FALSE);
- set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor));
+ set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor), TRUE);
}
const char *
@@ -463,7 +465,7 @@ meta_wayland_finalize (void)
compositor = meta_wayland_compositor_get_default ();
- meta_xwayland_stop (&compositor->xwayland_manager);
+ meta_xwayland_shutdown (&compositor->xwayland_manager);
g_clear_pointer (&compositor->display_name, g_free);
}
diff --git a/src/wayland/meta-xwayland-private.h b/src/wayland/meta-xwayland-private.h
index 9a109da66..29e481b17 100644
--- a/src/wayland/meta-xwayland-private.h
+++ b/src/wayland/meta-xwayland-private.h
@@ -34,6 +34,9 @@ meta_xwayland_complete_init (MetaDisplay *display);
void
meta_xwayland_stop (MetaXWaylandManager *manager);
+void
+meta_xwayland_shutdown (MetaXWaylandManager *manager);
+
/* wl_data_device/X11 selection interoperation */
void meta_xwayland_init_dnd (void);
void meta_xwayland_shutdown_dnd (void);
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index 4432a05af..c66f6cf33 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -33,6 +33,7 @@
#include <sys/un.h>
#include "compositor/meta-surface-actor-wayland.h"
+#include "core/main-private.h"
#include "meta/main.h"
#include "wayland/meta-wayland-actor-surface.h"
@@ -351,24 +352,33 @@ xserver_died (GObject *source,
g_warning ("Failed to finish waiting for Xwayland: %s", error->message);
}
else if (!g_subprocess_get_successful (proc))
- g_warning ("X Wayland crashed; exiting");
- else
+ g_warning ("X Wayland process exited");
+
+ if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
{
- /* For now we simply abort if we see the server exit.
- *
- * In the future X will only be loaded lazily for legacy X support
- * but for now it's a hard requirement. */
- g_warning ("Spurious exit of X Wayland server");
+ meta_exit (META_EXIT_ERROR);
}
+ else if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
+ {
+ MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+ MetaDisplay *display = meta_get_display ();
- meta_exit (META_EXIT_ERROR);
+ if (display->x11_display)
+ meta_display_shutdown_x11 (display);
+
+ if (!meta_xwayland_start (&compositor->xwayland_manager,
+ compositor->wayland_display))
+ g_warning ("Failed to init X sockets");
+ }
}
static int
x_io_error (Display *display)
{
g_warning ("Connection to xwayland lost");
- meta_exit (META_EXIT_ERROR);
+
+ if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
+ meta_exit (META_EXIT_ERROR);
return 0;
}
@@ -437,6 +447,29 @@ choose_xdisplay (MetaXWaylandManager *manager)
return TRUE;
}
+static gboolean
+reopen_display_sockets (MetaXWaylandManager *manager)
+{
+ gboolean fatal;
+
+ manager->abstract_fd = bind_to_abstract_socket (manager->display_index,
+ &fatal);
+ if (manager->abstract_fd < 0)
+ {
+ g_warning ("Failed to bind abstract socket");
+ return FALSE;
+ }
+
+ manager->unix_fd = bind_to_unix_socket (manager->display_index);
+ if (manager->unix_fd < 0)
+ {
+ close (manager->abstract_fd);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void
xserver_finished_init (MetaXWaylandManager *manager)
{
@@ -454,6 +487,7 @@ on_displayfd_ready (int fd,
gpointer user_data)
{
MetaXWaylandManager *manager = user_data;
+ MetaDisplay *display = meta_get_display ();
/* The server writes its display name to the displayfd
* socket when it's ready. We don't care about the data
@@ -461,6 +495,8 @@ on_displayfd_ready (int fd,
* that means it's ready. */
xserver_finished_init (manager);
+ meta_display_init_x11 (display, NULL);
+
return G_SOURCE_REMOVE;
}
@@ -474,6 +510,9 @@ meta_xwayland_init_xserver (MetaXWaylandManager *manager)
GSubprocessFlags flags;
GError *error = NULL;
+ g_clear_object (&manager->xserver_died_cancellable);
+ g_clear_object (&manager->proc);
+
/* We want xwayland to be a wayland client so we make a socketpair to setup a
* wayland protocol connection. */
if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, xwayland_client_fd) < 0)
@@ -552,27 +591,121 @@ out:
return started;
}
+static gboolean
+xdisplay_connection_activity_cb (gint fd,
+ GIOCondition cond,
+ gpointer user_data)
+{
+ MetaXWaylandManager *manager = user_data;
+
+ if (!meta_xwayland_init_xserver (manager))
+ g_critical ("Could not start Xserver");
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+shutdown_xwayland_cb (gpointer data)
+{
+ MetaXWaylandManager *manager = data;
+
+ g_debug ("Shutting down Xwayland");
+ meta_display_shutdown_x11 (meta_get_display ());
+ meta_xwayland_stop (manager);
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+shutdown_xwayland_timeout_cb (gpointer data)
+{
+ MetaDBusWindowing *windowing;
+
+ windowing = meta_backend_get_windowing (meta_get_backend ());
+ meta_dbus_windowing_emit_x11_pre_shutdown (windowing);
+
+ /* Have a grace period for clients to handle shutdown */
+ g_timeout_add_seconds (2, shutdown_xwayland_cb, data);
+}
+
+static void
+window_unmanaged_cb (MetaWindow *window,
+ MetaXWaylandManager *manager)
+{
+ manager->x11_windows = g_list_remove (manager->x11_windows, window);
+ g_signal_handlers_disconnect_by_func (window,
+ window_unmanaged_cb,
+ manager);
+ if (!manager->x11_windows)
+ {
+ g_debug ("All X11 windows gone, setting shutdown timeout");
+ g_timeout_add_seconds (10, shutdown_xwayland_timeout_cb, manager);
+ }
+}
+
+static void
+window_created_cb (MetaDisplay *display,
+ MetaWindow *window,
+ MetaXWaylandManager *manager)
+{
+ if (window->xwindow &&
+ meta_window_get_client_pid (window) != getpid ())
+ {
+ manager->x11_windows = g_list_prepend (manager->x11_windows, window);
+ g_signal_connect (window, "unmanaged",
+ G_CALLBACK (window_unmanaged_cb), manager);
+ }
+}
+
gboolean
meta_xwayland_start (MetaXWaylandManager *manager,
struct wl_display *wl_display)
{
- if (!choose_xdisplay (manager))
- return FALSE;
+ MetaDisplayPolicy policy;
+
+ if (!manager->display_name)
+ {
+ if (!choose_xdisplay (manager))
+ return FALSE;
+ }
+ else
+ {
+ if (!reopen_display_sockets (manager))
+ return FALSE;
+ }
manager->wayland_display = wl_display;
- return meta_xwayland_init_xserver (manager);
+ policy = meta_get_x11_display_policy ();
+
+ if (policy == META_DISPLAY_POLICY_MANDATORY)
+ {
+ return meta_xwayland_init_xserver (manager);
+ }
+ else if (policy == META_DISPLAY_POLICY_ON_DEMAND)
+ {
+ g_unix_fd_add (manager->abstract_fd, G_IO_IN,
+ xdisplay_connection_activity_cb, manager);
+ return TRUE;
+ }
+
+ return FALSE;
}
static void
on_x11_display_closing (MetaDisplay *display)
{
meta_xwayland_shutdown_dnd ();
+ g_signal_handlers_disconnect_by_func (display,
+ on_x11_display_closing,
+ NULL);
}
/* To be called right after connecting */
void
meta_xwayland_complete_init (MetaDisplay *display)
{
+ MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
+ MetaXWaylandManager *manager = &compositor->xwayland_manager;
+
/* We install an X IO error handler in addition to the child watch,
because after Xlib connects our child watch may not be called soon
enough, and therefore we won't crash when X exits (and most important
@@ -583,10 +716,22 @@ meta_xwayland_complete_init (MetaDisplay *display)
g_signal_connect (display, "x11-display-closing",
G_CALLBACK (on_x11_display_closing), NULL);
meta_xwayland_init_dnd ();
+
+ g_signal_connect (meta_get_display (), "window-created",
+ G_CALLBACK (window_created_cb), manager);
}
void
meta_xwayland_stop (MetaXWaylandManager *manager)
+{
+ g_subprocess_send_signal (manager->proc, SIGTERM);
+ g_signal_handlers_disconnect_by_func (meta_get_display (),
+ window_created_cb,
+ manager);
+}
+
+void
+meta_xwayland_shutdown (MetaXWaylandManager *manager)
{
char path[256];
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index d4bbf53a7..e2e0da08a 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -243,4 +243,6 @@ void meta_x11_display_set_input_focus (MetaX11Display *x11_display,
Window xwindow,
guint32 timestamp);
+const gchar * meta_x11_get_display_name (void);
+
#endif /* META_X11_DISPLAY_PRIVATE_H */
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index e035a8138..9efc4cea5 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -236,8 +236,14 @@ meta_x11_display_dispose (GObject *object)
if (x11_display->gdk_display)
{
+ MetaDBusWindowing *windowing;
+
gdk_display_close (x11_display->gdk_display);
x11_display->gdk_display = NULL;
+
+ windowing = meta_backend_get_windowing (meta_get_backend ());
+ meta_dbus_windowing_set_x11_available (windowing, FALSE);
+ meta_dbus_windowing_emit_x11_shutdown (windowing);
}
if (x11_display->display_close_idle)
@@ -1001,6 +1007,25 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
gnome_wm_keybindings = wm_keybindings;
}
+const gchar *
+meta_x11_get_display_name (void)
+{
+#ifdef HAVE_WAYLAND
+ if (meta_is_wayland_compositor ())
+ {
+ MetaWaylandCompositor *compositor;
+
+ compositor = meta_wayland_compositor_get_default ();
+
+ return meta_wayland_get_xwayland_display_name (compositor);
+ }
+ else
+#endif
+ {
+ return g_getenv ("DISPLAY");
+ }
+}
+
gboolean
meta_x11_init_gdk_display (GError **error)
{
@@ -1009,7 +1034,7 @@ meta_x11_init_gdk_display (GError **error)
const char *gdk_gl_env = NULL;
Display *xdisplay;
- xdisplay_name = g_getenv ("DISPLAY");
+ xdisplay_name = meta_x11_get_display_name ();
if (!xdisplay_name)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -1105,6 +1130,7 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
+ MetaDBusWindowing *windowing;
/* A list of all atom names, so that we can intern them in one go. */
const char *atom_names[] = {
@@ -1386,6 +1412,10 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
meta_x11_startup_notification_init (x11_display);
meta_x11_selection_init (x11_display);
+ windowing = meta_backend_get_windowing (meta_get_backend ());
+ meta_dbus_windowing_emit_x11_started (windowing);
+ meta_dbus_windowing_set_x11_available (windowing, TRUE);
+
return x11_display;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]