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