feat: hide decorations on tiled windows
This commit is contained in:
1 parent
9f550e275c
commit
d32f20dbbf
4 files changed
+73
-14
No files matched your search
@@ -273,21 +273,32 @@ fn check_grab(
|
|||||||
|
|
||||||
impl XdgDecorationHandler for Ferese {
|
impl XdgDecorationHandler for Ferese {
|
||||||
fn new_decoration(&mut self, toplevel: ToplevelSurface) {
|
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) {
|
fn request_mode(&mut self, toplevel: ToplevelSurface, _mode: Mode) {
|
||||||
// Phase 1 negotiates decorations but does not yet draw a server frame.
|
let mode = self.decoration_mode_for(&toplevel);
|
||||||
// Honor CSD and safely fall back to CSD for premature SSD requests.
|
|
||||||
let mode = match mode {
|
|
||||||
Mode::ClientSide | Mode::ServerSide => Mode::ClientSide,
|
|
||||||
_ => Mode::ClientSide,
|
|
||||||
};
|
|
||||||
set_decoration_mode(&toplevel, mode);
|
set_decoration_mode(&toplevel, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset_mode(&mut self, toplevel: ToplevelSurface) {
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(())
|
FilterResult::Intercept(())
|
||||||
} else if !modifiers.shift
|
} else if !modifiers.shift
|
||||||
&& matches!(symbol, keysyms::KEY_f | keysyms::KEY_F)
|
&& matches!(symbol, keysyms::KEY_f | keysyms::KEY_F)
|
||||||
|
|||||||
+39
-5
@@ -23,7 +23,10 @@ use smithay::{
|
|||||||
output::Output,
|
output::Output,
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::{EventLoop, Interest, LoopSignal, Mode, PostAction, generic::Generic},
|
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::{
|
wayland_server::{
|
||||||
Display, DisplayHandle,
|
Display, DisplayHandle,
|
||||||
backend::{ClientData, ClientId, DisconnectReason},
|
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<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let now = self.start_time.elapsed();
|
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 committed_size = client_size(&window);
|
||||||
let geometry = self
|
let geometry = self
|
||||||
.window_geometry
|
.window_geometry
|
||||||
@@ -534,11 +543,21 @@ impl Ferese {
|
|||||||
state.size = Some((size.width, size.height).into());
|
state.size = Some((size.width, size.height).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_fullscreen {
|
let fullscreen_changed = if is_fullscreen {
|
||||||
state.states.set(xdg_toplevel::State::Fullscreen)
|
state.states.set(xdg_toplevel::State::Fullscreen)
|
||||||
} else {
|
} else {
|
||||||
state.states.unset(xdg_toplevel::State::Fullscreen)
|
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 {
|
if requested_size.is_some() || state_changed {
|
||||||
@@ -763,6 +782,21 @@ impl Ferese {
|
|||||||
self.relayout();
|
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) {
|
pub fn set_window_fullscreen(&mut self, window: WindowId, enabled: bool) {
|
||||||
match self.workspaces.set_fullscreen(window, enabled) {
|
match self.workspaces.set_fullscreen(window, enabled) {
|
||||||
Ok(true) => self.relayout(),
|
Ok(true) => self.relayout(),
|
||||||
|
|||||||
@@ -630,6 +630,11 @@ decorations, Ferese MUST provide usable move, resize, and close interactions.
|
|||||||
Shadows, masks, and focus borders are compositor effects and may apply in either
|
Shadows, masks, and focus borders are compositor effects and may apply in either
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
|
Tiled and fullscreen windows default to borderless server-side decoration so
|
||||||
|
application title bars do not consume layout space. Floating windows and
|
||||||
|
dialogs default to client-side decoration until Ferese provides a complete
|
||||||
|
compositor-drawn floating frame.
|
||||||
|
|
||||||
### 8.3 XWayland
|
### 8.3 XWayland
|
||||||
|
|
||||||
The desktop tier SHOULD use `xwayland-satellite`, launched on demand, so X11
|
The desktop tier SHOULD use `xwayland-satellite`, launched on demand, so X11
|
||||||
|
|||||||
Reference in new issue
Block a user