atagen

monolith

public
Star0
Watch0
211452a41a25332763d8bb3c43c75da9e7ac1490
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git
crates/layout/src/scratchpad.rsRust92 lines3.1 KB
1
use crate::{Layout, Scratchpad, WindowId, centred, translate};
2
3
impl Layout {
4
    /// Adds a window to a named scratchpad, creating it. Scratchpad windows
5
    /// float and are shown only by summoning.
6
    pub fn scratchpad_add(&mut self, w: WindowId, name: &str) {
7
        let Some(win) = self.windows.get(w) else {
8
            return;
9
        };
10
        if let Some(s) = win.scratchpad {
11
            self.leave_scratchpad(s, w);
12
        }
13
        self.unplace(w);
14
        let s = match self.scratchpads.iter().position(|sp| sp.name == name) {
15
            Some(s) => s,
16
            None => {
17
                self.scratchpads.push(Scratchpad {
18
                    name: name.into(),
19
                    windows: Vec::new(),
20
                    shown: None,
21
                    output: None,
22
                });
23
                self.scratchpads.len() - 1
24
            }
25
        };
26
        self.scratchpads[s].windows.push(w);
27
        let area = self.windows[w].output.map(|o| self.outputs[o].area);
28
        let win = &mut self.windows[w];
29
        win.scratchpad = Some(s);
30
        win.floating = true;
31
        if win.float_rect.is_none() {
32
            win.float_rect = area.map(|a| centred(a, 0.6));
33
        }
34
    }
35
36
    /// Cycles a scratchpad through off, each window, and off again, on the
37
    /// active output.
38
    pub fn summon(&mut self, name: &str) -> Option<WindowId> {
39
        let s = self.scratchpads.iter().position(|sp| sp.name == name)?;
40
        let o = self.active?;
41
        let sp = &mut self.scratchpads[s];
42
        let next = match sp.shown {
43
            None => 0,
44
            Some(i) => i + 1,
45
        };
46
        if next >= sp.windows.len() {
47
            sp.shown = None;
48
            return None;
49
        }
50
        let from = sp.output.map(|f| self.outputs[f].area);
51
        sp.shown = Some(next);
52
        sp.output = Some(o);
53
        let w = sp.windows[next];
54
        self.last_scratchpad = Some(s);
55
        let area = self.outputs[o].area;
56
        let win = &mut self.windows[w];
57
        if win.output != Some(o) {
58
            win.float_rect = match (from, win.float_rect) {
59
                (Some(from), Some(r)) => Some(translate(r, from, area)),
60
                _ => Some(centred(area, 0.6)),
61
            };
62
            win.output = Some(o);
63
        }
64
        self.focus(w);
65
        Some(w)
66
    }
67
68
    /// Hides a scratchpad, by default the last one summoned.
69
    pub fn dismiss(&mut self, name: Option<&str>) {
70
        let s = match name {
71
            Some(name) => self.scratchpads.iter().position(|sp| sp.name == name),
72
            None => self.last_scratchpad,
73
        };
74
        if let Some(sp) = s.and_then(|s| self.scratchpads.get_mut(s)) {
75
            sp.shown = None;
76
        }
77
    }
78
79
    pub(crate) fn leave_scratchpad(&mut self, s: usize, w: WindowId) {
80
        let sp = &mut self.scratchpads[s];
81
        let Some(i) = sp.windows.iter().position(|&x| x == w) else {
82
            return;
83
        };
84
        sp.windows.remove(i);
85
        sp.shown = match sp.shown {
86
            Some(j) if j == i => None,
87
            Some(j) if j > i => Some(j - 1),
88
            other => other,
89
        };
90
        self.windows[w].scratchpad = None;
91
    }
92
}