[Bf-blender-cvs] [aee5fcc120e] blender-v3.4-release: GHOST/Wayland: improve workaround for libdecor setting the window state
Campbell Barton
noreply at git.blender.org
Wed Nov 16 02:33:15 CET 2022
Commit: aee5fcc120e538e5850a0fe7cf7a0118b1574783
Author: Campbell Barton
Date: Wed Nov 16 10:45:56 2022 +1100
Branches: blender-v3.4-release
https://developer.blender.org/rBaee5fcc120e538e5850a0fe7cf7a0118b1574783
GHOST/Wayland: improve workaround for libdecor setting the window state
libdecor has a workaround where creating the window would loop until
the windows configure callback ran.
Simplify this workaround by setting the initial state on the underlying
xdg_toplevel struct.
Also correct mixup between bool / GHOST_TSuccess types.
===================================================================
M intern/ghost/intern/GHOST_WindowWayland.cpp
M intern/wayland_dynload/extern/wayland_dynload_libdecor.h
===================================================================
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 9a916f9bd1b..99bbf9109ec 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -173,35 +173,24 @@ static GHOST_TWindowState gwl_window_state_get(const GWL_Window *win)
return GHOST_kWindowStateNormal;
}
-static bool gwl_window_state_set(GWL_Window *win, const GHOST_TWindowState state)
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+/**
+ * \note Keep in sync with #gwl_window_state_set_for_xdg.
+ */
+static bool gwl_window_state_set_for_libdecor(struct libdecor_frame *frame,
+ const GHOST_TWindowState state,
+ const GHOST_TWindowState state_current)
{
- const GHOST_TWindowState state_current = gwl_window_state_get(win);
switch (state) {
case GHOST_kWindowStateNormal:
/* Unset states. */
switch (state_current) {
case GHOST_kWindowStateMaximized: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_unset_maximized(win->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_unset_maximized(win->xdg_decor->toplevel);
- }
+ libdecor_frame_unset_maximized(frame);
break;
}
case GHOST_kWindowStateFullScreen: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_unset_fullscreen(win->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_unset_fullscreen(win->xdg_decor->toplevel);
- }
+ libdecor_frame_unset_fullscreen(frame);
break;
}
default: {
@@ -210,46 +199,83 @@ static bool gwl_window_state_set(GWL_Window *win, const GHOST_TWindowState state
}
break;
case GHOST_kWindowStateMaximized: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_set_maximized(win->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_set_maximized(win->xdg_decor->toplevel);
- }
+ libdecor_frame_set_maximized(frame);
break;
}
case GHOST_kWindowStateMinimized: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_set_minimized(win->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_set_minimized(win->xdg_decor->toplevel);
- }
+ libdecor_frame_set_minimized(frame);
break;
}
case GHOST_kWindowStateFullScreen: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_set_fullscreen(win->libdecor->frame, nullptr);
- }
- else
-#endif
- {
- xdg_toplevel_set_fullscreen(win->xdg_decor->toplevel, nullptr);
+ libdecor_frame_set_fullscreen(frame, nullptr);
+ break;
+ }
+ case GHOST_kWindowStateEmbedded: {
+ return false;
+ }
+ }
+ return true;
+}
+
+#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
+
+/**
+ * \note Keep in sync with #gwl_window_state_set_for_libdecor.
+ */
+static bool gwl_window_state_set_for_xdg(struct xdg_toplevel *toplevel,
+ const GHOST_TWindowState state,
+ const GHOST_TWindowState state_current)
+{
+ switch (state) {
+ case GHOST_kWindowStateNormal:
+ /* Unset states. */
+ switch (state_current) {
+ case GHOST_kWindowStateMaximized: {
+ xdg_toplevel_unset_maximized(toplevel);
+ break;
+ }
+ case GHOST_kWindowStateFullScreen: {
+ xdg_toplevel_unset_fullscreen(toplevel);
+ break;
+ }
+ default: {
+ break;
+ }
}
break;
+ case GHOST_kWindowStateMaximized: {
+ xdg_toplevel_set_maximized(toplevel);
+ break;
+ }
+ case GHOST_kWindowStateMinimized: {
+ xdg_toplevel_set_minimized(toplevel);
+ break;
+ }
+ case GHOST_kWindowStateFullScreen: {
+ xdg_toplevel_set_fullscreen(toplevel, nullptr);
+ break;
}
case GHOST_kWindowStateEmbedded: {
- return GHOST_kFailure;
+ return false;
}
}
- return GHOST_kSuccess;
+ return true;
+}
+
+static bool gwl_window_state_set(GWL_Window *win, const GHOST_TWindowState state)
+{
+ const GHOST_TWindowState state_current = gwl_window_state_get(win);
+ bool result;
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ result = gwl_window_state_set_for_libdecor(win->libdecor->frame, state, state_current);
+ }
+ else
+#endif
+ {
+ result = gwl_window_state_set_for_xdg(win->xdg_decor->toplevel, state, state_current);
+ }
+ return result;
}
/** \} */
@@ -856,26 +882,23 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
wl_surface_commit(window_->wl_surface);
wl_display_roundtrip(system_->wl_display());
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- WGL_LibDecor_Window &decor = *window_->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(system_->libdecor_context(), 0) < 0) {
- break;
- }
- }
- }
-#endif
-
#ifdef GHOST_OPENGL_ALPHA
setOpaque();
#endif
/* Causes a glitch with `libdecor` for some reason. */
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor == false)
+ if (use_libdecor) {
+ /* Additional round-trip is needed to ensure `xdg_toplevel` is set. */
+ wl_display_roundtrip(system_->wl_display());
+
+ /* NOTE: LIBDECOR requires the window to be created & configured before the state can be set.
+ * Workaround this by using the underlying `xdg_toplevel` */
+ WGL_LibDecor_Window &decor = *window_->libdecor;
+ struct xdg_toplevel *toplevel = libdecor_frame_get_xdg_toplevel(decor.frame);
+ gwl_window_state_set_for_xdg(toplevel, state, GHOST_kWindowStateNormal);
+ }
+ else
#endif
{
gwl_window_state_set(window_, state);
diff --git a/intern/wayland_dynload/extern/wayland_dynload_libdecor.h b/intern/wayland_dynload/extern/wayland_dynload_libdecor.h
index 9dcecb4d876..0f5459491c0 100644
--- a/intern/wayland_dynload/extern/wayland_dynload_libdecor.h
+++ b/intern/wayland_dynload/extern/wayland_dynload_libdecor.h
@@ -19,6 +19,7 @@ WAYLAND_DYNLOAD_FN(libdecor_configuration_get_window_state)
WAYLAND_DYNLOAD_FN(libdecor_decorate)
WAYLAND_DYNLOAD_FN(libdecor_dispatch)
WAYLAND_DYNLOAD_FN(libdecor_frame_commit)
+WAYLAND_DYNLOAD_FN(libdecor_frame_get_xdg_toplevel)
WAYLAND_DYNLOAD_FN(libdecor_frame_map)
WAYLAND_DYNLOAD_FN(libdecor_frame_set_app_id)
WAYLAND_DYNLOAD_FN(libdecor_frame_set_fullscreen)
@@ -73,6 +74,7 @@ struct WaylandDynload_Libdecor {
void WL_DYN_FN(libdecor_frame_commit)(struct libdecor_frame *frame,
struct libdecor_state *state,
struct libdecor_configuration *configuration);
+ struct xdg_toplevel *WL_DYN_FN(libdecor_frame_get_xdg_toplevel)(struct libdecor_frame *frame);
void WL_DYN_FN(libdecor_frame_map)(struct libdecor_frame *frame);
void WL_DYN_FN(libdecor_frame_set_app_id)(struct libdecor_frame *frame, const char *app_id);
void WL_DYN_FN(libdecor_frame_set_fullscreen)(struct libdecor_frame *frame,
@@ -108,6 +110,8 @@ struct WaylandDynload_Libdecor {
# define libdecor_dispatch(...) (*wayland_dynload_libdecor.libdecor_dispatch)(__VA_ARGS__)
# define libdecor_frame_commit(...) \
(*wayland_dynload_libdecor.libdecor_frame_commit)(__VA_ARGS__)
+# define libdecor_frame_get_xdg_toplevel(...) \
+ (*wayland_dynload_libdecor.libdecor_frame_get_xdg_toplevel)(__VA_ARGS__)
# define libdecor_frame_map(...) (*wayland_dynload_libdecor.libdecor_frame_map)(__VA_ARGS__)
# define libdecor_frame_set_app_id(...) \
(*wayland_dynload_libdecor.libdecor_frame_set_app_id)(__VA_ARGS__)
More information about the Bf-blender-cvs
mailing list