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