[mutter] x11: Open window decoration X11 connection earlier



commit f635876eac2b892991a791009ff88d3975cb2c9a
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Dec 26 15:58:54 2017 +0800

    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

 src/core/main.c             |  16 +++++++
 src/meta/meta-x11-display.h |   2 +
 src/x11/meta-x11-display.c  | 108 +++++++++++++++++++++++++++-----------------
 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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]