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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use dispatch::Queue;
use polyhorn_core::{Command, Composition};
use polyhorn_ui::layout::LayoutTree;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, RwLock};
use super::{Environment, OpaqueContainer, Platform, QueueBound};
#[derive(Clone)]
pub struct Compositor {
buffer: Arc<QueueBound<Composition<Platform>>>,
counter: Arc<AtomicUsize>,
layout_tree: Arc<RwLock<LayoutTree>>,
}
impl Compositor {
pub fn new(layout_tree: Arc<RwLock<LayoutTree>>) -> Compositor {
Compositor {
buffer: Arc::new(QueueBound::new(Queue::main(), || Default::default())),
counter: Arc::new(AtomicUsize::default()),
layout_tree,
}
}
fn next_id(&mut self) -> ContainerID {
let id = self.counter.fetch_add(1, Ordering::Relaxed);
ContainerID(id)
}
pub(crate) fn track(&mut self, container: OpaqueContainer) -> ContainerID {
let id = self.next_id();
unsafe {
self.buffer.with_adopt(container, move |state, container| {
state.insert(id, container);
});
}
id
}
}
impl polyhorn_core::Compositor<Platform> for Compositor {
fn buffer(&self) -> CommandBuffer {
CommandBuffer {
compositor: self.clone(),
commands: vec![],
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub struct ContainerID(usize);
pub struct CommandBuffer {
compositor: Compositor,
commands: Vec<Command<Platform>>,
}
impl polyhorn_core::CommandBuffer<Platform> for CommandBuffer {
fn mount<F>(&mut self, parent_id: ContainerID, initializer: F) -> ContainerID
where
F: FnOnce(&mut OpaqueContainer, &mut Environment) -> OpaqueContainer + Send + 'static,
{
let id = self.compositor.next_id();
self.commands
.push(Command::Mount(id, parent_id, Box::new(initializer)));
id
}
fn mutate<F>(&mut self, ids: &[ContainerID], mutator: F)
where
F: FnOnce(&mut [&mut OpaqueContainer], &mut Environment) + Send + 'static,
{
self.commands
.push(Command::Mutate(ids.to_owned(), Box::new(mutator)));
}
fn unmount(&mut self, id: ContainerID) {
self.commands.push(Command::Unmount(id));
}
fn layout(&mut self) {
self.mutate(&[], |_, environment| {
let mut layout_tree = environment.layout_tree().write().unwrap();
layout_tree.recompute_roots();
});
}
fn commit(mut self) {
let commands = std::mem::take(&mut self.commands);
let layout_tree = self.compositor.layout_tree.clone();
self.compositor.buffer.with(move |state| {
let mut environment = Environment::new(layout_tree.clone());
for command in commands {
state.process(&mut environment, command);
}
});
}
}