1use crate::{
2 AnyView, AnyWindowHandle, AppContext, AsyncApp, DispatchPhase, Effect, EntityId, EventEmitter,
3 FocusHandle, FocusOutEvent, Focusable, Global, KeystrokeObserver, Priority, Reservation,
4 SubscriberSet, Subscription, Task, WeakEntity, WeakFocusHandle, Window, WindowHandle,
5};
6use anyhow::Result;
7use futures::FutureExt;
8use gpui_util::Deferred;
9use std::{
10 any::{Any, TypeId},
11 borrow::{Borrow, BorrowMut},
12 future::Future,
13 ops,
14 sync::Arc,
15};
16
17use super::{App, AsyncWindowContext, Entity, KeystrokeEvent};
18
19/// The app context, with specialized behavior for the given entity.
20pub 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 /// The entity id of the entity backing this context.
45 pub fn entity_id(&self) -> EntityId {
46 self.entity_state.entity_id
47 }
48
49 /// Returns a handle to the entity belonging to this context.
50 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 /// Returns a weak handle to the entity belonging to this context.
57 pub fn weak_entity(&self) -> WeakEntity<T> {
58 self.entity_state.clone()
59 }
60
61 /// Arranges for the given function to be called whenever [`Context::notify`] is
62 /// called with the given entity.
63 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 /// Observe changes to ourselves
84 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 /// Subscribe to an event type from another entity
98 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 /// Subscribe to an event type from ourself
120 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 /// Register a callback to be invoked when GPUI releases this entity.
135 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 /// Register a callback to be run on the release of another entity
151 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 /// Register a callback to for updates to the given global
176 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 /// Register a callback to be invoked when the application is about to restart.
193 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 /// Arrange for the given function to be invoked whenever the application is quit.
207 /// The future returned from this callback will be polled for up to [crate::SHUTDOWN_TIMEOUT] until the app fully quits.
208 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 /// Tell GPUI that this entity has changed and observers of it should be notified.
229 pub fn notify(&mut self) {
230 self.app.notify(self.entity_state.entity_id);
231 }
232
233 /// Spawn the future returned by the given function.
234 /// The function is provided a weak handle to the entity owned by this context and a context that can be held across await points.
235 /// The returned task must be held or detached.
236 #[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 /// Convenience method for accessing view state in an event callback.
248 ///
249 /// Many GPUI callbacks take the form of `Fn(&E, &mut Window, &mut App)`,
250 /// but it's often useful to be able to access view state in these
251 /// callbacks. This method provides a convenient way to do so.
252 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 /// Convenience method for producing view state in a closure.
263 /// See `listener` for more details.
264 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 /// Run something using this entity and cx, when the returned struct is dropped
275 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 gpui_util::defer(move || {
282 this.update(&mut cx, f).ok();
283 })
284 }
285
286 /// Focus the given view in the given window. View type is required to implement Focusable.
287 pub fn focus_view<W: Focusable>(&mut self, view: &Entity<W>, window: &mut Window) {
288 window.focus(&view.focus_handle(self), self);
289 }
290
291 /// Sets a given callback to be run on the next frame.
292 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 /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
304 /// that are currently on the stack to be returned to the app.
305 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 /// Observe another entity for changes to its state, as tracked by [`Context::notify`].
317 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 /// Subscribe to events emitted by another entity.
353 /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
354 /// 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.
355 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 /// Register a callback to be invoked when the view is released.
394 ///
395 /// The callback receives a handle to the view's window. This handle may be
396 /// invalid, if the window was closed before the view was released.
397 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 /// Register a callback to be invoked when the given Entity is released.
407 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 /// Register a callback to be invoked when the window is resized.
429 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 /// Register a callback to be invoked when the window is activated or deactivated.
447 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 /// Registers a callback to be invoked when the window appearance changes.
465 pub fn observe_window_appearance(
466 &self,
467 window: &mut Window,
468 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
469 ) -> Subscription {
470 let view = self.weak_entity();
471 let (subscription, activate) = window.appearance_observers.insert(
472 (),
473 Box::new(move |window, cx| {
474 view.update(cx, |view, cx| callback(view, window, cx))
475 .is_ok()
476 }),
477 );
478 activate();
479 subscription
480 }
481
482 /// Registers a callback to be invoked when the window button layout changes.
483 pub fn observe_button_layout_changed(
484 &self,
485 window: &mut Window,
486 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
487 ) -> Subscription {
488 let view = self.weak_entity();
489 let (subscription, activate) = window.button_layout_observers.insert(
490 (),
491 Box::new(move |window, cx| {
492 view.update(cx, |view, cx| callback(view, window, cx))
493 .is_ok()
494 }),
495 );
496 activate();
497 subscription
498 }
499
500 /// Register a callback to be invoked when a keystroke is received by the application
501 /// in any window. Note that this fires after all other action and event mechanisms have resolved
502 /// and that this API will not be invoked if the event's propagation is stopped.
503 pub fn observe_keystrokes(
504 &mut self,
505 mut f: impl FnMut(&mut T, &KeystrokeEvent, &mut Window, &mut Context<T>) + 'static,
506 ) -> Subscription {
507 fn inner(
508 keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
509 handler: KeystrokeObserver,
510 ) -> Subscription {
511 let (subscription, activate) = keystroke_observers.insert((), handler);
512 activate();
513 subscription
514 }
515
516 let view = self.weak_entity();
517 inner(
518 &self.keystroke_observers,
519 Box::new(move |event, window, cx| {
520 if let Some(view) = view.upgrade() {
521 view.update(cx, |view, cx| f(view, event, window, cx));
522 true
523 } else {
524 false
525 }
526 }),
527 )
528 }
529
530 /// Register a callback to be invoked when the window's pending input changes.
531 pub fn observe_pending_input(
532 &self,
533 window: &mut Window,
534 mut callback: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
535 ) -> Subscription {
536 let view = self.weak_entity();
537 let (subscription, activate) = window.pending_input_observers.insert(
538 (),
539 Box::new(move |window, cx| {
540 view.update(cx, |view, cx| callback(view, window, cx))
541 .is_ok()
542 }),
543 );
544 activate();
545 subscription
546 }
547
548 /// Register a listener to be called when the given focus handle receives focus.
549 /// Returns a subscription and persists until the subscription is dropped.
550 pub fn on_focus(
551 &mut self,
552 handle: &FocusHandle,
553 window: &mut Window,
554 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
555 ) -> Subscription {
556 let view = self.weak_entity();
557 let focus_id = handle.id;
558 let (subscription, activate) =
559 window.new_focus_listener(Box::new(move |event, window, cx| {
560 view.update(cx, |view, cx| {
561 if event.previous_focus_path.last() != Some(&focus_id)
562 && event.current_focus_path.last() == Some(&focus_id)
563 {
564 listener(view, window, cx)
565 }
566 })
567 .is_ok()
568 }));
569 self.defer(|_| activate());
570 subscription
571 }
572
573 /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
574 /// This does not fire if the given focus handle - or one of its descendants - was previously focused.
575 /// Returns a subscription and persists until the subscription is dropped.
576 pub fn on_focus_in(
577 &mut self,
578 handle: &FocusHandle,
579 window: &mut Window,
580 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
581 ) -> Subscription {
582 let view = self.weak_entity();
583 let focus_id = handle.id;
584 let (subscription, activate) =
585 window.new_focus_listener(Box::new(move |event, window, cx| {
586 view.update(cx, |view, cx| {
587 if event.is_focus_in(focus_id) {
588 listener(view, window, cx)
589 }
590 })
591 .is_ok()
592 }));
593 self.defer(|_| activate());
594 subscription
595 }
596
597 /// Register a listener to be called when the given focus handle loses focus.
598 /// Returns a subscription and persists until the subscription is dropped.
599 pub fn on_blur(
600 &mut self,
601 handle: &FocusHandle,
602 window: &mut Window,
603 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
604 ) -> Subscription {
605 let view = self.weak_entity();
606 let focus_id = handle.id;
607 let (subscription, activate) =
608 window.new_focus_listener(Box::new(move |event, window, cx| {
609 view.update(cx, |view, cx| {
610 if event.previous_focus_path.last() == Some(&focus_id)
611 && event.current_focus_path.last() != Some(&focus_id)
612 {
613 listener(view, window, cx)
614 }
615 })
616 .is_ok()
617 }));
618 self.defer(|_| activate());
619 subscription
620 }
621
622 /// Register a listener to be called when nothing in the window has focus.
623 /// This typically happens when the node that was focused is removed from the tree,
624 /// and this callback lets you chose a default place to restore the users focus.
625 /// Returns a subscription and persists until the subscription is dropped.
626 pub fn on_focus_lost(
627 &mut self,
628 window: &mut Window,
629 mut listener: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
630 ) -> Subscription {
631 let view = self.weak_entity();
632 let (subscription, activate) = window.focus_lost_listeners.insert(
633 (),
634 Box::new(move |window, cx| {
635 view.update(cx, |view, cx| listener(view, window, cx))
636 .is_ok()
637 }),
638 );
639 self.defer(|_| activate());
640 subscription
641 }
642
643 /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
644 /// Returns a subscription and persists until the subscription is dropped.
645 pub fn on_focus_out(
646 &mut self,
647 handle: &FocusHandle,
648 window: &mut Window,
649 mut listener: impl FnMut(&mut T, FocusOutEvent, &mut Window, &mut Context<T>) + 'static,
650 ) -> Subscription {
651 let view = self.weak_entity();
652 let focus_id = handle.id;
653 let (subscription, activate) =
654 window.new_focus_listener(Box::new(move |event, window, cx| {
655 view.update(cx, |view, cx| {
656 if let Some(blurred_id) = event.previous_focus_path.last().copied()
657 && event.is_focus_out(focus_id)
658 {
659 let event = FocusOutEvent {
660 blurred: WeakFocusHandle {
661 id: blurred_id,
662 handles: Arc::downgrade(&cx.focus_handles),
663 },
664 };
665 listener(view, event, window, cx)
666 }
667 })
668 .is_ok()
669 }));
670 self.defer(|_| activate());
671 subscription
672 }
673
674 /// Schedule a future to be run asynchronously.
675 /// The given callback is invoked with a [`WeakEntity<V>`] to avoid leaking the entity for a long-running process.
676 /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the entity across await points.
677 /// The returned future will be polled on the main thread.
678 #[track_caller]
679 pub fn spawn_in<AsyncFn, R>(&self, window: &Window, f: AsyncFn) -> Task<R>
680 where
681 R: 'static,
682 AsyncFn: AsyncFnOnce(WeakEntity<T>, &mut AsyncWindowContext) -> R + 'static,
683 {
684 let view = self.weak_entity();
685 window.spawn(self, async move |cx| f(view, cx).await)
686 }
687
688 /// Schedule a future to be run asynchronously with the given priority.
689 /// The given callback is invoked with a [`WeakEntity<V>`] to avoid leaking the entity for a long-running process.
690 /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the entity across await points.
691 /// The returned future will be polled on the main thread.
692 #[track_caller]
693 pub fn spawn_in_with_priority<AsyncFn, R>(
694 &self,
695 priority: Priority,
696 window: &Window,
697 f: AsyncFn,
698 ) -> Task<R>
699 where
700 R: 'static,
701 AsyncFn: AsyncFnOnce(WeakEntity<T>, &mut AsyncWindowContext) -> R + 'static,
702 {
703 let view = self.weak_entity();
704 window.spawn_with_priority(priority, self, async move |cx| f(view, cx).await)
705 }
706
707 /// Register a callback to be invoked when the given global state changes.
708 pub fn observe_global_in<G: Global>(
709 &mut self,
710 window: &Window,
711 mut f: impl FnMut(&mut T, &mut Window, &mut Context<T>) + 'static,
712 ) -> Subscription {
713 let window_handle = window.handle;
714 let view = self.weak_entity();
715 let (subscription, activate) = self.global_observers.insert(
716 TypeId::of::<G>(),
717 Box::new(move |cx| {
718 // If the entity has been dropped, remove this observer.
719 if view.upgrade().is_none() {
720 return false;
721 }
722 // If the window is unavailable (e.g. temporarily taken during a
723 // nested update, or already closed), skip this notification but
724 // keep the observer alive so it can fire on future changes.
725 let Ok(entity_alive) = window_handle.update(cx, |_, window, cx| {
726 view.update(cx, |view, cx| f(view, window, cx)).is_ok()
727 }) else {
728 return true;
729 };
730 entity_alive
731 }),
732 );
733 self.defer(move |_| activate());
734 subscription
735 }
736
737 /// Register a callback to be invoked when the given Action type is dispatched to the window.
738 pub fn on_action(
739 &mut self,
740 action_type: TypeId,
741 window: &mut Window,
742 listener: impl Fn(&mut T, &dyn Any, DispatchPhase, &mut Window, &mut Context<T>) + 'static,
743 ) {
744 let handle = self.weak_entity();
745 window.on_action(action_type, move |action, phase, window, cx| {
746 handle
747 .update(cx, |view, cx| {
748 listener(view, action, phase, window, cx);
749 })
750 .ok();
751 });
752 }
753
754 /// Move focus to the current view, assuming it implements [`Focusable`].
755 pub fn focus_self(&mut self, window: &mut Window)
756 where
757 T: Focusable,
758 {
759 let view = self.entity();
760 window.defer(self, move |window, cx| {
761 view.read(cx).focus_handle(cx).focus(window, cx)
762 })
763 }
764}
765
766impl<T> Context<'_, T> {
767 /// Emit an event of the specified type, which can be handled by other entities that have subscribed via `subscribe` methods on their respective contexts.
768 pub fn emit<Evt>(&mut self, event: Evt)
769 where
770 T: EventEmitter<Evt>,
771 Evt: 'static,
772 {
773 let event = self
774 .event_arena
775 .alloc(|| event)
776 .map(|it| it as &mut dyn Any);
777 self.app.pending_effects.push_back(Effect::Emit {
778 emitter: self.entity_state.entity_id,
779 event_type: TypeId::of::<Evt>(),
780 event,
781 });
782 }
783}
784
785impl<T> AppContext for Context<'_, T> {
786 #[inline]
787 fn new<U: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<U>) -> U) -> Entity<U> {
788 self.app.new(build_entity)
789 }
790
791 #[inline]
792 fn reserve_entity<U: 'static>(&mut self) -> Reservation<U> {
793 self.app.reserve_entity()
794 }
795
796 #[inline]
797 fn insert_entity<U: 'static>(
798 &mut self,
799 reservation: Reservation<U>,
800 build_entity: impl FnOnce(&mut Context<U>) -> U,
801 ) -> Entity<U> {
802 self.app.insert_entity(reservation, build_entity)
803 }
804
805 #[inline]
806 fn update_entity<U: 'static, R>(
807 &mut self,
808 handle: &Entity<U>,
809 update: impl FnOnce(&mut U, &mut Context<U>) -> R,
810 ) -> R {
811 self.app.update_entity(handle, update)
812 }
813
814 #[inline]
815 fn as_mut<'a, E>(&'a mut self, handle: &Entity<E>) -> super::GpuiBorrow<'a, E>
816 where
817 E: 'static,
818 {
819 self.app.as_mut(handle)
820 }
821
822 #[inline]
823 fn read_entity<U, R>(&self, handle: &Entity<U>, read: impl FnOnce(&U, &App) -> R) -> R
824 where
825 U: 'static,
826 {
827 self.app.read_entity(handle, read)
828 }
829
830 #[inline]
831 fn update_window<R, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<R>
832 where
833 F: FnOnce(AnyView, &mut Window, &mut App) -> R,
834 {
835 self.app.update_window(window, update)
836 }
837
838 #[inline]
839 fn read_window<U, R>(
840 &self,
841 window: &WindowHandle<U>,
842 read: impl FnOnce(Entity<U>, &App) -> R,
843 ) -> Result<R>
844 where
845 U: 'static,
846 {
847 self.app.read_window(window, read)
848 }
849
850 #[inline]
851 fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
852 where
853 R: Send + 'static,
854 {
855 self.app.background_executor.spawn(future)
856 }
857
858 #[inline]
859 fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> R
860 where
861 G: Global,
862 {
863 self.app.read_global(callback)
864 }
865}
866
867impl<T> Borrow<App> for Context<'_, T> {
868 fn borrow(&self) -> &App {
869 self.app
870 }
871}
872
873impl<T> BorrowMut<App> for Context<'_, T> {
874 fn borrow_mut(&mut self) -> &mut App {
875 self.app
876 }
877}