Skip to main content

gpui/
app.rs

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