polyhorn_android/raw/
compositor.rs1use polyhorn_android_sys::Runnable;
2use polyhorn_core::{Command, Composition};
3use std::sync::atomic::{AtomicUsize, Ordering};
4use std::sync::{Arc, Mutex};
5
6use super::{Environment, OpaqueContainer, Platform};
7
8#[derive(Clone)]
12pub struct Compositor {
13 environment: Environment,
14 buffer: Arc<Mutex<Composition<Platform>>>,
15 counter: Arc<AtomicUsize>,
16}
17
18impl Compositor {
19 pub fn new(environment: Environment) -> Compositor {
21 Compositor {
22 environment,
23 buffer: Arc::new(Default::default()),
24 counter: Arc::new(AtomicUsize::default()),
25 }
26 }
27
28 fn next_id(&mut self) -> ContainerID {
29 let id = self.counter.fetch_add(1, Ordering::Relaxed);
30 ContainerID(id)
31 }
32
33 pub(crate) fn track(&mut self, container: OpaqueContainer) -> ContainerID {
34 let id = self.next_id();
35 self.buffer.lock().unwrap().insert(id, container);
36 id
37 }
38}
39
40impl polyhorn_core::Compositor<Platform> for Compositor {
41 fn buffer(&self) -> CommandBuffer {
42 CommandBuffer {
43 compositor: self.clone(),
44 commands: vec![],
45 }
46 }
47}
48
49#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
51pub struct ContainerID(usize);
52
53pub struct CommandBuffer {
56 compositor: Compositor,
57 commands: Vec<Command<Platform>>,
58}
59
60impl polyhorn_core::CommandBuffer<Platform> for CommandBuffer {
61 fn mount<F>(&mut self, parent_id: ContainerID, initializer: F) -> ContainerID
62 where
63 F: FnOnce(&mut OpaqueContainer, &mut Environment) -> OpaqueContainer + Send + 'static,
64 {
65 let id = self.compositor.next_id();
66 self.commands
67 .push(Command::Mount(id, parent_id, Box::new(initializer)));
68 id
69 }
70
71 fn mutate<F>(&mut self, ids: &[ContainerID], mutator: F)
72 where
73 F: FnOnce(&mut [&mut OpaqueContainer], &mut Environment) + Send + 'static,
74 {
75 self.commands
76 .push(Command::Mutate(ids.to_owned(), Box::new(mutator)));
77 }
78
79 fn unmount(&mut self, id: ContainerID) {
80 self.commands.push(Command::Unmount(id));
81 }
82
83 fn layout(&mut self) {
84 self.mutate(&[], |_, environment| {
85 environment.layout_tree().write().unwrap().recompute_roots();
86 });
87 }
88
89 fn commit(mut self) {
90 let commands = std::mem::take(&mut self.commands);
91
92 let activity = self.compositor.environment.activity().clone();
93 let layout_tree = self.compositor.environment.layout_tree().clone();
94 let state = self.compositor.buffer.clone();
95
96 Runnable::new(&self.compositor.environment.env(), move |env| {
97 let mut environment = Environment::new(
98 activity,
99 unsafe { env.clone().prolong_lifetime() },
100 layout_tree.clone(),
101 );
102
103 let mut state = state.lock().unwrap();
104
105 for command in commands {
107 state.process(&mut environment, command);
108 }
109
110 let mut layout_tree = layout_tree.write().unwrap();
111 layout_tree.recompute_roots();
112 })
113 .queue(&self.compositor.environment.env());
114 }
115}