1use crate::{
2 image_cache::RenderImageParams, px, size, AnyView, AppContext, AsyncWindowContext,
3 AvailableSpace, BorrowAppContext, Bounds, Context, Corners, DevicePixels, DisplayId, Effect,
4 Element, EntityId, FontId, GlyphId, Handle, Hsla, ImageData, IsZero, LayoutId, MainThread,
5 MainThreadOnly, MonochromeSprite, Pixels, PlatformAtlas, PlatformWindow, Point,
6 PolychromeSprite, Reference, RenderGlyphParams, RenderSvgParams, ScaledPixels, Scene,
7 SharedString, Size, StackingOrder, Style, TaffyLayoutEngine, Task, Underline, UnderlineStyle,
8 WeakHandle, WindowOptions, SUBPIXEL_VARIANTS,
9};
10use anyhow::Result;
11use smallvec::SmallVec;
12use std::{any::TypeId, borrow::Cow, future::Future, marker::PhantomData, mem, sync::Arc};
13use util::ResultExt;
14
15pub struct AnyWindow {}
16
17pub struct Window {
18 handle: AnyWindowHandle,
19 platform_window: MainThreadOnly<Box<dyn PlatformWindow>>,
20 pub(crate) display_id: DisplayId, // todo!("make private again?")
21 sprite_atlas: Arc<dyn PlatformAtlas>,
22 rem_size: Pixels,
23 content_size: Size<Pixels>,
24 layout_engine: TaffyLayoutEngine,
25 pub(crate) root_view: Option<AnyView<()>>,
26 mouse_position: Point<Pixels>,
27 current_stacking_order: StackingOrder,
28 content_mask_stack: Vec<ContentMask>,
29 pub(crate) scene: Scene,
30 pub(crate) dirty: bool,
31}
32
33impl Window {
34 pub fn new(
35 handle: AnyWindowHandle,
36 options: WindowOptions,
37 cx: &mut MainThread<AppContext>,
38 ) -> Self {
39 let platform_window = cx.platform().open_window(handle, options);
40 let display_id = platform_window.display().id();
41 let sprite_atlas = platform_window.sprite_atlas();
42 let mouse_position = platform_window.mouse_position();
43 let content_size = platform_window.content_size();
44 let scale_factor = platform_window.scale_factor();
45 platform_window.on_resize(Box::new({
46 let handle = handle;
47 let cx = cx.to_async();
48 move |content_size, scale_factor| {
49 cx.update_window(handle, |cx| {
50 cx.window.scene = Scene::new(scale_factor);
51 cx.window.content_size = content_size;
52 cx.window.display_id = cx
53 .window
54 .platform_window
55 .borrow_on_main_thread()
56 .display()
57 .id();
58 cx.window.dirty = true;
59 })
60 .log_err();
61 }
62 }));
63
64 let platform_window = MainThreadOnly::new(Arc::new(platform_window), cx.executor.clone());
65
66 Window {
67 handle,
68 platform_window,
69 display_id,
70 sprite_atlas,
71 rem_size: px(16.),
72 content_size,
73 layout_engine: TaffyLayoutEngine::new(),
74 root_view: None,
75 mouse_position,
76 current_stacking_order: SmallVec::new(),
77 content_mask_stack: Vec::new(),
78 scene: Scene::new(scale_factor),
79 dirty: true,
80 }
81 }
82}
83
84#[derive(Clone, Debug)]
85pub struct ContentMask {
86 pub bounds: Bounds<Pixels>,
87}
88
89impl ContentMask {
90 pub fn scale(&self, factor: f32) -> ScaledContentMask {
91 ScaledContentMask {
92 bounds: self.bounds.scale(factor),
93 }
94 }
95
96 pub fn intersect(&self, other: &Self) -> Self {
97 let bounds = self.bounds.intersect(&other.bounds);
98 ContentMask { bounds }
99 }
100}
101
102#[derive(Default, Clone, Debug, PartialEq, Eq)]
103#[repr(C)]
104pub struct ScaledContentMask {
105 bounds: Bounds<ScaledPixels>,
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.scene.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 scene(&mut self) -> &mut Scene {
249 &mut self.window.scene
250 }
251
252 pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
253 self.window.current_stacking_order.push(order);
254 let result = f(self);
255 self.window.current_stacking_order.pop();
256 result
257 }
258
259 pub fn current_stacking_order(&self) -> StackingOrder {
260 self.window.current_stacking_order.clone()
261 }
262
263 pub fn paint_underline(
264 &mut self,
265 origin: Point<Pixels>,
266 width: Pixels,
267 style: &UnderlineStyle,
268 ) -> Result<()> {
269 let scale_factor = self.scale_factor();
270 let height = if style.wavy {
271 style.thickness * 3.
272 } else {
273 style.thickness
274 };
275 let bounds = Bounds {
276 origin,
277 size: size(width, height),
278 };
279 let content_mask = self.content_mask();
280 let layer_id = self.current_stacking_order();
281 self.window.scene.insert(
282 layer_id,
283 Underline {
284 order: 0,
285 bounds: bounds.scale(scale_factor),
286 content_mask: content_mask.scale(scale_factor),
287 thickness: style.thickness.scale(scale_factor),
288 color: style.color.unwrap_or_default(),
289 wavy: style.wavy,
290 },
291 );
292 Ok(())
293 }
294
295 pub fn paint_glyph(
296 &mut self,
297 origin: Point<Pixels>,
298 font_id: FontId,
299 glyph_id: GlyphId,
300 font_size: Pixels,
301 color: Hsla,
302 ) -> Result<()> {
303 let scale_factor = self.scale_factor();
304 let glyph_origin = origin.scale(scale_factor);
305 let subpixel_variant = Point {
306 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
307 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
308 };
309 let params = RenderGlyphParams {
310 font_id,
311 glyph_id,
312 font_size,
313 subpixel_variant,
314 scale_factor,
315 is_emoji: false,
316 };
317
318 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
319 if !raster_bounds.is_zero() {
320 let layer_id = self.current_stacking_order();
321 let tile =
322 self.window
323 .sprite_atlas
324 .get_or_insert_with(¶ms.clone().into(), &mut || {
325 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
326 Ok((size, Cow::Owned(bytes)))
327 })?;
328 let bounds = Bounds {
329 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
330 size: tile.bounds.size.map(Into::into),
331 };
332 let content_mask = self.content_mask().scale(scale_factor);
333
334 self.window.scene.insert(
335 layer_id,
336 MonochromeSprite {
337 order: 0,
338 bounds,
339 content_mask,
340 color,
341 tile,
342 },
343 );
344 }
345 Ok(())
346 }
347
348 pub fn paint_emoji(
349 &mut self,
350 origin: Point<Pixels>,
351 font_id: FontId,
352 glyph_id: GlyphId,
353 font_size: Pixels,
354 ) -> Result<()> {
355 let scale_factor = self.scale_factor();
356 let glyph_origin = origin.scale(scale_factor);
357 let params = RenderGlyphParams {
358 font_id,
359 glyph_id,
360 font_size,
361 // We don't render emojis with subpixel variants.
362 subpixel_variant: Default::default(),
363 scale_factor,
364 is_emoji: true,
365 };
366
367 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
368 if !raster_bounds.is_zero() {
369 let layer_id = self.current_stacking_order();
370 let tile =
371 self.window
372 .sprite_atlas
373 .get_or_insert_with(¶ms.clone().into(), &mut || {
374 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
375 Ok((size, Cow::Owned(bytes)))
376 })?;
377 let bounds = Bounds {
378 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
379 size: tile.bounds.size.map(Into::into),
380 };
381 let content_mask = self.content_mask().scale(scale_factor);
382
383 self.window.scene.insert(
384 layer_id,
385 PolychromeSprite {
386 order: 0,
387 bounds,
388 corner_radii: Default::default(),
389 content_mask,
390 tile,
391 grayscale: false,
392 },
393 );
394 }
395 Ok(())
396 }
397
398 pub fn paint_svg(
399 &mut self,
400 bounds: Bounds<Pixels>,
401 path: SharedString,
402 color: Hsla,
403 ) -> Result<()> {
404 let scale_factor = self.scale_factor();
405 let bounds = bounds.scale(scale_factor);
406 // Render the SVG at twice the size to get a higher quality result.
407 let params = RenderSvgParams {
408 path,
409 size: bounds
410 .size
411 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
412 };
413
414 let layer_id = self.current_stacking_order();
415 let tile =
416 self.window
417 .sprite_atlas
418 .get_or_insert_with(¶ms.clone().into(), &mut || {
419 let bytes = self.svg_renderer.render(¶ms)?;
420 Ok((params.size, Cow::Owned(bytes)))
421 })?;
422 let content_mask = self.content_mask().scale(scale_factor);
423
424 self.window.scene.insert(
425 layer_id,
426 MonochromeSprite {
427 order: 0,
428 bounds,
429 content_mask,
430 color,
431 tile,
432 },
433 );
434
435 Ok(())
436 }
437
438 pub fn paint_image(
439 &mut self,
440 bounds: Bounds<Pixels>,
441 corner_radii: Corners<Pixels>,
442 data: Arc<ImageData>,
443 grayscale: bool,
444 ) -> Result<()> {
445 let scale_factor = self.scale_factor();
446 let bounds = bounds.scale(scale_factor);
447 let params = RenderImageParams { image_id: data.id };
448
449 let order = self.current_stacking_order();
450 let tile = self
451 .window
452 .sprite_atlas
453 .get_or_insert_with(¶ms.clone().into(), &mut || {
454 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
455 })?;
456 let content_mask = self.content_mask().scale(scale_factor);
457 let corner_radii = corner_radii.scale(scale_factor);
458
459 self.window.scene.insert(
460 order,
461 PolychromeSprite {
462 order: 0,
463 bounds,
464 content_mask,
465 corner_radii,
466 tile,
467 grayscale,
468 },
469 );
470
471 Ok(())
472 }
473
474 pub(crate) fn draw(&mut self) -> Result<()> {
475 let unit_entity = self.unit_entity.clone();
476 self.update_entity(&unit_entity, |view, cx| {
477 let mut root_view = cx.window.root_view.take().unwrap();
478 let (root_layout_id, mut frame_state) = root_view.layout(&mut (), cx)?;
479 let available_space = cx.window.content_size.map(Into::into);
480
481 cx.window
482 .layout_engine
483 .compute_layout(root_layout_id, available_space)?;
484 let layout = cx.window.layout_engine.layout_bounds(root_layout_id)?;
485
486 root_view.paint(layout, &mut (), &mut frame_state, cx)?;
487 cx.window.root_view = Some(root_view);
488 let scene = cx.window.scene.take();
489
490 cx.run_on_main(view, |_, cx| {
491 cx.window
492 .platform_window
493 .borrow_on_main_thread()
494 .draw(scene);
495 cx.window.dirty = false;
496 })
497 .detach();
498
499 Ok(())
500 })
501 }
502}
503
504impl Context for WindowContext<'_, '_> {
505 type EntityContext<'a, 'w, T: 'static + Send + Sync> = ViewContext<'a, 'w, T>;
506 type Result<T> = T;
507
508 fn entity<T: Send + Sync + 'static>(
509 &mut self,
510 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T>) -> T,
511 ) -> Handle<T> {
512 let slot = self.app.entities.reserve();
513 let entity = build_entity(&mut ViewContext::mutable(
514 &mut *self.app,
515 &mut self.window,
516 slot.id,
517 ));
518 self.entities.insert(slot, entity)
519 }
520
521 fn update_entity<T: Send + Sync + 'static, R>(
522 &mut self,
523 handle: &Handle<T>,
524 update: impl FnOnce(&mut T, &mut Self::EntityContext<'_, '_, T>) -> R,
525 ) -> R {
526 let mut entity = self.entities.lease(handle);
527 let result = update(
528 &mut *entity,
529 &mut ViewContext::mutable(&mut *self.app, &mut *self.window, handle.id),
530 );
531 self.entities.end_lease(entity);
532 result
533 }
534}
535
536impl<'a, 'w> std::ops::Deref for WindowContext<'a, 'w> {
537 type Target = AppContext;
538
539 fn deref(&self) -> &Self::Target {
540 &self.app
541 }
542}
543
544impl<'a, 'w> std::ops::DerefMut for WindowContext<'a, 'w> {
545 fn deref_mut(&mut self) -> &mut Self::Target {
546 &mut self.app
547 }
548}
549
550impl BorrowAppContext for WindowContext<'_, '_> {
551 fn app_mut(&mut self) -> &mut AppContext {
552 &mut *self.app
553 }
554}
555
556pub trait BorrowWindow: BorrowAppContext {
557 fn window(&self) -> &Window;
558 fn window_mut(&mut self) -> &mut Window;
559
560 fn with_content_mask<R>(&mut self, mask: ContentMask, f: impl FnOnce(&mut Self) -> R) -> R {
561 let mask = mask.intersect(&self.content_mask());
562 self.window_mut().content_mask_stack.push(mask);
563 let result = f(self);
564 self.window_mut().content_mask_stack.pop();
565 result
566 }
567
568 fn content_mask(&self) -> ContentMask {
569 self.window()
570 .content_mask_stack
571 .last()
572 .cloned()
573 .unwrap_or_else(|| ContentMask {
574 bounds: Bounds {
575 origin: Point::default(),
576 size: self.window().content_size,
577 },
578 })
579 }
580
581 fn rem_size(&self) -> Pixels {
582 self.window().rem_size
583 }
584}
585
586impl BorrowWindow for WindowContext<'_, '_> {
587 fn window(&self) -> &Window {
588 &*self.window
589 }
590
591 fn window_mut(&mut self) -> &mut Window {
592 &mut *self.window
593 }
594}
595
596pub struct ViewContext<'a, 'w, S> {
597 window_cx: WindowContext<'a, 'w>,
598 entity_type: PhantomData<S>,
599 entity_id: EntityId,
600}
601
602impl<S> BorrowAppContext for ViewContext<'_, '_, S> {
603 fn app_mut(&mut self) -> &mut AppContext {
604 &mut *self.window_cx.app
605 }
606
607 fn with_text_style<F, R>(&mut self, style: crate::TextStyleRefinement, f: F) -> R
608 where
609 F: FnOnce(&mut Self) -> R,
610 {
611 self.window_cx.app.push_text_style(style);
612 let result = f(self);
613 self.window_cx.app.pop_text_style();
614 result
615 }
616
617 fn with_state<T: Send + Sync + 'static, F, R>(&mut self, state: T, f: F) -> R
618 where
619 F: FnOnce(&mut Self) -> R,
620 {
621 self.window_cx.app.push_state(state);
622 let result = f(self);
623 self.window_cx.app.pop_state::<T>();
624 result
625 }
626}
627
628impl<S> BorrowWindow for ViewContext<'_, '_, S> {
629 fn window(&self) -> &Window {
630 &self.window_cx.window
631 }
632
633 fn window_mut(&mut self) -> &mut Window {
634 &mut *self.window_cx.window
635 }
636}
637
638impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
639 fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self {
640 Self {
641 window_cx: WindowContext::mutable(app, window),
642 entity_id,
643 entity_type: PhantomData,
644 }
645 }
646
647 pub fn handle(&self) -> WeakHandle<S> {
648 self.entities.weak_handle(self.entity_id)
649 }
650
651 pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
652 self.window.current_stacking_order.push(order);
653 let result = f(self);
654 self.window.current_stacking_order.pop();
655 result
656 }
657
658 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut S, &mut ViewContext<S>) + Send + 'static) {
659 let entity = self.handle();
660 self.window_cx.on_next_frame(move |cx| {
661 entity.update(cx, f).ok();
662 });
663 }
664
665 pub fn observe<E: Send + Sync + 'static>(
666 &mut self,
667 handle: &Handle<E>,
668 on_notify: impl Fn(&mut S, Handle<E>, &mut ViewContext<'_, '_, S>) + Send + Sync + 'static,
669 ) {
670 let this = self.handle();
671 let handle = handle.downgrade();
672 let window_handle = self.window.handle;
673 self.app
674 .observers
675 .entry(handle.id)
676 .or_default()
677 .push(Arc::new(move |cx| {
678 cx.update_window(window_handle.id, |cx| {
679 if let Some(handle) = handle.upgrade(cx) {
680 this.update(cx, |this, cx| on_notify(this, handle, cx))
681 .is_ok()
682 } else {
683 false
684 }
685 })
686 .unwrap_or(false)
687 }));
688 }
689
690 pub fn notify(&mut self) {
691 self.window_cx.notify();
692 self.window_cx
693 .app
694 .pending_effects
695 .push_back(Effect::Notify(self.entity_id));
696 }
697
698 pub fn run_on_main<R>(
699 &mut self,
700 view: &mut S,
701 f: impl FnOnce(&mut S, &mut MainThread<ViewContext<'_, '_, S>>) -> R + Send + 'static,
702 ) -> Task<Result<R>>
703 where
704 R: Send + 'static,
705 {
706 if self.executor.is_main_thread() {
707 let cx = unsafe { mem::transmute::<&mut Self, &mut MainThread<Self>>(self) };
708 Task::ready(Ok(f(view, cx)))
709 } else {
710 let handle = self.handle().upgrade(self).unwrap();
711 self.window_cx.run_on_main(move |cx| handle.update(cx, f))
712 }
713 }
714
715 pub fn spawn<Fut, R>(
716 &mut self,
717 f: impl FnOnce(WeakHandle<S>, AsyncWindowContext) -> Fut + Send + 'static,
718 ) -> Task<R>
719 where
720 R: Send + 'static,
721 Fut: Future<Output = R> + Send + 'static,
722 {
723 let handle = self.handle();
724 self.window_cx.spawn(move |_, cx| {
725 let result = f(handle, cx);
726 async move { result.await }
727 })
728 }
729
730 pub(crate) fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
731 let entity_id = self.unit_entity.id;
732 let mut cx = ViewContext::mutable(
733 &mut *self.window_cx.app,
734 &mut *self.window_cx.window,
735 entity_id,
736 );
737 f(&mut cx)
738 }
739}
740
741impl<'a, 'w, S> Context for ViewContext<'a, 'w, S> {
742 type EntityContext<'b, 'c, U: 'static + Send + Sync> = ViewContext<'b, 'c, U>;
743 type Result<U> = U;
744
745 fn entity<T2: Send + Sync + 'static>(
746 &mut self,
747 build_entity: impl FnOnce(&mut Self::EntityContext<'_, '_, T2>) -> T2,
748 ) -> Handle<T2> {
749 self.window_cx.entity(build_entity)
750 }
751
752 fn update_entity<U: Send + Sync + 'static, R>(
753 &mut self,
754 handle: &Handle<U>,
755 update: impl FnOnce(&mut U, &mut Self::EntityContext<'_, '_, U>) -> R,
756 ) -> R {
757 self.window_cx.update_entity(handle, update)
758 }
759}
760
761impl<'a, 'w, S: 'static> std::ops::Deref for ViewContext<'a, 'w, S> {
762 type Target = WindowContext<'a, 'w>;
763
764 fn deref(&self) -> &Self::Target {
765 &self.window_cx
766 }
767}
768
769impl<'a, 'w, S: 'static> std::ops::DerefMut for ViewContext<'a, 'w, S> {
770 fn deref_mut(&mut self) -> &mut Self::Target {
771 &mut self.window_cx
772 }
773}
774
775// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
776slotmap::new_key_type! { pub struct WindowId; }
777
778#[derive(PartialEq, Eq)]
779pub struct WindowHandle<S> {
780 id: WindowId,
781 state_type: PhantomData<S>,
782}
783
784impl<S> Copy for WindowHandle<S> {}
785
786impl<S> Clone for WindowHandle<S> {
787 fn clone(&self) -> Self {
788 WindowHandle {
789 id: self.id,
790 state_type: PhantomData,
791 }
792 }
793}
794
795impl<S> WindowHandle<S> {
796 pub fn new(id: WindowId) -> Self {
797 WindowHandle {
798 id,
799 state_type: PhantomData,
800 }
801 }
802}
803
804impl<S: 'static> Into<AnyWindowHandle> for WindowHandle<S> {
805 fn into(self) -> AnyWindowHandle {
806 AnyWindowHandle {
807 id: self.id,
808 state_type: TypeId::of::<S>(),
809 }
810 }
811}
812
813#[derive(Copy, Clone, PartialEq, Eq)]
814pub struct AnyWindowHandle {
815 pub(crate) id: WindowId,
816 state_type: TypeId,
817}