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, ®istry_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. @@ _______________________________________________ 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