Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-10-12 08:54:31 +0300
committerCampbell Barton <campbell@blender.org>2022-10-12 09:01:52 +0300
commitf0e1089a33f4054998c96a50b92503251a47aa97 (patch)
tree66eee14b091d73b2b52445799bacca932cfa3a7a
parent0f60872461e19282d8d058c6edc5e2cebd4f5c7e (diff)
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.
-rw-r--r--intern/ghost/CMakeLists.txt20
-rw-r--r--intern/ghost/intern/GHOST_ISystem.cpp8
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp217
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h19
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp286
5 files changed, 364 insertions, 186 deletions
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) {
+ display_destroy(d);
+ throw std::runtime_error("Wayland: unable to create window decorations!");
+ }
+ }
+ else
#endif
+ {
+ WGL_XDG_Decor_System &decor = *d->xdg_decor;
+ if (!decor.shell) {
+ display_destroy(d);
+ throw std::runtime_error("Wayland: unable to access xdg_shell!");
+ }
+ }
/* Register data device per seat for IPC between Wayland clients. */
if (d->data_device_manager) {
@@ -4052,24 +4139,26 @@ wl_compositor *GHOST_SystemWayland::compositor()
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
-libdecor *GHOST_SystemWayland::decor_context()
+libdecor *GHOST_SystemWayland::libdecor_context()
{
- return d->decor_context;
+ GHOST_ASSERT(use_libdecor, "X");
+ GHOST_ASSERT(d->libdecor != nullptr, "X");
+ return d->libdecor->context;
}
-#else /* WITH_GHOST_WAYLAND_LIBDECOR */
+#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
-xdg_wm_base *GHOST_SystemWayland::xdg_shell()
+xdg_wm_base *GHOST_SystemWayland::xdg_decor_shell()
{
- return d->xdg_shell;
+ return d->xdg_decor->shell;
}
-zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager()
+zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decor_manager()
{
- return d->xdg_decoration_manager;
+ return d->xdg_decor->manager;
}
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
+/* End `xdg_decor`. */
const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs() const
{
@@ -4317,8 +4406,15 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
return GHOST_kSuccess;
}
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+bool GHOST_SystemWayland::use_libdecor_runtime()
+{
+ return use_libdecor;
+}
+#endif
+
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
-bool ghost_wl_dynload_libraries()
+bool ghost_wl_dynload_libraries_init()
{
# ifdef WITH_GHOST_X11
/* When running in WAYLAND, let the user know when a missing library is the only reason
@@ -4329,38 +4425,33 @@ bool ghost_wl_dynload_libraries()
bool verbose = true;
# endif /* !WITH_GHOST_X11 */
-# ifdef WITH_GHOST_WAYLAND_LIBDECOR
- int8_t libdecor_init = -1;
-# endif
-
if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
wayland_dynload_cursor_init(verbose) && /* `libwayland-cursor`. */
- wayland_dynload_egl_init(verbose) && /* `libwayland-egl`. */
+ wayland_dynload_egl_init(verbose) /* `libwayland-egl`. */
+ ) {
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
- (libdecor_init = wayland_dynload_libdecor_init(verbose)) && /* `libdecor-0`. */
+ has_libdecor = wayland_dynload_libdecor_init(verbose); /* `libdecor-0`. */
# endif
- true) {
return true;
}
-# if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_GHOST_X11)
- if (libdecor_init == 0) {
- /* 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
-
-# ifdef WITH_GHOST_WAYLAND_LIBDECOR
- wayland_dynload_libdecor_exit();
-# endif
wayland_dynload_client_exit();
wayland_dynload_cursor_exit();
wayland_dynload_egl_exit();
return false;
}
+
+void ghost_wl_dynload_libraries_exit()
+{
+ wayland_dynload_client_exit();
+ wayland_dynload_cursor_exit();
+ wayland_dynload_egl_exit();
+# ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ wayland_dynload_libdecor_exit();
+# endif
+}
+
#endif /* WITH_GHOST_WAYLAND_DYNLOAD */
/** \} */
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index caea7b0d748..864dee72b0c 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -21,10 +21,6 @@
# include <wayland_dynload_libdecor.h>
# endif
# include <libdecor.h>
-#else
-/* Generated by `wayland-scanner`. */
-# include <xdg-decoration-unstable-v1-client-protocol.h>
-# include <xdg-shell-client-protocol.h>
#endif
#include <string>
@@ -52,7 +48,8 @@ void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface);
* Return true when all required WAYLAND libraries are present,
* Performs dynamic loading when `WITH_GHOST_WAYLAND_DYNLOAD` is in use.
*/
-bool ghost_wl_dynload_libraries();
+bool ghost_wl_dynload_libraries_init();
+void ghost_wl_dynload_libraries_exit();
#endif
struct GWL_Output {
@@ -167,11 +164,11 @@ 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();
+ libdecor *libdecor_context();
#endif
+ struct xdg_wm_base *xdg_decor_shell();
+ struct zxdg_decoration_manager_v1 *xdg_decor_manager();
+ /* End `xdg_decor`. */
const std::vector<GWL_Output *> &outputs() const;
@@ -192,6 +189,10 @@ class GHOST_SystemWayland : public GHOST_System {
wl_surface *wl_surface,
int scale);
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ static bool use_libdecor_runtime();
+#endif
+
private:
struct GWL_Display *d;
std::string selection;
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 5f3cb3e3f3a..62897b220b8 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -31,13 +31,52 @@
# include <libdecor.h>
#endif
+/* Generated by `wayland-scanner`. */
+#include <xdg-decoration-unstable-v1-client-protocol.h>
+#include <xdg-shell-client-protocol.h>
+
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
static constexpr size_t base_dpi = 96;
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+/* Access `use_libdecor` in #GHOST_SystemWayland. */
+# define use_libdecor GHOST_SystemWayland::use_libdecor_runtime()
+#endif
+
static GHOST_WindowManager *window_manager = nullptr;
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+struct WGL_LibDecor_Window {
+ struct libdecor_frame *frame = nullptr;
+ bool configured = false;
+};
+
+static void wgl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
+{
+ libdecor_frame_unref(decor->frame);
+ delete decor;
+}
+#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
+
+struct WGL_XDG_Decor_Window {
+ struct xdg_surface *surface = nullptr;
+ struct zxdg_toplevel_decoration_v1 *toplevel_decor = nullptr;
+ struct xdg_toplevel *toplevel = nullptr;
+ enum zxdg_toplevel_decoration_v1_mode mode = (enum zxdg_toplevel_decoration_v1_mode)0;
+};
+
+static void wgl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
+{
+ if (decor->toplevel_decor) {
+ zxdg_toplevel_decoration_v1_destroy(decor->toplevel_decor);
+ }
+ xdg_toplevel_destroy(decor->toplevel);
+ xdg_surface_destroy(decor->surface);
+ delete decor;
+}
+
struct GWL_Window {
GHOST_WindowWayland *w = nullptr;
struct wl_surface *wl_surface = nullptr;
@@ -60,15 +99,9 @@ struct GWL_Window {
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 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;
+ WGL_LibDecor_Window *libdecor = nullptr;
#endif
+ WGL_XDG_Decor_Window *xdg_decor = nullptr;
wl_egl_window *egl_window = nullptr;
bool is_maximised = false;
@@ -146,10 +179,8 @@ static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs
/** \name Listener (XDG Top Level), #xdg_toplevel_listener
* \{ */
-#ifndef WITH_GHOST_WAYLAND_LIBDECOR
-
static CLG_LogRef LOG_WL_XDG_TOPLEVEL = {"ghost.wl.handle.xdg_toplevel"};
-# define LOG (&LOG_WL_XDG_TOPLEVEL)
+#define LOG (&LOG_WL_XDG_TOPLEVEL)
static void xdg_toplevel_handle_configure(void *data,
xdg_toplevel * /*xdg_toplevel*/,
@@ -197,9 +228,7 @@ static const xdg_toplevel_listener toplevel_listener = {
xdg_toplevel_handle_close,
};
-# undef LOG
-
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
+#undef LOG
/** \} */
@@ -250,7 +279,7 @@ static void frame_handle_configure(struct libdecor_frame *frame,
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
- win->decor_configured = true;
+ win->libdecor->configured = true;
}
static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data)
@@ -285,10 +314,8 @@ static struct libdecor_frame_interface libdecor_frame_iface = {
/** \name Listener (XDG Decoration Listener), #zxdg_toplevel_decoration_v1_listener
* \{ */
-#ifndef WITH_GHOST_WAYLAND_LIBDECOR
-
static CLG_LogRef LOG_WL_XDG_TOPLEVEL_DECORATION = {"ghost.wl.handle.xdg_toplevel_decoration"};
-# define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
+#define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
static void xdg_toplevel_decoration_handle_configure(
void *data,
@@ -296,16 +323,14 @@ static void xdg_toplevel_decoration_handle_configure(
const uint32_t mode)
{
CLOG_INFO(LOG, 2, "configure (mode=%u)", mode);
- static_cast<GWL_Window *>(data)->decoration_mode = (zxdg_toplevel_decoration_v1_mode)mode;
+ static_cast<GWL_Window *>(data)->xdg_decor->mode = (zxdg_toplevel_decoration_v1_mode)mode;
}
static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
xdg_toplevel_decoration_handle_configure,
};
-# undef LOG
-
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
+#undef LOG
/** \} */
@@ -313,10 +338,8 @@ static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listene
/** \name Listener (XDG Surface Handle Configure), #xdg_surface_listener
* \{ */
-#ifndef WITH_GHOST_WAYLAND_LIBDECOR
-
static CLG_LogRef LOG_WL_XDG_SURFACE = {"ghost.wl.handle.xdg_surface"};
-# define LOG (&LOG_WL_XDG_SURFACE)
+#define LOG (&LOG_WL_XDG_SURFACE)
static void xdg_surface_handle_configure(void *data,
xdg_surface *xdg_surface,
@@ -324,7 +347,7 @@ static void xdg_surface_handle_configure(void *data,
{
GWL_Window *win = static_cast<GWL_Window *>(data);
- if (win->xdg_surface != xdg_surface) {
+ if (win->xdg_decor->surface != xdg_surface) {
CLOG_INFO(LOG, 2, "configure (skipped)");
return;
}
@@ -354,9 +377,7 @@ static const xdg_surface_listener xdg_surface_listener = {
xdg_surface_handle_configure,
};
-# undef LOG
-
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
+#undef LOG
/** \} */
@@ -477,42 +498,52 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
const int32_t size_min[2] = {320, 240};
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- /* create window decorations */
- w->decor_frame = libdecor_decorate(
- m_system->decor_context(), w->wl_surface, &libdecor_frame_iface, w);
- libdecor_frame_map(w->decor_frame);
+ if (use_libdecor) {
+ w->libdecor = new WGL_LibDecor_Window;
+ WGL_LibDecor_Window &decor = *w->libdecor;
- libdecor_frame_set_min_content_size(w->decor_frame, UNPACK2(size_min));
+ /* create window decorations */
+ decor.frame = libdecor_decorate(
+ m_system->libdecor_context(), w->wl_surface, &libdecor_frame_iface, w);
+ libdecor_frame_map(w->libdecor->frame);
- if (parentWindow) {
- libdecor_frame_set_parent(
- w->decor_frame, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->decor_frame);
- }
-#else
- w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->xdg_shell(), w->wl_surface);
- w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
-
- xdg_toplevel_set_min_size(w->xdg_toplevel, UNPACK2(size_min));
+ libdecor_frame_set_min_content_size(decor.frame, UNPACK2(size_min));
- if (m_system->xdg_decoration_manager()) {
- w->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
- m_system->xdg_decoration_manager(), w->xdg_toplevel);
- zxdg_toplevel_decoration_v1_add_listener(
- w->xdg_toplevel_decoration, &toplevel_decoration_v1_listener, w);
- zxdg_toplevel_decoration_v1_set_mode(w->xdg_toplevel_decoration,
- ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+ if (parentWindow) {
+ WGL_LibDecor_Window &decor_parent =
+ *dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->libdecor;
+ libdecor_frame_set_parent(decor.frame, decor_parent.frame);
+ }
}
+ else
+#endif
+ {
+ w->xdg_decor = new WGL_XDG_Decor_Window;
+ WGL_XDG_Decor_Window &decor = *w->xdg_decor;
+ decor.surface = xdg_wm_base_get_xdg_surface(m_system->xdg_decor_shell(), w->wl_surface);
+ decor.toplevel = xdg_surface_get_toplevel(decor.surface);
+
+ xdg_toplevel_set_min_size(decor.toplevel, UNPACK2(size_min));
+
+ if (m_system->xdg_decor_manager()) {
+ decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
+ m_system->xdg_decor_manager(), decor.toplevel);
+ zxdg_toplevel_decoration_v1_add_listener(
+ decor.toplevel_decor, &toplevel_decoration_v1_listener, w);
+ zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
+ ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+ }
- xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
- xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
+ xdg_surface_add_listener(decor.surface, &xdg_surface_listener, w);
+ xdg_toplevel_add_listener(decor.toplevel, &toplevel_listener, w);
- if (parentWindow && is_dialog) {
- xdg_toplevel_set_parent(
- w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
+ if (parentWindow && is_dialog) {
+ WGL_XDG_Decor_Window &decor_parent =
+ *dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_decor;
+ xdg_toplevel_set_parent(decor.toplevel, decor_parent.toplevel);
+ }
}
-#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
-
setTitle(title);
wl_surface_set_user_data(w->wl_surface, this);
@@ -522,11 +553,14 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
wl_display_roundtrip(m_system->display());
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- /* It's important not to return until the window is configured or
- * calls to `setState` from Blender will crash `libdecor`. */
- while (!w->decor_configured) {
- if (libdecor_dispatch(m_system->decor_context(), 0) < 0) {
- break;
+ if (use_libdecor) {
+ WGL_LibDecor_Window &decor = *w->libdecor;
+ /* It's important not to return until the window is configured or
+ * calls to `setState` from Blender will crash `libdecor`. */
+ while (!decor.configured) {
+ if (libdecor_dispatch(m_system->libdecor_context(), 0) < 0) {
+ break;
+ }
}
}
#endif
@@ -535,9 +569,13 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
setOpaque();
#endif
-#ifndef WITH_GHOST_WAYLAND_LIBDECOR /* Causes a glitch with `libdecor` for some reason. */
- setState(state);
+ /* Causes a glitch with `libdecor` for some reason. */
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor == false)
#endif
+ {
+ setState(state);
+ }
/* EGL context. */
if (setDrawingContextType(type) == GHOST_kFailure) {
@@ -596,12 +634,18 @@ GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
void GHOST_WindowWayland::setTitle(const char *title)
{
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_set_app_id(w->decor_frame, title);
- libdecor_frame_set_title(w->decor_frame, title);
-#else
- xdg_toplevel_set_title(w->xdg_toplevel, title);
- xdg_toplevel_set_app_id(w->xdg_toplevel, title);
+ if (use_libdecor) {
+ WGL_LibDecor_Window &decor = *w->libdecor;
+ libdecor_frame_set_app_id(decor.frame, title);
+ libdecor_frame_set_title(decor.frame, title);
+ }
+ else
#endif
+ {
+ WGL_XDG_Decor_Window &decor = *w->xdg_decor;
+ xdg_toplevel_set_title(decor.toplevel, title);
+ xdg_toplevel_set_app_id(decor.toplevel, title);
+ }
this->title = title;
}
@@ -672,14 +716,14 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
wl_egl_window_destroy(w->egl_window);
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_unref(w->decor_frame);
-#else
- if (w->xdg_toplevel_decoration) {
- zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration);
+ if (use_libdecor) {
+ wgl_libdecor_window_destroy(w->libdecor);
}
- xdg_toplevel_destroy(w->xdg_toplevel);
- xdg_surface_destroy(w->xdg_surface);
+ else
#endif
+ {
+ wgl_xdg_decor_window_destroy(w->xdg_decor);
+ }
/* Clear any pointers to this window. This is needed because there are no guarantees
* that flushing the display will the "leave" handlers before handling events. */
@@ -711,47 +755,74 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
case GHOST_kWindowStateNormal:
/* Unset states. */
switch (getState()) {
- case GHOST_kWindowStateMaximized:
+ case GHOST_kWindowStateMaximized: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_unset_maximized(w->decor_frame);
-#else
- xdg_toplevel_unset_maximized(w->xdg_toplevel);
+ if (use_libdecor) {
+ libdecor_frame_unset_maximized(w->libdecor->frame);
+ }
+ else
#endif
+ {
+ xdg_toplevel_unset_maximized(w->xdg_decor->toplevel);
+ }
break;
- case GHOST_kWindowStateFullScreen:
+ }
+ case GHOST_kWindowStateFullScreen: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_unset_fullscreen(w->decor_frame);
-#else
- xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
+ if (use_libdecor) {
+ libdecor_frame_unset_fullscreen(w->libdecor->frame);
+ }
+ else
#endif
+ {
+ xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
+ }
break;
- default:
+ }
+ default: {
break;
+ }
}
break;
- case GHOST_kWindowStateMaximized:
+ case GHOST_kWindowStateMaximized: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_set_maximized(w->decor_frame);
-#else
- xdg_toplevel_set_maximized(w->xdg_toplevel);
+ if (use_libdecor) {
+ libdecor_frame_set_maximized(w->libdecor->frame);
+ }
+ else
#endif
+ {
+ xdg_toplevel_set_maximized(w->xdg_decor->toplevel);
+ }
break;
- case GHOST_kWindowStateMinimized:
+ }
+ case GHOST_kWindowStateMinimized: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_set_minimized(w->decor_frame);
-#else
- xdg_toplevel_set_minimized(w->xdg_toplevel);
+ if (use_libdecor) {
+ libdecor_frame_set_minimized(w->libdecor->frame);
+ }
+ else
#endif
+ {
+ xdg_toplevel_set_minimized(w->xdg_decor->toplevel);
+ }
break;
- case GHOST_kWindowStateFullScreen:
+ }
+ case GHOST_kWindowStateFullScreen: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
-#else
- xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
+ if (use_libdecor) {
+ libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
+ }
+ else
#endif
+ {
+ xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
+ }
break;
- case GHOST_kWindowStateEmbedded:
+ }
+ case GHOST_kWindowStateEmbedded: {
return GHOST_kFailure;
+ }
}
return GHOST_kSuccess;
}
@@ -780,20 +851,29 @@ GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
{
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
-#else
- xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
+ if (use_libdecor) {
+ libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
+ }
+ else
#endif
+ {
+ xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
+ }
+
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
{
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- libdecor_frame_unset_fullscreen(w->decor_frame);
-#else
- xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
+ if (use_libdecor) {
+ libdecor_frame_unset_fullscreen(w->libdecor->frame);
+ }
+ else
#endif
+ {
+ xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
+ }
return GHOST_kSuccess;
}