Skip to main content

gpui/
app.rs

1use scheduler::Instant;
2use std::{
3    any::{TypeId, type_name},
4    cell::{BorrowMutError, Cell, Ref, RefCell, RefMut},
5    ffi::OsString,
6    marker::PhantomData,
7    mem,
8    ops::{Deref, DerefMut},
9    path::{Path, PathBuf},
10    rc::{Rc, Weak},
11    sync::{Arc, atomic::Ordering::SeqCst},
12    time::Duration,
13};
14
15use anyhow::{Context as _, Result, anyhow};
16use derive_more::{Deref, DerefMut};
17use futures::{Future, FutureExt, channel::oneshot, future::LocalBoxFuture};
18use itertools::Itertools;
19use parking_lot::RwLock;
20use slotmap::SlotMap;
21
22pub use async_context::*;
23#[cfg(feature = "bench-support")]
24pub use bench_context::{
25    BenchAppContext, BenchMeasurement, BenchReport, BenchWindowContext, CountingAllocator,
26    MetricReport, bench_platform,
27};
28use collections::{FxHashMap, FxHashSet, HashMap, TypeIdHashMap, TypeIdHashSet, VecDeque};
29pub use context::*;
30pub use entity_map::*;
31use gpui_util::{ResultExt, debug_panic};
32#[cfg(any(test, feature = "test-support"))]
33pub use headless_app_context::*;
34use http_client::{HttpClient, Url};
35use smallvec::SmallVec;
36#[cfg(any(test, feature = "test-support"))]
37pub use test_app::*;
38#[cfg(any(test, feature = "test-support"))]
39pub use test_context::*;
40#[cfg(all(target_os = "macos", any(test, feature = "test-support")))]
41pub use visual_test_context::*;
42
43#[cfg(any(feature = "inspector", debug_assertions))]
44use crate::InspectorElementRegistry;
45use crate::asset_cache::CachedLoad;
46use crate::{
47    Action, ActionBuildError, ActionRegistry, ActivationPolicy, ActivityGuard, Any, AnyView,
48    AnyWindowHandle, AppContext, Arena, ArenaBox, Asset, AssetSource, BackgroundExecutor, Bounds,
49    ClipboardItem, ClipboardReadError, CursorStyle, DispatchPhase, DisplayId, EventEmitter,
50    ExternalDragPayload, FocusHandle, FocusMap, ForegroundExecutor, Global, KeyBinding, KeyContext,
51    Keymap, Keystroke, LayoutId, Menu, MenuItem, MissingGlyph, OwnedMenu, PathPromptOptions,
52    Pixels, Platform, PlatformDisplay, PlatformKeyboardLayout, PlatformKeyboardMapper, Point,
53    Priority, PromptBuilder, PromptButton, PromptHandle, PromptLevel, Render, RenderImage,
54    RenderablePromptHandle, Reservation, ScreenCaptureSource, SharedString, SubscriberSet,
55    Subscription, SvgRenderer, SystemNotification, SystemNotificationResponse, Task,
56    TextRenderingMode, TextSystem, ThermalState, Window, WindowAppearance, WindowButtonLayout,
57    WindowHandle, WindowId, WindowInvalidator, WindowingRequest,
58    colors::{Colors, GlobalColors},
59    hash, init_app_menus,
60};
61
62mod async_context;
63#[cfg(feature = "bench-support")]
64mod bench_context;
65mod context;
66mod entity_map;
67#[cfg(any(test, feature = "test-support"))]
68mod headless_app_context;
69#[cfg(any(test, feature = "test-support"))]
70mod test_app;
71#[cfg(any(test, feature = "test-support"))]
72mod test_context;
73#[cfg(all(target_os = "macos", any(test, feature = "test-support")))]
74mod visual_test_context;
75
76/// The duration for which native applications wait for futures returned from
77/// [Context::on_app_quit] before fully quitting.
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/// A reference to a GPUI application, typically constructed in the `main` function of your app.
146/// You won't interact with this type much outside of initial configuration and startup.
147pub struct Application(Rc<AppCell>);
148
149/// A strong handle to an [`Application`] started with [`Application::run_embedded`].
150///
151/// Dropping this handle releases the app, so an embedder must hold it for as long as the
152/// app should run. While held, it is the embedder's entry point back into GPUI each time
153/// the external run loop gives it control.
154pub struct ApplicationHandle {
155    app: Rc<AppCell>,
156}
157
158impl ApplicationHandle {
159    /// Invoke `f` with the app context. Must not be called re-entrantly from code that
160    /// is already inside an update; the app state is a `RefCell` and will panic on a
161    /// double borrow.
162    pub fn update<R>(&self, f: impl FnOnce(&mut App) -> R) -> R {
163        let cx = &mut *self.app.borrow_mut();
164        f(cx)
165    }
166
167    /// An [`AsyncApp`] for use across await points. It holds the app weakly; keeping the
168    /// app alive remains this handle's job.
169    pub fn to_async(&self) -> AsyncApp {
170        self.update(|cx| cx.to_async())
171    }
172}
173
174/// Represents an application before it is fully launched. Once your app is
175/// configured, you'll start the app with `App::run`.
176impl Application {
177    /// Builds an app with a caller-provided platform implementation.
178    pub fn with_platform(platform: Rc<dyn Platform>) -> Self {
179        Self(App::new_app(
180            platform,
181            Arc::new(()),
182            Arc::new(NullHttpClient),
183        ))
184    }
185
186    /// Builds an app with accessibility (AccessKit) integration forcibly
187    /// disabled.
188    ///
189    /// In this mode, accessibility APIs (e.g.
190    /// [`div().role()`][crate::StatefulInteractiveElement::role]) silently
191    /// no-op.
192    ///
193    /// See the [accessibility guide](crate::_accessibility) for an overview of
194    /// the features this disables.
195    pub fn new_inaccessible(platform: Rc<dyn Platform>) -> Self {
196        let this = Self::with_platform(platform);
197        this.0.borrow_mut().accessibility_force_disabled = true;
198        this
199    }
200
201    /// Assigns the source of assets for the application.
202    pub fn with_assets(self, asset_source: impl AssetSource) -> Self {
203        let mut context_lock = self.0.borrow_mut();
204        let asset_source = Arc::new(asset_source);
205        context_lock.asset_source = asset_source.clone();
206        context_lock.svg_renderer = SvgRenderer::new(asset_source);
207        drop(context_lock);
208        self
209    }
210
211    /// Configures arguments to pass when restarting the application.
212    pub fn with_restart_arguments(self, arguments: Vec<OsString>) -> Self {
213        self.0.borrow_mut().restart_arguments = arguments;
214        self
215    }
216
217    /// Sets the HTTP client for the application.
218    pub fn with_http_client(self, http_client: Arc<dyn HttpClient>) -> Self {
219        let mut context_lock = self.0.borrow_mut();
220        context_lock.http_client = http_client;
221        drop(context_lock);
222        self
223    }
224
225    /// Configures when the application should automatically quit.
226    /// By default, [`QuitMode::Default`] is used.
227    pub fn with_quit_mode(self, mode: QuitMode) -> Self {
228        self.0.borrow_mut().quit_mode = mode;
229        self
230    }
231
232    /// Sets the windowing mode the app starts in. See [`App::request_windowing`].
233    ///
234    /// Defaults to windowed. On Linux, the default environment is the process's own, and the app
235    /// starts headless if that names no allowed display server. On macOS, headless means the app
236    /// starts without a Dock icon or menu bar ([`ActivationPolicy::Accessory`]). Has no effect on
237    /// other platforms.
238    pub fn with_windowing(self, request: WindowingRequest) -> Self {
239        self.0.borrow().platform.set_initial_windowing(request);
240        self
241    }
242
243    /// Start the application. The provided callback will be called once the
244    /// app is fully launched.
245    ///
246    /// On WebAssembly, this returns immediately and retains the app for the lifetime
247    /// of the Wasm instance. Use [`Self::run_embedded`] to control its lifetime explicitly.
248    pub fn run<F>(self, on_finish_launching: F)
249    where
250        F: 'static + FnOnce(&mut App),
251    {
252        let this = self.0.clone();
253        let platform = self.0.borrow().platform.clone();
254        platform.run(Box::new(move || {
255            let cx = &mut *this.borrow_mut();
256            on_finish_launching(cx);
257        }));
258
259        #[cfg(target_family = "wasm")]
260        std::mem::forget(self);
261    }
262
263    /// Start the application for an embedder that drives the run loop itself.
264    ///
265    /// On ordinary platforms `Platform::run` blocks for the lifetime of the app, and the
266    /// app state is kept alive by [`Application::run`]'s stack frame. Embedded platforms —
267    /// where the run loop belongs to someone else, e.g. GPUI compiled into a Wasm guest,
268    /// or a GPUI view hosted inside a foreign native application — implement
269    /// `Platform::run` to invoke the launch callback and return immediately. This method
270    /// supports that shape: it returns an [`ApplicationHandle`] that keeps the app alive
271    /// and lets the embedder re-enter it whenever the external run loop yields control.
272    pub fn run_embedded<F>(self, on_finish_launching: F) -> ApplicationHandle
273    where
274        F: 'static + FnOnce(&mut App),
275    {
276        let this = self.0.clone();
277        let platform = self.0.borrow().platform.clone();
278        platform.run(Box::new(move || {
279            let cx = &mut *this.borrow_mut();
280            on_finish_launching(cx);
281        }));
282        ApplicationHandle { app: self.0 }
283    }
284
285    /// Register a handler to be invoked when the platform instructs the application
286    /// to open one or more URLs.
287    pub fn on_open_urls<F>(&self, mut callback: F) -> &Self
288    where
289        F: 'static + FnMut(Vec<String>),
290    {
291        self.0.borrow().platform.on_open_urls(Box::new(callback));
292        self
293    }
294
295    /// Invokes a handler when an already-running application is launched.
296    /// On macOS, this can occur when the application icon is double-clicked or the app is launched via the dock.
297    pub fn on_reopen<F>(&self, mut callback: F) -> &Self
298    where
299        F: 'static + FnMut(&mut App),
300    {
301        let this = Rc::downgrade(&self.0);
302        self.0.borrow_mut().platform.on_reopen(Box::new(move || {
303            if let Some(app) = this.upgrade() {
304                callback(&mut app.borrow_mut());
305            }
306        }));
307        self
308    }
309
310    /// Returns a handle to the [`BackgroundExecutor`] associated with this app, which can be used to spawn futures in the background.
311    pub fn background_executor(&self) -> BackgroundExecutor {
312        self.0.borrow().background_executor.clone()
313    }
314
315    /// Returns a handle to the [`ForegroundExecutor`] associated with this app, which can be used to spawn futures in the foreground.
316    pub fn foreground_executor(&self) -> ForegroundExecutor {
317        self.0.borrow().foreground_executor.clone()
318    }
319
320    /// Returns a reference to the [`TextSystem`] associated with this app.
321    pub fn text_system(&self) -> Arc<TextSystem> {
322        self.0.borrow().text_system.clone()
323    }
324
325    /// Returns the file URL of the executable with the specified name in the application bundle
326    pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
327        self.0.borrow().path_for_auxiliary_executable(name)
328    }
329}
330
331type Handler = Box<dyn FnMut(&mut App) -> bool + 'static>;
332type Listener = Box<dyn FnMut(&dyn Any, &mut App) -> bool + 'static>;
333type MissingGlyphCallback = Box<dyn FnMut(&[MissingGlyph], &mut App) + 'static>;
334pub(crate) type KeystrokeObserver =
335    Box<dyn FnMut(&KeystrokeEvent, &mut Window, &mut App) -> bool + 'static>;
336type QuitHandler = Box<dyn FnOnce(&mut App) -> LocalBoxFuture<'static, ()> + 'static>;
337type WindowClosedHandler = Box<dyn FnMut(&mut App, WindowId)>;
338type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut App) + 'static>;
339type NewEntityListener = Box<dyn FnMut(AnyEntity, &mut Option<&mut Window>, &mut App) + 'static>;
340
341struct MissingGlyphCallbackEntry {
342    registration: Rc<()>,
343    callback: Option<MissingGlyphCallback>,
344}
345
346#[derive(Default)]
347struct MissingGlyphCallbackSlot {
348    entry: RefCell<Option<MissingGlyphCallbackEntry>>,
349}
350
351impl MissingGlyphCallbackSlot {
352    fn replace(&self, callback: MissingGlyphCallback) -> Rc<()> {
353        let registration = Rc::new(());
354        self.entry.borrow_mut().replace(MissingGlyphCallbackEntry {
355            registration: registration.clone(),
356            callback: Some(callback),
357        });
358        registration
359    }
360
361    fn invoke(&self, missing_glyphs: &[MissingGlyph], cx: &mut App) {
362        let Some((registration, mut callback)) =
363            self.entry.borrow_mut().as_mut().and_then(|entry| {
364                entry
365                    .callback
366                    .take()
367                    .map(|callback| (entry.registration.clone(), callback))
368            })
369        else {
370            return;
371        };
372        callback(missing_glyphs, cx);
373
374        let mut entry = self.entry.borrow_mut();
375        let is_current = entry
376            .as_ref()
377            .is_some_and(|entry| Rc::ptr_eq(&entry.registration, &registration));
378        if is_current {
379            let Some(entry) = entry.as_mut() else {
380                return;
381            };
382            entry.callback = Some(callback);
383        }
384    }
385
386    fn remove(&self, registration: &Rc<()>) -> bool {
387        let mut entry = self.entry.borrow_mut();
388        let is_current = entry
389            .as_ref()
390            .is_some_and(|entry| Rc::ptr_eq(&entry.registration, registration));
391        if is_current {
392            entry.take();
393        }
394        is_current
395    }
396}
397
398/// Defines when the application should automatically quit.
399#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
400pub enum QuitMode {
401    /// Use [`QuitMode::Explicit`] on macOS and [`QuitMode::LastWindowClosed`] on other platforms.
402    #[default]
403    Default,
404    /// Quit automatically when the last window is closed.
405    LastWindowClosed,
406    /// Quit only when requested via [`App::quit`].
407    Explicit,
408}
409
410/// Controls when GPUI hides the mouse cursor in response to keyboard input.
411///
412/// Restoration on mouse motion is handled by the platform layer; this enum
413/// only describes the policy for *triggering* a hide.
414#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
415pub enum CursorHideMode {
416    /// Never hide the cursor automatically.
417    Never,
418    /// Hide on character-producing key presses (typing).
419    OnTyping,
420    /// Hide on character-producing key presses, *and* when a key binding
421    /// resolves to an action that consumes the keystroke.
422    #[default]
423    OnTypingAndAction,
424}
425
426#[doc(hidden)]
427#[derive(Clone, PartialEq, Eq)]
428pub struct SystemWindowTab {
429    pub id: WindowId,
430    pub title: SharedString,
431    pub handle: AnyWindowHandle,
432    pub last_active_at: Instant,
433}
434
435impl SystemWindowTab {
436    /// Create a new instance of the window tab.
437    pub fn new(title: SharedString, handle: AnyWindowHandle) -> Self {
438        Self {
439            id: handle.id,
440            title,
441            handle,
442            last_active_at: Instant::now(),
443        }
444    }
445}
446
447/// A controller for managing window tabs.
448#[derive(Default)]
449pub struct SystemWindowTabController {
450    visible: Option<bool>,
451    tab_groups: FxHashMap<usize, Vec<SystemWindowTab>>,
452}
453
454impl Global for SystemWindowTabController {}
455
456impl SystemWindowTabController {
457    /// Create a new instance of the window tab controller.
458    pub fn new() -> Self {
459        Self {
460            visible: None,
461            tab_groups: FxHashMap::default(),
462        }
463    }
464
465    /// Initialize the global window tab controller.
466    pub fn init(cx: &mut App) {
467        cx.set_global(SystemWindowTabController::new());
468    }
469
470    /// Get all tab groups.
471    pub fn tab_groups(&self) -> &FxHashMap<usize, Vec<SystemWindowTab>> {
472        &self.tab_groups
473    }
474
475    /// Get the next tab group window handle.
476    pub fn get_next_tab_group_window(cx: &mut App, id: WindowId) -> Option<&AnyWindowHandle> {
477        let controller = cx.global::<SystemWindowTabController>();
478        let current_group = controller
479            .tab_groups
480            .iter()
481            .find_map(|(group, tabs)| tabs.iter().find(|tab| tab.id == id).map(|_| group));
482
483        let current_group = current_group?;
484        // TODO: `.keys()` returns arbitrary order, what does "next" mean?
485        let mut group_ids: Vec<_> = controller.tab_groups.keys().collect();
486        let idx = group_ids.iter().position(|g| *g == current_group)?;
487        let next_idx = (idx + 1) % group_ids.len();
488
489        controller
490            .tab_groups
491            .get(group_ids[next_idx])
492            .and_then(|tabs| {
493                tabs.iter()
494                    .max_by_key(|tab| tab.last_active_at)
495                    .or_else(|| tabs.first())
496                    .map(|tab| &tab.handle)
497            })
498    }
499
500    /// Get the previous tab group window handle.
501    pub fn get_prev_tab_group_window(cx: &mut App, id: WindowId) -> Option<&AnyWindowHandle> {
502        let controller = cx.global::<SystemWindowTabController>();
503        let current_group = controller
504            .tab_groups
505            .iter()
506            .find_map(|(group, tabs)| tabs.iter().find(|tab| tab.id == id).map(|_| group));
507
508        let current_group = current_group?;
509        // TODO: `.keys()` returns arbitrary order, what does "previous" mean?
510        let mut group_ids: Vec<_> = controller.tab_groups.keys().collect();
511        let idx = group_ids.iter().position(|g| *g == current_group)?;
512        let prev_idx = if idx == 0 {
513            group_ids.len() - 1
514        } else {
515            idx - 1
516        };
517
518        controller
519            .tab_groups
520            .get(group_ids[prev_idx])
521            .and_then(|tabs| {
522                tabs.iter()
523                    .max_by_key(|tab| tab.last_active_at)
524                    .or_else(|| tabs.first())
525                    .map(|tab| &tab.handle)
526            })
527    }
528
529    /// Get all tabs in the same window.
530    pub fn tabs(&self, id: WindowId) -> Option<&Vec<SystemWindowTab>> {
531        self.tab_groups
532            .values()
533            .find(|tabs| tabs.iter().any(|tab| tab.id == id))
534    }
535
536    /// Initialize the visibility of the system window tab controller.
537    pub fn init_visible(cx: &mut App, visible: bool) {
538        let mut controller = cx.global_mut::<SystemWindowTabController>();
539        if controller.visible.is_none() {
540            controller.visible = Some(visible);
541        }
542    }
543
544    /// Get the visibility of the system window tab controller.
545    pub fn is_visible(&self) -> bool {
546        self.visible.unwrap_or(false)
547    }
548
549    /// Set the visibility of the system window tab controller.
550    pub fn set_visible(cx: &mut App, visible: bool) {
551        let mut controller = cx.global_mut::<SystemWindowTabController>();
552        controller.visible = Some(visible);
553    }
554
555    /// Update the last active of a window.
556    pub fn update_last_active(cx: &mut App, id: WindowId) {
557        let mut controller = cx.global_mut::<SystemWindowTabController>();
558        for windows in controller.tab_groups.values_mut() {
559            for tab in windows.iter_mut() {
560                if tab.id == id {
561                    tab.last_active_at = Instant::now();
562                }
563            }
564        }
565    }
566
567    /// Update the position of a tab within its group.
568    pub fn update_tab_position(cx: &mut App, id: WindowId, ix: usize) {
569        let mut controller = cx.global_mut::<SystemWindowTabController>();
570        for (_, windows) in controller.tab_groups.iter_mut() {
571            if let Some(current_pos) = windows.iter().position(|tab| tab.id == id) {
572                if ix < windows.len() && current_pos != ix {
573                    let window_tab = windows.remove(current_pos);
574                    windows.insert(ix, window_tab);
575                }
576                break;
577            }
578        }
579    }
580
581    /// Update the title of a tab.
582    pub fn update_tab_title(cx: &mut App, id: WindowId, title: SharedString) {
583        let controller = cx.global::<SystemWindowTabController>();
584        let tab = controller
585            .tab_groups
586            .values()
587            .flat_map(|windows| windows.iter())
588            .find(|tab| tab.id == id);
589
590        if tab.map_or(true, |t| t.title == title) {
591            return;
592        }
593
594        let mut controller = cx.global_mut::<SystemWindowTabController>();
595        for windows in controller.tab_groups.values_mut() {
596            for tab in windows.iter_mut() {
597                if tab.id == id {
598                    tab.title = title;
599                    return;
600                }
601            }
602        }
603    }
604
605    /// Insert a tab into a tab group.
606    pub fn add_tab(cx: &mut App, id: WindowId, tabs: Vec<SystemWindowTab>) {
607        let mut controller = cx.global_mut::<SystemWindowTabController>();
608        let Some(tab) = tabs.iter().find(|tab| tab.id == id).cloned() else {
609            return;
610        };
611
612        let mut expected_tab_ids: Vec<_> = tabs
613            .iter()
614            .filter(|tab| tab.id != id)
615            .map(|tab| tab.id)
616            .sorted()
617            .collect();
618
619        let mut tab_group_id = None;
620        for (group_id, group_tabs) in &controller.tab_groups {
621            let tab_ids: Vec<_> = group_tabs.iter().map(|tab| tab.id).sorted().collect();
622            if tab_ids == expected_tab_ids {
623                tab_group_id = Some(*group_id);
624                break;
625            }
626        }
627
628        if let Some(tab_group_id) = tab_group_id {
629            if let Some(tabs) = controller.tab_groups.get_mut(&tab_group_id) {
630                tabs.push(tab);
631            }
632        } else {
633            let new_group_id = controller.tab_groups.len();
634            controller.tab_groups.insert(new_group_id, tabs);
635        }
636    }
637
638    /// Remove a tab from a tab group.
639    pub fn remove_tab(cx: &mut App, id: WindowId) -> Option<SystemWindowTab> {
640        let mut controller = cx.global_mut::<SystemWindowTabController>();
641        let mut removed_tab = None;
642
643        controller.tab_groups.retain(|_, tabs| {
644            if let Some(pos) = tabs.iter().position(|tab| tab.id == id) {
645                removed_tab = Some(tabs.remove(pos));
646            }
647            !tabs.is_empty()
648        });
649
650        removed_tab
651    }
652
653    /// Move a tab to a new tab group.
654    pub fn move_tab_to_new_window(cx: &mut App, id: WindowId) {
655        let mut removed_tab = Self::remove_tab(cx, id);
656        let mut controller = cx.global_mut::<SystemWindowTabController>();
657
658        if let Some(tab) = removed_tab {
659            let new_group_id = controller.tab_groups.keys().max().map_or(0, |k| k + 1);
660            controller.tab_groups.insert(new_group_id, vec![tab]);
661        }
662    }
663
664    /// Merge all tab groups into a single group.
665    pub fn merge_all_windows(cx: &mut App, id: WindowId) {
666        let mut controller = cx.global_mut::<SystemWindowTabController>();
667        let Some(initial_tabs) = controller.tabs(id) else {
668            return;
669        };
670
671        let initial_tabs_len = initial_tabs.len();
672        let mut all_tabs = initial_tabs.clone();
673
674        for (_, mut tabs) in controller.tab_groups.drain() {
675            tabs.retain(|tab| !all_tabs[..initial_tabs_len].contains(tab));
676            all_tabs.extend(tabs);
677        }
678
679        controller.tab_groups.insert(0, all_tabs);
680    }
681
682    /// Selects the next tab in the tab group in the trailing direction.
683    pub fn select_next_tab(cx: &mut App, id: WindowId) {
684        let mut controller = cx.global_mut::<SystemWindowTabController>();
685        let Some(tabs) = controller.tabs(id) else {
686            return;
687        };
688
689        let current_index = tabs.iter().position(|tab| tab.id == id).unwrap();
690        let next_index = (current_index + 1) % tabs.len();
691
692        let _ = &tabs[next_index].handle.update(cx, |_, window, _| {
693            window.activate_window();
694        });
695    }
696
697    /// Selects the previous tab in the tab group in the leading direction.
698    pub fn select_previous_tab(cx: &mut App, id: WindowId) {
699        let mut controller = cx.global_mut::<SystemWindowTabController>();
700        let Some(tabs) = controller.tabs(id) else {
701            return;
702        };
703
704        let current_index = tabs.iter().position(|tab| tab.id == id).unwrap();
705        let previous_index = if current_index == 0 {
706            tabs.len() - 1
707        } else {
708            current_index - 1
709        };
710
711        let _ = &tabs[previous_index].handle.update(cx, |_, window, _| {
712            window.activate_window();
713        });
714    }
715}
716
717pub(crate) enum GpuiMode {
718    #[cfg(any(test, feature = "test-support"))]
719    Test {
720        skip_drawing: bool,
721    },
722    Production,
723}
724
725impl GpuiMode {
726    #[cfg(any(test, feature = "test-support"))]
727    pub fn test() -> Self {
728        GpuiMode::Test {
729            skip_drawing: false,
730        }
731    }
732
733    #[inline]
734    pub(crate) fn skip_drawing(&self) -> bool {
735        match self {
736            #[cfg(any(test, feature = "test-support"))]
737            GpuiMode::Test { skip_drawing } => *skip_drawing,
738            GpuiMode::Production => false,
739        }
740    }
741}
742
743struct PlatformOwnedDrag {
744    source_window: WindowId,
745    state: PlatformOwnedDragState,
746}
747
748enum PlatformOwnedDragState {
749    Suspended(AnyDrag),
750    // A source-window drop consumes `active_drag` before AppKit ends the dragging session, so this
751    // marker can outlive the active drag and is cleaned up by `FileDropEvent::Ended`.
752    RestoredInSourceWindow,
753}
754
755/// Contains the state of the full application, and passed as a reference to a variety of callbacks.
756/// Other [Context] derefs to this type.
757/// You need a reference to an `App` to access the state of a [Entity].
758pub struct App {
759    pub(crate) this: Weak<AppCell>,
760    pub(crate) platform: Rc<dyn Platform>,
761    text_system: Arc<TextSystem>,
762
763    pub(crate) actions: Rc<ActionRegistry>,
764    pub(crate) active_drag: Option<AnyDrag>,
765    platform_owned_drag: Option<PlatformOwnedDrag>,
766    pub(crate) background_executor: BackgroundExecutor,
767    pub(crate) foreground_executor: ForegroundExecutor,
768    #[cfg(feature = "profiler")]
769    foreground_journal: crate::profiler::journal::ForegroundJournal,
770    #[cfg(all(feature = "profiler", not(target_family = "wasm")))]
771    hang_monitor: Option<crate::profiler::hang::HangMonitor>,
772    pub(crate) entities: EntityMap,
773    pub(crate) new_entity_observers: SubscriberSet<TypeId, NewEntityListener>,
774    pub(crate) windows: SlotMap<WindowId, Option<Box<Window>>>,
775    pub(crate) window_handles: FxHashMap<WindowId, AnyWindowHandle>,
776    pub(crate) focus_handles: Arc<FocusMap>,
777    pub(crate) keymap: Rc<RefCell<Keymap>>,
778    pub(crate) keyboard_layout: Box<dyn PlatformKeyboardLayout>,
779    pub(crate) keyboard_mapper: Rc<dyn PlatformKeyboardMapper>,
780    pub(crate) global_action_listeners:
781        TypeIdHashMap<Vec<Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Self)>>>,
782    pending_effects: VecDeque<Effect>,
783
784    pub(crate) observers: SubscriberSet<EntityId, Handler>,
785    pub(crate) event_listeners: SubscriberSet<EntityId, (TypeId, Listener)>,
786    pub(crate) keystroke_observers: SubscriberSet<(), KeystrokeObserver>,
787    pub(crate) keystroke_interceptors: SubscriberSet<(), KeystrokeObserver>,
788    pub(crate) keyboard_layout_observers: SubscriberSet<(), Handler>,
789    missing_glyph_callback: Rc<MissingGlyphCallbackSlot>,
790    pub(crate) thermal_state_observers: SubscriberSet<(), Handler>,
791    pub(crate) system_sleep_observers: SubscriberSet<(), Handler>,
792    pub(crate) system_wake_observers: SubscriberSet<(), Handler>,
793    pub(crate) release_listeners: SubscriberSet<EntityId, ReleaseListener>,
794    pub(crate) global_observers: SubscriberSet<TypeId, Handler>,
795    pub(crate) quit_observers: SubscriberSet<(), QuitHandler>,
796    pub(crate) restart_observers: SubscriberSet<(), Handler>,
797    pub(crate) window_closed_observers: SubscriberSet<(), WindowClosedHandler>,
798
799    /// Per-App element arena. This isolates element allocations between different
800    /// App instances (important for tests where multiple Apps run concurrently).
801    pub(crate) element_arena: RefCell<Arena>,
802    /// Per-App event arena.
803    pub(crate) event_arena: Arena,
804
805    // Drop globals last. We need to ensure all tasks owned by entities and
806    // callbacks are marked cancelled at this point as this will also shutdown
807    // the tokio runtime. As any task attempting to spawn a blocking tokio task,
808    // might panic.
809    pub(crate) globals_by_type: TypeIdHashMap<Box<dyn Any>>,
810
811    // assets
812    pub(crate) loading_assets: FxHashMap<(TypeId, u64), Box<dyn Any>>,
813    asset_source: Arc<dyn AssetSource>,
814    pub(crate) svg_renderer: SvgRenderer,
815    http_client: Arc<dyn HttpClient>,
816
817    // below is plain data, the drop order is insignificant here
818    pub(crate) pending_notifications: FxHashSet<EntityId>,
819    pub(crate) pending_global_notifications: TypeIdHashSet,
820    pub(crate) restart_path: Option<PathBuf>,
821    pub(crate) restart_arguments: Vec<OsString>,
822    pub(crate) layout_id_buffer: Vec<LayoutId>, // We recycle this memory across layout requests.
823    pub(crate) propagate_event: bool,
824    pub(crate) prompt_builder: Option<PromptBuilder>,
825    pub(crate) window_invalidators_by_entity:
826        FxHashMap<EntityId, FxHashMap<WindowId, WindowInvalidator>>,
827    pub(crate) tracked_entities: FxHashMap<WindowId, FxHashSet<EntityId>>,
828    pub(crate) current_window_by_entity: FxHashMap<EntityId, WindowId>,
829    #[cfg(any(feature = "inspector", debug_assertions))]
830    pub(crate) inspector_renderer: Option<crate::InspectorRenderer>,
831    #[cfg(any(feature = "inspector", debug_assertions))]
832    pub(crate) inspector_element_registry: InspectorElementRegistry,
833    #[cfg(any(test, feature = "test-support", debug_assertions))]
834    pub(crate) name: Option<&'static str>,
835    pub(crate) text_rendering_mode: Rc<Cell<TextRenderingMode>>,
836
837    pub(crate) window_update_stack: Vec<WindowId>,
838    pub(crate) mode: GpuiMode,
839    pub(crate) cursor_hide_mode: CursorHideMode,
840    pub(crate) reduce_motion: bool,
841    /// Origin of the shared clock that phase-locks synced repeating animations.
842    pub(crate) synced_animation_epoch: Instant,
843    /// Whether the app was created by [`Application::new_inaccessible`]. No
844    /// accesskit APIs will be called when this flag is set.
845    pub(crate) accessibility_force_disabled: bool,
846    flushing_effects: bool,
847    pending_updates: usize,
848    quit_mode: QuitMode,
849    quitting: bool,
850
851    // We need to ensure the leak detector drops last, after all tasks, callbacks and things have been dropped.
852    // Otherwise it may report false positives.
853    #[cfg(any(test, gpui_leak_detection))]
854    _ref_counts: Arc<RwLock<EntityRefCounts>>,
855}
856
857impl App {
858    #[allow(clippy::new_ret_no_self)]
859    pub(crate) fn new_app(
860        platform: Rc<dyn Platform>,
861        asset_source: Arc<dyn AssetSource>,
862        http_client: Arc<dyn HttpClient>,
863    ) -> Rc<AppCell> {
864        let background_executor = platform.background_executor();
865        let foreground_executor = platform.foreground_executor();
866        assert!(
867            background_executor.is_main_thread(),
868            "must construct App on main thread"
869        );
870        #[cfg(feature = "profiler")]
871        let foreground_journal = crate::profiler::journal::install_foreground_journal();
872        let synced_animation_epoch = background_executor.now();
873
874        let text_system = Arc::new(TextSystem::new(platform.text_system()));
875        let entities = EntityMap::new();
876        let keyboard_layout = platform.keyboard_layout();
877        let keyboard_mapper = platform.keyboard_mapper();
878
879        #[cfg(any(test, gpui_leak_detection))]
880        let _ref_counts = entities.ref_counts_drop_handle();
881
882        let app = Rc::new_cyclic(|this| AppCell {
883            app: RefCell::new(App {
884                this: this.clone(),
885                platform: platform.clone(),
886                text_system,
887                text_rendering_mode: Rc::new(Cell::new(TextRenderingMode::default())),
888                mode: GpuiMode::Production,
889                actions: Rc::new(ActionRegistry::default()),
890                flushing_effects: false,
891                pending_updates: 0,
892                active_drag: None,
893                platform_owned_drag: None,
894                background_executor,
895                foreground_executor,
896                #[cfg(feature = "profiler")]
897                foreground_journal,
898                #[cfg(all(feature = "profiler", not(target_family = "wasm")))]
899                hang_monitor: None,
900                svg_renderer: SvgRenderer::new(asset_source.clone()),
901                loading_assets: Default::default(),
902                asset_source,
903                http_client,
904                globals_by_type: Default::default(),
905                entities,
906                new_entity_observers: SubscriberSet::new(),
907                windows: SlotMap::with_key(),
908                window_update_stack: Vec::new(),
909                window_handles: FxHashMap::default(),
910                focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
911                keymap: Rc::new(RefCell::new(Keymap::default())),
912                keyboard_layout,
913                keyboard_mapper,
914                global_action_listeners: Default::default(),
915                pending_effects: VecDeque::new(),
916                pending_notifications: FxHashSet::default(),
917                pending_global_notifications: Default::default(),
918                observers: SubscriberSet::new(),
919                tracked_entities: FxHashMap::default(),
920                window_invalidators_by_entity: FxHashMap::default(),
921                current_window_by_entity: FxHashMap::default(),
922                event_listeners: SubscriberSet::new(),
923                release_listeners: SubscriberSet::new(),
924                keystroke_observers: SubscriberSet::new(),
925                keystroke_interceptors: SubscriberSet::new(),
926                keyboard_layout_observers: SubscriberSet::new(),
927                missing_glyph_callback: Rc::default(),
928                thermal_state_observers: SubscriberSet::new(),
929                system_sleep_observers: SubscriberSet::new(),
930                system_wake_observers: SubscriberSet::new(),
931                global_observers: SubscriberSet::new(),
932                quit_observers: SubscriberSet::new(),
933                restart_observers: SubscriberSet::new(),
934                restart_path: None,
935                restart_arguments: Vec::new(),
936                window_closed_observers: SubscriberSet::new(),
937                layout_id_buffer: Default::default(),
938                propagate_event: true,
939                prompt_builder: Some(PromptBuilder::Default),
940                #[cfg(any(feature = "inspector", debug_assertions))]
941                inspector_renderer: None,
942                #[cfg(any(feature = "inspector", debug_assertions))]
943                inspector_element_registry: InspectorElementRegistry::default(),
944                quit_mode: QuitMode::default(),
945                quitting: false,
946                cursor_hide_mode: CursorHideMode::default(),
947                reduce_motion: false,
948                synced_animation_epoch,
949                accessibility_force_disabled: false,
950
951                #[cfg(any(test, feature = "test-support", debug_assertions))]
952                name: None,
953                element_arena: RefCell::new(Arena::new(1024 * 1024)),
954                event_arena: Arena::new(1024 * 1024),
955
956                #[cfg(any(test, gpui_leak_detection))]
957                _ref_counts,
958            }),
959        });
960
961        init_app_menus(platform.as_ref(), &app.borrow());
962        SystemWindowTabController::init(&mut app.borrow_mut());
963        #[cfg(feature = "profiler")]
964        crate::profiler::journal::observe_power(&app.borrow());
965
966        platform.on_keyboard_layout_change(Box::new({
967            let app = Rc::downgrade(&app);
968            move || {
969                if let Some(app) = app.upgrade() {
970                    let cx = &mut app.borrow_mut();
971                    cx.keyboard_layout = cx.platform.keyboard_layout();
972                    cx.keyboard_mapper = cx.platform.keyboard_mapper();
973                    cx.keyboard_layout_observers
974                        .clone()
975                        .retain(&(), move |callback| (callback)(cx));
976                }
977            }
978        }));
979
980        platform.on_thermal_state_change(Box::new({
981            let app = Rc::downgrade(&app);
982            move || {
983                if let Some(app) = app.upgrade() {
984                    let cx = &mut app.borrow_mut();
985                    cx.thermal_state_observers
986                        .clone()
987                        .retain(&(), move |callback| (callback)(cx));
988                }
989            }
990        }));
991
992        platform.on_system_sleep(Box::new({
993            let app = Rc::downgrade(&app);
994            move || {
995                if let Some(app) = app.upgrade() {
996                    let cx = &mut app.borrow_mut();
997                    cx.system_sleep_observers
998                        .clone()
999                        .retain(&(), move |callback| (callback)(cx));
1000                }
1001            }
1002        }));
1003
1004        platform.on_system_wake(Box::new({
1005            let app = Rc::downgrade(&app);
1006            move || {
1007                if let Some(app) = app.upgrade() {
1008                    let cx = &mut app.borrow_mut();
1009                    cx.system_wake_observers
1010                        .clone()
1011                        .retain(&(), move |callback| (callback)(cx));
1012                }
1013            }
1014        }));
1015
1016        platform.on_quit(Box::new({
1017            let cx = Rc::downgrade(&app);
1018            move || {
1019                let Some(cx) = cx.upgrade() else {
1020                    return true;
1021                };
1022                match cx.try_borrow_mut() {
1023                    Ok(mut cx) => {
1024                        cx.shutdown();
1025                        true
1026                    }
1027                    Err(_) => {
1028                        // Quit was requested while the AppCell was borrowed, so we can't shut down synchronously.
1029                        // The platform decides how to proceed.
1030                        false
1031                    }
1032                }
1033            }
1034        }));
1035
1036        app
1037    }
1038
1039    #[doc(hidden)]
1040    pub fn ref_counts_drop_handle(&self) -> impl Sized + use<> {
1041        self.entities.ref_counts_drop_handle()
1042    }
1043
1044    /// Captures a snapshot of all entities that currently have alive handles.
1045    ///
1046    /// The returned [`LeakDetectorSnapshot`] can later be passed to
1047    /// [`assert_no_new_leaks`](Self::assert_no_new_leaks) to verify that no
1048    /// entities created after the snapshot are still alive.
1049    #[cfg(any(test, gpui_leak_detection))]
1050    pub fn leak_detector_snapshot(&self) -> LeakDetectorSnapshot {
1051        self.entities.leak_detector_snapshot()
1052    }
1053
1054    /// Asserts that no entities created after `snapshot` still have alive handles.
1055    ///
1056    /// Entities that were already tracked at the time of the snapshot are ignored,
1057    /// even if they still have handles. Only *new* entities (those whose
1058    /// `EntityId` was not present in the snapshot) are considered leaks.
1059    ///
1060    /// # Panics
1061    ///
1062    /// Panics if any new entity handles exist. The panic message lists every
1063    /// leaked entity with its type name, and includes allocation-site backtraces
1064    /// when `LEAK_BACKTRACE` is set.
1065    #[cfg(any(test, gpui_leak_detection))]
1066    pub fn assert_no_new_leaks(&self, snapshot: &LeakDetectorSnapshot) {
1067        self.entities.assert_no_new_leaks(snapshot)
1068    }
1069
1070    /// Without leak detection compiled in, this records nothing.
1071    #[cfg(all(feature = "test-support", not(any(test, gpui_leak_detection))))]
1072    pub fn leak_detector_snapshot(&self) -> LeakDetectorSnapshot {
1073        LeakDetectorSnapshot::default()
1074    }
1075
1076    /// Without leak detection compiled in, this checks nothing. Set
1077    /// `GPUI_LEAK_DETECTION` when building to enable it.
1078    #[cfg(all(feature = "test-support", not(any(test, gpui_leak_detection))))]
1079    pub fn assert_no_new_leaks(&self, _snapshot: &LeakDetectorSnapshot) {}
1080
1081    /// Quit the application gracefully.
1082    ///
1083    /// Native applications give handlers registered with [`Context::on_app_quit`]
1084    /// [`SHUTDOWN_TIMEOUT`] to complete. WebAssembly runs them asynchronously as best-effort cleanup
1085    /// because its event-loop thread cannot block.
1086    pub fn shutdown(&mut self) {
1087        // Requested first so the final hang poll overlaps with the quit
1088        // handlers. It's awaited alongside them, within `SHUTDOWN_TIMEOUT`.
1089        #[cfg(all(feature = "profiler", not(target_family = "wasm")))]
1090        let hang_monitor_flush = self
1091            .hang_monitor
1092            .as_ref()
1093            .and_then(|hang_monitor| hang_monitor.request_flush());
1094
1095        let mut futures: Vec<LocalBoxFuture<'static, ()>> = Vec::new();
1096
1097        for observer in self.quit_observers.remove(&()) {
1098            futures.push(observer(self));
1099        }
1100
1101        #[cfg(all(feature = "profiler", not(target_family = "wasm")))]
1102        if let Some(flushed) = hang_monitor_flush {
1103            futures.push(
1104                async move {
1105                    if flushed.await.is_err() {
1106                        log::warn!("hang monitor exited before flushing");
1107                    }
1108                }
1109                .boxed_local(),
1110            );
1111        }
1112
1113        self.windows.clear();
1114        self.window_handles.clear();
1115        self.flush_effects();
1116        self.quitting = true;
1117
1118        let futures = futures::future::join_all(futures);
1119        #[cfg(not(target_family = "wasm"))]
1120        if self
1121            .foreground_executor
1122            .block_with_timeout(SHUTDOWN_TIMEOUT, futures)
1123            .is_err()
1124        {
1125            log::error!("timed out waiting on app_will_quit");
1126        }
1127        #[cfg(target_family = "wasm")]
1128        self.foreground_executor.spawn(futures).detach();
1129
1130        self.quitting = false;
1131    }
1132
1133    /// Get the id of the current keyboard layout
1134    pub fn keyboard_layout(&self) -> &dyn PlatformKeyboardLayout {
1135        self.keyboard_layout.as_ref()
1136    }
1137
1138    /// Get the current keyboard mapper.
1139    pub fn keyboard_mapper(&self) -> &Rc<dyn PlatformKeyboardMapper> {
1140        &self.keyboard_mapper
1141    }
1142
1143    /// Invokes a handler when the current keyboard layout changes
1144    pub fn on_keyboard_layout_change<F>(&self, mut callback: F) -> Subscription
1145    where
1146        F: 'static + FnMut(&mut App),
1147    {
1148        let (subscription, activate) = self.keyboard_layout_observers.insert(
1149            (),
1150            Box::new(move |cx| {
1151                callback(cx);
1152                true
1153            }),
1154        );
1155        activate();
1156        subscription
1157    }
1158
1159    /// Gracefully quit the application via the platform's standard routine.
1160    pub fn quit(&self) {
1161        self.platform.quit();
1162    }
1163
1164    /// Switches the platform between headless and windowed modes.
1165    ///
1166    /// On Linux, headless means no display server: windows opened afterwards lay out and handle
1167    /// input but draw nothing. Windowed, the platform connects to the display server the
1168    /// environment names. On macOS, the modes set the [`ActivationPolicy`]: headless is
1169    /// `Accessory` (no Dock icon or menu bar) and windowed is `Regular`. Switching to windowed
1170    /// doesn't activate the app: call [`App::activate`] for that.
1171    ///
1172    /// The returned task resolves once the switch has been applied. It fails if the platform is
1173    /// already in the requested mode (switching to another display server means going headless
1174    /// first), if the platform doesn't allow the mode or can't switch at all, if any window is
1175    /// open (a window belongs to the display server that opened it), or if the display server
1176    /// can't be reached.
1177    pub fn request_windowing(&self, request: WindowingRequest) -> Task<anyhow::Result<()>> {
1178        if !self.windows.is_empty() {
1179            return Task::ready(Err(anyhow::anyhow!(
1180                "cannot switch windowing modes while windows are open"
1181            )));
1182        }
1183        self.platform.request_windowing(request)
1184    }
1185
1186    /// The environment of the display server the platform is connected to, or `None` while
1187    /// headless. Its activation token is always unset, since the connection has used it.
1188    ///
1189    /// Programs an app launches inherit this process's environment, which may name another
1190    /// graphical session, or none if the app started headless. Pass them this one with
1191    /// [`GraphicalEnvironment::apply_to`](crate::GraphicalEnvironment::apply_to).
1192    ///
1193    /// On macOS, the environment carries nothing, and this is `None` while the activation
1194    /// policy is `Accessory`. Always `None` on platforms that can't switch windowing modes.
1195    pub fn graphical_environment(&self) -> Option<crate::GraphicalEnvironment> {
1196        self.platform.graphical_environment()
1197    }
1198
1199    /// Returns the current policy for hiding the cursor in response to
1200    /// keyboard input.
1201    pub fn cursor_hide_mode(&self) -> CursorHideMode {
1202        self.cursor_hide_mode
1203    }
1204
1205    /// Sets the policy controlling when GPUI hides the cursor in response
1206    /// to keyboard input.
1207    pub fn set_cursor_hide_mode(&mut self, mode: CursorHideMode) {
1208        self.cursor_hide_mode = mode;
1209    }
1210
1211    /// Returns whether the cursor is currently visible according to the
1212    /// platform. This will report `false` after a keyboard input has hidden
1213    /// the cursor and the user has not yet moved the mouse to restore it.
1214    ///
1215    /// See [`App::set_cursor_hide_mode`].
1216    pub fn is_cursor_visible(&self) -> bool {
1217        self.platform.is_cursor_visible()
1218    }
1219
1220    /// Returns whether non-essential animations (e.g. loading spinners) should
1221    /// be rendered in a static state instead of animating.
1222    pub fn reduce_motion(&self) -> bool {
1223        self.reduce_motion
1224    }
1225
1226    /// Sets whether non-essential animations (e.g. loading spinners) should be
1227    /// rendered in a static state instead of animating.
1228    pub fn set_reduce_motion(&mut self, reduce_motion: bool) {
1229        if self.reduce_motion != reduce_motion {
1230            self.reduce_motion = reduce_motion;
1231            self.refresh_windows();
1232        }
1233    }
1234
1235    /// Schedules all windows in the application to be redrawn. This can be called
1236    /// multiple times in an update cycle and still result in a single redraw.
1237    pub fn refresh_windows(&mut self) {
1238        self.pending_effects.push_back(Effect::RefreshWindows);
1239    }
1240
1241    #[inline(always)]
1242    pub(crate) fn update<R>(&mut self, update: impl FnOnce(&mut Self) -> R) -> R {
1243        self.start_update();
1244        let result = update(self);
1245        self.finish_update();
1246        result
1247    }
1248
1249    pub(crate) fn start_update(&mut self) {
1250        self.pending_updates += 1;
1251    }
1252
1253    #[inline(never)]
1254    pub(crate) fn finish_update(&mut self) {
1255        if !self.flushing_effects && self.pending_updates == 1 {
1256            self.flushing_effects = true;
1257            self.flush_effects();
1258            self.flushing_effects = false;
1259        }
1260        self.pending_updates -= 1;
1261    }
1262
1263    /// Arrange a callback to be invoked when the given entity calls `notify` on its respective context.
1264    pub fn observe<W>(
1265        &mut self,
1266        entity: &Entity<W>,
1267        mut on_notify: impl FnMut(Entity<W>, &mut App) + 'static,
1268    ) -> Subscription
1269    where
1270        W: 'static,
1271    {
1272        self.observe_internal(entity, move |e, cx| {
1273            on_notify(e, cx);
1274            true
1275        })
1276    }
1277
1278    pub(crate) fn detect_accessed_entities<R>(
1279        &mut self,
1280        callback: impl FnOnce(&mut App) -> R,
1281    ) -> (R, FxHashSet<EntityId>) {
1282        let accessed_entities_start = self.entities.accessed_entities.get_mut().clone();
1283        let result = callback(self);
1284        let entities_accessed_in_callback = self
1285            .entities
1286            .accessed_entities
1287            .get_mut()
1288            .difference(&accessed_entities_start)
1289            .copied()
1290            .collect::<FxHashSet<EntityId>>();
1291        (result, entities_accessed_in_callback)
1292    }
1293
1294    pub(crate) fn record_entities_accessed(
1295        &mut self,
1296        window_handle: AnyWindowHandle,
1297        invalidator: WindowInvalidator,
1298        entities: &FxHashSet<EntityId>,
1299    ) {
1300        let mut tracked_entities =
1301            std::mem::take(self.tracked_entities.entry(window_handle.id).or_default());
1302        for entity in tracked_entities.iter() {
1303            self.window_invalidators_by_entity
1304                .entry(*entity)
1305                .and_modify(|windows| {
1306                    windows.remove(&window_handle.id);
1307                });
1308        }
1309        for entity in entities.iter() {
1310            self.window_invalidators_by_entity
1311                .entry(*entity)
1312                .or_default()
1313                .insert(window_handle.id, invalidator.clone());
1314            self.current_window_by_entity
1315                .insert(*entity, window_handle.id);
1316        }
1317        tracked_entities.clear();
1318        tracked_entities.extend(entities.iter().copied());
1319        self.tracked_entities
1320            .insert(window_handle.id, tracked_entities);
1321    }
1322
1323    pub(crate) fn new_observer(&mut self, key: EntityId, value: Handler) -> Subscription {
1324        let (subscription, activate) = self.observers.insert(key, value);
1325        self.defer(move |_| activate());
1326        subscription
1327    }
1328
1329    pub(crate) fn observe_internal<W>(
1330        &mut self,
1331        entity: &Entity<W>,
1332        mut on_notify: impl FnMut(Entity<W>, &mut App) -> bool + 'static,
1333    ) -> Subscription
1334    where
1335        W: 'static,
1336    {
1337        let entity_id = entity.entity_id();
1338        let handle = entity.downgrade();
1339        self.new_observer(
1340            entity_id,
1341            Box::new(move |cx| {
1342                if let Some(entity) = handle.upgrade() {
1343                    on_notify(entity, cx)
1344                } else {
1345                    false
1346                }
1347            }),
1348        )
1349    }
1350
1351    /// Arrange for the given callback to be invoked whenever the given entity emits an event of a given type.
1352    /// The callback is provided a handle to the emitting entity and a reference to the emitted event.
1353    pub fn subscribe<T, Event>(
1354        &mut self,
1355        entity: &Entity<T>,
1356        mut on_event: impl FnMut(Entity<T>, &Event, &mut App) + 'static,
1357    ) -> Subscription
1358    where
1359        T: 'static + EventEmitter<Event>,
1360        Event: 'static,
1361    {
1362        self.subscribe_internal(entity, move |entity, event, cx| {
1363            on_event(entity, event, cx);
1364            true
1365        })
1366    }
1367
1368    pub(crate) fn new_subscription(
1369        &mut self,
1370        key: EntityId,
1371        value: (TypeId, Listener),
1372    ) -> Subscription {
1373        let (subscription, activate) = self.event_listeners.insert(key, value);
1374        self.defer(move |_| activate());
1375        subscription
1376    }
1377    pub(crate) fn subscribe_internal<T, Evt>(
1378        &mut self,
1379        entity: &Entity<T>,
1380        mut on_event: impl FnMut(Entity<T>, &Evt, &mut App) -> bool + 'static,
1381    ) -> Subscription
1382    where
1383        T: 'static + EventEmitter<Evt>,
1384        Evt: 'static,
1385    {
1386        let entity_id = entity.entity_id();
1387        let handle = entity.downgrade();
1388        self.new_subscription(
1389            entity_id,
1390            (
1391                TypeId::of::<Evt>(),
1392                Box::new(move |event, cx| {
1393                    let event: &Evt = event.downcast_ref().expect("invalid event type");
1394                    if let Some(entity) = handle.upgrade() {
1395                        on_event(entity, event, cx)
1396                    } else {
1397                        false
1398                    }
1399                }),
1400            ),
1401        )
1402    }
1403
1404    /// Returns handles to all open windows in the application.
1405    /// Each handle could be downcast to a handle typed for the root view of that window.
1406    /// To find all windows of a given type, you could filter on
1407    pub fn windows(&self) -> Vec<AnyWindowHandle> {
1408        self.windows
1409            .keys()
1410            .flat_map(|window_id| self.window_handles.get(&window_id).copied())
1411            .collect()
1412    }
1413
1414    /// Returns the window handles ordered by their appearance on screen, front to back.
1415    ///
1416    /// The first window in the returned list is the active/topmost window of the application.
1417    ///
1418    /// This method returns None if the platform doesn't implement the method yet.
1419    pub fn window_stack(&self) -> Option<Vec<AnyWindowHandle>> {
1420        self.platform.window_stack()
1421    }
1422
1423    /// Returns a handle to the window that is currently focused at the platform level, if one exists.
1424    pub fn active_window(&self) -> Option<AnyWindowHandle> {
1425        self.platform.active_window()
1426    }
1427
1428    /// Opens a new window with the given option and the root view returned by the given function.
1429    /// The function is invoked with a `Window`, which can be used to interact with window-specific
1430    /// functionality.
1431    pub fn open_window<V: 'static + Render>(
1432        &mut self,
1433        options: crate::WindowOptions,
1434        build_root_view: impl FnOnce(&mut Window, &mut App) -> Entity<V>,
1435    ) -> anyhow::Result<WindowHandle<V>> {
1436        self.update(|cx| {
1437            let id = cx.windows.insert(None);
1438            let handle = WindowHandle::new(id);
1439            match Window::new(handle.into(), options, cx) {
1440                Ok(mut window) => {
1441                    cx.window_update_stack.push(id);
1442                    let root_view = build_root_view(&mut window, cx);
1443                    cx.window_update_stack.pop();
1444                    window.root.replace(root_view.into());
1445                    window.defer(cx, |window: &mut Window, cx| window.appearance_changed(cx));
1446
1447                    // allow a window to draw at least once before returning
1448                    // this didn't cause any issues on non windows platforms as it seems we always won the race to on_request_frame
1449                    // on windows we quite frequently lose the race and return a window that has never rendered, which leads to a crash
1450                    // where DispatchTree::root_node_id asserts on empty nodes
1451                    let clear = window.draw(cx);
1452                    clear.clear(cx);
1453
1454                    cx.window_handles.insert(id, window.handle);
1455                    cx.windows.get_mut(id).unwrap().replace(Box::new(window));
1456                    Ok(handle)
1457                }
1458                Err(e) => {
1459                    cx.windows.remove(id);
1460                    Err(e)
1461                }
1462            }
1463        })
1464    }
1465
1466    /// Instructs the platform to activate the application by bringing it to the foreground.
1467    pub fn activate(&self, ignoring_other_apps: bool) {
1468        self.platform.activate(ignoring_other_apps);
1469    }
1470
1471    /// Hide the application at the platform level.
1472    pub fn hide(&self) {
1473        self.platform.hide();
1474    }
1475
1476    /// Hide other applications at the platform level.
1477    pub fn hide_other_apps(&self) {
1478        self.platform.hide_other_apps();
1479    }
1480
1481    /// Unhide other applications at the platform level.
1482    pub fn unhide_other_apps(&self) {
1483        self.platform.unhide_other_apps();
1484    }
1485
1486    /// Returns the list of currently active displays.
1487    pub fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
1488        self.platform.displays()
1489    }
1490
1491    /// Returns the primary display that will be used for new windows.
1492    pub fn primary_display(&self) -> Option<Rc<dyn PlatformDisplay>> {
1493        self.platform.primary_display()
1494    }
1495
1496    /// Returns whether `screen_capture_sources` may work.
1497    pub fn is_screen_capture_supported(&self) -> bool {
1498        self.platform.is_screen_capture_supported()
1499    }
1500
1501    /// Returns a list of available screen capture sources.
1502    pub fn screen_capture_sources(
1503        &self,
1504    ) -> oneshot::Receiver<Result<Vec<Rc<dyn ScreenCaptureSource>>>> {
1505        self.platform.screen_capture_sources()
1506    }
1507
1508    /// Returns the display with the given ID, if one exists.
1509    pub fn find_display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
1510        self.displays()
1511            .iter()
1512            .find(|display| display.id() == id)
1513            .cloned()
1514    }
1515
1516    /// Returns the current thermal state of the system.
1517    pub fn thermal_state(&self) -> ThermalState {
1518        self.platform.thermal_state()
1519    }
1520
1521    /// Prevents idle sleep while the returned guard is held.
1522    pub fn prevent_idle_sleep(&self, reason: &str) -> Task<Result<ActivityGuard>> {
1523        self.platform.prevent_idle_sleep(reason)
1524    }
1525
1526    /// Invokes a handler when the thermal state changes
1527    pub fn on_thermal_state_change<F>(&self, mut callback: F) -> Subscription
1528    where
1529        F: 'static + FnMut(&mut App),
1530    {
1531        let (subscription, activate) = self.thermal_state_observers.insert(
1532            (),
1533            Box::new(move |cx| {
1534                callback(cx);
1535                true
1536            }),
1537        );
1538        activate();
1539        subscription
1540    }
1541
1542    /// Invokes a handler when the system is about to sleep.
1543    ///
1544    /// The platform gives the process only a short time before suspending, so
1545    /// handlers should record state or cancel work rather than start it.
1546    pub fn on_system_sleep<F>(&self, mut callback: F) -> Subscription
1547    where
1548        F: 'static + FnMut(&mut App),
1549    {
1550        let (subscription, activate) = self.system_sleep_observers.insert(
1551            (),
1552            Box::new(move |cx| {
1553                callback(cx);
1554                true
1555            }),
1556        );
1557        activate();
1558        subscription
1559    }
1560
1561    /// Invokes a handler when the system wakes from sleep.
1562    pub fn on_system_wake<F>(&self, mut callback: F) -> Subscription
1563    where
1564        F: 'static + FnMut(&mut App),
1565    {
1566        let (subscription, activate) = self.system_wake_observers.insert(
1567            (),
1568            Box::new(move |cx| {
1569                callback(cx);
1570                true
1571            }),
1572        );
1573        activate();
1574        subscription
1575    }
1576
1577    /// Returns the appearance of the application's windows.
1578    pub fn window_appearance(&self) -> WindowAppearance {
1579        self.platform.window_appearance()
1580    }
1581
1582    /// Overrides the appearance (light/dark) applied to the app's windows, independent of
1583    /// the OS-wide setting. Pass `None` to clear the override and follow the system again.
1584    /// The current value is reported by [`App::window_appearance`].
1585    ///
1586    /// On macOS this sets the underlying `NSApplication.appearance`, which controls the
1587    /// native window chrome (the window border and titlebar) of every window. Use this
1588    /// when the app uses a dark theme while the system is in light mode (or vice versa)
1589    /// so the window edges render to match the theme. While an appearance is forced,
1590    /// windows stop tracking system light/dark changes; pass `None` to resume following
1591    /// the system. On other platforms this is a no-op.
1592    pub fn set_window_appearance(&self, appearance: Option<WindowAppearance>) {
1593        self.platform.set_window_appearance(appearance);
1594    }
1595
1596    /// Returns the window button layout configuration when supported.
1597    pub fn button_layout(&self) -> Option<WindowButtonLayout> {
1598        self.platform.button_layout()
1599    }
1600
1601    /// Reads data from the platform clipboard.
1602    pub fn read_from_clipboard(&self) -> Option<ClipboardItem> {
1603        self.platform.read_from_clipboard()
1604    }
1605
1606    /// Reads data from the platform clipboard, resolving once the contents
1607    /// are available.
1608    ///
1609    /// Prefer this over [`App::read_from_clipboard`] in code that can await:
1610    /// on platforms where clipboard access is asynchronous and
1611    /// permission-gated (e.g. web), the synchronous read always returns
1612    /// `None` while this method performs a real read.
1613    pub fn read_from_clipboard_async(
1614        &self,
1615    ) -> Task<Result<Option<ClipboardItem>, ClipboardReadError>> {
1616        self.platform.read_from_clipboard_async()
1617    }
1618
1619    /// Sets the text rendering mode for the application.
1620    pub fn set_text_rendering_mode(&mut self, mode: TextRenderingMode) {
1621        self.text_rendering_mode.set(mode);
1622    }
1623
1624    /// Returns the current text rendering mode for the application.
1625    pub fn text_rendering_mode(&self) -> TextRenderingMode {
1626        self.text_rendering_mode.get()
1627    }
1628
1629    /// Writes data to the platform clipboard.
1630    pub fn write_to_clipboard(&self, item: ClipboardItem) {
1631        self.platform.write_to_clipboard(item)
1632    }
1633
1634    /// Reads data from the primary selection buffer.
1635    /// Only available on Linux.
1636    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
1637    pub fn read_from_primary(&self) -> Option<ClipboardItem> {
1638        self.platform.read_from_primary()
1639    }
1640
1641    /// Writes data to the primary selection buffer.
1642    /// Only available on Linux.
1643    #[cfg(any(target_os = "linux", target_os = "freebsd"))]
1644    pub fn write_to_primary(&self, item: ClipboardItem) {
1645        self.platform.write_to_primary(item)
1646    }
1647
1648    /// Reads data from macOS's "Find" pasteboard.
1649    ///
1650    /// Used to share the current search string between apps.
1651    ///
1652    /// https://developer.apple.com/documentation/appkit/nspasteboard/name-swift.struct/find
1653    #[cfg(target_os = "macos")]
1654    pub fn read_from_find_pasteboard(&self) -> Option<ClipboardItem> {
1655        self.platform.read_from_find_pasteboard()
1656    }
1657
1658    /// Writes data to macOS's "Find" pasteboard.
1659    ///
1660    /// Used to share the current search string between apps.
1661    ///
1662    /// https://developer.apple.com/documentation/appkit/nspasteboard/name-swift.struct/find
1663    #[cfg(target_os = "macos")]
1664    pub fn write_to_find_pasteboard(&self, item: ClipboardItem) {
1665        self.platform.write_to_find_pasteboard(item)
1666    }
1667
1668    /// Writes credentials to the platform keychain.
1669    pub fn write_credentials(
1670        &self,
1671        url: &str,
1672        username: &str,
1673        password: &[u8],
1674    ) -> Task<Result<()>> {
1675        self.platform.write_credentials(url, username, password)
1676    }
1677
1678    /// Reads credentials from the platform keychain.
1679    pub fn read_credentials(&self, url: &str) -> Task<Result<Option<(String, Vec<u8>)>>> {
1680        self.platform.read_credentials(url)
1681    }
1682
1683    /// Deletes credentials from the platform keychain.
1684    pub fn delete_credentials(&self, url: &str) -> Task<Result<()>> {
1685        self.platform.delete_credentials(url)
1686    }
1687
1688    /// Directs the platform's default browser to open the given URL.
1689    pub fn open_url(&self, url: &str) {
1690        self.platform.open_url(url);
1691    }
1692
1693    /// Registers the given URL scheme (e.g. `zed` for `zed://` urls) to be
1694    /// opened by the current app.
1695    ///
1696    /// On some platforms (e.g. macOS) you may be able to register URL schemes
1697    /// as part of app distribution, but this method exists to let you register
1698    /// schemes at runtime.
1699    pub fn register_url_scheme(&self, scheme: &str) -> Task<Result<()>> {
1700        self.platform.register_url_scheme(scheme)
1701    }
1702
1703    /// Sets the application's process-wide identity and user-visible name.
1704    ///
1705    /// The identifier is used for platform identity mechanisms such as the
1706    /// Windows AppUserModelID. The name is used wherever the operating system
1707    /// presents the application to the user. Call this once, early in startup,
1708    /// before opening windows or posting notifications.
1709    pub fn set_app_identity(&self, identifier: &str, name: &str) {
1710        self.platform.set_app_identity(identifier, name);
1711    }
1712
1713    /// Posts a notification to the operating system's notification center.
1714    ///
1715    /// Posting a notification whose [`SystemNotification::tag`] matches an
1716    /// earlier one replaces that notification where the platform supports it.
1717    /// No-op on platforms without notification support, or when delivery is
1718    /// unavailable (e.g. authorization was denied).
1719    pub fn show_system_notification(&self, notification: SystemNotification) {
1720        self.platform.show_system_notification(notification);
1721    }
1722
1723    /// Removes the delivered or pending notification with this tag.
1724    ///
1725    /// Best-effort: some platforms cannot retract a notification once shown,
1726    /// in which case it ages out of the notification center on its own.
1727    pub fn dismiss_system_notification(&self, tag: &str) {
1728        self.platform.dismiss_system_notification(tag);
1729    }
1730
1731    /// Registers the handler invoked when the user activates a system
1732    /// notification, either by clicking its body or one of its action
1733    /// buttons. Subsequent registrations replace the handler.
1734    pub fn on_system_notification_response<F>(&self, mut callback: F)
1735    where
1736        F: 'static + FnMut(SystemNotificationResponse, &mut App),
1737    {
1738        let this = self.this.clone();
1739        self.platform
1740            .on_system_notification_response(Box::new(move |response| {
1741                if let Some(app) = this.upgrade() {
1742                    callback(response, &mut app.borrow_mut());
1743                }
1744            }));
1745    }
1746
1747    /// Returns the full pathname of the current app bundle.
1748    ///
1749    /// Returns an error if the app is not being run from a bundle.
1750    pub fn app_path(&self) -> Result<PathBuf> {
1751        self.platform.app_path()
1752    }
1753
1754    /// On Linux, returns the name of the compositor in use.
1755    ///
1756    /// Returns an empty string on other platforms.
1757    pub fn compositor_name(&self) -> &'static str {
1758        self.platform.compositor_name()
1759    }
1760
1761    /// Returns the file URL of the executable with the specified name in the application bundle
1762    pub fn path_for_auxiliary_executable(&self, name: &str) -> Result<PathBuf> {
1763        self.platform.path_for_auxiliary_executable(name)
1764    }
1765
1766    /// Displays a platform modal for selecting paths.
1767    ///
1768    /// When one or more paths are selected, they'll be relayed asynchronously via the returned oneshot channel.
1769    /// If cancelled, a `None` will be relayed instead.
1770    /// May return an error on Linux if the file picker couldn't be opened.
1771    pub fn prompt_for_paths(
1772        &self,
1773        options: PathPromptOptions,
1774    ) -> oneshot::Receiver<Result<Option<Vec<PathBuf>>>> {
1775        self.platform.prompt_for_paths(options)
1776    }
1777
1778    /// Displays a platform modal for selecting a new path where a file can be saved.
1779    ///
1780    /// The provided directory will be used to set the initial location.
1781    /// When a path is selected, it is relayed asynchronously via the returned oneshot channel.
1782    /// If cancelled, a `None` will be relayed instead.
1783    /// May return an error on Linux if the file picker couldn't be opened.
1784    pub fn prompt_for_new_path(
1785        &self,
1786        directory: &Path,
1787        suggested_name: Option<&str>,
1788    ) -> oneshot::Receiver<Result<Option<PathBuf>>> {
1789        self.platform.prompt_for_new_path(directory, suggested_name)
1790    }
1791
1792    /// Reveals the specified path at the platform level, such as in Finder on macOS.
1793    pub fn reveal_path(&self, path: &Path) {
1794        self.platform.reveal_path(path)
1795    }
1796
1797    /// Opens the specified path with the system's default application.
1798    pub fn open_with_system(&self, path: &Path) {
1799        self.platform.open_with_system(path)
1800    }
1801
1802    /// Returns whether the user has configured scrollbars to auto-hide at the platform level.
1803    pub fn should_auto_hide_scrollbars(&self) -> bool {
1804        self.platform.should_auto_hide_scrollbars()
1805    }
1806
1807    /// Restarts the application.
1808    pub fn restart(&mut self) {
1809        self.restart_observers
1810            .clone()
1811            .retain(&(), |observer| observer(self));
1812        self.platform.restart(
1813            self.restart_path.take(),
1814            std::mem::take(&mut self.restart_arguments),
1815        )
1816    }
1817
1818    /// Sets the path to use when restarting the application.
1819    pub fn set_restart_path(&mut self, path: PathBuf) {
1820        self.restart_path = Some(path);
1821    }
1822
1823    /// Returns the HTTP client for the application.
1824    pub fn http_client(&self) -> Arc<dyn HttpClient> {
1825        self.http_client.clone()
1826    }
1827
1828    /// Sets the HTTP client for the application.
1829    pub fn set_http_client(&mut self, new_client: Arc<dyn HttpClient>) {
1830        self.http_client = new_client;
1831    }
1832
1833    /// Configures when the application should automatically quit.
1834    /// By default, [`QuitMode::Default`] is used.
1835    pub fn set_quit_mode(&mut self, mode: QuitMode) {
1836        self.quit_mode = mode;
1837    }
1838
1839    /// Sets whether the application participates in the system's foreground UI.
1840    ///
1841    /// Only has an effect on macOS, where [`Self::request_windowing`] normally sets it. Use this
1842    /// for an accessory app that shows windows, such as a menu bar utility. It overrides the
1843    /// policy until the next [`Self::request_windowing`], and the app counts as headless while
1844    /// `Accessory`. After switching to [`ActivationPolicy::Regular`], activate the app yourself
1845    /// with [`Self::activate`]; otherwise its menu bar may not appear until the app is
1846    /// reactivated.
1847    pub fn set_activation_policy(&mut self, policy: ActivationPolicy) {
1848        self.platform.set_activation_policy(policy);
1849    }
1850
1851    /// Returns the SVG renderer used by the application.
1852    pub fn svg_renderer(&self) -> SvgRenderer {
1853        self.svg_renderer.clone()
1854    }
1855
1856    pub(crate) fn push_effect(&mut self, effect: Effect) {
1857        match &effect {
1858            Effect::Notify { emitter } => {
1859                if !self.pending_notifications.insert(*emitter) {
1860                    return;
1861                }
1862            }
1863            Effect::NotifyGlobalObservers { global_type } => {
1864                if !self.pending_global_notifications.insert(*global_type) {
1865                    return;
1866                }
1867            }
1868            _ => {}
1869        };
1870
1871        self.pending_effects.push_back(effect);
1872    }
1873
1874    /// Called at the end of [`App::update`] to complete any side effects
1875    /// such as notifying observers, emitting events, etc. Effects can themselves
1876    /// cause effects, so we continue looping until all effects are processed.
1877    fn flush_effects(&mut self) {
1878        loop {
1879            self.release_dropped_entities();
1880            self.release_dropped_focus_handles();
1881            if let Some(effect) = self.pending_effects.pop_front() {
1882                match effect {
1883                    Effect::Notify { emitter } => {
1884                        self.apply_notify_effect(emitter);
1885                    }
1886
1887                    Effect::Emit {
1888                        emitter,
1889                        event_type,
1890                        event,
1891                    } => self.apply_emit_effect(emitter, event_type, &*event),
1892
1893                    Effect::RefreshWindows => {
1894                        self.apply_refresh_effect();
1895                    }
1896
1897                    Effect::NotifyGlobalObservers { global_type } => {
1898                        self.apply_notify_global_observers_effect(global_type);
1899                    }
1900
1901                    Effect::Defer { callback } => {
1902                        self.apply_defer_effect(callback);
1903                    }
1904                    Effect::EntityCreated {
1905                        entity,
1906                        tid,
1907                        window,
1908                    } => {
1909                        self.apply_entity_created_effect(entity, tid, window);
1910                    }
1911                }
1912            } else {
1913                #[cfg(any(test, feature = "test-support"))]
1914                if matches!(self.mode, GpuiMode::Test { .. }) {
1915                    for window in self
1916                        .windows
1917                        .values()
1918                        .filter_map(|window| {
1919                            let window = window.as_deref()?;
1920                            window.invalidator.is_dirty().then_some(window.handle)
1921                        })
1922                        .collect::<Vec<_>>()
1923                    {
1924                        self.update_window(window, |_, window, cx| window.draw(cx).clear(cx))
1925                            .unwrap();
1926                    }
1927                }
1928
1929                if self.pending_effects.is_empty() {
1930                    for window in self.windows.values().filter_map(|window| window.as_deref()) {
1931                        if window.invalidator.is_dirty()
1932                            || window.needs_present.get()
1933                            || !window.next_frame_callbacks.borrow().is_empty()
1934                        {
1935                            window.platform_window.schedule_frame();
1936                        }
1937                    }
1938
1939                    self.event_arena.clear();
1940                    break;
1941                }
1942            }
1943        }
1944    }
1945
1946    /// Repeatedly called during `flush_effects` to release any entities whose
1947    /// reference count has become zero. We invoke any release observers before dropping
1948    /// each entity.
1949    fn release_dropped_entities(&mut self) {
1950        loop {
1951            let dropped = self.entities.take_dropped();
1952            if dropped.is_empty() {
1953                break;
1954            }
1955
1956            for (entity_id, mut entity) in dropped {
1957                self.observers.remove(&entity_id);
1958                self.event_listeners.remove(&entity_id);
1959                self.window_invalidators_by_entity.remove(&entity_id);
1960                self.current_window_by_entity.remove(&entity_id);
1961                for release_callback in self.release_listeners.remove(&entity_id) {
1962                    release_callback(entity.as_mut(), self);
1963                }
1964            }
1965        }
1966    }
1967
1968    /// Repeatedly called during `flush_effects` to handle a focused handle being dropped.
1969    fn release_dropped_focus_handles(&mut self) {
1970        self.focus_handles
1971            .clone()
1972            .write()
1973            .retain(|handle_id, focus| {
1974                if focus.ref_count.load(SeqCst) == 0 {
1975                    for window_handle in self.windows() {
1976                        window_handle
1977                            .update(self, |_, window, cx| {
1978                                if window.focus == Some(handle_id) {
1979                                    window.blur(cx);
1980                                }
1981                            })
1982                            .unwrap();
1983                    }
1984                    false
1985                } else {
1986                    true
1987                }
1988            });
1989    }
1990
1991    fn apply_notify_effect(&mut self, emitter: EntityId) {
1992        self.pending_notifications.remove(&emitter);
1993
1994        self.observers
1995            .clone()
1996            .retain(&emitter, |handler| handler(self));
1997    }
1998
1999    fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: &dyn Any) {
2000        self.event_listeners
2001            .clone()
2002            .retain(&emitter, |(stored_type, handler)| {
2003                if *stored_type == event_type {
2004                    handler(event, self)
2005                } else {
2006                    true
2007                }
2008            });
2009    }
2010
2011    fn apply_refresh_effect(&mut self) {
2012        for window in self.windows.values_mut() {
2013            if let Some(window) = window.as_deref_mut() {
2014                window.refreshing = true;
2015                window.invalidator.set_dirty(true);
2016            }
2017        }
2018    }
2019
2020    fn apply_notify_global_observers_effect(&mut self, type_id: TypeId) {
2021        self.pending_global_notifications.remove(&type_id);
2022        self.global_observers
2023            .clone()
2024            .retain(&type_id, |observer| observer(self));
2025    }
2026
2027    fn apply_defer_effect(&mut self, callback: Box<dyn FnOnce(&mut Self) + 'static>) {
2028        callback(self);
2029    }
2030
2031    fn apply_entity_created_effect(
2032        &mut self,
2033        entity: AnyEntity,
2034        tid: TypeId,
2035        window: Option<WindowId>,
2036    ) {
2037        // Seed the entity's current window from its creation context so
2038        // `with_window` resolves correctly before the entity has ever been
2039        // rendered.
2040        if let Some(id) = window {
2041            self.current_window_by_entity.insert(entity.entity_id(), id);
2042        }
2043
2044        self.new_entity_observers.clone().retain(&tid, |observer| {
2045            if let Some(id) = window {
2046                self.update_window_id(id, {
2047                    let entity = entity.clone();
2048                    |_, window, cx| (observer)(entity, &mut Some(window), cx)
2049                })
2050                .expect("All windows should be off the stack when flushing effects");
2051            } else {
2052                (observer)(entity.clone(), &mut None, self)
2053            }
2054            true
2055        });
2056    }
2057
2058    /// Run `f` against the entity's *current* window — the most recently
2059    /// rendered window that referenced the entity, or its creation window if
2060    /// it has yet to be rendered. Returns `None` if the entity has no
2061    /// current window, or if that window has been closed, or if it is
2062    /// already on the update stack.
2063    #[inline(always)]
2064    pub fn with_window<R>(
2065        &mut self,
2066        entity_id: EntityId,
2067        f: impl FnOnce(&mut Window, &mut App) -> R,
2068    ) -> Option<R> {
2069        let window_id = *self.current_window_by_entity.get(&entity_id)?;
2070        self.update_window_id(window_id, |_, window, cx| f(window, cx))
2071            .ok()
2072    }
2073
2074    fn ensure_window(&mut self, entity_id: EntityId, window: WindowId) {
2075        self.current_window_by_entity
2076            .entry(entity_id)
2077            .or_insert(window);
2078    }
2079
2080    #[inline(always)]
2081    pub(crate) fn update_window_id<T, F>(&mut self, id: WindowId, update: F) -> Result<T>
2082    where
2083        F: FnOnce(AnyView, &mut Window, &mut App) -> T,
2084    {
2085        let mut update = Some(update);
2086        let mut result = None;
2087        self.update_window_erased(id, &mut |arguments| {
2088            if let Some((root_view, window, cx)) = arguments {
2089                result = Some(update.take().unwrap()(root_view, window, cx));
2090            } else {
2091                drop(update.take());
2092                drop(result.take());
2093            }
2094        });
2095        result.context("window not found")
2096    }
2097
2098    /// Creates an `AsyncApp`, which can be cloned and has a static lifetime
2099    /// so it can be held across `await` points.
2100    pub fn to_async(&self) -> AsyncApp {
2101        AsyncApp {
2102            app: self.this.clone(),
2103            background_executor: self.background_executor.clone(),
2104            foreground_executor: self.foreground_executor.clone(),
2105        }
2106    }
2107
2108    /// Obtains a reference to the executor, which can be used to spawn futures.
2109    pub fn background_executor(&self) -> &BackgroundExecutor {
2110        &self.background_executor
2111    }
2112
2113    /// Whether this app runs on the deterministic test scheduler. See
2114    /// [`BackgroundExecutor::is_test`].
2115    pub fn is_test(&self) -> bool {
2116        self.background_executor.is_test()
2117    }
2118
2119    /// Obtains a reference to the executor, which can be used to spawn futures.
2120    pub fn foreground_executor(&self) -> &ForegroundExecutor {
2121        if self.quitting {
2122            panic!("Can't spawn on main thread after on_app_quit")
2123        };
2124        &self.foreground_executor
2125    }
2126
2127    /// Returns the foreground work journal for this app's foreground thread.
2128    /// Apps constructed on the same thread share the stream.
2129    #[cfg(feature = "profiler")]
2130    pub fn foreground_journal(&self) -> crate::profiler::journal::ForegroundJournal {
2131        self.foreground_journal.clone()
2132    }
2133
2134    /// Starts detecting foreground hangs on a dedicated thread.
2135    ///
2136    /// Nothing is spawned unless the app calls this. The thread polls a
2137    /// detector over this app's foreground journal every `config.interval`
2138    /// and passes each poll's incidents, including empty polls, to `on_poll`
2139    /// on that thread. When the app quits, a final poll with
2140    /// [`HangMonitorPollReason::Flush`] runs during shutdown, concurrently
2141    /// with quit handlers and within [`SHUTDOWN_TIMEOUT`], so `on_poll` can
2142    /// deliver batched results.
2143    ///
2144    /// # Errors
2145    ///
2146    /// Fails if the monitor was already started or its thread can't be
2147    /// spawned.
2148    ///
2149    /// [`HangMonitorPollReason::Flush`]: crate::profiler::hang::HangMonitorPollReason::Flush
2150    #[cfg(all(feature = "profiler", not(target_family = "wasm")))]
2151    pub fn start_hang_monitor(
2152        &mut self,
2153        config: crate::profiler::hang::HangMonitorConfig,
2154        on_poll: impl FnMut(crate::profiler::hang::HangMonitorPoll) + Send + 'static,
2155    ) -> Result<(), crate::profiler::hang::HangMonitorError> {
2156        use crate::profiler::hang::{HangDetector, HangMonitor, HangMonitorError};
2157
2158        if self.hang_monitor.is_some() {
2159            debug_assert!(false, "the hang monitor was started twice");
2160            return Err(HangMonitorError::AlreadyStarted);
2161        }
2162        let detector = HangDetector::new(
2163            self.foreground_journal(),
2164            config.threshold,
2165            config.frame_budget,
2166        );
2167        let monitor = HangMonitor::spawn(detector, config.interval, on_poll)
2168            .map_err(HangMonitorError::Spawn)?;
2169        self.hang_monitor = Some(monitor);
2170        Ok(())
2171    }
2172
2173    /// Spawns the future returned by the given function on the main thread. The closure will be invoked
2174    /// with [AsyncApp], which allows the application state to be accessed across await points.
2175    #[track_caller]
2176    #[inline(always)]
2177    pub fn spawn<AsyncFn, R>(&self, f: AsyncFn) -> Task<R>
2178    where
2179        AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static,
2180        R: 'static,
2181    {
2182        let mut cx = self.prepare_spawn();
2183
2184        self.foreground_executor
2185            .spawn(async move { f(&mut cx).await }.boxed_local())
2186    }
2187
2188    /// Spawns the future returned by the given function on the main thread with
2189    /// the given priority. The closure will be invoked with [AsyncApp], which
2190    /// allows the application state to be accessed across await points.
2191    pub fn spawn_with_priority<AsyncFn, R>(&self, priority: Priority, f: AsyncFn) -> Task<R>
2192    where
2193        AsyncFn: AsyncFnOnce(&mut AsyncApp) -> R + 'static,
2194        R: 'static,
2195    {
2196        if self.quitting {
2197            debug_panic!("Can't spawn on main thread after on_app_quit")
2198        };
2199
2200        let mut cx = self.to_async();
2201
2202        self.foreground_executor
2203            .spawn_with_priority(priority, async move { f(&mut cx).await }.boxed_local())
2204    }
2205
2206    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
2207    /// that are currently on the stack to be returned to the app.
2208    pub fn defer(&mut self, f: impl FnOnce(&mut App) + 'static) {
2209        self.push_effect(Effect::Defer {
2210            callback: Box::new(f),
2211        });
2212    }
2213
2214    /// Accessor for the application's asset source, which is provided when constructing the `App`.
2215    pub fn asset_source(&self) -> &Arc<dyn AssetSource> {
2216        &self.asset_source
2217    }
2218
2219    /// Accessor for the text system.
2220    pub fn text_system(&self) -> &Arc<TextSystem> {
2221        &self.text_system
2222    }
2223
2224    /// Invokes a callback with grapheme clusters that exhausted font fallback.
2225    ///
2226    /// Registering a callback replaces the previous callback and enables missing-glyph
2227    /// detection. The callback runs on the foreground executor after shaping has
2228    /// released its internal locks. Dropping its subscription disables detection until
2229    /// another callback is registered.
2230    ///
2231    /// Reports are queued without blocking shaping, then deduplicated before delivery.
2232    /// The bounded queue can drop reports on overflow. Dropped reports may be reported
2233    /// again when the text is reshaped; no retry is scheduled automatically.
2234    pub fn on_missing_glyphs(
2235        &self,
2236        callback: impl FnMut(&[MissingGlyph], &mut App) + 'static,
2237    ) -> Subscription {
2238        let registration = self.missing_glyph_callback.replace(Box::new(callback));
2239
2240        if let Some(mut receiver) = self.text_system.take_missing_glyph_receiver() {
2241            let callback = self.missing_glyph_callback.clone();
2242            self.spawn(async move |cx| {
2243                while let Ok(missing_glyphs) = receiver.recv().await {
2244                    cx.update(|cx| callback.invoke(&missing_glyphs, cx));
2245                }
2246            })
2247            .detach();
2248        }
2249        self.text_system.enable_missing_glyph_reporting();
2250
2251        let callback = self.missing_glyph_callback.clone();
2252        let text_system = self.text_system.clone();
2253        Subscription::new(move || {
2254            if callback.remove(&registration) {
2255                text_system.disable_missing_glyph_reporting();
2256            }
2257        })
2258    }
2259
2260    /// Check whether a global of the given type has been assigned.
2261    pub fn has_global<G: Global>(&self) -> bool {
2262        self.globals_by_type.contains_key(&TypeId::of::<G>())
2263    }
2264
2265    /// Access the global of the given type. Panics if a global for that type has not been assigned.
2266    #[track_caller]
2267    pub fn global<G: Global>(&self) -> &G {
2268        self.globals_by_type
2269            .get(&TypeId::of::<G>())
2270            .map(|any_state| any_state.downcast_ref::<G>().unwrap())
2271            .unwrap_or_else(|| panic!("no state of type {} exists", type_name::<G>()))
2272    }
2273
2274    /// Access the global of the given type if a value has been assigned.
2275    pub fn try_global<G: Global>(&self) -> Option<&G> {
2276        self.globals_by_type
2277            .get(&TypeId::of::<G>())
2278            .map(|any_state| any_state.downcast_ref::<G>().unwrap())
2279    }
2280
2281    /// Access the global of the given type mutably. Panics if a global for that type has not been assigned.
2282    #[track_caller]
2283    pub fn global_mut<G: Global>(&mut self) -> &mut G {
2284        let global_type = TypeId::of::<G>();
2285        self.push_effect(Effect::NotifyGlobalObservers { global_type });
2286        self.globals_by_type
2287            .get_mut(&global_type)
2288            .and_then(|any_state| any_state.downcast_mut::<G>())
2289            .unwrap_or_else(|| panic!("no state of type {} exists", type_name::<G>()))
2290    }
2291
2292    /// Access the global of the given type mutably. A default value is assigned if a global of this type has not
2293    /// yet been assigned.
2294    pub fn default_global<G: Global + Default>(&mut self) -> &mut G {
2295        let global_type = TypeId::of::<G>();
2296        self.push_effect(Effect::NotifyGlobalObservers { global_type });
2297        self.globals_by_type
2298            .entry(global_type)
2299            .or_insert_with(|| Box::<G>::default())
2300            .downcast_mut::<G>()
2301            .unwrap()
2302    }
2303
2304    /// Sets the value of the global of the given type.
2305    pub fn set_global<G: Global>(&mut self, global: G) {
2306        let global_type = TypeId::of::<G>();
2307        self.push_effect(Effect::NotifyGlobalObservers { global_type });
2308        self.globals_by_type.insert(global_type, Box::new(global));
2309    }
2310
2311    /// Clear all stored globals. Does not notify global observers.
2312    #[cfg(any(test, feature = "test-support"))]
2313    pub fn clear_globals(&mut self) {
2314        self.globals_by_type.drain();
2315    }
2316
2317    /// Remove the global of the given type from the app context. Does not notify global observers.
2318    pub fn remove_global<G: Global>(&mut self) -> G {
2319        let global_type = TypeId::of::<G>();
2320        self.push_effect(Effect::NotifyGlobalObservers { global_type });
2321        *self
2322            .globals_by_type
2323            .remove(&global_type)
2324            .unwrap_or_else(|| panic!("no global added for {}", type_name::<G>()))
2325            .downcast()
2326            .unwrap()
2327    }
2328
2329    /// Register a callback to be invoked when a global of the given type is updated.
2330    pub fn observe_global<G: Global>(
2331        &mut self,
2332        mut f: impl FnMut(&mut Self) + 'static,
2333    ) -> Subscription {
2334        let (subscription, activate) = self.global_observers.insert(
2335            TypeId::of::<G>(),
2336            Box::new(move |cx| {
2337                f(cx);
2338                true
2339            }),
2340        );
2341        self.defer(move |_| activate());
2342        subscription
2343    }
2344
2345    /// Move the global of the given type to the stack.
2346    #[track_caller]
2347    pub(crate) fn lease_global<G: Global>(&mut self) -> GlobalLease<G> {
2348        GlobalLease::new(
2349            self.globals_by_type
2350                .remove(&TypeId::of::<G>())
2351                .with_context(|| format!("no global registered of type {}", type_name::<G>()))
2352                .unwrap(),
2353        )
2354    }
2355
2356    /// Restore the global of the given type after it is moved to the stack.
2357    pub(crate) fn end_global_lease<G: Global>(&mut self, lease: GlobalLease<G>) {
2358        let global_type = TypeId::of::<G>();
2359
2360        self.push_effect(Effect::NotifyGlobalObservers { global_type });
2361        self.globals_by_type.insert(global_type, lease.global);
2362    }
2363
2364    pub(crate) fn new_entity_observer(
2365        &self,
2366        key: TypeId,
2367        value: NewEntityListener,
2368    ) -> Subscription {
2369        let (subscription, activate) = self.new_entity_observers.insert(key, value);
2370        activate();
2371        subscription
2372    }
2373
2374    /// Arrange for the given function to be invoked whenever a view of the specified type is created.
2375    /// The function will be passed a mutable reference to the view along with an appropriate context.
2376    pub fn observe_new<T: 'static>(
2377        &self,
2378        on_new: impl 'static + Fn(&mut T, Option<&mut Window>, &mut Context<T>),
2379    ) -> Subscription {
2380        self.new_entity_observer(
2381            TypeId::of::<T>(),
2382            Box::new(
2383                move |any_entity: AnyEntity, window: &mut Option<&mut Window>, cx: &mut App| {
2384                    any_entity
2385                        .downcast::<T>()
2386                        .unwrap()
2387                        .update(cx, |entity_state, cx| {
2388                            on_new(entity_state, window.as_deref_mut(), cx)
2389                        })
2390                },
2391            ),
2392        )
2393    }
2394
2395    /// Observe the release of a entity. The callback is invoked after the entity
2396    /// has no more strong references but before it has been dropped.
2397    pub fn observe_release<T>(
2398        &self,
2399        handle: &Entity<T>,
2400        on_release: impl FnOnce(&mut T, &mut App) + 'static,
2401    ) -> Subscription
2402    where
2403        T: 'static,
2404    {
2405        let (subscription, activate) = self.release_listeners.insert(
2406            handle.entity_id(),
2407            Box::new(move |entity, cx| {
2408                let entity = entity.downcast_mut().expect("invalid entity type");
2409                on_release(entity, cx)
2410            }),
2411        );
2412        activate();
2413        subscription
2414    }
2415
2416    /// Observe the release of a entity. The callback is invoked after the entity
2417    /// has no more strong references but before it has been dropped.
2418    pub fn observe_release_in<T>(
2419        &self,
2420        handle: &Entity<T>,
2421        window: &Window,
2422        on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
2423    ) -> Subscription
2424    where
2425        T: 'static,
2426    {
2427        let window_handle = window.handle;
2428        self.observe_release(handle, move |entity, cx| {
2429            let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
2430        })
2431    }
2432
2433    /// Register a callback to be invoked after a keystroke is resolved in any window,
2434    /// including the action that handled it, if any. Keystrokes consumed by an
2435    /// interceptor or raw keyboard event handler are not observed.
2436    /// Standalone modifiers are observed on release.
2437    pub fn observe_keystrokes(
2438        &mut self,
2439        mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static,
2440    ) -> Subscription {
2441        fn inner(
2442            keystroke_observers: &SubscriberSet<(), KeystrokeObserver>,
2443            handler: KeystrokeObserver,
2444        ) -> Subscription {
2445            let (subscription, activate) = keystroke_observers.insert((), handler);
2446            activate();
2447            subscription
2448        }
2449
2450        inner(
2451            &self.keystroke_observers,
2452            Box::new(move |event, window, cx| {
2453                f(event, window, cx);
2454                true
2455            }),
2456        )
2457    }
2458
2459    /// Register a callback to be invoked when a keystroke is received by the application
2460    /// in any window. Note that this fires _before_ all other action and event mechanisms have resolved
2461    /// unlike [`App::observe_keystrokes`] which fires after. This means that `cx.stop_propagation` calls
2462    /// within interceptors will prevent action dispatch
2463    pub fn intercept_keystrokes(
2464        &mut self,
2465        mut f: impl FnMut(&KeystrokeEvent, &mut Window, &mut App) + 'static,
2466    ) -> Subscription {
2467        fn inner(
2468            keystroke_interceptors: &SubscriberSet<(), KeystrokeObserver>,
2469            handler: KeystrokeObserver,
2470        ) -> Subscription {
2471            let (subscription, activate) = keystroke_interceptors.insert((), handler);
2472            activate();
2473            subscription
2474        }
2475
2476        inner(
2477            &self.keystroke_interceptors,
2478            Box::new(move |event, window, cx| {
2479                f(event, window, cx);
2480                true
2481            }),
2482        )
2483    }
2484
2485    /// Register key bindings.
2486    pub fn bind_keys(&mut self, bindings: impl IntoIterator<Item = KeyBinding>) {
2487        self.keymap.borrow_mut().add_bindings(bindings);
2488        self.pending_effects.push_back(Effect::RefreshWindows);
2489    }
2490
2491    /// Clear all key bindings in the app.
2492    pub fn clear_key_bindings(&mut self) {
2493        self.keymap.borrow_mut().clear();
2494        self.pending_effects.push_back(Effect::RefreshWindows);
2495    }
2496
2497    /// Get all key bindings in the app.
2498    pub fn key_bindings(&self) -> Rc<RefCell<Keymap>> {
2499        self.keymap.clone()
2500    }
2501
2502    /// Register a global handler for actions invoked via the keyboard. These handlers are run at
2503    /// the end of the bubble phase for actions, and so will only be invoked if there are no other
2504    /// handlers or if they called `cx.propagate()`.
2505    pub fn on_action<A: Action>(
2506        &mut self,
2507        listener: impl Fn(&A, &mut Self) + 'static,
2508    ) -> &mut Self {
2509        self.global_action_listeners
2510            .entry(TypeId::of::<A>())
2511            .or_default()
2512            .push(Rc::new(move |action, phase, cx| {
2513                if phase == DispatchPhase::Bubble {
2514                    let action = action.downcast_ref().unwrap();
2515                    listener(action, cx)
2516                }
2517            }));
2518        self
2519    }
2520
2521    /// Event handlers propagate events by default. Call this method to stop dispatching to
2522    /// event handlers with a lower z-index (mouse) or higher in the tree (keyboard). This is
2523    /// the opposite of [`Self::propagate`]. It's also possible to cancel a call to [`Self::propagate`] by
2524    /// calling this method before effects are flushed.
2525    pub fn stop_propagation(&mut self) {
2526        self.propagate_event = false;
2527    }
2528
2529    /// Action handlers stop propagation by default during the bubble phase of action dispatch
2530    /// dispatching to action handlers higher in the element tree. This is the opposite of
2531    /// [`Self::stop_propagation`]. It's also possible to cancel a call to [`Self::stop_propagation`] by calling
2532    /// this method before effects are flushed.
2533    pub fn propagate(&mut self) {
2534        self.propagate_event = true;
2535    }
2536
2537    /// Build an action from some arbitrary data, typically a keymap entry.
2538    pub fn build_action(
2539        &self,
2540        name: &str,
2541        data: Option<serde_json::Value>,
2542    ) -> std::result::Result<Box<dyn Action>, ActionBuildError> {
2543        self.actions.build_action(name, data)
2544    }
2545
2546    /// Get all action names that have been registered. Note that registration only allows for
2547    /// actions to be built dynamically, and is unrelated to binding actions in the element tree.
2548    pub fn all_action_names(&self) -> &[&'static str] {
2549        self.actions.all_action_names()
2550    }
2551
2552    /// Returns key bindings that invoke the given action on the currently focused element, without
2553    /// checking context. Bindings are returned in the order they were added. For display, the last
2554    /// binding should take precedence.
2555    pub fn all_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
2556        RefCell::borrow(&self.keymap).all_bindings_for_input(input)
2557    }
2558
2559    /// Get all non-internal actions that have been registered, along with their schemas.
2560    pub fn action_schemas(
2561        &self,
2562        generator: &mut schemars::SchemaGenerator,
2563    ) -> Vec<(&'static str, Option<schemars::Schema>)> {
2564        self.actions.action_schemas(generator)
2565    }
2566
2567    /// Get the schema for a specific action by name.
2568    /// Returns `None` if the action is not found.
2569    /// Returns `Some(None)` if the action exists but has no schema.
2570    /// Returns `Some(Some(schema))` if the action exists and has a schema.
2571    pub fn action_schema_by_name(
2572        &self,
2573        name: &str,
2574        generator: &mut schemars::SchemaGenerator,
2575    ) -> Option<Option<schemars::Schema>> {
2576        self.actions.action_schema_by_name(name, generator)
2577    }
2578
2579    /// Get a map from a deprecated action name to the canonical name.
2580    pub fn deprecated_actions_to_preferred_actions(&self) -> &HashMap<&'static str, &'static str> {
2581        self.actions.deprecated_aliases()
2582    }
2583
2584    /// Get a map from an action name to the deprecation messages.
2585    pub fn action_deprecation_messages(&self) -> &HashMap<&'static str, &'static str> {
2586        self.actions.deprecation_messages()
2587    }
2588
2589    /// Get a map from an action name to the documentation.
2590    pub fn action_documentation(&self) -> &HashMap<&'static str, &'static str> {
2591        self.actions.documentation()
2592    }
2593
2594    /// Register a callback to be invoked when the application is about to quit.
2595    /// It is not possible to cancel the quit event at this point.
2596    pub fn on_app_quit<Fut>(
2597        &self,
2598        mut on_quit: impl FnMut(&mut App) -> Fut + 'static,
2599    ) -> Subscription
2600    where
2601        Fut: 'static + Future<Output = ()>,
2602    {
2603        let (subscription, activate) = self.quit_observers.insert(
2604            (),
2605            Box::new(move |cx| {
2606                let future = on_quit(cx);
2607                future.boxed_local()
2608            }),
2609        );
2610        activate();
2611        subscription
2612    }
2613
2614    /// Register a callback to be invoked when the application is about to restart.
2615    ///
2616    /// These callbacks are called before any `on_app_quit` callbacks.
2617    pub fn on_app_restart(&self, mut on_restart: impl 'static + FnMut(&mut App)) -> Subscription {
2618        let (subscription, activate) = self.restart_observers.insert(
2619            (),
2620            Box::new(move |cx| {
2621                on_restart(cx);
2622                true
2623            }),
2624        );
2625        activate();
2626        subscription
2627    }
2628
2629    /// Register a callback to be invoked when a window is closed
2630    /// The window is no longer accessible at the point this callback is invoked.
2631    pub fn on_window_closed(
2632        &self,
2633        mut on_closed: impl FnMut(&mut App, WindowId) + 'static,
2634    ) -> Subscription {
2635        let (subscription, activate) = self.window_closed_observers.insert((), Box::new(on_closed));
2636        activate();
2637        subscription
2638    }
2639
2640    pub(crate) fn clear_pending_keystrokes(&mut self) {
2641        for window in self.windows() {
2642            window
2643                .update(self, |_, window, cx| {
2644                    window.clear_pending_keystrokes(cx);
2645                })
2646                .ok();
2647        }
2648    }
2649
2650    /// Checks if the given action is bound in the current context, as defined by the app's current focus,
2651    /// the bindings in the element tree, and any global action listeners.
2652    pub fn is_action_available(&mut self, action: &dyn Action) -> bool {
2653        let mut action_available = false;
2654        if let Some(window) = self.active_window()
2655            && let Ok(window_action_available) =
2656                window.update(self, |_, window, cx| window.is_action_available(action, cx))
2657        {
2658            action_available = window_action_available;
2659        }
2660
2661        action_available
2662            || self
2663                .global_action_listeners
2664                .contains_key(&action.as_any().type_id())
2665    }
2666
2667    /// Sets the menu bar for this application. This will replace any existing menu bar.
2668    pub fn set_menus(&self, menus: impl IntoIterator<Item = Menu>) {
2669        let menus: Vec<Menu> = menus.into_iter().collect();
2670        self.platform.set_menus(menus, &self.keymap.borrow());
2671    }
2672
2673    /// Gets the menu bar for this application.
2674    pub fn get_menus(&self) -> Option<Vec<OwnedMenu>> {
2675        self.platform.get_menus()
2676    }
2677
2678    /// Sets the right click menu for the app icon in the dock
2679    pub fn set_dock_menu(&self, menus: Vec<MenuItem>) {
2680        self.platform.set_dock_menu(menus, &self.keymap.borrow())
2681    }
2682
2683    /// Performs the action associated with the given dock menu item, only used on Windows for now.
2684    pub fn perform_dock_menu_action(&self, action: usize) {
2685        self.platform.perform_dock_menu_action(action);
2686    }
2687
2688    /// Adds given path to the bottom of the list of recent paths for the application.
2689    /// The list is usually shown on the application icon's context menu in the dock,
2690    /// and allows to open the recent files via that context menu.
2691    /// If the path is already in the list, it will be moved to the bottom of the list.
2692    pub fn add_recent_document(&self, path: &Path) {
2693        self.platform.add_recent_document(path);
2694    }
2695
2696    /// Updates the jump list with the updated list of recent paths for the application, only used on Windows for now.
2697    /// Note that this also sets the dock menu on Windows.
2698    pub fn update_jump_list(
2699        &self,
2700        menus: Vec<MenuItem>,
2701        entries: Vec<SmallVec<[PathBuf; 2]>>,
2702    ) -> Task<Vec<SmallVec<[PathBuf; 2]>>> {
2703        self.platform.update_jump_list(menus, entries)
2704    }
2705
2706    /// Dispatch an action to the currently active window or global action handler
2707    /// See [`crate::Action`] for more information on how actions work
2708    pub fn dispatch_action(&mut self, action: &dyn Action) {
2709        if let Some(active_window) = self.active_window() {
2710            active_window
2711                .update(self, |_, window, cx| {
2712                    window.dispatch_action(action.boxed_clone(), cx)
2713                })
2714                .log_err();
2715        } else {
2716            self.dispatch_global_action(action);
2717        }
2718    }
2719
2720    fn dispatch_global_action(&mut self, action: &dyn Action) {
2721        self.propagate_event = true;
2722
2723        if let Some(mut global_listeners) = self
2724            .global_action_listeners
2725            .remove(&action.as_any().type_id())
2726        {
2727            for listener in &global_listeners {
2728                listener(action.as_any(), DispatchPhase::Capture, self);
2729                if !self.propagate_event {
2730                    break;
2731                }
2732            }
2733
2734            global_listeners.extend(
2735                self.global_action_listeners
2736                    .remove(&action.as_any().type_id())
2737                    .unwrap_or_default(),
2738            );
2739
2740            self.global_action_listeners
2741                .insert(action.as_any().type_id(), global_listeners);
2742        }
2743
2744        if self.propagate_event
2745            && let Some(mut global_listeners) = self
2746                .global_action_listeners
2747                .remove(&action.as_any().type_id())
2748        {
2749            for listener in global_listeners.iter().rev() {
2750                listener(action.as_any(), DispatchPhase::Bubble, self);
2751                if !self.propagate_event {
2752                    break;
2753                }
2754            }
2755
2756            global_listeners.extend(
2757                self.global_action_listeners
2758                    .remove(&action.as_any().type_id())
2759                    .unwrap_or_default(),
2760            );
2761
2762            self.global_action_listeners
2763                .insert(action.as_any().type_id(), global_listeners);
2764        }
2765    }
2766
2767    /// Is there currently something being dragged?
2768    pub fn has_active_drag(&self) -> bool {
2769        self.active_drag.is_some()
2770    }
2771
2772    /// Gets the cursor style of the currently active drag operation.
2773    pub fn active_drag_cursor_style(&self) -> Option<CursorStyle> {
2774        self.active_drag.as_ref().and_then(|drag| drag.cursor_style)
2775    }
2776
2777    /// Stops active drag and clears any related effects.
2778    pub fn stop_active_drag(&mut self, window: &mut Window) -> bool {
2779        if self.active_drag.is_some() {
2780            self.active_drag = None;
2781            if self.platform_owned_drag.as_ref().is_some_and(|drag| {
2782                drag.source_window == window.window_handle().window_id()
2783                    && matches!(&drag.state, PlatformOwnedDragState::RestoredInSourceWindow)
2784            }) {
2785                self.platform_owned_drag = None;
2786            }
2787            window.refresh();
2788            true
2789        } else {
2790            false
2791        }
2792    }
2793
2794    pub(crate) fn hand_active_drag_to_platform(&mut self, source_window: WindowId) -> bool {
2795        let Some(drag) = self.active_drag.take() else {
2796            return false;
2797        };
2798        self.platform_owned_drag = Some(PlatformOwnedDrag {
2799            source_window,
2800            state: PlatformOwnedDragState::Suspended(drag),
2801        });
2802        true
2803    }
2804
2805    pub(crate) fn restore_platform_drag(&mut self, source_window: WindowId) -> bool {
2806        let Some(platform_drag) = self
2807            .platform_owned_drag
2808            .as_mut()
2809            .filter(|drag| drag.source_window == source_window)
2810        else {
2811            return false;
2812        };
2813        let state = std::mem::replace(
2814            &mut platform_drag.state,
2815            PlatformOwnedDragState::RestoredInSourceWindow,
2816        );
2817        let PlatformOwnedDragState::Suspended(drag) = state else {
2818            return false;
2819        };
2820        self.active_drag = Some(drag);
2821        true
2822    }
2823
2824    pub(crate) fn hand_restored_drag_to_platform(&mut self, source_window: WindowId) -> bool {
2825        let Some(platform_drag) = self.platform_owned_drag.as_mut().filter(|drag| {
2826            drag.source_window == source_window
2827                && matches!(&drag.state, PlatformOwnedDragState::RestoredInSourceWindow)
2828        }) else {
2829            return false;
2830        };
2831        let Some(drag) = self.active_drag.take() else {
2832            return false;
2833        };
2834        platform_drag.state = PlatformOwnedDragState::Suspended(drag);
2835        true
2836    }
2837
2838    pub(crate) fn end_platform_drag(&mut self, source_window: WindowId) -> bool {
2839        if !self
2840            .platform_owned_drag
2841            .as_ref()
2842            .is_some_and(|drag| drag.source_window == source_window)
2843        {
2844            return false;
2845        }
2846        self.platform_owned_drag = None;
2847        self.active_drag = None;
2848        true
2849    }
2850
2851    /// Sets the cursor style for the currently active drag operation.
2852    pub fn set_active_drag_cursor_style(
2853        &mut self,
2854        cursor_style: CursorStyle,
2855        window: &mut Window,
2856    ) -> bool {
2857        if let Some(ref mut drag) = self.active_drag {
2858            drag.cursor_style = Some(cursor_style);
2859            window.refresh();
2860            true
2861        } else {
2862            false
2863        }
2864    }
2865
2866    /// Set the prompt renderer for GPUI. This will replace the default or platform specific
2867    /// prompts with this custom implementation.
2868    pub fn set_prompt_builder(
2869        &mut self,
2870        renderer: impl Fn(
2871            PromptLevel,
2872            &str,
2873            Option<&str>,
2874            &[PromptButton],
2875            PromptHandle,
2876            &mut Window,
2877            &mut App,
2878        ) -> RenderablePromptHandle
2879        + 'static,
2880    ) {
2881        self.prompt_builder = Some(PromptBuilder::Custom(Box::new(renderer)));
2882    }
2883
2884    /// Reset the prompt builder to the default implementation.
2885    pub fn reset_prompt_builder(&mut self) {
2886        self.prompt_builder = Some(PromptBuilder::Default);
2887    }
2888
2889    /// Remove an asset from GPUI's cache
2890    pub fn remove_asset<A: Asset>(&mut self, source: &A::Source) {
2891        let asset_id = (TypeId::of::<A>(), hash(source));
2892        self.loading_assets.remove(&asset_id);
2893    }
2894
2895    /// Check whether an asset is present in GPUI's cache (loading or loaded),
2896    /// without fetching it.
2897    #[cfg(any(test, feature = "test-support"))]
2898    pub fn has_asset<A: Asset>(&self, source: &A::Source) -> bool {
2899        let asset_id = (TypeId::of::<A>(), hash(source));
2900        self.loading_assets.contains_key(&asset_id)
2901    }
2902
2903    /// Starts loading an uncached asset and returns its result once available.
2904    ///
2905    /// Pending loads and completed results are cached until [`Self::remove_asset`].
2906    /// This method does not subscribe a view to completion notifications.
2907    pub fn fetch_asset<A: Asset>(&mut self, source: &A::Source) -> Option<A::Output> {
2908        self.asset_entry::<A>(source).get()
2909    }
2910
2911    pub(crate) fn asset_entry<A: Asset>(&mut self, source: &A::Source) -> &CachedLoad<A::Output> {
2912        let asset_id = (TypeId::of::<A>(), hash(source));
2913        if !self.loading_assets.contains_key(&asset_id) {
2914            let future = A::load(source.clone(), self);
2915            let entry = CachedLoad::new(future, self);
2916            self.loading_assets.insert(asset_id, Box::new(entry));
2917        }
2918        self.loading_assets
2919            .get(&asset_id)
2920            .and_then(|entry| entry.downcast_ref())
2921            .expect("asset cache entries are keyed by their asset type")
2922    }
2923
2924    /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus
2925    /// for elements rendered within this window.
2926    #[track_caller]
2927    pub fn focus_handle(&self) -> FocusHandle {
2928        FocusHandle::new(&self.focus_handles)
2929    }
2930
2931    /// Tell GPUI that an entity has changed and observers of it should be notified.
2932    pub fn notify(&mut self, entity_id: EntityId) {
2933        let window_invalidators = mem::take(
2934            self.window_invalidators_by_entity
2935                .entry(entity_id)
2936                .or_default(),
2937        );
2938
2939        // `window_invalidators_by_entity` is monotonic, so an entry alone
2940        // doesn't mean the window is currently rendering the entity. Filter
2941        // through `tracked_entities` to keep invalidation tight to windows
2942        // that actually display this entity right now.
2943        let live_invalidators: SmallVec<[WindowInvalidator; 2]> = window_invalidators
2944            .iter()
2945            .filter(|(window_id, _)| {
2946                self.tracked_entities
2947                    .get(window_id)
2948                    .is_some_and(|set| set.contains(&entity_id))
2949            })
2950            .map(|(_, invalidator)| invalidator.clone())
2951            .collect();
2952
2953        if live_invalidators.is_empty() {
2954            if self.pending_notifications.insert(entity_id) {
2955                self.pending_effects
2956                    .push_back(Effect::Notify { emitter: entity_id });
2957            }
2958        } else {
2959            for invalidator in &live_invalidators {
2960                invalidator.invalidate_view(entity_id, self);
2961            }
2962        }
2963
2964        self.window_invalidators_by_entity
2965            .insert(entity_id, window_invalidators);
2966    }
2967
2968    /// Returns the name for this [`App`].
2969    #[cfg(any(test, feature = "test-support", debug_assertions))]
2970    pub fn get_name(&self) -> Option<&'static str> {
2971        self.name
2972    }
2973
2974    /// Returns `true` if the platform file picker supports selecting a mix of files and directories.
2975    pub fn can_select_mixed_files_and_dirs(&self) -> bool {
2976        self.platform.can_select_mixed_files_and_dirs()
2977    }
2978
2979    /// Removes an image from the sprite atlas on all windows.
2980    ///
2981    /// If the current window is being updated, it will be removed from `App.windows`, you can use `current_window` to specify the current window.
2982    /// This is a no-op if the image is not in the sprite atlas.
2983    pub fn drop_image(&mut self, image: Arc<RenderImage>, current_window: Option<&mut Window>) {
2984        // remove the texture from all other windows
2985        for window in self.windows.values_mut().flatten() {
2986            _ = window.drop_image(image.clone());
2987        }
2988
2989        // remove the texture from the current window
2990        if let Some(window) = current_window {
2991            _ = window.drop_image(image);
2992        }
2993    }
2994
2995    /// Sets the renderer for the inspector.
2996    #[cfg(any(feature = "inspector", debug_assertions))]
2997    pub fn set_inspector_renderer(&mut self, f: crate::InspectorRenderer) {
2998        self.inspector_renderer = Some(f);
2999    }
3000
3001    /// Registers a renderer specific to an inspector state.
3002    #[cfg(any(feature = "inspector", debug_assertions))]
3003    pub fn register_inspector_element<T: 'static, R: crate::IntoElement, F>(
3004        &mut self,
3005        factory: impl 'static + Fn(&mut Window, &mut App) -> F,
3006    ) where
3007        F: 'static + FnMut(crate::InspectorElementId, &T, &mut Window, &mut App) -> R,
3008    {
3009        self.inspector_element_registry.register(factory);
3010    }
3011
3012    /// Initializes gpui's default colors for the application.
3013    ///
3014    /// These colors can be accessed through `cx.default_colors()`.
3015    pub fn init_colors(&mut self) {
3016        self.set_global(GlobalColors(Arc::new(Colors::default())));
3017    }
3018
3019    #[inline(never)]
3020    fn update_window_erased(
3021        &mut self,
3022        window_id: WindowId,
3023        update: &mut dyn FnMut(Option<(AnyView, &mut Window, &mut App)>),
3024    ) {
3025        self.update(|cx| {
3026            let Some(mut window) = cx.windows.get_mut(window_id).and_then(Option::take) else {
3027                update(None);
3028                return;
3029            };
3030
3031            let root_view = window.root.clone().unwrap();
3032
3033            cx.window_update_stack.push(window.handle.id);
3034            update(Some((root_view, &mut window, cx)));
3035            fn trail(window_id: WindowId, window: Box<Window>, cx: &mut App) -> Option<()> {
3036                cx.window_update_stack.pop();
3037
3038                if window.removed {
3039                    cx.end_platform_drag(window_id);
3040                    cx.window_handles.remove(&window_id);
3041                    cx.windows.remove(window_id);
3042                    if let Some(tracked) = cx.tracked_entities.remove(&window_id) {
3043                        for entity_id in tracked {
3044                            if let Some(windows) =
3045                                cx.window_invalidators_by_entity.get_mut(&entity_id)
3046                            {
3047                                windows.remove(&window_id);
3048                            }
3049                            if cx.current_window_by_entity.get(&entity_id) == Some(&window_id) {
3050                                cx.current_window_by_entity.remove(&entity_id);
3051                            }
3052                        }
3053                    }
3054
3055                    cx.window_closed_observers.clone().retain(&(), |callback| {
3056                        callback(cx, window_id);
3057                        true
3058                    });
3059
3060                    let quit_on_empty = match cx.quit_mode {
3061                        QuitMode::Explicit => false,
3062                        QuitMode::LastWindowClosed => true,
3063                        QuitMode::Default => cfg!(not(target_os = "macos")),
3064                    };
3065
3066                    if quit_on_empty && cx.windows.is_empty() {
3067                        cx.quit();
3068                    }
3069                } else {
3070                    cx.windows.get_mut(window_id)?.replace(window);
3071                }
3072                Some(())
3073            }
3074            if trail(window_id, window, cx).is_none() {
3075                update(None);
3076            }
3077        });
3078    }
3079
3080    #[inline(never)]
3081    fn update_entity_erased(
3082        &mut self,
3083        handle: &AnyEntity,
3084        entity_type: &str,
3085        update: &mut dyn FnMut(&mut dyn Any, &mut App),
3086    ) {
3087        self.update(|cx| {
3088            let mut lease = cx.entities.lease_erased(handle, entity_type);
3089            update(lease.entity.as_deref_mut().unwrap(), cx);
3090            cx.entities.end_lease_erased(handle.entity_id, lease);
3091        });
3092    }
3093
3094    #[inline(never)]
3095    #[track_caller]
3096    fn prepare_spawn(&self) -> AsyncApp {
3097        if self.quitting {
3098            debug_panic!("Can't spawn on main thread after on_app_quit")
3099        };
3100        self.to_async()
3101    }
3102}
3103
3104impl AppContext for App {
3105    /// Builds an entity that is owned by the application.
3106    ///
3107    /// The given function will be invoked with a [`Context`] and must return an object representing the entity. An
3108    /// [`Entity`] handle will be returned, which can be used to access the entity in a context.
3109    fn new<T: 'static>(&mut self, build_entity: impl FnOnce(&mut Context<T>) -> T) -> Entity<T> {
3110        self.update(|cx| {
3111            let slot = cx.entities.reserve();
3112            let handle = slot.clone();
3113            let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
3114
3115            cx.push_effect(Effect::EntityCreated {
3116                entity: handle.into_any(),
3117                tid: TypeId::of::<T>(),
3118                window: cx.window_update_stack.last().cloned(),
3119            });
3120
3121            cx.entities.insert(slot, entity)
3122        })
3123    }
3124
3125    fn reserve_entity<T: 'static>(&mut self) -> Reservation<T> {
3126        Reservation(self.entities.reserve())
3127    }
3128
3129    fn insert_entity<T: 'static>(
3130        &mut self,
3131        reservation: Reservation<T>,
3132        build_entity: impl FnOnce(&mut Context<T>) -> T,
3133    ) -> Entity<T> {
3134        self.update(|cx| {
3135            let slot = reservation.0;
3136            let entity = build_entity(&mut Context::new_context(cx, slot.downgrade()));
3137            cx.entities.insert(slot, entity)
3138        })
3139    }
3140
3141    /// Updates the entity referenced by the given handle. The function is passed a mutable reference to the
3142    /// entity along with a `Context` for the entity.
3143    #[inline(always)]
3144    fn update_entity<T: 'static, R>(
3145        &mut self,
3146        handle: &Entity<T>,
3147        update: impl FnOnce(&mut T, &mut Context<T>) -> R,
3148    ) -> R {
3149        let mut update = Some(update);
3150        let mut result = None;
3151        self.update_entity_erased(handle, type_name::<T>(), &mut |entity, cx| {
3152            let value = update.take().unwrap()(
3153                entity.downcast_mut::<T>().unwrap(),
3154                &mut Context::new_context(cx, handle.downgrade()),
3155            );
3156            result = Some(value);
3157        });
3158        result.unwrap()
3159    }
3160
3161    fn as_mut<'a, T>(&'a mut self, handle: &Entity<T>) -> GpuiBorrow<'a, T>
3162    where
3163        T: 'static,
3164    {
3165        GpuiBorrow::new(handle.clone(), self)
3166    }
3167
3168    #[inline(always)]
3169    fn read_entity<T, R>(&self, handle: &Entity<T>, read: impl FnOnce(&T, &App) -> R) -> R
3170    where
3171        T: 'static,
3172    {
3173        let entity = self.entities.read(handle);
3174        read(entity, self)
3175    }
3176
3177    fn update_window<T, F>(&mut self, handle: AnyWindowHandle, update: F) -> Result<T>
3178    where
3179        F: FnOnce(AnyView, &mut Window, &mut App) -> T,
3180    {
3181        self.update_window_id(handle.id, update)
3182    }
3183
3184    fn with_window<R>(
3185        &mut self,
3186        entity_id: EntityId,
3187        f: impl FnOnce(&mut Window, &mut App) -> R,
3188    ) -> Option<R> {
3189        App::with_window(self, entity_id, f)
3190    }
3191
3192    fn read_window<T, R>(
3193        &self,
3194        window: &WindowHandle<T>,
3195        read: impl FnOnce(Entity<T>, &App) -> R,
3196    ) -> Result<R>
3197    where
3198        T: 'static,
3199    {
3200        let window = self
3201            .windows
3202            .get(window.id)
3203            .context("window not found")?
3204            .as_deref()
3205            .expect("attempted to read a window that is already on the stack");
3206
3207        let root_view = window.root.clone().unwrap();
3208        let view = root_view
3209            .downcast::<T>()
3210            .map_err(|_| anyhow!("root view's type has changed"))?;
3211
3212        Ok(read(view, self))
3213    }
3214
3215    fn background_spawn<R>(&self, future: impl Future<Output = R> + Send + 'static) -> Task<R>
3216    where
3217        R: Send + 'static,
3218    {
3219        self.background_executor.spawn(future)
3220    }
3221
3222    fn read_global<G, R>(&self, callback: impl FnOnce(&G, &App) -> R) -> R
3223    where
3224        G: Global,
3225    {
3226        let mut g = self.global::<G>();
3227        callback(g, self)
3228    }
3229}
3230
3231/// These effects are processed at the end of each application update cycle.
3232pub(crate) enum Effect {
3233    Notify {
3234        emitter: EntityId,
3235    },
3236    Emit {
3237        emitter: EntityId,
3238        event_type: TypeId,
3239        event: ArenaBox<dyn Any>,
3240    },
3241    RefreshWindows,
3242    NotifyGlobalObservers {
3243        global_type: TypeId,
3244    },
3245    Defer {
3246        callback: Box<dyn FnOnce(&mut App) + 'static>,
3247    },
3248    EntityCreated {
3249        entity: AnyEntity,
3250        tid: TypeId,
3251        window: Option<WindowId>,
3252    },
3253}
3254
3255impl std::fmt::Debug for Effect {
3256    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3257        match self {
3258            Effect::Notify { emitter } => write!(f, "Notify({})", emitter),
3259            Effect::Emit { emitter, .. } => write!(f, "Emit({:?})", emitter),
3260            Effect::RefreshWindows => write!(f, "RefreshWindows"),
3261            Effect::NotifyGlobalObservers { global_type } => {
3262                write!(f, "NotifyGlobalObservers({:?})", global_type)
3263            }
3264            Effect::Defer { .. } => write!(f, "Defer(..)"),
3265            Effect::EntityCreated { entity, .. } => write!(f, "EntityCreated({:?})", entity),
3266        }
3267    }
3268}
3269
3270/// Wraps a global variable value during `update_global` while the value has been moved to the stack.
3271pub(crate) struct GlobalLease<G: Global> {
3272    global: Box<dyn Any>,
3273    global_type: PhantomData<G>,
3274}
3275
3276impl<G: Global> GlobalLease<G> {
3277    fn new(global: Box<dyn Any>) -> Self {
3278        GlobalLease {
3279            global,
3280            global_type: PhantomData,
3281        }
3282    }
3283}
3284
3285impl<G: Global> Deref for GlobalLease<G> {
3286    type Target = G;
3287
3288    fn deref(&self) -> &Self::Target {
3289        self.global.downcast_ref().unwrap()
3290    }
3291}
3292
3293impl<G: Global> DerefMut for GlobalLease<G> {
3294    fn deref_mut(&mut self) -> &mut Self::Target {
3295        self.global.downcast_mut().unwrap()
3296    }
3297}
3298
3299/// Contains state associated with an active drag operation, started by dragging an element
3300/// within the window or by dragging into the app from the underlying platform.
3301pub struct AnyDrag {
3302    /// The view used to render this drag
3303    pub view: AnyView,
3304
3305    /// The value of the dragged item, to be dropped
3306    pub value: Arc<dyn Any>,
3307
3308    /// This is used to render the dragged item in the same place
3309    /// on the original element that the drag was initiated
3310    pub cursor_offset: Point<Pixels>,
3311
3312    /// The cursor style to use while dragging
3313    pub cursor_style: Option<CursorStyle>,
3314
3315    /// Resolves the payload to offer the platform if the drag leaves the window.
3316    /// Invoked at most once per drag gesture, at promotion time.
3317    pub external_payload_source: Option<ExternalDragPayloadSource>,
3318}
3319
3320/// Lazily resolves the payload handed to the platform when an internal drag is
3321/// promoted to a native drag session.
3322pub type ExternalDragPayloadSource =
3323    Box<dyn FnOnce(&mut Window, &mut App) -> Option<ExternalDragPayload> + 'static>;
3324
3325/// Contains state associated with a tooltip. You'll only need this struct if you're implementing
3326/// tooltip behavior on a custom element. Otherwise, use [Div::tooltip](crate::Interactivity::tooltip).
3327#[derive(Clone)]
3328pub struct AnyTooltip {
3329    /// The view used to display the tooltip
3330    pub view: AnyView,
3331
3332    /// The absolute position of the mouse when the tooltip was deployed.
3333    pub mouse_position: Point<Pixels>,
3334
3335    /// Given the bounds of the tooltip, checks whether the tooltip should still be visible and
3336    /// updates its state accordingly. This is needed atop the hovered element's mouse move handler
3337    /// to handle the case where the element is not painted (e.g. via use of `visible_on_hover`).
3338    pub check_visible_and_update: Rc<dyn Fn(Bounds<Pixels>, &mut Window, &mut App) -> bool>,
3339}
3340
3341/// Whether a keystroke should prefer character input or key bindings.
3342#[derive(Clone, Copy, Debug, Eq, PartialEq)]
3343pub enum InputPreference {
3344    /// Prefer typing text over triggering key bindings.
3345    CharacterInput,
3346    /// Dispatch key bindings normally, if any match.
3347    KeyBindings,
3348}
3349
3350/// A keystroke event, and potentially the associated action
3351#[derive(Debug)]
3352pub struct KeystrokeEvent {
3353    /// The keystroke that occurred
3354    pub keystroke: Keystroke,
3355
3356    /// Whether this keystroke should prefer character input or key bindings.
3357    /// This is [`InputPreference::CharacterInput`] when the platform prefers text for the key
3358    /// (e.g. AltGr on Windows) and the focused input accepts text. Interceptors still receive
3359    /// these keystrokes and can consume them.
3360    ///
3361    /// If the keystroke is part of a multi-stroke binding, it still waits as pending input
3362    /// even when this is [`InputPreference::CharacterInput`].
3363    pub input_preference: InputPreference,
3364
3365    /// The action that was resolved for the keystroke, if any
3366    pub action: Option<Box<dyn Action>>,
3367
3368    /// The context stack at the time
3369    pub context_stack: Vec<KeyContext>,
3370}
3371
3372struct NullHttpClient;
3373
3374impl HttpClient for NullHttpClient {
3375    fn send(
3376        &self,
3377        _req: http_client::Request<http_client::AsyncBody>,
3378    ) -> futures::future::BoxFuture<
3379        'static,
3380        anyhow::Result<http_client::Response<http_client::AsyncBody>>,
3381    > {
3382        async move {
3383            anyhow::bail!("No HttpClient available");
3384        }
3385        .boxed()
3386    }
3387
3388    fn user_agent(&self) -> Option<&http_client::http::HeaderValue> {
3389        None
3390    }
3391
3392    fn proxy(&self) -> Option<&Url> {
3393        None
3394    }
3395}
3396
3397/// A mutable reference to an entity owned by GPUI
3398pub struct GpuiBorrow<'a, T> {
3399    inner: Option<Lease<T>>,
3400    app: &'a mut App,
3401}
3402
3403impl<'a, T: 'static> GpuiBorrow<'a, T> {
3404    fn new(inner: Entity<T>, app: &'a mut App) -> Self {
3405        app.start_update();
3406        let lease = app.entities.lease(&inner);
3407        Self {
3408            inner: Some(lease),
3409            app,
3410        }
3411    }
3412}
3413
3414impl<'a, T: 'static> std::borrow::Borrow<T> for GpuiBorrow<'a, T> {
3415    fn borrow(&self) -> &T {
3416        self.inner.as_ref().unwrap().borrow()
3417    }
3418}
3419
3420impl<'a, T: 'static> std::borrow::BorrowMut<T> for GpuiBorrow<'a, T> {
3421    fn borrow_mut(&mut self) -> &mut T {
3422        self.inner.as_mut().unwrap().borrow_mut()
3423    }
3424}
3425
3426impl<'a, T: 'static> std::ops::Deref for GpuiBorrow<'a, T> {
3427    type Target = T;
3428
3429    fn deref(&self) -> &Self::Target {
3430        self.inner.as_ref().unwrap()
3431    }
3432}
3433
3434impl<'a, T: 'static> std::ops::DerefMut for GpuiBorrow<'a, T> {
3435    fn deref_mut(&mut self) -> &mut T {
3436        self.inner.as_mut().unwrap()
3437    }
3438}
3439
3440impl<'a, T> Drop for GpuiBorrow<'a, T> {
3441    fn drop(&mut self) {
3442        let lease = self.inner.take().unwrap();
3443        self.app.notify(lease.id);
3444        self.app.entities.end_lease(lease);
3445        self.app.finish_update();
3446    }
3447}
3448
3449#[cfg(test)]
3450mod test {
3451    use std::{
3452        cell::{Cell, RefCell},
3453        ffi::OsString,
3454        path::PathBuf,
3455        rc::Rc,
3456    };
3457
3458    #[cfg(unix)]
3459    use std::os::unix::ffi::OsStringExt;
3460
3461    use crate::{
3462        AppContext, Context, Empty, FallbackFontClass, IntoElement, MissingGlyph, Render,
3463        TestAppContext, Window,
3464    };
3465
3466    struct RenderCounter(Rc<Cell<usize>>);
3467
3468    impl Render for RenderCounter {
3469        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
3470            self.0.set(self.0.get() + 1);
3471            Empty
3472        }
3473    }
3474
3475    #[gpui::test]
3476    fn async_app_refresh_flushes_refresh_effect(cx: &mut TestAppContext) {
3477        let render_count = Rc::new(Cell::new(0));
3478
3479        let _window = cx.add_window({
3480            let render_count = render_count.clone();
3481            move |_, _| RenderCounter(render_count)
3482        });
3483
3484        cx.run_until_parked();
3485        let render_count_before_refresh = render_count.get();
3486
3487        cx.to_async().refresh();
3488
3489        assert_eq!(render_count.get(), render_count_before_refresh + 1);
3490    }
3491
3492    #[gpui::test]
3493    fn missing_glyph_callbacks_follow_subscription_lifetime(cx: &mut TestAppContext) {
3494        let observed = Rc::new(RefCell::new(Vec::new()));
3495        let subscription = cx.update(|cx| {
3496            let observed = observed.clone();
3497            cx.on_missing_glyphs(move |missing_glyphs, _| {
3498                observed.borrow_mut().extend_from_slice(missing_glyphs);
3499            })
3500        });
3501        cx.update(|cx| {
3502            cx.text_system()
3503                .report_missing_glyphs_in_test(vec![missing_glyph("active")]);
3504        });
3505        cx.run_until_parked();
3506        assert_eq!(observed.borrow().as_slice(), &[missing_glyph("active")]);
3507
3508        let second_observed = Rc::new(RefCell::new(Vec::new()));
3509        let second_subscription = cx.update(|cx| {
3510            let second_observed = second_observed.clone();
3511            cx.on_missing_glyphs(move |missing_glyphs, _| {
3512                second_observed
3513                    .borrow_mut()
3514                    .extend_from_slice(missing_glyphs);
3515            })
3516        });
3517        cx.update(|cx| {
3518            cx.text_system()
3519                .report_missing_glyphs_in_test(vec![missing_glyph("replacement")]);
3520        });
3521        cx.run_until_parked();
3522        assert_eq!(observed.borrow().as_slice(), &[missing_glyph("active")]);
3523        assert_eq!(
3524            second_observed.borrow().as_slice(),
3525            &[missing_glyph("replacement")]
3526        );
3527
3528        drop(subscription);
3529        cx.update(|cx| {
3530            cx.text_system()
3531                .report_missing_glyphs_in_test(vec![missing_glyph("after old drop")]);
3532        });
3533        cx.run_until_parked();
3534        assert_eq!(
3535            second_observed.borrow().as_slice(),
3536            &[
3537                missing_glyph("replacement"),
3538                missing_glyph("after old drop")
3539            ]
3540        );
3541
3542        drop(second_subscription);
3543        cx.update(|cx| {
3544            cx.text_system()
3545                .report_missing_glyphs_in_test(vec![missing_glyph("inactive")]);
3546        });
3547        cx.run_until_parked();
3548        assert_eq!(second_observed.borrow().len(), 2);
3549    }
3550
3551    #[test]
3552    fn test_gpui_borrow() {
3553        let cx = TestAppContext::single();
3554        let observation_count = Rc::new(RefCell::new(0));
3555
3556        let state = cx.update(|cx| {
3557            let state = cx.new(|_| false);
3558            cx.observe(&state, {
3559                let observation_count = observation_count.clone();
3560                move |_, _| {
3561                    let mut count = observation_count.borrow_mut();
3562                    *count += 1;
3563                }
3564            })
3565            .detach();
3566
3567            state
3568        });
3569
3570        cx.update(|cx| {
3571            // Calling this like this so that we don't clobber the borrow_mut above
3572            *std::borrow::BorrowMut::borrow_mut(&mut state.as_mut(cx)) = true;
3573        });
3574
3575        cx.update(|cx| {
3576            state.write(cx, false);
3577        });
3578
3579        assert_eq!(*observation_count.borrow(), 2);
3580    }
3581
3582    #[gpui::test]
3583    async fn test_restart_preserves_path_and_arguments(cx: &mut TestAppContext) {
3584        #[cfg(unix)]
3585        let user_data_dir = OsString::from_vec(b"/tmp/zed data/\xff".to_vec());
3586        #[cfg(not(unix))]
3587        let user_data_dir = OsString::from("C:\\zed data");
3588        let arguments = vec![OsString::from("--user-data-dir"), user_data_dir];
3589        let restart_path = PathBuf::from("updated-zed");
3590        let _application =
3591            super::Application(cx.app.clone()).with_restart_arguments(arguments.clone());
3592        let restart = cx.expect_restart();
3593
3594        cx.update(|cx| {
3595            cx.set_restart_path(restart_path.clone());
3596            cx.restart();
3597        });
3598
3599        let (path, restart_arguments) = restart.await.expect("restart was not requested");
3600        assert_eq!(path, Some(restart_path));
3601        assert_eq!(restart_arguments, arguments);
3602    }
3603
3604    fn missing_glyph(grapheme: &'static str) -> MissingGlyph {
3605        MissingGlyph::new(grapheme.into(), FallbackFontClass::Proportional)
3606    }
3607}