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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs