diff --git a/src/wayland/shell/xdg/mod.rs b/src/wayland/shell/xdg/mod.rs index f135606..b76a481 100644 --- a/src/wayland/shell/xdg/mod.rs +++ b/src/wayland/shell/xdg/mod.rs @@ -125,6 +125,9 @@ pub const ZXDG_TOPLEVEL_ROLE: &str = "zxdg_toplevel"; /// [xdg_popup]: self::XDG_POPUP_ROLE pub const ZXDG_POPUP_ROLE: &str = "zxdg_popup"; +/// Constant for toplevel state version checking +const XDG_TOPLEVEL_STATE_TILED_SINCE: u32 = 2; + macro_rules! xdg_role { ($configure:ty, $(#[$attr:meta])* $element:ident {$($(#[$field_attr:meta])* $vis:vis$field:ident:$type:ty),*}, @@ -615,6 +618,39 @@ impl ToplevelStateSet { true } } + + /// Filter the states according to the provided version + /// of the [`XdgToplevel`] + pub(crate) fn into_filtered_states(self, version: u32) -> Vec { + // If the client version supports the tiled states + // we can directly return the states which will save + // us from allocating another vector + if version >= XDG_TOPLEVEL_STATE_TILED_SINCE { + return self.states; + } + + let is_tiled = |state: &xdg_toplevel::State| { + matches!( + state, + xdg_toplevel::State::TiledTop + | xdg_toplevel::State::TiledBottom + | xdg_toplevel::State::TiledLeft + | xdg_toplevel::State::TiledRight + ) + }; + + let contains_tiled = self.states.iter().any(|state| is_tiled(state)); + + // If the states do not contain a tiled state + // we can directly return the states which will save + // us from allocating another vector + if !contains_tiled { + return self.states; + } + + // We need to filter out the unsupported states + self.states.into_iter().filter(|state| !is_tiled(state)).collect() + } } impl Default for ToplevelStateSet { diff --git a/src/wayland/shell/xdg/xdg_handlers.rs b/src/wayland/shell/xdg/xdg_handlers.rs index c5aa5b8..bef65f0 100644 --- a/src/wayland/shell/xdg/xdg_handlers.rs +++ b/src/wayland/shell/xdg/xdg_handlers.rs @@ -519,7 +519,10 @@ pub fn send_toplevel_configure(resource: &xdg_toplevel::XdgToplevel, configure: let (width, height) = configure.state.size.unwrap_or_default().into(); // convert the Vec (which is really a Vec) into Vec let states = { - let mut states: Vec = configure.state.states.into(); + let mut states: Vec = configure + .state + .states + .into_filtered_states(resource.as_ref().version()); let ptr = states.as_mut_ptr(); let len = states.len(); let cap = states.capacity(); diff --git a/src/wayland/shell/xdg/zxdgv6_handlers.rs b/src/wayland/shell/xdg/zxdgv6_handlers.rs index 9ae7a70..b9ca8f2 100644 --- a/src/wayland/shell/xdg/zxdgv6_handlers.rs +++ b/src/wayland/shell/xdg/zxdgv6_handlers.rs @@ -522,7 +522,10 @@ pub fn send_toplevel_configure(resource: &zxdg_toplevel_v6::ZxdgToplevelV6, conf let (width, height) = configure.state.size.unwrap_or_default().into(); // convert the Vec (which is really a Vec) into Vec let states = { - let mut states: Vec = configure.state.states.into(); + let mut states: Vec = configure + .state + .states + .into_filtered_states(resource.as_ref().version()); let ptr = states.as_mut_ptr(); let len = states.len(); let cap = states.capacity();