1use crate::{
2 px, size, AnyBox, AnyView, AppContext, AsyncWindowContext, AvailableSpace, BorrowAppContext,
3 Bounds, BoxShadow, Context, Corners, DevicePixels, DisplayId, Edges, Effect, Element, EntityId,
4 Event, FontId, GlobalElementId, GlyphId, Handle, Hsla, ImageData, IsZero, LayoutId, MainThread,
5 MainThreadOnly, MonochromeSprite, MouseMoveEvent, Path, Pixels, PlatformAtlas, PlatformWindow,
6 Point, PolychromeSprite, Quad, Reference, RenderGlyphParams, RenderImageParams,
7 RenderSvgParams, ScaledPixels, SceneBuilder, Shadow, SharedString, Size, Style,
8 TaffyLayoutEngine, Task, Underline, UnderlineStyle, WeakHandle, WindowOptions,
9 SUBPIXEL_VARIANTS,
10};
11use anyhow::Result;
12use collections::HashMap;
13use derive_more::{Deref, DerefMut};
14use smallvec::SmallVec;
15use std::{
16 any::{Any, TypeId},
17 borrow::Cow,
18 fmt::Debug,
19 future::Future,
20 marker::PhantomData,
21 mem,
22 sync::Arc,
23};
24use util::{arc_cow::ArcCow, ResultExt};
25
26#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Default)]
27pub struct StackingOrder(pub(crate) SmallVec<[u32; 16]>);
28
29#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
30pub enum DispatchPhase {
31 /// After the capture phase comes the bubble phase, in which event handlers are
32 /// invoked front to back. This is the phase you'll usually want to use for event handlers.
33 #[default]
34 Bubble,
35 /// During the initial capture phase, event handlers are invoked back to front. This phase
36 /// is used for special purposes such as clearing the "pressed" state for click events. If
37 /// you stop event propagation during this phase, you need to know what you're doing. Handlers
38 /// outside of the immediate region may rely on detecting non-local events during this phase.
39 Capture,
40}
41
42type MouseEventHandler =
43 Arc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext) + Send + Sync + 'static>;
44
45pub struct Window {
46 handle: AnyWindowHandle,
47 platform_window: MainThreadOnly<Box<dyn PlatformWindow>>,
48 pub(crate) display_id: DisplayId, // todo!("make private again?")
49 sprite_atlas: Arc<dyn PlatformAtlas>,
50 rem_size: Pixels,
51 content_size: Size<Pixels>,
52 layout_engine: TaffyLayoutEngine,
53 pub(crate) root_view: Option<AnyView<()>>,
54 pub(crate) element_id_stack: GlobalElementId,
55 prev_element_states: HashMap<GlobalElementId, AnyBox>,
56 element_states: HashMap<GlobalElementId, AnyBox>,
57 z_index_stack: StackingOrder,
58 content_mask_stack: Vec<ContentMask<Pixels>>,
59 mouse_event_handlers: HashMap<TypeId, Vec<(StackingOrder, MouseEventHandler)>>,
60 propagate_event: bool,
61 mouse_position: Point<Pixels>,
62 scale_factor: f32,
63 pub(crate) scene_builder: SceneBuilder,
64 pub(crate) dirty: bool,
65}
66
67impl Window {
68 pub fn new(
69 handle: AnyWindowHandle,
70 options: WindowOptions,
71 cx: &mut MainThread<AppContext>,
72 ) -> Self {
73 let platform_window = cx.platform().open_window(handle, options);
74 let display_id = platform_window.display().id();
75 let sprite_atlas = platform_window.sprite_atlas();
76 let mouse_position = platform_window.mouse_position();
77 let content_size = platform_window.content_size();
78 let scale_factor = platform_window.scale_factor();
79 platform_window.on_resize(Box::new({
80 let cx = cx.to_async();
81 move |content_size, scale_factor| {
82 cx.update_window(handle, |cx| {
83 cx.window.scale_factor = scale_factor;
84 cx.window.scene_builder = SceneBuilder::new();
85 cx.window.content_size = content_size;
86 cx.window.display_id = cx
87 .window
88 .platform_window
89 .borrow_on_main_thread()
90 .display()
91 .id();
92 cx.window.dirty = true;
93 })
94 .log_err();
95 }
96 }));
97
98 platform_window.on_event({
99 let cx = cx.to_async();
100 Box::new(move |event| {
101 cx.update_window(handle, |cx| cx.dispatch_event(event))
102 .log_err()
103 .unwrap_or(true)
104 })
105 });
106
107 let platform_window = MainThreadOnly::new(Arc::new(platform_window), cx.executor.clone());
108
109 Window {
110 handle,
111 platform_window,
112 display_id,
113 sprite_atlas,
114 rem_size: px(16.),
115 content_size,
116 layout_engine: TaffyLayoutEngine::new(),
117 root_view: None,
118 element_id_stack: GlobalElementId::default(),
119 prev_element_states: HashMap::default(),
120 element_states: HashMap::default(),
121 z_index_stack: StackingOrder(SmallVec::new()),
122 content_mask_stack: Vec::new(),
123 mouse_event_handlers: HashMap::default(),
124 propagate_event: true,
125 mouse_position,
126 scale_factor,
127 scene_builder: SceneBuilder::new(),
128 dirty: true,
129 }
130 }
131}
132
133#[derive(Clone, Debug, Default, PartialEq, Eq)]
134#[repr(C)]
135pub struct ContentMask<P: Clone + Debug> {
136 pub bounds: Bounds<P>,
137}
138
139impl ContentMask<Pixels> {
140 pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
141 ContentMask {
142 bounds: self.bounds.scale(factor),
143 }
144 }
145
146 pub fn intersect(&self, other: &Self) -> Self {
147 let bounds = self.bounds.intersect(&other.bounds);
148 ContentMask { bounds }
149 }
150}
151
152pub struct WindowContext<'a, 'w> {
153 app: Reference<'a, AppContext>,
154 pub(crate) window: Reference<'w, Window>,
155}
156
157impl<'a, 'w> WindowContext<'a, 'w> {
158 pub(crate) fn mutable(app: &'a mut AppContext, window: &'w mut Window) -> Self {
159 Self {
160 app: Reference::Mutable(app),
161 window: Reference::Mutable(window),
162 }
163 }
164
165 pub fn notify(&mut self) {
166 self.window.dirty = true;
167 }
168
169 pub fn run_on_main<R>(
170 &mut self,
171 f: impl FnOnce(&mut MainThread<WindowContext<'_, '_>>) -> R + Send + 'static,
172 ) -> Task<Result<R>>
173 where
174 R: Send + 'static,
175 {
176 if self.executor.is_main_thread() {
177 Task::ready(Ok(f(unsafe {
178 mem::transmute::<&mut Self, &mut MainThread<Self>>(self)
179 })))
180 } else {
181 let id = self.window.handle.id;
182 self.app.run_on_main(move |cx| cx.update_window(id, f))
183 }
184 }
185
186 pub fn to_async(&self) -> AsyncWindowContext {
187 AsyncWindowContext::new(self.app.to_async(), self.window.handle)
188 }
189
190 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut WindowContext) + Send + 'static) {
191 let f = Box::new(f);
192 let display_id = self.window.display_id;
193 let async_cx = self.to_async();
194 let app_cx = self.app_mut();
195 match app_cx.next_frame_callbacks.entry(display_id) {
196 collections::hash_map::Entry::Occupied(mut entry) => {
197 if entry.get().is_empty() {
198 app_cx.display_linker.start(display_id);
199 }
200 entry.get_mut().push(f);
201 }
202 collections::hash_map::Entry::Vacant(entry) => {
203 app_cx.display_linker.set_output_callback(
204 display_id,
205 Box::new(move |_current_time, _output_time| {
206 let _ = async_cx.update(|cx| {
207 let callbacks = cx
208 .next_frame_callbacks
209 .get_mut(&display_id)
210 .unwrap()
211 .drain(..)
212 .collect::<Vec<_>>();
213 for callback in callbacks {
214 callback(cx);
215 }
216
217 if cx.next_frame_callbacks.get(&display_id).unwrap().is_empty() {
218 cx.display_linker.stop(display_id);
219 }
220 });
221 }),
222 );
223 app_cx.display_linker.start(display_id);
224 entry.insert(vec![f]);
225 }
226 }
227 }
228
229 pub fn spawn<Fut, R>(
230 &mut self,
231 f: impl FnOnce(AnyWindowHandle, AsyncWindowContext) -> Fut + Send + 'static,
232 ) -> Task<R>
233 where
234 R: Send + 'static,
235 Fut: Future<Output = R> + Send + 'static,
236 {
237 let window = self.window.handle;
238 self.app.spawn(move |app| {
239 let cx = AsyncWindowContext::new(app, window);
240 let future = f(window, cx);
241 async move { future.await }
242 })
243 }
244
245 pub fn request_layout(
246 &mut self,
247 style: Style,
248 children: impl IntoIterator<Item = LayoutId>,
249 ) -> LayoutId {
250 self.app.layout_id_buffer.clear();
251 self.app.layout_id_buffer.extend(children.into_iter());
252 let rem_size = self.rem_size();
253
254 self.window
255 .layout_engine
256 .request_layout(style, rem_size, &self.app.layout_id_buffer)
257 }
258
259 pub fn request_measured_layout<
260 F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>) -> Size<Pixels> + Send + Sync + 'static,
261 >(
262 &mut self,
263 style: Style,
264 rem_size: Pixels,
265 measure: F,
266 ) -> LayoutId {
267 self.window
268 .layout_engine
269 .request_measured_layout(style, rem_size, measure)
270 }
271
272 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
273 self.window
274 .layout_engine
275 .layout_bounds(layout_id)
276 .map(Into::into)
277 }
278
279 pub fn scale_factor(&self) -> f32 {
280 self.window.scale_factor
281 }
282
283 pub fn rem_size(&self) -> Pixels {
284 self.window.rem_size
285 }
286
287 pub fn stop_propagation(&mut self) {
288 self.window.propagate_event = false;
289 }
290
291 pub fn on_mouse_event<Event: 'static>(
292 &mut self,
293 handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + Send + Sync + 'static,
294 ) {
295 let order = self.window.z_index_stack.clone();
296 self.window
297 .mouse_event_handlers
298 .entry(TypeId::of::<Event>())
299 .or_default()
300 .push((
301 order,
302 Arc::new(move |event: &dyn Any, phase, cx| {
303 handler(event.downcast_ref().unwrap(), phase, cx)
304 }),
305 ))
306 }
307
308 pub fn mouse_position(&self) -> Point<Pixels> {
309 self.window.mouse_position
310 }
311
312 pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
313 self.window.z_index_stack.push(order);
314 let result = f(self);
315 self.window.z_index_stack.pop();
316 result
317 }
318
319 pub fn paint_shadows(
320 &mut self,
321 bounds: Bounds<Pixels>,
322 corner_radii: Corners<Pixels>,
323 shadows: &[BoxShadow],
324 ) {
325 let scale_factor = self.scale_factor();
326 let content_mask = self.content_mask();
327 let window = &mut *self.window;
328 for shadow in shadows {
329 let mut shadow_bounds = bounds;
330 shadow_bounds.origin += shadow.offset;
331 shadow_bounds.dilate(shadow.spread_radius);
332 window.scene_builder.insert(
333 &window.z_index_stack,
334 Shadow {
335 order: 0,
336 bounds: shadow_bounds.scale(scale_factor),
337 content_mask: content_mask.scale(scale_factor),
338 corner_radii: corner_radii.scale(scale_factor),
339 color: shadow.color,
340 blur_radius: shadow.blur_radius.scale(scale_factor),
341 },
342 );
343 }
344 }
345
346 pub fn paint_quad(
347 &mut self,
348 bounds: Bounds<Pixels>,
349 corner_radii: Corners<Pixels>,
350 background: impl Into<Hsla>,
351 border_widths: Edges<Pixels>,
352 border_color: impl Into<Hsla>,
353 ) {
354 let scale_factor = self.scale_factor();
355 let content_mask = self.content_mask();
356
357 let window = &mut *self.window;
358 window.scene_builder.insert(
359 &window.z_index_stack,
360 Quad {
361 order: 0,
362 bounds: bounds.scale(scale_factor),
363 content_mask: content_mask.scale(scale_factor),
364 background: background.into(),
365 border_color: border_color.into(),
366 corner_radii: corner_radii.scale(scale_factor),
367 border_widths: border_widths.scale(scale_factor),
368 },
369 );
370 }
371
372 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Hsla>) {
373 let scale_factor = self.scale_factor();
374 let content_mask = self.content_mask();
375 path.content_mask = content_mask;
376 path.color = color.into();
377 let window = &mut *self.window;
378 window
379 .scene_builder
380 .insert(&window.z_index_stack, path.scale(scale_factor));
381 }
382
383 pub fn paint_underline(
384 &mut self,
385 origin: Point<Pixels>,
386 width: Pixels,
387 style: &UnderlineStyle,
388 ) -> Result<()> {
389 let scale_factor = self.scale_factor();
390 let height = if style.wavy {
391 style.thickness * 3.
392 } else {
393 style.thickness
394 };
395 let bounds = Bounds {
396 origin,
397 size: size(width, height),
398 };
399 let content_mask = self.content_mask();
400 let window = &mut *self.window;
401 window.scene_builder.insert(
402 &window.z_index_stack,
403 Underline {
404 order: 0,
405 bounds: bounds.scale(scale_factor),
406 content_mask: content_mask.scale(scale_factor),
407 thickness: style.thickness.scale(scale_factor),
408 color: style.color.unwrap_or_default(),
409 wavy: style.wavy,
410 },
411 );
412 Ok(())
413 }
414
415 pub fn paint_glyph(
416 &mut self,
417 origin: Point<Pixels>,
418 font_id: FontId,
419 glyph_id: GlyphId,
420 font_size: Pixels,
421 color: Hsla,
422 ) -> Result<()> {
423 let scale_factor = self.scale_factor();
424 let glyph_origin = origin.scale(scale_factor);
425 let subpixel_variant = Point {
426 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
427 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
428 };
429 let params = RenderGlyphParams {
430 font_id,
431 glyph_id,
432 font_size,
433 subpixel_variant,
434 scale_factor,
435 is_emoji: false,
436 };
437
438 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
439 if !raster_bounds.is_zero() {
440 let tile =
441 self.window
442 .sprite_atlas
443 .get_or_insert_with(¶ms.clone().into(), &mut || {
444 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
445 Ok((size, Cow::Owned(bytes)))
446 })?;
447 let bounds = Bounds {
448 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
449 size: tile.bounds.size.map(Into::into),
450 };
451 let content_mask = self.content_mask().scale(scale_factor);
452 let window = &mut *self.window;
453 window.scene_builder.insert(
454 &window.z_index_stack,
455 MonochromeSprite {
456 order: 0,
457 bounds,
458 content_mask,
459 color,
460 tile,
461 },
462 );
463 }
464 Ok(())
465 }
466
467 pub fn paint_emoji(
468 &mut self,
469 origin: Point<Pixels>,
470 font_id: FontId,
471 glyph_id: GlyphId,
472 font_size: Pixels,
473 ) -> Result<()> {
474 let scale_factor = self.scale_factor();
475 let glyph_origin = origin.scale(scale_factor);
476 let params = RenderGlyphParams {
477 font_id,
478 glyph_id,
479 font_size,
480 // We don't render emojis with subpixel variants.
481 subpixel_variant: Default::default(),
482 scale_factor,
483 is_emoji: true,
484 };
485
486 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
487 if !raster_bounds.is_zero() {
488 let tile =
489 self.window
490 .sprite_atlas
491 .get_or_insert_with(¶ms.clone().into(), &mut || {
492 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
493 Ok((size, Cow::Owned(bytes)))
494 })?;
495 let bounds = Bounds {
496 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
497 size: tile.bounds.size.map(Into::into),
498 };
499 let content_mask = self.content_mask().scale(scale_factor);
500 let window = &mut *self.window;
501
502 window.scene_builder.insert(
503 &window.z_index_stack,
504 PolychromeSprite {
505 order: 0,
506 bounds,
507 corner_radii: Default::default(),
508 content_mask,
509 tile,
510 grayscale: false,
511 },
512 );
513 }
514 Ok(())
515 }
516
517 pub fn paint_svg(
518 &mut self,
519 bounds: Bounds<Pixels>,
520 path: SharedString,
521 color: Hsla,
522 ) -> Result<()> {
523 let scale_factor = self.scale_factor();
524 let bounds = bounds.scale(scale_factor);
525 // Render the SVG at twice the size to get a higher quality result.
526 let params = RenderSvgParams {
527 path,
528 size: bounds
529 .size
530 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
531 };
532
533 let tile =
534 self.window
535 .sprite_atlas
536 .get_or_insert_with(¶ms.clone().into(), &mut || {
537 let bytes = self.svg_renderer.render(¶ms)?;
538 Ok((params.size, Cow::Owned(bytes)))
539 })?;
540 let content_mask = self.content_mask().scale(scale_factor);
541
542 let window = &mut *self.window;
543 window.scene_builder.insert(
544 &window.z_index_stack,
545 MonochromeSprite {
546 order: 0,
547 bounds,
548 content_mask,
549 color,
550 tile,
551 },
552 );
553
554 Ok(())
555 }
556
557 pub fn paint_image(
558 &mut self,
559 bounds: Bounds<Pixels>,
560 corner_radii: Corners<Pixels>,
561 data: Arc<ImageData>,
562 grayscale: bool,
563 ) -> Result<()> {
564 let scale_factor = self.scale_factor();
565 let bounds = bounds.scale(scale_factor);
566 let params = RenderImageParams { image_id: data.id };
567
568 let tile = self
569 .window
570 .sprite_atlas
571 .get_or_insert_with(¶ms.clone().into(), &mut || {
572 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
573 })?;
574 let content_mask = self.content_mask().scale(scale_factor);
575 let corner_radii = corner_radii.scale(scale_factor);
576
577 let window = &mut *self.window;
578 window.scene_builder.insert(
579 &window.z_index_stack,
580 PolychromeSprite {
581 order: 0,
582 bounds,
583 content_mask,
584 corner_radii,
585 tile,
586 grayscale,
587 },
588 );
589 Ok(())
590 }
591
592 pub(crate) fn draw(&mut self) {
593 let unit_entity = self.unit_entity.clone();
594 self.update_entity(&unit_entity, |view, cx| {
595 cx.start_frame();
596
597 let mut root_view = cx.window.root_view.take().unwrap();
598
599 if let Some(element_id) = root_view.element_id() {
600 cx.with_element_state(element_id, |element_state, cx| {
601 let element_state = draw_with_element_state(&mut root_view, element_state, cx);
602 ((), element_state)
603 });
604 } else {
605 draw_with_element_state(&mut root_view, None, cx);
606 };
607
608 cx.window.root_view = Some(root_view);
609
610 let scene = cx.window.scene_builder.build();
611 cx.run_on_main(view, |_, cx| {
612 cx.window
613 .platform_window
614 .borrow_on_main_thread()
615 .draw(scene);
616 cx.window.dirty = false;
617 })
618 .detach();
619 });
620
621 fn draw_with_element_state(
622 root_view: &mut AnyView<()>,
623 element_state: Option<AnyBox>,
624 cx: &mut ViewContext<()>,
625 ) -> AnyBox {
626 let (layout_id, mut element_state) = root_view.layout(&mut (), element_state, cx);
627 let available_space = cx.window.content_size.map(Into::into);
628 cx.window
629 .layout_engine
630 .compute_layout(layout_id, available_space);
631 let bounds = cx.window.layout_engine.layout_bounds(layout_id);
632 root_view.paint(bounds, &mut (), &mut element_state, cx);
633 element_state
634 }
635 }
636
637 fn start_frame(&mut self) {
638 // Make the current element states the previous, and then clear the current.
639 // The empty element states map will be populated for any element states we
640 // reference during the upcoming frame.
641 let window = &mut *self.window;
642 mem::swap(&mut window.element_states, &mut window.prev_element_states);
643 self.window.element_states.clear();
644
645 // Clear mouse event listeners, because elements add new element listeners
646 // when the upcoming frame is painted.
647 self.window
648 .mouse_event_handlers
649 .values_mut()
650 .for_each(Vec::clear);
651 }
652
653 fn dispatch_event(&mut self, event: Event) -> bool {
654 if let Some(any_mouse_event) = event.mouse_event() {
655 if let Some(MouseMoveEvent { position, .. }) = any_mouse_event.downcast_ref() {
656 self.window.mouse_position = *position;
657 }
658
659 if let Some(mut handlers) = self
660 .window
661 .mouse_event_handlers
662 .remove(&any_mouse_event.type_id())
663 {
664 // Because handlers may add other handlers, we sort every time.
665 handlers.sort_by(|(a, _), (b, _)| a.cmp(b));
666
667 // Handlers may set this to false by calling `stop_propagation`
668 self.window.propagate_event = true;
669
670 // Capture phase, events bubble from back to front. Handlers for this phase are used for
671 // special purposes, such as detecting events outside of a given Bounds.
672 for (_, handler) in &handlers {
673 handler(any_mouse_event, DispatchPhase::Capture, self);
674 if !self.window.propagate_event {
675 break;
676 }
677 }
678
679 // Bubble phase, where most normal handlers do their work.
680 if self.window.propagate_event {
681 for (_, handler) in handlers.iter().rev() {
682 handler(any_mouse_event, DispatchPhase::Bubble, self);
683 if !self.window.propagate_event {
684 break;
685 }
686 }
687 }
688
689 // Just in case any handlers added new handlers, which is weird, but possible.
690 handlers.extend(
691 self.window
692 .mouse_event_handlers
693 .get_mut(&any_mouse_event.type_id())
694 .into_iter()
695 .flat_map(|handlers| handlers.drain(..)),
696 );
697 self.window
698 .mouse_event_handlers
699 .insert(any_mouse_event.type_id(), handlers);
700 }
701 }
702
703 true
704 }
705}
706
707impl Context for WindowContext<'_, '_> {
708 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
709 type Result<T> = T;
710
711 fn entity<T: Send + Sync + 'static>(
712 &mut self,
713 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
714 ) -> Handle<T> {
715 let slot = self.app.entities.reserve();
716 let entity = build_entity(&mut ViewContext::mutable(
717 &mut *self.app,
718 &mut self.window,
719 slot.id,
720 ));
721 self.entities.insert(slot, entity)
722 }
723
724 fn update_entity<T: Send + Sync + 'static, R>(
725 &mut self,
726 handle: &Handle<T>,
727 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
728 ) -> R {
729 let mut entity = self.entities.lease(handle);
730 let result = update(
731 &mut *entity,
732 &mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.id),
733 );
734 self.entities.end_lease(entity);
735 result
736 }
737}
738
739impl<'a, 'w> std::ops::Deref for WindowContext<'a, 'w> {
740 type Target = AppContext;
741
742 fn deref(&self) -> &Self::Target {
743 &self.app
744 }
745}
746
747impl<'a, 'w> std::ops::DerefMut for WindowContext<'a, 'w> {
748 fn deref_mut(&mut self) -> &mut Self::Target {
749 &mut self.app
750 }
751}
752
753impl BorrowAppContext for WindowContext<'_, '_> {
754 fn app_mut(&mut self) -> &mut AppContext {
755 &mut *self.app
756 }
757}
758
759pub trait BorrowWindow: BorrowAppContext {
760 fn window(&self) -> &Window;
761 fn window_mut(&mut self) -> &mut Window;
762
763 fn with_element_id<R>(
764 &mut self,
765 id: impl Into<ElementId>,
766 f: impl FnOnce(&mut Self) -> R,
767 ) -> R {
768 self.window_mut().element_id_stack.push(id.into());
769 let result = f(self);
770 self.window_mut().element_id_stack.pop();
771 result
772 }
773
774 fn with_content_mask<R>(
775 &mut self,
776 mask: ContentMask<Pixels>,
777 f: impl FnOnce(&mut Self) -> R,
778 ) -> R {
779 let mask = mask.intersect(&self.content_mask());
780 self.window_mut().content_mask_stack.push(mask);
781 let result = f(self);
782 self.window_mut().content_mask_stack.pop();
783 result
784 }
785
786 fn with_element_state<S: 'static + Send + Sync, R>(
787 &mut self,
788 id: ElementId,
789 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
790 ) -> R {
791 self.window_mut().element_id_stack.push(id);
792 let global_id = self.window_mut().element_id_stack.clone();
793
794 if let Some(any) = self
795 .window_mut()
796 .element_states
797 .remove(&global_id)
798 .or_else(|| self.window_mut().prev_element_states.remove(&global_id))
799 {
800 // Using the extra inner option to avoid needing to reallocate a new box.
801 let mut state_box = any
802 .downcast::<Option<S>>()
803 .expect("invalid element state type for id");
804 let state = state_box
805 .take()
806 .expect("element state is already on the stack");
807 let (result, state) = f(Some(state), self);
808 state_box.replace(state);
809 self.window_mut()
810 .element_states
811 .insert(global_id, state_box);
812 result
813 } else {
814 let (result, state) = f(None, self);
815 self.window_mut()
816 .element_states
817 .insert(global_id, Box::new(Some(state)));
818 result
819 }
820 }
821
822 fn content_mask(&self) -> ContentMask<Pixels> {
823 self.window()
824 .content_mask_stack
825 .last()
826 .cloned()
827 .unwrap_or_else(|| ContentMask {
828 bounds: Bounds {
829 origin: Point::default(),
830 size: self.window().content_size,
831 },
832 })
833 }
834
835 fn rem_size(&self) -> Pixels {
836 self.window().rem_size
837 }
838}
839
840impl BorrowWindow for WindowContext<'_, '_> {
841 fn window(&self) -> &Window {
842 &*self.window
843 }
844
845 fn window_mut(&mut self) -> &mut Window {
846 &mut *self.window
847 }
848}
849
850pub struct ViewContext<'a, 'w, S> {
851 window_cx: WindowContext<'a, 'w>,
852 entity_type: PhantomData<S>,
853 entity_id: EntityId,
854}
855
856impl<S> BorrowAppContext for ViewContext<'_, '_, S> {
857 fn app_mut(&mut self) -> &mut AppContext {
858 &mut *self.window_cx.app
859 }
860}
861
862impl<S> BorrowWindow for ViewContext<'_, '_, S> {
863 fn window(&self) -> &Window {
864 &self.window_cx.window
865 }
866
867 fn window_mut(&mut self) -> &mut Window {
868 &mut *self.window_cx.window
869 }
870}
871
872impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
873 fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self {
874 Self {
875 window_cx: WindowContext::mutable(app, window),
876 entity_id,
877 entity_type: PhantomData,
878 }
879 }
880
881 pub fn handle(&self) -> WeakHandle<S> {
882 self.entities.weak_handle(self.entity_id)
883 }
884
885 pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
886 self.window.z_index_stack.push(order);
887 let result = f(self);
888 self.window.z_index_stack.pop();
889 result
890 }
891
892 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut S, &mut ViewContext<S>) + Send + 'static) {
893 let entity = self.handle();
894 self.window_cx.on_next_frame(move |cx| {
895 entity.update(cx, f).ok();
896 });
897 }
898
899 pub fn observe<E: Send + Sync + 'static>(
900 &mut self,
901 handle: &Handle<E>,
902 on_notify: impl Fn(&mut S, Handle<E>, &mut ViewContext<'_, '_, S>) + Send + Sync + 'static,
903 ) {
904 let this = self.handle();
905 let handle = handle.downgrade();
906 let window_handle = self.window.handle;
907 self.app
908 .observers
909 .entry(handle.id)
910 .or_default()
911 .push(Arc::new(move |cx| {
912 cx.update_window(window_handle.id, |cx| {
913 if let Some(handle) = handle.upgrade(cx) {
914 this.update(cx, |this, cx| on_notify(this, handle, cx))
915 .is_ok()
916 } else {
917 false
918 }
919 })
920 .unwrap_or(false)
921 }));
922 }
923
924 pub fn notify(&mut self) {
925 self.window_cx.notify();
926 self.window_cx
927 .app
928 .pending_effects
929 .push_back(Effect::Notify(self.entity_id));
930 }
931
932 pub fn run_on_main<R>(
933 &mut self,
934 view: &mut S,
935 f: impl FnOnce(&mut S, &mut MainThread<ViewContext<'_, '_, S>>) -> R + Send + 'static,
936 ) -> Task<Result<R>>
937 where
938 R: Send + 'static,
939 {
940 if self.executor.is_main_thread() {
941 let cx = unsafe { mem::transmute::<&mut Self, &mut MainThread<Self>>(self) };
942 Task::ready(Ok(f(view, cx)))
943 } else {
944 let handle = self.handle().upgrade(self).unwrap();
945 self.window_cx.run_on_main(move |cx| handle.update(cx, f))
946 }
947 }
948
949 pub fn spawn<Fut, R>(
950 &mut self,
951 f: impl FnOnce(WeakHandle<S>, AsyncWindowContext) -> Fut + Send + 'static,
952 ) -> Task<R>
953 where
954 R: Send + 'static,
955 Fut: Future<Output = R> + Send + 'static,
956 {
957 let handle = self.handle();
958 self.window_cx.spawn(move |_, cx| {
959 let result = f(handle, cx);
960 async move { result.await }
961 })
962 }
963
964 pub fn on_mouse_event<Event: 'static>(
965 &mut self,
966 handler: impl Fn(&mut S, &Event, DispatchPhase, &mut ViewContext<S>) + Send + Sync + 'static,
967 ) {
968 let handle = self.handle().upgrade(self).unwrap();
969 self.window_cx.on_mouse_event(move |event, phase, cx| {
970 handle.update(cx, |view, cx| {
971 handler(view, event, phase, cx);
972 })
973 });
974 }
975}
976
977impl<'a, 'w, S> Context for ViewContext<'a, 'w, S> {
978 type EntityContext<'b, 'c, U: 'static + Send + Sync> = ViewContext<'b, 'c, U>;
979 type Result<U> = U;
980
981 fn entity<T2: Send + Sync + 'static>(
982 &mut self,
983 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T2>) -> T2,
984 ) -> Handle<T2> {
985 self.window_cx.entity(build_entity)
986 }
987
988 fn update_entity<U: Send + Sync + 'static, R>(
989 &mut self,
990 handle: &Handle<U>,
991 update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
992 ) -> R {
993 self.window_cx.update_entity(handle, update)
994 }
995}
996
997impl<'a, 'w, S: 'static> std::ops::Deref for ViewContext<'a, 'w, S> {
998 type Target = WindowContext<'a, 'w>;
999
1000 fn deref(&self) -> &Self::Target {
1001 &self.window_cx
1002 }
1003}
1004
1005impl<'a, 'w, S: 'static> std::ops::DerefMut for ViewContext<'a, 'w, S> {
1006 fn deref_mut(&mut self) -> &mut Self::Target {
1007 &mut self.window_cx
1008 }
1009}
1010
1011// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
1012slotmap::new_key_type! { pub struct WindowId; }
1013
1014#[derive(PartialEq, Eq)]
1015pub struct WindowHandle<S> {
1016 id: WindowId,
1017 state_type: PhantomData<S>,
1018}
1019
1020impl<S> Copy for WindowHandle<S> {}
1021
1022impl<S> Clone for WindowHandle<S> {
1023 fn clone(&self) -> Self {
1024 WindowHandle {
1025 id: self.id,
1026 state_type: PhantomData,
1027 }
1028 }
1029}
1030
1031impl<S> WindowHandle<S> {
1032 pub fn new(id: WindowId) -> Self {
1033 WindowHandle {
1034 id,
1035 state_type: PhantomData,
1036 }
1037 }
1038}
1039
1040impl<S: 'static> Into<AnyWindowHandle> for WindowHandle<S> {
1041 fn into(self) -> AnyWindowHandle {
1042 AnyWindowHandle {
1043 id: self.id,
1044 state_type: TypeId::of::<S>(),
1045 }
1046 }
1047}
1048
1049#[derive(Copy, Clone, PartialEq, Eq)]
1050pub struct AnyWindowHandle {
1051 pub(crate) id: WindowId,
1052 state_type: TypeId,
1053}
1054
1055#[cfg(any(test, feature = "test"))]
1056impl From<SmallVec<[u32; 16]>> for StackingOrder {
1057 fn from(small_vec: SmallVec<[u32; 16]>) -> Self {
1058 StackingOrder(small_vec)
1059 }
1060}
1061
1062#[derive(Clone, Debug, Eq, PartialEq, Hash)]
1063pub struct ElementId(ArcCow<'static, [u8]>);