window.rs

  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(&params)?;
376        if !raster_bounds.is_zero() {
377            let tile =
378                self.window
379                    .sprite_atlas
380                    .get_or_insert_with(&params.clone().into(), &mut || {
381                        let (size, bytes) = self.text_system().rasterize_glyph(&params)?;
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(&params)?;
424        if !raster_bounds.is_zero() {
425            let tile =
426                self.window
427                    .sprite_atlas
428                    .get_or_insert_with(&params.clone().into(), &mut || {
429                        let (size, bytes) = self.text_system().rasterize_glyph(&params)?;
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(&params.clone().into(), &mut || {
474                    let bytes = self.svg_renderer.render(&params)?;
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(&params.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}