summaryrefslogtreecommitdiff
path: root/src/clients
diff options
context:
space:
mode:
Diffstat (limited to 'src/clients')
-rw-r--r--src/clients/client.rs65
-rw-r--r--src/clients/mod.rs19
2 files changed, 61 insertions, 23 deletions
diff --git a/src/clients/client.rs b/src/clients/client.rs
index c9fa645..43d4c54 100644
--- a/src/clients/client.rs
+++ b/src/clients/client.rs
@@ -1,7 +1,8 @@
use xcb::{
x::{
- ChangeProperty, ChangeWindowAttributes, ConfigWindow, ConfigureNotifyEvent,
- ConfigureWindow, Cw, EventMask, MapWindow, SendEvent, SendEventDest, StackMode, Window,
+ self, ChangeProperty, ChangeWindowAttributes, ConfigWindow, ConfigureNotifyEvent,
+ ConfigureWindow, Cw, EventMask, MapWindow, PropMode, SendEvent, SendEventDest, StackMode,
+ Window,
},
VoidCookieChecked, Xid,
};
@@ -125,25 +126,40 @@ impl Client {
matches!(self.layout_mode, LayoutMode::Tiled)
}
+ /// Whether the client is fullscreen
+ pub const fn fullscreen(&self) -> bool {
+ matches!(self.layout_mode, LayoutMode::Fullscreen)
+ }
+
/// Set the window as tiled
- pub fn set_tiled(&mut self) {
+ pub fn set_tiled(&mut self, conn: &Connection<'_>) {
+ let dirty = !matches!(self.layout_mode, LayoutMode::Tiled);
self.layout_mode = LayoutMode::Tiled;
+ if dirty {
+ self.apply_net_wm_state(conn)
+ }
}
/// Set the window as floating
pub fn set_floating(&mut self, conn: &Connection<'_>) {
- if !matches!(self.layout_mode, LayoutMode::Floating) {
+ let dirty = !matches!(self.layout_mode, LayoutMode::Floating);
+ self.layout_mode = LayoutMode::Floating;
+
+ if dirty {
conn.send_request(&ConfigureWindow {
window: self.window,
value_list: &[ConfigWindow::StackMode(StackMode::Above)],
});
+ self.apply_net_wm_state(conn);
}
- self.layout_mode = LayoutMode::Floating;
}
/// Set the window as fullscreen
pub fn set_fullscreen(&mut self, conn: &Connection<'_>, mon_geom: &MonitorGeometry) {
- if !matches!(self.layout_mode, LayoutMode::Fullscreen) {
+ let dirty = !matches!(self.layout_mode, LayoutMode::Fullscreen);
+ self.layout_mode = LayoutMode::Fullscreen;
+
+ if dirty {
conn.send_request(&ConfigureWindow {
window: self.window,
value_list: &[ConfigWindow::StackMode(StackMode::Above)],
@@ -157,8 +173,22 @@ impl Client {
mon_geom.height,
self.border_width,
);
+ self.apply_net_wm_state(conn);
}
- self.layout_mode = LayoutMode::Fullscreen;
+ }
+
+ fn apply_net_wm_state(&self, conn: &Connection<'_>) {
+ conn.send_request(&ChangeProperty {
+ mode: PropMode::Replace,
+ window: self.window,
+ property: conn.atoms.net_wm_state,
+ r#type: x::ATOM_ATOM,
+ data: &[match self.layout_mode {
+ LayoutMode::Tiled => 0_u32,
+ LayoutMode::Floating => 0_u32,
+ LayoutMode::Fullscreen => conn.atoms.net_wm_fullscreen.resource_id(),
+ }],
+ });
}
/// Ensure this client is currently mapped / visible
@@ -188,8 +218,8 @@ impl Client {
})
}
- /// Sync the non-geometry related properties with EWMH hints
- pub fn sync_properties(&mut self, conn: &Connection<'_>, focused: bool) {
+ /// Sync the non-geometry related hints with EWMH hints
+ pub fn sync_hints(&mut self, conn: &Connection<'_>, focused: bool) {
let Some(mut hints) = hints::Ewm::get(conn, self.window) else {
return;
};
@@ -204,6 +234,15 @@ impl Client {
self.never_focus = hints.input().is_some_and(|i| !i);
}
+ /// Apply any geometry-related EWM hints on the window
+ pub fn apply_geometry_hints(&mut self, conn: &Connection<'_>, mon_geom: &MonitorGeometry) {
+ if hints::is_fullscreen(conn, self.window) {
+ self.set_fullscreen(conn, mon_geom);
+ } else if hints::is_dialog(conn, self.window) {
+ self.set_floating(conn);
+ }
+ }
+
/// Set the given window as withdrawn / not withdrawn.
pub fn set_withdrawn(&self, conn: &Connection<'_>, withdrawn: bool) -> VoidCookieChecked {
conn.send_request_checked(&ChangeProperty {
@@ -215,14 +254,6 @@ impl Client {
})
}
- pub fn update_window_type(&mut self, conn: &Connection<'_>, mon_geom: &MonitorGeometry) {
- if hints::is_fullscreen(conn, self.window) {
- self.set_fullscreen(conn, mon_geom);
- } else if hints::is_dialog(conn, self.window) {
- self.set_floating(conn);
- }
- }
-
pub fn set_urgent(&mut self, urgent: bool) {
self.urgent = urgent;
}
diff --git a/src/clients/mod.rs b/src/clients/mod.rs
index 053b4de..597a336 100644
--- a/src/clients/mod.rs
+++ b/src/clients/mod.rs
@@ -210,13 +210,15 @@ impl ClientState {
BORDER_WIDTH,
);
c.set_border(conn, conn.colours.border_normal());
+
if floating {
c.set_floating(conn);
}
- c.update_window_type(conn, &mon_geom);
- c.ensure_mapped(conn);
- c.sync_properties(conn, true);
+ c.sync_hints(conn, true);
+ c.apply_geometry_hints(conn, &mon_geom);
+
+ c.ensure_mapped(conn);
c.set_event_mask(
conn,
@@ -266,7 +268,7 @@ impl ClientState {
self.unfocus(conn);
if let Some(new) = self.set_focused(mon, i) {
new.set_border(conn, conn.colours.border_focused());
- new.sync_properties(conn, true);
+ new.sync_hints(conn, true);
if !new.never_focus() {
conn.send_request(&SetInputFocus {
revert_to: InputFocus::PointerRoot,
@@ -332,7 +334,7 @@ impl ClientState {
if c.tiled() {
c.set_floating(conn);
} else {
- c.set_tiled();
+ c.set_tiled(conn);
}
self.rearrange_monitor(conn, mon);
@@ -345,7 +347,7 @@ impl ClientState {
if c.tiled() {
c.set_fullscreen(conn, &mon_info.screen_info);
} else {
- c.set_tiled();
+ c.set_tiled(conn);
}
self.rearrange_monitor(conn, mon);
@@ -482,6 +484,11 @@ impl ClientState {
const fn focused_mon(&self) -> usize {
self.focused.0
}
+
+ /// Get the geometry of the monitor with the given index
+ pub fn mon_geometry(&self, mon: usize) -> MonitorGeometry {
+ self.mons[mon].screen_info
+ }
}
impl Default for ClientState {