srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/core/src/manager/fake_monitor.rs
blob: 2533e833cede94c70ed167be16949d0c86aa9dcf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! Requesting a fake (fully virtual, no real hardware) monitor be created
//! or removed - see `crates/wayland/src/udev/virtual_heads.rs`'s own
//! module doc comment for the full design. Split out the same way
//! `lock.rs`/`input_pin.rs` are: everything here is plain `impl
//! WindowManager` methods; see `super` (`mod.rs`) for `WindowManager`'s
//! field definitions.

use super::*;

impl WindowManager {
    /// Queues a request to create a fake monitor named `name` at
    /// `width`x`height` - the only caller today is the IPC
    /// `"create_fake_monitor"` dispatch, the compositor-agnostic side of
    /// `srd dispatch create fake-monitor`. Core has no real `wl_output`
    /// to create itself (backend-owned, same as every other cross-
    /// boundary request here); the Wayland backend drains and applies
    /// this on its own next poll.
    pub fn request_create_fake_monitor(&mut self, name: String, width: u32, height: u32) {
        self.create_fake_monitor_requests.push((name, width, height));
    }

    pub fn drain_create_fake_monitor_requests(&mut self) -> Vec<(String, u32, u32)> {
        std::mem::take(&mut self.create_fake_monitor_requests)
    }

    /// Same cross-boundary-request pattern, for removing a fake monitor
    /// by name - the IPC `"remove_fake_monitor"` dispatch.
    pub fn request_remove_fake_monitor(&mut self, name: String) {
        self.remove_fake_monitor_requests.push(name);
    }

    pub fn drain_remove_fake_monitor_requests(&mut self) -> Vec<String> {
        std::mem::take(&mut self.remove_fake_monitor_requests)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn a_create_request_is_reported_once_then_the_queue_is_empty() {
        let mut wm = WindowManager::new();
        assert!(wm.drain_create_fake_monitor_requests().is_empty());
        wm.request_create_fake_monitor("FAKE-1".into(), 1920, 1080);
        assert_eq!(wm.drain_create_fake_monitor_requests(), vec![("FAKE-1".to_string(), 1920, 1080)]);
        assert!(wm.drain_create_fake_monitor_requests().is_empty());
    }

    #[test]
    fn a_remove_request_is_reported_once_then_the_queue_is_empty() {
        let mut wm = WindowManager::new();
        wm.request_remove_fake_monitor("FAKE-1".into());
        assert_eq!(wm.drain_remove_fake_monitor_requests(), vec!["FAKE-1".to_string()]);
        assert!(wm.drain_remove_fake_monitor_requests().is_empty());
    }

    #[test]
    fn multiple_create_requests_before_a_drain_are_all_preserved() {
        // Unlike `request_pin_input`'s own "replace, don't accumulate"
        // semantics (one pid can only ever have one current pin target),
        // two different fake-monitor names are two genuinely independent
        // creations - both must survive to the next drain.
        let mut wm = WindowManager::new();
        wm.request_create_fake_monitor("FAKE-1".into(), 1920, 1080);
        wm.request_create_fake_monitor("FAKE-2".into(), 1280, 720);
        assert_eq!(wm.drain_create_fake_monitor_requests(), vec![("FAKE-1".to_string(), 1920, 1080), ("FAKE-2".to_string(), 1280, 720)]);
    }
}