[Bf-blender-cvs] [f0e1089a33f] master: GHOST/Wayland: only require libdecor when running in gnome-shell

Campbell Barton noreply at git.blender.org
Wed Oct 12 08:03:20 CEST 2022


Commit: f0e1089a33f4054998c96a50b92503251a47aa97
Author: Campbell Barton
Date:   Wed Oct 12 16:54:31 2022 +1100
Branches: master
https://developer.blender.org/rBf0e1089a33f4054998c96a50b92503251a47aa97

GHOST/Wayland: only require libdecor when running in gnome-shell

- Support switching between libdecor and xdg_shell at run-time.

- Require libdecor when using gnome-shell, otherwise use xdg_shell.

- Gnome-shell detection checks for a gtk_shell* interface which
  isn't ideal however it's not possible to check server-side-decorations
  are supported without first creating a window.

- Unload Wayland libraries when Wayland fails to load.

===================================================================

M	intern/ghost/CMakeLists.txt
M	intern/ghost/intern/GHOST_ISystem.cpp
M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h
M	intern/ghost/intern/GHOST_WindowWayland.cpp

===================================================================

diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 9e3a15dd543..2f8ea1f9065 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -349,16 +349,16 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
       ${INC_DST}
     )
 
-    if(NOT WITH_GHOST_WAYLAND_LIBDECOR)
-      # `xdg-shell`.
-      generate_protocol_bindings(
-        "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
-      )
-      # `xdg-decoration`.
-      generate_protocol_bindings(
-        "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
-      )
-    endif()
+    # Used when: LIBDECOR is not needed.
+    # `xdg-shell`.
+    generate_protocol_bindings(
+      "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
+    )
+    # `xdg-decoration`.
+    generate_protocol_bindings(
+      "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
+    )
+    # End LIBDECOR alternative.
 
     # `xdg-output`.
     generate_protocol_bindings(
diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp
index 0a35d1af5a4..8e2859ca1e1 100644
--- a/intern/ghost/intern/GHOST_ISystem.cpp
+++ b/intern/ghost/intern/GHOST_ISystem.cpp
@@ -48,7 +48,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
     /* Pass. */
 #elif defined(WITH_GHOST_WAYLAND)
 #  if defined(WITH_GHOST_WAYLAND_DYNLOAD)
-    const bool has_wayland_libraries = ghost_wl_dynload_libraries();
+    const bool has_wayland_libraries = ghost_wl_dynload_libraries_init();
 #  else
     const bool has_wayland_libraries = true;
 #  endif
@@ -66,6 +66,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
       catch (const std::runtime_error &) {
         delete m_system;
         m_system = nullptr;
+#  ifdef WITH_GHOST_WAYLAND_DYNLOAD
+        ghost_wl_dynload_libraries_exit();
+#  endif
       }
     }
     else {
@@ -101,6 +104,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
       catch (const std::runtime_error &) {
         delete m_system;
         m_system = nullptr;
+#  ifdef WITH_GHOST_WAYLAND_DYNLOAD
+        ghost_wl_dynload_libraries_exit();
+#  endif
       }
     }
     else {
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 7e56ed0affb..44b20ae2aef 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -54,6 +54,11 @@
 #include <tablet-unstable-v2-client-protocol.h>
 #include <xdg-output-unstable-v1-client-protocol.h>
 
+/* Decorations `xdg_decor`. */
+#include <xdg-decoration-unstable-v1-client-protocol.h>
+#include <xdg-shell-client-protocol.h>
+/* End `xdg_decor`. */
+
 #include <fcntl.h>
 #include <sys/mman.h>
 #include <unistd.h>
@@ -64,6 +69,15 @@
 /* Logging, use `ghost.wl.*` prefix. */
 #include "CLG_log.h"
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+static bool use_libdecor = true;
+#  ifdef WITH_GHOST_WAYLAND_DYNLOAD
+static bool has_libdecor = false;
+#  else
+static bool has_libdecor = true;
+#  endif
+#endif
+
 static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
 
 static void output_handle_done(void *data, struct wl_output *wl_output);
@@ -106,6 +120,13 @@ static bool use_gnome_confine_hack = false;
  */
 #define USE_GNOME_KEYBOARD_SUPPRESS_WARNING
 
+/**
+ * When GNOME is found, require `libdecor`.
+ * This is a hack because it seems there is no way to check if the compositor supports
+ * server side decorations when initializing WAYLAND.
+ */
+#define USE_GNOME_NEEDS_LIBDECOR_HACK
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -357,6 +378,36 @@ struct WGL_KeyboardDepressedState {
   int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0};
 };
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+struct WGL_LibDecor_System {
+  struct libdecor *context = nullptr;
+};
+
+static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor)
+{
+  if (decor->context) {
+    libdecor_unref(decor->context);
+  }
+  delete decor;
+}
+#endif
+
+struct WGL_XDG_Decor_System {
+  struct xdg_wm_base *shell = nullptr;
+  struct zxdg_decoration_manager_v1 *manager = nullptr;
+};
+
+static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor)
+{
+  if (decor->manager) {
+    zxdg_decoration_manager_v1_destroy(decor->manager);
+  }
+  if (decor->shell) {
+    xdg_wm_base_destroy(decor->shell);
+  }
+  delete decor;
+}
+
 struct GWL_Seat {
   GHOST_SystemWayland *system = nullptr;
 
@@ -455,11 +506,10 @@ struct GWL_Display {
   struct wl_compositor *compositor = nullptr;
 
 #ifdef WITH_GHOST_WAYLAND_LIBDECOR
-  struct libdecor *decor_context = nullptr;
-#else
-  struct xdg_wm_base *xdg_shell = nullptr;
-  struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
+  WGL_LibDecor_System *libdecor = nullptr;
+  bool libdecor_required = false;
 #endif
+  WGL_XDG_Decor_System *xdg_decor = nullptr;
 
   struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
   struct wl_shm *shm = nullptr;
@@ -626,19 +676,19 @@ static void display_destroy(GWL_Display *d)
   }
 
 #ifdef WITH_GHOST_WAYLAND_LIBDECOR
-  if (d->decor_context) {
-    libdecor_unref(d->decor_context);
+  if (use_libdecor) {
+    if (d->libdecor) {
+      wgl_libdecor_system_destroy(d->libdecor);
+    }
   }
-#else
-  if (d->xdg_decoration_manager) {
-    zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
+  else
+#endif
+  {
+    if (d->xdg_decor) {
+      wgl_xdg_decor_system_destroy(d->xdg_decor);
+    }
   }
 
-  if (d->xdg_shell) {
-    xdg_wm_base_destroy(d->xdg_shell);
-  }
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
-
   if (eglGetDisplay) {
     ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
   }
@@ -2903,10 +2953,8 @@ static const struct wl_output_listener output_listener = {
 /** \name Listener (XDG WM Base), #xdg_wm_base_listener
  * \{ */
 
-#ifndef WITH_GHOST_WAYLAND_LIBDECOR
-
 static CLG_LogRef LOG_WL_XDG_WM_BASE = {"ghost.wl.handle.xdg_wm_base"};
-#  define LOG (&LOG_WL_XDG_WM_BASE)
+#define LOG (&LOG_WL_XDG_WM_BASE)
 
 static void shell_handle_ping(void * /*data*/,
                               struct xdg_wm_base *xdg_wm_base,
@@ -2920,9 +2968,7 @@ static const struct xdg_wm_base_listener shell_listener = {
     shell_handle_ping,
 };
 
-#  undef LOG
-
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
+#undef LOG
 
 /** \} */
 
@@ -2978,19 +3024,17 @@ static void global_handle_add(void *data,
     display->compositor = static_cast<wl_compositor *>(
         wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
   }
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
-  /* Pass. */
-#else
   else if (STREQ(interface, xdg_wm_base_interface.name)) {
-    display->xdg_shell = static_cast<xdg_wm_base *>(
+    WGL_XDG_Decor_System &decor = *display->xdg_decor;
+    decor.shell = static_cast<xdg_wm_base *>(
         wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
-    xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
+    xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr);
   }
   else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) {
-    display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>(
+    WGL_XDG_Decor_System &decor = *display->xdg_decor;
+    decor.manager = static_cast<zxdg_decoration_manager_v1 *>(
         wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
   }
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
   else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) {
     display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
         wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
@@ -3048,6 +3092,18 @@ static void global_handle_add(void *data,
   }
   else {
     found = false;
+
+#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
+#  ifdef WITH_GHOST_X11
+#    ifdef WITH_GHOST_WAYLAND_LIBDECOR
+    if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */
+      /* Only require libdecor when built with X11 support,
+       * otherwise there is nothing to fall back on. */
+      display->libdecor_required = true;
+    }
+#    endif /* WITH_GHOST_WAYLAND_LIBDECOR */
+#  endif   /* WITH_GHOST_X11 */
+#endif     /* USE_GNOME_NEEDS_LIBDECOR_HACK */
   }
 
   CLOG_INFO(LOG,
@@ -3102,6 +3158,9 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
     throw std::runtime_error("Wayland: unable to connect to display!");
   }
 
+  /* This may be removed later if decorations are required, needed as part of registration. */
+  d->xdg_decor = new WGL_XDG_Decor_System;
+
   /* Register interfaces. */
   struct wl_registry *registry = wl_display_get_registry(d->display);
   wl_registry_add_listener(registry, &registry_listener, d);
@@ -3112,17 +3171,45 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
   wl_registry_destroy(registry);
 
 #ifdef WITH_GHOST_WAYLAND_LIBDECOR
-  d->decor_context = libdecor_new(d->display, &libdecor_interface);
-  if (!d->decor_context) {
-    display_destroy(d);
-    throw std::runtime_error("Wayland: unable to create window decorations!");
+  if (d->libdecor_required) {
+    wgl_xdg_decor_system_destroy(d->xdg_decor);
+    d->xdg_decor = nullptr;
+
+    if (!has_libdecor) {
+#  ifdef WITH_GHOST_X11
+      /* LIBDECOR was the only reason X11 was used, let the user know they need it installed. */
+      fprintf(stderr,
+              "WAYLAND found but libdecor was not, install libdecor for Wayland support, "
+              "falling back to X11\n");
+#  endif
+      display_destroy(d);
+      throw std::runtime_error("Wayland: unable to find libdecor!");
+    }
   }
-#else
-  if (!d->xdg_shell) {
-    display_destroy(d);
-    throw std::runtime_error("Wayland: unable to access xdg_shell!");
+  else {
+    use_libdecor = false;
   }
+#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
+
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  if (use_libdecor) {
+    d->libdecor = new WGL_LibDecor_System;
+    WGL_LibDecor_System &decor = *d->libdecor;
+    decor.context = libdecor_new(d->display, &libdecor_interface);
+    if (!decor.context) {
+      displ

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list