1use super::Composition;
16use super::composer::{Composer, EventCallback, ROOT};
17use super::seam::{Batch, Runtime};
18use super::{drain_graveyard, effects, state, with_composer};
19use crate::boundary::{Host, request_frame_from_worker};
20use crate::protocol::{HostEvent, ProtocolError};
21use crate::schema::{EventPayload, Theme};
22use crate::{KeyEvent, RangeRequest};
23use std::any::Any;
24use std::rc::Rc;
25use std::sync::Arc;
26
27pub struct Recomposer {
33 content: Rc<dyn Fn()>,
34 composition: Rc<Composition>,
35 _subscriptions: Vec<Box<dyn Any>>,
38}
39
40impl Recomposer {
41 pub fn new(content: impl Fn() + 'static) -> Self {
43 let composition = Composition::new();
44 let (window, design, permission) = {
45 let composer = composition.composer.borrow();
46 (
47 composer.ambient.window.clone(),
48 composer.ambient.design.clone(),
49 composer.ambient.permission.clone(),
50 )
51 };
52 let subscriptions: Vec<Box<dyn Any>> = vec![
56 Box::new(crate::window::subscribe(Arc::new(move || {
57 window.set(crate::window::window_size())
58 }))),
59 Box::new(crate::design::subscribe(Arc::new(move || {
60 design.set(crate::design::design_system())
61 }))),
62 Box::new(crate::notification::subscribe_permission(Arc::new(
63 move || permission.set(crate::notification::notification_permission()),
64 ))),
65 ];
66 Self {
67 content: Rc::new(content),
68 composition,
69 _subscriptions: subscriptions,
70 }
71 }
72
73 pub fn arena(&self) -> (*const u8, usize) {
75 self.composition.composer.borrow().writer.arena()
76 }
77
78 pub fn size_token(&self, node_id: u32) -> Option<u32> {
80 self.composition
81 .composer
82 .borrow()
83 .writer
84 .size_token(node_id)
85 }
86
87 pub fn rebuild(&mut self) {
89 let _composition = self.composition.enter();
90 with_composer(|composer| {
91 composer.abandon_composition();
92 composer.begin_root();
93 });
94 (self.content)();
95 with_composer(Composer::end_root);
96 self.after_composition();
97 }
98
99 pub fn render(&mut self, frame_time_nanos: Option<u64>) {
102 let _composition = self.composition.enter();
103 if let Some(now) = frame_time_nanos {
104 with_composer(|composer| composer.executor.deliver_frame(now));
105 }
106 effects::poll_woken();
107 self.recompose();
108 }
109
110 pub fn handle_event(&mut self, event: &HostEvent<'_>) -> Result<i64, ProtocolError> {
116 let _composition = self.composition.enter();
117 let Some((node, callback)) = with_composer(|composer| {
118 composer
119 .handlers
120 .get(&event.handler_id)
121 .map(|entry| (entry.node, entry.callback.clone()))
122 })
123 .flatten() else {
124 return Err(ProtocolError::InvalidValueKind(0));
125 };
126 if node != event.node_id {
127 return Err(ProtocolError::InvalidValueKind(0));
128 }
129 deliver(&callback, &event.payload)
130 }
131
132 pub fn run_in_context(&mut self, action: &mut dyn FnMut()) {
136 let _composition = self.composition.enter();
137 action();
138 }
139
140 fn recompose(&mut self) {
147 with_composer(Composer::abandon_composition);
148 state::apply_state_changes();
149 let root = with_composer(|composer| composer.root_invalid()).unwrap_or(false);
150 if root {
151 with_composer(Composer::begin_root);
152 (self.content)();
153 with_composer(Composer::end_root);
154 }
155 let invalid = with_composer(Composer::take_invalid).unwrap_or_default();
156 for group in invalid {
157 if group == ROOT {
158 continue;
159 }
160 let restart = with_composer(|composer| composer.prepare_restart(group)).flatten();
161 if let Some(restart) = restart {
162 restart();
163 with_composer(Composer::finish_restart);
164 }
165 }
166 self.after_composition();
167 }
168
169 fn after_composition(&mut self) {
170 drain_graveyard();
171 effects::apply_effects();
172 drain_graveyard();
173 effects::poll_woken();
174 let pending = with_composer(|composer| {
177 !composer
178 .signal
179 .dirty
180 .lock()
181 .unwrap_or_else(|poison| poison.into_inner())
182 .is_empty()
183 || !composer.invalid.is_empty()
184 })
185 .unwrap_or(false);
186 if pending {
187 request_frame_from_worker();
188 }
189 }
190}
191
192pub struct ComposeHost(Host);
199
200impl ComposeHost {
201 pub fn new(content: fn()) -> Self {
203 Self(Host::new(recomposer_for(content)))
204 }
205
206 pub fn with_theme(content: fn(), theme: Theme) -> Self {
208 Self(Host::with_theme(recomposer_for(content), theme))
209 }
210
211 pub fn with_content(content: impl Fn() + Send + Sync + 'static) -> Self {
215 let content = Arc::new(content);
216 Self(Host::new(move || {
217 let content = Arc::clone(&content);
218 Box::new(Recomposer::new(move || content())) as Box<dyn Runtime>
219 }))
220 }
221}
222
223impl std::ops::Deref for ComposeHost {
224 type Target = Host;
225
226 fn deref(&self) -> &Host {
227 &self.0
228 }
229}
230
231impl std::ops::DerefMut for ComposeHost {
232 fn deref_mut(&mut self) -> &mut Host {
233 &mut self.0
234 }
235}
236
237pub fn recomposer_for(content: fn()) -> impl Fn() -> Box<dyn Runtime> + Send + Sync + 'static {
240 move || Box::new(Recomposer::new(content)) as Box<dyn Runtime>
241}
242
243impl crate::LaunchBuilder {
244 pub fn launch(self, content: fn()) {
258 self.launch_runtime(recomposer_for(content));
259 }
260
261 pub fn try_launch(self, content: fn()) -> i32 {
264 self.try_launch_runtime(recomposer_for(content))
265 }
266
267 pub fn application(self, content: fn()) {
269 self.launch(content);
270 }
271}
272
273pub fn launch(content: fn()) {
288 crate::LaunchBuilder::new().launch(content);
289}
290
291pub fn application(content: fn()) {
293 launch(content);
294}
295
296fn deliver(callback: &EventCallback, payload: &EventPayload<'_>) -> Result<i64, ProtocolError> {
298 match (callback, payload) {
299 (
300 EventCallback::Unit(handler),
301 EventPayload::Clicked | EventPayload::FocusLost | EventPayload::FilesEntered,
302 ) => (*handler.borrow_mut())(),
303 (EventCallback::Text(handler), EventPayload::TextChanged(text))
304 | (EventCallback::Text(handler), EventPayload::TextSubmitted(text)) => {
305 (*handler.borrow_mut())((*text).to_owned())
306 }
307 (
308 EventCallback::Key(handler),
309 EventPayload::KeyDown {
310 key,
311 shift_key,
312 ctrl_key,
313 alt_key,
314 meta_key,
315 },
316 ) => {
317 let event = KeyEvent::new(*key, *shift_key, *ctrl_key, *alt_key, *meta_key);
318 (*handler.borrow_mut())(event.clone());
319 return Ok(i64::from(event.consumed()));
320 }
321 (
322 EventCallback::Pointer(handler),
323 EventPayload::Pointer {
324 kind,
325 pointer_id,
326 pointer_type,
327 x,
328 y,
329 buttons,
330 button,
331 modifiers,
332 click_count,
333 delta_x,
334 delta_y,
335 delta_mode,
336 timestamp_nanos,
337 },
338 ) => {
339 let event = crate::PointerEvent::new(
340 *kind,
341 *pointer_id,
342 *pointer_type,
343 *x,
344 *y,
345 *buttons,
346 *button,
347 *modifiers,
348 *click_count,
349 *delta_x,
350 *delta_y,
351 *delta_mode,
352 *timestamp_nanos,
353 );
354 (*handler.borrow_mut())(event.clone());
355 return Ok(i64::from(event.consumed()));
356 }
357 (EventCallback::Value(handler), EventPayload::ValueChanged(value)) => {
358 (*handler.borrow_mut())(*value)
359 }
360 (EventCallback::Range(handler), EventPayload::RangeRequested { start, count }) => {
361 (*handler.borrow_mut())(RangeRequest::new(*start, *count))
362 }
363 (EventCallback::Files(handler), EventPayload::FilesDropped(paths)) => {
364 (*handler.borrow_mut())(crate::FileDrop::new(paths))
365 }
366 _ => return Err(ProtocolError::InvalidValueKind(0)),
367 }
368 Ok(0)
369}
370
371impl Composer {
372 pub(crate) fn abandon_composition(&mut self) {
374 self.clear_walk();
375 }
376}
377
378impl Runtime for Recomposer {
379 fn batch(&self) -> &Batch {
380 let composer = self.composition.composer.as_ptr();
381 unsafe { (*composer).writer.batch() }
385 }
386
387 fn batch_mut(&mut self) -> &mut Batch {
388 let composer = self.composition.composer.as_ptr();
389 unsafe { (*composer).writer.batch_mut() }
391 }
392
393 fn rebuild(&mut self) {
394 Recomposer::rebuild(self);
395 }
396
397 fn render(&mut self, frame_time_nanos: Option<u64>) {
398 Recomposer::render(self, frame_time_nanos);
399 }
400
401 fn handle_event(&mut self, event: &HostEvent<'_>) -> Result<i64, ProtocolError> {
402 Recomposer::handle_event(self, event)
403 }
404
405 fn size_token(&self, node_id: u32) -> Option<u32> {
406 Recomposer::size_token(self, node_id)
407 }
408
409 fn run_in_context(&mut self, action: &mut dyn FnMut()) {
410 Recomposer::run_in_context(self, action);
411 }
412}