From 5d2a23a5d618725b75ba77d7185601e5439801c5 Mon Sep 17 00:00:00 2001 From: tcmal Date: Mon, 15 Jul 2024 15:30:06 +0100 Subject: support fullscreen mode --- src/clients/client.rs | 60 ++++++++++++++++++++++++++++++++++++++++--------- src/clients/mod.rs | 23 +++++++++++++++++-- src/clients/monitors.rs | 2 +- src/config.rs | 3 ++- src/helpers.rs | 7 ++++++ todos.org | 2 -- 6 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/clients/client.rs b/src/clients/client.rs index 6845e4e..84f787a 100644 --- a/src/clients/client.rs +++ b/src/clients/client.rs @@ -8,7 +8,7 @@ use xcb::{ use crate::{config::BORDER_WIDTH, conn_info::Connection}; -use super::hints; +use super::{hints, MonitorGeometry}; /// Information about a single client / window #[derive(Debug)] @@ -26,7 +26,20 @@ pub struct Client { urgent: bool, never_focus: bool, - floating: bool, + layout_mode: LayoutMode, +} + +/// How this window's geometry is determined, +#[derive(Debug)] +pub enum LayoutMode { + /// By the tiling algorithm + Tiled, + + /// By the user + Floating, + + /// By the monitor its on + Fullscreen, } impl Client { @@ -41,7 +54,7 @@ impl Client { mapped: false, urgent: false, never_focus: false, - floating: false, + layout_mode: LayoutMode::Tiled, } } @@ -107,20 +120,45 @@ impl Client { }); } - /// Whether the client is floating - outside of current tiling rules and displaying over any tiled windows - pub const fn floating(&self) -> bool { - self.floating + /// Whether the client is tiled + pub const fn tiled(&self) -> bool { + matches!(self.layout_mode, LayoutMode::Tiled) + } + + /// Set the window as tiled + pub fn set_tiled(&mut self) { + self.layout_mode = LayoutMode::Tiled; + } + + /// Set the window as floating + pub fn set_floating(&mut self, conn: &Connection<'_>) { + if !matches!(self.layout_mode, LayoutMode::Floating) { + conn.send_request(&ConfigureWindow { + window: self.window, + value_list: &[ConfigWindow::StackMode(StackMode::Above)], + }); + } + self.layout_mode = LayoutMode::Floating; } - /// Set the floating status. - pub fn set_floating(&mut self, conn: &Connection<'_>, floating: bool) { - if floating && floating != self.floating { + /// Set the window as fullscreen + pub fn set_fullscreen(&mut self, conn: &Connection<'_>, mon_geom: &MonitorGeometry) { + if !matches!(self.layout_mode, LayoutMode::Fullscreen) { conn.send_request(&ConfigureWindow { window: self.window, value_list: &[ConfigWindow::StackMode(StackMode::Above)], }); + + self.set_geom( + conn, + mon_geom.x_org, + mon_geom.y_org, + mon_geom.width, + mon_geom.height, + self.border_width, + ); } - self.floating = floating; + self.layout_mode = LayoutMode::Fullscreen; } /// Ensure this client is currently mapped / visible @@ -180,7 +218,7 @@ impl Client { pub fn update_window_type(&mut self, conn: &Connection<'_>) { // TODO: Fullscreen from net_wm_state if hints::is_dialog(conn, self.window) { - self.set_floating(conn, true); + self.set_floating(conn); } } diff --git a/src/clients/mod.rs b/src/clients/mod.rs index 8efa5b1..c370e04 100644 --- a/src/clients/mod.rs +++ b/src/clients/mod.rs @@ -210,7 +210,9 @@ impl ClientState { BORDER_WIDTH, ); c.set_border(conn, conn.colours.border_normal()); - c.set_floating(conn, floating); + if floating { + c.set_floating(conn); + } c.update_window_type(conn); c.ensure_mapped(conn); @@ -327,7 +329,24 @@ impl ClientState { /// Toggle whether the client with the given position is floating pub fn toggle_floating(&mut self, conn: &Connection<'_>, (mon, pos): (usize, usize)) { let c = &mut self.mons[mon].clients[pos]; - c.set_floating(conn, !c.floating()); + if c.tiled() { + c.set_floating(conn); + } else { + c.set_tiled(); + } + + self.rearrange_monitor(conn, mon); + } + + /// Toggle whether the client with the given position is fullscreen + pub fn toggle_fullscreen(&mut self, conn: &Connection<'_>, (mon, pos): (usize, usize)) { + let mon_info = &mut self.mons[mon]; + let c = &mut mon_info.clients[pos]; + if c.tiled() { + c.set_fullscreen(conn, &mon_info.screen_info); + } else { + c.set_tiled(); + } self.rearrange_monitor(conn, mon); } diff --git a/src/clients/monitors.rs b/src/clients/monitors.rs index 6ca6fdf..6790632 100644 --- a/src/clients/monitors.rs +++ b/src/clients/monitors.rs @@ -16,7 +16,7 @@ impl MonitorInfo { /// Iterate over all tiled clients, returning a mutable reference to each. pub fn clients_tiled_mut(&mut self) -> impl Iterator { // TODO: tag filtering - self.clients.iter_mut().filter(|c| !c.floating()) + self.clients.iter_mut().filter(|c| c.tiled()) } } diff --git a/src/config.rs b/src/config.rs index aac47ae..9cbfc40 100644 --- a/src/config.rs +++ b/src/config.rs @@ -7,7 +7,7 @@ use xkeysym::Keysym; use crate::{ bind, conn_info::Colour, - helpers::{focus_next, focus_prev, spawn, toggle_floating}, + helpers::{focus_next, focus_prev, spawn, toggle_floating, toggle_fullscreen}, keys::{Keybind, Keybinds}, }; @@ -33,6 +33,7 @@ pub const KEYBINDS: Keybinds = Keybinds(&[ bind!(MAIN_MODIFIER , j -> &focus_next), bind!(MAIN_MODIFIER , k -> &focus_prev), bind!(MAIN_MODIFIER.union(ModMask::SHIFT) , space -> &toggle_floating), + bind!(MAIN_MODIFIER.union(ModMask::SHIFT) , f -> &toggle_fullscreen), // { MODKEY, XK_j, focusstack, {.i = +1 } }, // { MODKEY, XK_k, focusstack, {.i = -1 } }, // { MODKEY, XK_i, incnmaster, {.i = +1 } }, diff --git a/src/helpers.rs b/src/helpers.rs index b7488dd..24c8cf2 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -47,3 +47,10 @@ pub fn toggle_floating(wm: &mut WM<'_>) { wm.clients.toggle_floating(&wm.conn, pos); } } + +/// Toggle fullscreen status for the currently focused window +pub fn toggle_fullscreen(wm: &mut WM<'_>) { + if let Some(pos) = wm.clients.focused_pos() { + wm.clients.toggle_fullscreen(&wm.conn, pos); + } +} diff --git a/todos.org b/todos.org index 3b4a9d8..7bb97ab 100644 --- a/todos.org +++ b/todos.org @@ -1,5 +1,3 @@ -* Support fullscreen - * Set fullscreen based on hint * Fix focus changing bug -- cgit v1.2.3