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__)