diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index f60f9dad1831a..d396ef207650a 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -340,6 +340,8 @@ static void set_surface_scaling(struct vo_wayland_state *wl); static void update_output_scaling(struct vo_wayland_state *wl); static void update_output_geometry(struct vo_wayland_state *wl); static void destroy_offer(struct vo_wayland_data_offer *o); +static void apply_toplevel_config(struct vo_wayland_state *wl); +static void apply_decorations(struct vo_wayland_state *wl); #if HAVE_WAYLAND_PROTOCOLS_1_48 static char *session_file(void *talloc_ctx, const char *session, struct vo *vo); static char *read_session_id(void *talloc_ctx, struct vo_wayland_state *wl, const char *path); @@ -1777,7 +1779,12 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = { static void handle_surface_config(void *data, struct xdg_surface *surface, uint32_t serial) { + struct vo_wayland_state *wl = data; + + apply_decorations(wl); + apply_toplevel_config(wl); xdg_surface_ack_configure(surface, serial); + wl->pending_vo_events |= VO_EVENT_EXPOSE; } static const struct xdg_surface_listener xdg_surface_listener = { @@ -1788,55 +1795,75 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, struct wl_array *states) { struct vo_wayland_state *wl = data; - struct mp_vo_opts *opts = wl->opts; - struct mp_rect old_geometry = wl->geometry; + struct vo_wayland_toplevel_pending_state *pending = &wl->pending_state; + struct vo_wayland_toplevel_pending_flags *flags = &pending->flags; if (width < 0 || height < 0) { MP_WARN(wl, "Compositor sent negative width/height values. Treating them as zero.\n"); width = height = 0; } - bool is_maximized = false; - bool is_fullscreen = false; - bool is_activated = false; - bool is_resizing = false; - bool is_suspended = false; - bool is_tiled = false; + pending->width = width; + pending->height = height; + *flags = (struct vo_wayland_toplevel_pending_flags){ 0 }; + enum xdg_toplevel_state *state; wl_array_for_each(state, states) { switch (*state) { case XDG_TOPLEVEL_STATE_FULLSCREEN: - is_fullscreen = true; + flags->is_fullscreen = true; break; case XDG_TOPLEVEL_STATE_RESIZING: - is_resizing = true; + flags->is_resizing = true; break; case XDG_TOPLEVEL_STATE_ACTIVATED: - is_activated = true; - /* - * If we get an ACTIVATED state, we know it cannot be - * minimized, but it may not have been minimized - * previously, so we can't detect the exact state. - */ - opts->window_minimized = false; - m_config_cache_write_opt(wl->opts_cache, - &opts->window_minimized); + flags->is_activated = true; break; case XDG_TOPLEVEL_STATE_TILED_TOP: case XDG_TOPLEVEL_STATE_TILED_LEFT: case XDG_TOPLEVEL_STATE_TILED_RIGHT: case XDG_TOPLEVEL_STATE_TILED_BOTTOM: - is_tiled = true; + flags->is_tiled = true; break; case XDG_TOPLEVEL_STATE_MAXIMIZED: - is_maximized = true; + flags->is_maximized = true; break; case XDG_TOPLEVEL_STATE_SUSPENDED: - is_suspended = true; + flags->is_suspended = true; break; } } +} +static void apply_toplevel_config(struct vo_wayland_state *wl) +{ + struct mp_vo_opts *opts = wl->opts; + struct mp_rect old_geometry = wl->geometry; + struct vo_wayland_toplevel_pending_state *pending = &wl->pending_state; + struct vo_wayland_toplevel_pending_flags *flags = &pending->flags; + + wl->bounded_width = pending->bounded_width; + wl->bounded_height = pending->bounded_height; + + int32_t width = pending->width; + int32_t height = pending->height; + bool is_maximized = flags->is_maximized; + bool is_fullscreen = flags->is_fullscreen; + bool is_activated = flags->is_activated; + bool is_resizing = flags->is_resizing; + bool is_suspended = flags->is_suspended; + bool is_tiled = flags->is_tiled; + + if (is_activated) { + /* + * If we get an ACTIVATED state, we know it cannot be + * minimized, but it may not have been minimized + * previously, so we can't detect the exact state. + */ + opts->window_minimized = false; + m_config_cache_write_opt(wl->opts_cache, + &opts->window_minimized); + } /* Only update the toplevel state values if either mpv already has * configured its initial geometry or if the compositor gives us some * initial state to use. */ @@ -1934,8 +1961,6 @@ static void handle_toplevel_config(void *data, struct xdg_toplevel *toplevel, mp_rect_w(old_geometry), mp_rect_h(old_geometry), mp_rect_w(wl->geometry), mp_rect_h(wl->geometry)); wl->pending_vo_events |= VO_EVENT_RESIZE; - } else if (wl->resizing) { - wl->pending_vo_events |= VO_EVENT_EXPOSE; } wl->override_surface_local = width == 0 || height == 0 || wl->reconfigured; @@ -1953,8 +1978,8 @@ static void handle_configure_bounds(void *data, struct xdg_toplevel *xdg_topleve int32_t width, int32_t height) { struct vo_wayland_state *wl = data; - wl->bounded_width = handle_round(wl->scaling, width); - wl->bounded_height = handle_round(wl->scaling, height); + wl->pending_state.bounded_width = handle_round(wl->scaling, width); + wl->pending_state.bounded_height = handle_round(wl->scaling, height); } static void handle_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, @@ -2488,7 +2513,22 @@ static void configure_decorations(void *data, uint32_t mode) { struct vo_wayland_state *wl = data; + struct vo_wayland_toplevel_pending_state *pending = &wl->pending_state; + + pending->new_decoration_mode = mode; +} + +static void apply_decorations(struct vo_wayland_state *wl) +{ struct mp_vo_opts *opts = wl->opts; + struct vo_wayland_toplevel_pending_state *pending = &wl->pending_state; + uint32_t mode = pending->new_decoration_mode; + + if (mode == 0) { + return; + } + + pending->new_decoration_mode = 0; if (wl->requested_decoration && mode != wl->requested_decoration) { MP_DBG(wl, diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index f3f40fb013aaf..2474e374b6a85 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -35,6 +35,24 @@ struct drm_format { uint64_t modifier; }; +struct vo_wayland_toplevel_pending_flags { + bool is_maximized; + bool is_fullscreen; + bool is_activated; + bool is_resizing; + bool is_suspended; + bool is_tiled; +}; + +struct vo_wayland_toplevel_pending_state { + int32_t bounded_width; + int32_t bounded_height; + int32_t width; + int32_t height; + struct vo_wayland_toplevel_pending_flags flags; + uint32_t new_decoration_mode; +}; + struct vo_wayland_state { struct m_config_cache *opts_cache; struct mp_log *log; @@ -69,6 +87,7 @@ struct vo_wayland_state { bool override_surface_local; /* State */ + struct vo_wayland_toplevel_pending_state pending_state; bool activated; bool focused; bool frame_wait;