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