feat: hide decorations on tiled windows

This commit is contained in:
Samuel Onoja committed 2026-09-25 01:20:16 +01:00
1 parent 9f550e275c
commit d32f20dbbf
4 files changed
+73 -14

No files matched your search

+20 -9
View File
@@ -273,21 +273,32 @@ fn check_grab(
impl XdgDecorationHandler for Ferese {
fn new_decoration(&mut self, toplevel: ToplevelSurface) {
set_decoration_mode(&toplevel, Mode::ClientSide);
let mode = self.decoration_mode_for(&toplevel);
set_decoration_mode(&toplevel, mode);
}
fn request_mode(&mut self, toplevel: ToplevelSurface, mode: Mode) {
// Phase 1 negotiates decorations but does not yet draw a server frame.
// Honor CSD and safely fall back to CSD for premature SSD requests.
let mode = match mode {
Mode::ClientSide | Mode::ServerSide => Mode::ClientSide,
_ => Mode::ClientSide,
};
fn request_mode(&mut self, toplevel: ToplevelSurface, _mode: Mode) {
let mode = self.decoration_mode_for(&toplevel);
set_decoration_mode(&toplevel, mode);
}
fn unset_mode(&mut self, toplevel: ToplevelSurface) {
set_decoration_mode(&toplevel, Mode::ClientSide);
let mode = self.decoration_mode_for(&toplevel);
set_decoration_mode(&toplevel, mode);
}
}
impl Ferese {
fn decoration_mode_for(&self, toplevel: &ToplevelSurface) -> Mode {
self.space
.elements()
.find(|window| {
window
.toplevel()
.is_some_and(|candidate| candidate.wl_surface() == toplevel.wl_surface())
})
.filter(|window| self.is_floating_window(window))
.map_or(Mode::ServerSide, |_| Mode::ClientSide)
}
}
+9
View File
@@ -120,6 +120,15 @@ impl Ferese {
}
}
FilterResult::Intercept(())
} else if !modifiers.shift
&& matches!(symbol, keysyms::KEY_q | keysyms::KEY_Q)
{
if state == KeyState::Pressed {
data.intercepted_keys.insert(keycode);
data.close_focused_window();
}
FilterResult::Intercept(())
} else if !modifiers.shift
&& matches!(symbol, keysyms::KEY_f | keysyms::KEY_F)
+39 -5
View File
@@ -23,7 +23,10 @@ use smithay::{
output::Output,
reexports::{
calloop::{EventLoop, Interest, LoopSignal, Mode, PostAction, generic::Generic},
wayland_protocols::xdg::shell::server::xdg_toplevel,
wayland_protocols::xdg::{
decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode as DecorationMode,
shell::server::xdg_toplevel,
},
wayland_server::{
Display, DisplayHandle,
backend::{ClientData, ClientId, DisconnectReason},
@@ -511,13 +514,19 @@ impl Ferese {
}
};
Some((window.clone(), *id, rect, fullscreen == Some(*id)))
let is_fullscreen = fullscreen == Some(*id);
let is_floating = matches!(
self.workspaces.placement(*id),
Some(WindowPlacement::Floating { .. })
);
Some((window.clone(), *id, rect, is_fullscreen, is_floating))
})
.collect::<Vec<_>>();
let now = self.start_time.elapsed();
for (window, id, rect, is_fullscreen) in placements {
for (window, id, rect, is_fullscreen, is_floating) in placements {
let committed_size = client_size(&window);
let geometry = self
.window_geometry
@@ -534,11 +543,21 @@ impl Ferese {
state.size = Some((size.width, size.height).into());
}
if is_fullscreen {
let fullscreen_changed = if is_fullscreen {
state.states.set(xdg_toplevel::State::Fullscreen)
} else {
state.states.unset(xdg_toplevel::State::Fullscreen)
}
};
let decoration_mode = if is_floating && !is_fullscreen {
DecorationMode::ClientSide
} else {
DecorationMode::ServerSide
};
let decoration_changed = state.decoration_mode != Some(decoration_mode);
state.decoration_mode = Some(decoration_mode);
fullscreen_changed || decoration_changed
});
if requested_size.is_some() || state_changed {
@@ -763,6 +782,21 @@ impl Ferese {
self.relayout();
}
pub fn close_focused_window(&self) {
let Some(focused) = self.focused_window else {
return;
};
let Some(toplevel) = self
.window_ids
.iter()
.find_map(|(window, id)| (*id == focused).then(|| window.toplevel()).flatten())
else {
return;
};
toplevel.send_close();
}
pub fn set_window_fullscreen(&mut self, window: WindowId, enabled: bool) {
match self.workspaces.set_fullscreen(window, enabled) {
Ok(true) => self.relayout(),