atagen

monolith

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