Skip to main content

gpui/
app.rs

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