Skip to main content

gpui_authoring/
app.rs

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