1use crate::{
2 AnyView, AnyWindowHandle, AppContext, AsyncApp, DispatchPhase, Effect, EntityId, EventEmitter,
3 FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Reservation, SubscriberSet,
4 Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle, WindowVisibility,
5};
6use anyhow::Result;
7use futures::FutureExt;
8use std::{
9 any::{Any, TypeId},
10 borrow::{Borrow, BorrowMut},
11 future::Future,
12 ops,
13 sync::Arc,
14};
15use util::Deferred;
16
17use super::{App, AsyncWindowContext, Entity, KeystrokeEvent};
18
19pub struct Context<'a, T> {
21 app: &'a mut App,
22 entity_state: WeakEntity<T>,
23}
24
25impl<'a, T> ops::Deref for Context<'a, T> {
26 type Target = App;
27
28 fn deref(&self) -> &Self::Target {
29 self.app
30 }
31}
32
33impl<'a, T> ops::DerefMut for Context<'a, T> {
34 fn deref_mut(&mut self) -> &mut Self::Target {
35 self.app
36 }
37}
38
39impl<'a, T: 'static> Context<'a, T> {
40 pub(crate) fn new_context(app: &'a mut App, entity_state: WeakEntity<T>) -> Self {
41 Self { app, entity_state }
42 }
43
44 pub fn entity_id(&self) -> EntityId {
46 self.entity_state.entity_id
47 }
48
49 pub fn entity(&self) -> Entity<T> {
51 self.weak_entity()
52 .upgrade()
53 .expect("The entity must be alive if we have a entity context")
54 }
55
56 pub fn weak_entity(&self) -> WeakEntity<T> {
58 self.entity_state.clone()
59 }
60
61 pub fn observe<W>(
64 &mut self,
65 entity: &Entity<W>,
66 mut on_notify: impl FnMut(&mut T, Entity<W>, &mut Context<T>) + 'static,
67 ) -> Subscription
68 where
69 T: 'static,
70 W: 'static,
71 {
72 let this = self.weak_entity();
73 self.app.observe_internal(entity, move |e, cx| {
74 if let Some(this) = this.upgrade() {
75 this.update(cx, |this, cx| on_notify(this, e, cx));
76 true
77 } else {
78 false
79 }
80 })
81 }
82
83 pub fn observe_self(
85 &mut self,
86 mut on_event: impl FnMut(&mut T, &mut Context<T>) + 'static,
87 ) -> Subscription
88 where
89 T: 'static,
90 {
91 let this = self.entity();
92 self.app.observe(&this, move |this, cx| {
93 this.update(cx, |this, cx| on_event(this, cx))
94 })
95 }
96
97 pub fn subscribe<T2, Evt>(
99 &mut self,
100 entity: &Entity<T2>,
101 mut on_event: impl FnMut(&mut T, Entity<T2>, &Evt, &mut Context<T>) + 'static,
102 ) -> Subscription
103 where
104 T: 'static,
105 T2: 'static + EventEmitter<Evt>,
106 Evt: 'static,
107 {
108 let this = self.weak_entity();
109 self.app.subscribe_internal(entity, move |e, event, cx| {
110 if let Some(this) = this.upgrade() {
111 this.update(cx, |this, cx| on_event(this, e, event, cx));
112 true
113 } else {
114 false
115 }
116 })
117 }
118
119 pub fn subscribe_self<Evt>(
121 &mut self,
122 mut on_event: impl FnMut(&mut T, &Evt, &mut Context<T>) + 'static,
123 ) -> Subscription
124 where
125 T: 'static + EventEmitter<Evt>,
126 Evt: 'static,
127 {
128 let this = self.entity();
129 self.app.subscribe(&this, move |this, evt, cx| {
130 this.update(cx, |this, cx| on_event(this, evt, cx))
131 })
132 }
133
134 pub fn on_release(&self, on_release: impl FnOnce(&mut T, &mut App) + 'static) -> Subscription
136 where
137 T: 'static,
138 {
139 let (subscription, activate) = self.app.release_listeners.insert(
140 self.entity_state.entity_id,
141 Box::new(move |this, cx| {
142 let this = this.downcast_mut().expect("invalid entity type");
143 on_release(this, cx);
144 }),
145 );
146 activate();
147 subscription
148 }
149
150 pub fn observe_release<T2>(
152 &self,
153 entity: &Entity<T2>,
154 on_release: impl FnOnce(&mut T, &mut T2, &mut Context<T>) + 'static,
155 ) -> Subscription
156 where
157 T: Any,
158 T2: 'static,
159 {
160 let entity_id = entity.entity_id();
161 let this = self.weak_entity();
162 let (subscription, activate) = self.app.release_listeners.insert(
163 entity_id,
164 Box::new(move |entity, cx| {
165 let entity = entity.downcast_mut().expect("invalid entity type");
166 if let Some(this) = this.upgrade() {
167 this.update(cx, |this, cx| on_release(this, entity, cx));
168 }
169 }),
170 );
171 activate();
172 subscription
173 }
174
175 pub fn observe_global<G: 'static>(
177 &mut self,
178 mut f: impl FnMut(&mut T, &mut Context<T>) + 'static,
179 ) -> Subscription
180 where
181 T: 'static,
182 {
183 let handle = self.weak_entity();
184 let (subscription, activate) = self.global_observers.insert(
185 TypeId::of::<G>(),
186 Box::new(move |cx| handle.update(cx, |view, cx| f(view, cx)).is_ok()),
187 );
188 self.defer(move |_| activate());
189 subscription
190 }
191
192 pub fn on_app_restart(
194 &self,
195 mut on_restart: impl FnMut(&mut T, &mut App) + 'static,
196 ) -> Subscription
197 where
198 T: 'static,
199 {
200 let handle = self.weak_entity();
201 self.app.on_app_restart(move |cx| {
202 handle.update(cx, |entity, cx| on_restart(entity, cx)).ok();
203 })
204 }
205
206 pub fn on_app_quit<Fut>(
209 &self,
210 mut on_quit: impl FnMut(&mut T, &mut Context<T>) -> Fut + 'static,
211 ) -> Subscription
212 where
213 Fut: 'static + Future<Output = ()>,
214 T: 'static,
215 {
216 let handle = self.weak_entity();
217 self.app.on_app_quit(move |cx| {
218 let future = handle.update(cx, |entity, cx| on_quit(entity, cx)).ok();
219 async move {
220 if let Some(future) = future {
221 future.await;
222 }
223 }
224 .boxed_local()
225 })
226 }
227
228 pub fn notify(&mut self) {
230 self.app.notify(self.entity_state.entity_id);
231 }
232
233 #[track_caller]
237 pub fn spawn<AsyncFn, R>(&self, f: AsyncFn) -> Task<R>
238 where
239 T: 'static,
240 AsyncFn: AsyncFnOnce(WeakEntity<T>, &mut AsyncApp) -> R + 'static,
241 R: 'static,
242 {
243 let this = self.weak_entity();
244 self.app.spawn(async move |cx| f(this, cx).await)
245 }
246
247 pub fn listener<E: ?Sized>(
253 &self,
254 f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
255 ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
256 let view = self.entity().downgrade();
257 move |e: &E, window: &mut Window, cx: &mut App| {
258 view.update(cx, |view, cx| f(view, e, window, cx)).ok();
259 }
260 }
261
262 pub fn processor<E, R>(
265 &self,
266 f: impl Fn(&mut T, E, &mut Window, &mut Context<T>) -> R + 'static,
267 ) -> impl Fn(E, &mut Window, &mut App) -> R + 'static {
268 let view = self.entity();
269 move |e: E, window: &mut Window, cx: &mut App| {
270 view.update(cx, |view, cx| f(view, e, window, cx))
271 }
272 }
273
274 pub fn on_drop(
276 &self,
277 f: impl FnOnce(&mut T, &mut Context<T>) + 'static,
278 ) -> Deferred<impl FnOnce()> {
279 let this = self.weak_entity();
280 let mut cx = self.to_async();
281 util::defer(move || {
282 this.update(&mut cx, f).ok();
283 })
284 }
285
286 pub fn focus_view<W: Focusable>(&mut self, view: &Entity<W>, window: &mut Window) {
288 window.focus(&view.focus_handle(self));
289 }
290
291 pub fn on_next_frame(
293 &self,
294 window: &mut Window,
295 f: impl FnOnce(&mut T, &mut Window, &mut Context<T>) + 'static,
296 ) where
297 T: 'static,
298 {
299 let view = self.entity();
300 window.on_next_frame(move |window, cx| view.update(cx, |view, cx| f(view, window, cx)));
301 }
302
303 pub fn defer_in(
306 &mut self,
307 window: &Window,
308 f: impl FnOnce(&mut T, &mut Window, &mut Context<T>) + 'static,
309 ) {
310 let view = self.entity();
311 window.defer(self, move |window, cx| {
312 view.update(cx, |view, cx| f(view, window, cx))
313 });
314 }
315
316 pub fn observe_in<V2>(
318 &mut self,
319 observed: &Entity<V2>,
320 window: &mut Window,
321 mut on_notify: impl FnMut(&mut T, Entity<V2>, &mut Window, &mut Context<T>) + 'static,
322 ) -> Subscription
323 where
324 V2: 'static,
325 T: 'static,
326 {
327 let observed_id = observed.entity_id();
328 let observed = observed.downgrade();
329 let window_handle = window.handle;
330 let observer = self.weak_entity();
331 self.new_observer(
332 observed_id,
333 Box::new(move |cx| {
334 window_handle
335 .update(cx, |_, window, cx| {
336 if let Some((observer, observed)) =
337 observer.upgrade().zip(observed.upgrade())
338 {
339 observer.update(cx, |observer, cx| {
340 on_notify(observer, observed, window, cx);
341 });
342 true
343 } else {
344 false
345 }
346 })
347 .unwrap_or(false)
348 }),
349 )
350 }
351
352 pub fn subscribe_in<Emitter, Evt>(
356 &mut self,
357 emitter: &Entity<Emitter>,
358 window: &Window,
359 mut on_event: impl FnMut(&mut T, &Entity<Emitter>, &Evt, &mut Window, &mut Context<T>) + 'static,
360 ) -> Subscription
361 where
362 Emitter: EventEmitter<Evt>,
363 Evt: 'static,
364 {
365 let emitter = emitter.downgrade();
366 let window_handle = window.handle;
367 let subscriber = self.weak_entity();
368 self.new_subscription(
369 emitter.entity_id(),
370 (
371 TypeId::of::<Evt>(),
372 Box::new(move |event, cx| {
373 window_handle
374 .update(cx, |_, window, cx| {
375 if let Some((subscriber, emitter)) =
376 subscriber.upgrade().zip(emitter.upgrade())
377 {
378 let event = event.downcast_ref().expect("invalid event type");
379 subscriber.update(cx, |subscriber, cx| {
380 on_event(subscriber, &emitter, event, window, cx);
381 });
382 true
383 } else {
384 false
385 }
386 })
387 .unwrap_or(false)
388 }),
389 ),
390 )
391 }
392
393 pub fn on_release_in(
398 &mut self,
399 window: &Window,
400 on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
401 ) -> Subscription {
402 let entity = self.entity();
403 self.app.observe_release_in(&entity, window, on_release)
404 }
405
406 pub fn observe_release_in<T2>(
408 &self,
409 observed: &Entity<T2>,
410 window: &Window,
411 mut on_release: impl FnMut(&mut T, &mut T2, &mut Window, &mut Context<T>) + 'static,
412 ) -> Subscription
413 where
414 T: 'static,
415 T2: 'static,
416 {
417 let observer = self.weak_entity();
418 self.app
419 .observe_release_in(observed, window, move |observed, window, cx| {
420 observer
421 .update(cx, |observer, cx| {
422 on_release(observer, observed, window, cx)
423 })
424 .ok();
425 })
426 }
427
428 pub fn observe_window_bounds(
430 &self,
431 window: &mut Window,
432 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
433 ) -> Subscription {
434 let view = self.weak_entity();
435 let (subscription, activate) = window.bounds_observers.insert(
436 (),
437 Box::new(move |window, cx| {
438 view.update(cx, |view, cx| callback(view, window, cx))
439 .is_ok()
440 }),
441 );
442 activate();
443 subscription
444 }
445
446 pub fn observe_window_activation(
448 &self,
449 window: &mut Window,
450 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
451 ) -> Subscription {
452 let view = self.weak_entity();
453 let (subscription, activate) = window.activation_observers.insert(
454 (),
455 Box::new(move |window, cx| {
456 view.update(cx, |view, cx| callback(view, window, cx))
457 .is_ok()
458 }),
459 );
460 activate();
461 subscription
462 }
463
464 pub fn observe_window_visibility(
467 &self,
468 window: &mut Window,
469 mut callback: impl FnMut(&mut T, WindowVisibility, &mut Window, &mut Context<T>) + 'static,
470 ) -> Subscription {
471 let view = self.weak_entity();
472 let (subscription, activate) = window.visibility_observers.insert(
473 (),
474 Box::new(move |visibility, window, cx| {
475 view.update(cx, |view, cx| callback(view, visibility, window, cx))
476 .is_ok()
477 }),
478 );
479 activate();
480 subscription
481 }
482
483 pub fn observe_window_appearance(
485 &self,
486 window: &mut Window,
487 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
488 ) -> Subscription {
489 let view = self.weak_entity();
490 let (subscription, activate) = window.appearance_observers.insert(
491 (),
492 Box::new(move |window, cx| {
493 view.update(cx, |view, cx| callback(view, window, cx))
494 .is_ok()
495 }),
496 );
497 activate();
498 subscription
499 }
500
501 pub fn observe_keystrokes(
503 &mut self,
504 mut f: impl FnMut(&mut T, &KeystrokeEvent, &mut Window, &mut Context<T>) + 'static,
505 ) -> Subscription {
506 fn inner(
507 keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
508 handler: KeystrokeObserver,
509 ) -> Subscription {
510 let (subscription, activate) = keystroke_observers.insert((), handler);
511 activate();
512 subscription
513 }
514
515 let view = self.weak_entity();
516 inner(
517 &self.keystroke_observers,
518 Box::new(move |event, window, cx| {
519 if let Some(view) = view.upgrade() {
520 view.update(cx, |view, cx| f(view, event, window, cx));
521 true
522 } else {
523 false
524 }
525 }),
526 )
527 }
528
529 pub fn observe_pending_input(
531 &self,
532 window: &mut Window,
533 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
534 ) -> Subscription {
535 let view = self.weak_entity();
536 let (subscription, activate) = window.pending_input_observers.insert(
537 (),
538 Box::new(move |window, cx| {
539 view.update(cx, |view, cx| callback(view, window, cx))
540 .is_ok()
541 }),
542 );
543 activate();
544 subscription
545 }
546
547 pub fn on_focus(
550 &mut self,
551 handle: &FocusHandle,
552 window: &mut Window,
553 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
554 ) -> Subscription {
555 let view = self.weak_entity();
556 let focus_id = handle.id;
557 let (subscription, activate) =
558 window.new_focus_listener(Box::new(move |event, window, cx| {
559 view.update(cx, |view, cx| {
560 if event.previous_focus_path.last() != Some(&focus_id)
561 && event.current_focus_path.last() == Some(&focus_id)
562 {
563 listener(view, window, cx)
564 }
565 })
566 .is_ok()
567 }));
568 self.defer(|_| activate());
569 subscription
570 }
571
572 pub fn on_focus_in(
576 &mut self,
577 handle: &FocusHandle,
578 window: &mut Window,
579 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
580 ) -> Subscription {
581 let view = self.weak_entity();
582 let focus_id = handle.id;
583 let (subscription, activate) =
584 window.new_focus_listener(Box::new(move |event, window, cx| {
585 view.update(cx, |view, cx| {
586 if event.is_focus_in(focus_id) {
587 listener(view, window, cx)
588 }
589 })
590 .is_ok()
591 }));
592 self.defer(|_| activate());
593 subscription
594 }
595
596 pub fn on_blur(
599 &mut self,
600 handle: &FocusHandle,
601 window: &mut Window,
602 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
603 ) -> Subscription {
604 let view = self.weak_entity();
605 let focus_id = handle.id;
606 let (subscription, activate) =
607 window.new_focus_listener(Box::new(move |event, window, cx| {
608 view.update(cx, |view, cx| {
609 if event.previous_focus_path.last() == Some(&focus_id)
610 && event.current_focus_path.last() != Some(&focus_id)
611 {
612 listener(view, window, cx)
613 }
614 })
615 .is_ok()
616 }));
617 self.defer(|_| activate());
618 subscription
619 }
620
621 pub fn on_focus_lost(
626 &mut self,
627 window: &mut Window,
628 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
629 ) -> Subscription {
630 let view = self.weak_entity();
631 let (subscription, activate) = window.focus_lost_listeners.insert(
632 (),
633 Box::new(move |window, cx| {
634 view.update(cx, |view, cx| listener(view, window, cx))
635 .is_ok()
636 }),
637 );
638 self.defer(|_| activate());
639 subscription
640 }
641
642 pub fn on_focus_out(
645 &mut self,
646 handle: &FocusHandle,
647 window: &mut Window,
648 mut listener: impl FnMut(&mut T, FocusOutEvent, &mut Window, &mut Context<T>) + 'static,
649 ) -> Subscription {
650 let view = self.weak_entity();
651 let focus_id = handle.id;
652 let (subscription, activate) =
653 window.new_focus_listener(Box::new(move |event, window, cx| {
654 view.update(cx, |view, cx| {
655 if let Some(blurred_id) = event.previous_focus_path.last().copied()
656 && event.is_focus_out(focus_id)
657 {
658 let event = FocusOutEvent {
659 blurred: WeakFocusHandle {
660 id: blurred_id,
661 handles: Arc::downgrade(&cx.focus_handles),
662 },
663 };
664 listener(view, event, window, cx)
665 }
666 })
667 .is_ok()
668 }));
669 self.defer(|_| activate());
670 subscription
671 }
672
673 #[track_caller]
678 pub fn spawn_in<AsyncFn, R>(&self, window: &Window, f: AsyncFn) -> Task<R>
679 where
680 R: 'static,
681 AsyncFn: AsyncFnOnce(WeakEntity<T>, &mut AsyncWindowContext) -> R + 'static,
682 {
683 let view = self.weak_entity();
684 window.spawn(self, async move |cx| f(view, cx).await)
685 }
686
687 pub fn observe_global_in<G: Global>(
689 &mut self,
690 window: &Window,
691 mut f: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
692 ) -> Subscription {
693 let window_handle = window.handle;
694 let view = self.weak_entity();
695 let (subscription, activate) = self.global_observers.insert(
696 TypeId::of::<G>(),
697 Box::new(move |cx| {
698 window_handle
699 .update(cx, |_, window, cx| {
700 view.update(cx, |view, cx| f(view, window, cx)).is_ok()
701 })
702 .unwrap_or(false)
703 }),
704 );
705 self.defer(move |_| activate());
706 subscription
707 }
708
709 pub fn on_action(
711 &mut self,
712 action_type: TypeId,
713 window: &mut Window,
714 listener: impl Fn(&mut T, &dyn Any, DispatchPhase, &mut Window, &mut Context<T>) + 'static,
715 ) {
716 let handle = self.weak_entity();
717 window.on_action(action_type, move |action, phase, window, cx| {
718 handle
719 .update(cx, |view, cx| {
720 listener(view, action, phase, window, cx);
721 })
722 .ok();
723 });
724 }
725
726 pub fn focus_self(&mut self, window: &mut Window)
728 where
729 T: Focusable,
730 {
731 let view = self.entity();
732 window.defer(self, move |window, cx| {
733 view.read(cx).focus_handle(cx).focus(window)
734 })
735 }
736}
737
738impl<T> Context<'_, T> {
739 pub fn emit<Evt>(&mut self, event: Evt)
741 where
742 T: EventEmitter<Evt>,
743 Evt: 'static,
744 {
745 self.app.pending_effects.push_back(Effect::Emit {
746 emitter: self.entity_state.entity_id,
747 event_type: TypeId::of::<Evt>(),
748 event: Box::new(event),
749 });
750 }
751}
752
753impl<T> AppContext for Context<'_, T> {
754 type Result<U> = U;
755
756 fn new<U: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<U>) -> U) -> Entity<U> {
757 self.app.new(build_entity)
758 }
759
760 fn reserve_entity<U: 'static>(&mut self) -> Reservation<U> {
761 self.app.reserve_entity()
762 }
763
764 fn insert_entity<U: 'static>(
765 &mut self,
766 reservation: Reservation<U>,
767 build_entity: impl FnOnce(&mut Context<U>) -> U,
768 ) -> Self::Result<Entity<U>> {
769 self.app.insert_entity(reservation, build_entity)
770 }
771
772 fn update_entity<U: 'static, R>(
773 &mut self,
774 handle: &Entity<U>,
775 update: impl FnOnce(&mut U, &mut Context<U>) -> R,
776 ) -> R {
777 self.app.update_entity(handle, update)
778 }
779
780 fn as_mut<'a, E>(&'a mut self, handle: &Entity<E>) -> Self::Result<super::GpuiBorrow<'a, E>>
781 where
782 E: 'static,
783 {
784 self.app.as_mut(handle)
785 }
786
787 fn read_entity<U, R>(
788 &self,
789 handle: &Entity<U>,
790 read: impl FnOnce(&U, &App) -> R,
791 ) -> Self::Result<R>
792 where
793 U: 'static,
794 {
795 self.app.read_entity(handle, read)
796 }
797
798 fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
799 where
800 F: FnOnce(AnyView, &mut Window, &mut App) -> R,
801 {
802 self.app.update_window(window, update)
803 }
804
805 fn read_window<U, R>(
806 &self,
807 window: &WindowHandle<U>,
808 read: impl FnOnce(Entity<U>, &App) -> R,
809 ) -> Result<R>
810 where
811 U: 'static,
812 {
813 self.app.read_window(window, read)
814 }
815
816 fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
817 where
818 R: Send + 'static,
819 {
820 self.app.background_executor.spawn(future)
821 }
822
823 fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
824 where
825 G: Global,
826 {
827 self.app.read_global(callback)
828 }
829}
830
831impl<T> Borrow<App> for Context<'_, T> {
832 fn borrow(&self) -> &App {
833 self.app
834 }
835}
836
837impl<T> BorrowMut<App> for Context<'_, T> {
838 fn borrow_mut(&mut self) -> &mut App {
839 self.app
840 }
841}