diff options
author | tcmal <me@aria.rip> | 2024-08-30 16:26:34 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-30 16:49:19 +0100 |
commit | a568b4a79d1ccabfdff0a5a8ecbb908e96f17cf5 (patch) | |
tree | aa646de48cb2ef040b7d9e7164f59c827f6961a3 /src/clients/mod.rs | |
parent | b5601a6eb3a8d0603bb837a847701d3d49f984c3 (diff) |
Add binds for moving clients up/down stack
Diffstat (limited to 'src/clients/mod.rs')
-rw-r--r-- | src/clients/mod.rs | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/src/clients/mod.rs b/src/clients/mod.rs index 4ebd634..70ffb00 100644 --- a/src/clients/mod.rs +++ b/src/clients/mod.rs @@ -1,6 +1,6 @@ //! Tracking and managing windows. -use std::cmp::Ordering; +use std::{cmp::Ordering, mem}; use crate::{ buttons, @@ -323,6 +323,72 @@ impl ClientState { self.refocus(conn, new_idx); } + /// Shift the focused client up (increase = false) or down (increase = true) the client list + pub fn shift_focused_client(&mut self, conn: &Connection<'_>, increase: bool) { + // We always want to place it after/before the next/previous one on the focused tag + let Some(target) = self.focused_client else { + return; + }; + let mon_idx = self.client_mon_idx(target); + let tag_focus = self.mons[mon_idx].focused_tag; + let look_through = self + .clients + .iter() + .enumerate() + .filter(|(_, c)| tag_focus.matches(c.tag)) + .filter(|(_, c)| c.tiled()) + .map(|(i, _)| i); + + let new_idx = if increase { + look_through + .cycle() + .skip_while(|i| *i != target) + .nth(1) + .unwrap_or(0) + } else { + look_through + .rev() + .cycle() + .skip_while(|i| *i != target) + .nth(1) + .unwrap_or(0) + }; + + // Need to do split it so that the borrow checker is happy + match new_idx.cmp(&target) { + Ordering::Less => { + let (before, after) = self.clients.split_at_mut(target); + mem::swap(&mut before[new_idx], &mut after[0]); + } + Ordering::Greater => { + let (before, after) = self.clients.split_at_mut(new_idx); + mem::swap(&mut before[target], &mut after[0]); + } + Ordering::Equal => return, + } + + self.focused_client = Some(new_idx); // Doesn't need any actual X operations done + self.rearrange_mon(conn, mon_idx); + } + + /// Shift the focused client to the top of the stack + pub fn shift_focused_to_top(&mut self, conn: &Connection<'_>) { + if self.clients.len() == 1 { + return; // Already at the top + } + + let Some(target) = self.focused_client else { + return; + }; + + // Need to do split it so that the borrow checker is happy + let (before, after) = self.clients.split_at_mut(1); + mem::swap(&mut before[0], &mut after[target - 1]); + + self.focused_client = Some(0); // Doesn't need any actual X operations done + self.rearrange_mon(conn, self.focused_mon_idx()); + } + /// Toggle whether the client with the given position is floating pub fn toggle_floating(&mut self, conn: &Connection<'_>, pos: ClientIdx) { let c = &mut self.clients[pos]; |