[Bf-blender-cvs] [29755e1df82] master: GHOST/Wayland: support client-side window decorations

Christian Rauch noreply at git.blender.org
Fri Jun 24 16:13:40 CEST 2022


Commit: 29755e1df82e34061a0b0586234a5aaac5177d35
Author: Christian Rauch
Date:   Fri Jun 24 16:10:20 2022 +1000
Branches: master
https://developer.blender.org/rB29755e1df82e34061a0b0586234a5aaac5177d35

GHOST/Wayland: support client-side window decorations

This implements client-side window decorations for moving and resizing
windows and HiDPI support.

This functionality depends on the external project 'libdecor' that is
currently a build option: WITH_GHOST_WAYLAND_LIBDECOR.

Reviewed by: brecht, campbellbarton

Ref D7989

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

M	CMakeLists.txt
M	build_files/cmake/platform/platform_unix.cmake
M	intern/ghost/CMakeLists.txt
M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h
M	intern/ghost/intern/GHOST_WindowWayland.cpp

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

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 31608b0c1ce..60d980930c1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -222,6 +222,11 @@ if(UNIX AND NOT (APPLE OR HAIKU))
 
   option(WITH_GHOST_WAYLAND "Enable building Blender against Wayland for windowing (under development)" OFF)
   mark_as_advanced(WITH_GHOST_WAYLAND)
+
+  if (WITH_GHOST_WAYLAND)
+    option(WITH_GHOST_WAYLAND_LIBDECOR "Optionally build with LibDecor window decorations" OFF)
+    mark_as_advanced(WITH_GHOST_WAYLAND_LIBDECOR)
+  endif()
 endif()
 
 if(WITH_GHOST_X11)
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 6750c23d548..781e2798fea 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -615,6 +615,10 @@ if(WITH_GHOST_WAYLAND)
   pkg_check_modules(wayland-cursor REQUIRED wayland-cursor)
   pkg_check_modules(dbus REQUIRED dbus-1)
 
+  if(WITH_GHOST_WAYLAND_LIBDECOR)
+    pkg_check_modules(libdecor REQUIRED libdecor-0>=0.1)
+  endif()
+
   set(WITH_GL_EGL ON)
 
   list(APPEND PLATFORM_LINKLIBS
@@ -624,6 +628,13 @@ if(WITH_GHOST_WAYLAND)
     ${wayland-cursor_LINK_LIBRARIES}
     ${dbus_LINK_LIBRARIES}
   )
+
+  if(WITH_GHOST_WAYLAND_LIBDECOR)
+    list(APPEND PLATFORM_LINKLIBS
+      ${libdecor_LIBRARIES}
+    )
+    add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
+  endif()
 endif()
 
 if(WITH_GHOST_X11)
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 945b3261562..150bcb9273e 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -271,6 +271,12 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
       ${dbus_INCLUDE_DIRS}
     )
 
+    if(WITH_GHOST_WAYLAND_LIBDECOR)
+      list(APPEND INC_SYS
+        ${libdecor_INCLUDE_DIRS}
+      )
+    endif()
+
     include(CheckSymbolExists)
     set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
     check_symbol_exists(memfd_create "sys/mman.h" HAVE_MEMFD_CREATE)
@@ -332,14 +338,17 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
       ${INC_DST}
     )
 
-    # `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"
-    )
+    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()
+
     # `xdg-output`.
     generate_protocol_bindings(
       "${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-output/xdg-output-unstable-v1.xml"
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 8e3ca59cc74..66d0902c0ca 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -254,8 +254,14 @@ struct display_t {
 
   struct wl_display *display = nullptr;
   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;
+#endif
+
   struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
   struct wl_shm *shm = nullptr;
   std::vector<output_t *> outputs;
@@ -402,6 +408,11 @@ static void display_destroy(display_t *d)
     wl_compositor_destroy(d->compositor);
   }
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  if (d->decor_context) {
+    libdecor_unref(d->decor_context);
+  }
+#else
   if (d->xdg_decoration_manager) {
     zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
   }
@@ -409,6 +420,7 @@ static void display_destroy(display_t *d)
   if (d->xdg_shell) {
     xdg_wm_base_destroy(d->xdg_shell);
   }
+#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
 
   if (eglGetDisplay) {
     ::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
@@ -2190,6 +2202,8 @@ static const struct wl_output_listener output_listener = {
 /** \name Listener (XDG WM Base), #xdg_wm_base_listener
  * \{ */
 
+#ifndef WITH_GHOST_WAYLAND_LIBDECOR
+
 static void shell_handle_ping(void * /*data*/,
                               struct xdg_wm_base *xdg_wm_base,
                               const uint32_t serial)
@@ -2201,6 +2215,32 @@ static const struct xdg_wm_base_listener shell_listener = {
     shell_handle_ping,
 };
 
+#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Listener (LibDecor), #libdecor_interface
+ * \{ */
+
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+
+static void decor_handle_error(struct libdecor * /*context*/,
+                               enum libdecor_error error,
+                               const char *message)
+{
+  (void)(error);
+  (void)(message);
+  GHOST_PRINT("decoration error (" << error << "): " << message << std::endl);
+  exit(EXIT_FAILURE);
+}
+
+static struct libdecor_interface libdecor_interface = {
+    decor_handle_error,
+};
+
+#endif /* WITH_GHOST_WAYLAND_LIBDECOR. */
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -2218,6 +2258,9 @@ 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 (!strcmp(interface, xdg_wm_base_interface.name)) {
     display->xdg_shell = static_cast<xdg_wm_base *>(
         wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
@@ -2227,6 +2270,7 @@ static void global_handle_add(void *data,
     display->xdg_decoration_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 (!strcmp(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, 3));
@@ -2330,10 +2374,18 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new display_t)
   wl_display_roundtrip(d->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!");
+  }
+#else
   if (!d->xdg_shell) {
     display_destroy(d);
     throw std::runtime_error("Wayland: unable to access xdg_shell!");
   }
+#endif
 
   /* Register data device per seat for IPC between Wayland clients. */
   if (d->data_device_manager) {
@@ -2667,6 +2719,15 @@ wl_compositor *GHOST_SystemWayland::compositor()
   return d->compositor;
 }
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+
+libdecor *GHOST_SystemWayland::decor_context()
+{
+  return d->decor_context;
+}
+
+#else /* WITH_GHOST_WAYLAND_LIBDECOR */
+
 xdg_wm_base *GHOST_SystemWayland::xdg_shell()
 {
   return d->xdg_shell;
@@ -2677,6 +2738,8 @@ zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager()
   return d->xdg_decoration_manager;
 }
 
+#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
+
 const std::vector<output_t *> &GHOST_SystemWayland::outputs() const
 {
   return d->outputs;
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index 4b953dccac6..972d16257eb 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -13,9 +13,13 @@
 
 #include <wayland-client.h>
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+#  include <libdecor.h>
+#else
 /* Generated by `wayland-scanner`. */
-#include <xdg-decoration-unstable-v1-client-protocol.h>
-#include <xdg-shell-client-protocol.h>
+#  include <xdg-decoration-unstable-v1-client-protocol.h>
+#  include <xdg-shell-client-protocol.h>
+#endif
 
 #include <string>
 
@@ -103,9 +107,12 @@ class GHOST_SystemWayland : public GHOST_System {
 
   wl_compositor *compositor();
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  libdecor *decor_context();
+#else
   xdg_wm_base *xdg_shell();
-
   zxdg_decoration_manager_v1 *xdg_decoration_manager();
+#endif
 
   const std::vector<output_t *> &outputs() const;
 
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index afaa2e11aa7..bd11476b2e2 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -18,6 +18,10 @@
 
 #include <algorithm> /* For `std::find`. */
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+#  include <libdecor.h>
+#endif
+
 static constexpr size_t base_dpi = 96;
 
 struct window_t {
@@ -41,10 +45,17 @@ struct window_t {
    */
   uint32_t dpi = 0;
 
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+  struct libdecor_frame *decor_frame = nullptr;
+  bool decor_configured = false;
+#else
   struct xdg_surface *xdg_surface = nullptr;
-  struct xdg_toplevel *xdg_toplevel = nullptr;
   struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr;
+  struct xdg_toplevel *xdg_toplevel = nullptr;
+
   enum zxdg_toplevel_decoration_v1_mode decoration_mode = (enum zxdg_toplevel_decoration_v1_mode)0;
+#endif
+
   wl_egl_window *egl_window = nullptr;
   bool is_maximised = false;
   bool is_fullscreen = false;
@@ -121,6 +132,8 @@ static int outputs_max_scale_or_default(const std::vector<output_t *> &outputs,
 /** \name Listener (XDG Top Level), #xdg_toplevel_listener
  * \{ */
 
+#ifndef WITH_GHOST_WAYLAND_LIBDECOR
+
 static void xdg_toplevel_handle_configure(void *data,
                                           xdg_toplevel * /*xdg_toplevel*/,
                                           const int32_t width,
@@ -163,12 +176,83 @@ static const xdg_toplevel_listener toplevel_listener = {
     xdg_toplevel_handle_close,
 };
 
+#endif /* !WITH_GHOST_W

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list