atagen

monolith

public
Star0
Watch0
e01b19ca3e20e402a7bc4e790fe326f738b09ad8
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: crates/layout/src/outputs.rs

4cbf881c67bdatagen2026-10-17 04:56 UTC1
use crate::{Insets, Layout, Output, OutputId, Rect, TagId, Tree, WindowId, translate};
4cbf881c67bdatagen2026-10-17 04:56 UTC2
4cbf881c67bdatagen2026-10-17 04:56 UTC3
#[derive(Clone, Debug)]
4cbf881c67bdatagen2026-10-17 04:56 UTC4
pub(crate) struct Parked {
4cbf881c67bdatagen2026-10-17 04:56 UTC5
    tree: Tree<WindowId>,
4cbf881c67bdatagen2026-10-17 04:56 UTC6
    viewed: Vec<TagId>,
4cbf881c67bdatagen2026-10-17 04:56 UTC7
    floating: Vec<WindowId>,
4cbf881c67bdatagen2026-10-17 04:56 UTC8
}
4cbf881c67bdatagen2026-10-17 04:56 UTC9
4cbf881c67bdatagen2026-10-17 04:56 UTC10
impl Layout {
4cbf881c67bdatagen2026-10-17 04:56 UTC11
    /// Adds an output. One that was unplugged before gets back its tree,
4cbf881c67bdatagen2026-10-17 04:56 UTC12
    /// views and the windows that had to leave it.
4cbf881c67bdatagen2026-10-17 04:56 UTC13
    pub fn add_output(&mut self, name: &str, area: Rect) -> OutputId {
4cbf881c67bdatagen2026-10-17 04:56 UTC14
        let id = self.outputs.insert(Output {
4cbf881c67bdatagen2026-10-17 04:56 UTC15
            name: name.into(),
4cbf881c67bdatagen2026-10-17 04:56 UTC16
            area,
4cbf881c67bdatagen2026-10-17 04:56 UTC17
            reserved: Insets::default(),
4cbf881c67bdatagen2026-10-17 04:56 UTC18
            tree: Tree::default(),
4cbf881c67bdatagen2026-10-17 04:56 UTC19
            viewed: Vec::new(),
4cbf881c67bdatagen2026-10-17 04:56 UTC20
            floating: Vec::new(),
4cbf881c67bdatagen2026-10-17 04:56 UTC21
        });
4cbf881c67bdatagen2026-10-17 04:56 UTC22
        if let Some(parked) = self.parked.remove(name) {
4cbf881c67bdatagen2026-10-17 04:56 UTC23
            self.restore(id, parked);
4cbf881c67bdatagen2026-10-17 04:56 UTC24
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC25
        self.active.get_or_insert(id);
4cbf881c67bdatagen2026-10-17 04:56 UTC26
        let detached: Vec<WindowId> = self
4cbf881c67bdatagen2026-10-17 04:56 UTC27
            .windows
4cbf881c67bdatagen2026-10-17 04:56 UTC28
            .iter()
4cbf881c67bdatagen2026-10-17 04:56 UTC29
            .filter(|(_, w)| w.output.is_none())
4cbf881c67bdatagen2026-10-17 04:56 UTC30
            .map(|(id, _)| id)
4cbf881c67bdatagen2026-10-17 04:56 UTC31
            .collect();
4cbf881c67bdatagen2026-10-17 04:56 UTC32
        for w in detached {
4cbf881c67bdatagen2026-10-17 04:56 UTC33
            self.windows[w].output = Some(id);
4cbf881c67bdatagen2026-10-17 04:56 UTC34
            self.place(w);
4cbf881c67bdatagen2026-10-17 04:56 UTC35
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC36
        id
4cbf881c67bdatagen2026-10-17 04:56 UTC37
    }
4cbf881c67bdatagen2026-10-17 04:56 UTC38
4cbf881c67bdatagen2026-10-17 04:56 UTC39
    fn restore(&mut self, id: OutputId, parked: Parked) {
4cbf881c67bdatagen2026-10-17 04:56 UTC40
        let name = self.outputs[id].name.clone();
4cbf881c67bdatagen2026-10-17 04:56 UTC41
        let ours = |l: &Self, w: WindowId| {
4cbf881c67bdatagen2026-10-17 04:56 UTC42
            l.windows
4cbf881c67bdatagen2026-10-17 04:56 UTC43
                .get(w)
4cbf881c67bdatagen2026-10-17 04:56 UTC44
                .is_some_and(|x| x.evicted_from.as_deref() == Some(&name) && x.scratchpad.is_none())
4cbf881c67bdatagen2026-10-17 04:56 UTC45
        };
4cbf881c67bdatagen2026-10-17 04:56 UTC46
        let mut tree = parked.tree;
4cbf881c67bdatagen2026-10-17 04:56 UTC47
        tree.retain(|w| ours(self, w) && !self.windows[w].floating);
4cbf881c67bdatagen2026-10-17 04:56 UTC48
        let floating: Vec<WindowId> = parked
4cbf881c67bdatagen2026-10-17 04:56 UTC49
            .floating
4cbf881c67bdatagen2026-10-17 04:56 UTC50
            .into_iter()
4cbf881c67bdatagen2026-10-17 04:56 UTC51
            .filter(|&w| ours(self, w) && self.windows[w].floating)
4cbf881c67bdatagen2026-10-17 04:56 UTC52
            .collect();
4cbf881c67bdatagen2026-10-17 04:56 UTC53
        for w in tree
4cbf881c67bdatagen2026-10-17 04:56 UTC54
            .windows()
4cbf881c67bdatagen2026-10-17 04:56 UTC55
            .chain(floating.iter().copied())
4cbf881c67bdatagen2026-10-17 04:56 UTC56
            .collect::<Vec<_>>()
4cbf881c67bdatagen2026-10-17 04:56 UTC57
        {
4cbf881c67bdatagen2026-10-17 04:56 UTC58
            self.unplace(w);
4cbf881c67bdatagen2026-10-17 04:56 UTC59
            let win = &mut self.windows[w];
4cbf881c67bdatagen2026-10-17 04:56 UTC60
            if let (Some(from), Some(rect)) = (win.output, win.float_rect) {
4b73e40af1e3atagen2026-10-19 07:44 UTC61
                win.float_rect = Some(translate(
4b73e40af1e3atagen2026-10-19 07:44 UTC62
                    rect,
4b73e40af1e3atagen2026-10-19 07:44 UTC63
                    self.outputs[from].usable(),
4b73e40af1e3atagen2026-10-19 07:44 UTC64
                    self.outputs[id].usable(),
4b73e40af1e3atagen2026-10-19 07:44 UTC65
                ));
4cbf881c67bdatagen2026-10-17 04:56 UTC66
            }
4cbf881c67bdatagen2026-10-17 04:56 UTC67
            win.output = Some(id);
4cbf881c67bdatagen2026-10-17 04:56 UTC68
            win.evicted_from = None;
4cbf881c67bdatagen2026-10-17 04:56 UTC69
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC70
        let out = &mut self.outputs[id];
4cbf881c67bdatagen2026-10-17 04:56 UTC71
        out.tree = tree;
4cbf881c67bdatagen2026-10-17 04:56 UTC72
        out.floating = floating;
4cbf881c67bdatagen2026-10-17 04:56 UTC73
        out.viewed = parked
4cbf881c67bdatagen2026-10-17 04:56 UTC74
            .viewed
4cbf881c67bdatagen2026-10-17 04:56 UTC75
            .into_iter()
4cbf881c67bdatagen2026-10-17 04:56 UTC76
            .filter(|&t| self.tags.contains_key(t))
4cbf881c67bdatagen2026-10-17 04:56 UTC77
            .collect();
4cbf881c67bdatagen2026-10-17 04:56 UTC78
    }
4cbf881c67bdatagen2026-10-17 04:56 UTC79
4cbf881c67bdatagen2026-10-17 04:56 UTC80
    /// Removes an output. Its windows move to an output viewing their tag,
4cbf881c67bdatagen2026-10-17 04:56 UTC81
    /// or the active one, and remember where they came from.
4cbf881c67bdatagen2026-10-17 04:56 UTC82
    pub fn remove_output(&mut self, o: OutputId) {
4cbf881c67bdatagen2026-10-17 04:56 UTC83
        let Some(out) = self.outputs.remove(o) else {
4cbf881c67bdatagen2026-10-17 04:56 UTC84
            return;
4cbf881c67bdatagen2026-10-17 04:56 UTC85
        };
4b73e40af1e3atagen2026-10-19 07:44 UTC86
        let left_usable = out.usable();
4cbf881c67bdatagen2026-10-17 04:56 UTC87
        self.parked.insert(
4cbf881c67bdatagen2026-10-17 04:56 UTC88
            out.name.clone(),
4cbf881c67bdatagen2026-10-17 04:56 UTC89
            Parked {
4cbf881c67bdatagen2026-10-17 04:56 UTC90
                tree: out.tree,
4cbf881c67bdatagen2026-10-17 04:56 UTC91
                viewed: out.viewed,
4cbf881c67bdatagen2026-10-17 04:56 UTC92
                floating: out.floating,
4cbf881c67bdatagen2026-10-17 04:56 UTC93
            },
4cbf881c67bdatagen2026-10-17 04:56 UTC94
        );
4cbf881c67bdatagen2026-10-17 04:56 UTC95
        if self.active == Some(o) {
4cbf881c67bdatagen2026-10-17 04:56 UTC96
            self.active = self.outputs.keys().next();
4cbf881c67bdatagen2026-10-17 04:56 UTC97
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC98
        for sp in &mut self.scratchpads {
4cbf881c67bdatagen2026-10-17 04:56 UTC99
            if sp.output == Some(o) {
4cbf881c67bdatagen2026-10-17 04:56 UTC100
                sp.output = self.active;
4cbf881c67bdatagen2026-10-17 04:56 UTC101
            }
4cbf881c67bdatagen2026-10-17 04:56 UTC102
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC103
        let leaving: Vec<WindowId> = self
4cbf881c67bdatagen2026-10-17 04:56 UTC104
            .windows
4cbf881c67bdatagen2026-10-17 04:56 UTC105
            .iter()
4cbf881c67bdatagen2026-10-17 04:56 UTC106
            .filter(|(_, w)| w.output == Some(o))
4cbf881c67bdatagen2026-10-17 04:56 UTC107
            .map(|(id, _)| id)
4cbf881c67bdatagen2026-10-17 04:56 UTC108
            .collect();
4cbf881c67bdatagen2026-10-17 04:56 UTC109
        for w in leaving {
4cbf881c67bdatagen2026-10-17 04:56 UTC110
            let tag = self.windows[w].tag;
4cbf881c67bdatagen2026-10-17 04:56 UTC111
            let target = self
4cbf881c67bdatagen2026-10-17 04:56 UTC112
                .outputs
4cbf881c67bdatagen2026-10-17 04:56 UTC113
                .keys()
4cbf881c67bdatagen2026-10-17 04:56 UTC114
                .find(|&t| self.is_viewed(t, tag))
4cbf881c67bdatagen2026-10-17 04:56 UTC115
                .or(self.active);
4cbf881c67bdatagen2026-10-17 04:56 UTC116
            let win = &mut self.windows[w];
4cbf881c67bdatagen2026-10-17 04:56 UTC117
            if let (Some(t), Some(rect)) = (target, win.float_rect) {
4b73e40af1e3atagen2026-10-19 07:44 UTC118
                win.float_rect = Some(translate(rect, left_usable, self.outputs[t].usable()));
4cbf881c67bdatagen2026-10-17 04:56 UTC119
            }
4cbf881c67bdatagen2026-10-17 04:56 UTC120
            win.output = target;
4cbf881c67bdatagen2026-10-17 04:56 UTC121
            if win.scratchpad.is_some() {
4cbf881c67bdatagen2026-10-17 04:56 UTC122
                continue;
4cbf881c67bdatagen2026-10-17 04:56 UTC123
            }
8ffa3fa4d4a9atagen2026-10-18 09:38 UTC124
            win.evicted_from.get_or_insert_with(|| out.name.clone());
4cbf881c67bdatagen2026-10-17 04:56 UTC125
            if target.is_some() {
4cbf881c67bdatagen2026-10-17 04:56 UTC126
                self.place(w);
4cbf881c67bdatagen2026-10-17 04:56 UTC127
            }
4cbf881c67bdatagen2026-10-17 04:56 UTC128
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC129
    }
4cbf881c67bdatagen2026-10-17 04:56 UTC130
4cbf881c67bdatagen2026-10-17 04:56 UTC131
    pub fn set_output_area(&mut self, o: OutputId, area: Rect) {
4b73e40af1e3atagen2026-10-19 07:44 UTC132
        let Some(out) = self.outputs.get_mut(o) else {
4b73e40af1e3atagen2026-10-19 07:44 UTC133
            return;
4b73e40af1e3atagen2026-10-19 07:44 UTC134
        };
4b73e40af1e3atagen2026-10-19 07:44 UTC135
        let before = out.usable();
4b73e40af1e3atagen2026-10-19 07:44 UTC136
        out.area = area;
4b73e40af1e3atagen2026-10-19 07:44 UTC137
        self.rescale_floats(o, before);
4cbf881c67bdatagen2026-10-17 04:56 UTC138
    }
4cbf881c67bdatagen2026-10-17 04:56 UTC139
4cbf881c67bdatagen2026-10-17 04:56 UTC140
    /// Returns whether anything changed.
4cbf881c67bdatagen2026-10-17 04:56 UTC141
    pub fn set_reserved(&mut self, o: OutputId, reserved: Insets) -> bool {
4b73e40af1e3atagen2026-10-19 07:44 UTC142
        let Some(out) = self.outputs.get_mut(o) else {
4b73e40af1e3atagen2026-10-19 07:44 UTC143
            return false;
4b73e40af1e3atagen2026-10-19 07:44 UTC144
        };
4b73e40af1e3atagen2026-10-19 07:44 UTC145
        if out.reserved == reserved {
4b73e40af1e3atagen2026-10-19 07:44 UTC146
            return false;
4b73e40af1e3atagen2026-10-19 07:44 UTC147
        }
4b73e40af1e3atagen2026-10-19 07:44 UTC148
        out.reserved = reserved;
9c937ba68fa7atagen2026-10-19 08:02 UTC149
        let bounds = out.usable();
9c937ba68fa7atagen2026-10-19 08:02 UTC150
        for win in self.windows.values_mut().filter(|w| w.output == Some(o)) {
9c937ba68fa7atagen2026-10-19 08:02 UTC151
            if let Some(rect) = win.float_rect {
9c937ba68fa7atagen2026-10-19 08:02 UTC152
                win.float_rect = Some(crate::clamp_float(rect, bounds));
9c937ba68fa7atagen2026-10-19 08:02 UTC153
            }
9c937ba68fa7atagen2026-10-19 08:02 UTC154
        }
4b73e40af1e3atagen2026-10-19 07:44 UTC155
        true
4b73e40af1e3atagen2026-10-19 07:44 UTC156
    }
4b73e40af1e3atagen2026-10-19 07:44 UTC157
4b73e40af1e3atagen2026-10-19 07:44 UTC158
    /// Carries floating windows along when the usable area of o changes.
4b73e40af1e3atagen2026-10-19 07:44 UTC159
    fn rescale_floats(&mut self, o: OutputId, before: Rect) {
4b73e40af1e3atagen2026-10-19 07:44 UTC160
        let after = self.outputs[o].usable();
4b73e40af1e3atagen2026-10-19 07:44 UTC161
        if after == before {
4b73e40af1e3atagen2026-10-19 07:44 UTC162
            return;
4b73e40af1e3atagen2026-10-19 07:44 UTC163
        }
4b73e40af1e3atagen2026-10-19 07:44 UTC164
        for win in self.windows.values_mut().filter(|w| w.output == Some(o)) {
4b73e40af1e3atagen2026-10-19 07:44 UTC165
            if let Some(rect) = win.float_rect {
4b73e40af1e3atagen2026-10-19 07:44 UTC166
                win.float_rect = Some(translate(rect, before, after));
4cbf881c67bdatagen2026-10-17 04:56 UTC167
            }
4cbf881c67bdatagen2026-10-17 04:56 UTC168
        }
4cbf881c67bdatagen2026-10-17 04:56 UTC169
    }
4cbf881c67bdatagen2026-10-17 04:56 UTC170
}