diff --git a/src/xdg.rs b/src/xdg.rs index 2060bfe..26fea08 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -184,6 +184,12 @@ impl ClientXdgToplevel { } } +enum ToplevelState { + Normal, + Maximixed, + Fullscreen, +} + impl XdgToplevelHandler for ClientXdgToplevel { fn handle_set_title(&mut self, slf: &Rc, title: &str) { slf.send_set_title(title); @@ -213,9 +219,51 @@ impl XdgToplevelHandler for ClientXdgToplevel { slf.send_unset_fullscreen(); } - fn handle_configure(&mut self, slf: &Rc, width: i32, height: i32, _states: &[u8]) { - let states = (1u64 << 32 | XdgToplevelState::TILED_TOP.0 as u64).to_ne_bytes(); + fn handle_configure(&mut self, slf: &Rc, width: i32, height: i32, states: &[u8]) { + log::debug!("configure {slf:?}: {width}x{height}, {states:?}"); + let (_prefix, states, _suffix) = unsafe { states.align_to::() }; + let mut top_state = ToplevelState::Normal; + let mut resizing = false; + let mut activated = false; + let mut suspended = false; + for state in states { + if *state == XdgToplevelState::RESIZING.0 { + resizing = true; + } else if *state == XdgToplevelState::ACTIVATED.0 { + activated = true; + } else if *state == XdgToplevelState::SUSPENDED.0 { + suspended = true; + } else if *state == XdgToplevelState::MAXIMIZED.0 { + top_state = ToplevelState::Maximixed; + } else if *state == XdgToplevelState::FULLSCREEN.0 { + top_state = ToplevelState::Fullscreen; + } + } + + let mut outer_state = Vec::with_capacity(8); + if resizing { + outer_state.push(XdgToplevelState::RESIZING); + } + if activated { + outer_state.push(XdgToplevelState::ACTIVATED); + } + if suspended { + outer_state.push(XdgToplevelState::SUSPENDED); + } + match top_state { + ToplevelState::Normal => { + // Let the client think it's tiled, so that it avoids drawing its own deco/shadows + outer_state.push(XdgToplevelState::TILED_TOP); + outer_state.push(XdgToplevelState::TILED_RIGHT); + outer_state.push(XdgToplevelState::TILED_BOTTOM); + outer_state.push(XdgToplevelState::TILED_LEFT); + } + ToplevelState::Maximixed => outer_state.push(XdgToplevelState::MAXIMIZED), + ToplevelState::Fullscreen => outer_state.push(XdgToplevelState::FULLSCREEN), + }; + let (width, height) = self.deco.transform_configure(width, height); + let (_prefix, states, _suffix) = unsafe { outer_state.align_to::() }; slf.send_configure(width, height, &states[..]); }