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,
5};
6use anyhow::Result;
7use futures::FutureExt;
8use std::{
9 any::{Any, TypeId},
10 borrow::{Borrow, BorrowMut},
11 future::Future,
12 ops,
13 rc::Rc,
14 sync::Arc,
15};
16use util::Deferred;
17
18use super::{App, AsyncWindowContext, Entity, KeystrokeEvent};
19
20/// The app context, with specialized behavior for the given entity.
21pub struct Context<'a, T> {
22 app: &'a mut App,
23 entity_state: WeakEntity<T>,
24}
25
26impl<'a, T> ops::Deref for Context<'a, T> {
27 type Target = App;
28
29 fn deref(&self) -> &Self::Target {
30 self.app
31 }
32}
33
34impl<'a, T> ops::DerefMut for Context<'a, T> {
35 fn deref_mut(&mut self) -> &mut Self::Target {
36 self.app
37 }
38}
39
40impl<'a, T: 'static> Context<'a, T> {
41 pub(crate) fn new_context(app: &'a mut App, entity_state: WeakEntity<T>) -> Self {
42 Self { app, entity_state }
43 }
44
45 /// The entity id of the entity backing this context.
46 pub fn entity_id(&self) -> EntityId {
47 self.entity_state.entity_id
48 }
49
50 /// Returns a handle to the entity belonging to this context.
51 pub fn entity(&self) -> Entity<T> {
52 self.weak_entity()
53 .upgrade()
54 .expect("The entity must be alive if we have a entity context")
55 }
56
57 /// Returns a weak handle to the entity belonging to this context.
58 pub fn weak_entity(&self) -> WeakEntity<T> {
59 self.entity_state.clone()
60 }
61
62 /// Arranges for the given function to be called whenever [`Context::notify`] is
63 /// called with the given entity.
64 pub fn observe<W>(
65 &mut self,
66 entity: &Entity<W>,
67 mut on_notify: impl FnMut(&mut T, Entity<W>, &mut Context<T>) + 'static,
68 ) -> Subscription
69 where
70 T: 'static,
71 W: 'static,
72 {
73 let this = self.weak_entity();
74 self.app.observe_internal(entity, move |e, cx| {
75 if let Some(this) = this.upgrade() {
76 this.update(cx, |this, cx| on_notify(this, e, cx));
77 true
78 } else {
79 false
80 }
81 })
82 }
83
84 /// Observe changes to ourselves
85 pub fn observe_self(
86 &mut self,
87 mut on_event: impl FnMut(&mut T, &mut Context<T>) + 'static,
88 ) -> Subscription
89 where
90 T: 'static,
91 {
92 let this = self.entity();
93 self.app.observe(&this, move |this, cx| {
94 this.update(cx, |this, cx| on_event(this, cx))
95 })
96 }
97
98 /// Subscribe to an event type of another entity whenever a new entity of that type is created
99 pub fn subscribe_in_new<T2, Evt>(
100 &mut self,
101 mut on_event: impl Fn(&mut T, &Entity<T2>, &Evt, &mut Window, &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 let on_event = Rc::new(on_event);
110
111 self.app.observe_new::<T2>(move |_, window, cx| {
112 let handle = window.map(|window| window.handle);
113
114 cx.app
115 .subscribe_internal(&cx.entity(), {
116 let this = this.clone();
117 let on_event = on_event.clone();
118 let handle = handle.clone();
119
120 move |e, event, cx| {
121 if let Some(this) = this.upgrade()
122 && let Some(window) = handle
123 {
124 window
125 .update(cx, |_, window, cx| {
126 this.update(cx, |this, cx| {
127 on_event(this, &e, event, window, cx)
128 });
129 })
130 .is_ok()
131 } else {
132 false
133 }
134 }
135 })
136 .detach();
137 })
138 }
139
140 /// Subscribe to an event type of another entity whenever a new entity of that type is created
141 pub fn subscribe_new<T2, Evt>(
142 &mut self,
143 mut on_event: impl Fn(&mut T, Entity<T2>, &Evt, &mut Context<T>) + 'static,
144 ) -> Subscription
145 where
146 T: 'static,
147 T2: 'static + EventEmitter<Evt>,
148 Evt: 'static,
149 {
150 let this = self.weak_entity();
151 let on_event = Rc::new(on_event);
152
153 self.app.observe_new::<T2>(move |_, _, cx| {
154 cx.app
155 .subscribe_internal(&cx.entity(), {
156 let this = this.clone();
157 let on_event = on_event.clone();
158
159 move |e, event, cx| {
160 if let Some(this) = this.upgrade() {
161 this.update(cx, |this, cx| on_event(this, e, event, cx));
162 true
163 } else {
164 false
165 }
166 }
167 })
168 .detach();
169 })
170 }
171
172 /// Subscribe to an event type from another entity
173 pub fn subscribe<T2, Evt>(
174 &mut self,
175 entity: &Entity<T2>,
176 mut on_event: impl FnMut(&mut T, Entity<T2>, &Evt, &mut Context<T>) + 'static,
177 ) -> Subscription
178 where
179 T: 'static,
180 T2: 'static + EventEmitter<Evt>,
181 Evt: 'static,
182 {
183 let this = self.weak_entity();
184 self.app.subscribe_internal(entity, move |e, event, cx| {
185 if let Some(this) = this.upgrade() {
186 this.update(cx, |this, cx| on_event(this, e, event, cx));
187 true
188 } else {
189 false
190 }
191 })
192 }
193
194 /// Subscribe to an event type from ourself
195 pub fn subscribe_self<Evt>(
196 &mut self,
197 mut on_event: impl FnMut(&mut T, &Evt, &mut Context<T>) + 'static,
198 ) -> Subscription
199 where
200 T: 'static + EventEmitter<Evt>,
201 Evt: 'static,
202 {
203 let this = self.entity();
204 self.app.subscribe(&this, move |this, evt, cx| {
205 this.update(cx, |this, cx| on_event(this, evt, cx))
206 })
207 }
208
209 /// Register a callback to be invoked when GPUI releases this entity.
210 pub fn on_release(&self, on_release: impl FnOnce(&mut T, &mut App) + 'static) -> Subscription
211 where
212 T: 'static,
213 {
214 let (subscription, activate) = self.app.release_listeners.insert(
215 self.entity_state.entity_id,
216 Box::new(move |this, cx| {
217 let this = this.downcast_mut().expect("invalid entity type");
218 on_release(this, cx);
219 }),
220 );
221 activate();
222 subscription
223 }
224
225 /// Register a callback to be run on the release of another entity
226 pub fn observe_release<T2>(
227 &self,
228 entity: &Entity<T2>,
229 on_release: impl FnOnce(&mut T, &mut T2, &mut Context<T>) + 'static,
230 ) -> Subscription
231 where
232 T: Any,
233 T2: 'static,
234 {
235 let entity_id = entity.entity_id();
236 let this = self.weak_entity();
237 let (subscription, activate) = self.app.release_listeners.insert(
238 entity_id,
239 Box::new(move |entity, cx| {
240 let entity = entity.downcast_mut().expect("invalid entity type");
241 if let Some(this) = this.upgrade() {
242 this.update(cx, |this, cx| on_release(this, entity, cx));
243 }
244 }),
245 );
246 activate();
247 subscription
248 }
249
250 /// Register a callback to for updates to the given global
251 pub fn observe_global<G: 'static>(
252 &mut self,
253 mut f: impl FnMut(&mut T, &mut Context<T>) + 'static,
254 ) -> Subscription
255 where
256 T: 'static,
257 {
258 let handle = self.weak_entity();
259 let (subscription, activate) = self.global_observers.insert(
260 TypeId::of::<G>(),
261 Box::new(move |cx| handle.update(cx, |view, cx| f(view, cx)).is_ok()),
262 );
263 self.defer(move |_| activate());
264 subscription
265 }
266
267 /// Register a callback to be invoked when the application is about to restart.
268 pub fn on_app_restart(
269 &self,
270 mut on_restart: impl FnMut(&mut T, &mut App) + 'static,
271 ) -> Subscription
272 where
273 T: 'static,
274 {
275 let handle = self.weak_entity();
276 self.app.on_app_restart(move |cx| {
277 handle.update(cx, |entity, cx| on_restart(entity, cx)).ok();
278 })
279 }
280
281 /// Arrange for the given function to be invoked whenever the application is quit.
282 /// The future returned from this callback will be polled for up to [crate::SHUTDOWN_TIMEOUT] until the app fully quits.
283 pub fn on_app_quit<Fut>(
284 &self,
285 mut on_quit: impl FnMut(&mut T, &mut Context<T>) -> Fut + 'static,
286 ) -> Subscription
287 where
288 Fut: 'static + Future<Output = ()>,
289 T: 'static,
290 {
291 let handle = self.weak_entity();
292 self.app.on_app_quit(move |cx| {
293 let future = handle.update(cx, |entity, cx| on_quit(entity, cx)).ok();
294 async move {
295 if let Some(future) = future {
296 future.await;
297 }
298 }
299 .boxed_local()
300 })
301 }
302
303 /// Tell GPUI that this entity has changed and observers of it should be notified.
304 pub fn notify(&mut self) {
305 self.app.notify(self.entity_state.entity_id);
306 }
307
308 /// Spawn the future returned by the given function.
309 /// The function is provided a weak handle to the entity owned by this context and a context that can be held across await points.
310 /// The returned task must be held or detached.
311 #[track_caller]
312 pub fn spawn<AsyncFn, R>(&self, f: AsyncFn) -> Task<R>
313 where
314 T: 'static,
315 AsyncFn: AsyncFnOnce(WeakEntity<T>, &mut AsyncApp) -> R + 'static,
316 R: 'static,
317 {
318 let this = self.weak_entity();
319 self.app.spawn(async move |cx| f(this, cx).await)
320 }
321
322 /// Convenience method for accessing view state in an event callback.
323 ///
324 /// Many GPUI callbacks take the form of `Fn(&E, &mut Window, &mut App)`,
325 /// but it's often useful to be able to access view state in these
326 /// callbacks. This method provides a convenient way to do so.
327 pub fn listener<E: ?Sized>(
328 &self,
329 f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
330 ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
331 let entity = self.entity().downgrade();
332 move |e: &E, window: &mut Window, cx: &mut App| {
333 entity
334 .update(cx, |entity, cx| f(entity, e, window, cx))
335 .ok();
336 }
337 }
338
339 /// Convenience method for producing view state in a closure.
340 /// See `listener` for more details.
341 pub fn processor<E, R>(
342 &self,
343 f: impl Fn(&mut T, E, &mut Window, &mut Context<T>) -> R + 'static,
344 ) -> impl Fn(E, &mut Window, &mut App) -> R + 'static {
345 let entity = self.entity();
346 move |e: E, window: &mut Window, cx: &mut App| {
347 entity.update(cx, |entity, cx| f(entity, e, window, cx))
348 }
349 }
350
351 /// Run something using this entity and cx, when the returned struct is dropped
352 pub fn on_drop(
353 &self,
354 f: impl FnOnce(&mut T, &mut Context<T>) + 'static,
355 ) -> Deferred<impl FnOnce()> {
356 let this = self.weak_entity();
357 let mut cx = self.to_async();
358 util::defer(move || {
359 this.update(&mut cx, f).ok();
360 })
361 }
362
363 /// Focus the given view in the given window. View type is required to implement Focusable.
364 pub fn focus_view<W: Focusable>(&mut self, view: &Entity<W>, window: &mut Window) {
365 window.focus(&view.focus_handle(self));
366 }
367
368 /// Sets a given callback to be run on the next frame.
369 pub fn on_next_frame(
370 &self,
371 window: &mut Window,
372 f: impl FnOnce(&mut T, &mut Window, &mut Context<T>) + 'static,
373 ) where
374 T: 'static,
375 {
376 let entity = self.entity();
377 window
378 .on_next_frame(move |window, cx| entity.update(cx, |entity, cx| f(entity, window, cx)));
379 }
380
381 /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
382 /// that are currently on the stack to be returned to the app.
383 pub fn defer_in(
384 &mut self,
385 window: &Window,
386 f: impl FnOnce(&mut T, &mut Window, &mut Context<T>) + 'static,
387 ) {
388 let entity = self.entity();
389 window.defer(self, move |window, cx| {
390 entity.update(cx, |entity, cx| f(entity, window, cx))
391 });
392 }
393
394 /// Observe another entity for changes to its state, as tracked by [`Context::notify`].
395 pub fn observe_in<V2>(
396 &mut self,
397 observed: &Entity<V2>,
398 window: &mut Window,
399 mut on_notify: impl FnMut(&mut T, Entity<V2>, &mut Window, &mut Context<T>) + 'static,
400 ) -> Subscription
401 where
402 V2: 'static,
403 T: 'static,
404 {
405 let observed_id = observed.entity_id();
406 let observed = observed.downgrade();
407 let window_handle = window.handle;
408 let observer = self.weak_entity();
409 self.new_observer(
410 observed_id,
411 Box::new(move |cx| {
412 window_handle
413 .update(cx, |_, window, cx| {
414 if let Some((observer, observed)) =
415 observer.upgrade().zip(observed.upgrade())
416 {
417 observer.update(cx, |observer, cx| {
418 on_notify(observer, observed, window, cx);
419 });
420 true
421 } else {
422 false
423 }
424 })
425 .unwrap_or(false)
426 }),
427 )
428 }
429
430 /// Subscribe to events emitted by another entity.
431 /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
432 /// The callback will be invoked with a reference to the current view, a handle to the emitting `Entity`, the event, a mutable reference to the `Window`, and the context for the entity.
433 pub fn subscribe_in<Emitter, Evt>(
434 &mut self,
435 emitter: &Entity<Emitter>,
436 window: &Window,
437 mut on_event: impl FnMut(&mut T, &Entity<Emitter>, &Evt, &mut Window, &mut Context<T>) + 'static,
438 ) -> Subscription
439 where
440 Emitter: EventEmitter<Evt>,
441 Evt: 'static,
442 {
443 let emitter = emitter.downgrade();
444 let window_handle = window.handle;
445 let subscriber = self.weak_entity();
446 self.new_subscription(
447 emitter.entity_id(),
448 (
449 TypeId::of::<Evt>(),
450 Box::new(move |event, cx| {
451 window_handle
452 .update(cx, |_, window, cx| {
453 if let Some((subscriber, emitter)) =
454 subscriber.upgrade().zip(emitter.upgrade())
455 {
456 let event = event.downcast_ref().expect("invalid event type");
457 subscriber.update(cx, |subscriber, cx| {
458 on_event(subscriber, &emitter, event, window, cx);
459 });
460 true
461 } else {
462 false
463 }
464 })
465 .unwrap_or(false)
466 }),
467 ),
468 )
469 }
470
471 /// Register a callback to be invoked when the view is released.
472 ///
473 /// The callback receives a handle to the view's window. This handle may be
474 /// invalid, if the window was closed before the view was released.
475 pub fn on_release_in(
476 &mut self,
477 window: &Window,
478 on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
479 ) -> Subscription {
480 let entity = self.entity();
481 self.app.observe_release_in(&entity, window, on_release)
482 }
483
484 /// Register a callback to be invoked when the given Entity is released.
485 pub fn observe_release_in<T2>(
486 &self,
487 observed: &Entity<T2>,
488 window: &Window,
489 mut on_release: impl FnMut(&mut T, &mut T2, &mut Window, &mut Context<T>) + 'static,
490 ) -> Subscription
491 where
492 T: 'static,
493 T2: 'static,
494 {
495 let observer = self.weak_entity();
496 self.app
497 .observe_release_in(observed, window, move |observed, window, cx| {
498 observer
499 .update(cx, |observer, cx| {
500 on_release(observer, observed, window, cx)
501 })
502 .ok();
503 })
504 }
505
506 /// Register a callback to be invoked when the window is resized.
507 pub fn observe_window_bounds(
508 &self,
509 window: &mut Window,
510 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
511 ) -> Subscription {
512 let view = self.weak_entity();
513 let (subscription, activate) = window.bounds_observers.insert(
514 (),
515 Box::new(move |window, cx| {
516 view.update(cx, |view, cx| callback(view, window, cx))
517 .is_ok()
518 }),
519 );
520 activate();
521 subscription
522 }
523
524 /// Register a callback to be invoked when the window is activated or deactivated.
525 pub fn observe_window_activation(
526 &self,
527 window: &mut Window,
528 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
529 ) -> Subscription {
530 let view = self.weak_entity();
531 let (subscription, activate) = window.activation_observers.insert(
532 (),
533 Box::new(move |window, cx| {
534 view.update(cx, |view, cx| callback(view, window, cx))
535 .is_ok()
536 }),
537 );
538 activate();
539 subscription
540 }
541
542 /// Registers a callback to be invoked when the window appearance changes.
543 pub fn observe_window_appearance(
544 &self,
545 window: &mut Window,
546 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
547 ) -> Subscription {
548 let view = self.weak_entity();
549 let (subscription, activate) = window.appearance_observers.insert(
550 (),
551 Box::new(move |window, cx| {
552 view.update(cx, |view, cx| callback(view, window, cx))
553 .is_ok()
554 }),
555 );
556 activate();
557 subscription
558 }
559
560 /// Register a callback to be invoked when a keystroke is received by the application
561 /// in any window. Note that this fires after all other action and event mechanisms have resolved
562 /// and that this API will not be invoked if the event's propagation is stopped.
563 pub fn observe_keystrokes(
564 &mut self,
565 mut f: impl FnMut(&mut T, &KeystrokeEvent, &mut Window, &mut Context<T>) + 'static,
566 ) -> Subscription {
567 fn inner(
568 keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
569 handler: KeystrokeObserver,
570 ) -> Subscription {
571 let (subscription, activate) = keystroke_observers.insert((), handler);
572 activate();
573 subscription
574 }
575
576 let view = self.weak_entity();
577 inner(
578 &self.keystroke_observers,
579 Box::new(move |event, window, cx| {
580 if let Some(view) = view.upgrade() {
581 view.update(cx, |view, cx| f(view, event, window, cx));
582 true
583 } else {
584 false
585 }
586 }),
587 )
588 }
589
590 /// Register a callback to be invoked when the window's pending input changes.
591 pub fn observe_pending_input(
592 &self,
593 window: &mut Window,
594 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
595 ) -> Subscription {
596 let view = self.weak_entity();
597 let (subscription, activate) = window.pending_input_observers.insert(
598 (),
599 Box::new(move |window, cx| {
600 view.update(cx, |view, cx| callback(view, window, cx))
601 .is_ok()
602 }),
603 );
604 activate();
605 subscription
606 }
607
608 /// Register a listener to be called when the given focus handle receives focus.
609 /// Returns a subscription and persists until the subscription is dropped.
610 pub fn on_focus(
611 &mut self,
612 handle: &FocusHandle,
613 window: &mut Window,
614 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
615 ) -> Subscription {
616 let view = self.weak_entity();
617 let focus_id = handle.id;
618 let (subscription, activate) =
619 window.new_focus_listener(Box::new(move |event, window, cx| {
620 view.update(cx, |view, cx| {
621 if event.previous_focus_path.last() != Some(&focus_id)
622 && event.current_focus_path.last() == Some(&focus_id)
623 {
624 listener(view, window, cx)
625 }
626 })
627 .is_ok()
628 }));
629 self.defer(|_| activate());
630 subscription
631 }
632
633 /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
634 /// This does not fire if the given focus handle - or one of its descendants - was previously focused.
635 /// Returns a subscription and persists until the subscription is dropped.
636 pub fn on_focus_in(
637 &mut self,
638 handle: &FocusHandle,
639 window: &mut Window,
640 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
641 ) -> Subscription {
642 let view = self.weak_entity();
643 let focus_id = handle.id;
644 let (subscription, activate) =
645 window.new_focus_listener(Box::new(move |event, window, cx| {
646 view.update(cx, |view, cx| {
647 if event.is_focus_in(focus_id) {
648 listener(view, window, cx)
649 }
650 })
651 .is_ok()
652 }));
653 self.defer(|_| activate());
654 subscription
655 }
656
657 /// Register a listener to be called when the given focus handle loses focus.
658 /// Returns a subscription and persists until the subscription is dropped.
659 pub fn on_blur(
660 &mut self,
661 handle: &FocusHandle,
662 window: &mut Window,
663 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
664 ) -> Subscription {
665 let view = self.weak_entity();
666 let focus_id = handle.id;
667 let (subscription, activate) =
668 window.new_focus_listener(Box::new(move |event, window, cx| {
669 view.update(cx, |view, cx| {
670 if event.previous_focus_path.last() == Some(&focus_id)
671 && event.current_focus_path.last() != Some(&focus_id)
672 {
673 listener(view, window, cx)
674 }
675 })
676 .is_ok()
677 }));
678 self.defer(|_| activate());
679 subscription
680 }
681
682 /// Register a listener to be called when nothing in the window has focus.
683 /// This typically happens when the node that was focused is removed from the tree,
684 /// and this callback lets you chose a default place to restore the users focus.
685 /// Returns a subscription and persists until the subscription is dropped.
686 pub fn on_focus_lost(
687 &mut self,
688 window: &mut Window,
689 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
690 ) -> Subscription {
691 let view = self.weak_entity();
692 let (subscription, activate) = window.focus_lost_listeners.insert(
693 (),
694 Box::new(move |window, cx| {
695 view.update(cx, |view, cx| listener(view, window, cx))
696 .is_ok()
697 }),
698 );
699 self.defer(|_| activate());
700 subscription
701 }
702
703 /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
704 /// Returns a subscription and persists until the subscription is dropped.
705 pub fn on_focus_out(
706 &mut self,
707 handle: &FocusHandle,
708 window: &mut Window,
709 mut listener: impl FnMut(&mut T, FocusOutEvent, &mut Window, &mut Context<T>) + 'static,
710 ) -> Subscription {
711 let view = self.weak_entity();
712 let focus_id = handle.id;
713 let (subscription, activate) =
714 window.new_focus_listener(Box::new(move |event, window, cx| {
715 view.update(cx, |view, cx| {
716 if let Some(blurred_id) = event.previous_focus_path.last().copied()
717 && event.is_focus_out(focus_id)
718 {
719 let event = FocusOutEvent {
720 blurred: WeakFocusHandle {
721 id: blurred_id,
722 handles: Arc::downgrade(&cx.focus_handles),
723 },
724 };
725 listener(view, event, window, cx)
726 }
727 })
728 .is_ok()
729 }));
730 self.defer(|_| activate());
731 subscription
732 }
733
734 /// Schedule a future to be run asynchronously.
735 /// The given callback is invoked with a [`WeakEntity<V>`] to avoid leaking the entity for a long-running process.
736 /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the entity across await points.
737 /// The returned future will be polled on the main thread.
738 #[track_caller]
739 pub fn spawn_in<AsyncFn, R>(&self, window: &Window, f: AsyncFn) -> Task<R>
740 where
741 R: 'static,
742 AsyncFn: AsyncFnOnce(WeakEntity<T>, &mut AsyncWindowContext) -> R + 'static,
743 {
744 let view = self.weak_entity();
745 window.spawn(self, async move |cx| f(view, cx).await)
746 }
747
748 /// Register a callback to be invoked when the given global state changes.
749 pub fn observe_global_in<G: Global>(
750 &mut self,
751 window: &Window,
752 mut f: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
753 ) -> Subscription {
754 let window_handle = window.handle;
755 let view = self.weak_entity();
756 let (subscription, activate) = self.global_observers.insert(
757 TypeId::of::<G>(),
758 Box::new(move |cx| {
759 window_handle
760 .update(cx, |_, window, cx| {
761 view.update(cx, |view, cx| f(view, window, cx)).is_ok()
762 })
763 .unwrap_or(false)
764 }),
765 );
766 self.defer(move |_| activate());
767 subscription
768 }
769
770 /// Register a callback to be invoked when the given Action type is dispatched to the window.
771 pub fn on_action(
772 &mut self,
773 action_type: TypeId,
774 window: &mut Window,
775 listener: impl Fn(&mut T, &dyn Any, DispatchPhase, &mut Window, &mut Context<T>) + 'static,
776 ) {
777 let handle = self.weak_entity();
778 window.on_action(action_type, move |action, phase, window, cx| {
779 handle
780 .update(cx, |view, cx| {
781 listener(view, action, phase, window, cx);
782 })
783 .ok();
784 });
785 }
786
787 /// Move focus to the current view, assuming it implements [`Focusable`].
788 pub fn focus_self(&mut self, window: &mut Window)
789 where
790 T: Focusable,
791 {
792 let view = self.entity();
793 window.defer(self, move |window, cx| {
794 view.read(cx).focus_handle(cx).focus(window)
795 })
796 }
797}
798
799impl<T> Context<'_, T> {
800 /// Emit an event of the specified type, which can be handled by other entities that have subscribed via `subscribe` methods on their respective contexts.
801 pub fn emit<Evt>(&mut self, event: Evt)
802 where
803 T: EventEmitter<Evt>,
804 Evt: 'static,
805 {
806 self.app.pending_effects.push_back(Effect::Emit {
807 emitter: self.entity_state.entity_id,
808 event_type: TypeId::of::<Evt>(),
809 event: Box::new(event),
810 });
811 }
812}
813
814impl<T> AppContext for Context<'_, T> {
815 type Result<U> = U;
816
817 fn new<U: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<U>) -> U) -> Entity<U> {
818 self.app.new(build_entity)
819 }
820
821 fn reserve_entity<U: 'static>(&mut self) -> Reservation<U> {
822 self.app.reserve_entity()
823 }
824
825 fn insert_entity<U: 'static>(
826 &mut self,
827 reservation: Reservation<U>,
828 build_entity: impl FnOnce(&mut Context<U>) -> U,
829 ) -> Self::Result<Entity<U>> {
830 self.app.insert_entity(reservation, build_entity)
831 }
832
833 fn update_entity<U: 'static, R>(
834 &mut self,
835 handle: &Entity<U>,
836 update: impl FnOnce(&mut U, &mut Context<U>) -> R,
837 ) -> R {
838 self.app.update_entity(handle, update)
839 }
840
841 fn as_mut<'a, E>(&'a mut self, handle: &Entity<E>) -> Self::Result<super::GpuiBorrow<'a, E>>
842 where
843 E: 'static,
844 {
845 self.app.as_mut(handle)
846 }
847
848 fn read_entity<U, R>(
849 &self,
850 handle: &Entity<U>,
851 read: impl FnOnce(&U, &App) -> R,
852 ) -> Self::Result<R>
853 where
854 U: 'static,
855 {
856 self.app.read_entity(handle, read)
857 }
858
859 fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
860 where
861 F: FnOnce(AnyView, &mut Window, &mut App) -> R,
862 {
863 self.app.update_window(window, update)
864 }
865
866 fn read_window<U, R>(
867 &self,
868 window: &WindowHandle<U>,
869 read: impl FnOnce(Entity<U>, &App) -> R,
870 ) -> Result<R>
871 where
872 U: 'static,
873 {
874 self.app.read_window(window, read)
875 }
876
877 fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
878 where
879 R: Send + 'static,
880 {
881 self.app.background_executor.spawn(future)
882 }
883
884 fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> Self::Result<R>
885 where
886 G: Global,
887 {
888 self.app.read_global(callback)
889 }
890}
891
892impl<T> Borrow<App> for Context<'_, T> {
893 fn borrow(&self) -> &App {
894 self.app
895 }
896}
897
898impl<T> BorrowMut<App> for Context<'_, T> {
899 fn borrow_mut(&mut self) -> &mut App {
900 self.app
901 }
902}