Skip to main content

open_gpui/
app.rs

1use open_gpui_scheduler::Instant;
2use std::{
3    any::{TypeId, type_name},
4    cell::{BorrowMutError, Cell, Ref, RefCell, RefMut},
5    marker::PhantomData,
6    mem,
7    ops::{Deref, DerefMut},
8    path::{Path, PathBuf},
9    rc::{Rc, Weak},
10    sync::{Arc, atomic::Ordering::SeqCst},
11    time::Duration,
12};
13
14use anyhow::{Context as _, Result, anyhow};
15use derive_more::{Deref, DerefMut};
16use futures::{
17    Future, FutureExt,
18    channel::oneshot,
19    future::{LocalBoxFuture, Shared},
20};
21use itertools::Itertools;
22use parking_lot::RwLock;
23use slotmap::SlotMap;
24
25pub use async_context::*;
26#[cfg(any(test, feature = "test-support"))]
27pub use bench_context::{BenchAppContext, BenchWindowContext};
28pub use context::*;
29pub use entity_map::*;
30#[cfg(any(test, feature = "test-support"))]
31pub use headless_app_context::*;
32use open_gpui_collections::{
33    FxHashMap, FxHashSet, HashMap, TypeIdHashMap, TypeIdHashSet, VecDeque,
34};
35use open_gpui_core_util::{ResultExt, debug_panic};
36use open_gpui_http_client::{HttpClient, Url};
37use smallvec::SmallVec;
38#[cfg(any(test, feature = "test-support"))]
39pub use test_app::*;
40#[cfg(any(test, feature = "test-support"))]
41pub use test_context::*;
42#[cfg(all(target_os = "macos", any(test, feature = "test-support")))]
43pub use visual_test_context::*;
44
45#[cfg(any(feature = "inspector", debug_assertions))]
46use crate::InspectorElementRegistry;
47use crate::{
48    Action, ActionBuildError, ActionRegistry, Any, AnyView, AnyWindowHandle, AppContext, Arena,
49    ArenaBox, Asset, AssetSource, BackgroundExecutor, Bounds, ClipboardItem, CursorStyle,
50    DispatchPhase, DisplayId, EventEmitter, FocusHandle, FocusMap, ForegroundExecutor, Global,
51    KeyBinding, KeyContext, Keymap, Keystroke, LayoutId, Menu, MenuItem, MouseButton, OwnedMenu,
52    PathPromptOptions, Pixels, Platform, PlatformDisplay, PlatformFocusedWindow,
53    PlatformHoveredWindow, PlatformKeyboardLayout, PlatformKeyboardMapper,
54    PlatformViewportCapabilities, PlatformViewportFlagCapabilities, Point, Priority, PromptBuilder,
55    PromptButton, PromptHandle, PromptLevel, Render, RenderImage, RenderablePromptHandle,
56    Reservation, ScreenCaptureSource, SharedString, SubscriberSet, Subscription, SvgRenderer, Task,
57    TextRenderingMode, TextSystem, ThermalState, Window, WindowAppearance, WindowButtonLayout,
58    WindowHandle, WindowId, WindowInvalidator,
59    colors::{Colors, GlobalColors},
60    hash, init_app_menus,
61};
62
63mod async_context;
64#[cfg(any(test, feature = "test-support"))]
65mod bench_context;
66mod context;
67mod entity_map;
68#[cfg(any(test, feature = "test-support"))]
69mod headless_app_context;
70#[cfg(any(test, feature = "test-support"))]
71mod test_app;
72#[cfg(any(test, feature = "test-support"))]
73mod test_context;
74#[cfg(all(target_os = "macos", any(test, feature = "test-support")))]
75mod visual_test_context;
76
77/// The duration for which futures returned from [Context::on_app_quit] can run before the application fully quits.
78pub const SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(200);
79
80/// Temporary(?) wrapper around [`RefCell<App>`] to help us debug any double borrows.
81/// Strongly consider removing after stabilization.
82#[doc(hidden)]
83pub struct AppCell {
84    app: RefCell<App>,
85}
86
87impl AppCell {
88    #[doc(hidden)]
89    #[track_caller]
90    pub fn borrow(&self) -> AppRef<'_> {
91        if option_env!("TRACK_THREAD_BORROWS").is_some() {
92            let thread_id = std::thread::current().id();
93            eprintln!("borrowed {thread_id:?}");
94        }
95        AppRef(self.app.borrow())
96    }
97
98    #[doc(hidden)]
99    #[track_caller]
100    pub fn borrow_mut(&self) -> AppRefMut<'_> {
101        if option_env!("TRACK_THREAD_BORROWS").is_some() {
102            let thread_id = std::thread::current().id();
103            eprintln!("borrowed {thread_id:?}");
104        }
105        AppRefMut(self.app.borrow_mut())
106    }
107
108    #[doc(hidden)]
109    #[track_caller]
110    pub fn try_borrow_mut(&self) -> Result<AppRefMut<'_>, BorrowMutError> {
111        if option_env!("TRACK_THREAD_BORROWS").is_some() {
112            let thread_id = std::thread::current().id();
113            eprintln!("borrowed {thread_id:?}");
114        }
115        Ok(AppRefMut(self.app.try_borrow_mut()?))
116    }
117}
118
119#[doc(hidden)]
120#[derive(Deref, DerefMut)]
121pub struct AppRef<'a>(Ref<'a, App>);
122
123impl Drop for AppRef<'_> {
124    fn drop(&mut self) {
125        if option_env!("TRACK_THREAD_BORROWS").is_some() {
126            let thread_id = std::thread::current().id();
127            eprintln!("dropped borrow from {thread_id:?}");
128        }
129    }
130}
131
132#[doc(hidden)]
133#[derive(Deref, DerefMut)]
134pub struct AppRefMut<'a>(RefMut<'a, App>);
135
136impl Drop for AppRefMut<'_> {
137    fn drop(&mut self) {
138        if option_env!("TRACK_THREAD_BORROWS").is_some() {
139            let thread_id = std::thread::current().id();
140            eprintln!("dropped {thread_id:?}");
141        }
142    }
143}
144
145#[cfg(target_family = "wasm")]
146thread_local! {
147    static RUNNING_WEB_APPLICATIONS: RefCell<Vec<Rc<AppCell>>> = RefCell::new(Vec::new());
148}
149
150/// A reference to a GPUI application, typically constructed in the `main` function of your app.
151/// You won't interact with this type much outside of initial configuration and startup.
152pub struct Application(Rc<AppCell>);
153
154/// Represents an application before it is fully launched. Once your app is
155/// configured, you'll start the app with `App::run`.
156impl Application {
157    /// Builds an app with a caller-provided platform implementation.
158    pub fn with_platform(platform: Rc<dyn Platform>) -> Self {
159        Self(App::new_app(
160            platform,
161            Arc::new(()),
162            Arc::new(NullHttpClient),
163        ))
164    }
165
166    /// Builds an app with accessibility (AccessKit) integration forcibly
167    /// disabled.
168    ///
169    /// In this mode, accessibility APIs (e.g.
170    /// [`div().role()`][crate::StatefulInteractiveElement::role]) silently
171    /// no-op.
172    ///
173    /// See the [accessibility guide](crate::_accessibility) for an overview of
174    /// the features this disables.
175    pub fn new_inaccessible(platform: Rc<dyn Platform>) -> Self {
176        let this = Self::with_platform(platform);
177        this.0.borrow_mut().accessibility_force_disabled = true;
178        this
179    }
180
181    /// Assigns the source of assets for the application.
182    pub fn with_assets(self, asset_source: impl AssetSource) -> Self {
183        let mut context_lock = self.0.borrow_mut();
184        let asset_source = Arc::new(asset_source);
185        context_lock.asset_source = asset_source.clone();
186        context_lock.svg_renderer = SvgRenderer::new(asset_source);
187        drop(context_lock);
188        self
189    }
190
191    /// Sets the HTTP client for the application.
192    pub fn with_http_client(self, http_client: Arc<dyn HttpClient>) -> Self {
193        let mut context_lock = self.0.borrow_mut();
194        context_lock.http_client = http_client;
195        drop(context_lock);
196        self
197    }
198
199    /// Configures when the application should automatically quit.
200    /// By default, [`QuitMode::Default`] is used.
201    pub fn with_quit_mode(self, mode: QuitMode) -> Self {
202        self.0.borrow_mut().quit_mode = mode;
203        self
204    }
205
206    /// Start the application. The provided callback will be called once the
207    /// app is fully launched.
208    pub fn run<F>(self, on_finish_launching: F)
209    where
210        F: 'static + FnOnce(&mut App),
211    {
212        let this = self.0.clone();
213        let platform = self.0.borrow().platform.clone();
214        #[cfg(target_family = "wasm")]
215        let keep_alive = this.clone();
216        platform.run(Box::new(move || {
217            let cx = &mut *this.borrow_mut();
218            on_finish_launching(cx);
219        }));
220        #[cfg(target_family = "wasm")]
221        RUNNING_WEB_APPLICATIONS.with(|applications| {
222            applications.borrow_mut().push(keep_alive);
223        });
224    }
225
226    /// Register a handler to be invoked when the platform instructs the application
227    /// to open one or more URLs.
228    pub fn on_open_urls<F>(&self, mut callback: F) -> &Self
229    where
230        F: 'static + FnMut(Vec<String>),
231    {
232        self.0.borrow().platform.on_open_urls(Box::new(callback));
233        self
234    }
235
236    /// Invokes a handler when an already-running application is launched.
237    /// On macOS, this can occur when the application icon is double-clicked or the app is launched via the dock.
238    pub fn on_reopen<F>(&self, mut callback: F) -> &Self
239    where
240        F: 'static + FnMut(&mut App),
241    {
242        let this = Rc::downgrade(&self.0);
243        self.0.borrow_mut().platform.on_reopen(Box::new(move || {
244            if let Some(app) = this.upgrade() {
245                callback(&mut app.borrow_mut());
246            }
247        }));
248        self
249    }
250
251    /// Invokes a handler when the system wakes from sleep.
252    pub fn on_system_wake<F>(&self, mut callback: F) -> &Self
253    where
254        F: 'static + FnMut(&mut App),
255    {
256        let this = Rc::downgrade(&self.0);
257        self.0
258            .borrow_mut()
259            .platform
260            .on_system_wake(Box::new(move || {
261                if let Some(app) = this.upgrade() {
262                    callback(&mut app.borrow_mut());
263                }
264            }));
265        self
266    }
267
268    /// Returns a handle to the [`BackgroundExecutor`] associated with this app, which can be used to spawn futures in the background.
269    pub fn background_executor(&self) -> BackgroundExecutor {
270        self.0.borrow().background_executor.clone()
271    }
272
273    /// Returns a handle to the [`ForegroundExecutor`] associated with this app, which can be used to spawn futures in the foreground.
274    pub fn foreground_executor(&self) -> ForegroundExecutor {
275        self.0.borrow().foreground_executor.clone()
276    }
277
278    /// Returns a reference to the [`TextSystem`] associated with this app.
279    pub fn text_system(&self) -> Arc<TextSystem> {
280        self.0.borrow().text_system.clone()
281    }
282
283    /// Returns the file URL of the executable with the specified name in the application bundle
284    pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
285        self.0.borrow().path_for_auxiliary_executable(name)
286    }
287}
288
289type Handler = Box<dyn FnMut(&mut App) -> bool + 'static>;
290type Listener = Box<dyn FnMut(&dyn Any, &mut App) -> bool + 'static>;
291pub(crate) type KeystrokeObserver =
292    Box<dyn FnMut(&KeystrokeEvent, &mut Window, &mut App) -> bool + 'static>;
293type QuitHandler = Box<dyn FnOnce(&mut App) -> LocalBoxFuture<'static, ()> + 'static>;
294type WindowClosedHandler = Box<dyn FnMut(&mut App, WindowId)>;
295type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut App) + 'static>;
296type NewEntityListener = Box<dyn FnMut(AnyEntity, &mut Option<&mut Window>, &mut App) + 'static>;
297
298/// Defines when the application should automatically quit.
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
300pub enum QuitMode {
301    /// Use [`QuitMode::Explicit`] on macOS and [`QuitMode::LastWindowClosed`] on other platforms.
302    #[default]
303    Default,
304    /// Quit automatically when the last window is closed.
305    LastWindowClosed,
306    /// Quit only when requested via [`App::quit`].
307    Explicit,
308}
309
310/// Controls when GPUI hides the mouse cursor in response to keyboard input.
311///
312/// Restoration on mouse motion is handled by the platform layer; this enum
313/// only describes the policy for *triggering* a hide.
314#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
315pub enum CursorHideMode {
316    /// Never hide the cursor automatically.
317    Never,
318    /// Hide on character-producing key presses (typing).
319    OnTyping,
320    /// Hide on character-producing key presses, *and* when a key binding
321    /// resolves to an action that consumes the keystroke.
322    #[default]
323    OnTypingAndAction,
324}
325
326#[doc(hidden)]
327#[derive(Clone, PartialEq, Eq)]
328pub struct SystemWindowTab {
329    pub id: WindowId,
330    pub title: SharedString,
331    pub handle: AnyWindowHandle,
332    pub last_active_at: Instant,
333}
334
335impl SystemWindowTab {
336    /// Create a new instance of the window tab.
337    pub fn new(title: SharedString, handle: AnyWindowHandle) -> Self {
338        Self {
339            id: handle.id,
340            title,
341            handle,
342            last_active_at: Instant::now(),
343        }
344    }
345}
346
347/// A controller for managing window tabs.
348#[derive(Default)]
349pub struct SystemWindowTabController {
350    visible: Option<bool>,
351    tab_groups: FxHashMap<usize, Vec<SystemWindowTab>>,
352}
353
354impl Global for SystemWindowTabController {}
355
356impl SystemWindowTabController {
357    /// Create a new instance of the window tab controller.
358    pub fn new() -> Self {
359        Self {
360            visible: None,
361            tab_groups: FxHashMap::default(),
362        }
363    }
364
365    /// Initialize the global window tab controller.
366    pub fn init(cx: &mut App) {
367        cx.set_global(SystemWindowTabController::new());
368    }
369
370    /// Get all tab groups.
371    pub fn tab_groups(&self) -> &FxHashMap<usize, Vec<SystemWindowTab>> {
372        &self.tab_groups
373    }
374
375    /// Get the next tab group window handle.
376    pub fn get_next_tab_group_window(cx: &mut App, id: WindowId) -> Option<&AnyWindowHandle> {
377        let controller = cx.global::<SystemWindowTabController>();
378        let current_group = controller
379            .tab_groups
380            .iter()
381            .find_map(|(group, tabs)| tabs.iter().find(|tab| tab.id == id).map(|_| group));
382
383        let current_group = current_group?;
384        // TODO: `.keys()` returns arbitrary order, what does "next" mean?
385        let mut group_ids: Vec<_> = controller.tab_groups.keys().collect();
386        let idx = group_ids.iter().position(|g| *g == current_group)?;
387        let next_idx = (idx + 1) % group_ids.len();
388
389        controller
390            .tab_groups
391            .get(group_ids[next_idx])
392            .and_then(|tabs| {
393                tabs.iter()
394                    .max_by_key(|tab| tab.last_active_at)
395                    .or_else(|| tabs.first())
396                    .map(|tab| &tab.handle)
397            })
398    }
399
400    /// Get the previous tab group window handle.
401    pub fn get_prev_tab_group_window(cx: &mut App, id: WindowId) -> Option<&AnyWindowHandle> {
402        let controller = cx.global::<SystemWindowTabController>();
403        let current_group = controller
404            .tab_groups
405            .iter()
406            .find_map(|(group, tabs)| tabs.iter().find(|tab| tab.id == id).map(|_| group));
407
408        let current_group = current_group?;
409        // TODO: `.keys()` returns arbitrary order, what does "previous" mean?
410        let mut group_ids: Vec<_> = controller.tab_groups.keys().collect();
411        let idx = group_ids.iter().position(|g| *g == current_group)?;
412        let prev_idx = if idx == 0 {
413            group_ids.len() - 1
414        } else {
415            idx - 1
416        };
417
418        controller
419            .tab_groups
420            .get(group_ids[prev_idx])
421            .and_then(|tabs| {
422                tabs.iter()
423                    .max_by_key(|tab| tab.last_active_at)
424                    .or_else(|| tabs.first())
425                    .map(|tab| &tab.handle)
426            })
427    }
428
429    /// Get all tabs in the same window.
430    pub fn tabs(&self, id: WindowId) -> Option<&Vec<SystemWindowTab>> {
431        self.tab_groups
432            .values()
433            .find(|tabs| tabs.iter().any(|tab| tab.id == id))
434    }
435
436    /// Initialize the visibility of the system window tab controller.
437    pub fn init_visible(cx: &mut App, visible: bool) {
438        let mut controller = cx.global_mut::<SystemWindowTabController>();
439        if controller.visible.is_none() {
440            controller.visible = Some(visible);
441        }
442    }
443
444    /// Get the visibility of the system window tab controller.
445    pub fn is_visible(&self) -> bool {
446        self.visible.unwrap_or(false)
447    }
448
449    /// Set the visibility of the system window tab controller.
450    pub fn set_visible(cx: &mut App, visible: bool) {
451        let mut controller = cx.global_mut::<SystemWindowTabController>();
452        controller.visible = Some(visible);
453    }
454
455    /// Update the last active of a window.
456    pub fn update_last_active(cx: &mut App, id: WindowId) {
457        let mut controller = cx.global_mut::<SystemWindowTabController>();
458        for windows in controller.tab_groups.values_mut() {
459            for tab in windows.iter_mut() {
460                if tab.id == id {
461                    tab.last_active_at = Instant::now();
462                }
463            }
464        }
465    }
466
467    /// Update the position of a tab within its group.
468    pub fn update_tab_position(cx: &mut App, id: WindowId, ix: usize) {
469        let mut controller = cx.global_mut::<SystemWindowTabController>();
470        for (_, windows) in controller.tab_groups.iter_mut() {
471            if let Some(current_pos) = windows.iter().position(|tab| tab.id == id) {
472                if ix < windows.len() && current_pos != ix {
473                    let window_tab = windows.remove(current_pos);
474                    windows.insert(ix, window_tab);
475                }
476                break;
477            }
478        }
479    }
480
481    /// Update the title of a tab.
482    pub fn update_tab_title(cx: &mut App, id: WindowId, title: SharedString) {
483        let controller = cx.global::<SystemWindowTabController>();
484        let tab = controller
485            .tab_groups
486            .values()
487            .flat_map(|windows| windows.iter())
488            .find(|tab| tab.id == id);
489
490        if tab.map_or(true, |t| t.title == title) {
491            return;
492        }
493
494        let mut controller = cx.global_mut::<SystemWindowTabController>();
495        for windows in controller.tab_groups.values_mut() {
496            for tab in windows.iter_mut() {
497                if tab.id == id {
498                    tab.title = title;
499                    return;
500                }
501            }
502        }
503    }
504
505    /// Insert a tab into a tab group.
506    pub fn add_tab(cx: &mut App, id: WindowId, tabs: Vec<SystemWindowTab>) {
507        let mut controller = cx.global_mut::<SystemWindowTabController>();
508        let Some(tab) = tabs.iter().find(|tab| tab.id == id).cloned() else {
509            return;
510        };
511
512        let mut expected_tab_ids: Vec<_> = tabs
513            .iter()
514            .filter(|tab| tab.id != id)
515            .map(|tab| tab.id)
516            .sorted()
517            .collect();
518
519        let mut tab_group_id = None;
520        for (group_id, group_tabs) in &controller.tab_groups {
521            let tab_ids: Vec<_> = group_tabs.iter().map(|tab| tab.id).sorted().collect();
522            if tab_ids == expected_tab_ids {
523                tab_group_id = Some(*group_id);
524                break;
525            }
526        }
527
528        if let Some(tab_group_id) = tab_group_id {
529            if let Some(tabs) = controller.tab_groups.get_mut(&tab_group_id) {
530                tabs.push(tab);
531            }
532        } else {
533            let new_group_id = controller.tab_groups.len();
534            controller.tab_groups.insert(new_group_id, tabs);
535        }
536    }
537
538    /// Remove a tab from a tab group.
539    pub fn remove_tab(cx: &mut App, id: WindowId) -> Option<SystemWindowTab> {
540        let mut controller = cx.global_mut::<SystemWindowTabController>();
541        let mut removed_tab = None;
542
543        controller.tab_groups.retain(|_, tabs| {
544            if let Some(pos) = tabs.iter().position(|tab| tab.id == id) {
545                removed_tab = Some(tabs.remove(pos));
546            }
547            !tabs.is_empty()
548        });
549
550        removed_tab
551    }
552
553    /// Move a tab to a new tab group.
554    pub fn move_tab_to_new_window(cx: &mut App, id: WindowId) {
555        let mut removed_tab = Self::remove_tab(cx, id);
556        let mut controller = cx.global_mut::<SystemWindowTabController>();
557
558        if let Some(tab) = removed_tab {
559            let new_group_id = controller.tab_groups.keys().max().map_or(0, |k| k + 1);
560            controller.tab_groups.insert(new_group_id, vec![tab]);
561        }
562    }
563
564    /// Merge all tab groups into a single group.
565    pub fn merge_all_windows(cx: &mut App, id: WindowId) {
566        let mut controller = cx.global_mut::<SystemWindowTabController>();
567        let Some(initial_tabs) = controller.tabs(id) else {
568            return;
569        };
570
571        let initial_tabs_len = initial_tabs.len();
572        let mut all_tabs = initial_tabs.clone();
573
574        for (_, mut tabs) in controller.tab_groups.drain() {
575            tabs.retain(|tab| !all_tabs[..initial_tabs_len].contains(tab));
576            all_tabs.extend(tabs);
577        }
578
579        controller.tab_groups.insert(0, all_tabs);
580    }
581
582    /// Selects the next tab in the tab group in the trailing direction.
583    pub fn select_next_tab(cx: &mut App, id: WindowId) {
584        let mut controller = cx.global_mut::<SystemWindowTabController>();
585        let Some(tabs) = controller.tabs(id) else {
586            return;
587        };
588
589        let current_index = tabs.iter().position(|tab| tab.id == id).unwrap();
590        let next_index = (current_index + 1) % tabs.len();
591
592        let _ = &tabs[next_index].handle.update(cx, |_, window, _| {
593            window.activate_window();
594        });
595    }
596
597    /// Selects the previous tab in the tab group in the leading direction.
598    pub fn select_previous_tab(cx: &mut App, id: WindowId) {
599        let mut controller = cx.global_mut::<SystemWindowTabController>();
600        let Some(tabs) = controller.tabs(id) else {
601            return;
602        };
603
604        let current_index = tabs.iter().position(|tab| tab.id == id).unwrap();
605        let previous_index = if current_index == 0 {
606            tabs.len() - 1
607        } else {
608            current_index - 1
609        };
610
611        let _ = &tabs[previous_index].handle.update(cx, |_, window, _| {
612            window.activate_window();
613        });
614    }
615}
616
617pub(crate) enum GpuiMode {
618    #[cfg(any(test, feature = "test-support"))]
619    Test {
620        skip_drawing: bool,
621    },
622    Production,
623}
624
625impl GpuiMode {
626    #[cfg(any(test, feature = "test-support"))]
627    pub fn test() -> Self {
628        GpuiMode::Test {
629            skip_drawing: false,
630        }
631    }
632
633    #[inline]
634    pub(crate) fn skip_drawing(&self) -> bool {
635        match self {
636            #[cfg(any(test, feature = "test-support"))]
637            GpuiMode::Test { skip_drawing } => *skip_drawing,
638            GpuiMode::Production => false,
639        }
640    }
641}
642
643/// Contains the state of the full application, and passed as a reference to a variety of callbacks.
644/// Other [Context] derefs to this type.
645/// You need a reference to an `App` to access the state of a [Entity].
646pub struct App {
647    pub(crate) this: Weak<AppCell>,
648    pub(crate) platform: Rc<dyn Platform>,
649    text_system: Arc<TextSystem>,
650
651    pub(crate) actions: Rc<ActionRegistry>,
652    pub(crate) active_drag: Option<AnyDrag>,
653    pub(crate) background_executor: BackgroundExecutor,
654    pub(crate) foreground_executor: ForegroundExecutor,
655    pub(crate) entities: EntityMap,
656    pub(crate) new_entity_observers: SubscriberSet<TypeId, NewEntityListener>,
657    pub(crate) windows: SlotMap<WindowId, Option<Box<Window>>>,
658    pub(crate) window_handles: FxHashMap<WindowId, AnyWindowHandle>,
659    pub(crate) focus_handles: Arc<FocusMap>,
660    pub(crate) keymap: Rc<RefCell<Keymap>>,
661    pub(crate) keyboard_layout: Box<dyn PlatformKeyboardLayout>,
662    pub(crate) keyboard_mapper: Rc<dyn PlatformKeyboardMapper>,
663    pub(crate) global_action_listeners:
664        TypeIdHashMap<Vec<Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Self)>>>,
665    pending_effects: VecDeque<Effect>,
666
667    pub(crate) observers: SubscriberSet<EntityId, Handler>,
668    pub(crate) event_listeners: SubscriberSet<EntityId, (TypeId, Listener)>,
669    pub(crate) keystroke_observers: SubscriberSet<(), KeystrokeObserver>,
670    pub(crate) keystroke_interceptors: SubscriberSet<(), KeystrokeObserver>,
671    pub(crate) keyboard_layout_observers: SubscriberSet<(), Handler>,
672    pub(crate) thermal_state_observers: SubscriberSet<(), Handler>,
673    pub(crate) release_listeners: SubscriberSet<EntityId, ReleaseListener>,
674    pub(crate) global_observers: SubscriberSet<TypeId, Handler>,
675    pub(crate) quit_observers: SubscriberSet<(), QuitHandler>,
676    pub(crate) restart_observers: SubscriberSet<(), Handler>,
677    pub(crate) window_closed_observers: SubscriberSet<(), WindowClosedHandler>,
678
679    /// Per-App element arena. This isolates element allocations between different
680    /// App instances (important for tests where multiple Apps run concurrently).
681    pub(crate) element_arena: RefCell<Arena>,
682    /// Per-App event arena.
683    pub(crate) event_arena: Arena,
684
685    // Drop globals last. We need to ensure all tasks owned by entities and
686    // callbacks are marked cancelled at this point as this will also shutdown
687    // the tokio runtime. As any task attempting to spawn a blocking tokio task,
688    // might panic.
689    pub(crate) globals_by_type: TypeIdHashMap<Box<dyn Any>>,
690
691    // assets
692    pub(crate) loading_assets: FxHashMap<(TypeId, u64), Box<dyn Any>>,
693    asset_source: Arc<dyn AssetSource>,
694    pub(crate) svg_renderer: SvgRenderer,
695    http_client: Arc<dyn HttpClient>,
696
697    // below is plain data, the drop order is insignificant here
698    pub(crate) pending_notifications: FxHashSet<EntityId>,
699    pub(crate) pending_global_notifications: TypeIdHashSet,
700    pub(crate) restart_path: Option<PathBuf>,
701    pub(crate) layout_id_buffer: Vec<LayoutId>, // We recycle this memory across layout requests.
702    pub(crate) propagate_event: bool,
703    pub(crate) prompt_builder: Option<PromptBuilder>,
704    pub(crate) window_invalidators_by_entity:
705        FxHashMap<EntityId, FxHashMap<WindowId, WindowInvalidator>>,
706    pub(crate) tracked_entities: FxHashMap<WindowId, FxHashSet<EntityId>>,
707    pub(crate) current_window_by_entity: FxHashMap<EntityId, WindowId>,
708    #[cfg(any(feature = "inspector", debug_assertions))]
709    pub(crate) inspector_renderer: Option<crate::InspectorRenderer>,
710    #[cfg(any(feature = "inspector", debug_assertions))]
711    pub(crate) inspector_element_registry: InspectorElementRegistry,
712    #[cfg(any(test, feature = "test-support", debug_assertions))]
713    pub(crate) name: Option<&'static str>,
714    pub(crate) text_rendering_mode: Rc<Cell<TextRenderingMode>>,
715
716    pub(crate) window_update_stack: Vec<WindowId>,
717    pub(crate) mode: GpuiMode,
718    pub(crate) cursor_hide_mode: CursorHideMode,
719    /// Whether the app was created by [`Application::new_inaccessible`]. No
720    /// accesskit APIs will be called when this flag is set.
721    pub(crate) accessibility_force_disabled: bool,
722    flushing_effects: bool,
723    pending_updates: usize,
724    quit_mode: QuitMode,
725    quitting: bool,
726
727    // We need to ensure the leak detector drops last, after all tasks, callbacks and things have been dropped.
728    // Otherwise it may report false positives.
729    #[cfg(any(test, feature = "leak-detection"))]
730    _ref_counts: Arc<RwLock<EntityRefCounts>>,
731}
732
733impl App {
734    #[allow(clippy::new_ret_no_self)]
735    pub(crate) fn new_app(
736        platform: Rc<dyn Platform>,
737        asset_source: Arc<dyn AssetSource>,
738        http_client: Arc<dyn HttpClient>,
739    ) -> Rc<AppCell> {
740        let background_executor = platform.background_executor();
741        let foreground_executor = platform.foreground_executor();
742        assert!(
743            background_executor.is_main_thread(),
744            "must construct App on main thread"
745        );
746
747        let text_system = Arc::new(TextSystem::new(platform.text_system()));
748        let entities = EntityMap::new();
749        let keyboard_layout = platform.keyboard_layout();
750        let keyboard_mapper = platform.keyboard_mapper();
751
752        #[cfg(any(test, feature = "leak-detection"))]
753        let _ref_counts = entities.ref_counts_drop_handle();
754
755        let app = Rc::new_cyclic(|this| AppCell {
756            app: RefCell::new(App {
757                this: this.clone(),
758                platform: platform.clone(),
759                text_system,
760                text_rendering_mode: Rc::new(Cell::new(TextRenderingMode::default())),
761                mode: GpuiMode::Production,
762                actions: Rc::new(ActionRegistry::default()),
763                flushing_effects: false,
764                pending_updates: 0,
765                active_drag: None,
766                background_executor,
767                foreground_executor,
768                svg_renderer: SvgRenderer::new(asset_source.clone()),
769                loading_assets: Default::default(),
770                asset_source,
771                http_client,
772                globals_by_type: Default::default(),
773                entities,
774                new_entity_observers: SubscriberSet::new(),
775                windows: SlotMap::with_key(),
776                window_update_stack: Vec::new(),
777                window_handles: FxHashMap::default(),
778                focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
779                keymap: Rc::new(RefCell::new(Keymap::default())),
780                keyboard_layout,
781                keyboard_mapper,
782                global_action_listeners: Default::default(),
783                pending_effects: VecDeque::new(),
784                pending_notifications: FxHashSet::default(),
785                pending_global_notifications: Default::default(),
786                observers: SubscriberSet::new(),
787                tracked_entities: FxHashMap::default(),
788                window_invalidators_by_entity: FxHashMap::default(),
789                current_window_by_entity: FxHashMap::default(),
790                event_listeners: SubscriberSet::new(),
791                release_listeners: SubscriberSet::new(),
792                keystroke_observers: SubscriberSet::new(),
793                keystroke_interceptors: SubscriberSet::new(),
794                keyboard_layout_observers: SubscriberSet::new(),
795                thermal_state_observers: SubscriberSet::new(),
796                global_observers: SubscriberSet::new(),
797                quit_observers: SubscriberSet::new(),
798                restart_observers: SubscriberSet::new(),
799                restart_path: None,
800                window_closed_observers: SubscriberSet::new(),
801                layout_id_buffer: Default::default(),
802                propagate_event: true,
803                prompt_builder: Some(PromptBuilder::Default),
804                #[cfg(any(feature = "inspector", debug_assertions))]
805                inspector_renderer: None,
806                #[cfg(any(feature = "inspector", debug_assertions))]
807                inspector_element_registry: InspectorElementRegistry::default(),
808                quit_mode: QuitMode::default(),
809                quitting: false,
810                cursor_hide_mode: CursorHideMode::default(),
811                accessibility_force_disabled: false,
812
813                #[cfg(any(test, feature = "test-support", debug_assertions))]
814                name: None,
815                element_arena: RefCell::new(Arena::new(1024 * 1024)),
816                event_arena: Arena::new(1024 * 1024),
817
818                #[cfg(any(test, feature = "leak-detection"))]
819                _ref_counts,
820            }),
821        });
822
823        init_app_menus(platform.as_ref(), &app.borrow());
824        SystemWindowTabController::init(&mut app.borrow_mut());
825
826        platform.on_keyboard_layout_change(Box::new({
827            let app = Rc::downgrade(&app);
828            move || {
829                if let Some(app) = app.upgrade() {
830                    let cx = &mut app.borrow_mut();
831                    cx.keyboard_layout = cx.platform.keyboard_layout();
832                    cx.keyboard_mapper = cx.platform.keyboard_mapper();
833                    cx.keyboard_layout_observers
834                        .clone()
835                        .retain(&(), move |callback| (callback)(cx));
836                }
837            }
838        }));
839
840        platform.on_thermal_state_change(Box::new({
841            let app = Rc::downgrade(&app);
842            move || {
843                if let Some(app) = app.upgrade() {
844                    let cx = &mut app.borrow_mut();
845                    cx.thermal_state_observers
846                        .clone()
847                        .retain(&(), move |callback| (callback)(cx));
848                }
849            }
850        }));
851
852        platform.on_quit(Box::new({
853            let cx = Rc::downgrade(&app);
854            move || {
855                if let Some(cx) = cx.upgrade() {
856                    cx.borrow_mut().shutdown();
857                }
858            }
859        }));
860
861        app
862    }
863
864    #[doc(hidden)]
865    pub fn ref_counts_drop_handle(&self) -> impl Sized + use<> {
866        self.entities.ref_counts_drop_handle()
867    }
868
869    /// Captures a snapshot of all entities that currently have alive handles.
870    ///
871    /// The returned [`LeakDetectorSnapshot`] can later be passed to
872    /// [`assert_no_new_leaks`](Self::assert_no_new_leaks) to verify that no
873    /// entities created after the snapshot are still alive.
874    #[cfg(any(test, feature = "leak-detection"))]
875    pub fn leak_detector_snapshot(&self) -> LeakDetectorSnapshot {
876        self.entities.leak_detector_snapshot()
877    }
878
879    /// Asserts that no entities created after `snapshot` still have alive handles.
880    ///
881    /// Entities that were already tracked at the time of the snapshot are ignored,
882    /// even if they still have handles. Only *new* entities (those whose
883    /// `EntityId` was not present in the snapshot) are considered leaks.
884    ///
885    /// # Panics
886    ///
887    /// Panics if any new entity handles exist. The panic message lists every
888    /// leaked entity with its type name, and includes allocation-site backtraces
889    /// when `LEAK_BACKTRACE` is set.
890    #[cfg(any(test, feature = "leak-detection"))]
891    pub fn assert_no_new_leaks(&self, snapshot: &LeakDetectorSnapshot) {
892        self.entities.assert_no_new_leaks(snapshot)
893    }
894
895    /// Quit the application gracefully. Handlers registered with [`Context::on_app_quit`]
896    /// will be given `SHUTDOWN_TIMEOUT` to complete before exiting.
897    pub fn shutdown(&mut self) {
898        let mut futures = Vec::new();
899
900        for observer in self.quit_observers.remove(&()) {
901            futures.push(observer(self));
902        }
903
904        self.windows.clear();
905        self.window_handles.clear();
906        self.flush_effects();
907        self.quitting = true;
908
909        let futures = futures::future::join_all(futures);
910        if self
911            .foreground_executor
912            .block_with_timeout(SHUTDOWN_TIMEOUT, futures)
913            .is_err()
914        {
915            log::error!("timed out waiting on app_will_quit");
916        }
917
918        self.quitting = false;
919    }
920
921    /// Get the id of the current keyboard layout
922    pub fn keyboard_layout(&self) -> &dyn PlatformKeyboardLayout {
923        self.keyboard_layout.as_ref()
924    }
925
926    /// Get the current keyboard mapper.
927    pub fn keyboard_mapper(&self) -> &Rc<dyn PlatformKeyboardMapper> {
928        &self.keyboard_mapper
929    }
930
931    /// Invokes a handler when the current keyboard layout changes
932    pub fn on_keyboard_layout_change<F>(&self, mut callback: F) -> Subscription
933    where
934        F: 'static + FnMut(&mut App),
935    {
936        let (subscription, activate) = self.keyboard_layout_observers.insert(
937            (),
938            Box::new(move |cx| {
939                callback(cx);
940                true
941            }),
942        );
943        activate();
944        subscription
945    }
946
947    /// Gracefully quit the application via the platform's standard routine.
948    pub fn quit(&self) {
949        self.platform.quit();
950    }
951
952    /// Returns the current policy for hiding the cursor in response to
953    /// keyboard input.
954    pub fn cursor_hide_mode(&self) -> CursorHideMode {
955        self.cursor_hide_mode
956    }
957
958    /// Sets the policy controlling when GPUI hides the cursor in response
959    /// to keyboard input.
960    pub fn set_cursor_hide_mode(&mut self, mode: CursorHideMode) {
961        self.cursor_hide_mode = mode;
962    }
963
964    /// Returns whether the cursor is currently visible according to the
965    /// platform. This will report `false` after a keyboard input has hidden
966    /// the cursor and the user has not yet moved the mouse to restore it.
967    ///
968    /// See [`App::set_cursor_hide_mode`].
969    pub fn is_cursor_visible(&self) -> bool {
970        self.platform.is_cursor_visible()
971    }
972
973    /// Schedules all windows in the application to be redrawn. This can be called
974    /// multiple times in an update cycle and still result in a single redraw.
975    pub fn refresh_windows(&mut self) {
976        self.pending_effects.push_back(Effect::RefreshWindows);
977    }
978
979    pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
980        self.start_update();
981        let result = update(self);
982        self.finish_update();
983        result
984    }
985
986    pub(crate) fn start_update(&mut self) {
987        self.pending_updates += 1;
988    }
989
990    pub(crate) fn finish_update(&mut self) {
991        if !self.flushing_effects && self.pending_updates == 1 {
992            self.flushing_effects = true;
993            self.flush_effects();
994            self.flushing_effects = false;
995        }
996        self.pending_updates -= 1;
997    }
998
999    /// Arrange a callback to be invoked when the given entity calls `notify` on its respective context.
1000    pub fn observe<W>(
1001        &mut self,
1002        entity: &Entity<W>,
1003        mut on_notify: impl FnMut(Entity<W>, &mut App) + 'static,
1004    ) -> Subscription
1005    where
1006        W: 'static,
1007    {
1008        self.observe_internal(entity, move |e, cx| {
1009            on_notify(e, cx);
1010            true
1011        })
1012    }
1013
1014    pub(crate) fn detect_accessed_entities<R>(
1015        &mut self,
1016        callback: impl FnOnce(&mut App) -> R,
1017    ) -> (R, FxHashSet<EntityId>) {
1018        let accessed_entities_start = self.entities.accessed_entities.get_mut().clone();
1019        let result = callback(self);
1020        let entities_accessed_in_callback = self
1021            .entities
1022            .accessed_entities
1023            .get_mut()
1024            .difference(&accessed_entities_start)
1025            .copied()
1026            .collect::<FxHashSet<EntityId>>();
1027        (result, entities_accessed_in_callback)
1028    }
1029
1030    pub(crate) fn record_entities_accessed(
1031        &mut self,
1032        window_handle: AnyWindowHandle,
1033        invalidator: WindowInvalidator,
1034        entities: &FxHashSet<EntityId>,
1035    ) {
1036        let mut tracked_entities =
1037            std::mem::take(self.tracked_entities.entry(window_handle.id).or_default());
1038        for entity in tracked_entities.iter() {
1039            self.window_invalidators_by_entity
1040                .entry(*entity)
1041                .and_modify(|windows| {
1042                    windows.remove(&window_handle.id);
1043                });
1044        }
1045        for entity in entities.iter() {
1046            self.window_invalidators_by_entity
1047                .entry(*entity)
1048                .or_default()
1049                .insert(window_handle.id, invalidator.clone());
1050            self.current_window_by_entity
1051                .insert(*entity, window_handle.id);
1052        }
1053        tracked_entities.clear();
1054        tracked_entities.extend(entities.iter().copied());
1055        self.tracked_entities
1056            .insert(window_handle.id, tracked_entities);
1057    }
1058
1059    pub(crate) fn new_observer(&mut self, key: EntityId, value: Handler) -> Subscription {
1060        let (subscription, activate) = self.observers.insert(key, value);
1061        self.defer(move |_| activate());
1062        subscription
1063    }
1064
1065    pub(crate) fn observe_internal<W>(
1066        &mut self,
1067        entity: &Entity<W>,
1068        mut on_notify: impl FnMut(Entity<W>, &mut App) -> bool + 'static,
1069    ) -> Subscription
1070    where
1071        W: 'static,
1072    {
1073        let entity_id = entity.entity_id();
1074        let handle = entity.downgrade();
1075        self.new_observer(
1076            entity_id,
1077            Box::new(move |cx| {
1078                if let Some(entity) = handle.upgrade() {
1079                    on_notify(entity, cx)
1080                } else {
1081                    false
1082                }
1083            }),
1084        )
1085    }
1086
1087    /// Arrange for the given callback to be invoked whenever the given entity emits an event of a given type.
1088    /// The callback is provided a handle to the emitting entity and a reference to the emitted event.
1089    pub fn subscribe<T, Event>(
1090        &mut self,
1091        entity: &Entity<T>,
1092        mut on_event: impl FnMut(Entity<T>, &Event, &mut App) + 'static,
1093    ) -> Subscription
1094    where
1095        T: 'static + EventEmitter<Event>,
1096        Event: 'static,
1097    {
1098        self.subscribe_internal(entity, move |entity, event, cx| {
1099            on_event(entity, event, cx);
1100            true
1101        })
1102    }
1103
1104    pub(crate) fn new_subscription(
1105        &mut self,
1106        key: EntityId,
1107        value: (TypeId, Listener),
1108    ) -> Subscription {
1109        let (subscription, activate) = self.event_listeners.insert(key, value);
1110        self.defer(move |_| activate());
1111        subscription
1112    }
1113    pub(crate) fn subscribe_internal<T, Evt>(
1114        &mut self,
1115        entity: &Entity<T>,
1116        mut on_event: impl FnMut(Entity<T>, &Evt, &mut App) -> bool + 'static,
1117    ) -> Subscription
1118    where
1119        T: 'static + EventEmitter<Evt>,
1120        Evt: 'static,
1121    {
1122        let entity_id = entity.entity_id();
1123        let handle = entity.downgrade();
1124        self.new_subscription(
1125            entity_id,
1126            (
1127                TypeId::of::<Evt>(),
1128                Box::new(move |event, cx| {
1129                    let event: &Evt = event.downcast_ref().expect("invalid event type");
1130                    if let Some(entity) = handle.upgrade() {
1131                        on_event(entity, event, cx)
1132                    } else {
1133                        false
1134                    }
1135                }),
1136            ),
1137        )
1138    }
1139
1140    /// Returns handles to all open windows in the application.
1141    /// Each handle could be downcast to a handle typed for the root view of that window.
1142    /// To find all windows of a given type, you could filter on
1143    pub fn windows(&self) -> Vec<AnyWindowHandle> {
1144        self.windows
1145            .keys()
1146            .flat_map(|window_id| self.window_handles.get(&window_id).copied())
1147            .collect()
1148    }
1149
1150    /// Returns the window handles ordered by their appearance on screen, front to back.
1151    ///
1152    /// The first window in the returned list is the active/topmost window of the application.
1153    ///
1154    /// This method returns None if the platform doesn't implement the method yet.
1155    pub fn window_stack(&self) -> Option<Vec<AnyWindowHandle>> {
1156        self.platform.window_stack()
1157    }
1158
1159    /// Returns platform capabilities relevant to multi-viewport docking.
1160    pub fn viewport_capabilities(&self) -> PlatformViewportCapabilities {
1161        self.platform.viewport_capabilities()
1162    }
1163
1164    /// Returns platform support for ImGui-style viewport window flags.
1165    pub fn viewport_flag_capabilities(&self) -> PlatformViewportFlagCapabilities {
1166        self.platform.viewport_flag_capabilities()
1167    }
1168
1169    /// Returns the backend hovered-window signal for the current pointer snapshot.
1170    pub fn hovered_window(&self) -> PlatformHoveredWindow {
1171        self.platform.hovered_window()
1172    }
1173
1174    /// Returns the backend focused-window signal for the current platform snapshot.
1175    pub fn focused_window(&self) -> PlatformFocusedWindow {
1176        self.platform.focused_window()
1177    }
1178
1179    /// Returns a handle to the window that is currently focused at the platform level, if one exists.
1180    pub fn active_window(&self) -> Option<AnyWindowHandle> {
1181        self.platform.active_window()
1182    }
1183
1184    /// Returns whether a mouse button is currently pressed when the platform can report it.
1185    pub fn mouse_button_is_pressed(&self, button: MouseButton) -> Option<bool> {
1186        self.platform.mouse_button_is_pressed(button)
1187    }
1188
1189    /// Opens a new window with the given option and the root view returned by the given function.
1190    /// The function is invoked with a `Window`, which can be used to interact with window-specific
1191    /// functionality.
1192    pub fn open_window<V: 'static + Render>(
1193        &mut self,
1194        options: crate::WindowOptions,
1195        build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity<V>,
1196    ) -> anyhow::Result<WindowHandle<V>> {
1197        self.update(|cx| {
1198            let id = cx.windows.insert(None);
1199            let handle = WindowHandle::new(id);
1200            match Window::new(handle.into(), options, cx) {
1201                Ok(mut window) => {
1202                    cx.window_update_stack.push(id);
1203                    let root_view = build_root_view(&mut window, cx);
1204                    cx.window_update_stack.pop();
1205                    window.root.replace(root_view.into());
1206                    window.defer(cx, |window: &mut Window, cx| window.appearance_changed(cx));
1207
1208                    // allow a window to draw at least once before returning
1209                    // this didn't cause any issues on non windows platforms as it seems we always won the race to on_request_frame
1210                    // on windows we quite frequently lose the race and return a window that has never rendered, which leads to a crash
1211                    // where DispatchTree::root_node_id asserts on empty nodes
1212                    let clear = window.draw(cx);
1213                    clear.clear();
1214
1215                    cx.window_handles.insert(id, window.handle);
1216                    cx.windows.get_mut(id).unwrap().replace(Box::new(window));
1217                    Ok(handle)
1218                }
1219                Err(e) => {
1220                    cx.windows.remove(id);
1221                    Err(e)
1222                }
1223            }
1224        })
1225    }
1226
1227    /// Instructs the platform to activate the application by bringing it to the foreground.
1228    pub fn activate(&self, ignoring_other_apps: bool) {
1229        self.platform.activate(ignoring_other_apps);
1230    }
1231
1232    /// Hide the application at the platform level.
1233    pub fn hide(&self) {
1234        self.platform.hide();
1235    }
1236
1237    /// Hide other applications at the platform level.
1238    pub fn hide_other_apps(&self) {
1239        self.platform.hide_other_apps();
1240    }
1241
1242    /// Unhide other applications at the platform level.
1243    pub fn unhide_other_apps(&self) {
1244        self.platform.unhide_other_apps();
1245    }
1246
1247    /// Returns the list of currently active displays.
1248    pub fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
1249        self.platform.displays()
1250    }
1251
1252    /// Returns the primary display that will be used for new windows.
1253    pub fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
1254        self.platform.primary_display()
1255    }
1256
1257    /// Returns whether `screen_capture_sources` may work.
1258    pub fn is_screen_capture_supported(&self) -> bool {
1259        self.platform.is_screen_capture_supported()
1260    }
1261
1262    /// Returns a list of available screen capture sources.
1263    pub fn screen_capture_sources(
1264        &self,
1265    ) -> oneshot::Receiver<Result<Vec<Rc<dyn ScreenCaptureSource>>>> {
1266        self.platform.screen_capture_sources()
1267    }
1268
1269    /// Returns the display with the given ID, if one exists.
1270    pub fn find_display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
1271        self.displays()
1272            .iter()
1273            .find(|display| display.id() == id)
1274            .cloned()
1275    }
1276
1277    /// Returns the current thermal state of the system.
1278    pub fn thermal_state(&self) -> ThermalState {
1279        self.platform.thermal_state()
1280    }
1281
1282    /// Invokes a handler when the thermal state changes
1283    pub fn on_thermal_state_change<F>(&self, mut callback: F) -> Subscription
1284    where
1285        F: 'static + FnMut(&mut App),
1286    {
1287        let (subscription, activate) = self.thermal_state_observers.insert(
1288            (),
1289            Box::new(move |cx| {
1290                callback(cx);
1291                true
1292            }),
1293        );
1294        activate();
1295        subscription
1296    }
1297
1298    /// Returns the appearance of the application's windows.
1299    pub fn window_appearance(&self) -> WindowAppearance {
1300        self.platform.window_appearance()
1301    }
1302
1303    /// Returns the window button layout configuration when supported.
1304    pub fn button_layout(&self) -> Option<WindowButtonLayout> {
1305        self.platform.button_layout()
1306    }
1307
1308    /// Reads data from the platform clipboard.
1309    pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
1310        self.platform.read_from_clipboard()
1311    }
1312
1313    /// Sets the text rendering mode for the application.
1314    pub fn set_text_rendering_mode(&mut self, mode: TextRenderingMode) {
1315        self.text_rendering_mode.set(mode);
1316    }
1317
1318    /// Returns the current text rendering mode for the application.
1319    pub fn text_rendering_mode(&self) -> TextRenderingMode {
1320        self.text_rendering_mode.get()
1321    }
1322
1323    /// Writes data to the platform clipboard.
1324    pub fn write_to_clipboard(&self, item: ClipboardItem) {
1325        self.platform.write_to_clipboard(item)
1326    }
1327
1328    /// Reads data from the primary selection buffer.
1329    /// Only available on Linux.
1330    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
1331    pub fn read_from_primary(&self) -> Option<ClipboardItem> {
1332        self.platform.read_from_primary()
1333    }
1334
1335    /// Writes data to the primary selection buffer.
1336    /// Only available on Linux.
1337    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
1338    pub fn write_to_primary(&self, item: ClipboardItem) {
1339        self.platform.write_to_primary(item)
1340    }
1341
1342    /// Reads data from macOS's "Find" pasteboard.
1343    ///
1344    /// Used to share the current search string between apps.
1345    ///
1346    /// https://developer.apple.com/documentation/appkit/nspasteboard/name-swift.struct/find
1347    #[cfg(target_os = "macos")]
1348    pub fn read_from_find_pasteboard(&self) -> Option<ClipboardItem> {
1349        self.platform.read_from_find_pasteboard()
1350    }
1351
1352    /// Writes data to macOS's "Find" pasteboard.
1353    ///
1354    /// Used to share the current search string between apps.
1355    ///
1356    /// https://developer.apple.com/documentation/appkit/nspasteboard/name-swift.struct/find
1357    #[cfg(target_os = "macos")]
1358    pub fn write_to_find_pasteboard(&self, item: ClipboardItem) {
1359        self.platform.write_to_find_pasteboard(item)
1360    }
1361
1362    /// Writes credentials to the platform keychain.
1363    pub fn write_credentials(
1364        &self,
1365        url: &str,
1366        username: &str,
1367        password: &[u8],
1368    ) -> Task<Result<()>> {
1369        self.platform.write_credentials(url, username, password)
1370    }
1371
1372    /// Reads credentials from the platform keychain.
1373    pub fn read_credentials(&self, url: &str) -> Task<Result<Option<(String, Vec<u8>)>>> {
1374        self.platform.read_credentials(url)
1375    }
1376
1377    /// Deletes credentials from the platform keychain.
1378    pub fn delete_credentials(&self, url: &str) -> Task<Result<()>> {
1379        self.platform.delete_credentials(url)
1380    }
1381
1382    /// Directs the platform's default browser to open the given URL.
1383    pub fn open_url(&self, url: &str) {
1384        self.platform.open_url(url);
1385    }
1386
1387    /// Registers the given URL scheme (e.g. `open-gpui` for `open-gpui://` URLs) to be
1388    /// opened by the current app.
1389    ///
1390    /// On some platforms (e.g. macOS) you may be able to register URL schemes
1391    /// as part of app distribution, but this method exists to let you register
1392    /// schemes at runtime.
1393    pub fn register_url_scheme(&self, scheme: &str) -> Task<Result<()>> {
1394        self.platform.register_url_scheme(scheme)
1395    }
1396
1397    /// Returns the full pathname of the current app bundle.
1398    ///
1399    /// Returns an error if the app is not being run from a bundle.
1400    pub fn app_path(&self) -> Result<PathBuf> {
1401        self.platform.app_path()
1402    }
1403
1404    /// On Linux, returns the name of the compositor in use.
1405    ///
1406    /// Returns an empty string on other platforms.
1407    pub fn compositor_name(&self) -> &'static str {
1408        self.platform.compositor_name()
1409    }
1410
1411    /// Returns the file URL of the executable with the specified name in the application bundle
1412    pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
1413        self.platform.path_for_auxiliary_executable(name)
1414    }
1415
1416    /// Displays a platform modal for selecting paths.
1417    ///
1418    /// When one or more paths are selected, they'll be relayed asynchronously via the returned oneshot channel.
1419    /// If cancelled, a `None` will be relayed instead.
1420    /// May return an error on Linux if the file picker couldn't be opened.
1421    pub fn prompt_for_paths(
1422        &self,
1423        options: PathPromptOptions,
1424    ) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
1425        self.platform.prompt_for_paths(options)
1426    }
1427
1428    /// Displays a platform modal for selecting a new path where a file can be saved.
1429    ///
1430    /// The provided directory will be used to set the initial location.
1431    /// When a path is selected, it is relayed asynchronously via the returned oneshot channel.
1432    /// If cancelled, a `None` will be relayed instead.
1433    /// May return an error on Linux if the file picker couldn't be opened.
1434    pub fn prompt_for_new_path(
1435        &self,
1436        directory: &Path,
1437        suggested_name: Option<&str>,
1438    ) -> oneshot::Receiver<Result<Option<PathBuf>>> {
1439        self.platform.prompt_for_new_path(directory, suggested_name)
1440    }
1441
1442    /// Reveals the specified path at the platform level, such as in Finder on macOS.
1443    pub fn reveal_path(&self, path: &Path) {
1444        self.platform.reveal_path(path)
1445    }
1446
1447    /// Opens the specified path with the system's default application.
1448    pub fn open_with_system(&self, path: &Path) {
1449        self.platform.open_with_system(path)
1450    }
1451
1452    /// Returns whether the user has configured scrollbars to auto-hide at the platform level.
1453    pub fn should_auto_hide_scrollbars(&self) -> bool {
1454        self.platform.should_auto_hide_scrollbars()
1455    }
1456
1457    /// Restarts the application.
1458    pub fn restart(&mut self) {
1459        self.restart_observers
1460            .clone()
1461            .retain(&(), |observer| observer(self));
1462        self.platform.restart(self.restart_path.take())
1463    }
1464
1465    /// Sets the path to use when restarting the application.
1466    pub fn set_restart_path(&mut self, path: PathBuf) {
1467        self.restart_path = Some(path);
1468    }
1469
1470    /// Returns the HTTP client for the application.
1471    pub fn http_client(&self) -> Arc<dyn HttpClient> {
1472        self.http_client.clone()
1473    }
1474
1475    /// Sets the HTTP client for the application.
1476    pub fn set_http_client(&mut self, new_client: Arc<dyn HttpClient>) {
1477        self.http_client = new_client;
1478    }
1479
1480    /// Configures when the application should automatically quit.
1481    /// By default, [`QuitMode::Default`] is used.
1482    pub fn set_quit_mode(&mut self, mode: QuitMode) {
1483        self.quit_mode = mode;
1484    }
1485
1486    /// Returns the SVG renderer used by the application.
1487    pub fn svg_renderer(&self) -> SvgRenderer {
1488        self.svg_renderer.clone()
1489    }
1490
1491    pub(crate) fn push_effect(&mut self, effect: Effect) {
1492        match &effect {
1493            Effect::Notify { emitter } => {
1494                if !self.pending_notifications.insert(*emitter) {
1495                    return;
1496                }
1497            }
1498            Effect::NotifyGlobalObservers { global_type } => {
1499                if !self.pending_global_notifications.insert(*global_type) {
1500                    return;
1501                }
1502            }
1503            _ => {}
1504        };
1505
1506        self.pending_effects.push_back(effect);
1507    }
1508
1509    /// Called at the end of [`App::update`] to complete any side effects
1510    /// such as notifying observers, emitting events, etc. Effects can themselves
1511    /// cause effects, so we continue looping until all effects are processed.
1512    fn flush_effects(&mut self) {
1513        loop {
1514            self.release_dropped_entities();
1515            self.release_dropped_focus_handles();
1516            if let Some(effect) = self.pending_effects.pop_front() {
1517                match effect {
1518                    Effect::Notify { emitter } => {
1519                        self.apply_notify_effect(emitter);
1520                    }
1521
1522                    Effect::Emit {
1523                        emitter,
1524                        event_type,
1525                        event,
1526                    } => self.apply_emit_effect(emitter, event_type, &*event),
1527
1528                    Effect::RefreshWindows => {
1529                        self.apply_refresh_effect();
1530                    }
1531
1532                    Effect::NotifyGlobalObservers { global_type } => {
1533                        self.apply_notify_global_observers_effect(global_type);
1534                    }
1535
1536                    Effect::Defer { callback } => {
1537                        self.apply_defer_effect(callback);
1538                    }
1539                    Effect::EntityCreated {
1540                        entity,
1541                        tid,
1542                        window,
1543                    } => {
1544                        self.apply_entity_created_effect(entity, tid, window);
1545                    }
1546                }
1547            } else {
1548                #[cfg(any(test, feature = "test-support"))]
1549                for window in self
1550                    .windows
1551                    .values()
1552                    .filter_map(|window| {
1553                        let window = window.as_deref()?;
1554                        window.invalidator.is_dirty().then_some(window.handle)
1555                    })
1556                    .collect::<Vec<_>>()
1557                {
1558                    self.update_window(window, |_, window, cx| window.draw(cx).clear())
1559                        .unwrap();
1560                }
1561
1562                if self.pending_effects.is_empty() {
1563                    self.event_arena.clear();
1564                    break;
1565                }
1566            }
1567        }
1568    }
1569
1570    /// Repeatedly called during `flush_effects` to release any entities whose
1571    /// reference count has become zero. We invoke any release observers before dropping
1572    /// each entity.
1573    fn release_dropped_entities(&mut self) {
1574        loop {
1575            let dropped = self.entities.take_dropped();
1576            if dropped.is_empty() {
1577                break;
1578            }
1579
1580            for (entity_id, mut entity) in dropped {
1581                self.observers.remove(&entity_id);
1582                self.event_listeners.remove(&entity_id);
1583                self.window_invalidators_by_entity.remove(&entity_id);
1584                self.current_window_by_entity.remove(&entity_id);
1585                for release_callback in self.release_listeners.remove(&entity_id) {
1586                    release_callback(entity.as_mut(), self);
1587                }
1588            }
1589        }
1590    }
1591
1592    /// Repeatedly called during `flush_effects` to handle a focused handle being dropped.
1593    fn release_dropped_focus_handles(&mut self) {
1594        self.focus_handles
1595            .clone()
1596            .write()
1597            .retain(|handle_id, focus| {
1598                if focus.ref_count.load(SeqCst) == 0 {
1599                    for window_handle in self.windows() {
1600                        window_handle
1601                            .update(self, |_, window, _| {
1602                                if window.focus == Some(handle_id) {
1603                                    window.blur();
1604                                }
1605                            })
1606                            .unwrap();
1607                    }
1608                    false
1609                } else {
1610                    true
1611                }
1612            });
1613    }
1614
1615    fn apply_notify_effect(&mut self, emitter: EntityId) {
1616        self.pending_notifications.remove(&emitter);
1617
1618        self.observers
1619            .clone()
1620            .retain(&emitter, |handler| handler(self));
1621    }
1622
1623    fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: &dyn Any) {
1624        self.event_listeners
1625            .clone()
1626            .retain(&emitter, |(stored_type, handler)| {
1627                if *stored_type == event_type {
1628                    handler(event, self)
1629                } else {
1630                    true
1631                }
1632            });
1633    }
1634
1635    fn apply_refresh_effect(&mut self) {
1636        for window in self.windows.values_mut() {
1637            if let Some(window) = window.as_deref_mut() {
1638                window.refreshing = true;
1639                window.invalidator.set_dirty(true);
1640            }
1641        }
1642    }
1643
1644    fn apply_notify_global_observers_effect(&mut self, type_id: TypeId) {
1645        self.pending_global_notifications.remove(&type_id);
1646        self.global_observers
1647            .clone()
1648            .retain(&type_id, |observer| observer(self));
1649    }
1650
1651    fn apply_defer_effect(&mut self, callback: Box<dyn FnOnce(&mut Self) + 'static>) {
1652        callback(self);
1653    }
1654
1655    fn apply_entity_created_effect(
1656        &mut self,
1657        entity: AnyEntity,
1658        tid: TypeId,
1659        window: Option<WindowId>,
1660    ) {
1661        // Seed the entity's current window from its creation context so
1662        // `with_window` resolves correctly before the entity has ever been
1663        // rendered.
1664        if let Some(id) = window {
1665            self.current_window_by_entity.insert(entity.entity_id(), id);
1666        }
1667
1668        self.new_entity_observers.clone().retain(&tid, |observer| {
1669            if let Some(id) = window {
1670                self.update_window_id(id, {
1671                    let entity = entity.clone();
1672                    |_, window, cx| (observer)(entity, &mut Some(window), cx)
1673                })
1674                .expect("All windows should be off the stack when flushing effects");
1675            } else {
1676                (observer)(entity.clone(), &mut None, self)
1677            }
1678            true
1679        });
1680    }
1681
1682    /// Run `f` against the entity's *current* window — the most recently
1683    /// rendered window that referenced the entity, or its creation window if
1684    /// it has yet to be rendered. Returns `None` if the entity has no
1685    /// current window, or if that window has been closed, or if it is
1686    /// already on the update stack.
1687    pub fn with_window<R>(
1688        &mut self,
1689        entity_id: EntityId,
1690        f: impl FnOnce(&mut Window, &mut App) -> R,
1691    ) -> Option<R> {
1692        let window_id = *self.current_window_by_entity.get(&entity_id)?;
1693        self.update_window_id(window_id, |_, window, cx| f(window, cx))
1694            .ok()
1695    }
1696
1697    fn ensure_window(&mut self, entity_id: EntityId, window: WindowId) {
1698        self.current_window_by_entity
1699            .entry(entity_id)
1700            .or_insert(window);
1701    }
1702
1703    pub(crate) fn update_window_id<T, F>(&mut self, id: WindowId, update: F) -> Result<T>
1704    where
1705        F: FnOnce(AnyView, &mut Window, &mut App) -> T,
1706    {
1707        self.update(|cx| {
1708            let mut window = cx.windows.get_mut(id)?.take()?;
1709
1710            let root_view = window.root.clone().unwrap();
1711
1712            cx.window_update_stack.push(window.handle.id);
1713            let result = update(root_view, &mut window, cx);
1714            fn trail(id: WindowId, window: Box<Window>, cx: &mut App) -> Option<()> {
1715                cx.window_update_stack.pop();
1716
1717                if window.removed {
1718                    cx.window_handles.remove(&id);
1719                    cx.windows.remove(id);
1720                    if let Some(tracked) = cx.tracked_entities.remove(&id) {
1721                        for entity_id in tracked {
1722                            if let Some(windows) =
1723                                cx.window_invalidators_by_entity.get_mut(&entity_id)
1724                            {
1725                                windows.remove(&id);
1726                            }
1727                            if cx.current_window_by_entity.get(&entity_id) == Some(&id) {
1728                                cx.current_window_by_entity.remove(&entity_id);
1729                            }
1730                        }
1731                    }
1732
1733                    cx.window_closed_observers.clone().retain(&(), |callback| {
1734                        callback(cx, id);
1735                        true
1736                    });
1737
1738                    let quit_on_empty = match cx.quit_mode {
1739                        QuitMode::Explicit => false,
1740                        QuitMode::LastWindowClosed => true,
1741                        QuitMode::Default => cfg!(not(target_os = "macos")),
1742                    };
1743
1744                    if quit_on_empty && cx.windows.is_empty() {
1745                        cx.quit();
1746                    }
1747                } else {
1748                    cx.windows.get_mut(id)?.replace(window);
1749                }
1750                Some(())
1751            }
1752            trail(id, window, cx)?;
1753
1754            Some(result)
1755        })
1756        .context("window not found")
1757    }
1758
1759    /// Creates an `AsyncApp`, which can be cloned and has a static lifetime
1760    /// so it can be held across `await` points.
1761    pub fn to_async(&self) -> AsyncApp {
1762        AsyncApp {
1763            app: self.this.clone(),
1764            background_executor: self.background_executor.clone(),
1765            foreground_executor: self.foreground_executor.clone(),
1766        }
1767    }
1768
1769    /// Obtains a reference to the executor, which can be used to spawn futures.
1770    pub fn background_executor(&self) -> &BackgroundExecutor {
1771        &self.background_executor
1772    }
1773
1774    /// Obtains a reference to the executor, which can be used to spawn futures.
1775    pub fn foreground_executor(&self) -> &ForegroundExecutor {
1776        if self.quitting {
1777            panic!("Can't spawn on main thread after on_app_quit")
1778        };
1779        &self.foreground_executor
1780    }
1781
1782    /// Spawns the future returned by the given function on the main thread. The closure will be invoked
1783    /// with [AsyncApp], which allows the application state to be accessed across await points.
1784    #[track_caller]
1785    pub fn spawn<AsyncFn, R>(&self, f: AsyncFn) -> Task<R>
1786    where
1787        AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static,
1788        R: 'static,
1789    {
1790        if self.quitting {
1791            debug_panic!("Can't spawn on main thread after on_app_quit")
1792        };
1793
1794        let mut cx = self.to_async();
1795
1796        self.foreground_executor
1797            .spawn(async move { f(&mut cx).await }.boxed_local())
1798    }
1799
1800    /// Spawns the future returned by the given function on the main thread with
1801    /// the given priority. The closure will be invoked with [AsyncApp], which
1802    /// allows the application state to be accessed across await points.
1803    pub fn spawn_with_priority<AsyncFn, R>(&self, priority: Priority, f: AsyncFn) -> Task<R>
1804    where
1805        AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static,
1806        R: 'static,
1807    {
1808        if self.quitting {
1809            debug_panic!("Can't spawn on main thread after on_app_quit")
1810        };
1811
1812        let mut cx = self.to_async();
1813
1814        self.foreground_executor
1815            .spawn_with_priority(priority, async move { f(&mut cx).await }.boxed_local())
1816    }
1817
1818    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
1819    /// that are currently on the stack to be returned to the app.
1820    pub fn defer(&mut self, f: impl FnOnce(&mut App) + 'static) {
1821        self.push_effect(Effect::Defer {
1822            callback: Box::new(f),
1823        });
1824    }
1825
1826    /// Accessor for the application's asset source, which is provided when constructing the `App`.
1827    pub fn asset_source(&self) -> &Arc<dyn AssetSource> {
1828        &self.asset_source
1829    }
1830
1831    /// Accessor for the text system.
1832    pub fn text_system(&self) -> &Arc<TextSystem> {
1833        &self.text_system
1834    }
1835
1836    /// Check whether a global of the given type has been assigned.
1837    pub fn has_global<G: Global>(&self) -> bool {
1838        self.globals_by_type.contains_key(&TypeId::of::<G>())
1839    }
1840
1841    /// Access the global of the given type. Panics if a global for that type has not been assigned.
1842    #[track_caller]
1843    pub fn global<G: Global>(&self) -> &G {
1844        self.globals_by_type
1845            .get(&TypeId::of::<G>())
1846            .map(|any_state| any_state.downcast_ref::<G>().unwrap())
1847            .unwrap_or_else(|| panic!("no state of type {} exists", type_name::<G>()))
1848    }
1849
1850    /// Access the global of the given type if a value has been assigned.
1851    pub fn try_global<G: Global>(&self) -> Option<&G> {
1852        self.globals_by_type
1853            .get(&TypeId::of::<G>())
1854            .map(|any_state| any_state.downcast_ref::<G>().unwrap())
1855    }
1856
1857    /// Access the global of the given type mutably. Panics if a global for that type has not been assigned.
1858    #[track_caller]
1859    pub fn global_mut<G: Global>(&mut self) -> &mut G {
1860        let global_type = TypeId::of::<G>();
1861        self.push_effect(Effect::NotifyGlobalObservers { global_type });
1862        self.globals_by_type
1863            .get_mut(&global_type)
1864            .and_then(|any_state| any_state.downcast_mut::<G>())
1865            .unwrap_or_else(|| panic!("no state of type {} exists", type_name::<G>()))
1866    }
1867
1868    /// Access the global of the given type mutably. A default value is assigned if a global of this type has not
1869    /// yet been assigned.
1870    pub fn default_global<G: Global + Default>(&mut self) -> &mut G {
1871        let global_type = TypeId::of::<G>();
1872        self.push_effect(Effect::NotifyGlobalObservers { global_type });
1873        self.globals_by_type
1874            .entry(global_type)
1875            .or_insert_with(|| Box::<G>::default())
1876            .downcast_mut::<G>()
1877            .unwrap()
1878    }
1879
1880    /// Sets the value of the global of the given type.
1881    pub fn set_global<G: Global>(&mut self, global: G) {
1882        let global_type = TypeId::of::<G>();
1883        self.push_effect(Effect::NotifyGlobalObservers { global_type });
1884        self.globals_by_type.insert(global_type, Box::new(global));
1885    }
1886
1887    /// Clear all stored globals. Does not notify global observers.
1888    #[cfg(any(test, feature = "test-support"))]
1889    pub fn clear_globals(&mut self) {
1890        self.globals_by_type.drain();
1891    }
1892
1893    /// Remove the global of the given type from the app context. Does not notify global observers.
1894    pub fn remove_global<G: Global>(&mut self) -> G {
1895        let global_type = TypeId::of::<G>();
1896        self.push_effect(Effect::NotifyGlobalObservers { global_type });
1897        *self
1898            .globals_by_type
1899            .remove(&global_type)
1900            .unwrap_or_else(|| panic!("no global added for {}", type_name::<G>()))
1901            .downcast()
1902            .unwrap()
1903    }
1904
1905    /// Register a callback to be invoked when a global of the given type is updated.
1906    pub fn observe_global<G: Global>(
1907        &mut self,
1908        mut f: impl FnMut(&mut Self) + 'static,
1909    ) -> Subscription {
1910        let (subscription, activate) = self.global_observers.insert(
1911            TypeId::of::<G>(),
1912            Box::new(move |cx| {
1913                f(cx);
1914                true
1915            }),
1916        );
1917        self.defer(move |_| activate());
1918        subscription
1919    }
1920
1921    /// Move the global of the given type to the stack.
1922    #[track_caller]
1923    pub(crate) fn lease_global<G: Global>(&mut self) -> GlobalLease<G> {
1924        GlobalLease::new(
1925            self.globals_by_type
1926                .remove(&TypeId::of::<G>())
1927                .with_context(|| format!("no global registered of type {}", type_name::<G>()))
1928                .unwrap(),
1929        )
1930    }
1931
1932    /// Restore the global of the given type after it is moved to the stack.
1933    pub(crate) fn end_global_lease<G: Global>(&mut self, lease: GlobalLease<G>) {
1934        let global_type = TypeId::of::<G>();
1935
1936        self.push_effect(Effect::NotifyGlobalObservers { global_type });
1937        self.globals_by_type.insert(global_type, lease.global);
1938    }
1939
1940    pub(crate) fn new_entity_observer(
1941        &self,
1942        key: TypeId,
1943        value: NewEntityListener,
1944    ) -> Subscription {
1945        let (subscription, activate) = self.new_entity_observers.insert(key, value);
1946        activate();
1947        subscription
1948    }
1949
1950    /// Arrange for the given function to be invoked whenever a view of the specified type is created.
1951    /// The function will be passed a mutable reference to the view along with an appropriate context.
1952    pub fn observe_new<T: 'static>(
1953        &self,
1954        on_new: impl 'static + Fn(&mut T, Option<&mut Window>, &mut Context<T>),
1955    ) -> Subscription {
1956        self.new_entity_observer(
1957            TypeId::of::<T>(),
1958            Box::new(
1959                move |any_entity: AnyEntity, window: &mut Option<&mut Window>, cx: &mut App| {
1960                    any_entity
1961                        .downcast::<T>()
1962                        .unwrap()
1963                        .update(cx, |entity_state, cx| {
1964                            on_new(entity_state, window.as_deref_mut(), cx)
1965                        })
1966                },
1967            ),
1968        )
1969    }
1970
1971    /// Observe the release of a entity. The callback is invoked after the entity
1972    /// has no more strong references but before it has been dropped.
1973    pub fn observe_release<T>(
1974        &self,
1975        handle: &Entity<T>,
1976        on_release: impl FnOnce(&mut T, &mut App) + 'static,
1977    ) -> Subscription
1978    where
1979        T: 'static,
1980    {
1981        let (subscription, activate) = self.release_listeners.insert(
1982            handle.entity_id(),
1983            Box::new(move |entity, cx| {
1984                let entity = entity.downcast_mut().expect("invalid entity type");
1985                on_release(entity, cx)
1986            }),
1987        );
1988        activate();
1989        subscription
1990    }
1991
1992    /// Observe the release of a entity. The callback is invoked after the entity
1993    /// has no more strong references but before it has been dropped.
1994    pub fn observe_release_in<T>(
1995        &self,
1996        handle: &Entity<T>,
1997        window: &Window,
1998        on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
1999    ) -> Subscription
2000    where
2001        T: 'static,
2002    {
2003        let window_handle = window.handle;
2004        self.observe_release(handle, move |entity, cx| {
2005            let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
2006        })
2007    }
2008
2009    /// Register a callback to be invoked when a keystroke is received by the application
2010    /// in any window. Note that this fires after all other action and event mechanisms have resolved
2011    /// and that this API will not be invoked if the event's propagation is stopped.
2012    pub fn observe_keystrokes(
2013        &mut self,
2014        mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static,
2015    ) -> Subscription {
2016        fn inner(
2017            keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
2018            handler: KeystrokeObserver,
2019        ) -> Subscription {
2020            let (subscription, activate) = keystroke_observers.insert((), handler);
2021            activate();
2022            subscription
2023        }
2024
2025        inner(
2026            &self.keystroke_observers,
2027            Box::new(move |event, window, cx| {
2028                f(event, window, cx);
2029                true
2030            }),
2031        )
2032    }
2033
2034    /// Register a callback to be invoked when a keystroke is received by the application
2035    /// in any window. Note that this fires _before_ all other action and event mechanisms have resolved
2036    /// unlike [`App::observe_keystrokes`] which fires after. This means that `cx.stop_propagation` calls
2037    /// within interceptors will prevent action dispatch
2038    pub fn intercept_keystrokes(
2039        &mut self,
2040        mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static,
2041    ) -> Subscription {
2042        fn inner(
2043            keystroke_interceptors: &SubscriberSet<(), KeystrokeObserver>,
2044            handler: KeystrokeObserver,
2045        ) -> Subscription {
2046            let (subscription, activate) = keystroke_interceptors.insert((), handler);
2047            activate();
2048            subscription
2049        }
2050
2051        inner(
2052            &self.keystroke_interceptors,
2053            Box::new(move |event, window, cx| {
2054                f(event, window, cx);
2055                true
2056            }),
2057        )
2058    }
2059
2060    /// Register key bindings.
2061    pub fn bind_keys(&mut self, bindings: impl IntoIterator<Item = KeyBinding>) {
2062        self.keymap.borrow_mut().add_bindings(bindings);
2063        self.pending_effects.push_back(Effect::RefreshWindows);
2064    }
2065
2066    /// Clear all key bindings in the app.
2067    pub fn clear_key_bindings(&mut self) {
2068        self.keymap.borrow_mut().clear();
2069        self.pending_effects.push_back(Effect::RefreshWindows);
2070    }
2071
2072    /// Get all key bindings in the app.
2073    pub fn key_bindings(&self) -> Rc<RefCell<Keymap>> {
2074        self.keymap.clone()
2075    }
2076
2077    /// Register a global handler for actions invoked via the keyboard. These handlers are run at
2078    /// the end of the bubble phase for actions, and so will only be invoked if there are no other
2079    /// handlers or if they called `cx.propagate()`.
2080    pub fn on_action<A: Action>(
2081        &mut self,
2082        listener: impl Fn(&A, &mut Self) + 'static,
2083    ) -> &mut Self {
2084        self.global_action_listeners
2085            .entry(TypeId::of::<A>())
2086            .or_default()
2087            .push(Rc::new(move |action, phase, cx| {
2088                if phase == DispatchPhase::Bubble {
2089                    let action = action.downcast_ref().unwrap();
2090                    listener(action, cx)
2091                }
2092            }));
2093        self
2094    }
2095
2096    /// Event handlers propagate events by default. Call this method to stop dispatching to
2097    /// event handlers with a lower z-index (mouse) or higher in the tree (keyboard). This is
2098    /// the opposite of [`Self::propagate`]. It's also possible to cancel a call to [`Self::propagate`] by
2099    /// calling this method before effects are flushed.
2100    pub fn stop_propagation(&mut self) {
2101        self.propagate_event = false;
2102    }
2103
2104    /// Action handlers stop propagation by default during the bubble phase of action dispatch
2105    /// dispatching to action handlers higher in the element tree. This is the opposite of
2106    /// [`Self::stop_propagation`]. It's also possible to cancel a call to [`Self::stop_propagation`] by calling
2107    /// this method before effects are flushed.
2108    pub fn propagate(&mut self) {
2109        self.propagate_event = true;
2110    }
2111
2112    /// Build an action from some arbitrary data, typically a keymap entry.
2113    pub fn build_action(
2114        &self,
2115        name: &str,
2116        data: Option<serde_json::Value>,
2117    ) -> std::result::Result<Box<dyn Action>, ActionBuildError> {
2118        self.actions.build_action(name, data)
2119    }
2120
2121    /// Get all action names that have been registered. Note that registration only allows for
2122    /// actions to be built dynamically, and is unrelated to binding actions in the element tree.
2123    pub fn all_action_names(&self) -> &[&'static str] {
2124        self.actions.all_action_names()
2125    }
2126
2127    /// Returns key bindings that invoke the given action on the currently focused element, without
2128    /// checking context. Bindings are returned in the order they were added. For display, the last
2129    /// binding should take precedence.
2130    pub fn all_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
2131        RefCell::borrow(&self.keymap).all_bindings_for_input(input)
2132    }
2133
2134    /// Get all non-internal actions that have been registered, along with their schemas.
2135    pub fn action_schemas(
2136        &self,
2137        generator: &mut schemars::SchemaGenerator,
2138    ) -> Vec<(&'static str, Option<schemars::Schema>)> {
2139        self.actions.action_schemas(generator)
2140    }
2141
2142    /// Get the schema for a specific action by name.
2143    /// Returns `None` if the action is not found.
2144    /// Returns `Some(None)` if the action exists but has no schema.
2145    /// Returns `Some(Some(schema))` if the action exists and has a schema.
2146    pub fn action_schema_by_name(
2147        &self,
2148        name: &str,
2149        generator: &mut schemars::SchemaGenerator,
2150    ) -> Option<Option<schemars::Schema>> {
2151        self.actions.action_schema_by_name(name, generator)
2152    }
2153
2154    /// Get a map from a deprecated action name to the canonical name.
2155    pub fn deprecated_actions_to_preferred_actions(&self) -> &HashMap<&'static str, &'static str> {
2156        self.actions.deprecated_aliases()
2157    }
2158
2159    /// Get a map from an action name to the deprecation messages.
2160    pub fn action_deprecation_messages(&self) -> &HashMap<&'static str, &'static str> {
2161        self.actions.deprecation_messages()
2162    }
2163
2164    /// Get a map from an action name to the documentation.
2165    pub fn action_documentation(&self) -> &HashMap<&'static str, &'static str> {
2166        self.actions.documentation()
2167    }
2168
2169    /// Register a callback to be invoked when the application is about to quit.
2170    /// It is not possible to cancel the quit event at this point.
2171    pub fn on_app_quit<Fut>(
2172        &self,
2173        mut on_quit: impl FnMut(&mut App) -> Fut + 'static,
2174    ) -> Subscription
2175    where
2176        Fut: 'static + Future<Output = ()>,
2177    {
2178        let (subscription, activate) = self.quit_observers.insert(
2179            (),
2180            Box::new(move |cx| {
2181                let future = on_quit(cx);
2182                future.boxed_local()
2183            }),
2184        );
2185        activate();
2186        subscription
2187    }
2188
2189    /// Register a callback to be invoked when the application is about to restart.
2190    ///
2191    /// These callbacks are called before any `on_app_quit` callbacks.
2192    pub fn on_app_restart(&self, mut on_restart: impl 'static + FnMut(&mut App)) -> Subscription {
2193        let (subscription, activate) = self.restart_observers.insert(
2194            (),
2195            Box::new(move |cx| {
2196                on_restart(cx);
2197                true
2198            }),
2199        );
2200        activate();
2201        subscription
2202    }
2203
2204    /// Register a callback to be invoked when a window is closed
2205    /// The window is no longer accessible at the point this callback is invoked.
2206    pub fn on_window_closed(
2207        &self,
2208        mut on_closed: impl FnMut(&mut App, WindowId) + 'static,
2209    ) -> Subscription {
2210        let (subscription, activate) = self.window_closed_observers.insert((), Box::new(on_closed));
2211        activate();
2212        subscription
2213    }
2214
2215    pub(crate) fn clear_pending_keystrokes(&mut self) {
2216        for window in self.windows() {
2217            window
2218                .update(self, |_, window, cx| {
2219                    if window.pending_input_keystrokes().is_some() {
2220                        window.clear_pending_keystrokes();
2221                        window.pending_input_changed(cx);
2222                    }
2223                })
2224                .ok();
2225        }
2226    }
2227
2228    /// Checks if the given action is bound in the current context, as defined by the app's current focus,
2229    /// the bindings in the element tree, and any global action listeners.
2230    pub fn is_action_available(&mut self, action: &dyn Action) -> bool {
2231        let mut action_available = false;
2232        if let Some(window) = self.focused_action_window()
2233            && let Ok(window_action_available) =
2234                window.update(self, |_, window, cx| window.is_action_available(action, cx))
2235        {
2236            action_available = window_action_available;
2237        }
2238
2239        action_available
2240            || self
2241                .global_action_listeners
2242                .contains_key(&action.as_any().type_id())
2243    }
2244
2245    /// Sets the menu bar for this application. This will replace any existing menu bar.
2246    pub fn set_menus(&self, menus: impl IntoIterator<Item = Menu>) {
2247        let menus: Vec<Menu> = menus.into_iter().collect();
2248        self.platform.set_menus(menus, &self.keymap.borrow());
2249    }
2250
2251    /// Gets the menu bar for this application.
2252    pub fn get_menus(&self) -> Option<Vec<OwnedMenu>> {
2253        self.platform.get_menus()
2254    }
2255
2256    /// Sets the right click menu for the app icon in the dock
2257    pub fn set_dock_menu(&self, menus: Vec<MenuItem>) {
2258        self.platform.set_dock_menu(menus, &self.keymap.borrow())
2259    }
2260
2261    /// Performs the action associated with the given dock menu item, only used on Windows for now.
2262    pub fn perform_dock_menu_action(&self, action: usize) {
2263        self.platform.perform_dock_menu_action(action);
2264    }
2265
2266    /// Adds given path to the bottom of the list of recent paths for the application.
2267    /// The list is usually shown on the application icon's context menu in the dock,
2268    /// and allows to open the recent files via that context menu.
2269    /// If the path is already in the list, it will be moved to the bottom of the list.
2270    pub fn add_recent_document(&self, path: &Path) {
2271        self.platform.add_recent_document(path);
2272    }
2273
2274    /// Updates the jump list with the updated list of recent paths for the application, only used on Windows for now.
2275    /// Note that this also sets the dock menu on Windows.
2276    pub fn update_jump_list(
2277        &self,
2278        menus: Vec<MenuItem>,
2279        entries: Vec<SmallVec<[PathBuf; 2]>>,
2280    ) -> Task<Vec<SmallVec<[PathBuf; 2]>>> {
2281        self.platform.update_jump_list(menus, entries)
2282    }
2283
2284    /// Dispatch an action to the currently focused window or global action handler
2285    /// See [`crate::Action`] for more information on how actions work
2286    pub fn dispatch_action(&mut self, action: &dyn Action) {
2287        if let Some(focused_window) = self.focused_action_window() {
2288            focused_window
2289                .update(self, |_, window, cx| {
2290                    window.dispatch_action(action.boxed_clone(), cx)
2291                })
2292                .log_err();
2293        } else {
2294            self.dispatch_global_action(action);
2295        }
2296    }
2297
2298    fn focused_action_window(&self) -> Option<AnyWindowHandle> {
2299        match self.focused_window() {
2300            PlatformFocusedWindow::Window(window) => Some(window),
2301            PlatformFocusedWindow::NoWindow | PlatformFocusedWindow::Unavailable => None,
2302        }
2303    }
2304
2305    fn dispatch_global_action(&mut self, action: &dyn Action) {
2306        self.propagate_event = true;
2307
2308        if let Some(mut global_listeners) = self
2309            .global_action_listeners
2310            .remove(&action.as_any().type_id())
2311        {
2312            for listener in &global_listeners {
2313                listener(action.as_any(), DispatchPhase::Capture, self);
2314                if !self.propagate_event {
2315                    break;
2316                }
2317            }
2318
2319            global_listeners.extend(
2320                self.global_action_listeners
2321                    .remove(&action.as_any().type_id())
2322                    .unwrap_or_default(),
2323            );
2324
2325            self.global_action_listeners
2326                .insert(action.as_any().type_id(), global_listeners);
2327        }
2328
2329        if self.propagate_event
2330            && let Some(mut global_listeners) = self
2331                .global_action_listeners
2332                .remove(&action.as_any().type_id())
2333        {
2334            for listener in global_listeners.iter().rev() {
2335                listener(action.as_any(), DispatchPhase::Bubble, self);
2336                if !self.propagate_event {
2337                    break;
2338                }
2339            }
2340
2341            global_listeners.extend(
2342                self.global_action_listeners
2343                    .remove(&action.as_any().type_id())
2344                    .unwrap_or_default(),
2345            );
2346
2347            self.global_action_listeners
2348                .insert(action.as_any().type_id(), global_listeners);
2349        }
2350    }
2351
2352    /// Is there currently something being dragged?
2353    pub fn has_active_drag(&self) -> bool {
2354        self.active_drag.is_some()
2355    }
2356
2357    /// Returns the typed value for the current drag operation, when it matches `T`.
2358    pub fn active_drag_value<T: 'static>(&self) -> Option<&T> {
2359        self.active_drag
2360            .as_ref()
2361            .and_then(|drag| drag.value.downcast_ref::<T>())
2362    }
2363
2364    /// Gets the cursor style of the currently active drag operation.
2365    pub fn active_drag_cursor_style(&self) -> Option<CursorStyle> {
2366        self.active_drag.as_ref().and_then(|drag| drag.cursor_style)
2367    }
2368
2369    /// Stops active drag and clears any related effects.
2370    pub fn stop_active_drag(&mut self, window: &mut Window) -> bool {
2371        if self.active_drag.is_some() {
2372            self.active_drag = None;
2373            window.refresh();
2374            true
2375        } else {
2376            false
2377        }
2378    }
2379
2380    /// Sets the cursor style for the currently active drag operation.
2381    pub fn set_active_drag_cursor_style(
2382        &mut self,
2383        cursor_style: CursorStyle,
2384        window: &mut Window,
2385    ) -> bool {
2386        if let Some(ref mut drag) = self.active_drag {
2387            drag.cursor_style = Some(cursor_style);
2388            window.refresh();
2389            true
2390        } else {
2391            false
2392        }
2393    }
2394
2395    /// Set the prompt renderer for GPUI. This will replace the default or platform specific
2396    /// prompts with this custom implementation.
2397    pub fn set_prompt_builder(
2398        &mut self,
2399        renderer: impl Fn(
2400            PromptLevel,
2401            &str,
2402            Option<&str>,
2403            &[PromptButton],
2404            PromptHandle,
2405            &mut Window,
2406            &mut App,
2407        ) -> RenderablePromptHandle
2408        + 'static,
2409    ) {
2410        self.prompt_builder = Some(PromptBuilder::Custom(Box::new(renderer)));
2411    }
2412
2413    /// Reset the prompt builder to the default implementation.
2414    pub fn reset_prompt_builder(&mut self) {
2415        self.prompt_builder = Some(PromptBuilder::Default);
2416    }
2417
2418    /// Remove an asset from GPUI's cache
2419    pub fn remove_asset<A: Asset>(&mut self, source: &A::Source) {
2420        let asset_id = (TypeId::of::<A>(), hash(source));
2421        self.loading_assets.remove(&asset_id);
2422    }
2423
2424    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
2425    ///
2426    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
2427    /// time, and the results of this call will be cached
2428    pub fn fetch_asset<A: Asset>(&mut self, source: &A::Source) -> (Shared<Task<A::Output>>, bool) {
2429        let asset_id = (TypeId::of::<A>(), hash(source));
2430        let mut is_first = false;
2431        let task = self
2432            .loading_assets
2433            .remove(&asset_id)
2434            .map(|boxed_task| *boxed_task.downcast::<Shared<Task<A::Output>>>().unwrap())
2435            .unwrap_or_else(|| {
2436                is_first = true;
2437                let future = A::load(source.clone(), self);
2438
2439                self.background_executor().spawn(future).shared()
2440            });
2441
2442        self.loading_assets.insert(asset_id, Box::new(task.clone()));
2443
2444        (task, is_first)
2445    }
2446
2447    /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus
2448    /// for elements rendered within this window.
2449    #[track_caller]
2450    pub fn focus_handle(&self) -> FocusHandle {
2451        FocusHandle::new(&self.focus_handles)
2452    }
2453
2454    /// Tell GPUI that an entity has changed and observers of it should be notified.
2455    pub fn notify(&mut self, entity_id: EntityId) {
2456        let window_invalidators = mem::take(
2457            self.window_invalidators_by_entity
2458                .entry(entity_id)
2459                .or_default(),
2460        );
2461
2462        // `window_invalidators_by_entity` is monotonic, so an entry alone
2463        // doesn't mean the window is currently rendering the entity. Filter
2464        // through `tracked_entities` to keep invalidation tight to windows
2465        // that actually display this entity right now.
2466        let live_invalidators: SmallVec<[WindowInvalidator; 2]> = window_invalidators
2467            .iter()
2468            .filter(|(window_id, _)| {
2469                self.tracked_entities
2470                    .get(window_id)
2471                    .is_some_and(|set| set.contains(&entity_id))
2472            })
2473            .map(|(_, invalidator)| invalidator.clone())
2474            .collect();
2475
2476        if live_invalidators.is_empty() {
2477            if self.pending_notifications.insert(entity_id) {
2478                self.pending_effects
2479                    .push_back(Effect::Notify { emitter: entity_id });
2480            }
2481        } else {
2482            for invalidator in &live_invalidators {
2483                invalidator.invalidate_view(entity_id, self);
2484            }
2485        }
2486
2487        self.window_invalidators_by_entity
2488            .insert(entity_id, window_invalidators);
2489    }
2490
2491    /// Returns the name for this [`App`].
2492    #[cfg(any(test, feature = "test-support", debug_assertions))]
2493    pub fn get_name(&self) -> Option<&'static str> {
2494        self.name
2495    }
2496
2497    /// Returns `true` if the platform file picker supports selecting a mix of files and directories.
2498    pub fn can_select_mixed_files_and_dirs(&self) -> bool {
2499        self.platform.can_select_mixed_files_and_dirs()
2500    }
2501
2502    /// Removes an image from the sprite atlas on all windows.
2503    ///
2504    /// If the current window is being updated, it will be removed from `App.windows`, you can use `current_window` to specify the current window.
2505    /// This is a no-op if the image is not in the sprite atlas.
2506    pub fn drop_image(&mut self, image: Arc<RenderImage>, current_window: Option<&mut Window>) {
2507        // remove the texture from all other windows
2508        for window in self.windows.values_mut().flatten() {
2509            _ = window.drop_image(image.clone());
2510        }
2511
2512        // remove the texture from the current window
2513        if let Some(window) = current_window {
2514            _ = window.drop_image(image);
2515        }
2516    }
2517
2518    /// Sets the renderer for the inspector.
2519    #[cfg(any(feature = "inspector", debug_assertions))]
2520    pub fn set_inspector_renderer(&mut self, f: crate::InspectorRenderer) {
2521        self.inspector_renderer = Some(f);
2522    }
2523
2524    /// Registers a renderer specific to an inspector state.
2525    #[cfg(any(feature = "inspector", debug_assertions))]
2526    pub fn register_inspector_element<T: 'static, R: crate::IntoElement>(
2527        &mut self,
2528        f: impl 'static + Fn(crate::InspectorElementId, &T, &mut Window, &mut App) -> R,
2529    ) {
2530        self.inspector_element_registry.register(f);
2531    }
2532
2533    /// Initializes gpui's default colors for the application.
2534    ///
2535    /// These colors can be accessed through `cx.default_colors()`.
2536    pub fn init_colors(&mut self) {
2537        self.set_global(GlobalColors(Arc::new(Colors::default())));
2538    }
2539}
2540
2541impl AppContext for App {
2542    /// Builds an entity that is owned by the application.
2543    ///
2544    /// The given function will be invoked with a [`Context`] and must return an object representing the entity. An
2545    /// [`Entity`] handle will be returned, which can be used to access the entity in a context.
2546    fn new<T: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<T>) -> T) -> Entity<T> {
2547        self.update(|cx| {
2548            let slot = cx.entities.reserve();
2549            let handle = slot.clone();
2550            let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
2551
2552            cx.push_effect(Effect::EntityCreated {
2553                entity: handle.into_any(),
2554                tid: TypeId::of::<T>(),
2555                window: cx.window_update_stack.last().cloned(),
2556            });
2557
2558            cx.entities.insert(slot, entity)
2559        })
2560    }
2561
2562    fn reserve_entity<T: 'static>(&mut self) -> Reservation<T> {
2563        Reservation(self.entities.reserve())
2564    }
2565
2566    fn insert_entity<T: 'static>(
2567        &mut self,
2568        reservation: Reservation<T>,
2569        build_entity: impl FnOnce(&mut Context<T>) -> T,
2570    ) -> Entity<T> {
2571        self.update(|cx| {
2572            let slot = reservation.0;
2573            let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
2574            cx.entities.insert(slot, entity)
2575        })
2576    }
2577
2578    /// Updates the entity referenced by the given handle. The function is passed a mutable reference to the
2579    /// entity along with a `Context` for the entity.
2580    fn update_entity<T: 'static, R>(
2581        &mut self,
2582        handle: &Entity<T>,
2583        update: impl FnOnce(&mut T, &mut Context<T>) -> R,
2584    ) -> R {
2585        self.update(|cx| {
2586            let mut entity = cx.entities.lease(handle);
2587            let result = update(
2588                &mut entity,
2589                &mut Context::new_context(cx, handle.downgrade()),
2590            );
2591            cx.entities.end_lease(entity);
2592            result
2593        })
2594    }
2595
2596    fn as_mut<'a, T>(&'a mut self, handle: &Entity<T>) -> GpuiBorrow<'a, T>
2597    where
2598        T: 'static,
2599    {
2600        GpuiBorrow::new(handle.clone(), self)
2601    }
2602
2603    fn read_entity<T, R>(&self, handle: &Entity<T>, read: impl FnOnce(&T, &App) -> R) -> R
2604    where
2605        T: 'static,
2606    {
2607        let entity = self.entities.read(handle);
2608        read(entity, self)
2609    }
2610
2611    fn update_window<T, F>(&mut self, handle: AnyWindowHandle, update: F) -> Result<T>
2612    where
2613        F: FnOnce(AnyView, &mut Window, &mut App) -> T,
2614    {
2615        self.update_window_id(handle.id, update)
2616    }
2617
2618    fn with_window<R>(
2619        &mut self,
2620        entity_id: EntityId,
2621        f: impl FnOnce(&mut Window, &mut App) -> R,
2622    ) -> Option<R> {
2623        App::with_window(self, entity_id, f)
2624    }
2625
2626    fn read_window<T, R>(
2627        &self,
2628        window: &WindowHandle<T>,
2629        read: impl FnOnce(Entity<T>, &App) -> R,
2630    ) -> Result<R>
2631    where
2632        T: 'static,
2633    {
2634        let window = self
2635            .windows
2636            .get(window.id)
2637            .context("window not found")?
2638            .as_deref()
2639            .expect("attempted to read a window that is already on the stack");
2640
2641        let root_view = window.root.clone().unwrap();
2642        let view = root_view
2643            .downcast::<T>()
2644            .map_err(|_| anyhow!("root view's type has changed"))?;
2645
2646        Ok(read(view, self))
2647    }
2648
2649    fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
2650    where
2651        R: Send + 'static,
2652    {
2653        self.background_executor.spawn(future)
2654    }
2655
2656    fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> R
2657    where
2658        G: Global,
2659    {
2660        let mut g = self.global::<G>();
2661        callback(g, self)
2662    }
2663}
2664
2665/// These effects are processed at the end of each application update cycle.
2666pub(crate) enum Effect {
2667    Notify {
2668        emitter: EntityId,
2669    },
2670    Emit {
2671        emitter: EntityId,
2672        event_type: TypeId,
2673        event: ArenaBox<dyn Any>,
2674    },
2675    RefreshWindows,
2676    NotifyGlobalObservers {
2677        global_type: TypeId,
2678    },
2679    Defer {
2680        callback: Box<dyn FnOnce(&mut App) + 'static>,
2681    },
2682    EntityCreated {
2683        entity: AnyEntity,
2684        tid: TypeId,
2685        window: Option<WindowId>,
2686    },
2687}
2688
2689impl std::fmt::Debug for Effect {
2690    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2691        match self {
2692            Effect::Notify { emitter } => write!(f, "Notify({})", emitter),
2693            Effect::Emit { emitter, .. } => write!(f, "Emit({:?})", emitter),
2694            Effect::RefreshWindows => write!(f, "RefreshWindows"),
2695            Effect::NotifyGlobalObservers { global_type } => {
2696                write!(f, "NotifyGlobalObservers({:?})", global_type)
2697            }
2698            Effect::Defer { .. } => write!(f, "Defer(..)"),
2699            Effect::EntityCreated { entity, .. } => write!(f, "EntityCreated({:?})", entity),
2700        }
2701    }
2702}
2703
2704/// Wraps a global variable value during `update_global` while the value has been moved to the stack.
2705pub(crate) struct GlobalLease<G: Global> {
2706    global: Box<dyn Any>,
2707    global_type: PhantomData<G>,
2708}
2709
2710impl<G: Global> GlobalLease<G> {
2711    fn new(global: Box<dyn Any>) -> Self {
2712        GlobalLease {
2713            global,
2714            global_type: PhantomData,
2715        }
2716    }
2717}
2718
2719impl<G: Global> Deref for GlobalLease<G> {
2720    type Target = G;
2721
2722    fn deref(&self) -> &Self::Target {
2723        self.global.downcast_ref().unwrap()
2724    }
2725}
2726
2727impl<G: Global> DerefMut for GlobalLease<G> {
2728    fn deref_mut(&mut self) -> &mut Self::Target {
2729        self.global.downcast_mut().unwrap()
2730    }
2731}
2732
2733/// Contains state associated with an active drag operation, started by dragging an element
2734/// within the window or by dragging into the app from the underlying platform.
2735pub struct AnyDrag {
2736    /// The view used to render this drag
2737    pub view: AnyView,
2738
2739    /// The value of the dragged item, to be dropped
2740    pub value: Arc<dyn Any>,
2741
2742    /// This is used to render the dragged item in the same place
2743    /// on the original element that the drag was initiated
2744    pub cursor_offset: Point<Pixels>,
2745
2746    /// The cursor style to use while dragging
2747    pub cursor_style: Option<CursorStyle>,
2748}
2749
2750/// Contains state associated with a tooltip. You'll only need this struct if you're implementing
2751/// tooltip behavior on a custom element. Otherwise, use [Div::tooltip](crate::Interactivity::tooltip).
2752#[derive(Clone)]
2753pub struct AnyTooltip {
2754    /// The view used to display the tooltip
2755    pub view: AnyView,
2756
2757    /// The absolute position of the mouse when the tooltip was deployed.
2758    pub mouse_position: Point<Pixels>,
2759
2760    /// Given the bounds of the tooltip, checks whether the tooltip should still be visible and
2761    /// updates its state accordingly. This is needed atop the hovered element's mouse move handler
2762    /// to handle the case where the element is not painted (e.g. via use of `visible_on_hover`).
2763    pub check_visible_and_update: Rc<dyn Fn(Bounds<Pixels>, &mut Window, &mut App) -> bool>,
2764}
2765
2766/// A keystroke event, and potentially the associated action
2767#[derive(Debug)]
2768pub struct KeystrokeEvent {
2769    /// The keystroke that occurred
2770    pub keystroke: Keystroke,
2771
2772    /// The action that was resolved for the keystroke, if any
2773    pub action: Option<Box<dyn Action>>,
2774
2775    /// The context stack at the time
2776    pub context_stack: Vec<KeyContext>,
2777}
2778
2779struct NullHttpClient;
2780
2781impl HttpClient for NullHttpClient {
2782    fn send(
2783        &self,
2784        _req: open_gpui_http_client::Request<open_gpui_http_client::AsyncBody>,
2785    ) -> futures::future::BoxFuture<
2786        'static,
2787        anyhow::Result<open_gpui_http_client::Response<open_gpui_http_client::AsyncBody>>,
2788    > {
2789        async move {
2790            anyhow::bail!("No HttpClient available");
2791        }
2792        .boxed()
2793    }
2794
2795    fn user_agent(&self) -> Option<&open_gpui_http_client::http::HeaderValue> {
2796        None
2797    }
2798
2799    fn proxy(&self) -> Option<&Url> {
2800        None
2801    }
2802}
2803
2804/// A mutable reference to an entity owned by GPUI
2805pub struct GpuiBorrow<'a, T> {
2806    inner: Option<Lease<T>>,
2807    app: &'a mut App,
2808}
2809
2810impl<'a, T: 'static> GpuiBorrow<'a, T> {
2811    fn new(inner: Entity<T>, app: &'a mut App) -> Self {
2812        app.start_update();
2813        let lease = app.entities.lease(&inner);
2814        Self {
2815            inner: Some(lease),
2816            app,
2817        }
2818    }
2819}
2820
2821impl<'a, T: 'static> std::borrow::Borrow<T> for GpuiBorrow<'a, T> {
2822    fn borrow(&self) -> &T {
2823        self.inner.as_ref().unwrap().borrow()
2824    }
2825}
2826
2827impl<'a, T: 'static> std::borrow::BorrowMut<T> for GpuiBorrow<'a, T> {
2828    fn borrow_mut(&mut self) -> &mut T {
2829        self.inner.as_mut().unwrap().borrow_mut()
2830    }
2831}
2832
2833impl<'a, T: 'static> std::ops::Deref for GpuiBorrow<'a, T> {
2834    type Target = T;
2835
2836    fn deref(&self) -> &Self::Target {
2837        self.inner.as_ref().unwrap()
2838    }
2839}
2840
2841impl<'a, T: 'static> std::ops::DerefMut for GpuiBorrow<'a, T> {
2842    fn deref_mut(&mut self) -> &mut T {
2843        self.inner.as_mut().unwrap()
2844    }
2845}
2846
2847impl<'a, T> Drop for GpuiBorrow<'a, T> {
2848    fn drop(&mut self) {
2849        let lease = self.inner.take().unwrap();
2850        self.app.notify(lease.id);
2851        self.app.entities.end_lease(lease);
2852        self.app.finish_update();
2853    }
2854}
2855
2856#[cfg(test)]
2857mod test {
2858    use std::{
2859        cell::{Cell, RefCell},
2860        rc::Rc,
2861    };
2862
2863    use crate::{AppContext, Empty, TestAppContext, px, size};
2864
2865    actions!(app_focus_tests, [DispatchProbe]);
2866
2867    #[test]
2868    fn test_gpui_borrow() {
2869        let cx = TestAppContext::single();
2870        let observation_count = Rc::new(RefCell::new(0));
2871
2872        let state = cx.update(|cx| {
2873            let state = cx.new(|_| false);
2874            cx.observe(&state, {
2875                let observation_count = observation_count.clone();
2876                move |_, _| {
2877                    let mut count = observation_count.borrow_mut();
2878                    *count += 1;
2879                }
2880            })
2881            .detach();
2882
2883            state
2884        });
2885
2886        cx.update(|cx| {
2887            // Calling this like this so that we don't clobber the borrow_mut above
2888            *std::borrow::BorrowMut::borrow_mut(&mut state.as_mut(cx)) = true;
2889        });
2890
2891        cx.update(|cx| {
2892            state.write(cx, false);
2893        });
2894
2895        assert_eq!(*observation_count.borrow(), 2);
2896    }
2897
2898    #[crate::test]
2899    fn application_on_system_wake_runs_callback(cx: &mut TestAppContext) {
2900        let wake_count = Rc::new(Cell::new(0));
2901        super::Application(cx.app.clone()).on_system_wake({
2902            let wake_count = wake_count.clone();
2903            move |_| wake_count.set(wake_count.get() + 1)
2904        });
2905
2906        cx.simulate_system_wake();
2907        cx.simulate_system_wake();
2908
2909        assert_eq!(wake_count.get(), 2);
2910    }
2911
2912    #[crate::test]
2913    fn app_dispatch_action_uses_focused_window_authority(cx: &mut TestAppContext) {
2914        let window = cx.open_window(size(px(320.0), px(200.0)), |_, _| Empty);
2915        window
2916            .update(cx, |_, window, _| window.activate_window())
2917            .expect("test window should be activatable");
2918        cx.run_until_parked();
2919        assert_eq!(
2920            cx.update(|app| app.active_window()),
2921            Some(window.into()),
2922            "setup should leave an active application window"
2923        );
2924
2925        let global_dispatch_count = Rc::new(RefCell::new(0));
2926        cx.update(|app| {
2927            let global_dispatch_count = global_dispatch_count.clone();
2928            app.on_action(move |_: &DispatchProbe, _| {
2929                *global_dispatch_count.borrow_mut() += 1;
2930            });
2931        });
2932
2933        cx.set_platform_focused_window_available(false);
2934        cx.update(|app| app.dispatch_action(&DispatchProbe));
2935
2936        assert_eq!(
2937            *global_dispatch_count.borrow(),
2938            1,
2939            "when backend focus authority is unavailable, app dispatch must not target active_window"
2940        );
2941    }
2942}