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