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