From 6e0037e54d8b7b34888d81bfa6bf0c8efe0eba69 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 13 Dec 2023 10:00:09 +1100 Subject: [PATCH] Fix #115878: build error with LIBDECOR & WITH_GHOST_WAYLAND_DYNLOAD=OFF There were two problems here: - libdecor_frame_get_content_* is not available in LIBDECOR v0.1.0. - These functions aren't exposed by , they're only exposed by `libdecor-plugin.h` (intended for plug-ins that implement window decorations). Resolve by storing the last applied size from LIBDECOR for reuse. --- intern/ghost/intern/GHOST_WindowWayland.cc | 53 ++++++++++++++++--- .../extern/wayland_dynload_libdecor.h | 8 --- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/intern/ghost/intern/GHOST_WindowWayland.cc b/intern/ghost/intern/GHOST_WindowWayland.cc index c938e7969e9..e3ebfb849f2 100644 --- a/intern/ghost/intern/GHOST_WindowWayland.cc +++ b/intern/ghost/intern/GHOST_WindowWayland.cc @@ -65,6 +65,18 @@ static constexpr size_t base_dpi = 96; struct WGL_LibDecor_Window { libdecor_frame *frame = nullptr; + /** + * Store the last size applied from #libdecor_frame_interface::configure + * This is meant to be equivalent of calling: + * `libdecor_frame_get_content_width(frame)` + * `libdecor_frame_get_content_height(frame)` + * However these functions are only available via the plugin API, + * so they need to be stored somewhere. + */ + struct { + int32_t size[2] = {0, 0}; + } applied; + /** * Used at startup to set the initial window size * (before fractional scale information is available). @@ -73,6 +85,8 @@ struct WGL_LibDecor_Window { /** The window has been configured (see #xdg_surface_ack_configure). */ bool initial_configure_seen = false; + /** The window size has been configured. */ + bool initial_configure_seen_with_size = false; /** The window state has been configured. */ bool initial_state_seen = false; }; @@ -1153,12 +1167,21 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame, GWL_WindowFrame *frame_pending = &static_cast(data)->frame_pending; /* Set the size. */ - int size_decor[2]{ - libdecor_frame_get_content_width(frame), - libdecor_frame_get_content_height(frame), - }; int size_next[2] = {0, 0}; bool has_size = false; + + /* Keep track the current size of window decorations (last set by this function). */ + int size_decor[2] = {0, 0}; + + { + const GWL_Window *win = static_cast(data); + const WGL_LibDecor_Window &decor = *win->libdecor; + if (decor.initial_configure_seen_with_size) { + size_decor[0] = decor.applied.size[0]; + size_decor[1] = decor.applied.size[1]; + } + } + { GWL_Window *win = static_cast(data); const int fractional_scale = win->frame.fractional_scale ? @@ -1259,12 +1282,21 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame, GWL_Window *win = static_cast(data); WGL_LibDecor_Window &decor = *win->libdecor; if (has_size == false) { + /* Keep the current decor size. */ size_next[0] = size_decor[0]; size_next[1] = size_decor[1]; } - libdecor_state *state = libdecor_state_new(UNPACK2(size_next)); - libdecor_frame_commit(frame, state, configuration); - libdecor_state_free(state); + else { + /* Store the new size for later reuse. */ + decor.applied.size[0] = size_next[0]; + decor.applied.size[1] = size_next[1]; + } + + if (size_next[0] && size_next[1]) { + libdecor_state *state = libdecor_state_new(UNPACK2(size_next)); + libdecor_frame_commit(frame, state, configuration); + libdecor_state_free(state); + } /* Only ever use this once, after initial creation: * #wp_fractional_scale_v1_listener::preferred_scale provides fractional scaling values. */ @@ -1278,6 +1310,13 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame, decor.initial_state_seen = true; } } + if (decor.initial_configure_seen_with_size == false) { + if (is_main_thread) { + if (size_next[0] && size_next[1]) { + decor.initial_configure_seen_with_size = true; + } + } + } } } diff --git a/intern/wayland_dynload/extern/wayland_dynload_libdecor.h b/intern/wayland_dynload/extern/wayland_dynload_libdecor.h index 82afefdf4f4..4e1f206dfdb 100644 --- a/intern/wayland_dynload/extern/wayland_dynload_libdecor.h +++ b/intern/wayland_dynload/extern/wayland_dynload_libdecor.h @@ -21,8 +21,6 @@ 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_content_height) -WAYLAND_DYNLOAD_FN(libdecor_frame_get_content_width) WAYLAND_DYNLOAD_FN(libdecor_frame_get_xdg_toplevel) WAYLAND_DYNLOAD_FN(libdecor_frame_map) WAYLAND_DYNLOAD_FN(libdecor_frame_set_app_id) @@ -78,8 +76,6 @@ struct WaylandDynload_Libdecor { void WL_DYN_FN(libdecor_frame_commit)(struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration); - int WL_DYN_FN(libdecor_frame_get_content_width)(struct libdecor_frame *frame); - int WL_DYN_FN(libdecor_frame_get_content_height)(struct libdecor_frame *frame); 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); @@ -116,10 +112,6 @@ 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_content_height(...) \ - (*wayland_dynload_libdecor.libdecor_frame_get_content_height)(__VA_ARGS__) -# define libdecor_frame_get_content_width(...) \ - (*wayland_dynload_libdecor.libdecor_frame_get_content_width)(__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__)