summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2017-12-26 15:58:54 +0800
committerJonas Ådahl <jadahl@gmail.com>2018-07-06 19:54:46 +0200
commitf635876eac2b892991a791009ff88d3975cb2c9a (patch)
treeb441f954faeae73a4e9a22d0597cf3017fb5902f
parent1caaf0cd1e770433f0c6ecc3a92f376fa2ed46f5 (diff)
downloadmutter-f635876eac2b892991a791009ff88d3975cb2c9a.tar.gz
x11: Open window decoration X11 connection earlier
If we wait with opening the X11 window decoration GDK connection, we might end up with a terminated X11 server before we finish initializing, depending on the things happening after spawning Xwayland and before opening the MetaX11Dispaly. In gnome-shell, this involves e.g. creating a couple of temporary X11 connections, and on disconnect, if they happen to be the last client, the X server will terminate itself. https://bugzilla.gnome.org/show_bug.cgi?id=759538
-rw-r--r--src/core/main.c16
-rw-r--r--src/meta/meta-x11-display.h2
-rw-r--r--src/x11/meta-x11-display.c108
3 files changed, 85 insertions, 41 deletions
diff --git a/src/core/main.c b/src/core/main.c
index ff2eea195..605290864 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -612,6 +612,22 @@ meta_init (void)
meta_fatal ("Can't specify both SM save file and SM client id\n");
meta_main_loop = g_main_loop_new (NULL, FALSE);
+
+ /*
+ * We need to make sure the first client connecting to the X server
+ * (e.g. Xwayland started from meta_wayland_init() above) is a permanent one,
+ * so prepare the GDK X11 connection now already. Without doing this, if
+ * there are any functionality that relies on X11 after here before
+ * meta_display_open(), the X server will terminate itself when such a client
+ * disconnects before the permanent GDK client connects.
+ */
+ if (meta_should_autostart_x11_display ())
+ {
+ GError *error = NULL;
+
+ if (!meta_x11_init_gdk_display (&error))
+ g_error ("Failed to open X11 display: %s", error->message);
+ }
}
/**
diff --git a/src/meta/meta-x11-display.h b/src/meta/meta-x11-display.h
index 9aeb60cb6..352ceb675 100644
--- a/src/meta/meta-x11-display.h
+++ b/src/meta/meta-x11-display.h
@@ -30,6 +30,8 @@
#define META_TYPE_X11_DISPLAY (meta_x11_display_get_type ())
G_DECLARE_FINAL_TYPE (MetaX11Display, meta_x11_display, META, X11_DISPLAY, GObject)
+gboolean meta_x11_init_gdk_display (GError **error);
+
int meta_x11_display_get_screen_number (MetaX11Display *x11_display);
Display *meta_x11_display_get_xdisplay (MetaX11Display *x11_display);
Window meta_x11_display_get_xroot (MetaX11Display *x11_display);
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 3dd7f204d..f5bff0da9 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -80,6 +80,8 @@ typedef struct _MetaX11DisplayLogicalMonitorData
int xinerama_index;
} MetaX11DisplayLogicalMonitorData;
+static GdkDisplay *prepared_gdk_display = NULL;
+
static const char *gnome_wm_keybindings = "Mutter";
static const char *net_wm_name = "Mutter";
@@ -972,39 +974,13 @@ meta_set_gnome_wm_keybindings (const char *wm_keybindings)
gnome_wm_keybindings = wm_keybindings;
}
-/**
- * meta_x11_display_new:
- *
- * Opens a new X11 display, sets it up, initialises all the X extensions
- * we will need.
- *
- * Returns: #MetaX11Display if the display was opened successfully,
- * and %NULL otherwise-- that is, if the display doesn't exist or
- * it already has a window manager, and sets the error appropriately.
- */
-MetaX11Display *
-meta_x11_display_new (MetaDisplay *display, GError **error)
+gboolean
+meta_x11_init_gdk_display (GError **error)
{
- MetaX11Display *x11_display;
- Display *xdisplay;
- Screen *xscreen;
- Window xroot;
- int i, number;
- Window new_wm_sn_owner;
- gboolean replace_current_wm;
- Atom wm_sn_atom;
- char buf[128];
- guint32 timestamp;
- MetaWorkspace *current_workspace;
- uint32_t current_workspace_index = 0;
- Atom atom_restart_helper;
- Window restart_helper_window = None;
+ const char *xdisplay_name;
GdkDisplay *gdk_display;
const char *gdk_gl_env = NULL;
- const char *xdisplay_name;
- MetaBackend *backend = meta_get_backend ();
- MetaMonitorManager *monitor_manager =
- meta_backend_get_monitor_manager (backend);
+ Display *xdisplay;
xdisplay_name = g_getenv ("DISPLAY");
if (!xdisplay_name)
@@ -1017,7 +993,15 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
gdk_set_allowed_backends ("x11");
gdk_gl_env = g_getenv ("GDK_GL");
- g_setenv("GDK_GL", "disable", TRUE);
+ g_setenv ("GDK_GL", "disable", TRUE);
+
+ gdk_parse_args (NULL, NULL);
+ if (!gtk_parse_args (NULL, NULL))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Failed to initialize gtk");
+ return FALSE;
+ }
gdk_display = gdk_display_open (xdisplay_name);
@@ -1028,7 +1012,7 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to initialize GDK");
- return NULL;
+ return FALSE;
}
if (gdk_gl_env)
@@ -1041,14 +1025,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
scale handling */
gdk_x11_display_set_window_scale (gdk_display, 1);
- /* A list of all atom names, so that we can intern them in one go. */
- const char *atom_names[] = {
-#define item(x) #x,
-#include "x11/atomnames.h"
-#undef item
- };
- Atom atoms[G_N_ELEMENTS(atom_names)];
-
meta_verbose ("Opening display '%s'\n", XDisplayName (NULL));
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display);
@@ -1063,14 +1039,64 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
gdk_display_close (gdk_display);
- return NULL;
+ return FALSE;
}
+ prepared_gdk_display = gdk_display;
+
+ return TRUE;
+}
+
+/**
+ * meta_x11_display_new:
+ *
+ * Opens a new X11 display, sets it up, initialises all the X extensions
+ * we will need.
+ *
+ * Returns: #MetaX11Display if the display was opened successfully,
+ * and %NULL otherwise-- that is, if the display doesn't exist or
+ * it already has a window manager, and sets the error appropriately.
+ */
+MetaX11Display *
+meta_x11_display_new (MetaDisplay *display, GError **error)
+{
+ MetaX11Display *x11_display;
+ Display *xdisplay;
+ Screen *xscreen;
+ Window xroot;
+ int i, number;
+ Window new_wm_sn_owner;
+ gboolean replace_current_wm;
+ Atom wm_sn_atom;
+ char buf[128];
+ guint32 timestamp;
+ MetaWorkspace *current_workspace;
+ uint32_t current_workspace_index = 0;
+ Atom atom_restart_helper;
+ Window restart_helper_window = None;
+ GdkDisplay *gdk_display;
+ MetaBackend *backend = meta_get_backend ();
+ MetaMonitorManager *monitor_manager =
+ meta_backend_get_monitor_manager (backend);
+
+ /* A list of all atom names, so that we can intern them in one go. */
+ const char *atom_names[] = {
+#define item(x) #x,
+#include "x11/atomnames.h"
+#undef item
+ };
+ Atom atoms[G_N_ELEMENTS(atom_names)];
+
+ g_assert (prepared_gdk_display);
+ gdk_display = g_steal_pointer (&prepared_gdk_display);
+
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
meta_xwayland_complete_init (display);
#endif
+ xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display);
+
if (meta_is_syncing ())
XSynchronize (xdisplay, True);