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