summaryrefslogtreecommitdiff
path: root/src/clients/mod.rs
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-30 16:26:34 +0100
committertcmal <me@aria.rip>2024-08-30 16:49:19 +0100
commita568b4a79d1ccabfdff0a5a8ecbb908e96f17cf5 (patch)
treeaa646de48cb2ef040b7d9e7164f59c827f6961a3 /src/clients/mod.rs
parentb5601a6eb3a8d0603bb837a847701d3d49f984c3 (diff)
Add binds for moving clients up/down stack
Diffstat (limited to 'src/clients/mod.rs')
-rw-r--r--src/clients/mod.rs68
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];