[mutter/wip/carlosg/xwayland-on-demand: 27/27] 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: 27/27] wayland: Launch Xwayland on demand
- Date: Tue, 16 Apr 2019 17:23:46 +0000 (UTC)
commit 3c2c3e1928885923ea1466a58dd05ddeee89f163
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 | 9 ++
src/meta/meta-x11-display.h | 23 -----
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 | 172 ++++++++++++++++++++++++++++++++---
src/x11/meta-x11-display-private.h | 2 +
src/x11/meta-x11-display.c | 32 ++++++-
24 files changed, 393 insertions(+), 64 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 7eba1806b..9a24729e9 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"
@@ -181,4 +182,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 23ab2faec..e9017e68b 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -65,6 +65,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"
@@ -126,6 +127,7 @@ struct _MetaBackendPrivate
MetaScreenCast *screen_cast;
MetaRemoteDesktop *remote_desktop;
#endif
+ MetaDBusWindowing *windowing;
ClutterBackend *clutter_backend;
ClutterActor *stage;
@@ -509,6 +511,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);
@@ -1383,3 +1391,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 619de1710..41eddea64 100644
--- a/src/backends/meta-settings-private.h
+++ b/src/backends/meta-settings-private.h
@@ -33,6 +33,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 0854a198b..fcd5e9d69 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -488,6 +488,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 e05d5d5ed..09ba15772 100644
--- a/src/core/display-private.h
+++ b/src/core/display-private.h
@@ -364,13 +364,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 0511fb28f..689859058 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"
@@ -644,8 +645,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;
}
@@ -675,7 +682,6 @@ meta_display_open (void)
{
GError *error = NULL;
MetaDisplay *display;
- MetaX11Display *x11_display;
int i;
guint32 timestamp;
Window old_active_xwindow = None;
@@ -757,7 +763,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 a99899f80..496e251d9 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -1624,7 +1624,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 ();
@@ -1670,8 +1674,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 fc0d2d7cb..8b48103da 100644
--- a/src/core/main-private.h
+++ b/src/core/main-private.h
@@ -30,10 +30,17 @@ 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;
+
META_EXPORT_TEST
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 eda51514f..4ecbab8c5 100644
--- a/src/core/meta-launch-context.c
+++ b/src/core/meta-launch-context.c
@@ -114,7 +114,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 ee8bf011f..5892ade44 100644
--- a/src/core/stack-tracker.c
+++ b/src/core/stack-tracker.c
@@ -508,6 +508,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)
{
@@ -523,6 +560,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 66b71d173..a782972c2 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -619,6 +619,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 c2df58f27..b2ed7ba95 100644
--- a/src/meta/display.h
+++ b/src/meta/display.h
@@ -93,6 +93,15 @@ MetaX11Display *meta_display_get_x11_display (MetaDisplay *display);
META_EXPORT
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
+META_EXPORT
+void meta_display_set_input_focus (MetaDisplay *display,
+ MetaWindow *window,
+ gboolean focus_frame,
+ guint32 timestamp);
+META_EXPORT
+void meta_display_unset_input_focus (MetaDisplay *display,
+ guint32 timestamp);
+
META_EXPORT
gboolean meta_display_xserver_time_is_before (MetaDisplay *display,
guint32 time1,
diff --git a/src/meta/meta-x11-display.h b/src/meta/meta-x11-display.h
index f5167af7d..9c9adf9b7 100644
--- a/src/meta/meta-x11-display.h
+++ b/src/meta/meta-x11-display.h
@@ -63,27 +63,4 @@ META_EXPORT
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)
- */
-META_EXPORT
-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
- */
-META_EXPORT
-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 a593f0a7b..199f93d26 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 955f18e65..4e414ac34 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"
@@ -352,24 +353,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;
}
@@ -438,6 +448,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)
{
@@ -455,6 +488,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
@@ -462,6 +496,9 @@ on_displayfd_ready (int fd,
* that means it's ready. */
xserver_finished_init (manager);
+ if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
+ meta_display_init_x11 (display, NULL);
+
return G_SOURCE_REMOVE;
}
@@ -475,6 +512,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)
@@ -553,27 +593,123 @@ 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);
+
+ return G_SOURCE_REMOVE;
+}
+
+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
@@ -584,10 +720,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 65fd611a5..4b9b2f3b3 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -246,4 +246,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 118dd89b9..0824703d4 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)
@@ -998,6 +1004,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)
{
@@ -1006,7 +1031,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,
@@ -1100,6 +1125,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[] = {
@@ -1358,6 +1384,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]