Skip to main content

gpui/
window.rs

1#[cfg(feature = "profiler")]
2use crate::DebugFrameOverlayMode;
3#[cfg(any(feature = "inspector", debug_assertions))]
4use crate::Inspector;
5#[cfg(feature = "profiler")]
6use crate::profiler;
7use crate::{
8    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,
9    AsyncWindowContext, AtlasTile, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow,
10    Capslock, Context, Corners, CursorHideMode, CursorStyle, Decorations, DevicePixels,
11    DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity,
12    EntityId, EventEmitter, FileDropEvent, FontId, Global, GlobalElementId, GlyphId, GpuSpecs,
13    Hsla, InputHandler, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke,
14    KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite,
15    MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas,
16    PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite,
17    Priority, PromptButton, PromptLevel, Quad, Render, RenderGlyphParams, RenderImage,
18    RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,
19    SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y, ScaledPixels, Scene, Shadow, SharedString, Size,
20    StrikethroughStyle, Style, SubpixelSprite, SubscriberSet, Subscription, SystemWindowTab,
21    SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task, TextInputConfiguration,
22    TextInputStateChange, TextRenderingMode, TextStyle, TextStyleRefinement, ThermalState,
23    TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,
24    WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowTextSystem,
25    point, prelude::*, px, rems, size, transparent_black,
26};
27
28use crate::gestures::{GestureTuning, RecognizedTouchGesture, TouchGestureRecognizer};
29use crate::interactive::TouchEvent;
30use anyhow::{Context as _, Result, anyhow};
31use collections::{FxHashMap, FxHashSet};
32#[cfg(target_os = "macos")]
33use core_video::pixel_buffer::CVPixelBuffer;
34use derive_more::{Deref, DerefMut};
35use futures::FutureExt;
36use futures::channel::oneshot;
37use gpui_util::post_inc;
38use gpui_util::{ResultExt, measure};
39use itertools::FoldWhile::{Continue, Done};
40use itertools::Itertools;
41use parking_lot::RwLock;
42use raw_window_handle::{HandleError, HasDisplayHandle, HasWindowHandle};
43use refineable::Refineable;
44use scheduler::Instant;
45use slotmap::SlotMap;
46use smallvec::SmallVec;
47use std::{
48    any::{Any, TypeId},
49    borrow::Cow,
50    cell::{Cell, RefCell},
51    cmp,
52    fmt::{Debug, Display},
53    hash::{Hash, Hasher},
54    marker::PhantomData,
55    mem,
56    ops::{DerefMut, Range},
57    rc::Rc,
58    sync::{
59        Arc, Weak,
60        atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
61    },
62    time::Duration,
63};
64use uuid::Uuid;
65
66pub(crate) mod a11y;
67mod prompts;
68
69pub use a11y::A11ySubtreeBuilder;
70
71use self::a11y::A11y;
72#[cfg(not(target_family = "wasm"))]
73use self::a11y::ROOT_NODE_ID;
74use crate::util::{
75    atomic_incr_if_not_zero, ceil_to_device_pixel, floor_to_device_pixel, round_half_toward_zero,
76    round_half_toward_zero_f64, round_stroke_to_device_pixel, round_to_device_pixel,
77};
78pub use prompts::*;
79
80/// Default window size used when no explicit size is provided.
81pub const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1536.), px(1095.));
82
83/// A 6:5 aspect ratio minimum window size to be used for functional,
84/// additional-to-main-Zed windows, like the settings and rules library windows.
85pub const DEFAULT_ADDITIONAL_WINDOW_SIZE: Size<Pixels> = Size {
86    width: Pixels(900.),
87    height: Pixels(750.),
88};
89
90/// Represents the two different phases when dispatching events.
91#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
92pub enum DispatchPhase {
93    /// After the capture phase comes the bubble phase, in which mouse event listeners are
94    /// invoked front to back and keyboard event listeners are invoked from the focused element
95    /// to the root of the element tree. This is the phase you'll most commonly want to use when
96    /// registering event listeners.
97    #[default]
98    Bubble,
99    /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard
100    /// listeners are invoked from the root of the tree downward toward the focused element. This phase
101    /// is used for special purposes such as clearing the "pressed" state for click events. If
102    /// you stop event propagation during this phase, you need to know what you're doing. Handlers
103    /// outside of the immediate region may rely on detecting non-local events during this phase.
104    Capture,
105}
106
107impl DispatchPhase {
108    /// Returns true if this represents the "bubble" phase.
109    #[inline]
110    pub fn bubble(self) -> bool {
111        self == DispatchPhase::Bubble
112    }
113
114    /// Returns true if this represents the "capture" phase.
115    #[inline]
116    pub fn capture(self) -> bool {
117        self == DispatchPhase::Capture
118    }
119}
120
121struct WindowInvalidatorInner {
122    #[cfg(feature = "profiler")]
123    pub window_id: WindowId,
124    pub dirty: bool,
125    pub draw_phase: DrawPhase,
126    pub dirty_views: FxHashSet<EntityId>,
127    pub update_count: usize,
128    #[cfg(feature = "profiler")]
129    pub frame_dirty: FrameDirtyAccumulator,
130    pub platform_waker: Option<Rc<dyn Fn()>>,
131}
132
133/// Per-frame invalidation bookkeeping, drained at draw time and emitted to the
134/// frame profiler. Tracks when the current frame first became dirty and how
135/// many invalidations were coalesced into it, whenever the profiler is
136/// compiled in. Retention of the resulting per-frame records is what
137/// `profiler::trace_enabled()` controls, not this measurement.
138#[cfg(feature = "profiler")]
139#[derive(Default)]
140struct FrameDirtyAccumulator {
141    dirty_at: Option<Instant>,
142    invalidations: u64,
143}
144
145#[derive(Clone)]
146pub(crate) struct WindowInvalidator {
147    inner: Rc<RefCell<WindowInvalidatorInner>>,
148}
149
150impl WindowInvalidator {
151    pub fn new(#[allow(unused_variables)] window_id: WindowId) -> Self {
152        WindowInvalidator {
153            inner: Rc::new(RefCell::new(WindowInvalidatorInner {
154                #[cfg(feature = "profiler")]
155                window_id,
156                dirty: true,
157                draw_phase: DrawPhase::None,
158                dirty_views: FxHashSet::default(),
159                update_count: 0,
160                #[cfg(feature = "profiler")]
161                frame_dirty: FrameDirtyAccumulator::default(),
162                platform_waker: None,
163            })),
164        }
165    }
166
167    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {
168        let mut inner = self.inner.borrow_mut();
169        inner.update_count += 1;
170        inner.dirty_views.insert(entity);
171        if inner.draw_phase == DrawPhase::None {
172            #[cfg(feature = "profiler")]
173            let dirty_at = Self::record_frame_dirty(&mut inner);
174            let became_dirty = !inner.dirty;
175            inner.dirty = true;
176            let waker = became_dirty.then(|| inner.platform_waker.clone()).flatten();
177            #[cfg(feature = "profiler")]
178            let window_id = inner.window_id;
179            drop(inner);
180            #[cfg(feature = "profiler")]
181            if became_dirty {
182                profiler::journal::record_frame_pending(window_id, dirty_at);
183            }
184            cx.push_effect(Effect::Notify { emitter: entity });
185            if let Some(waker) = waker {
186                waker();
187            }
188            true
189        } else {
190            false
191        }
192    }
193
194    pub fn is_dirty(&self) -> bool {
195        self.inner.borrow().dirty
196    }
197
198    pub fn set_dirty(&self, dirty: bool) {
199        let mut inner = self.inner.borrow_mut();
200        let became_dirty = dirty && !inner.dirty;
201        inner.dirty = dirty;
202        if dirty {
203            inner.update_count += 1;
204        }
205        #[cfg(feature = "profiler")]
206        let dirty_at = dirty.then(|| Self::record_frame_dirty(&mut inner));
207        let waker = became_dirty.then(|| inner.platform_waker.clone()).flatten();
208        #[cfg(feature = "profiler")]
209        let window_id = inner.window_id;
210        drop(inner);
211        #[cfg(feature = "profiler")]
212        if became_dirty && let Some(dirty_at) = dirty_at {
213            profiler::journal::record_frame_pending(window_id, dirty_at);
214        }
215        if let Some(waker) = waker {
216            waker();
217        }
218    }
219
220    pub fn set_platform_waker(&self, waker: Option<Rc<dyn Fn()>>) {
221        let mut inner = self.inner.borrow_mut();
222        inner.platform_waker = waker;
223        let waker = inner.dirty.then(|| inner.platform_waker.clone()).flatten();
224        drop(inner);
225        if let Some(waker) = waker {
226            waker();
227        }
228    }
229
230    /// Wakes the platform's frame-request source so a frame request is
231    /// delivered even if the platform stops requesting frames for idle
232    /// windows. No-op on platforms without a frame waker.
233    pub fn wake_platform(&self) {
234        let waker = self.inner.borrow().platform_waker.clone();
235        if let Some(waker) = waker {
236            waker();
237        }
238    }
239
240    pub fn set_phase(&self, phase: DrawPhase) {
241        self.inner.borrow_mut().draw_phase = phase
242    }
243
244    pub fn update_count(&self) -> usize {
245        self.inner.borrow().update_count
246    }
247
248    #[cfg(feature = "profiler")]
249    fn record_frame_dirty(inner: &mut WindowInvalidatorInner) -> Instant {
250        let dirty_at = *inner.frame_dirty.dirty_at.get_or_insert_with(Instant::now);
251        inner.frame_dirty.invalidations += 1;
252        dirty_at
253    }
254
255    #[cfg(feature = "profiler")]
256    fn take_frame_dirty(&self) -> FrameDirtyAccumulator {
257        mem::take(&mut self.inner.borrow_mut().frame_dirty)
258    }
259
260    pub fn take_views(&self) -> FxHashSet<EntityId> {
261        mem::take(&mut self.inner.borrow_mut().dirty_views)
262    }
263
264    pub fn replace_views(&self, views: FxHashSet<EntityId>) {
265        self.inner.borrow_mut().dirty_views = views;
266    }
267
268    pub fn not_drawing(&self) -> bool {
269        self.inner.borrow().draw_phase == DrawPhase::None
270    }
271
272    #[track_caller]
273    pub fn debug_assert_paint(&self) {
274        debug_assert!(
275            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),
276            "this method can only be called during paint"
277        );
278    }
279
280    #[track_caller]
281    pub fn debug_assert_prepaint(&self) {
282        debug_assert!(
283            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),
284            "this method can only be called during request_layout, or prepaint"
285        );
286    }
287
288    #[track_caller]
289    pub fn debug_assert_paint_or_prepaint(&self) {
290        debug_assert!(
291            matches!(
292                self.inner.borrow().draw_phase,
293                DrawPhase::Paint | DrawPhase::Prepaint
294            ),
295            "this method can only be called during request_layout, prepaint, or paint"
296        );
297    }
298}
299
300type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;
301
302pub(crate) type AnyWindowFocusListener =
303    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;
304
305pub(crate) struct WindowFocusEvent {
306    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,
307    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,
308}
309
310impl WindowFocusEvent {
311    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {
312        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)
313    }
314
315    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {
316        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)
317    }
318}
319
320/// This is provided when subscribing for `Context::on_focus_out` events.
321pub struct FocusOutEvent {
322    /// A weak focus handle representing what was blurred.
323    pub blurred: WeakFocusHandle,
324}
325
326slotmap::new_key_type! {
327    /// A globally unique identifier for a focusable element.
328    pub struct FocusId;
329}
330
331thread_local! {
332    /// Fallback arena used when no app-specific arena is active.
333    /// In production, each window draw sets CURRENT_ELEMENT_ARENA to the app's arena.
334    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));
335
336    /// Points to the current App's element arena during draw operations.
337    /// This allows multiple test Apps to have isolated arenas, preventing
338    /// cross-session corruption when the scheduler interleaves their tasks.
339    static CURRENT_ELEMENT_ARENA: Cell<Option<*const RefCell<Arena>>> = const { Cell::new(None) };
340}
341
342/// Whether a window draw is currently in progress on this thread.
343///
344/// This holds exactly while an `ElementArenaScope` is active: nested scopes
345/// restore the previous (still set) arena pointer, so `CURRENT_ELEMENT_ARENA`
346/// is `Some` from the outermost draw's start to its end.
347///
348/// The `on_request_frame` callback uses this to defer draw requests that
349/// arrive re-entrantly while a draw is already on the stack (e.g. via nested
350/// message pumping in the Windows window procedure), instead of running a
351/// nested draw or panicking on the already-borrowed App.
352fn draw_in_progress() -> bool {
353    CURRENT_ELEMENT_ARENA.with(|current| current.get().is_some())
354}
355
356/// Allocates an element in the current arena. Uses the app-specific arena if one
357/// is active (during draw), otherwise falls back to the thread-local ELEMENT_ARENA.
358pub(crate) fn with_element_arena<R>(f: impl FnOnce(&mut Arena) -> R) -> R {
359    CURRENT_ELEMENT_ARENA.with(|current| {
360        if let Some(arena_ptr) = current.get() {
361            // SAFETY: The pointer is valid for the duration of the draw operation
362            // that set it, and we're being called during that same draw.
363            let arena_cell = unsafe { &*arena_ptr };
364            f(&mut arena_cell.borrow_mut())
365        } else {
366            ELEMENT_ARENA.with_borrow_mut(f)
367        }
368    })
369}
370
371/// Scope guard that sets CURRENT_ELEMENT_ARENA for the duration of a draw
372/// operation and tracks the arena's scope depth, so that a nested draw's
373/// `ArenaClearNeeded::clear` is deferred rather than freeing memory the outer
374/// draw still references (see `Arena::clear`).
375///
376/// Call [`ElementArenaScope::exit`] with the same arena that was entered to
377/// obtain the [`ArenaClearNeeded`] token the draw now owes; requiring `exit`
378/// makes it impossible to request a clear before the scope has ended. The
379/// scope's teardown — restoring the thread-local and balancing `begin_scope`
380/// with `end_scope` — happens in `Drop`, so the arena's scope depth stays
381/// balanced on every path, including when a panic unwinds a draw before `exit`
382/// is reached. (If teardown lived only in `exit`, such a panic would leave the
383/// scope depth permanently elevated and defer every future clear, leaking
384/// memory unboundedly.)
385pub(crate) struct ElementArenaScope {
386    /// The entered arena: compared against the argument in `exit`, and
387    /// dereferenced in `Drop` to end its scope (see the SAFETY note there).
388    entered: *const RefCell<Arena>,
389    previous: Option<*const RefCell<Arena>>,
390    exited: bool,
391}
392
393impl ElementArenaScope {
394    /// Enter a scope where element allocations use the given arena.
395    pub(crate) fn enter(arena: &RefCell<Arena>) -> Self {
396        arena.borrow_mut().begin_scope();
397        let previous = CURRENT_ELEMENT_ARENA.with(|current| {
398            let prev = current.get();
399            current.set(Some(arena as *const RefCell<Arena>));
400            prev
401        });
402        Self {
403            entered: arena as *const RefCell<Arena>,
404            previous,
405            exited: false,
406        }
407    }
408
409    /// End the scope: restores the previously-current arena and ends the
410    /// arena's clear-deferral scope. Returns the token for the arena clear the
411    /// draw now owes; producing it here makes it impossible to request a clear
412    /// before the scope has ended (which would be silently deferred forever).
413    ///
414    /// Panics if passed a different arena than was entered: ending the scope
415    /// of the wrong arena would unbalance two arenas' scope depths, allowing
416    /// one of them to clear while a draw still references its memory.
417    pub(crate) fn exit(mut self, arena: &RefCell<Arena>) -> ArenaClearNeeded {
418        assert!(
419            std::ptr::eq(self.entered, arena),
420            "ElementArenaScope::exit called with a different arena than was entered"
421        );
422        self.exited = true;
423        // Teardown (restoring the thread-local and ending the arena's
424        // clear-deferral scope) runs in `Drop`, which fires both here — `self`
425        // is dropped as `exit` returns, before the token reaches the caller —
426        // and when a panic unwinds the draw before `exit` is reached.
427        ArenaClearNeeded::new(arena)
428    }
429}
430
431impl Drop for ElementArenaScope {
432    fn drop(&mut self) {
433        // Teardown lives here (rather than in `exit`) so it runs exactly once on
434        // every path: `exit` consumes and drops the guard on the normal path,
435        // and unwinding drops it on the panic path. Balancing `begin_scope` here
436        // keeps the arena's scope depth correct even when a draw panics; if this
437        // only happened in `exit`, a panic between `enter` and `exit` would leave
438        // the depth elevated and defer every future clear.
439        CURRENT_ELEMENT_ARENA.with(|current| {
440            current.set(self.previous);
441        });
442        // SAFETY: `entered` came from a `&RefCell<Arena>` in `enter`, and the
443        // arena (owned by the `App` being drawn) outlives this guard on both the
444        // normal and unwinding paths, since the guard is a local of the draw.
445        unsafe { &*self.entered }.borrow_mut().end_scope();
446        if !self.exited && !std::thread::panicking() {
447            debug_assert!(false, "ElementArenaScope dropped without calling exit()");
448            log::error!(
449                "ElementArenaScope dropped without calling exit(); \
450                 the arena clear for this draw was never requested"
451            );
452        }
453    }
454}
455
456/// Returned when the element arena has been used and so must be cleared before the next draw.
457#[must_use]
458pub struct ArenaClearNeeded {
459    /// Identity of the arena that was drawn into. Only ever compared against
460    /// another pointer in `clear`; never dereferenced.
461    arena: *const RefCell<Arena>,
462}
463
464impl ArenaClearNeeded {
465    /// Create a new ArenaClearNeeded token for the App whose arena was drawn
466    /// into. Private: the only way to obtain one is [`ElementArenaScope::exit`].
467    fn new(arena: &RefCell<Arena>) -> Self {
468        Self {
469            arena: arena as *const RefCell<Arena>,
470        }
471    }
472
473    /// Clear the element arena of the App the draw ran against. If an enclosing
474    /// draw is still in progress (this draw was nested inside it), the clear is
475    /// deferred to the enclosing draw's own `ArenaClearNeeded` so that its live
476    /// allocations aren't freed.
477    ///
478    /// Panics if passed a different App than the draw ran against, since
479    /// clearing another App's arena could free memory its draws still
480    /// reference.
481    pub fn clear(self, cx: &mut App) {
482        assert!(
483            std::ptr::eq(self.arena, &cx.element_arena),
484            "ArenaClearNeeded::clear called with a different App than the draw ran against"
485        );
486        cx.element_arena.borrow_mut().clear();
487    }
488}
489
490pub(crate) type FocusMap = RwLock<SlotMap<FocusId, FocusRef>>;
491pub(crate) struct FocusRef {
492    pub(crate) ref_count: AtomicUsize,
493    pub(crate) tab_index: isize,
494    pub(crate) tab_stop: bool,
495}
496
497impl FocusId {
498    /// Obtains whether the element associated with this handle is currently focused.
499    pub fn is_focused(&self, window: &Window) -> bool {
500        window.focus == Some(*self)
501    }
502
503    /// Obtains whether the element associated with this handle contains the focused
504    /// element or is itself focused.
505    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
506        window
507            .focused(cx)
508            .is_some_and(|focused| self.contains(focused.id, window))
509    }
510
511    /// Obtains whether the element associated with this handle is contained within the
512    /// focused element or is itself focused.
513    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {
514        let focused = window.focused(cx);
515        focused.is_some_and(|focused| focused.id.contains(*self, window))
516    }
517
518    /// Obtains whether this handle contains the given handle in the most recently rendered frame.
519    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {
520        window
521            .rendered_frame
522            .dispatch_tree
523            .focus_contains(*self, other)
524    }
525}
526
527/// A handle which can be used to track and manipulate the focused element in a window.
528pub struct FocusHandle {
529    pub(crate) id: FocusId,
530    handles: Arc<FocusMap>,
531    /// The index of this element in the tab order.
532    pub tab_index: isize,
533    /// Whether this element can be focused by tab navigation.
534    pub tab_stop: bool,
535}
536
537impl std::fmt::Debug for FocusHandle {
538    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
539        f.write_fmt(format_args!("FocusHandle({:?})", self.id))
540    }
541}
542
543impl FocusHandle {
544    pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {
545        let id = handles.write().insert(FocusRef {
546            ref_count: AtomicUsize::new(1),
547            tab_index: 0,
548            tab_stop: false,
549        });
550
551        Self {
552            id,
553            tab_index: 0,
554            tab_stop: false,
555            handles: handles.clone(),
556        }
557    }
558
559    pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {
560        let lock = handles.read();
561        let focus = lock.get(id)?;
562        if atomic_incr_if_not_zero(&focus.ref_count) == 0 {
563            return None;
564        }
565        Some(Self {
566            id,
567            tab_index: focus.tab_index,
568            tab_stop: focus.tab_stop,
569            handles: handles.clone(),
570        })
571    }
572
573    /// Sets the tab index of the element associated with this handle.
574    pub fn tab_index(mut self, index: isize) -> Self {
575        self.tab_index = index;
576        if let Some(focus) = self.handles.write().get_mut(self.id) {
577            focus.tab_index = index;
578        }
579        self
580    }
581
582    /// Sets whether the element associated with this handle is a tab stop.
583    ///
584    /// When `false`, the element will not be included in the tab order.
585    pub fn tab_stop(mut self, tab_stop: bool) -> Self {
586        self.tab_stop = tab_stop;
587        if let Some(focus) = self.handles.write().get_mut(self.id) {
588            focus.tab_stop = tab_stop;
589        }
590        self
591    }
592
593    /// Converts this focus handle into a weak variant, which does not prevent it from being released.
594    pub fn downgrade(&self) -> WeakFocusHandle {
595        WeakFocusHandle {
596            id: self.id,
597            handles: Arc::downgrade(&self.handles),
598        }
599    }
600
601    /// Moves the focus to the element associated with this handle.
602    pub fn focus(&self, window: &mut Window, cx: &mut App) {
603        window.focus(self, cx)
604    }
605
606    /// Obtains whether the element associated with this handle is currently focused.
607    pub fn is_focused(&self, window: &Window) -> bool {
608        self.id.is_focused(window)
609    }
610
611    /// Obtains whether the element associated with this handle contains the focused
612    /// element or is itself focused.
613    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
614        self.id.contains_focused(window, cx)
615    }
616
617    /// Obtains whether the element associated with this handle is contained within the
618    /// focused element or is itself focused.
619    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {
620        self.id.within_focused(window, cx)
621    }
622
623    /// Obtains whether this handle contains the given handle in the most recently rendered frame.
624    pub fn contains(&self, other: &Self, window: &Window) -> bool {
625        self.id.contains(other.id, window)
626    }
627
628    /// Dispatch an action on the element that rendered this focus handle
629    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {
630        if let Some(node_id) = window
631            .rendered_frame
632            .dispatch_tree
633            .focusable_node_id(self.id)
634        {
635            window.dispatch_action_on_node(node_id, action, cx)
636        }
637    }
638}
639
640impl Clone for FocusHandle {
641    fn clone(&self) -> Self {
642        Self::for_id(self.id, &self.handles).unwrap()
643    }
644}
645
646impl PartialEq for FocusHandle {
647    fn eq(&self, other: &Self) -> bool {
648        self.id == other.id
649    }
650}
651
652impl Eq for FocusHandle {}
653
654impl Drop for FocusHandle {
655    fn drop(&mut self) {
656        self.handles
657            .read()
658            .get(self.id)
659            .unwrap()
660            .ref_count
661            .fetch_sub(1, SeqCst);
662    }
663}
664
665/// A weak reference to a focus handle.
666#[derive(Clone, Debug)]
667pub struct WeakFocusHandle {
668    pub(crate) id: FocusId,
669    pub(crate) handles: Weak<FocusMap>,
670}
671
672impl WeakFocusHandle {
673    /// Attempts to upgrade the [WeakFocusHandle] to a [FocusHandle].
674    pub fn upgrade(&self) -> Option<FocusHandle> {
675        let handles = self.handles.upgrade()?;
676        FocusHandle::for_id(self.id, &handles)
677    }
678}
679
680impl PartialEq for WeakFocusHandle {
681    fn eq(&self, other: &WeakFocusHandle) -> bool {
682        self.id == other.id
683    }
684}
685
686impl Eq for WeakFocusHandle {}
687
688impl PartialEq<FocusHandle> for WeakFocusHandle {
689    fn eq(&self, other: &FocusHandle) -> bool {
690        self.id == other.id
691    }
692}
693
694impl PartialEq<WeakFocusHandle> for FocusHandle {
695    fn eq(&self, other: &WeakFocusHandle) -> bool {
696        self.id == other.id
697    }
698}
699
700/// Focusable allows users of your view to easily
701/// focus it (using window.focus_view(cx, view))
702pub trait Focusable: 'static {
703    /// Returns the focus handle associated with this view.
704    fn focus_handle(&self, cx: &App) -> FocusHandle;
705}
706
707impl<V: Focusable> Focusable for Entity<V> {
708    fn focus_handle(&self, cx: &App) -> FocusHandle {
709        self.read(cx).focus_handle(cx)
710    }
711}
712
713/// ManagedView is a view (like a Modal, Popover, Menu, etc.)
714/// where the lifecycle of the view is handled by another view.
715pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}
716
717impl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}
718
719/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.
720pub struct DismissEvent;
721
722type FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;
723
724pub(crate) type AnyMouseListener =
725    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
726
727#[derive(Clone)]
728pub(crate) struct CursorStyleRequest {
729    pub(crate) hitbox_id: Option<HitboxId>,
730    pub(crate) style: CursorStyle,
731}
732
733#[derive(Default, Eq, PartialEq)]
734pub(crate) struct HitTest {
735    pub(crate) ids: SmallVec<[HitboxId; 8]>,
736    pub(crate) hover_hitbox_count: usize,
737}
738
739/// A type of window control area that corresponds to the platform window.
740#[derive(Clone, Copy, Debug, Eq, PartialEq)]
741pub enum WindowControlArea {
742    /// An area that allows dragging of the platform window.
743    Drag,
744    /// An area that allows closing of the platform window.
745    Close,
746    /// An area that allows maximizing of the platform window.
747    Max,
748    /// An area that allows minimizing of the platform window.
749    Min,
750}
751
752/// An identifier for a [Hitbox] which also includes [HitboxBehavior].
753#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
754pub struct HitboxId(u64);
755
756#[cfg(feature = "test-support")]
757impl HitboxId {
758    /// A placeholder HitboxId exclusively for integration testing API's that
759    /// need a hitbox but where the value of the hitbox does not matter. The
760    /// alternative is to make the Hitbox optional but that complicates the
761    /// implementation.
762    pub const fn placeholder() -> Self {
763        Self(0)
764    }
765}
766
767impl HitboxId {
768    /// Checks if the hitbox with this ID is currently hovered. Returns `false` during keyboard
769    /// input modality so that keyboard navigation suppresses hover highlights. Except when handling
770    /// `ScrollWheelEvent`, this is typically what you want when determining whether to handle mouse
771    /// events or paint hover styles.
772    ///
773    /// See [`Hitbox::is_hovered`] for details.
774    pub fn is_hovered(self, window: &Window) -> bool {
775        // If this hitbox has captured the pointer, it's always considered hovered
776        if window.captured_hitbox == Some(self) {
777            return true;
778        }
779        if window.last_input_was_keyboard() {
780            return false;
781        }
782        self.hit_test(window)
783    }
784
785    /// Checks if the hitbox with this ID is currently hovered, regardless of the last
786    /// input modality used.
787    ///
788    /// See [`HitboxId::is_hovered`] for more details.
789    pub(crate) fn is_hovered_ignoring_last_input(self, window: &Window) -> bool {
790        // If this hitbox has captured the pointer, it's always considered hovered
791        if window.captured_hitbox == Some(self) {
792            return true;
793        }
794        self.hit_test(window)
795    }
796
797    fn hit_test(self, window: &Window) -> bool {
798        let hit_test = &window.mouse_hit_test;
799        for id in hit_test.ids.iter().take(hit_test.hover_hitbox_count) {
800            if self == *id {
801                return true;
802            }
803        }
804        false
805    }
806
807    /// Checks if the hitbox with this ID contains the mouse and should handle scroll events.
808    /// Typically this should only be used when handling `ScrollWheelEvent`, and otherwise
809    /// `is_hovered` should be used. See the documentation of `Hitbox::is_hovered` for details about
810    /// this distinction.
811    pub fn should_handle_scroll(self, window: &Window) -> bool {
812        window.mouse_hit_test.ids.contains(&self)
813    }
814
815    fn next(mut self) -> HitboxId {
816        HitboxId(self.0.wrapping_add(1))
817    }
818}
819
820/// A rectangular region that potentially blocks hitboxes inserted prior.
821/// See [Window::insert_hitbox] for more details.
822#[derive(Clone, Debug, Deref)]
823pub struct Hitbox {
824    /// A unique identifier for the hitbox.
825    pub id: HitboxId,
826    /// The bounds of the hitbox.
827    #[deref]
828    pub bounds: Bounds<Pixels>,
829    /// The content mask when the hitbox was inserted.
830    pub content_mask: ContentMask<Pixels>,
831    /// Flags that specify hitbox behavior.
832    pub behavior: HitboxBehavior,
833}
834
835impl Hitbox {
836    /// Checks if the hitbox is currently hovered. Returns `false` during keyboard input modality
837    /// so that keyboard navigation suppresses hover highlights. Except when handling
838    /// `ScrollWheelEvent`, this is typically what you want when determining whether to handle mouse
839    /// events or paint hover styles.
840    ///
841    /// This can return `false` even when the hitbox contains the mouse, if a hitbox in front of
842    /// this sets `HitboxBehavior::BlockMouse` (`InteractiveElement::occlude`) or
843    /// `HitboxBehavior::BlockMouseExceptScroll` (`InteractiveElement::block_mouse_except_scroll`),
844    /// or if the current input modality is keyboard (see [`Window::last_input_was_keyboard`]).
845    ///
846    /// Handling of `ScrollWheelEvent` should typically use `should_handle_scroll` instead.
847    /// Concretely, this is due to use-cases like overlays that cause the elements under to be
848    /// non-interactive while still allowing scrolling. More abstractly, this is because
849    /// `is_hovered` is about element interactions directly under the mouse - mouse moves, clicks,
850    /// hover styling, etc. In contrast, scrolling is about finding the current outer scrollable
851    /// container.
852    pub fn is_hovered(&self, window: &Window) -> bool {
853        self.id.is_hovered(window)
854    }
855
856    /// Checks if the hitbox contains the mouse and should handle scroll events. Typically this
857    /// should only be used when handling `ScrollWheelEvent`, and otherwise `is_hovered` should be
858    /// used. See the documentation of `Hitbox::is_hovered` for details about this distinction.
859    ///
860    /// This can return `false` even when the hitbox contains the mouse, if a hitbox in front of
861    /// this sets `HitboxBehavior::BlockMouse` (`InteractiveElement::occlude`).
862    pub fn should_handle_scroll(&self, window: &Window) -> bool {
863        self.id.should_handle_scroll(window)
864    }
865}
866
867/// How the hitbox affects mouse behavior.
868#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
869pub enum HitboxBehavior {
870    /// Normal hitbox mouse behavior, doesn't affect mouse handling for other hitboxes.
871    #[default]
872    Normal,
873
874    /// All hitboxes behind this hitbox will be ignored and so will have `hitbox.is_hovered() ==
875    /// false` and `hitbox.should_handle_scroll() == false`. Typically for elements this causes
876    /// skipping of all mouse events, hover styles, and tooltips. This flag is set by
877    /// [`InteractiveElement::occlude`].
878    ///
879    /// For mouse handlers that check those hitboxes, this behaves the same as registering a
880    /// bubble-phase handler for every mouse event type:
881    ///
882    /// ```ignore
883    /// window.on_mouse_event(move |_: &EveryMouseEventTypeHere, phase, window, cx| {
884    ///     if phase == DispatchPhase::Capture && hitbox.is_hovered(window) {
885    ///         cx.stop_propagation();
886    ///     }
887    /// })
888    /// ```
889    ///
890    /// This has effects beyond event handling - any use of hitbox checking, such as hover
891    /// styles and tooltips. These other behaviors are the main point of this mechanism. An
892    /// alternative might be to not affect mouse event handling - but this would allow
893    /// inconsistent UI where clicks and moves interact with elements that are not considered to
894    /// be hovered.
895    BlockMouse,
896
897    /// All hitboxes behind this hitbox will have `hitbox.is_hovered() == false`, even when
898    /// `hitbox.should_handle_scroll() == true`. Typically for elements this causes all mouse
899    /// interaction except scroll events to be ignored - see the documentation of
900    /// [`Hitbox::is_hovered`] for details. This flag is set by
901    /// [`InteractiveElement::block_mouse_except_scroll`].
902    ///
903    /// For mouse handlers that check those hitboxes, this behaves the same as registering a
904    /// bubble-phase handler for every mouse event type **except** `ScrollWheelEvent`:
905    ///
906    /// ```ignore
907    /// window.on_mouse_event(move |_: &EveryMouseEventTypeExceptScroll, phase, window, cx| {
908    ///     if phase == DispatchPhase::Bubble && hitbox.should_handle_scroll(window) {
909    ///         cx.stop_propagation();
910    ///     }
911    /// })
912    /// ```
913    ///
914    /// See the documentation of [`Hitbox::is_hovered`] for details of why `ScrollWheelEvent` is
915    /// handled differently than other mouse events. If also blocking these scroll events is
916    /// desired, then a `cx.stop_propagation()` handler like the one above can be used.
917    ///
918    /// This has effects beyond event handling - this affects any use of `is_hovered`, such as
919    /// hover styles and tooltips. These other behaviors are the main point of this mechanism.
920    /// An alternative might be to not affect mouse event handling - but this would allow
921    /// inconsistent UI where clicks and moves interact with elements that are not considered to
922    /// be hovered.
923    BlockMouseExceptScroll,
924}
925
926/// An identifier for a tooltip.
927#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
928pub struct TooltipId(usize);
929
930impl TooltipId {
931    /// Checks if the tooltip is currently hovered.
932    pub fn is_hovered(&self, window: &Window) -> bool {
933        window
934            .tooltip_bounds
935            .as_ref()
936            .is_some_and(|tooltip_bounds| {
937                tooltip_bounds.id == *self
938                    && tooltip_bounds.bounds.contains(&window.mouse_position())
939            })
940    }
941}
942
943pub(crate) struct TooltipBounds {
944    id: TooltipId,
945    bounds: Bounds<Pixels>,
946}
947
948#[derive(Clone)]
949pub(crate) struct TooltipRequest {
950    id: TooltipId,
951    tooltip: AnyTooltip,
952}
953
954pub(crate) struct DeferredDraw {
955    current_view: EntityId,
956    priority: usize,
957    parent_node: DispatchNodeId,
958    element_id_stack: SmallVec<[ElementId; 32]>,
959    text_style_stack: Vec<TextStyleRefinement>,
960    content_mask: Option<ContentMask<Pixels>>,
961    rem_size: Pixels,
962    element: Option<AnyElement>,
963    absolute_offset: Point<Pixels>,
964    prepaint_range: Range<PrepaintStateIndex>,
965    paint_range: Range<PaintIndex>,
966}
967
968pub(crate) struct Frame {
969    pub(crate) focus: Option<FocusId>,
970    pub(crate) window_active: bool,
971    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
972    accessed_element_states: Vec<(GlobalElementId, TypeId)>,
973    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
974    pub(crate) dispatch_tree: DispatchTree,
975    pub(crate) scene: Scene,
976    pub(crate) hitboxes: Vec<Hitbox>,
977    pub(crate) window_control_hitboxes: Vec<(WindowControlArea, Hitbox)>,
978    pub(crate) deferred_draws: Vec<DeferredDraw>,
979    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
980    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,
981    pub(crate) cursor_styles: Vec<CursorStyleRequest>,
982    #[cfg(any(test, feature = "test-support"))]
983    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
984    #[cfg(any(feature = "inspector", debug_assertions))]
985    pub(crate) next_inspector_instance_ids: FxHashMap<Rc<crate::InspectorElementPath>, usize>,
986    #[cfg(any(feature = "inspector", debug_assertions))]
987    pub(crate) inspector_hitboxes: FxHashMap<HitboxId, crate::InspectorElementId>,
988    pub(crate) tab_stops: TabStopMap,
989}
990
991#[derive(Clone, Default)]
992pub(crate) struct PrepaintStateIndex {
993    hitboxes_index: usize,
994    tooltips_index: usize,
995    deferred_draws_index: usize,
996    dispatch_tree_index: usize,
997    accessed_element_states_index: usize,
998    line_layout_index: LineLayoutIndex,
999}
1000
1001#[derive(Clone, Default)]
1002pub(crate) struct PaintIndex {
1003    scene_index: usize,
1004    mouse_listeners_index: usize,
1005    input_handlers_index: usize,
1006    cursor_styles_index: usize,
1007    accessed_element_states_index: usize,
1008    tab_handle_index: usize,
1009    line_layout_index: LineLayoutIndex,
1010}
1011
1012impl Frame {
1013    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
1014        Frame {
1015            focus: None,
1016            window_active: false,
1017            element_states: FxHashMap::default(),
1018            accessed_element_states: Vec::new(),
1019            mouse_listeners: Vec::new(),
1020            dispatch_tree,
1021            scene: Scene::default(),
1022            hitboxes: Vec::new(),
1023            window_control_hitboxes: Vec::new(),
1024            deferred_draws: Vec::new(),
1025            input_handlers: Vec::new(),
1026            tooltip_requests: Vec::new(),
1027            cursor_styles: Vec::new(),
1028
1029            #[cfg(any(test, feature = "test-support"))]
1030            debug_bounds: FxHashMap::default(),
1031
1032            #[cfg(any(feature = "inspector", debug_assertions))]
1033            next_inspector_instance_ids: FxHashMap::default(),
1034
1035            #[cfg(any(feature = "inspector", debug_assertions))]
1036            inspector_hitboxes: FxHashMap::default(),
1037            tab_stops: TabStopMap::default(),
1038        }
1039    }
1040
1041    pub(crate) fn clear(&mut self) {
1042        self.element_states.clear();
1043        self.accessed_element_states.clear();
1044        self.mouse_listeners.clear();
1045        self.dispatch_tree.clear();
1046        self.scene.clear();
1047        self.input_handlers.clear();
1048        self.tooltip_requests.clear();
1049        self.cursor_styles.clear();
1050        self.hitboxes.clear();
1051        self.window_control_hitboxes.clear();
1052        self.deferred_draws.clear();
1053        self.tab_stops.clear();
1054        self.focus = None;
1055
1056        #[cfg(any(test, feature = "test-support"))]
1057        {
1058            self.debug_bounds.clear();
1059        }
1060
1061        #[cfg(any(feature = "inspector", debug_assertions))]
1062        {
1063            self.next_inspector_instance_ids.clear();
1064            self.inspector_hitboxes.clear();
1065        }
1066    }
1067
1068    pub(crate) fn cursor_style(&self, window: &Window) -> Option<CursorStyle> {
1069        self.cursor_styles
1070            .iter()
1071            .rev()
1072            .fold_while(None, |style, request| match request.hitbox_id {
1073                None => Done(Some(request.style)),
1074                Some(hitbox_id) => Continue(style.or_else(|| {
1075                    hitbox_id
1076                        .is_hovered_ignoring_last_input(window)
1077                        .then_some(request.style)
1078                })),
1079            })
1080            .into_inner()
1081    }
1082
1083    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
1084        let mut set_hover_hitbox_count = false;
1085        let mut hit_test = HitTest::default();
1086        for hitbox in self.hitboxes.iter().rev() {
1087            let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);
1088            if bounds.contains(&position) {
1089                hit_test.ids.push(hitbox.id);
1090                if !set_hover_hitbox_count
1091                    && hitbox.behavior == HitboxBehavior::BlockMouseExceptScroll
1092                {
1093                    hit_test.hover_hitbox_count = hit_test.ids.len();
1094                    set_hover_hitbox_count = true;
1095                }
1096                if hitbox.behavior == HitboxBehavior::BlockMouse {
1097                    break;
1098                }
1099            }
1100        }
1101        if !set_hover_hitbox_count {
1102            hit_test.hover_hitbox_count = hit_test.ids.len();
1103        }
1104        hit_test
1105    }
1106
1107    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
1108        self.focus
1109            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
1110            .unwrap_or_default()
1111    }
1112
1113    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
1114        for element_state_key in &self.accessed_element_states {
1115            if let Some((element_state_key, element_state)) =
1116                prev_frame.element_states.remove_entry(element_state_key)
1117            {
1118                self.element_states.insert(element_state_key, element_state);
1119            }
1120        }
1121
1122        self.scene.finish();
1123    }
1124}
1125
1126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
1127enum InputModality {
1128    Mouse,
1129    Keyboard,
1130    Touch,
1131}
1132
1133/// Holds the state for a specific window.
1134pub struct Window {
1135    pub(crate) handle: AnyWindowHandle,
1136    pub(crate) invalidator: WindowInvalidator,
1137    pub(crate) removed: bool,
1138    pub(crate) platform_window: Box<dyn PlatformWindow>,
1139    display_id: Option<DisplayId>,
1140    is_resizable: bool,
1141    is_minimizable: bool,
1142    sprite_atlas: Arc<dyn PlatformAtlas>,
1143    text_system: Arc<WindowTextSystem>,
1144    text_rendering_mode: Rc<Cell<TextRenderingMode>>,
1145    rem_size: Pixels,
1146    /// The stack of override values for the window's rem size.
1147    ///
1148    /// This is used by `with_rem_size` to allow rendering an element tree with
1149    /// a given rem size.
1150    rem_size_override_stack: SmallVec<[Pixels; 8]>,
1151    pub(crate) viewport_size: Size<Pixels>,
1152    layout_engine: Option<TaffyLayoutEngine>,
1153    pub(crate) root: Option<AnyView>,
1154    pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,
1155    pub(crate) text_style_stack: Vec<TextStyleRefinement>,
1156    pub(crate) rendered_entity_stack: Vec<EntityId>,
1157    pub(crate) element_offset_stack: Vec<Point<Pixels>>,
1158    pub(crate) element_opacity: f32,
1159    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
1160    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,
1161    /// The [`TextInputConfiguration`] most recently forwarded to the platform
1162    /// window, so that only actual changes are forwarded (reconfiguring a live
1163    /// input session can restart the IME connection).
1164    last_text_input_configuration: Option<TextInputConfiguration>,
1165    focused_text_input_active: bool,
1166    pub(crate) image_cache_stack: Vec<AnyImageCache>,
1167    pub(crate) rendered_frame: Frame,
1168    pub(crate) next_frame: Frame,
1169    next_hitbox_id: HitboxId,
1170    pub(crate) next_tooltip_id: TooltipId,
1171    pub(crate) tooltip_bounds: Option<TooltipBounds>,
1172    pub(crate) next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
1173    pub(crate) dirty_views: FxHashSet<EntityId>,
1174    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
1175    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,
1176    focus_lost_path: SmallVec<[FocusId; 8]>,
1177    default_prevented: bool,
1178    mouse_position: Point<Pixels>,
1179    mouse_hit_test: HitTest,
1180    modifiers: Modifiers,
1181    capslock: Capslock,
1182    scale_factor: f32,
1183    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
1184    appearance: WindowAppearance,
1185    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,
1186    pub(crate) button_layout_observers: SubscriberSet<(), AnyObserver>,
1187    active: Rc<Cell<bool>>,
1188    hovered: Rc<Cell<bool>>,
1189    pub(crate) needs_present: Rc<Cell<bool>>,
1190    /// Tracks recent input event timestamps to determine if input is arriving at a high rate.
1191    /// Used to selectively enable VRR optimization only when input rate exceeds 60fps.
1192    pub(crate) input_rate_tracker: Rc<RefCell<InputRateTracker>>,
1193    #[cfg(feature = "profiler")]
1194    window_profiler: profiler::WindowProfiler,
1195    last_input_modality: InputModality,
1196    touch_gestures: TouchGestureRecognizer,
1197    touch_prediction_enabled: bool,
1198    long_press_timer: Option<Task<()>>,
1199    long_press_capture: Option<EntityId>,
1200    pub(crate) refreshing: bool,
1201    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,
1202    pub(crate) focus: Option<FocusId>,
1203    focus_enabled: bool,
1204    /// Incremented every time focus moves. Used to invalidate a
1205    /// pending keyboard activation state when focus changes.
1206    pub(crate) focus_generation: u64,
1207    pending_input: Option<PendingInput>,
1208    pending_modifier: ModifierState,
1209    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,
1210    prompt: Option<RenderablePromptHandle>,
1211    pub(crate) client_inset: Option<Pixels>,
1212    /// The hitbox that has captured the pointer, if any.
1213    /// While captured, mouse events route to this hitbox regardless of hit testing.
1214    captured_hitbox: Option<HitboxId>,
1215    #[cfg(any(feature = "inspector", debug_assertions))]
1216    inspector: Option<Entity<Inspector>>,
1217    #[cfg(feature = "profiler")]
1218    debug_frame_overlay: crate::debug_overlay::DebugFrameOverlay,
1219    pub(crate) a11y: A11y,
1220}
1221
1222#[derive(Clone, Debug, Default)]
1223struct ModifierState {
1224    modifiers: Modifiers,
1225    saw_other_input: bool,
1226}
1227
1228/// Tracks input event timestamps to determine if input is arriving at a high rate.
1229/// Used for selective VRR (Variable Refresh Rate) optimization.
1230#[derive(Clone, Debug)]
1231pub(crate) struct InputRateTracker {
1232    timestamps: Vec<Instant>,
1233    window: Duration,
1234    inputs_per_second: u32,
1235    sustain_until: Instant,
1236    sustain_duration: Duration,
1237}
1238
1239impl Default for InputRateTracker {
1240    fn default() -> Self {
1241        Self {
1242            timestamps: Vec::new(),
1243            window: Duration::from_millis(100),
1244            inputs_per_second: 60,
1245            sustain_until: Instant::now(),
1246            sustain_duration: Duration::from_secs(1),
1247        }
1248    }
1249}
1250
1251impl InputRateTracker {
1252    pub fn record_input(&mut self) {
1253        let now = Instant::now();
1254        self.timestamps.push(now);
1255        self.prune_old_timestamps(now);
1256
1257        let min_events = self.inputs_per_second as u128 * self.window.as_millis() / 1000;
1258        if self.timestamps.len() as u128 >= min_events {
1259            self.sustain_until = now + self.sustain_duration;
1260        }
1261    }
1262
1263    pub fn is_high_rate(&self) -> bool {
1264        Instant::now() < self.sustain_until
1265    }
1266
1267    fn prune_old_timestamps(&mut self, now: Instant) {
1268        self.timestamps
1269            .retain(|&t| now.duration_since(t) <= self.window);
1270    }
1271}
1272
1273#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1274pub(crate) enum DrawPhase {
1275    None,
1276    Prepaint,
1277    Paint,
1278    Focus,
1279}
1280
1281#[derive(Default, Debug)]
1282struct PendingInput {
1283    keystrokes: SmallVec<[Keystroke; 1]>,
1284    focus: Option<FocusId>,
1285    timer: Option<Task<()>>,
1286    needs_timeout: bool,
1287}
1288
1289pub(crate) struct ElementStateBox {
1290    pub(crate) inner: Box<dyn Any>,
1291    #[cfg(debug_assertions)]
1292    pub(crate) type_name: &'static str,
1293}
1294
1295fn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> WindowBounds {
1296    // TODO, BUG: if you open a window with the currently active window
1297    // on the stack, this will erroneously fallback to `None`
1298    //
1299    // TODO these should be the initial window bounds not considering maximized/fullscreen
1300    let active_window_bounds = cx
1301        .active_window()
1302        .and_then(|w| w.update(cx, |_, window, _| window.window_bounds()).ok());
1303
1304    const CASCADE_OFFSET: f32 = 25.0;
1305
1306    let display = display_id
1307        .map(|id| cx.find_display(id))
1308        .unwrap_or_else(|| cx.primary_display());
1309
1310    let default_placement = || Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE);
1311
1312    // Use visible_bounds to exclude taskbar/dock areas
1313    let display_bounds = display
1314        .as_ref()
1315        .map(|d| d.visible_bounds())
1316        .unwrap_or_else(default_placement);
1317
1318    let (
1319        Bounds {
1320            origin: base_origin,
1321            size: base_size,
1322        },
1323        window_bounds_ctor,
1324    ): (_, fn(Bounds<Pixels>) -> WindowBounds) = match active_window_bounds {
1325        Some(bounds) => match bounds {
1326            WindowBounds::Windowed(bounds) => (bounds, WindowBounds::Windowed),
1327            WindowBounds::Maximized(bounds) => (bounds, WindowBounds::Maximized),
1328            WindowBounds::Fullscreen(bounds) => (bounds, WindowBounds::Fullscreen),
1329        },
1330        None => (
1331            display
1332                .as_ref()
1333                .map(|d| d.default_bounds())
1334                .unwrap_or_else(default_placement),
1335            WindowBounds::Windowed,
1336        ),
1337    };
1338
1339    let cascade_offset = point(px(CASCADE_OFFSET), px(CASCADE_OFFSET));
1340    let proposed_origin = base_origin + cascade_offset;
1341    let proposed_bounds = Bounds::new(proposed_origin, base_size);
1342
1343    let display_right = display_bounds.origin.x + display_bounds.size.width;
1344    let display_bottom = display_bounds.origin.y + display_bounds.size.height;
1345    let window_right = proposed_bounds.origin.x + proposed_bounds.size.width;
1346    let window_bottom = proposed_bounds.origin.y + proposed_bounds.size.height;
1347
1348    let fits_horizontally = window_right <= display_right;
1349    let fits_vertically = window_bottom <= display_bottom;
1350
1351    let final_origin = match (fits_horizontally, fits_vertically) {
1352        (true, true) => proposed_origin,
1353        (false, true) => point(display_bounds.origin.x, base_origin.y),
1354        (true, false) => point(base_origin.x, display_bounds.origin.y),
1355        (false, false) => display_bounds.origin,
1356    };
1357    window_bounds_ctor(Bounds::new(final_origin, base_size))
1358}
1359
1360impl Window {
1361    pub(crate) fn new(
1362        handle: AnyWindowHandle,
1363        options: WindowOptions,
1364        cx: &mut App,
1365    ) -> Result<Self> {
1366        let WindowOptions {
1367            window_bounds,
1368            titlebar,
1369            focus,
1370            show,
1371            kind,
1372            is_movable,
1373            app_owns_titlebar_drag,
1374            inactive_frame_interval,
1375            is_resizable,
1376            is_minimizable,
1377            display_id,
1378            window_background,
1379            app_id,
1380            window_min_size,
1381            window_decorations,
1382            #[cfg_attr(
1383                not(any(target_os = "linux", target_os = "freebsd")),
1384                allow(unused_variables)
1385            )]
1386            icon,
1387            #[cfg_attr(not(target_os = "macos"), allow(unused_variables))]
1388            tabbing_identifier,
1389        } = options;
1390
1391        let initial_window_title = titlebar
1392            .as_ref()
1393            .and_then(|titlebar| titlebar.title.clone());
1394
1395        let window_bounds = window_bounds.unwrap_or_else(|| default_bounds(display_id, cx));
1396        let mut platform_window = cx.platform.open_window(
1397            handle,
1398            WindowParams {
1399                bounds: window_bounds.get_bounds(),
1400                titlebar,
1401                kind,
1402                is_movable,
1403                app_owns_titlebar_drag,
1404                is_resizable,
1405                is_minimizable,
1406                focus,
1407                show,
1408                display_id,
1409                window_min_size,
1410                app_id: app_id.clone(),
1411                icon,
1412                #[cfg(target_os = "macos")]
1413                tabbing_identifier,
1414            },
1415        )?;
1416
1417        let tab_bar_visible = platform_window.tab_bar_visible();
1418        SystemWindowTabController::init_visible(cx, tab_bar_visible);
1419        if let Some(tabs) = platform_window.tabbed_windows() {
1420            SystemWindowTabController::add_tab(cx, handle.window_id(), tabs);
1421        }
1422
1423        let display_id = platform_window.display().map(|display| display.id());
1424        let sprite_atlas = platform_window.sprite_atlas();
1425        let mouse_position = platform_window.mouse_position();
1426        let modifiers = platform_window.modifiers();
1427        let capslock = platform_window.capslock();
1428        let content_size = platform_window.content_size();
1429        let scale_factor = platform_window.scale_factor();
1430        let appearance = platform_window.appearance();
1431        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
1432        let invalidator = WindowInvalidator::new(handle.window_id());
1433        let active = Rc::new(Cell::new(platform_window.is_active()));
1434        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));
1435        let needs_present = Rc::new(Cell::new(false));
1436        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
1437        let input_rate_tracker = Rc::new(RefCell::new(InputRateTracker::default()));
1438        let last_frame_time = Rc::new(Cell::new(None));
1439
1440        platform_window
1441            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));
1442        platform_window.set_background_appearance(window_background);
1443
1444        match window_bounds {
1445            WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),
1446            WindowBounds::Maximized(_) => platform_window.zoom(),
1447            WindowBounds::Windowed(_) => {}
1448        }
1449
1450        let accessibility_force_disabled = cx.accessibility_force_disabled;
1451        let a11y_active_flag = Arc::new(AtomicBool::new(false));
1452
1453        #[cfg(not(target_family = "wasm"))]
1454        if !accessibility_force_disabled {
1455            let mut initial_root_node = accesskit::Node::new(accesskit::Role::Window);
1456            if let Some(title) = &initial_window_title {
1457                initial_root_node.set_label(title.to_string());
1458            }
1459            let initial_tree = accesskit::TreeUpdate {
1460                nodes: vec![(ROOT_NODE_ID, initial_root_node)],
1461                tree: Some(accesskit::Tree::new(ROOT_NODE_ID)),
1462                tree_id: accesskit::TreeId::ROOT,
1463                focus: ROOT_NODE_ID,
1464            };
1465            let (activation_sender, activation_receiver) = async_channel::unbounded::<()>();
1466            let (deactivation_sender, deactivation_receiver) = async_channel::unbounded::<()>();
1467            let (action_sender, action_receiver) =
1468                async_channel::unbounded::<accesskit::ActionRequest>();
1469
1470            platform_window.a11y_init(crate::A11yCallbacks {
1471                activation: {
1472                    let active_flag = a11y_active_flag.clone();
1473                    Box::new(move || {
1474                        log::info!("Accessibility activated");
1475                        active_flag.store(true, SeqCst);
1476                        activation_sender.send_blocking(()).log_err();
1477                        Some(initial_tree.clone())
1478                    })
1479                },
1480                action: Box::new(move |request| {
1481                    action_sender.send_blocking(request).log_err();
1482                }),
1483                deactivation: {
1484                    let active_flag = a11y_active_flag.clone();
1485                    Box::new(move || {
1486                        log::info!("Accessibility deactivated");
1487                        active_flag.store(false, SeqCst);
1488                        deactivation_sender.send_blocking(()).log_err();
1489                    })
1490                },
1491            });
1492
1493            // A11y can be activated at any time, and so we cannot compute a
1494            // correct `TreeUpdate` on-demand. When this happens, we return a
1495            // default empty `TreeUpdate`.
1496            //
1497            // So we force a new frame, which will then send a correct `TreeUpdate`.
1498            let mut async_cx = cx.to_async();
1499            cx.foreground_executor()
1500                .spawn(async move {
1501                    while activation_receiver.recv().await.is_ok() {
1502                        handle
1503                            .update(&mut async_cx, |_, window, _| window.refresh())
1504                            .log_err();
1505                    }
1506                })
1507                .detach();
1508
1509            let mut async_cx = cx.to_async();
1510            cx.foreground_executor()
1511                .spawn(async move {
1512                    while deactivation_receiver.recv().await.is_ok() {
1513                        handle
1514                            .update(&mut async_cx, |_, window, _| window.refresh())
1515                            .log_err();
1516                    }
1517                })
1518                .detach();
1519
1520            let mut async_cx = cx.to_async();
1521            cx.foreground_executor()
1522                .spawn(async move {
1523                    while let Ok(request) = action_receiver.recv().await {
1524                        handle
1525                            .update(&mut async_cx, |_, window, cx| {
1526                                window.handle_a11y_action(request, cx);
1527                            })
1528                            .log_err();
1529                    }
1530                })
1531                .detach();
1532        }
1533
1534        platform_window.on_close(Box::new({
1535            let window_id = handle.window_id();
1536            let mut cx = cx.to_async();
1537            move || {
1538                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());
1539                let _ = cx.update(|cx| {
1540                    SystemWindowTabController::remove_tab(cx, window_id);
1541                });
1542            }
1543        }));
1544        platform_window.on_request_frame(Box::new({
1545            let mut cx = cx.to_async();
1546            let invalidator = invalidator.clone();
1547            let active = active.clone();
1548            let needs_present = needs_present.clone();
1549            let next_frame_callbacks = next_frame_callbacks.clone();
1550            let input_rate_tracker = input_rate_tracker.clone();
1551            let mut deferred_force_render = false;
1552            move |request_frame_options| {
1553                #[cfg(feature = "profiler")]
1554                let _foreground_turn = profiler::journal::foreground_turn();
1555                // This must be checked before anything else: if this request
1556                // arrived re-entrantly while a draw is on this thread's stack
1557                // (e.g. via a nested message pump in the Windows window
1558                // procedure), drawing would nest draws, and even touching the
1559                // App would panic on its already-mutable borrow. Skip instead;
1560                // the platform leaves the window invalidated (or re-invalidates
1561                // it), so a fresh request arrives once the in-progress draw
1562                // unwinds. Remember force_render so the deferred frame still
1563                // bypasses the view cache.
1564                //
1565                // Returning here skips `complete_frame`, which on Wayland would
1566                // stall the window's frame callbacks (no `surface.commit()`) —
1567                // but calling it would hit the App borrow panic above, and this
1568                // branch is unreachable there in practice: only Windows pumps
1569                // platform events (and thus requests frames) mid-draw.
1570                if draw_in_progress() {
1571                    log::debug!("deferring re-entrant window draw request");
1572                    deferred_force_render |= request_frame_options.force_render;
1573                    return;
1574                }
1575                // Take the deferred flag first: `||` short-circuits, and leaving
1576                // the flag set when this request already forces a render would
1577                // force a second, redundant render on the next frame.
1578                let force_render =
1579                    mem::take(&mut deferred_force_render) || request_frame_options.force_render;
1580
1581                let thermal_state = handle
1582                    .update(&mut cx, |_, _, cx| cx.thermal_state())
1583                    .log_err();
1584
1585                // Throttle frame rate based on conditions:
1586                // - Thermal pressure (Serious/Critical): cap to ~60fps
1587                // - Inactive window (not focused): cap to ~30fps to save energy
1588                let min_frame_interval = if request_frame_options.require_presentation
1589                    || (!request_frame_options.force_render
1590                        && next_frame_callbacks.borrow().is_empty())
1591                {
1592                    None
1593                } else if !active.get() && !input_rate_tracker.borrow_mut().is_high_rate() {
1594                    inactive_frame_interval
1595                } else if let Some(ThermalState::Critical | ThermalState::Serious) = thermal_state {
1596                    Some(Duration::from_micros(16667))
1597                } else {
1598                    None
1599                };
1600
1601                let now = Instant::now();
1602                if let Some(min_interval) = min_frame_interval {
1603                    if let Some(last_frame) = last_frame_time.get()
1604                        && now.duration_since(last_frame) < min_interval
1605                    {
1606                        // Don't lose a pending forced render to throttling.
1607                        deferred_force_render |= force_render;
1608                        // Deferred by throttling: ask demand-driven platforms to retry.
1609                        handle
1610                            .update(&mut cx, |_, window, _| {
1611                                window.platform_window.schedule_frame();
1612                            })
1613                            .log_err();
1614                        // The demand that entered this branch (a deferred forced
1615                        // render or pending next-frame callbacks) is still
1616                        // unserved; platforms that stop requesting frames for
1617                        // idle windows need a wakeup to deliver the retry.
1618                        invalidator.wake_platform();
1619                        return;
1620                    }
1621                }
1622                last_frame_time.set(Some(now));
1623
1624                let pending_next_frame_callbacks = next_frame_callbacks.take();
1625                if !pending_next_frame_callbacks.is_empty() {
1626                    handle
1627                        .update(&mut cx, |_, window, cx| {
1628                            for callback in pending_next_frame_callbacks {
1629                                callback(window, cx);
1630                            }
1631                        })
1632                        .log_err();
1633                }
1634
1635                // Keep presenting if input was recently arriving at a high rate (>= 60fps).
1636                // Once high-rate input is detected, we sustain presentation for 1 second
1637                // to prevent display underclocking during active input.
1638                let needs_present = request_frame_options.require_presentation
1639                    || needs_present.get()
1640                    || input_rate_tracker.borrow_mut().is_high_rate();
1641
1642                if invalidator.is_dirty() || force_render {
1643                    measure("frame duration", || {
1644                        handle
1645                            .update(&mut cx, |_, window, cx| {
1646                                if force_render {
1647                                    // Bypass cached view reuse so we don't replay stale
1648                                    // atlas tile references after a GPU device recovery.
1649                                    window.refresh();
1650                                }
1651                                let arena_clear_needed = window.draw(cx);
1652                                window.present();
1653                                arena_clear_needed.clear(cx);
1654                            })
1655                            .log_err();
1656                    })
1657                } else if needs_present {
1658                    handle
1659                        .update(&mut cx, |_, window, _| window.present())
1660                        .log_err();
1661                }
1662
1663                handle
1664                    .update(&mut cx, |_, window, _| {
1665                        if window.invalidator.is_dirty()
1666                            || !window.next_frame_callbacks.borrow().is_empty()
1667                        {
1668                            window.platform_window.schedule_frame();
1669                        }
1670                    })
1671                    .log_err();
1672
1673                // Platforms that stop requesting frames for idle windows only
1674                // deliver another request after a wakeup. If demand remains
1675                // after this frame (the window was re-invalidated mid-draw, or
1676                // animations scheduled next-frame callbacks), re-arm the frame
1677                // source explicitly.
1678                if invalidator.is_dirty() || !next_frame_callbacks.borrow().is_empty() {
1679                    invalidator.wake_platform();
1680                }
1681            }
1682        }));
1683        invalidator.set_platform_waker(platform_window.frame_waker());
1684        platform_window.on_resize(Box::new({
1685            let mut cx = cx.to_async();
1686            move |_, _| {
1687                handle
1688                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1689                    .log_err();
1690            }
1691        }));
1692        platform_window.on_moved(Box::new({
1693            let mut cx = cx.to_async();
1694            move || {
1695                handle
1696                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1697                    .log_err();
1698            }
1699        }));
1700        platform_window.on_appearance_changed(Box::new({
1701            let cx = cx.to_async();
1702            let foreground_executor = cx.foreground_executor().clone();
1703            move || {
1704                let mut cx = cx.clone();
1705                // Defer the update because changing the AppKit appearance may
1706                // synchronously invoke this callback while App is already borrowed.
1707                foreground_executor
1708                    .spawn(async move {
1709                        handle
1710                            .update(&mut cx, |_, window, cx| window.appearance_changed(cx))
1711                            .log_err();
1712                    })
1713                    .detach();
1714            }
1715        }));
1716        platform_window.on_button_layout_changed(Box::new({
1717            let mut cx = cx.to_async();
1718            move || {
1719                handle
1720                    .update(&mut cx, |_, window, cx| window.button_layout_changed(cx))
1721                    .log_err();
1722            }
1723        }));
1724        platform_window.on_active_status_change(Box::new({
1725            let mut cx = cx.to_async();
1726            move |active| {
1727                handle
1728                    .update(&mut cx, |_, window, cx| {
1729                        window.active.set(active);
1730                        window.modifiers = window.platform_window.modifiers();
1731                        window.capslock = window.platform_window.capslock();
1732                        window
1733                            .activation_observers
1734                            .clone()
1735                            .retain(&(), |callback| callback(window, cx));
1736
1737                        window.bounds_changed(cx);
1738                        window.refresh();
1739
1740                        SystemWindowTabController::update_last_active(cx, window.handle.id);
1741                    })
1742                    .log_err();
1743            }
1744        }));
1745        platform_window.on_hover_status_change(Box::new({
1746            let mut cx = cx.to_async();
1747            move |active| {
1748                handle
1749                    .update(&mut cx, |_, window, _| {
1750                        window.hovered.set(active);
1751                        window.refresh();
1752                    })
1753                    .log_err();
1754            }
1755        }));
1756        platform_window.on_input({
1757            let mut cx = cx.to_async();
1758            Box::new(move |event| {
1759                handle
1760                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))
1761                    .log_err()
1762                    .unwrap_or(DispatchEventResult::default())
1763            })
1764        });
1765        platform_window.on_hit_test_window_control({
1766            let mut cx = cx.to_async();
1767            Box::new(move || {
1768                handle
1769                    .update(&mut cx, |_, window, _cx| {
1770                        for (area, hitbox) in &window.rendered_frame.window_control_hitboxes {
1771                            if window.mouse_hit_test.ids.contains(&hitbox.id) {
1772                                return Some(*area);
1773                            }
1774                        }
1775                        None
1776                    })
1777                    .log_err()
1778                    .unwrap_or(None)
1779            })
1780        });
1781        platform_window.on_move_tab_to_new_window({
1782            let mut cx = cx.to_async();
1783            Box::new(move || {
1784                handle
1785                    .update(&mut cx, |_, _window, cx| {
1786                        SystemWindowTabController::move_tab_to_new_window(cx, handle.window_id());
1787                    })
1788                    .log_err();
1789            })
1790        });
1791        platform_window.on_merge_all_windows({
1792            let mut cx = cx.to_async();
1793            Box::new(move || {
1794                handle
1795                    .update(&mut cx, |_, _window, cx| {
1796                        SystemWindowTabController::merge_all_windows(cx, handle.window_id());
1797                    })
1798                    .log_err();
1799            })
1800        });
1801        platform_window.on_select_next_tab({
1802            let mut cx = cx.to_async();
1803            Box::new(move || {
1804                handle
1805                    .update(&mut cx, |_, _window, cx| {
1806                        SystemWindowTabController::select_next_tab(cx, handle.window_id());
1807                    })
1808                    .log_err();
1809            })
1810        });
1811        platform_window.on_select_previous_tab({
1812            let mut cx = cx.to_async();
1813            Box::new(move || {
1814                handle
1815                    .update(&mut cx, |_, _window, cx| {
1816                        SystemWindowTabController::select_previous_tab(cx, handle.window_id())
1817                    })
1818                    .log_err();
1819            })
1820        });
1821        platform_window.on_toggle_tab_bar({
1822            let mut cx = cx.to_async();
1823            Box::new(move || {
1824                handle
1825                    .update(&mut cx, |_, window, cx| {
1826                        let tab_bar_visible = window.platform_window.tab_bar_visible();
1827                        SystemWindowTabController::set_visible(cx, tab_bar_visible);
1828                    })
1829                    .log_err();
1830            })
1831        });
1832
1833        if let Some(app_id) = app_id {
1834            platform_window.set_app_id(&app_id);
1835        }
1836
1837        platform_window.map_window().unwrap();
1838
1839        Ok(Window {
1840            handle,
1841            invalidator,
1842            removed: false,
1843            platform_window,
1844            display_id,
1845            is_resizable,
1846            is_minimizable,
1847            sprite_atlas,
1848            text_system,
1849            text_rendering_mode: cx.text_rendering_mode.clone(),
1850            rem_size: px(16.),
1851            rem_size_override_stack: SmallVec::new(),
1852            viewport_size: content_size,
1853            layout_engine: Some(TaffyLayoutEngine::new()),
1854            root: None,
1855            element_id_stack: SmallVec::default(),
1856            text_style_stack: Vec::new(),
1857            rendered_entity_stack: Vec::new(),
1858            element_offset_stack: Vec::new(),
1859            content_mask_stack: Vec::new(),
1860            element_opacity: 1.0,
1861            requested_autoscroll: None,
1862            last_text_input_configuration: None,
1863            focused_text_input_active: false,
1864            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1865            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1866            next_frame_callbacks,
1867            next_hitbox_id: HitboxId(0),
1868            next_tooltip_id: TooltipId::default(),
1869            tooltip_bounds: None,
1870            dirty_views: FxHashSet::default(),
1871            focus_listeners: SubscriberSet::new(),
1872            focus_lost_listeners: SubscriberSet::new(),
1873            focus_lost_path: SmallVec::new(),
1874            default_prevented: true,
1875            mouse_position,
1876            mouse_hit_test: HitTest::default(),
1877            modifiers,
1878            capslock,
1879            scale_factor,
1880            bounds_observers: SubscriberSet::new(),
1881            appearance,
1882            appearance_observers: SubscriberSet::new(),
1883            button_layout_observers: SubscriberSet::new(),
1884            active,
1885            hovered,
1886            needs_present,
1887            input_rate_tracker,
1888            #[cfg(feature = "profiler")]
1889            window_profiler: profiler::WindowProfiler::new(handle.window_id())?,
1890            last_input_modality: InputModality::Mouse,
1891            touch_gestures: TouchGestureRecognizer::new(
1892                cx.platform
1893                    .gestures()
1894                    .map_or_else(GestureTuning::default, |gestures| gestures.tuning()),
1895            ),
1896            touch_prediction_enabled: true,
1897            long_press_timer: None,
1898            long_press_capture: None,
1899            refreshing: false,
1900            activation_observers: SubscriberSet::new(),
1901            focus: None,
1902            focus_enabled: true,
1903            focus_generation: 0,
1904            pending_input: None,
1905            pending_modifier: ModifierState::default(),
1906            pending_input_observers: SubscriberSet::new(),
1907            prompt: None,
1908            client_inset: None,
1909            image_cache_stack: Vec::new(),
1910            captured_hitbox: None,
1911            #[cfg(any(feature = "inspector", debug_assertions))]
1912            inspector: None,
1913            #[cfg(feature = "profiler")]
1914            debug_frame_overlay: crate::debug_overlay::DebugFrameOverlay::new(),
1915            a11y: A11y::new(
1916                a11y_active_flag,
1917                accessibility_force_disabled,
1918                initial_window_title,
1919            ),
1920        })
1921    }
1922
1923    pub(crate) fn new_focus_listener(
1924        &self,
1925        value: AnyWindowFocusListener,
1926    ) -> (Subscription, impl FnOnce() + use<>) {
1927        self.focus_listeners.insert((), value)
1928    }
1929}
1930
1931#[derive(Clone, Debug, Default, PartialEq, Eq)]
1932#[expect(missing_docs)]
1933pub struct DispatchEventResult {
1934    pub propagate: bool,
1935    pub default_prevented: bool,
1936}
1937
1938/// Indicates which region of the window is visible. Content falling outside of this mask will not be
1939/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type
1940/// to leave room to support more complex shapes in the future.
1941#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1942#[repr(C)]
1943pub struct ContentMask<P: Clone + Debug + Default + PartialEq> {
1944    /// The bounds
1945    pub bounds: Bounds<P>,
1946}
1947
1948impl ContentMask<Pixels> {
1949    /// Scale the content mask's pixel units by the given scaling factor.
1950    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
1951        ContentMask {
1952            bounds: self.bounds.scale(factor),
1953        }
1954    }
1955
1956    /// Intersect the content mask with the given content mask.
1957    pub fn intersect(&self, other: &Self) -> Self {
1958        let bounds = self.bounds.intersect(&other.bounds);
1959        ContentMask { bounds }
1960    }
1961}
1962
1963impl Window {
1964    fn mark_view_dirty(&mut self, view_id: EntityId) {
1965        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors
1966        // should already be dirty.
1967        for view_id in self
1968            .rendered_frame
1969            .dispatch_tree
1970            .view_path_reversed(view_id)
1971        {
1972            if !self.dirty_views.insert(view_id) {
1973                break;
1974            }
1975        }
1976    }
1977
1978    /// Registers a callback to be invoked when the window appearance changes.
1979    pub fn observe_window_appearance(
1980        &self,
1981        mut callback: impl FnMut(&mut Window, &mut App) + 'static,
1982    ) -> Subscription {
1983        let (subscription, activate) = self.appearance_observers.insert(
1984            (),
1985            Box::new(move |window, cx| {
1986                callback(window, cx);
1987                true
1988            }),
1989        );
1990        activate();
1991        subscription
1992    }
1993
1994    /// Registers a callback to be invoked when the window button layout changes.
1995    pub fn observe_button_layout_changed(
1996        &self,
1997        mut callback: impl FnMut(&mut Window, &mut App) + 'static,
1998    ) -> Subscription {
1999        let (subscription, activate) = self.button_layout_observers.insert(
2000            (),
2001            Box::new(move |window, cx| {
2002                callback(window, cx);
2003                true
2004            }),
2005        );
2006        activate();
2007        subscription
2008    }
2009
2010    /// Replaces the root entity of the window with a new one.
2011    pub fn replace_root<E>(
2012        &mut self,
2013        cx: &mut App,
2014        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,
2015    ) -> Entity<E>
2016    where
2017        E: 'static + Render,
2018    {
2019        let view = cx.new(|cx| build_view(self, cx));
2020        self.root = Some(view.clone().into());
2021        self.refresh();
2022        view
2023    }
2024
2025    /// Returns the root entity of the window, if it has one.
2026    pub fn root<E>(&self) -> Option<Option<Entity<E>>>
2027    where
2028        E: 'static + Render,
2029    {
2030        self.root
2031            .as_ref()
2032            .map(|view| view.clone().downcast::<E>().ok())
2033    }
2034
2035    /// Obtain a handle to the window that belongs to this context.
2036    pub fn window_handle(&self) -> AnyWindowHandle {
2037        self.handle
2038    }
2039
2040    /// Mark the window as dirty, scheduling it to be redrawn on the next frame.
2041    pub fn refresh(&mut self) {
2042        if self.invalidator.not_drawing() {
2043            self.refreshing = true;
2044            self.invalidator.set_dirty(true);
2045        }
2046    }
2047
2048    /// Close this window.
2049    pub fn remove_window(&mut self) {
2050        self.removed = true;
2051    }
2052
2053    /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.
2054    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {
2055        self.focus
2056            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))
2057    }
2058
2059    /// While focus-lost listeners are being dispatched, returns the closest ancestor of the
2060    /// previously focused element that can still receive focus, making it a suitable target
2061    /// for focus restoration. Returns `None` at all other times, or when no such ancestor exists.
2062    pub fn focus_lost_restore_target(&self, cx: &App) -> Option<FocusHandle> {
2063        let (_leaf, ancestors) = self.focus_lost_path.split_last()?;
2064        ancestors.iter().rev().find_map(|id| {
2065            self.rendered_frame.dispatch_tree.focusable_node_id(*id)?;
2066            FocusHandle::for_id(*id, &cx.focus_handles)
2067        })
2068    }
2069
2070    /// Move focus to the element associated with the given [`FocusHandle`].
2071    pub fn focus(&mut self, handle: &FocusHandle, cx: &mut App) {
2072        if !self.focus_enabled || self.focus == Some(handle.id) {
2073            return;
2074        }
2075
2076        self.focus = Some(handle.id);
2077        self.focus_generation = self.focus_generation.wrapping_add(1);
2078        self.clear_pending_keystrokes(cx);
2079
2080        self.refresh();
2081    }
2082
2083    /// Remove focus from all elements within this context's window.
2084    pub fn blur(&mut self, cx: &mut App) {
2085        self.clear_pending_keystrokes(cx);
2086
2087        if !self.focus_enabled {
2088            return;
2089        }
2090
2091        if self.focus.is_some() {
2092            self.focus_generation = self.focus_generation.wrapping_add(1);
2093        }
2094        self.focus = None;
2095        self.refresh();
2096    }
2097
2098    /// Blur the window and don't allow anything in it to be focused again.
2099    pub fn disable_focus(&mut self, cx: &mut App) {
2100        self.blur(cx);
2101        self.focus_enabled = false;
2102    }
2103
2104    /// Move focus to next tab stop.
2105    pub fn focus_next(&mut self, cx: &mut App) {
2106        if !self.focus_enabled {
2107            return;
2108        }
2109
2110        if let Some(handle) = self.rendered_frame.tab_stops.next(self.focus.as_ref()) {
2111            self.focus(&handle, cx)
2112        }
2113    }
2114
2115    /// Move focus to previous tab stop.
2116    pub fn focus_prev(&mut self, cx: &mut App) {
2117        if !self.focus_enabled {
2118            return;
2119        }
2120
2121        if let Some(handle) = self.rendered_frame.tab_stops.prev(self.focus.as_ref()) {
2122            self.focus(&handle, cx)
2123        }
2124    }
2125
2126    /// Accessor for the text system.
2127    pub fn text_system(&self) -> &Arc<WindowTextSystem> {
2128        &self.text_system
2129    }
2130
2131    /// The current text style. Which is composed of all the style refinements provided to `with_text_style`.
2132    pub fn text_style(&self) -> TextStyle {
2133        let mut style = TextStyle::default();
2134        for refinement in &self.text_style_stack {
2135            style.refine(refinement);
2136        }
2137        style
2138    }
2139
2140    /// Check if the platform window is maximized.
2141    ///
2142    /// On some platforms (namely Windows) this is different than the bounds being the size of the display
2143    pub fn is_maximized(&self) -> bool {
2144        self.platform_window.is_maximized()
2145    }
2146
2147    /// request a certain window decoration (Wayland)
2148    pub fn request_decorations(&self, decorations: WindowDecorations) {
2149        self.platform_window.request_decorations(decorations);
2150    }
2151
2152    /// Set the exclusive zone for a layer-shell surface: how much screen space it
2153    /// reserves so other surfaces avoid occluding it (e.g. a panel reserving space).
2154    /// Positive values reserve that distance from the anchored edge, 0 lets the
2155    /// surface be moved out of others' exclusive zones, and -1 ignores reserved
2156    /// space and may extend under other surfaces. (Wayland layer-shell windows only)
2157    pub fn set_exclusive_zone(&self, zone: Pixels) {
2158        self.platform_window.set_exclusive_zone(zone);
2159    }
2160
2161    /// Set which anchored edge a layer-shell surface's exclusive zone applies to.
2162    /// This is only needed to disambiguate a corner-anchored surface; otherwise the
2163    /// edge is deduced from the anchor. The edge must be a single edge the surface
2164    /// is anchored to, or it is ignored. (Wayland layer-shell windows only)
2165    #[cfg(all(target_os = "linux", feature = "wayland"))]
2166    pub fn set_exclusive_edge(&self, edge: crate::layer_shell::Anchor) {
2167        self.platform_window.set_exclusive_edge(edge);
2168    }
2169
2170    /// Start an interactive window resize operation if this window is resizable.
2171    pub fn start_window_resize(&self, edge: ResizeEdge) {
2172        if self.is_resizable {
2173            self.platform_window.start_window_resize(edge);
2174        }
2175    }
2176
2177    /// Linux (wayland) only: Set the window's input region, the area that receives pointer
2178    /// and touch input. Events outside it pass through to whatever is below the window.
2179    ///
2180    /// - `Some(rects)` restricts input to the union of `rects`, in window coordinates.
2181    /// - `Some(&[])` is an empty region, so the window receives no pointer or touch input.
2182    /// - `None` resets the region to the default, so the whole window receives input again.
2183    pub fn set_input_region(&self, region: Option<&[Bounds<Pixels>]>) {
2184        self.platform_window.set_input_region(region);
2185    }
2186
2187    /// Return the `WindowBounds` to indicate that how a window should be opened
2188    /// after it has been closed
2189    pub fn window_bounds(&self) -> WindowBounds {
2190        self.platform_window.window_bounds()
2191    }
2192
2193    /// Return the `WindowBounds` excluding insets (Wayland and X11)
2194    pub fn inner_window_bounds(&self) -> WindowBounds {
2195        self.platform_window.inner_window_bounds()
2196    }
2197
2198    /// Dispatch the given action on the currently focused element.
2199    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {
2200        let focus_id = self.focused(cx).map(|handle| handle.id);
2201
2202        let window = self.handle;
2203        cx.defer(move |cx| {
2204            window
2205                .update(cx, |_, window, cx| {
2206                    let node_id = window.focus_node_id_in_rendered_frame(focus_id);
2207                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);
2208                })
2209                .log_err();
2210        })
2211    }
2212
2213    pub(crate) fn dispatch_keystroke_observers(
2214        &mut self,
2215        event: &dyn Any,
2216        action: Option<Box<dyn Action>>,
2217        context_stack: Vec<KeyContext>,
2218        cx: &mut App,
2219    ) {
2220        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
2221            return;
2222        };
2223
2224        cx.keystroke_observers.clone().retain(&(), move |callback| {
2225            (callback)(
2226                &KeystrokeEvent {
2227                    keystroke: key_down_event.keystroke.clone(),
2228                    action: action.as_ref().map(|action| action.boxed_clone()),
2229                    context_stack: context_stack.clone(),
2230                },
2231                self,
2232                cx,
2233            )
2234        });
2235    }
2236
2237    pub(crate) fn dispatch_keystroke_interceptors(
2238        &mut self,
2239        event: &dyn Any,
2240        context_stack: Vec<KeyContext>,
2241        cx: &mut App,
2242    ) {
2243        let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
2244            return;
2245        };
2246
2247        cx.keystroke_interceptors
2248            .clone()
2249            .retain(&(), move |callback| {
2250                (callback)(
2251                    &KeystrokeEvent {
2252                        keystroke: key_down_event.keystroke.clone(),
2253                        action: None,
2254                        context_stack: context_stack.clone(),
2255                    },
2256                    self,
2257                    cx,
2258                )
2259            });
2260    }
2261
2262    /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
2263    /// that are currently on the stack to be returned to the app.
2264    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {
2265        let handle = self.handle;
2266        cx.defer(move |cx| {
2267            handle.update(cx, |_, window, cx| f(window, cx)).ok();
2268        });
2269    }
2270
2271    /// Subscribe to events emitted by a entity.
2272    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
2273    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.
2274    pub fn observe<T: 'static>(
2275        &mut self,
2276        observed: &Entity<T>,
2277        cx: &mut App,
2278        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,
2279    ) -> Subscription {
2280        let entity_id = observed.entity_id();
2281        let observed = observed.downgrade();
2282        let window_handle = self.handle;
2283        cx.new_observer(
2284            entity_id,
2285            Box::new(move |cx| {
2286                window_handle
2287                    .update(cx, |_, window, cx| {
2288                        if let Some(handle) = observed.upgrade() {
2289                            on_notify(handle, window, cx);
2290                            true
2291                        } else {
2292                            false
2293                        }
2294                    })
2295                    .unwrap_or(false)
2296            }),
2297        )
2298    }
2299
2300    /// Subscribe to events emitted by a entity.
2301    /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
2302    /// The callback will be invoked a handle to the emitting entity, the event, and a window context for the current window.
2303    pub fn subscribe<Emitter, Evt>(
2304        &mut self,
2305        entity: &Entity<Emitter>,
2306        cx: &mut App,
2307        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,
2308    ) -> Subscription
2309    where
2310        Emitter: EventEmitter<Evt>,
2311        Evt: 'static,
2312    {
2313        let entity_id = entity.entity_id();
2314        let handle = entity.downgrade();
2315        let window_handle = self.handle;
2316        cx.new_subscription(
2317            entity_id,
2318            (
2319                TypeId::of::<Evt>(),
2320                Box::new(move |event, cx| {
2321                    window_handle
2322                        .update(cx, |_, window, cx| {
2323                            if let Some(entity) = handle.upgrade() {
2324                                let event = event.downcast_ref().expect("invalid event type");
2325                                on_event(entity, event, window, cx);
2326                                true
2327                            } else {
2328                                false
2329                            }
2330                        })
2331                        .unwrap_or(false)
2332                }),
2333            ),
2334        )
2335    }
2336
2337    /// Register a callback to be invoked when the given `Entity` is released.
2338    pub fn observe_release<T>(
2339        &self,
2340        entity: &Entity<T>,
2341        cx: &mut App,
2342        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
2343    ) -> Subscription
2344    where
2345        T: 'static,
2346    {
2347        let entity_id = entity.entity_id();
2348        let window_handle = self.handle;
2349        let (subscription, activate) = cx.release_listeners.insert(
2350            entity_id,
2351            Box::new(move |entity, cx| {
2352                let entity = entity.downcast_mut().expect("invalid entity type");
2353                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
2354            }),
2355        );
2356        activate();
2357        subscription
2358    }
2359
2360    /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across
2361    /// await points in async code.
2362    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {
2363        AsyncWindowContext::new_context(cx.to_async(), self.handle)
2364    }
2365
2366    /// Schedule the given closure to be run directly after the current frame is rendered.
2367    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {
2368        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));
2369        self.platform_window.schedule_frame();
2370        // Next-frame callbacks create frame demand without dirtying the
2371        // window, so the platform's frame source must be woken explicitly.
2372        self.invalidator.wake_platform();
2373    }
2374
2375    /// Schedule a frame to be drawn on the next animation frame.
2376    ///
2377    /// This is useful for elements that need to animate continuously, such as a video player or an animated GIF.
2378    /// It will cause the window to redraw on the next frame, even if no other changes have occurred.
2379    ///
2380    /// If called from within a view, it will notify that view on the next frame. Otherwise, it will refresh the entire window.
2381    ///
2382    /// Callers driving purely decorative animations (spinners, pulses, and the
2383    /// like) should prefer [`AnimationExt::with_animation`](crate::AnimationExt::with_animation),
2384    /// which automatically respects [`App::reduce_motion`]. When using this
2385    /// method directly for decorative motion, check [`App::reduce_motion`]
2386    /// and skip the frame request when it is set.
2387    pub fn request_animation_frame(&self) {
2388        let entity = self.current_view();
2389        self.on_next_frame(move |_, cx| cx.notify(entity));
2390    }
2391
2392    /// Runs all callbacks scheduled via [`Self::on_next_frame`], returning how many ran.
2393    ///
2394    /// Tests have no platform frame loop, so this simulates the delivery of the
2395    /// next frame.
2396    #[cfg(any(test, feature = "test-support"))]
2397    pub fn simulate_next_frame(&mut self, cx: &mut App) -> usize {
2398        let callbacks = self.next_frame_callbacks.take();
2399        let count = callbacks.len();
2400        for callback in callbacks {
2401            callback(self, cx);
2402        }
2403        count
2404    }
2405
2406    /// Spawn the future returned by the given closure on the application thread pool.
2407    /// The closure is provided a handle to the current window and an `AsyncWindowContext` for
2408    /// use within your future.
2409    #[track_caller]
2410    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>
2411    where
2412        R: 'static,
2413        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
2414    {
2415        let handle = self.handle;
2416        cx.spawn(async move |app| {
2417            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
2418            f(&mut async_window_cx).await
2419        })
2420    }
2421
2422    /// Spawn the future returned by the given closure on the application thread
2423    /// pool, with the given priority. The closure is provided a handle to the
2424    /// current window and an `AsyncWindowContext` for use within your future.
2425    #[track_caller]
2426    pub fn spawn_with_priority<AsyncFn, R>(
2427        &self,
2428        priority: Priority,
2429        cx: &App,
2430        f: AsyncFn,
2431    ) -> Task<R>
2432    where
2433        R: 'static,
2434        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
2435    {
2436        let handle = self.handle;
2437        cx.spawn_with_priority(priority, async move |app| {
2438            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
2439            f(&mut async_window_cx).await
2440        })
2441    }
2442
2443    /// Notify the window that its bounds have changed.
2444    ///
2445    /// This updates internal state like `viewport_size` and `scale_factor` from
2446    /// the platform window, then notifies observers. Normally called automatically
2447    /// by the platform's resize callback, but exposed publicly for test infrastructure.
2448    pub fn bounds_changed(&mut self, cx: &mut App) {
2449        self.scale_factor = self.platform_window.scale_factor();
2450        self.viewport_size = self.platform_window.content_size();
2451        self.display_id = self.platform_window.display().map(|display| display.id());
2452        self.mouse_position = self.platform_window.mouse_position();
2453
2454        self.refresh();
2455
2456        self.bounds_observers
2457            .clone()
2458            .retain(&(), |callback| callback(self, cx));
2459    }
2460
2461    /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.
2462    pub fn bounds(&self) -> Bounds<Pixels> {
2463        self.platform_window.bounds()
2464    }
2465
2466    /// Renders the current frame's scene to a texture and returns the pixel data as an RGBA image.
2467    /// This does not present the frame to screen - useful for visual testing where we want
2468    /// to capture what would be rendered without displaying it or requiring the window to be visible.
2469    #[cfg(any(test, feature = "test-support"))]
2470    pub fn render_to_image(&self) -> anyhow::Result<image::RgbaImage> {
2471        self.platform_window
2472            .render_to_image(&self.rendered_frame.scene)
2473    }
2474
2475    /// Returns the quads in the most recently rendered frame's scene, so tests can assert on
2476    /// painted output without rasterizing the frame. Quad bounds are in scaled pixels and are
2477    /// not clipped; each quad carries the content mask it will be clipped to when drawn. Quads
2478    /// whose bounds don't intersect their content mask are culled at paint time and won't appear.
2479    #[cfg(any(test, feature = "test-support"))]
2480    pub fn painted_quads(&self) -> Vec<Quad> {
2481        self.rendered_frame.scene.quads.clone()
2482    }
2483
2484    /// Set the content size of the window.
2485    pub fn resize(&mut self, size: Size<Pixels>) {
2486        self.platform_window.resize(size);
2487    }
2488
2489    /// Returns whether or not the window is currently fullscreen
2490    pub fn is_fullscreen(&self) -> bool {
2491        self.platform_window.is_fullscreen()
2492    }
2493
2494    /// Returns whether the window is currently in simple (borderless) fullscreen,
2495    /// where it covers the entire screen including the menu bar and notch area.
2496    /// Always `false` on platforms other than macOS.
2497    pub fn is_simple_fullscreen(&self) -> bool {
2498        self.platform_window.is_simple_fullscreen()
2499    }
2500
2501    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {
2502        self.appearance = self.platform_window.appearance();
2503
2504        self.appearance_observers
2505            .clone()
2506            .retain(&(), |callback| callback(self, cx));
2507    }
2508
2509    pub(crate) fn button_layout_changed(&mut self, cx: &mut App) {
2510        self.button_layout_observers
2511            .clone()
2512            .retain(&(), |callback| callback(self, cx));
2513    }
2514
2515    /// Returns the appearance of the current window.
2516    pub fn appearance(&self) -> WindowAppearance {
2517        self.appearance
2518    }
2519
2520    /// Returns the size of the drawable area within the window.
2521    pub fn viewport_size(&self) -> Size<Pixels> {
2522        self.viewport_size
2523    }
2524
2525    /// Returns whether this window is focused by the operating system (receiving key events).
2526    pub fn is_window_active(&self) -> bool {
2527        self.active.get()
2528    }
2529
2530    /// Returns whether this window is considered to be the window
2531    /// that currently owns the mouse cursor.
2532    /// On mac, this is equivalent to `is_window_active`.
2533    pub fn is_window_hovered(&self) -> bool {
2534        if cfg!(any(
2535            target_os = "windows",
2536            target_os = "linux",
2537            target_os = "freebsd"
2538        )) {
2539            self.hovered.get()
2540        } else {
2541            self.is_window_active()
2542        }
2543    }
2544
2545    /// Toggle zoom on the window.
2546    pub fn zoom_window(&self) {
2547        self.platform_window.zoom();
2548    }
2549
2550    /// Opens the native title bar context menu, useful when implementing client side decorations (Wayland and X11)
2551    pub fn show_window_menu(&self, position: Point<Pixels>) {
2552        self.platform_window.show_window_menu(position)
2553    }
2554
2555    /// Handle window movement for Linux and macOS.
2556    /// Tells the compositor to take control of window movement (Wayland and X11)
2557    ///
2558    /// Events may not be received during a move operation.
2559    pub fn start_window_move(&self) {
2560        self.platform_window.start_window_move()
2561    }
2562
2563    /// When using client side decorations, set this to the width of the invisible decorations (Wayland and X11)
2564    pub fn set_client_inset(&mut self, inset: Pixels) {
2565        self.client_inset = Some(inset);
2566        self.platform_window.set_client_inset(inset);
2567    }
2568
2569    /// Returns the client_inset value by [`Self::set_client_inset`].
2570    pub fn client_inset(&self) -> Option<Pixels> {
2571        self.client_inset
2572    }
2573
2574    /// Returns whether the title bar window controls need to be rendered by the application (Wayland and X11)
2575    pub fn window_decorations(&self) -> Decorations {
2576        self.platform_window.window_decorations()
2577    }
2578
2579    /// Returns whether this window is resizable.
2580    pub fn is_resizable(&self) -> bool {
2581        self.is_resizable
2582    }
2583
2584    /// Returns whether this window is minimizable.
2585    pub fn is_minimizable(&self) -> bool {
2586        self.is_minimizable
2587    }
2588
2589    /// Returns the controls supported by the platform.
2590    pub fn window_controls(&self) -> WindowControls {
2591        self.platform_window.window_controls()
2592    }
2593
2594    /// Updates the window's title at the platform level.
2595    pub fn set_window_title(&mut self, title: &str) {
2596        self.platform_window.set_title(title);
2597        self.a11y.set_window_title(title.to_string());
2598    }
2599
2600    /// Sets the position of the macOS traffic light buttons.
2601    #[cfg(target_os = "macos")]
2602    pub fn set_traffic_light_position(&self, position: Point<Pixels>) {
2603        self.platform_window.set_traffic_light_position(position);
2604    }
2605
2606    /// Sets the application identifier.
2607    pub fn set_app_id(&mut self, app_id: &str) {
2608        self.platform_window.set_app_id(app_id);
2609    }
2610
2611    /// Sets the window background appearance.
2612    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
2613        self.platform_window
2614            .set_background_appearance(background_appearance);
2615    }
2616
2617    /// Mark the window as dirty at the platform level.
2618    pub fn set_window_edited(&mut self, edited: bool) {
2619        self.platform_window.set_edited(edited);
2620    }
2621
2622    /// Set the path of the file this window represents.
2623    /// On macOS, this sets the window's accessibility document property (AXDocument).
2624    pub fn set_document_path(&self, path: Option<&std::path::Path>) {
2625        self.platform_window.set_document_path(path);
2626    }
2627
2628    /// Determine the display on which the window is visible.
2629    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {
2630        cx.platform
2631            .displays()
2632            .into_iter()
2633            .find(|display| Some(display.id()) == self.display_id)
2634    }
2635
2636    /// Show the platform character palette.
2637    pub fn show_character_palette(&self) {
2638        self.platform_window.show_character_palette();
2639    }
2640
2641    /// The scale factor of the display associated with the window. For example, it could
2642    /// return 2.0 for a "retina" display, indicating that each logical pixel should actually
2643    /// be rendered as two pixels on screen.
2644    pub fn scale_factor(&self) -> f32 {
2645        self.scale_factor
2646    }
2647
2648    /// Overrides the display scale factor for tests.
2649    #[cfg(any(test, feature = "test-support"))]
2650    pub fn set_scale_factor(&mut self, scale_factor: f32) {
2651        self.scale_factor = scale_factor;
2652        self.refresh();
2653    }
2654
2655    /// The size of an em for the base font of the application. Adjusting this value allows the
2656    /// UI to scale, just like zooming a web page.
2657    pub fn rem_size(&self) -> Pixels {
2658        self.rem_size_override_stack
2659            .last()
2660            .copied()
2661            .unwrap_or(self.rem_size)
2662    }
2663
2664    /// Sets the size of an em for the base font of the application. Adjusting this value allows the
2665    /// UI to scale, just like zooming a web page.
2666    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
2667        self.rem_size = rem_size.into();
2668    }
2669
2670    /// Acquire a globally unique identifier for the given ElementId.
2671    /// Only valid for the duration of the provided closure.
2672    pub fn with_global_id<R>(
2673        &mut self,
2674        element_id: ElementId,
2675        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,
2676    ) -> R {
2677        self.with_id(element_id, |this| {
2678            let global_id = GlobalElementId(Arc::from(&*this.element_id_stack));
2679
2680            f(&global_id, this)
2681        })
2682    }
2683
2684    /// Calls the provided closure with the element ID pushed on the stack.
2685    #[inline]
2686    pub fn with_id<R>(
2687        &mut self,
2688        element_id: impl Into<ElementId>,
2689        f: impl FnOnce(&mut Self) -> R,
2690    ) -> R {
2691        self.element_id_stack.push(element_id.into());
2692        let result = f(self);
2693        self.element_id_stack.pop();
2694        result
2695    }
2696
2697    /// Executes the provided function with the specified rem size.
2698    ///
2699    /// This method must only be called as part of element drawing.
2700    // This function is called in a highly recursive manner in editor
2701    // prepainting, make sure its inlined to reduce the stack burden
2702    #[inline]
2703    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R
2704    where
2705        F: FnOnce(&mut Self) -> R,
2706    {
2707        self.invalidator.debug_assert_paint_or_prepaint();
2708
2709        if let Some(rem_size) = rem_size {
2710            self.rem_size_override_stack.push(rem_size.into());
2711            let result = f(self);
2712            self.rem_size_override_stack.pop();
2713            result
2714        } else {
2715            f(self)
2716        }
2717    }
2718
2719    /// The line height associated with the current text style.
2720    pub fn line_height(&self) -> Pixels {
2721        self.text_style().line_height_in_pixels(self.rem_size())
2722    }
2723
2724    /// Rounds a logical value to the nearest device pixel.
2725    #[inline]
2726    pub fn pixel_snap(&self, value: Pixels) -> Pixels {
2727        px(round_to_device_pixel(value.0, self.scale_factor()) / self.scale_factor())
2728    }
2729
2730    /// f64 variant of [`Self::pixel_snap`].
2731    #[inline]
2732    pub fn pixel_snap_f64(&self, value: f64) -> f64 {
2733        let scale_factor = f64::from(self.scale_factor());
2734        round_half_toward_zero_f64(value * scale_factor) / scale_factor
2735    }
2736
2737    /// Snaps a bounds' origin and size to the nearest device pixel.
2738    #[inline]
2739    pub fn pixel_snap_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<Pixels> {
2740        bounds.map(|c| self.pixel_snap(c))
2741    }
2742
2743    /// Snaps a point's coordinates to the nearest device pixel.
2744    #[inline]
2745    pub fn pixel_snap_point(&self, position: Point<Pixels>) -> Point<Pixels> {
2746        position.map(|c| self.pixel_snap(c))
2747    }
2748
2749    #[inline]
2750    fn snap_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
2751        let scale_factor = self.scale_factor();
2752        let left = round_to_device_pixel(bounds.left().0, scale_factor);
2753        let top = round_to_device_pixel(bounds.top().0, scale_factor);
2754        let right = round_to_device_pixel(bounds.right().0, scale_factor).max(left);
2755        let bottom = round_to_device_pixel(bounds.bottom().0, scale_factor).max(top);
2756        Bounds::from_corners(
2757            point(ScaledPixels(left), ScaledPixels(top)),
2758            point(ScaledPixels(right), ScaledPixels(bottom)),
2759        )
2760    }
2761
2762    /// Rounds half-to-zero but clamps any non-zero input up to 1 dp so thin strokes do not disappear.
2763    #[inline]
2764    fn snap_stroke(&self, value: Pixels) -> ScaledPixels {
2765        ScaledPixels(round_stroke_to_device_pixel(value.0, self.scale_factor()))
2766    }
2767
2768    #[inline]
2769    fn snap_border_widths(&self, edges: Edges<Pixels>) -> Edges<ScaledPixels> {
2770        edges.map(|e| self.snap_stroke(*e))
2771    }
2772
2773    /// Floors the near edge and ceils the far edge, producing a strict superset of the raw region.
2774    #[inline]
2775    fn cover_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
2776        let scale_factor = self.scale_factor();
2777        let left = floor_to_device_pixel(bounds.left().0, scale_factor);
2778        let top = floor_to_device_pixel(bounds.top().0, scale_factor);
2779        let right = ceil_to_device_pixel(bounds.right().0, scale_factor).max(left);
2780        let bottom = ceil_to_device_pixel(bounds.bottom().0, scale_factor).max(top);
2781        Bounds::from_corners(
2782            point(ScaledPixels(left), ScaledPixels(top)),
2783            point(ScaledPixels(right), ScaledPixels(bottom)),
2784        )
2785    }
2786
2787    #[inline]
2788    fn snapped_content_mask(&self) -> ContentMask<ScaledPixels> {
2789        ContentMask {
2790            bounds: self.cover_bounds(self.content_mask().bounds),
2791        }
2792    }
2793
2794    /// Call to prevent the default action of an event. Currently only used to prevent
2795    /// parent elements from becoming focused on mouse down.
2796    pub fn prevent_default(&mut self) {
2797        self.default_prevented = true;
2798    }
2799
2800    /// Obtain whether default has been prevented for the event currently being dispatched.
2801    pub fn default_prevented(&self) -> bool {
2802        self.default_prevented
2803    }
2804
2805    /// Determine whether the given action is available along the dispatch path to the currently focused element.
2806    pub fn is_action_available(&self, action: &dyn Action, cx: &App) -> bool {
2807        let node_id =
2808            self.focus_node_id_in_rendered_frame(self.focused(cx).map(|handle| handle.id));
2809        self.rendered_frame
2810            .dispatch_tree
2811            .is_action_available(action, node_id)
2812    }
2813
2814    /// Determine whether the given action is available along the dispatch path to the given focus_handle.
2815    pub fn is_action_available_in(&self, action: &dyn Action, focus_handle: &FocusHandle) -> bool {
2816        let node_id = self.focus_node_id_in_rendered_frame(Some(focus_handle.id));
2817        self.rendered_frame
2818            .dispatch_tree
2819            .is_action_available(action, node_id)
2820    }
2821
2822    /// The position of the mouse relative to the window.
2823    pub fn mouse_position(&self) -> Point<Pixels> {
2824        self.mouse_position
2825    }
2826
2827    /// Captures the pointer for the given hitbox. While captured, all mouse move and mouse up
2828    /// events will be routed to listeners that check this hitbox's `is_hovered` status,
2829    /// regardless of actual hit testing. This enables drag operations that continue
2830    /// even when the pointer moves outside the element's bounds.
2831    ///
2832    /// The capture is automatically released on mouse up.
2833    pub fn capture_pointer(&mut self, hitbox_id: HitboxId) {
2834        self.captured_hitbox = Some(hitbox_id);
2835    }
2836
2837    /// Releases any active pointer capture.
2838    pub fn release_pointer(&mut self) {
2839        self.captured_hitbox = None;
2840    }
2841
2842    /// Returns the hitbox that has captured the pointer, if any.
2843    pub fn captured_hitbox(&self) -> Option<HitboxId> {
2844        self.captured_hitbox
2845    }
2846
2847    /// Captures the current long press for the given entity.
2848    ///
2849    /// The capture is released when the gesture ends or is cancelled, or when
2850    /// a replacement touch begins. A listener must also call
2851    /// [`Self::prevent_default`] on the started event to claim the gesture.
2852    pub fn capture_long_press<T: 'static>(&mut self, entity: &Entity<T>) {
2853        self.long_press_capture = Some(entity.entity_id());
2854    }
2855
2856    /// Returns whether the given entity has captured the current long press.
2857    pub fn has_long_press_capture<T: 'static>(&self, entity: &Entity<T>) -> bool {
2858        self.long_press_capture == Some(entity.entity_id())
2859    }
2860
2861    /// The current state of the keyboard's modifiers
2862    pub fn modifiers(&self) -> Modifiers {
2863        self.modifiers
2864    }
2865
2866    /// Returns true if the last input event was keyboard-based (key press, tab navigation, etc.)
2867    /// This is used for focus-visible styling to show focus indicators only for keyboard navigation.
2868    pub fn last_input_was_keyboard(&self) -> bool {
2869        self.last_input_modality == InputModality::Keyboard
2870    }
2871
2872    pub(crate) fn last_input_was_touch(&self) -> bool {
2873        self.last_input_modality == InputModality::Touch
2874    }
2875
2876    /// The current state of the keyboard's capslock
2877    pub fn capslock(&self) -> Capslock {
2878        self.capslock
2879    }
2880
2881    /// Produces a new frame and assigns it to `rendered_frame`. To actually show
2882    /// the contents of the new [`Scene`], use [`Self::present`].
2883    #[profiling::function]
2884    pub fn draw(&mut self, cx: &mut App) -> ArenaClearNeeded {
2885        // Drain every draw in profiler builds so a previous frame's
2886        // first-invalidation timestamp can't be attributed to this one.
2887        #[cfg(feature = "profiler")]
2888        let frame_dirty = self.invalidator.take_frame_dirty();
2889        #[cfg(feature = "profiler")]
2890        self.window_profiler.begin_draw();
2891
2892        // Set up the per-App arena for element allocation during this draw.
2893        // This ensures that multiple test Apps have isolated arenas.
2894        let arena_scope = ElementArenaScope::enter(&cx.element_arena);
2895
2896        self.invalidate_entities();
2897        cx.entities.clear_accessed();
2898        debug_assert!(self.rendered_entity_stack.is_empty());
2899        self.invalidator.set_dirty(false);
2900        self.requested_autoscroll = None;
2901
2902        // Restore the previously-used input handler.
2903        // Place it back into a None slot (left by a previous .take()) so that
2904        // cached paint_range indices in reuse_paint find the handler at the
2905        // expected position.
2906        if let Some(input_handler) = self.platform_window.take_input_handler() {
2907            if let Some(slot) = self
2908                .rendered_frame
2909                .input_handlers
2910                .iter_mut()
2911                .rev()
2912                .find(|h| h.is_none())
2913            {
2914                *slot = Some(input_handler);
2915            } else {
2916                self.rendered_frame.input_handlers.push(Some(input_handler));
2917            }
2918        }
2919        if !cx.mode.skip_drawing() {
2920            self.draw_roots(cx);
2921            #[cfg(feature = "profiler")]
2922            {
2923                let viewport_size = self.viewport_size;
2924                let scale_factor = self.scale_factor();
2925                self.debug_frame_overlay.paint(
2926                    &mut self.next_frame.scene,
2927                    viewport_size,
2928                    scale_factor,
2929                );
2930            }
2931        }
2932        self.dirty_views.clear();
2933        self.next_frame.window_active = self.active.get();
2934
2935        // Register requested input handler with the platform window.
2936        // Use .take() instead of .pop() to preserve Vec length, so that cached
2937        // paint_range indices remain valid for reuse_paint on the next frame.
2938        // Search backwards to find the last Some entry, since reuse_paint may
2939        // have copied None slots from the previous frame. (Fixes #50456)
2940        let focused_text_input_active = if let Some(mut input_handler) = self
2941            .next_frame
2942            .input_handlers
2943            .iter_mut()
2944            .rev()
2945            .find_map(|h| h.take())
2946        {
2947            let accepts_text_input = input_handler.accepts_text_input(self, cx);
2948            self.platform_window.set_input_handler(input_handler);
2949            accepts_text_input
2950        } else {
2951            false
2952        };
2953        self.apply_text_input_configuration(cx);
2954        if focused_text_input_active != self.focused_text_input_active {
2955            self.focused_text_input_active = focused_text_input_active;
2956            self.platform_window
2957                .text_input_state_changed(if focused_text_input_active {
2958                    TextInputStateChange::FocusGained
2959                } else {
2960                    TextInputStateChange::FocusLost
2961                });
2962        }
2963
2964        self.layout_engine.as_mut().unwrap().clear();
2965        self.text_system().finish_frame();
2966        self.next_frame.finish(&mut self.rendered_frame);
2967
2968        self.invalidator.set_phase(DrawPhase::Focus);
2969        let previous_focus_path = self.rendered_frame.focus_path();
2970        let previous_window_active = self.rendered_frame.window_active;
2971        mem::swap(&mut self.rendered_frame, &mut self.next_frame);
2972        self.next_frame.clear();
2973        let current_focus_path = self.rendered_frame.focus_path();
2974        let current_window_active = self.rendered_frame.window_active;
2975        let mut focus_before_listeners = self.focus;
2976
2977        if previous_focus_path != current_focus_path
2978            || previous_window_active != current_window_active
2979        {
2980            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
2981                self.focus_lost_path = previous_focus_path.clone();
2982                self.focus_lost_listeners
2983                    .clone()
2984                    .retain(&(), |listener| listener(self, cx));
2985                self.focus_lost_path = SmallVec::new();
2986                // The focus-lost fallback (e.g. a workspace refocusing itself) may target
2987                // an element that isn't part of the element tree, in which case scheduling
2988                // a redraw below would dispatch focus-lost again, looping forever. Only
2989                // track focus movement caused by the focus listeners.
2990                focus_before_listeners = self.focus;
2991            }
2992
2993            let event = WindowFocusEvent {
2994                previous_focus_path: if previous_window_active {
2995                    previous_focus_path
2996                } else {
2997                    Default::default()
2998                },
2999                current_focus_path: if current_window_active {
3000                    current_focus_path
3001                } else {
3002                    Default::default()
3003                },
3004            };
3005            self.focus_listeners
3006                .clone()
3007                .retain(&(), |listener| listener(&event, self, cx));
3008        }
3009
3010        debug_assert!(self.rendered_entity_stack.is_empty());
3011        self.record_entities_accessed(cx);
3012        self.reset_cursor_style(cx);
3013        self.refreshing = false;
3014        self.invalidator.set_phase(DrawPhase::None);
3015        // Focus listeners may move focus (e.g. a dock forwarding focus to its active
3016        // panel). `Window::focus` suppresses `refresh` while a draw is in progress, so
3017        // schedule another frame here to render the new focus state and dispatch the
3018        // resulting focus events.
3019        if self.focus != focus_before_listeners {
3020            self.refresh();
3021        }
3022        self.needs_present.set(true);
3023
3024        #[cfg(feature = "profiler")]
3025        {
3026            let draw_duration = self
3027                .window_profiler
3028                .end_draw(frame_dirty.dirty_at, frame_dirty.invalidations);
3029            self.debug_frame_overlay.record_frame(draw_duration);
3030        }
3031
3032        // Exit the scope to obtain the arena-clear token this draw owes; the
3033        // scope's teardown itself happens in `ElementArenaScope::drop`.
3034        arena_scope.exit(&cx.element_arena)
3035    }
3036
3037    fn record_entities_accessed(&mut self, cx: &mut App) {
3038        let mut entities_ref = cx.entities.accessed_entities.get_mut();
3039        let mut entities = mem::take(entities_ref.deref_mut());
3040        let handle = self.handle;
3041        cx.record_entities_accessed(
3042            handle,
3043            // Try moving window invalidator into the Window
3044            self.invalidator.clone(),
3045            &entities,
3046        );
3047        let mut entities_ref = cx.entities.accessed_entities.get_mut();
3048        mem::swap(&mut entities, entities_ref.deref_mut());
3049    }
3050
3051    fn invalidate_entities(&mut self) {
3052        let mut views = self.invalidator.take_views();
3053        for entity in views.drain() {
3054            self.mark_view_dirty(entity);
3055        }
3056        self.invalidator.replace_views(views);
3057    }
3058
3059    #[profiling::function]
3060    fn present(&mut self) {
3061        #[cfg(feature = "profiler")]
3062        let _foreground_turn = profiler::journal::foreground_turn();
3063        #[cfg(feature = "profiler")]
3064        let present_start = Instant::now();
3065        self.platform_window.draw(&self.rendered_frame.scene);
3066        #[cfg(feature = "profiler")]
3067        self.window_profiler.record_present(
3068            present_start,
3069            Instant::now(),
3070            self.active.get(),
3071            !self.next_frame_callbacks.borrow().is_empty(),
3072        );
3073        self.needs_present.set(false);
3074        profiling::finish_frame!();
3075    }
3076
3077    /// Presents the most recently drawn frame if it hasn't been presented yet.
3078    ///
3079    /// Benchmarks drive drawing synchronously rather than through a platform
3080    /// frame-request loop, so they call this after each measured update to
3081    /// submit the frame like production presentation would.
3082    #[cfg(any(feature = "bench-support", all(test, feature = "profiler")))]
3083    pub fn present_if_needed(&mut self) {
3084        if self.needs_present.get() {
3085            self.present();
3086        }
3087    }
3088
3089    /// Returns a snapshot of the current input-latency histograms.
3090    #[cfg(feature = "profiler")]
3091    pub fn input_latency_snapshot(&self) -> profiler::InputLatencySnapshot {
3092        self.window_profiler.input_latency_snapshot()
3093    }
3094
3095    /// Returns a snapshot of the current frame-duration histograms.
3096    #[cfg(feature = "profiler")]
3097    pub fn frame_duration_snapshot(&self) -> profiler::FrameDurationSnapshot {
3098        self.window_profiler.frame_duration_snapshot()
3099    }
3100
3101    /// Returns the current mode of the debug frame overlay.
3102    #[cfg(feature = "profiler")]
3103    pub fn debug_frame_overlay_mode(&self) -> DebugFrameOverlayMode {
3104        self.debug_frame_overlay.mode()
3105    }
3106
3107    /// Sets the mode of the debug frame overlay and schedules a redraw.
3108    #[cfg(feature = "profiler")]
3109    pub fn set_debug_frame_overlay_mode(&mut self, mode: DebugFrameOverlayMode) {
3110        self.debug_frame_overlay.set_mode(mode);
3111        self.refresh();
3112    }
3113
3114    /// Advances the debug frame overlay through its hidden, frame-time-only,
3115    /// and detailed modes.
3116    #[cfg(feature = "profiler")]
3117    pub fn cycle_debug_frame_overlay_mode(&mut self) {
3118        self.set_debug_frame_overlay_mode(self.debug_frame_overlay.mode().next());
3119    }
3120
3121    /// Clears the debug frame overlay's frame-time statistics, except for the
3122    /// total frame count, and schedules a redraw.
3123    #[cfg(feature = "profiler")]
3124    pub fn reset_debug_frame_overlay_stats(&mut self) {
3125        self.debug_frame_overlay.reset_stats();
3126        self.refresh();
3127    }
3128
3129    fn draw_roots(&mut self, cx: &mut App) {
3130        self.invalidator.set_phase(DrawPhase::Prepaint);
3131        self.tooltip_bounds.take();
3132
3133        self.a11y.sync_active_flag();
3134        if self.a11y.is_active() {
3135            self.a11y.begin_frame();
3136        }
3137
3138        let _inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size());
3139        let root_size = {
3140            #[cfg(any(feature = "inspector", debug_assertions))]
3141            {
3142                if self.inspector.is_some() {
3143                    let mut size = self.viewport_size;
3144                    size.width = (size.width - _inspector_width).max(px(0.0));
3145                    size
3146                } else {
3147                    self.viewport_size
3148                }
3149            }
3150            #[cfg(not(any(feature = "inspector", debug_assertions)))]
3151            {
3152                self.viewport_size
3153            }
3154        };
3155
3156        // Layout all root elements. Like the root element on the web, which
3157        // stretches to fill the viewport unless explicitly sized, window roots
3158        // fill the window when their size is `auto`.
3159        let scale_factor = self.scale_factor();
3160        let mut root_element = self.root.as_ref().unwrap().clone().into_any_element();
3161        let root_layout_id = root_element.request_layout(self, cx);
3162        self.layout_engine
3163            .as_mut()
3164            .unwrap()
3165            .stretch_auto_size_to_fill(root_layout_id, root_size, scale_factor);
3166        root_element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
3167
3168        #[cfg(any(feature = "inspector", debug_assertions))]
3169        let inspector_element = self.prepaint_inspector(_inspector_width, cx);
3170
3171        self.prepaint_deferred_draws(cx);
3172
3173        let mut prompt_element = None;
3174        let mut active_drag_element = None;
3175        let mut tooltip_element = None;
3176        if let Some(prompt) = self.prompt.take() {
3177            let mut element = prompt.view.any_view().into_any_element();
3178            let prompt_layout_id = element.request_layout(self, cx);
3179            self.layout_engine
3180                .as_mut()
3181                .unwrap()
3182                .stretch_auto_size_to_fill(prompt_layout_id, root_size, scale_factor);
3183            element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
3184            prompt_element = Some(element);
3185            self.prompt = Some(prompt);
3186        } else if let Some(active_drag) = cx.active_drag.take() {
3187            let mut element = active_drag.view.clone().into_any_element();
3188            let offset = self.mouse_position() - active_drag.cursor_offset;
3189            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);
3190            active_drag_element = Some(element);
3191            cx.active_drag = Some(active_drag);
3192        } else {
3193            tooltip_element = self.prepaint_tooltip(cx);
3194        }
3195
3196        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);
3197
3198        // Now actually paint the elements.
3199        self.invalidator.set_phase(DrawPhase::Paint);
3200        root_element.paint(self, cx);
3201
3202        #[cfg(any(feature = "inspector", debug_assertions))]
3203        self.paint_inspector(inspector_element, cx);
3204
3205        self.paint_deferred_draws(cx);
3206
3207        if let Some(mut prompt_element) = prompt_element {
3208            prompt_element.paint(self, cx);
3209        } else if let Some(mut drag_element) = active_drag_element {
3210            drag_element.paint(self, cx);
3211        } else if let Some(mut tooltip_element) = tooltip_element {
3212            tooltip_element.paint(self, cx);
3213        }
3214
3215        #[cfg(any(feature = "inspector", debug_assertions))]
3216        self.paint_inspector_hitbox(cx);
3217
3218        // a11y may have been activated/deactivated halfway through the frame
3219        let a11y_active_start_of_frame = self.a11y.is_active();
3220        self.a11y.sync_active_flag();
3221        let a11y_active_end_of_frame = self.a11y.is_active();
3222
3223        let should_send_a11y_update = a11y_active_start_of_frame && a11y_active_end_of_frame;
3224
3225        if a11y_active_start_of_frame {
3226            // Harvest frame metadata for the debug dump while the live window
3227            // and frame are still in scope.
3228            let frame_info = crate::window::a11y::debug::FrameDebugInfo {
3229                viewport_size: self.viewport_size,
3230                scale_factor: self.scale_factor,
3231                tab_stop_count: self.next_frame.tab_stops.tab_stop_count(),
3232            };
3233            // clear the builder state regardless
3234            let tree_update = self.a11y.end_frame(frame_info);
3235
3236            if should_send_a11y_update {
3237                log::debug!(
3238                    "Sending a11y tree update: {} nodes",
3239                    tree_update.nodes.len()
3240                );
3241                self.platform_window.a11y_tree_update(tree_update);
3242            }
3243        }
3244    }
3245
3246    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {
3247        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.
3248        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {
3249            let Some(Some(tooltip_request)) = self
3250                .next_frame
3251                .tooltip_requests
3252                .get(tooltip_request_index)
3253                .cloned()
3254            else {
3255                log::error!("Unexpectedly absent TooltipRequest");
3256                continue;
3257            };
3258            let mut element = tooltip_request.tooltip.view.clone().into_any_element();
3259            let mouse_position = tooltip_request.tooltip.mouse_position;
3260            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);
3261
3262            let mut tooltip_bounds =
3263                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
3264            let window_bounds = Bounds {
3265                origin: Point::default(),
3266                size: self.viewport_size(),
3267            };
3268
3269            if tooltip_bounds.right() > window_bounds.right() {
3270                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
3271                if new_x >= Pixels::ZERO {
3272                    tooltip_bounds.origin.x = new_x;
3273                } else {
3274                    tooltip_bounds.origin.x = cmp::max(
3275                        Pixels::ZERO,
3276                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
3277                    );
3278                }
3279            }
3280
3281            if tooltip_bounds.bottom() > window_bounds.bottom() {
3282                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
3283                if new_y >= Pixels::ZERO {
3284                    tooltip_bounds.origin.y = new_y;
3285                } else {
3286                    tooltip_bounds.origin.y = cmp::max(
3287                        Pixels::ZERO,
3288                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
3289                    );
3290                }
3291            }
3292
3293            // It's possible for an element to have an active tooltip while not being painted (e.g.
3294            // via the `visible_on_hover` method). Since mouse listeners are not active in this
3295            // case, instead update the tooltip's visibility here.
3296            let is_visible =
3297                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);
3298            if !is_visible {
3299                continue;
3300            }
3301
3302            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {
3303                element.prepaint(window, cx)
3304            });
3305
3306            self.tooltip_bounds = Some(TooltipBounds {
3307                id: tooltip_request.id,
3308                bounds: tooltip_bounds,
3309            });
3310            return Some(element);
3311        }
3312        None
3313    }
3314
3315    fn prepaint_deferred_draws(&mut self, cx: &mut App) {
3316        assert_eq!(self.element_id_stack.len(), 0);
3317
3318        // Process deferred draws in multiple rounds to support nesting.
3319        // Each round processes all current deferred draws, which may push new ones.
3320        //
3321        // The draws are processed in place rather than being moved out of
3322        // `next_frame.deferred_draws`: `prepaint_index` snapshots that vector's
3323        // length, so any prepaint range recorded during a round (view caches,
3324        // nested deferred draws) must index the same vector `reuse_prepaint`
3325        // slices on the next frame. Moving the draws out and re-appending them
3326        // shifts the indices of nested draws, causing reused subtrees to graft
3327        // the wrong deferred draws and panic in the dispatch tree.
3328        let mut round_start = 0;
3329        let mut depth = 0;
3330        loop {
3331            let round_end = self.next_frame.deferred_draws.len();
3332            if round_start == round_end {
3333                break;
3334            }
3335            // Limit maximum nesting depth to prevent infinite loops.
3336            assert!(depth < 10, "Exceeded maximum (10) deferred depth");
3337            depth += 1;
3338
3339            // Sort this round by priority.
3340            let mut traversal_order = (round_start..round_end).collect::<SmallVec<[usize; 8]>>();
3341            traversal_order.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
3342
3343            for deferred_draw_ix in traversal_order {
3344                let (element, parent_node, current_view, rem_size, absolute_offset, prepaint_range) = {
3345                    let deferred_draw = &mut self.next_frame.deferred_draws[deferred_draw_ix];
3346                    self.element_id_stack
3347                        .clone_from(&deferred_draw.element_id_stack);
3348                    self.text_style_stack
3349                        .clone_from(&deferred_draw.text_style_stack);
3350                    (
3351                        deferred_draw.element.take(),
3352                        deferred_draw.parent_node,
3353                        deferred_draw.current_view,
3354                        deferred_draw.rem_size,
3355                        deferred_draw.absolute_offset,
3356                        deferred_draw.prepaint_range.clone(),
3357                    )
3358                };
3359                self.next_frame.dispatch_tree.set_active_node(parent_node);
3360
3361                let prepaint_start = self.prepaint_index();
3362                if let Some(mut element) = element {
3363                    self.with_rendered_view(current_view, |window| {
3364                        window.with_rem_size(Some(rem_size), |window| {
3365                            window.with_absolute_element_offset(absolute_offset, |window| {
3366                                element.prepaint(window, cx);
3367                            });
3368                        });
3369                    });
3370                    self.next_frame.deferred_draws[deferred_draw_ix].element = Some(element);
3371                } else {
3372                    self.reuse_prepaint(prepaint_range);
3373                }
3374                let prepaint_end = self.prepaint_index();
3375                self.next_frame.deferred_draws[deferred_draw_ix].prepaint_range =
3376                    prepaint_start..prepaint_end;
3377            }
3378
3379            self.element_id_stack.clear();
3380            self.text_style_stack.clear();
3381            round_start = round_end;
3382        }
3383    }
3384
3385    fn paint_deferred_draws(&mut self, cx: &mut App) {
3386        assert_eq!(self.element_id_stack.len(), 0);
3387
3388        // Paint all deferred draws in priority order.
3389        // Since prepaint has already processed nested deferreds, we just paint them all.
3390        if self.next_frame.deferred_draws.len() == 0 {
3391            return;
3392        }
3393
3394        let traversal_order = self.deferred_draw_traversal_order();
3395        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
3396        for deferred_draw_ix in traversal_order {
3397            let mut deferred_draw = &mut deferred_draws[deferred_draw_ix];
3398            self.element_id_stack
3399                .clone_from(&deferred_draw.element_id_stack);
3400            self.next_frame
3401                .dispatch_tree
3402                .set_active_node(deferred_draw.parent_node);
3403
3404            let paint_start = self.paint_index();
3405            let content_mask = deferred_draw.content_mask;
3406            if let Some(element) = deferred_draw.element.as_mut() {
3407                self.with_rendered_view(deferred_draw.current_view, |window| {
3408                    window.with_content_mask(content_mask, |window| {
3409                        window.with_rem_size(Some(deferred_draw.rem_size), |window| {
3410                            element.paint(window, cx);
3411                        });
3412                    })
3413                })
3414            } else {
3415                self.reuse_paint(deferred_draw.paint_range.clone());
3416            }
3417            let paint_end = self.paint_index();
3418            deferred_draw.paint_range = paint_start..paint_end;
3419        }
3420        self.next_frame.deferred_draws = deferred_draws;
3421        self.element_id_stack.clear();
3422    }
3423
3424    fn deferred_draw_traversal_order(&mut self) -> SmallVec<[usize; 8]> {
3425        let deferred_count = self.next_frame.deferred_draws.len();
3426        let mut sorted_indices = (0..deferred_count).collect::<SmallVec<[_; 8]>>();
3427        sorted_indices.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
3428        sorted_indices
3429    }
3430
3431    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {
3432        PrepaintStateIndex {
3433            hitboxes_index: self.next_frame.hitboxes.len(),
3434            tooltips_index: self.next_frame.tooltip_requests.len(),
3435            deferred_draws_index: self.next_frame.deferred_draws.len(),
3436            dispatch_tree_index: self.next_frame.dispatch_tree.len(),
3437            accessed_element_states_index: self.next_frame.accessed_element_states.len(),
3438            line_layout_index: self.text_system.layout_index(),
3439        }
3440    }
3441
3442    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {
3443        self.next_frame.hitboxes.extend(
3444            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
3445                .iter()
3446                .cloned(),
3447        );
3448        self.next_frame.tooltip_requests.extend(
3449            self.rendered_frame.tooltip_requests
3450                [range.start.tooltips_index..range.end.tooltips_index]
3451                .iter_mut()
3452                .map(|request| request.take()),
3453        );
3454        self.next_frame.accessed_element_states.extend(
3455            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
3456                ..range.end.accessed_element_states_index]
3457                .iter()
3458                .map(|(id, type_id)| (id.clone(), *type_id)),
3459        );
3460        self.text_system
3461            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
3462
3463        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(
3464            range.start.dispatch_tree_index..range.end.dispatch_tree_index,
3465            &mut self.rendered_frame.dispatch_tree,
3466            self.focus,
3467        );
3468
3469        if reused_subtree.contains_focus() {
3470            self.next_frame.focus = self.focus;
3471        }
3472
3473        self.next_frame.deferred_draws.extend(
3474            self.rendered_frame.deferred_draws
3475                [range.start.deferred_draws_index..range.end.deferred_draws_index]
3476                .iter()
3477                .map(|deferred_draw| DeferredDraw {
3478                    current_view: deferred_draw.current_view,
3479                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
3480                    element_id_stack: deferred_draw.element_id_stack.clone(),
3481                    text_style_stack: deferred_draw.text_style_stack.clone(),
3482                    content_mask: deferred_draw.content_mask,
3483                    rem_size: deferred_draw.rem_size,
3484                    priority: deferred_draw.priority,
3485                    element: None,
3486                    absolute_offset: deferred_draw.absolute_offset,
3487                    prepaint_range: deferred_draw.prepaint_range.clone(),
3488                    paint_range: deferred_draw.paint_range.clone(),
3489                }),
3490        );
3491    }
3492
3493    pub(crate) fn paint_index(&self) -> PaintIndex {
3494        PaintIndex {
3495            scene_index: self.next_frame.scene.len(),
3496            mouse_listeners_index: self.next_frame.mouse_listeners.len(),
3497            input_handlers_index: self.next_frame.input_handlers.len(),
3498            cursor_styles_index: self.next_frame.cursor_styles.len(),
3499            accessed_element_states_index: self.next_frame.accessed_element_states.len(),
3500            tab_handle_index: self.next_frame.tab_stops.paint_index(),
3501            line_layout_index: self.text_system.layout_index(),
3502        }
3503    }
3504
3505    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
3506        self.next_frame.cursor_styles.extend(
3507            self.rendered_frame.cursor_styles
3508                [range.start.cursor_styles_index..range.end.cursor_styles_index]
3509                .iter()
3510                .cloned(),
3511        );
3512        self.next_frame.input_handlers.extend(
3513            self.rendered_frame.input_handlers
3514                [range.start.input_handlers_index..range.end.input_handlers_index]
3515                .iter_mut()
3516                .map(|handler| handler.take()),
3517        );
3518        self.next_frame.mouse_listeners.extend(
3519            self.rendered_frame.mouse_listeners
3520                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
3521                .iter_mut()
3522                .map(|listener| listener.take()),
3523        );
3524        self.next_frame.accessed_element_states.extend(
3525            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
3526                ..range.end.accessed_element_states_index]
3527                .iter()
3528                .map(|(id, type_id)| (id.clone(), *type_id)),
3529        );
3530        self.next_frame.tab_stops.replay(
3531            &self.rendered_frame.tab_stops.insertion_history
3532                [range.start.tab_handle_index..range.end.tab_handle_index],
3533        );
3534
3535        self.text_system
3536            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
3537        self.next_frame.scene.replay(
3538            range.start.scene_index..range.end.scene_index,
3539            &self.rendered_frame.scene,
3540        );
3541    }
3542
3543    /// Push a text style onto the stack, and call a function with that style active.
3544    /// Use [`Window::text_style`] to get the current, combined text style. This method
3545    /// should only be called as part of element drawing.
3546    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
3547    where
3548        F: FnOnce(&mut Self) -> R,
3549    {
3550        self.invalidator.debug_assert_paint_or_prepaint();
3551        if let Some(style) = style {
3552            self.text_style_stack.push(style);
3553            let result = f(self);
3554            self.text_style_stack.pop();
3555            result
3556        } else {
3557            f(self)
3558        }
3559    }
3560
3561    /// Updates the cursor style at the platform level. This method should only be called
3562    /// during the paint phase of element drawing.
3563    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
3564        self.invalidator.debug_assert_paint();
3565        self.next_frame.cursor_styles.push(CursorStyleRequest {
3566            hitbox_id: Some(hitbox.id),
3567            style,
3568        });
3569    }
3570
3571    /// Updates the cursor style for the entire window at the platform level. A cursor
3572    /// style using this method will have precedence over any cursor style set using
3573    /// `set_cursor_style`. This method should only be called during the paint
3574    /// phase of element drawing.
3575    pub fn set_window_cursor_style(&mut self, style: CursorStyle) {
3576        self.invalidator.debug_assert_paint();
3577        self.next_frame.cursor_styles.push(CursorStyleRequest {
3578            hitbox_id: None,
3579            style,
3580        })
3581    }
3582
3583    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called
3584    /// during the paint phase of element drawing.
3585    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
3586        self.invalidator.debug_assert_prepaint();
3587        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));
3588        self.next_frame
3589            .tooltip_requests
3590            .push(Some(TooltipRequest { id, tooltip }));
3591        id
3592    }
3593
3594    /// Invoke the given function with the given content mask after intersecting it
3595    /// with the current mask. This method should only be called during element drawing.
3596    // This function is called in a highly recursive manner in editor
3597    // prepainting, make sure its inlined to reduce the stack burden
3598    #[inline]
3599    pub fn with_content_mask<R>(
3600        &mut self,
3601        mask: Option<ContentMask<Pixels>>,
3602        f: impl FnOnce(&mut Self) -> R,
3603    ) -> R {
3604        self.invalidator.debug_assert_paint_or_prepaint();
3605        if let Some(mask) = mask {
3606            let mask = mask.intersect(&self.content_mask());
3607            self.content_mask_stack.push(mask);
3608            let result = f(self);
3609            self.content_mask_stack.pop();
3610            result
3611        } else {
3612            f(self)
3613        }
3614    }
3615
3616    /// Updates the global element offset relative to the current offset. This is used to implement
3617    /// scrolling. This method should only be called during the prepaint phase of element drawing.
3618    pub fn with_element_offset<R>(
3619        &mut self,
3620        offset: Point<Pixels>,
3621        f: impl FnOnce(&mut Self) -> R,
3622    ) -> R {
3623        self.invalidator.debug_assert_prepaint();
3624
3625        if offset.is_zero() {
3626            return f(self);
3627        };
3628
3629        let abs_offset = self.element_offset() + offset;
3630        self.with_absolute_element_offset(abs_offset, f)
3631    }
3632
3633    /// Updates the global element offset based on the given offset. This is used to implement
3634    /// drag handles and other manual painting of elements. This method should only be called during
3635    /// the prepaint phase of element drawing.
3636    pub fn with_absolute_element_offset<R>(
3637        &mut self,
3638        offset: Point<Pixels>,
3639        f: impl FnOnce(&mut Self) -> R,
3640    ) -> R {
3641        self.invalidator.debug_assert_prepaint();
3642        self.element_offset_stack.push(offset);
3643        let result = f(self);
3644        self.element_offset_stack.pop();
3645        result
3646    }
3647
3648    pub(crate) fn with_element_opacity<R>(
3649        &mut self,
3650        opacity: Option<f32>,
3651        f: impl FnOnce(&mut Self) -> R,
3652    ) -> R {
3653        self.invalidator.debug_assert_paint_or_prepaint();
3654
3655        let Some(opacity) = opacity else {
3656            return f(self);
3657        };
3658
3659        let previous_opacity = self.element_opacity;
3660        self.element_opacity = previous_opacity * opacity;
3661        let result = f(self);
3662        self.element_opacity = previous_opacity;
3663        result
3664    }
3665
3666    /// Perform prepaint on child elements in a "retryable" manner, so that any side effects
3667    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll
3668    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the
3669    /// element offset and prepaint again. See [`crate::List`] for an example. This method should only be
3670    /// called during the prepaint phase of element drawing.
3671    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {
3672        self.invalidator.debug_assert_prepaint();
3673        let index = self.prepaint_index();
3674        let result = f(self);
3675        if result.is_err() {
3676            self.next_frame.hitboxes.truncate(index.hitboxes_index);
3677            self.next_frame
3678                .tooltip_requests
3679                .truncate(index.tooltips_index);
3680            self.next_frame
3681                .deferred_draws
3682                .truncate(index.deferred_draws_index);
3683            self.next_frame
3684                .dispatch_tree
3685                .truncate(index.dispatch_tree_index);
3686            self.next_frame
3687                .accessed_element_states
3688                .truncate(index.accessed_element_states_index);
3689            self.text_system.truncate_layouts(index.line_layout_index);
3690        }
3691        result
3692    }
3693
3694    /// When you call this method during [`Element::prepaint`], containing elements will attempt to
3695    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call
3696    /// [`Element::prepaint`] again with a new set of bounds. See [`crate::List`] for an example of an element
3697    /// that supports this method being called on the elements it contains. This method should only be
3698    /// called during the prepaint phase of element drawing.
3699    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {
3700        self.invalidator.debug_assert_prepaint();
3701        self.requested_autoscroll = Some(bounds);
3702    }
3703
3704    /// This method can be called from a containing element such as [`crate::List`] to support the autoscroll behavior
3705    /// described in [`Self::request_autoscroll`].
3706    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {
3707        self.invalidator.debug_assert_prepaint();
3708        self.requested_autoscroll.take()
3709    }
3710
3711    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
3712    /// Your view will be re-drawn once the asset has finished loading.
3713    ///
3714    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
3715    /// time.
3716    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
3717        let (task, is_first) = cx.fetch_asset::<A>(source);
3718        task.clone().now_or_never().or_else(|| {
3719            if is_first {
3720                let entity_id = self.current_view();
3721                self.spawn(cx, {
3722                    let task = task.clone();
3723                    async move |cx| {
3724                        task.await;
3725
3726                        cx.on_next_frame(move |_, cx| {
3727                            cx.notify(entity_id);
3728                        });
3729                    }
3730                })
3731                .detach();
3732            }
3733
3734            None
3735        })
3736    }
3737
3738    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.
3739    /// Your view will not be re-drawn once the asset has finished loading.
3740    ///
3741    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
3742    /// time.
3743    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
3744        let (task, _) = cx.fetch_asset::<A>(source);
3745        task.now_or_never()
3746    }
3747    /// Obtain the current element offset. This method should only be called during the
3748    /// prepaint phase of element drawing.
3749    pub fn element_offset(&self) -> Point<Pixels> {
3750        self.invalidator.debug_assert_prepaint();
3751        self.element_offset_stack
3752            .last()
3753            .copied()
3754            .unwrap_or_default()
3755    }
3756
3757    /// Obtain the current element opacity. This method should only be called during the
3758    /// prepaint phase of element drawing.
3759    #[inline]
3760    pub(crate) fn element_opacity(&self) -> f32 {
3761        self.invalidator.debug_assert_paint_or_prepaint();
3762        self.element_opacity
3763    }
3764
3765    /// Obtain the current content mask. This method should only be called during element drawing.
3766    pub fn content_mask(&self) -> ContentMask<Pixels> {
3767        self.invalidator.debug_assert_paint_or_prepaint();
3768        self.content_mask_stack
3769            .last()
3770            .cloned()
3771            .unwrap_or_else(|| ContentMask {
3772                bounds: Bounds {
3773                    origin: Point::default(),
3774                    size: self.viewport_size,
3775                },
3776            })
3777    }
3778
3779    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.
3780    /// This can be used within a custom element to distinguish multiple sets of child elements.
3781    pub fn with_element_namespace<R>(
3782        &mut self,
3783        element_id: impl Into<ElementId>,
3784        f: impl FnOnce(&mut Self) -> R,
3785    ) -> R {
3786        self.element_id_stack.push(element_id.into());
3787        let result = f(self);
3788        self.element_id_stack.pop();
3789        result
3790    }
3791
3792    /// Use a piece of state that exists as long this element is being rendered in consecutive frames.
3793    pub fn use_keyed_state<S: 'static>(
3794        &mut self,
3795        key: impl Into<ElementId>,
3796        cx: &mut App,
3797        init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
3798    ) -> Entity<S> {
3799        let current_view = self.current_view();
3800        self.with_global_id(key.into(), |global_id, window| {
3801            window.with_element_state(global_id, |state: Option<Entity<S>>, window| {
3802                if let Some(state) = state {
3803                    (state.clone(), state)
3804                } else {
3805                    let new_state = cx.new(|cx| init(window, cx));
3806                    cx.observe(&new_state, move |_, cx| {
3807                        cx.notify(current_view);
3808                    })
3809                    .detach();
3810                    (new_state.clone(), new_state)
3811                }
3812            })
3813        })
3814    }
3815
3816    /// Use a piece of state that exists as long this element is being rendered in consecutive frames, without needing to specify a key
3817    ///
3818    /// NOTE: This method uses the location of the caller to generate an ID for this state.
3819    ///       If this is not sufficient to identify your state (e.g. you're rendering a list item),
3820    ///       you can provide a custom ElementID using the `use_keyed_state` method.
3821    #[track_caller]
3822    pub fn use_state<S: 'static>(
3823        &mut self,
3824        cx: &mut App,
3825        init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
3826    ) -> Entity<S> {
3827        self.use_keyed_state(
3828            ElementId::CodeLocation(*core::panic::Location::caller()),
3829            cx,
3830            init,
3831        )
3832    }
3833
3834    /// Updates or initializes state for an element with the given id that lives across multiple
3835    /// frames. If an element with this ID existed in the rendered frame, its state will be passed
3836    /// to the given closure. The state returned by the closure will be stored so it can be referenced
3837    /// when drawing the next frame. This method should only be called as part of element drawing.
3838    pub fn with_element_state<S, R>(
3839        &mut self,
3840        global_id: &GlobalElementId,
3841        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
3842    ) -> R
3843    where
3844        S: 'static,
3845    {
3846        self.invalidator.debug_assert_paint_or_prepaint();
3847
3848        let key = (global_id.clone(), TypeId::of::<S>());
3849        self.next_frame.accessed_element_states.push(key.clone());
3850
3851        if let Some(any) = self
3852            .next_frame
3853            .element_states
3854            .remove(&key)
3855            .or_else(|| self.rendered_frame.element_states.remove(&key))
3856        {
3857            let ElementStateBox {
3858                inner,
3859                #[cfg(debug_assertions)]
3860                type_name,
3861            } = any;
3862            // Using the extra inner option to avoid needing to reallocate a new box.
3863            let mut state_box = inner
3864                .downcast::<Option<S>>()
3865                .map_err(|_| {
3866                    #[cfg(debug_assertions)]
3867                    {
3868                        anyhow::anyhow!(
3869                            "invalid element state type for id, requested {:?}, actual: {:?}",
3870                            std::any::type_name::<S>(),
3871                            type_name
3872                        )
3873                    }
3874
3875                    #[cfg(not(debug_assertions))]
3876                    {
3877                        anyhow::anyhow!(
3878                            "invalid element state type for id, requested {:?}",
3879                            std::any::type_name::<S>(),
3880                        )
3881                    }
3882                })
3883                .unwrap();
3884
3885            let state = state_box.take().expect(
3886                "reentrant call to with_element_state for the same state type and element id",
3887            );
3888            let (result, state) = f(Some(state), self);
3889            state_box.replace(state);
3890            self.next_frame.element_states.insert(
3891                key,
3892                ElementStateBox {
3893                    inner: state_box,
3894                    #[cfg(debug_assertions)]
3895                    type_name,
3896                },
3897            );
3898            result
3899        } else {
3900            let (result, state) = f(None, self);
3901            self.next_frame.element_states.insert(
3902                key,
3903                ElementStateBox {
3904                    inner: Box::new(Some(state)),
3905                    #[cfg(debug_assertions)]
3906                    type_name: std::any::type_name::<S>(),
3907                },
3908            );
3909            result
3910        }
3911    }
3912
3913    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience
3914    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`
3915    /// when the element is guaranteed to have an id.
3916    ///
3917    /// The first option means 'no ID provided'
3918    /// The second option means 'not yet initialized'
3919    pub fn with_optional_element_state<S, R>(
3920        &mut self,
3921        global_id: Option<&GlobalElementId>,
3922        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
3923    ) -> R
3924    where
3925        S: 'static,
3926    {
3927        self.invalidator.debug_assert_paint_or_prepaint();
3928
3929        if let Some(global_id) = global_id {
3930            self.with_element_state(global_id, |state, cx| {
3931                let (result, state) = f(Some(state), cx);
3932                let state =
3933                    state.expect("you must return some state when you pass some element id");
3934                (result, state)
3935            })
3936        } else {
3937            let (result, state) = f(None, self);
3938            debug_assert!(
3939                state.is_none(),
3940                "you must not return an element state when passing None for the global id"
3941            );
3942            result
3943        }
3944    }
3945
3946    /// Executes the given closure within the context of a tab group.
3947    #[inline]
3948    pub fn with_tab_group<R>(&mut self, index: Option<isize>, f: impl FnOnce(&mut Self) -> R) -> R {
3949        if let Some(index) = index {
3950            self.next_frame.tab_stops.begin_group(index);
3951            let result = f(self);
3952            self.next_frame.tab_stops.end_group();
3953            result
3954        } else {
3955            f(self)
3956        }
3957    }
3958
3959    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree
3960    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,
3961    /// with higher values being drawn on top.
3962    ///
3963    /// When `content_mask` is provided, the deferred element will be clipped to that region during
3964    /// both prepaint and paint. When `None`, no additional clipping is applied.
3965    ///
3966    /// This method should only be called as part of the prepaint phase of element drawing.
3967    pub fn defer_draw(
3968        &mut self,
3969        element: AnyElement,
3970        absolute_offset: Point<Pixels>,
3971        priority: usize,
3972        content_mask: Option<ContentMask<Pixels>>,
3973    ) {
3974        self.invalidator.debug_assert_prepaint();
3975        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();
3976        self.next_frame.deferred_draws.push(DeferredDraw {
3977            current_view: self.current_view(),
3978            parent_node,
3979            element_id_stack: self.element_id_stack.clone(),
3980            text_style_stack: self.text_style_stack.clone(),
3981            content_mask,
3982            rem_size: self.rem_size(),
3983            priority,
3984            element: Some(element),
3985            absolute_offset,
3986            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),
3987            paint_range: PaintIndex::default()..PaintIndex::default(),
3988        });
3989    }
3990
3991    /// Creates a new painting layer for the specified bounds. A "layer" is a batch
3992    /// of geometry that are non-overlapping and have the same draw order. This is typically used
3993    /// for performance reasons.
3994    ///
3995    /// This method should only be called as part of the paint phase of element drawing.
3996    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
3997        self.invalidator.debug_assert_paint();
3998
3999        let content_mask = self.content_mask();
4000        let clipped_bounds = bounds.intersect(&content_mask.bounds);
4001        if !clipped_bounds.is_empty() {
4002            self.next_frame
4003                .scene
4004                .push_layer(self.cover_bounds(clipped_bounds));
4005        }
4006
4007        let result = f(self);
4008
4009        if !clipped_bounds.is_empty() {
4010            self.next_frame.scene.pop_layer();
4011        }
4012
4013        result
4014    }
4015
4016    /// Paint the drop (non-inset) shadows from `shadows` into the scene at the current
4017    /// z-index. Inset shadows are skipped; paint those with [`Self::paint_inset_shadows`]
4018    /// after the element's background so they layer on top of the fill.
4019    ///
4020    /// This method should only be called as part of the paint phase of element drawing.
4021    pub fn paint_drop_shadows(
4022        &mut self,
4023        bounds: Bounds<Pixels>,
4024        corner_radii: Corners<Pixels>,
4025        shadows: &[BoxShadow],
4026    ) {
4027        self.invalidator.debug_assert_paint();
4028
4029        let scale_factor = self.scale_factor();
4030        let content_mask = self.snapped_content_mask();
4031        let opacity = self.element_opacity();
4032        let element_bounds = self.cover_bounds(bounds);
4033        let element_corner_radii = corner_radii.scale(scale_factor);
4034        for shadow in shadows {
4035            if shadow.inset {
4036                continue;
4037            }
4038            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);
4039            self.next_frame.scene.insert_primitive(Shadow {
4040                order: 0,
4041                blur_radius: shadow.blur_radius.scale(scale_factor),
4042                bounds: self.cover_bounds(shadow_bounds),
4043                content_mask,
4044                corner_radii: corner_radii.scale(scale_factor),
4045                color: shadow.color.opacity(opacity),
4046                element_bounds,
4047                element_corner_radii,
4048                inset: 0,
4049                pad: 0,
4050            });
4051        }
4052    }
4053
4054    /// Paint the inset shadows from `shadows` into the scene at the current z-index. Should
4055    /// be called after the element's background so the shadow layers on top of the fill.
4056    /// Drop shadows are skipped; paint those with [`Self::paint_drop_shadows`] before the background.
4057    pub fn paint_inset_shadows(
4058        &mut self,
4059        bounds: Bounds<Pixels>,
4060        corner_radii: Corners<Pixels>,
4061        shadows: &[BoxShadow],
4062    ) {
4063        self.invalidator.debug_assert_paint();
4064
4065        let scale_factor = self.scale_factor();
4066        let content_mask = self.snapped_content_mask();
4067        let opacity = self.element_opacity();
4068        let element_bounds = self.cover_bounds(bounds);
4069        let element_corner_radii = corner_radii.scale(scale_factor);
4070        for shadow in shadows {
4071            if !shadow.inset {
4072                continue;
4073            }
4074            let hole = (bounds + shadow.offset).dilate(-shadow.spread_radius);
4075            // Clamp at zero so a large spread can't produce negative radii, which would
4076            // break the SDF in the shader.
4077            let zero = Pixels::ZERO;
4078            let hole_corner_radii = Corners {
4079                top_left: (corner_radii.top_left - shadow.spread_radius).max(zero),
4080                top_right: (corner_radii.top_right - shadow.spread_radius).max(zero),
4081                bottom_right: (corner_radii.bottom_right - shadow.spread_radius).max(zero),
4082                bottom_left: (corner_radii.bottom_left - shadow.spread_radius).max(zero),
4083            };
4084            self.next_frame.scene.insert_primitive(Shadow {
4085                order: 0,
4086                blur_radius: shadow.blur_radius.scale(scale_factor),
4087                bounds: self.cover_bounds(hole),
4088                content_mask,
4089                corner_radii: hole_corner_radii.scale(scale_factor),
4090                color: shadow.color.opacity(opacity),
4091                element_bounds,
4092                element_corner_radii,
4093                inset: 1,
4094                pad: 0,
4095            });
4096        }
4097    }
4098
4099    fn largest_border_interior(quad: &Quad) -> Bounds<ScaledPixels> {
4100        let radii = &quad.corner_radii;
4101        let widths = &quad.border_widths;
4102        let edge_radii = Edges {
4103            top: radii.top_left.max(radii.top_right),
4104            right: radii.top_right.max(radii.bottom_right),
4105            bottom: radii.bottom_left.max(radii.bottom_right),
4106            left: radii.top_left.max(radii.bottom_left),
4107        };
4108
4109        let antialias_inset = point(ScaledPixels(1.0), ScaledPixels(1.0));
4110        let inset_bounds = |top_left_inset, bottom_right_inset| {
4111            Bounds::from_corners(
4112                quad.bounds.origin + top_left_inset + antialias_inset,
4113                quad.bounds.bottom_right() - bottom_right_inset - antialias_inset,
4114            )
4115        };
4116
4117        // Rounded corners need only be excluded on one axis. Either candidate
4118        // is empty of border pixels, so use the larger interior.
4119        let horizontal_band = inset_bounds(
4120            point(widths.left, widths.top.max(edge_radii.top)),
4121            point(widths.right, widths.bottom.max(edge_radii.bottom)),
4122        );
4123        let vertical_band = inset_bounds(
4124            point(widths.left.max(edge_radii.left), widths.top),
4125            point(widths.right.max(edge_radii.right), widths.bottom),
4126        );
4127
4128        let area = |bounds: &Bounds<ScaledPixels>| {
4129            bounds.size.width.0.max(0.) * bounds.size.height.0.max(0.)
4130        };
4131        if area(&horizontal_band) >= area(&vertical_band) {
4132            horizontal_band
4133        } else {
4134            vertical_band
4135        }
4136    }
4137
4138    /// Paint one or more quads into the scene for the next frame at the current stacking context.
4139    /// Quads are colored rectangular regions with an optional background, border, and corner radius.
4140    /// see [`fill`], [`outline`], and [`quad`] to construct this type.
4141    ///
4142    /// This method should only be called as part of the paint phase of element drawing.
4143    ///
4144    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners
4145    /// where the circular arcs meet. This will not display well when combined with dashed borders.
4146    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.
4147    pub fn paint_quad(&mut self, quad: PaintQuad) {
4148        self.invalidator.debug_assert_paint();
4149
4150        let opacity = self.element_opacity();
4151        let snapped_bounds = self.snap_bounds(quad.bounds);
4152        let snapped_border_widths = self.snap_border_widths(quad.border_widths);
4153        let quad = Quad {
4154            order: 0,
4155            bounds: snapped_bounds,
4156            content_mask: self.snapped_content_mask(),
4157            background: quad.background.opacity(opacity),
4158            border_color: quad.border_color.opacity(opacity),
4159            corner_radii: quad.corner_radii.scale(self.scale_factor()),
4160            border_widths: snapped_border_widths,
4161            border_style: quad.border_style,
4162        };
4163
4164        if !quad.background.is_transparent() {
4165            self.next_frame.scene.insert_primitive(quad);
4166            return;
4167        }
4168
4169        // Splitting a border-only quad around its empty interior avoids shading
4170        // every transparent pixel inside large outlines.
4171        let outer_bounds = quad.bounds;
4172        let inner_bounds = Self::largest_border_interior(&quad);
4173
4174        if inner_bounds.is_empty() {
4175            self.next_frame.scene.insert_primitive(quad);
4176            return;
4177        }
4178
4179        let strips = [
4180            // Top
4181            Bounds::from_corners(
4182                outer_bounds.origin,
4183                point(outer_bounds.right(), inner_bounds.top()),
4184            ),
4185            // Bottom
4186            Bounds::from_corners(
4187                point(outer_bounds.left(), inner_bounds.bottom()),
4188                outer_bounds.bottom_right(),
4189            ),
4190            // Left
4191            Bounds::from_corners(
4192                point(outer_bounds.left(), inner_bounds.top()),
4193                inner_bounds.bottom_left(),
4194            ),
4195            // Right
4196            Bounds::from_corners(
4197                inner_bounds.top_right(),
4198                point(outer_bounds.right(), inner_bounds.bottom()),
4199            ),
4200        ];
4201
4202        for strip in strips {
4203            let content_mask_bounds = quad.content_mask.bounds.intersect(&strip);
4204            if !content_mask_bounds.is_empty() {
4205                self.next_frame.scene.insert_primitive(Quad {
4206                    content_mask: ContentMask {
4207                        bounds: content_mask_bounds,
4208                    },
4209                    ..quad
4210                });
4211            }
4212        }
4213    }
4214
4215    /// Paint the given `Path` into the scene for the next frame at the current z-index.
4216    ///
4217    /// This method should only be called as part of the paint phase of element drawing.
4218    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {
4219        self.invalidator.debug_assert_paint();
4220
4221        let scale_factor = self.scale_factor();
4222        let content_mask = self.content_mask();
4223        let opacity = self.element_opacity();
4224        path.content_mask = content_mask;
4225        let color: Background = color.into();
4226        path.color = color.opacity(opacity);
4227        self.next_frame
4228            .scene
4229            .insert_primitive(path.scale(scale_factor));
4230    }
4231
4232    /// Paint an underline into the scene for the next frame at the current z-index.
4233    ///
4234    /// This method should only be called as part of the paint phase of element drawing.
4235    pub fn paint_underline(
4236        &mut self,
4237        origin: Point<Pixels>,
4238        width: Pixels,
4239        style: &UnderlineStyle,
4240    ) {
4241        self.invalidator.debug_assert_paint();
4242
4243        let scale_factor = self.scale_factor();
4244        let thickness = self.snap_stroke(style.thickness);
4245        let height = if style.wavy {
4246            ScaledPixels(thickness.0 * 3.)
4247        } else {
4248            thickness
4249        };
4250        let bounds = Bounds {
4251            origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
4252            size: size(self.snap_stroke(width), height),
4253        };
4254        let element_opacity = self.element_opacity();
4255
4256        self.next_frame.scene.insert_primitive(Underline {
4257            order: 0,
4258            pad: 0,
4259            bounds,
4260            content_mask: self.snapped_content_mask(),
4261            color: style.color.unwrap_or_default().opacity(element_opacity),
4262            thickness,
4263            wavy: style.wavy.into(),
4264        });
4265    }
4266
4267    /// Paint a strikethrough into the scene for the next frame at the current z-index.
4268    ///
4269    /// This method should only be called as part of the paint phase of element drawing.
4270    pub fn paint_strikethrough(
4271        &mut self,
4272        origin: Point<Pixels>,
4273        width: Pixels,
4274        style: &StrikethroughStyle,
4275    ) {
4276        self.invalidator.debug_assert_paint();
4277
4278        let scale_factor = self.scale_factor();
4279        let height = style.thickness;
4280        let bounds = Bounds {
4281            origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
4282            size: size(self.snap_stroke(width), self.snap_stroke(height)),
4283        };
4284        let opacity = self.element_opacity();
4285
4286        self.next_frame.scene.insert_primitive(Underline {
4287            order: 0,
4288            pad: 0,
4289            bounds,
4290            content_mask: self.snapped_content_mask(),
4291            thickness: self.snap_stroke(style.thickness),
4292            color: style.color.unwrap_or_default().opacity(opacity),
4293            wavy: false.into(),
4294        });
4295    }
4296
4297    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
4298    ///
4299    /// The y component of the origin is the baseline of the glyph.
4300    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
4301    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
4302    /// This method is only useful if you need to paint a single glyph that has already been shaped.
4303    ///
4304    /// This method should only be called as part of the paint phase of element drawing.
4305    pub fn paint_glyph(
4306        &mut self,
4307        origin: Point<Pixels>,
4308        font_id: FontId,
4309        glyph_id: GlyphId,
4310        font_size: Pixels,
4311        color: Hsla,
4312    ) -> Result<()> {
4313        self.invalidator.debug_assert_paint();
4314
4315        let element_opacity = self.element_opacity();
4316        let scale_factor = self.scale_factor();
4317        let glyph_origin = origin.scale(scale_factor);
4318
4319        let quantized_origin = Point::new(
4320            round_half_toward_zero(glyph_origin.x.0 * SUBPIXEL_VARIANTS_X as f32)
4321                / SUBPIXEL_VARIANTS_X as f32,
4322            round_half_toward_zero(glyph_origin.y.0 * SUBPIXEL_VARIANTS_Y as f32)
4323                / SUBPIXEL_VARIANTS_Y as f32,
4324        );
4325        let subpixel_variant = Point::new(
4326            (quantized_origin.x.fract() * SUBPIXEL_VARIANTS_X as f32) as u8,
4327            (quantized_origin.y.fract() * SUBPIXEL_VARIANTS_Y as f32) as u8,
4328        );
4329        let integer_origin = quantized_origin.map(|c| ScaledPixels(c.trunc()));
4330        let subpixel_rendering = self.should_use_subpixel_rendering(font_id, font_size);
4331        let dilation = self.text_system().glyph_dilation_for_color(color);
4332        let params = RenderGlyphParams {
4333            font_id,
4334            glyph_id,
4335            font_size,
4336            subpixel_variant,
4337            scale_factor,
4338            is_emoji: false,
4339            subpixel_rendering,
4340            dilation,
4341        };
4342
4343        let raster_bounds = self.text_system().raster_bounds(&params)?;
4344        if !raster_bounds.is_zero() {
4345            let tile = self
4346                .sprite_atlas
4347                .get_or_insert_with(&params.clone().into(), &mut || {
4348                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;
4349                    Ok(Some((size, Cow::Owned(bytes))))
4350                })?
4351                .expect("Callback above only errors or returns Some");
4352            let bounds = Bounds {
4353                origin: integer_origin + raster_bounds.origin.map(Into::into),
4354                size: tile.bounds.size.map(Into::into),
4355            };
4356            let content_mask = self.snapped_content_mask();
4357
4358            if subpixel_rendering {
4359                self.next_frame.scene.insert_primitive(SubpixelSprite {
4360                    order: 0,
4361                    pad: 0,
4362                    bounds,
4363                    content_mask,
4364                    color: color.opacity(element_opacity),
4365                    tile,
4366                    transformation: TransformationMatrix::unit(),
4367                });
4368            } else {
4369                self.next_frame.scene.insert_primitive(MonochromeSprite {
4370                    order: 0,
4371                    pad: 0,
4372                    bounds,
4373                    content_mask,
4374                    color: color.opacity(element_opacity),
4375                    tile,
4376                    transformation: TransformationMatrix::unit(),
4377                });
4378            }
4379        }
4380        Ok(())
4381    }
4382
4383    fn should_use_subpixel_rendering(&self, font_id: FontId, font_size: Pixels) -> bool {
4384        if self.platform_window.background_appearance() != WindowBackgroundAppearance::Opaque {
4385            return false;
4386        }
4387
4388        if !self.platform_window.is_subpixel_rendering_supported() {
4389            return false;
4390        }
4391
4392        let mode = match self.text_rendering_mode.get() {
4393            TextRenderingMode::PlatformDefault => self
4394                .text_system()
4395                .recommended_rendering_mode(font_id, font_size),
4396            mode => mode,
4397        };
4398
4399        mode == TextRenderingMode::Subpixel
4400    }
4401
4402    /// Paints an emoji glyph into the scene for the next frame at the current z-index.
4403    ///
4404    /// The y component of the origin is the baseline of the glyph.
4405    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
4406    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
4407    /// This method is only useful if you need to paint a single emoji that has already been shaped.
4408    ///
4409    /// This method should only be called as part of the paint phase of element drawing.
4410    pub fn paint_emoji(
4411        &mut self,
4412        origin: Point<Pixels>,
4413        font_id: FontId,
4414        glyph_id: GlyphId,
4415        font_size: Pixels,
4416    ) -> Result<()> {
4417        self.invalidator.debug_assert_paint();
4418
4419        let scale_factor = self.scale_factor();
4420        let glyph_origin = origin.scale(scale_factor);
4421        let integer_origin = glyph_origin.map(|c| ScaledPixels(round_half_toward_zero(c.0)));
4422        let params = RenderGlyphParams {
4423            font_id,
4424            glyph_id,
4425            font_size,
4426            subpixel_variant: Default::default(),
4427            scale_factor,
4428            is_emoji: true,
4429            subpixel_rendering: false,
4430            dilation: 0,
4431        };
4432
4433        let raster_bounds = self.text_system().raster_bounds(&params)?;
4434        if !raster_bounds.is_zero() {
4435            let tile = self
4436                .sprite_atlas
4437                .get_or_insert_with(&params.clone().into(), &mut || {
4438                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;
4439                    Ok(Some((size, Cow::Owned(bytes))))
4440                })?
4441                .expect("Callback above only errors or returns Some");
4442
4443            let bounds = Bounds {
4444                origin: integer_origin + raster_bounds.origin.map(Into::into),
4445                size: tile.bounds.size.map(Into::into),
4446            };
4447            let content_mask = self.snapped_content_mask();
4448            let opacity = self.element_opacity();
4449
4450            self.next_frame.scene.insert_primitive(PolychromeSprite {
4451                order: 0,
4452                pad: 0,
4453                grayscale: false.into(),
4454                bounds,
4455                corner_radii: Default::default(),
4456                content_mask,
4457                tile,
4458                opacity,
4459            });
4460        }
4461        Ok(())
4462    }
4463
4464    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
4465    ///
4466    /// This method should only be called as part of the paint phase of element drawing.
4467    pub fn paint_svg(
4468        &mut self,
4469        bounds: Bounds<Pixels>,
4470        path: SharedString,
4471        mut data: Option<&[u8]>,
4472        transformation: TransformationMatrix,
4473        color: Hsla,
4474        cx: &App,
4475    ) -> Result<()> {
4476        self.invalidator.debug_assert_paint();
4477
4478        let element_opacity = self.element_opacity();
4479        let bounds = self.snap_bounds(bounds);
4480
4481        let params = RenderSvgParams {
4482            path,
4483            size: bounds.size.map(|pixels| {
4484                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)
4485            }),
4486        };
4487
4488        let Some(tile) =
4489            self.sprite_atlas
4490                .get_or_insert_with(&params.clone().into(), &mut || {
4491                    let Some((size, bytes)) = cx.svg_renderer.render_alpha_mask(&params, data)?
4492                    else {
4493                        return Ok(None);
4494                    };
4495                    Ok(Some((size, Cow::Owned(bytes))))
4496                })?
4497        else {
4498            return Ok(());
4499        };
4500        let content_mask = self.snapped_content_mask();
4501        let svg_bounds = Bounds {
4502            origin: bounds.center()
4503                - Point::new(
4504                    ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
4505                    ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
4506                ),
4507            size: tile
4508                .bounds
4509                .size
4510                .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)),
4511        };
4512        let final_bounds = svg_bounds
4513            .map_origin(|value| ScaledPixels(round_half_toward_zero(value.0)))
4514            .map_size(|size| size.ceil());
4515
4516        self.next_frame.scene.insert_primitive(MonochromeSprite {
4517            order: 0,
4518            pad: 0,
4519            bounds: final_bounds,
4520            content_mask,
4521            color: color.opacity(element_opacity),
4522            tile,
4523            transformation,
4524        });
4525
4526        Ok(())
4527    }
4528
4529    /// Paint an image into the scene for the next frame at the current z-index.
4530    /// This method will panic if the frame_index is not valid
4531    ///
4532    /// This method should only be called as part of the paint phase of element drawing.
4533    /// Paint an image into `bounds`, positioning and scaling it according to `image_bounds`.
4534    ///
4535    /// The visible region rendered is `bounds.intersect(&image_bounds)`, with `corner_radii`
4536    /// applied to `bounds`.
4537    pub fn paint_image(
4538        &mut self,
4539        bounds: Bounds<Pixels>,
4540        image_bounds: Bounds<Pixels>,
4541        corner_radii: Corners<Pixels>,
4542        data: Arc<RenderImage>,
4543        frame_index: usize,
4544        grayscale: bool,
4545    ) -> Result<()> {
4546        self.invalidator.debug_assert_paint();
4547
4548        let visible_bounds = bounds.intersect(&image_bounds);
4549        if visible_bounds.size.width <= Pixels::ZERO || visible_bounds.size.height <= Pixels::ZERO {
4550            return Ok(());
4551        }
4552        if image_bounds.size.width <= Pixels::ZERO || image_bounds.size.height <= Pixels::ZERO {
4553            return Ok(());
4554        }
4555
4556        let params = RenderImageParams {
4557            image_id: data.id,
4558            frame_index,
4559        };
4560
4561        let tile = self
4562            .sprite_atlas
4563            .get_or_insert_with(&params.into(), &mut || {
4564                Ok(Some((
4565                    data.size(frame_index),
4566                    Cow::Borrowed(
4567                        data.as_bytes(frame_index)
4568                            .expect("It's the caller's job to pass a valid frame index"),
4569                    ),
4570                )))
4571            })?
4572            .expect("Callback above only returns Some");
4573
4574        let visible_bounds_snapped = self.snap_bounds(visible_bounds);
4575
4576        let sub_tile = if visible_bounds == image_bounds {
4577            tile
4578        } else {
4579            let x_offset_ratio =
4580                (visible_bounds.origin.x - image_bounds.origin.x) / image_bounds.size.width;
4581            let y_offset_ratio =
4582                (visible_bounds.origin.y - image_bounds.origin.y) / image_bounds.size.height;
4583            let width_ratio = visible_bounds.size.width / image_bounds.size.width;
4584            let height_ratio = visible_bounds.size.height / image_bounds.size.height;
4585
4586            let tile_origin_x = tile.bounds.origin.x.0;
4587            let tile_origin_y = tile.bounds.origin.y.0;
4588            let tile_width = tile.bounds.size.width.0;
4589            let tile_height = tile.bounds.size.height.0;
4590
4591            let sub_origin_x = tile_origin_x + (x_offset_ratio * tile_width as f32).round() as i32;
4592            let sub_origin_y = tile_origin_y + (y_offset_ratio * tile_height as f32).round() as i32;
4593            let sub_width = (width_ratio * tile_width as f32).round() as i32;
4594            let sub_height = (height_ratio * tile_height as f32).round() as i32;
4595
4596            let max_x = tile_origin_x + tile_width;
4597            let max_y = tile_origin_y + tile_height;
4598
4599            let clamped_origin_x = sub_origin_x.clamp(tile_origin_x, max_x);
4600            let clamped_origin_y = sub_origin_y.clamp(tile_origin_y, max_y);
4601            let clamped_width = sub_width.min(max_x - clamped_origin_x).max(0);
4602            let clamped_height = sub_height.min(max_y - clamped_origin_y).max(0);
4603
4604            AtlasTile {
4605                bounds: Bounds {
4606                    origin: point(
4607                        DevicePixels(clamped_origin_x),
4608                        DevicePixels(clamped_origin_y),
4609                    ),
4610                    size: size(DevicePixels(clamped_width), DevicePixels(clamped_height)),
4611                },
4612                ..tile
4613            }
4614        };
4615
4616        let content_mask = self.snapped_content_mask();
4617        let corner_radii = corner_radii
4618            .clamp_radii_for_quad_size(visible_bounds.size)
4619            .scale(self.scale_factor());
4620        let opacity = self.element_opacity();
4621
4622        self.next_frame.scene.insert_primitive(PolychromeSprite {
4623            order: 0,
4624            pad: 0,
4625            grayscale: grayscale.into(),
4626            bounds: visible_bounds_snapped,
4627            content_mask,
4628            corner_radii,
4629            tile: sub_tile,
4630            opacity,
4631        });
4632        Ok(())
4633    }
4634
4635    /// Paint a surface into the scene for the next frame at the current z-index.
4636    ///
4637    /// This method should only be called as part of the paint phase of element drawing.
4638    #[cfg(target_os = "macos")]
4639    pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {
4640        use crate::PaintSurface;
4641
4642        self.invalidator.debug_assert_paint();
4643
4644        let bounds = self.snap_bounds(bounds);
4645        let content_mask = self.snapped_content_mask();
4646        self.next_frame.scene.insert_primitive(PaintSurface {
4647            order: 0,
4648            bounds,
4649            content_mask,
4650            image_buffer,
4651        });
4652    }
4653
4654    /// Removes an image from the sprite atlas.
4655    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {
4656        for frame_index in 0..data.frame_count() {
4657            let params = RenderImageParams {
4658                image_id: data.id,
4659                frame_index,
4660            };
4661
4662            self.sprite_atlas.remove(&params.clone().into());
4663        }
4664
4665        Ok(())
4666    }
4667
4668    /// Returns whether every frame of an image is present in the sprite atlas.
4669    #[cfg(any(test, feature = "test-support"))]
4670    pub fn has_image_atlas_entry(&self, data: &RenderImage) -> bool {
4671        data.frame_count() > 0
4672            && (0..data.frame_count()).all(|frame_index| {
4673                self.sprite_atlas.contains(
4674                    &RenderImageParams {
4675                        image_id: data.id,
4676                        frame_index,
4677                    }
4678                    .into(),
4679                )
4680            })
4681    }
4682
4683    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
4684    /// layout is being requested, along with the layout ids of any children. This method is called during
4685    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.
4686    ///
4687    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.
4688    #[must_use]
4689    pub fn request_layout(
4690        &mut self,
4691        style: Style,
4692        children: impl IntoIterator<Item = LayoutId>,
4693        cx: &mut App,
4694    ) -> LayoutId {
4695        self.invalidator.debug_assert_prepaint();
4696
4697        cx.layout_id_buffer.clear();
4698        cx.layout_id_buffer.extend(children);
4699        let rem_size = self.rem_size();
4700        let scale_factor = self.scale_factor();
4701
4702        self.layout_engine.as_mut().unwrap().request_layout(
4703            style,
4704            rem_size,
4705            scale_factor,
4706            &cx.layout_id_buffer,
4707        )
4708    }
4709
4710    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
4711    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
4712    /// determine the element's size. One place this is used internally is when measuring text.
4713    ///
4714    /// The given closure is invoked at layout time with the known dimensions and available space and
4715    /// returns a `Size`.
4716    ///
4717    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.
4718    pub fn request_measured_layout<F>(&mut self, style: Style, measure: F) -> LayoutId
4719    where
4720        F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
4721            + 'static,
4722    {
4723        self.invalidator.debug_assert_prepaint();
4724
4725        let rem_size = self.rem_size();
4726        let scale_factor = self.scale_factor();
4727        self.layout_engine
4728            .as_mut()
4729            .unwrap()
4730            .request_measured_layout(style, rem_size, scale_factor, measure)
4731    }
4732
4733    /// Compute the layout for the given id within the given available space.
4734    /// This method is called for its side effect, typically by the framework prior to painting.
4735    /// After calling it, you can request the bounds of the given layout node id or any descendant.
4736    ///
4737    /// This method should only be called as part of the prepaint phase of element drawing.
4738    pub fn compute_layout(
4739        &mut self,
4740        layout_id: LayoutId,
4741        available_space: Size<AvailableSpace>,
4742        cx: &mut App,
4743    ) {
4744        self.invalidator.debug_assert_prepaint();
4745
4746        let mut layout_engine = self.layout_engine.take().unwrap();
4747        layout_engine.compute_layout(layout_id, available_space, self, cx);
4748        self.layout_engine = Some(layout_engine);
4749    }
4750
4751    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by
4752    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.
4753    ///
4754    /// This method should only be called as part of element drawing.
4755    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
4756        self.invalidator.debug_assert_prepaint();
4757
4758        let scale_factor = self.scale_factor();
4759        let mut bounds = self
4760            .layout_engine
4761            .as_mut()
4762            .unwrap()
4763            .layout_bounds(layout_id, scale_factor)
4764            .map(Into::into);
4765        let snapped_offset = self.pixel_snap_point(self.element_offset());
4766        bounds.origin += snapped_offset;
4767        bounds
4768    }
4769
4770    /// This method should be called during `prepaint`. You can use
4771    /// the returned [Hitbox] during `paint` or in an event handler
4772    /// to determine whether the inserted hitbox was the topmost.
4773    ///
4774    /// This method should only be called as part of the prepaint phase of element drawing.
4775    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, behavior: HitboxBehavior) -> Hitbox {
4776        self.invalidator.debug_assert_prepaint();
4777
4778        let content_mask = self.content_mask();
4779        let mut id = self.next_hitbox_id;
4780        self.next_hitbox_id = self.next_hitbox_id.next();
4781        let hitbox = Hitbox {
4782            id,
4783            bounds,
4784            content_mask,
4785            behavior,
4786        };
4787        self.next_frame.hitboxes.push(hitbox.clone());
4788        hitbox
4789    }
4790
4791    /// Set a hitbox which will act as a control area of the platform window.
4792    ///
4793    /// This method should only be called as part of the paint phase of element drawing.
4794    pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) {
4795        self.invalidator.debug_assert_paint();
4796        self.next_frame.window_control_hitboxes.push((area, hitbox));
4797    }
4798
4799    /// Sets the key context for the current element. This context will be used to translate
4800    /// keybindings into actions.
4801    ///
4802    /// This method should only be called as part of the paint phase of element drawing.
4803    pub fn set_key_context(&mut self, context: KeyContext) {
4804        self.invalidator.debug_assert_paint();
4805        self.next_frame.dispatch_tree.set_key_context(context);
4806    }
4807
4808    /// Sets the focus handle for the current element. This handle will be used to manage focus state
4809    /// and keyboard event dispatch for the element.
4810    ///
4811    /// This method should only be called as part of the prepaint phase of element drawing.
4812    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {
4813        self.invalidator.debug_assert_prepaint();
4814        if focus_handle.is_focused(self) {
4815            self.next_frame.focus = Some(focus_handle.id);
4816        }
4817        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);
4818    }
4819
4820    /// Sets the view id for the current element, which will be used to manage view caching.
4821    ///
4822    /// This method should only be called as part of element prepaint. We plan on removing this
4823    /// method eventually when we solve some issues that require us to construct editor elements
4824    /// directly instead of always using editors via views.
4825    pub fn set_view_id(&mut self, view_id: EntityId) {
4826        self.invalidator.debug_assert_prepaint();
4827        self.next_frame.dispatch_tree.set_view_id(view_id);
4828    }
4829
4830    /// Get the entity ID for the currently rendering view
4831    pub fn current_view(&self) -> EntityId {
4832        self.invalidator.debug_assert_paint_or_prepaint();
4833        self.rendered_entity_stack.last().copied().unwrap()
4834    }
4835
4836    #[inline]
4837    pub(crate) fn with_rendered_view<R>(
4838        &mut self,
4839        id: EntityId,
4840        f: impl FnOnce(&mut Self) -> R,
4841    ) -> R {
4842        self.rendered_entity_stack.push(id);
4843        let result = f(self);
4844        self.rendered_entity_stack.pop();
4845        result
4846    }
4847
4848    /// Executes the provided function with the specified image cache.
4849    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R
4850    where
4851        F: FnOnce(&mut Self) -> R,
4852    {
4853        if let Some(image_cache) = image_cache {
4854            self.image_cache_stack.push(image_cache);
4855            let result = f(self);
4856            self.image_cache_stack.pop();
4857            result
4858        } else {
4859            f(self)
4860        }
4861    }
4862
4863    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
4864    /// platform to receive textual input with proper integration with concerns such
4865    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
4866    /// rendered.
4867    ///
4868    /// This method should only be called as part of the paint phase of element drawing.
4869    ///
4870    /// [element_input_handler]: crate::ElementInputHandler
4871    pub fn handle_input(
4872        &mut self,
4873        focus_handle: &FocusHandle,
4874        input_handler: impl InputHandler,
4875        cx: &App,
4876    ) {
4877        self.invalidator.debug_assert_paint();
4878
4879        if focus_handle.is_focused(self) {
4880            let cx = self.to_async(cx);
4881            self.next_frame
4882                .input_handlers
4883                .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));
4884        }
4885    }
4886
4887    /// Forwards the focused input handler's [`TextInputConfiguration`] to the
4888    /// platform window when it differs from the last forwarded value. With no
4889    /// input handler the default configuration applies, so a field's
4890    /// preferences don't outlive its focus.
4891    fn apply_text_input_configuration(&mut self, cx: &mut App) {
4892        let configuration = match self.platform_window.take_input_handler() {
4893            Some(mut input_handler) => {
4894                let configuration = input_handler.text_input_configuration(self, cx);
4895                self.platform_window.set_input_handler(input_handler);
4896                configuration
4897            }
4898            None => TextInputConfiguration::default(),
4899        };
4900        if self.last_text_input_configuration.as_ref() != Some(&configuration) {
4901            self.platform_window
4902                .set_text_input_configuration(configuration.clone());
4903            self.last_text_input_configuration = Some(configuration);
4904        }
4905    }
4906
4907    /// Register a mouse event listener on the window for the next frame. The type of event
4908    /// is determined by the first parameter of the given listener. When the next frame is rendered
4909    /// the listener will be cleared.
4910    ///
4911    /// This method should only be called as part of the paint phase of element drawing.
4912    pub fn on_mouse_event<Event: MouseEvent>(
4913        &mut self,
4914        mut listener: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
4915    ) {
4916        self.invalidator.debug_assert_paint();
4917
4918        self.next_frame.mouse_listeners.push(Some(Box::new(
4919            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {
4920                if let Some(event) = event.downcast_ref() {
4921                    listener(event, phase, window, cx)
4922                }
4923            },
4924        )));
4925    }
4926
4927    /// Register a key event listener on this node for the next frame. The type of event
4928    /// is determined by the first parameter of the given listener. When the next frame is rendered
4929    /// the listener will be cleared.
4930    ///
4931    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
4932    /// a specific need to register a listener yourself.
4933    ///
4934    /// This method should only be called as part of the paint phase of element drawing.
4935    pub fn on_key_event<Event: KeyEvent>(
4936        &mut self,
4937        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
4938    ) {
4939        self.invalidator.debug_assert_paint();
4940
4941        self.next_frame.dispatch_tree.on_key_event(Rc::new(
4942            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {
4943                if let Some(event) = event.downcast_ref::<Event>() {
4944                    listener(event, phase, window, cx)
4945                }
4946            },
4947        ));
4948    }
4949
4950    /// Register a modifiers changed event listener on the window for the next frame.
4951    ///
4952    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
4953    /// a specific need to register a global listener.
4954    ///
4955    /// This method should only be called as part of the paint phase of element drawing.
4956    pub fn on_modifiers_changed(
4957        &mut self,
4958        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
4959    ) {
4960        self.invalidator.debug_assert_paint();
4961
4962        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(
4963            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {
4964                listener(event, window, cx)
4965            },
4966        ));
4967    }
4968
4969    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
4970    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.
4971    /// Returns a subscription and persists until the subscription is dropped.
4972    pub fn on_focus_in(
4973        &mut self,
4974        handle: &FocusHandle,
4975        cx: &mut App,
4976        mut listener: impl FnMut(&mut Window, &mut App) + 'static,
4977    ) -> Subscription {
4978        let focus_id = handle.id;
4979        let (subscription, activate) =
4980            self.new_focus_listener(Box::new(move |event, window, cx| {
4981                if event.is_focus_in(focus_id) {
4982                    listener(window, cx);
4983                }
4984                true
4985            }));
4986        cx.defer(move |_| activate());
4987        subscription
4988    }
4989
4990    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
4991    /// Returns a subscription and persists until the subscription is dropped.
4992    pub fn on_focus_out(
4993        &mut self,
4994        handle: &FocusHandle,
4995        cx: &mut App,
4996        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,
4997    ) -> Subscription {
4998        let focus_id = handle.id;
4999        let (subscription, activate) =
5000            self.new_focus_listener(Box::new(move |event, window, cx| {
5001                if let Some(blurred_id) = event.previous_focus_path.last().copied()
5002                    && event.is_focus_out(focus_id)
5003                {
5004                    let event = FocusOutEvent {
5005                        blurred: WeakFocusHandle {
5006                            id: blurred_id,
5007                            handles: Arc::downgrade(&cx.focus_handles),
5008                        },
5009                    };
5010                    listener(event, window, cx)
5011                }
5012                true
5013            }));
5014        cx.defer(move |_| activate());
5015        subscription
5016    }
5017
5018    fn reset_cursor_style(&self, cx: &mut App) {
5019        // Set the cursor only if we're the active window.
5020        if self.is_window_hovered() {
5021            let style = self
5022                .rendered_frame
5023                .cursor_style(self)
5024                .unwrap_or(CursorStyle::Arrow);
5025            cx.platform.set_cursor_style(style);
5026        }
5027    }
5028
5029    /// Dispatch a given keystroke as though the user had typed it.
5030    /// You can create a keystroke with Keystroke::parse("").
5031    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {
5032        let keystroke = keystroke.with_simulated_ime();
5033        let result = self.dispatch_event(
5034            PlatformInput::KeyDown(KeyDownEvent {
5035                keystroke: keystroke.clone(),
5036                is_held: false,
5037                prefer_character_input: false,
5038            }),
5039            cx,
5040        );
5041        if !result.propagate {
5042            return true;
5043        }
5044
5045        if let Some(input) = keystroke.key_char
5046            && let Some(mut input_handler) = self.platform_window.take_input_handler()
5047        {
5048            input_handler.dispatch_input(&input, self, cx);
5049            self.platform_window.set_input_handler(input_handler);
5050            return true;
5051        }
5052
5053        false
5054    }
5055
5056    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence
5057    /// binding for the action (last binding added to the keymap).
5058    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {
5059        self.highest_precedence_binding_for_action(action)
5060            .map(|binding| {
5061                binding
5062                    .keystrokes()
5063                    .iter()
5064                    .map(ToString::to_string)
5065                    .collect::<Vec<_>>()
5066                    .join(" ")
5067            })
5068            .unwrap_or_else(|| action.name().to_string())
5069    }
5070
5071    /// Dispatch a mouse, keyboard, or touch event on the window.
5072    #[profiling::function]
5073    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {
5074        #[cfg(feature = "profiler")]
5075        self.window_profiler.begin_input(event.kind_name());
5076        let update_count_before = self.invalidator.update_count();
5077        // Track input modality for focus-visible styling and hover suppression.
5078        // Hover is suppressed during keyboard modality so that keyboard navigation
5079        // doesn't show hover highlights on the item under the mouse cursor.
5080        let old_modality = self.last_input_modality;
5081        self.last_input_modality = match &event {
5082            PlatformInput::KeyDown(_) => InputModality::Keyboard,
5083            PlatformInput::MouseMove(_) | PlatformInput::MouseDown(_) => InputModality::Mouse,
5084            PlatformInput::Touch(_) => InputModality::Touch,
5085            _ => self.last_input_modality,
5086        };
5087        if self.last_input_modality != old_modality {
5088            self.refresh();
5089        }
5090
5091        // Handlers may set this to false by calling `stop_propagation`.
5092        cx.propagate_event = true;
5093        // Handlers may set this to true by calling `prevent_default`.
5094        self.default_prevented = false;
5095
5096        let event = match event {
5097            // Track the mouse position with our own state, since accessing the platform
5098            // API for the mouse position can only occur on the main thread.
5099            PlatformInput::MouseMove(mouse_move) => {
5100                self.mouse_position = mouse_move.position;
5101                self.modifiers = mouse_move.modifiers;
5102                PlatformInput::MouseMove(mouse_move)
5103            }
5104            PlatformInput::MouseDown(mouse_down) => {
5105                self.mouse_position = mouse_down.position;
5106                self.modifiers = mouse_down.modifiers;
5107                PlatformInput::MouseDown(mouse_down)
5108            }
5109            PlatformInput::MouseUp(mouse_up) => {
5110                self.mouse_position = mouse_up.position;
5111                self.modifiers = mouse_up.modifiers;
5112                PlatformInput::MouseUp(mouse_up)
5113            }
5114            PlatformInput::MousePressure(mouse_pressure) => {
5115                PlatformInput::MousePressure(mouse_pressure)
5116            }
5117            PlatformInput::MouseExited(mouse_exited) => {
5118                self.modifiers = mouse_exited.modifiers;
5119                PlatformInput::MouseExited(mouse_exited)
5120            }
5121            PlatformInput::ModifiersChanged(modifiers_changed) => {
5122                self.modifiers = modifiers_changed.modifiers;
5123                self.capslock = modifiers_changed.capslock;
5124                PlatformInput::ModifiersChanged(modifiers_changed)
5125            }
5126            PlatformInput::ScrollWheel(scroll_wheel) => {
5127                self.mouse_position = scroll_wheel.position;
5128                self.modifiers = scroll_wheel.modifiers;
5129                PlatformInput::ScrollWheel(scroll_wheel)
5130            }
5131            PlatformInput::Pinch(pinch) => {
5132                self.mouse_position = pinch.position;
5133                self.modifiers = pinch.modifiers;
5134                PlatformInput::Pinch(pinch)
5135            }
5136            // Translate dragging and dropping of external files from the operating system
5137            // to internal drag and drop events.
5138            PlatformInput::FileDrop(file_drop) => match file_drop {
5139                FileDropEvent::Entered { position, paths } => {
5140                    self.mouse_position = position;
5141                    let source_window = self.handle.window_id();
5142                    if !cx.restore_platform_drag(source_window) && cx.active_drag.is_none() {
5143                        cx.active_drag = Some(AnyDrag {
5144                            value: Arc::new(paths.clone()),
5145                            view: cx.new(|_| paths).into(),
5146                            cursor_offset: position,
5147                            cursor_style: None,
5148                            external_payload_source: None,
5149                        });
5150                    }
5151                    PlatformInput::MouseMove(MouseMoveEvent {
5152                        position,
5153                        pressed_button: Some(MouseButton::Left),
5154                        modifiers: Modifiers::default(),
5155                    })
5156                }
5157                FileDropEvent::Pending { position } => {
5158                    self.mouse_position = position;
5159                    PlatformInput::MouseMove(MouseMoveEvent {
5160                        position,
5161                        pressed_button: Some(MouseButton::Left),
5162                        modifiers: Modifiers::default(),
5163                    })
5164                }
5165                FileDropEvent::Submit { position } => {
5166                    cx.activate(true);
5167                    self.mouse_position = position;
5168                    PlatformInput::MouseUp(MouseUpEvent {
5169                        button: MouseButton::Left,
5170                        position,
5171                        modifiers: Modifiers::default(),
5172                        click_count: 1,
5173                    })
5174                }
5175                FileDropEvent::Exited => {
5176                    if !cx.hand_restored_drag_to_platform(self.handle.window_id()) {
5177                        cx.active_drag.take();
5178                    }
5179                    self.refresh();
5180                    PlatformInput::FileDrop(FileDropEvent::Exited)
5181                }
5182                FileDropEvent::Ended => {
5183                    cx.end_platform_drag(self.handle.window_id());
5184                    self.refresh();
5185                    PlatformInput::FileDrop(FileDropEvent::Ended)
5186                }
5187            },
5188            PlatformInput::Touch(touch) => PlatformInput::Touch(touch),
5189            PlatformInput::LongPress(long_press) => {
5190                self.mouse_position = if long_press.phase == crate::TouchPhase::Started {
5191                    long_press.start_position
5192                } else {
5193                    long_press.position
5194                };
5195                if long_press.phase == crate::TouchPhase::Started {
5196                    self.long_press_capture = None;
5197                }
5198                PlatformInput::LongPress(long_press)
5199            }
5200            PlatformInput::TouchDrag(touch_drag) => {
5201                self.mouse_position = touch_drag.start_position;
5202                PlatformInput::TouchDrag(touch_drag)
5203            }
5204            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
5205        };
5206
5207        if let Some(any_mouse_event) = event.mouse_event() {
5208            self.dispatch_mouse_event(any_mouse_event, cx);
5209        } else if let Some(any_key_event) = event.keyboard_event() {
5210            self.dispatch_key_event(any_key_event, cx);
5211        } else if let Some(touch_event) = event.touch_event() {
5212            self.dispatch_touch_event(touch_event, cx);
5213        }
5214        if let PlatformInput::LongPress(long_press) = &event {
5215            match long_press.phase {
5216                crate::TouchPhase::Started if !self.default_prevented => {
5217                    self.long_press_capture = None;
5218                }
5219                crate::TouchPhase::Ended | crate::TouchPhase::Cancelled => {
5220                    self.long_press_capture = None;
5221                }
5222                crate::TouchPhase::Started | crate::TouchPhase::Moved => {}
5223            }
5224        }
5225
5226        // Must run after the move is dispatched: the platform owns the gesture afterwards, so this
5227        // is the last chance for drag listeners to see the pointer leave and reset their state.
5228        self.promote_external_drag_to_platform(&event, cx);
5229
5230        let caused_invalidation = self.invalidator.update_count() > update_count_before;
5231        if caused_invalidation {
5232            self.input_rate_tracker.borrow_mut().record_input();
5233        }
5234        #[cfg(feature = "profiler")]
5235        self.window_profiler.end_input(caused_invalidation);
5236
5237        DispatchEventResult {
5238            propagate: cx.propagate_event,
5239            default_prevented: self.default_prevented,
5240        }
5241    }
5242
5243    fn promote_external_drag_to_platform(&mut self, event: &PlatformInput, cx: &mut App) {
5244        let PlatformInput::MouseMove(mouse_move) = event else {
5245            return;
5246        };
5247        if mouse_move.pressed_button != Some(MouseButton::Left) {
5248            return;
5249        }
5250        if Bounds::new(Point::default(), self.viewport_size).contains(&mouse_move.position) {
5251            return;
5252        }
5253        if !self.platform_window.can_start_external_drag() {
5254            return;
5255        }
5256        let Some(payload_source) = cx
5257            .active_drag
5258            .as_mut()
5259            .and_then(|drag| drag.external_payload_source.take())
5260        else {
5261            return;
5262        };
5263        let Some(payload) = payload_source(self, cx) else {
5264            return;
5265        };
5266        if self.platform_window.start_external_drag(&payload)
5267            && cx.hand_active_drag_to_platform(self.handle.window_id())
5268        {
5269            self.refresh();
5270        }
5271    }
5272
5273    /// Whether recognized touch pans may use the platform's predicted touch
5274    /// positions ([`TouchEvent::predicted_position`]) to compensate for input
5275    /// latency. Defaults to true.
5276    pub fn touch_prediction_enabled(&self) -> bool {
5277        self.touch_prediction_enabled
5278    }
5279
5280    /// Sets whether recognized touch pans may use the platform's predicted
5281    /// touch positions. Disabling drops [`TouchEvent::predicted_position`]
5282    /// before gesture recognition, so pans track only raw touch positions.
5283    pub fn set_touch_prediction_enabled(&mut self, enabled: bool) {
5284        self.touch_prediction_enabled = enabled;
5285    }
5286
5287    /// Runs the portable gesture recognizer over a raw touch event and
5288    /// dispatches whatever it resolves (scroll steps, synthesized taps)
5289    /// through the ordinary mouse-event path.
5290    fn dispatch_touch_event(&mut self, event: &TouchEvent, cx: &mut App) {
5291        let mut event = event.clone();
5292        if !self.touch_prediction_enabled {
5293            event.predicted_position = None;
5294        }
5295        let recognized_gestures = self.touch_gestures.handle_event(&event);
5296        if event.phase == crate::TouchPhase::Started
5297            && let Some(touch_drag) = self.touch_gestures.offer_touch_drag(event.id)
5298        {
5299            self.dispatch_recognized_touch_gesture(touch_drag, cx);
5300        }
5301        if event.phase == crate::TouchPhase::Started
5302            && self.touch_gestures.pending_long_press().is_some()
5303        {
5304            self.long_press_capture = None;
5305        }
5306        let mut tapped = false;
5307        for gesture in recognized_gestures {
5308            tapped |= matches!(gesture, RecognizedTouchGesture::Tap { .. });
5309            self.dispatch_recognized_touch_gesture(gesture, cx);
5310        }
5311        if event.phase == crate::TouchPhase::Started {
5312            self.schedule_long_press_timer(cx);
5313        } else if self.touch_gestures.pending_long_press().is_none() {
5314            self.long_press_timer.take();
5315        }
5316        // The platform's touch-release handler may inspect the input handler
5317        // as soon as this dispatch returns (the web platform decides virtual
5318        // keyboard visibility there, inside the user gesture). Input handlers
5319        // are registered during draw, so draw now to make them reflect any
5320        // focus change the tap just caused.
5321        if tapped && self.invalidator.is_dirty() {
5322            self.draw(cx).clear(cx);
5323        }
5324        if self.touch_gestures.has_momentum() {
5325            self.schedule_touch_momentum_tick();
5326        }
5327    }
5328
5329    fn dispatch_recognized_touch_gesture(&mut self, gesture: RecognizedTouchGesture, cx: &mut App) {
5330        match gesture {
5331            RecognizedTouchGesture::Scroll(scroll_wheel) => {
5332                self.mouse_position = scroll_wheel.position;
5333                cx.propagate_event = true;
5334                self.dispatch_mouse_event(&scroll_wheel, cx);
5335            }
5336            RecognizedTouchGesture::Tap { down, up } => {
5337                self.mouse_position = up.position;
5338                cx.propagate_event = true;
5339                self.dispatch_mouse_event(&down, cx);
5340                cx.propagate_event = true;
5341                self.dispatch_mouse_event(&up, cx);
5342            }
5343            RecognizedTouchGesture::TouchDrag(touch_drag) => {
5344                self.mouse_position = touch_drag.start_position;
5345                cx.propagate_event = true;
5346                self.default_prevented = false;
5347                let started = touch_drag.phase == crate::TouchPhase::Started;
5348                self.dispatch_mouse_event(&touch_drag, cx);
5349                if started {
5350                    self.touch_gestures
5351                        .resolve_touch_drag(self.default_prevented);
5352                }
5353            }
5354            RecognizedTouchGesture::LongPress(long_press) => {
5355                self.mouse_position = if long_press.phase == crate::TouchPhase::Started {
5356                    long_press.start_position
5357                } else {
5358                    long_press.position
5359                };
5360                cx.propagate_event = true;
5361                self.default_prevented = false;
5362                let started = long_press.phase == crate::TouchPhase::Started;
5363                let ended = matches!(
5364                    long_press.phase,
5365                    crate::TouchPhase::Ended | crate::TouchPhase::Cancelled
5366                );
5367                self.dispatch_mouse_event(&long_press, cx);
5368                if started {
5369                    let claimed = self.default_prevented;
5370                    self.touch_gestures.resolve_long_press(claimed);
5371                    if !claimed {
5372                        self.long_press_capture = None;
5373                    }
5374                }
5375                if ended {
5376                    self.long_press_capture = None;
5377                }
5378            }
5379        }
5380    }
5381
5382    fn schedule_long_press_timer(&mut self, cx: &mut App) {
5383        self.long_press_timer.take();
5384        let Some((touch_id, duration)) = self.touch_gestures.pending_long_press() else {
5385            return;
5386        };
5387        self.long_press_timer = Some(self.spawn(cx, async move |cx| {
5388            cx.background_executor.timer(duration).await;
5389            cx.update(move |window, cx| {
5390                window.long_press_timer.take();
5391                if let Some(gesture) = window.touch_gestures.offer_long_press(touch_id) {
5392                    window.dispatch_recognized_touch_gesture(gesture, cx);
5393                }
5394            })
5395            .log_err();
5396        }));
5397    }
5398
5399    fn schedule_touch_momentum_tick(&mut self) {
5400        self.on_next_frame(|window, cx| {
5401            if let Some(gesture) = window.touch_gestures.tick_momentum() {
5402                window.dispatch_recognized_touch_gesture(gesture, cx);
5403            }
5404            if window.touch_gestures.has_momentum() {
5405                window.schedule_touch_momentum_tick();
5406            }
5407        });
5408    }
5409
5410    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
5411        let hit_test = self.rendered_frame.hit_test(self.mouse_position());
5412        if hit_test != self.mouse_hit_test {
5413            self.mouse_hit_test = hit_test;
5414            self.reset_cursor_style(cx);
5415        }
5416
5417        #[cfg(any(feature = "inspector", debug_assertions))]
5418        if self.is_inspector_picking(cx) {
5419            self.handle_inspector_mouse_event(event, cx);
5420            // When inspector is picking, all other mouse handling is skipped.
5421            return;
5422        }
5423
5424        let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);
5425
5426        // Capture phase, events bubble from back to front. Handlers for this phase are used for
5427        // special purposes, such as detecting events outside of a given Bounds.
5428        for listener in &mut mouse_listeners {
5429            let listener = listener.as_mut().unwrap();
5430            listener(event, DispatchPhase::Capture, self, cx);
5431            if !cx.propagate_event {
5432                break;
5433            }
5434        }
5435
5436        // Bubble phase, where most normal handlers do their work.
5437        if cx.propagate_event {
5438            for listener in mouse_listeners.iter_mut().rev() {
5439                let listener = listener.as_mut().unwrap();
5440                listener(event, DispatchPhase::Bubble, self, cx);
5441                if !cx.propagate_event {
5442                    break;
5443                }
5444            }
5445        }
5446
5447        self.rendered_frame.mouse_listeners = mouse_listeners;
5448
5449        if cx.has_active_drag() {
5450            if event.is::<MouseMoveEvent>() {
5451                // If this was a mouse move event, redraw the window so that the
5452                // active drag can follow the mouse cursor.
5453                self.refresh();
5454            } else if event.is::<MouseUpEvent>() {
5455                // If this was a mouse up event, cancel the active drag and redraw
5456                // the window.
5457                cx.active_drag = None;
5458                self.refresh();
5459            }
5460        }
5461
5462        // Auto-release pointer capture on mouse up
5463        if event.is::<MouseUpEvent>() && self.captured_hitbox.is_some() {
5464            self.captured_hitbox = None;
5465        }
5466    }
5467
5468    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {
5469        if self.invalidator.is_dirty() {
5470            self.draw(cx).clear(cx);
5471        }
5472
5473        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
5474        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
5475
5476        let mut keystroke: Option<Keystroke> = None;
5477
5478        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {
5479            if event.modifiers.number_of_modifiers() == 0
5480                && self.pending_modifier.modifiers.number_of_modifiers() == 1
5481                && !self.pending_modifier.saw_other_input
5482            {
5483                let key = match self.pending_modifier.modifiers {
5484                    modifiers if modifiers.shift => Some("shift"),
5485                    modifiers if modifiers.control => Some("control"),
5486                    modifiers if modifiers.alt => Some("alt"),
5487                    modifiers if modifiers.platform => Some("platform"),
5488                    modifiers if modifiers.function => Some("function"),
5489                    _ => None,
5490                };
5491                if let Some(key) = key {
5492                    keystroke = Some(Keystroke {
5493                        key: key.to_string(),
5494                        key_char: None,
5495                        modifiers: Modifiers::default(),
5496                    });
5497                }
5498            }
5499
5500            if self.pending_modifier.modifiers.number_of_modifiers() == 0
5501                && event.modifiers.number_of_modifiers() == 1
5502            {
5503                self.pending_modifier.saw_other_input = false
5504            } else if event.modifiers.number_of_modifiers() > 1 {
5505                self.pending_modifier.saw_other_input = true
5506            }
5507            self.pending_modifier.modifiers = event.modifiers
5508        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
5509            self.pending_modifier.saw_other_input = true;
5510            keystroke = Some(key_down_event.keystroke.clone());
5511            if key_down_event.keystroke.key_char.is_some()
5512                && matches!(
5513                    cx.cursor_hide_mode,
5514                    CursorHideMode::OnTyping | CursorHideMode::OnTypingAndAction
5515                )
5516            {
5517                cx.platform.hide_cursor_until_mouse_moves();
5518            }
5519        }
5520
5521        let Some(keystroke) = keystroke else {
5522            self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
5523            return;
5524        };
5525
5526        cx.propagate_event = true;
5527        self.dispatch_keystroke_interceptors(event, self.context_stack(), cx);
5528        if !cx.propagate_event {
5529            self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
5530            return;
5531        }
5532
5533        let mut currently_pending = self.pending_input.take().unwrap_or_default();
5534        if currently_pending.focus.is_some() && currently_pending.focus != self.focus {
5535            currently_pending = PendingInput::default();
5536        }
5537
5538        let match_result = self.rendered_frame.dispatch_tree.dispatch_key(
5539            currently_pending.keystrokes,
5540            keystroke,
5541            &dispatch_path,
5542        );
5543
5544        if !match_result.to_replay.is_empty() {
5545            self.replay_pending_input(match_result.to_replay, cx);
5546            cx.propagate_event = true;
5547        }
5548
5549        if !match_result.pending.is_empty() {
5550            currently_pending.timer.take();
5551            currently_pending.keystrokes = match_result.pending;
5552            currently_pending.focus = self.focus;
5553
5554            let text_input_requires_timeout = event
5555                .downcast_ref::<KeyDownEvent>()
5556                .filter(|key_down| key_down.keystroke.key_char.is_some())
5557                .and_then(|_| self.platform_window.take_input_handler())
5558                .map_or(false, |mut input_handler| {
5559                    let accepts = input_handler.accepts_text_input(self, cx);
5560                    self.platform_window.set_input_handler(input_handler);
5561                    accepts
5562                });
5563
5564            currently_pending.needs_timeout |=
5565                match_result.pending_has_binding || text_input_requires_timeout;
5566
5567            if currently_pending.needs_timeout {
5568                currently_pending.timer = Some(self.spawn(cx, async move |cx| {
5569                    cx.background_executor.timer(Duration::from_secs(1)).await;
5570                    cx.update(move |window, cx| {
5571                        let Some(currently_pending) = window
5572                            .pending_input
5573                            .take()
5574                            .filter(|pending| pending.focus == window.focus)
5575                        else {
5576                            return;
5577                        };
5578
5579                        let node_id = window.focus_node_id_in_rendered_frame(window.focus);
5580                        let dispatch_path =
5581                            window.rendered_frame.dispatch_tree.dispatch_path(node_id);
5582
5583                        let to_replay = window
5584                            .rendered_frame
5585                            .dispatch_tree
5586                            .flush_dispatch(currently_pending.keystrokes, &dispatch_path);
5587
5588                        window.pending_input_changed(cx);
5589                        window.replay_pending_input(to_replay, cx)
5590                    })
5591                    .log_err();
5592                }));
5593            } else {
5594                currently_pending.timer = None;
5595            }
5596            self.pending_input = Some(currently_pending);
5597            self.pending_input_changed(cx);
5598            cx.propagate_event = false;
5599            return;
5600        }
5601
5602        let skip_bindings = event
5603            .downcast_ref::<KeyDownEvent>()
5604            .filter(|key_down_event| key_down_event.prefer_character_input)
5605            .map(|_| {
5606                self.platform_window
5607                    .take_input_handler()
5608                    .map_or(false, |mut input_handler| {
5609                        let accepts = input_handler.accepts_text_input(self, cx);
5610                        self.platform_window.set_input_handler(input_handler);
5611                        // If modifiers are not excessive (e.g. AltGr), and the input handler is accepting text input,
5612                        // we prefer the text input over bindings.
5613                        accepts
5614                    })
5615            })
5616            .unwrap_or(false);
5617
5618        if !skip_bindings {
5619            for binding in match_result.bindings {
5620                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
5621                if !cx.propagate_event {
5622                    self.dispatch_keystroke_observers(
5623                        event,
5624                        Some(binding.action),
5625                        match_result.context_stack,
5626                        cx,
5627                    );
5628                    self.pending_input_changed(cx);
5629                    return;
5630                }
5631            }
5632        }
5633
5634        self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);
5635        self.pending_input_changed(cx);
5636    }
5637
5638    fn finish_dispatch_key_event(
5639        &mut self,
5640        event: &dyn Any,
5641        dispatch_path: SmallVec<[DispatchNodeId; 32]>,
5642        context_stack: Vec<KeyContext>,
5643        cx: &mut App,
5644    ) {
5645        self.dispatch_key_down_up_event(event, &dispatch_path, cx);
5646        if !cx.propagate_event {
5647            return;
5648        }
5649
5650        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);
5651        if !cx.propagate_event {
5652            return;
5653        }
5654
5655        self.dispatch_keystroke_observers(event, None, context_stack, cx);
5656    }
5657
5658    pub(crate) fn pending_input_changed(&mut self, cx: &mut App) {
5659        self.pending_input_observers
5660            .clone()
5661            .retain(&(), |callback| callback(self, cx));
5662    }
5663
5664    fn defer_pending_input_changed(&self, cx: &mut App) {
5665        // Avoid re-entrant entity updates by deferring observer notifications to the end of the
5666        // current effect cycle, and only for this window.
5667        let window_handle = self.handle;
5668        cx.defer(move |cx| {
5669            window_handle
5670                .update(cx, |_, window, cx| {
5671                    window.pending_input_changed(cx);
5672                })
5673                .ok();
5674        });
5675    }
5676
5677    fn dispatch_key_down_up_event(
5678        &mut self,
5679        event: &dyn Any,
5680        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
5681        cx: &mut App,
5682    ) {
5683        // Capture phase
5684        for node_id in dispatch_path {
5685            let node = self.rendered_frame.dispatch_tree.node(*node_id);
5686
5687            for key_listener in node.key_listeners.clone() {
5688                key_listener(event, DispatchPhase::Capture, self, cx);
5689                if !cx.propagate_event {
5690                    return;
5691                }
5692            }
5693        }
5694
5695        // Bubble phase
5696        for node_id in dispatch_path.iter().rev() {
5697            // Handle low level key events
5698            let node = self.rendered_frame.dispatch_tree.node(*node_id);
5699            for key_listener in node.key_listeners.clone() {
5700                key_listener(event, DispatchPhase::Bubble, self, cx);
5701                if !cx.propagate_event {
5702                    return;
5703                }
5704            }
5705        }
5706    }
5707
5708    fn dispatch_modifiers_changed_event(
5709        &mut self,
5710        event: &dyn Any,
5711        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
5712        cx: &mut App,
5713    ) {
5714        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {
5715            return;
5716        };
5717        for node_id in dispatch_path.iter().rev() {
5718            let node = self.rendered_frame.dispatch_tree.node(*node_id);
5719            for listener in node.modifiers_changed_listeners.clone() {
5720                listener(event, self, cx);
5721                if !cx.propagate_event {
5722                    return;
5723                }
5724            }
5725        }
5726    }
5727
5728    /// Pending input that can still complete a binding. Input left over from a previous focus can
5729    /// never complete one.
5730    fn active_pending_input(&self) -> Option<&PendingInput> {
5731        self.pending_input
5732            .as_ref()
5733            .filter(|pending_input| pending_input.focus == self.focus)
5734    }
5735
5736    /// Determine whether a potential multi-stroke key binding is in progress on this window.
5737    pub fn has_pending_keystrokes(&self) -> bool {
5738        self.active_pending_input().is_some()
5739    }
5740
5741    #[cfg(test)]
5742    pub(crate) fn pending_input_is_none(&self) -> bool {
5743        self.pending_input.is_none()
5744    }
5745
5746    pub(crate) fn clear_pending_keystrokes(&mut self, cx: &mut App) {
5747        if self.pending_input.take().is_some() {
5748            self.defer_pending_input_changed(cx);
5749        }
5750    }
5751
5752    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.
5753    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {
5754        self.active_pending_input()
5755            .map(|pending_input| pending_input.keystrokes.as_slice())
5756    }
5757
5758    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {
5759        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
5760        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
5761
5762        'replay: for replay in replays {
5763            let event = KeyDownEvent {
5764                keystroke: replay.keystroke.clone(),
5765                is_held: false,
5766                prefer_character_input: true,
5767            };
5768
5769            cx.propagate_event = true;
5770            for binding in replay.bindings {
5771                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
5772                if !cx.propagate_event {
5773                    self.dispatch_keystroke_observers(
5774                        &event,
5775                        Some(binding.action),
5776                        Vec::default(),
5777                        cx,
5778                    );
5779                    continue 'replay;
5780                }
5781            }
5782
5783            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);
5784            if !cx.propagate_event {
5785                continue 'replay;
5786            }
5787            if let Some(input) = replay.keystroke.key_char.as_ref().cloned()
5788                && let Some(mut input_handler) = self.platform_window.take_input_handler()
5789            {
5790                input_handler.dispatch_input(&input, self, cx);
5791                self.platform_window.set_input_handler(input_handler)
5792            }
5793        }
5794    }
5795
5796    fn focus_node_id_in_rendered_frame(&self, focus_id: Option<FocusId>) -> DispatchNodeId {
5797        focus_id
5798            .and_then(|focus_id| {
5799                self.rendered_frame
5800                    .dispatch_tree
5801                    .focusable_node_id(focus_id)
5802            })
5803            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id())
5804    }
5805
5806    fn dispatch_action_on_node(
5807        &mut self,
5808        node_id: DispatchNodeId,
5809        action: &dyn Action,
5810        cx: &mut App,
5811    ) {
5812        self.dispatch_action_on_node_inner(node_id, action, cx);
5813
5814        if !cx.propagate_event
5815            && cx.cursor_hide_mode == CursorHideMode::OnTypingAndAction
5816            && self.last_input_was_keyboard()
5817        {
5818            cx.platform.hide_cursor_until_mouse_moves();
5819        }
5820    }
5821
5822    fn dispatch_action_on_node_inner(
5823        &mut self,
5824        node_id: DispatchNodeId,
5825        action: &dyn Action,
5826        cx: &mut App,
5827    ) {
5828        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
5829
5830        // Capture phase for global actions.
5831        cx.propagate_event = true;
5832        if let Some(mut global_listeners) = cx
5833            .global_action_listeners
5834            .remove(&action.as_any().type_id())
5835        {
5836            for listener in &global_listeners {
5837                #[cfg(feature = "profiler")]
5838                self.window_profiler.begin_action_handler(action, cx);
5839                listener(action.as_any(), DispatchPhase::Capture, cx);
5840                #[cfg(feature = "profiler")]
5841                self.window_profiler.end_action_handler();
5842                if !cx.propagate_event {
5843                    break;
5844                }
5845            }
5846
5847            global_listeners.extend(
5848                cx.global_action_listeners
5849                    .remove(&action.as_any().type_id())
5850                    .unwrap_or_default(),
5851            );
5852
5853            cx.global_action_listeners
5854                .insert(action.as_any().type_id(), global_listeners);
5855        }
5856
5857        if !cx.propagate_event {
5858            return;
5859        }
5860
5861        // Capture phase for window actions.
5862        for node_id in &dispatch_path {
5863            let node = self.rendered_frame.dispatch_tree.node(*node_id);
5864            for DispatchActionListener {
5865                action_type,
5866                listener,
5867            } in node.action_listeners.clone()
5868            {
5869                let any_action = action.as_any();
5870                if action_type == any_action.type_id() {
5871                    #[cfg(feature = "profiler")]
5872                    self.window_profiler.begin_action_handler(action, cx);
5873                    listener(any_action, DispatchPhase::Capture, self, cx);
5874                    #[cfg(feature = "profiler")]
5875                    self.window_profiler.end_action_handler();
5876
5877                    if !cx.propagate_event {
5878                        return;
5879                    }
5880                }
5881            }
5882        }
5883
5884        // Bubble phase for window actions.
5885        for node_id in dispatch_path.iter().rev() {
5886            let node = self.rendered_frame.dispatch_tree.node(*node_id);
5887            for DispatchActionListener {
5888                action_type,
5889                listener,
5890            } in node.action_listeners.clone()
5891            {
5892                let any_action = action.as_any();
5893                if action_type == any_action.type_id() {
5894                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
5895                    #[cfg(feature = "profiler")]
5896                    self.window_profiler.begin_action_handler(action, cx);
5897                    listener(any_action, DispatchPhase::Bubble, self, cx);
5898                    #[cfg(feature = "profiler")]
5899                    self.window_profiler.end_action_handler();
5900
5901                    if !cx.propagate_event {
5902                        return;
5903                    }
5904                }
5905            }
5906        }
5907
5908        // Bubble phase for global actions.
5909        if let Some(mut global_listeners) = cx
5910            .global_action_listeners
5911            .remove(&action.as_any().type_id())
5912        {
5913            for listener in global_listeners.iter().rev() {
5914                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
5915
5916                #[cfg(feature = "profiler")]
5917                self.window_profiler.begin_action_handler(action, cx);
5918                listener(action.as_any(), DispatchPhase::Bubble, cx);
5919                #[cfg(feature = "profiler")]
5920                self.window_profiler.end_action_handler();
5921                if !cx.propagate_event {
5922                    break;
5923                }
5924            }
5925
5926            global_listeners.extend(
5927                cx.global_action_listeners
5928                    .remove(&action.as_any().type_id())
5929                    .unwrap_or_default(),
5930            );
5931
5932            cx.global_action_listeners
5933                .insert(action.as_any().type_id(), global_listeners);
5934        }
5935    }
5936
5937    /// Register the given handler to be invoked whenever the global of the given type
5938    /// is updated.
5939    pub fn observe_global<G: Global>(
5940        &mut self,
5941        cx: &mut App,
5942        f: impl Fn(&mut Window, &mut App) + 'static,
5943    ) -> Subscription {
5944        let window_handle = self.handle;
5945        let (subscription, activate) = cx.global_observers.insert(
5946            TypeId::of::<G>(),
5947            Box::new(move |cx| {
5948                window_handle
5949                    .update(cx, |_, window, cx| f(window, cx))
5950                    .is_ok()
5951            }),
5952        );
5953        cx.defer(move |_| activate());
5954        subscription
5955    }
5956
5957    /// Focus the current window and bring it to the foreground at the platform level.
5958    pub fn activate_window(&self) {
5959        self.platform_window.activate();
5960    }
5961
5962    /// Requests that the operating system draw attention to this window.
5963    pub fn request_attention(&self) {
5964        self.platform_window.request_attention();
5965    }
5966
5967    /// Minimize the current window at the platform level.
5968    pub fn minimize_window(&self) {
5969        self.platform_window.minimize();
5970    }
5971
5972    /// Toggle full screen status on the current window at the platform level.
5973    pub fn toggle_fullscreen(&self) {
5974        self.platform_window.toggle_fullscreen();
5975    }
5976
5977    /// Toggle simple (borderless) fullscreen, where the window covers the entire
5978    /// screen including the menu bar and, on notched displays, the area around the
5979    /// notch. Unlike [`Window::toggle_fullscreen`], this does not move the window
5980    /// into its own Mission Control space. Only has an effect on macOS.
5981    pub fn toggle_simple_fullscreen(&self) {
5982        self.platform_window.toggle_simple_fullscreen();
5983    }
5984
5985    /// Updates the IME panel position suggestions for languages like japanese, chinese.
5986    pub fn invalidate_character_coordinates(&self) {
5987        self.on_next_frame(|window, cx| {
5988            if let Some(mut input_handler) = window.platform_window.take_input_handler() {
5989                if let Some(bounds) = input_handler.selected_bounds(window, cx) {
5990                    window.platform_window.update_ime_position(bounds);
5991                }
5992                window.platform_window.set_input_handler(input_handler);
5993            }
5994        });
5995    }
5996
5997    /// Present a platform dialog.
5998    /// The provided message will be presented, along with buttons for each answer.
5999    /// When a button is clicked, the returned Receiver will receive the index of the clicked button.
6000    pub fn prompt<T>(
6001        &mut self,
6002        level: PromptLevel,
6003        message: &str,
6004        detail: Option<&str>,
6005        answers: &[T],
6006        cx: &mut App,
6007    ) -> oneshot::Receiver<usize>
6008    where
6009        T: Clone + Into<PromptButton>,
6010    {
6011        let prompt_builder = cx.prompt_builder.take();
6012        let Some(prompt_builder) = prompt_builder else {
6013            unreachable!("Re-entrant window prompting is not supported by GPUI");
6014        };
6015
6016        let answers = answers
6017            .iter()
6018            .map(|answer| answer.clone().into())
6019            .collect::<Vec<_>>();
6020
6021        let receiver = match &prompt_builder {
6022            PromptBuilder::Default => self
6023                .platform_window
6024                .prompt(level, message, detail, &answers)
6025                .unwrap_or_else(|| {
6026                    self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
6027                }),
6028            PromptBuilder::Custom(_) => {
6029                self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
6030            }
6031        };
6032
6033        cx.prompt_builder = Some(prompt_builder);
6034
6035        receiver
6036    }
6037
6038    fn build_custom_prompt(
6039        &mut self,
6040        prompt_builder: &PromptBuilder,
6041        level: PromptLevel,
6042        message: &str,
6043        detail: Option<&str>,
6044        answers: &[PromptButton],
6045        cx: &mut App,
6046    ) -> oneshot::Receiver<usize> {
6047        let (sender, receiver) = oneshot::channel();
6048        let handle = PromptHandle::new(sender);
6049        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);
6050        self.prompt = Some(handle);
6051        receiver
6052    }
6053
6054    /// Returns whether a prompt rendered by GPUI is currently active in this window.
6055    ///
6056    /// This is only true for prompts rendered in the window (see
6057    /// [`App::set_prompt_builder`]), not for platform-native prompt dialogs.
6058    pub fn has_active_prompt(&self) -> bool {
6059        self.prompt.is_some()
6060    }
6061
6062    /// Returns the current context stack.
6063    pub fn context_stack(&self) -> Vec<KeyContext> {
6064        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
6065        let dispatch_tree = &self.rendered_frame.dispatch_tree;
6066        dispatch_tree
6067            .dispatch_path(node_id)
6068            .iter()
6069            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())
6070            .collect()
6071    }
6072
6073    /// Returns all available actions for the focused element.
6074    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {
6075        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
6076        let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);
6077        for action_type in cx.global_action_listeners.keys() {
6078            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {
6079                let action = cx.actions.build_action_type(action_type).ok();
6080                if let Some(action) = action {
6081                    actions.insert(ix, action);
6082                }
6083            }
6084        }
6085        actions
6086    }
6087
6088    /// Returns key bindings that invoke an action on the currently focused element. Bindings are
6089    /// returned in the order they were added. For display, the last binding should take precedence.
6090    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
6091        self.rendered_frame
6092            .dispatch_tree
6093            .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)
6094    }
6095
6096    /// Returns the highest precedence key binding that invokes an action on the currently focused
6097    /// element. This is more efficient than getting the last result of `bindings_for_action`.
6098    pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option<KeyBinding> {
6099        self.rendered_frame
6100            .dispatch_tree
6101            .highest_precedence_binding_for_action(
6102                action,
6103                &self.rendered_frame.dispatch_tree.context_stack,
6104            )
6105    }
6106
6107    /// Returns the key bindings for an action in a context.
6108    pub fn bindings_for_action_in_context(
6109        &self,
6110        action: &dyn Action,
6111        context: KeyContext,
6112    ) -> Vec<KeyBinding> {
6113        let dispatch_tree = &self.rendered_frame.dispatch_tree;
6114        dispatch_tree.bindings_for_action(action, &[context])
6115    }
6116
6117    /// Returns the highest precedence key binding for an action in a context. This is more
6118    /// efficient than getting the last result of `bindings_for_action_in_context`.
6119    pub fn highest_precedence_binding_for_action_in_context(
6120        &self,
6121        action: &dyn Action,
6122        context: KeyContext,
6123    ) -> Option<KeyBinding> {
6124        let dispatch_tree = &self.rendered_frame.dispatch_tree;
6125        dispatch_tree.highest_precedence_binding_for_action(action, &[context])
6126    }
6127
6128    /// Returns any bindings that would invoke an action on the given focus handle if it were
6129    /// focused. Bindings are returned in the order they were added. For display, the last binding
6130    /// should take precedence.
6131    pub fn bindings_for_action_in(
6132        &self,
6133        action: &dyn Action,
6134        focus_handle: &FocusHandle,
6135    ) -> Vec<KeyBinding> {
6136        let dispatch_tree = &self.rendered_frame.dispatch_tree;
6137        let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else {
6138            return vec![];
6139        };
6140        dispatch_tree.bindings_for_action(action, &context_stack)
6141    }
6142
6143    /// Returns the highest precedence key binding that would invoke an action on the given focus
6144    /// handle if it were focused. This is more efficient than getting the last result of
6145    /// `bindings_for_action_in`.
6146    pub fn highest_precedence_binding_for_action_in(
6147        &self,
6148        action: &dyn Action,
6149        focus_handle: &FocusHandle,
6150    ) -> Option<KeyBinding> {
6151        let dispatch_tree = &self.rendered_frame.dispatch_tree;
6152        let context_stack = self.context_stack_for_focus_handle(focus_handle)?;
6153        dispatch_tree.highest_precedence_binding_for_action(action, &context_stack)
6154    }
6155
6156    /// Find the bindings that can follow the current input sequence for the current context stack.
6157    pub fn possible_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
6158        self.rendered_frame
6159            .dispatch_tree
6160            .possible_next_bindings_for_input(input, &self.context_stack())
6161    }
6162
6163    fn context_stack_for_focus_handle(
6164        &self,
6165        focus_handle: &FocusHandle,
6166    ) -> Option<Vec<KeyContext>> {
6167        let dispatch_tree = &self.rendered_frame.dispatch_tree;
6168        let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?;
6169        let context_stack: Vec<_> = dispatch_tree
6170            .dispatch_path(node_id)
6171            .into_iter()
6172            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
6173            .collect();
6174        Some(context_stack)
6175    }
6176
6177    /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.
6178    pub fn listener_for<T: 'static, E>(
6179        &self,
6180        view: &Entity<T>,
6181        f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
6182    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
6183        let view = view.downgrade();
6184        move |e: &E, window: &mut Window, cx: &mut App| {
6185            view.update(cx, |view, cx| f(view, e, window, cx)).ok();
6186        }
6187    }
6188
6189    /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.
6190    pub fn handler_for<E: 'static, Callback: Fn(&mut E, &mut Window, &mut Context<E>) + 'static>(
6191        &self,
6192        entity: &Entity<E>,
6193        f: Callback,
6194    ) -> impl Fn(&mut Window, &mut App) + 'static {
6195        let entity = entity.downgrade();
6196        move |window: &mut Window, cx: &mut App| {
6197            entity.update(cx, |entity, cx| f(entity, window, cx)).ok();
6198        }
6199    }
6200
6201    /// Register a callback that can interrupt the closing of the current window based the returned boolean.
6202    /// If the callback returns false, the window won't be closed.
6203    pub fn on_window_should_close(
6204        &self,
6205        cx: &App,
6206        f: impl Fn(&mut Window, &mut App) -> bool + 'static,
6207    ) {
6208        let mut cx = self.to_async(cx);
6209        self.platform_window.on_should_close(Box::new(move || {
6210            cx.update(|window, cx| f(window, cx)).unwrap_or(true)
6211        }))
6212    }
6213
6214    /// Register an action listener on this node for the next frame. The type of action
6215    /// is determined by the first parameter of the given listener. When the next frame is rendered
6216    /// the listener will be cleared.
6217    ///
6218    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
6219    /// a specific need to register a listener yourself.
6220    ///
6221    /// This method should only be called as part of the paint phase of element drawing.
6222    pub fn on_action(
6223        &mut self,
6224        action_type: TypeId,
6225        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
6226    ) {
6227        self.invalidator.debug_assert_paint();
6228
6229        self.next_frame
6230            .dispatch_tree
6231            .on_action(action_type, Rc::new(listener));
6232    }
6233
6234    /// Register a capturing action listener on this node for the next frame if the condition is true.
6235    /// The type of action is determined by the first parameter of the given listener. When the next
6236    /// frame is rendered the listener will be cleared.
6237    ///
6238    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
6239    /// a specific need to register a listener yourself.
6240    ///
6241    /// This method should only be called as part of the paint phase of element drawing.
6242    pub fn on_action_when(
6243        &mut self,
6244        condition: bool,
6245        action_type: TypeId,
6246        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
6247    ) {
6248        self.invalidator.debug_assert_paint();
6249
6250        if condition {
6251            self.next_frame
6252                .dispatch_tree
6253                .on_action(action_type, Rc::new(listener));
6254        }
6255    }
6256
6257    /// Read information about the GPU backing this window.
6258    /// Currently returns None on Mac and Windows.
6259    pub fn gpu_specs(&self) -> Option<GpuSpecs> {
6260        self.platform_window.gpu_specs()
6261    }
6262
6263    /// Perform titlebar double-click action.
6264    /// This is macOS specific.
6265    pub fn titlebar_double_click(&self) {
6266        self.platform_window
6267            .titlebar_double_click(self.is_resizable, self.is_minimizable);
6268    }
6269
6270    /// Gets the window's title at the platform level.
6271    /// This is macOS specific.
6272    pub fn window_title(&self) -> String {
6273        self.platform_window.get_title()
6274    }
6275
6276    /// Returns a list of all tabbed windows and their titles.
6277    /// This is macOS specific.
6278    pub fn tabbed_windows(&self) -> Option<Vec<SystemWindowTab>> {
6279        self.platform_window.tabbed_windows()
6280    }
6281
6282    /// Returns the tab bar visibility.
6283    /// This is macOS specific.
6284    pub fn tab_bar_visible(&self) -> bool {
6285        self.platform_window.tab_bar_visible()
6286    }
6287
6288    /// Merges all open windows into a single tabbed window.
6289    /// This is macOS specific.
6290    pub fn merge_all_windows(&self) {
6291        self.platform_window.merge_all_windows()
6292    }
6293
6294    /// Moves the tab to a new containing window.
6295    /// This is macOS specific.
6296    pub fn move_tab_to_new_window(&self) {
6297        self.platform_window.move_tab_to_new_window()
6298    }
6299
6300    /// Shows or hides the window tab overview.
6301    /// This is macOS specific.
6302    pub fn toggle_window_tab_overview(&self) {
6303        self.platform_window.toggle_window_tab_overview()
6304    }
6305
6306    /// Sets the tabbing identifier for the window.
6307    /// This is macOS specific.
6308    pub fn set_tabbing_identifier(&self, tabbing_identifier: Option<String>) {
6309        self.platform_window
6310            .set_tabbing_identifier(tabbing_identifier)
6311    }
6312
6313    /// Request the OS to play an alert sound. On some platforms this is associated
6314    /// with the window, for others it's just a simple global function call.
6315    pub fn play_system_bell(&self) {
6316        self.platform_window.play_system_bell()
6317    }
6318
6319    /// Returns whether accessibility features are active for this frame,
6320    /// i.e. whether assistive technology (such as a screen reader) is
6321    /// connected and an accessibility tree is being built.
6322    ///
6323    /// Use this to skip computing data during rendering that is only
6324    /// observable through the accessibility tree. When accessibility is
6325    /// activated, a redraw is forced, so gated work is recomputed before the
6326    /// next tree update is sent to the platform.
6327    ///
6328    /// See the [accessibility guide](crate::_accessibility) for an overview.
6329    pub fn is_a11y_active(&self) -> bool {
6330        self.a11y.is_active()
6331    }
6332
6333    /// Debug representation of the last frame's accessibility information.
6334    pub fn debug_a11y_tree_json(&self) -> Option<String> {
6335        self.a11y.debug_tree_json()
6336    }
6337
6338    /// Register a listener for an accessibility action on a specific node.
6339    /// The listener will be called when a screen reader requests the given
6340    /// action on the node identified by `node_id`.
6341    ///
6342    /// See the [accessibility guide](crate::_accessibility) for an overview.
6343    pub fn on_a11y_action(
6344        &mut self,
6345        node_id: accesskit::NodeId,
6346        action: accesskit::Action,
6347        listener: impl FnMut(Option<&accesskit::ActionData>, &mut Window, &mut App) + 'static,
6348    ) {
6349        self.a11y
6350            .action_listeners
6351            .entry(node_id)
6352            .or_default()
6353            .push((action, Box::new(listener)));
6354    }
6355
6356    #[cfg(not(target_family = "wasm"))]
6357    pub(crate) fn handle_a11y_action(&mut self, request: accesskit::ActionRequest, cx: &mut App) {
6358        // Take listeners out temporarily so the closures can borrow Window
6359        // mutably, then restore them afterward.
6360        if let Some(mut listeners) = self.a11y.action_listeners.remove(&request.target_node) {
6361            let extra_data = request.data.as_ref();
6362            let mut matched = false;
6363            for (action, listener) in &mut listeners {
6364                if *action == request.action {
6365                    listener(extra_data, self, cx);
6366                    matched = true;
6367                }
6368            }
6369            self.a11y
6370                .action_listeners
6371                .insert(request.target_node, listeners);
6372            if matched {
6373                return;
6374            }
6375        }
6376
6377        // Fall back to built-in action handling.
6378        match request.action {
6379            accesskit::Action::Click => {
6380                if let Some(bounds) = self.a11y.node_bounds.get(&request.target_node).copied() {
6381                    let center = bounds.center();
6382                    let mouse_down = PlatformInput::MouseDown(crate::MouseDownEvent {
6383                        button: MouseButton::Left,
6384                        position: center,
6385                        modifiers: Modifiers::default(),
6386                        click_count: 1,
6387                        first_mouse: false,
6388                    });
6389                    let mouse_up = PlatformInput::MouseUp(MouseUpEvent {
6390                        button: MouseButton::Left,
6391                        position: center,
6392                        modifiers: Modifiers::default(),
6393                        click_count: 1,
6394                    });
6395                    self.dispatch_event(mouse_down, cx);
6396                    self.dispatch_event(mouse_up, cx);
6397                }
6398            }
6399            accesskit::Action::Focus => {
6400                if let Some(focus_id) = self.a11y.focus_ids.get(&request.target_node).copied()
6401                    && let Some(handle) = FocusHandle::for_id(focus_id, &cx.focus_handles)
6402                {
6403                    self.focus(&handle, cx);
6404                }
6405            }
6406            accesskit::Action::Blur => {
6407                self.blur(cx);
6408            }
6409            _ => {
6410                log::debug!(
6411                    "Unhandled a11y action: {:?} on {:?}",
6412                    request.action,
6413                    request.target_node
6414                );
6415            }
6416        }
6417    }
6418
6419    /// Toggles the inspector mode on this window.
6420    #[cfg(any(feature = "inspector", debug_assertions))]
6421    pub fn toggle_inspector(&mut self, cx: &mut App) {
6422        self.inspector = match self.inspector {
6423            None => Some(cx.new(|_| Inspector::new())),
6424            Some(_) => None,
6425        };
6426        self.refresh();
6427    }
6428
6429    /// Returns true if the window is in inspector mode.
6430    pub fn is_inspector_picking(&self, _cx: &App) -> bool {
6431        #[cfg(any(feature = "inspector", debug_assertions))]
6432        {
6433            if let Some(inspector) = &self.inspector {
6434                return inspector.read(_cx).is_picking();
6435            }
6436        }
6437        false
6438    }
6439
6440    /// Executes the provided function with mutable access to an inspector state.
6441    #[cfg(any(feature = "inspector", debug_assertions))]
6442    pub fn with_inspector_state<T: 'static, R>(
6443        &mut self,
6444        _inspector_id: Option<&crate::InspectorElementId>,
6445        cx: &mut App,
6446        f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
6447    ) -> R {
6448        if let Some(inspector_id) = _inspector_id
6449            && let Some(inspector) = &self.inspector
6450        {
6451            let inspector = inspector.clone();
6452            let active_element_id = inspector.read(cx).active_element_id();
6453            if Some(inspector_id) == active_element_id {
6454                return inspector.update(cx, |inspector, _cx| {
6455                    inspector.with_active_element_state(self, f)
6456                });
6457            }
6458        }
6459        f(&mut None, self)
6460    }
6461
6462    #[cfg(any(feature = "inspector", debug_assertions))]
6463    pub(crate) fn build_inspector_element_id(
6464        &mut self,
6465        path: crate::InspectorElementPath,
6466    ) -> crate::InspectorElementId {
6467        self.invalidator.debug_assert_paint_or_prepaint();
6468        let path = Rc::new(path);
6469        let next_instance_id = self
6470            .next_frame
6471            .next_inspector_instance_ids
6472            .entry(path.clone())
6473            .or_insert(0);
6474        let instance_id = *next_instance_id;
6475        *next_instance_id += 1;
6476        crate::InspectorElementId { path, instance_id }
6477    }
6478
6479    #[cfg(any(feature = "inspector", debug_assertions))]
6480    fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option<AnyElement> {
6481        if let Some(inspector) = self.inspector.take() {
6482            let mut inspector_element = AnyView::from(inspector.clone()).into_any_element();
6483            inspector_element.prepaint_as_root(
6484                point(self.viewport_size.width - inspector_width, px(0.0)),
6485                size(inspector_width, self.viewport_size.height).into(),
6486                self,
6487                cx,
6488            );
6489            self.inspector = Some(inspector);
6490            Some(inspector_element)
6491        } else {
6492            None
6493        }
6494    }
6495
6496    #[cfg(any(feature = "inspector", debug_assertions))]
6497    fn paint_inspector(&mut self, mut inspector_element: Option<AnyElement>, cx: &mut App) {
6498        if let Some(mut inspector_element) = inspector_element {
6499            inspector_element.paint(self, cx);
6500        };
6501    }
6502
6503    /// Registers a hitbox that can be used for inspector picking mode, allowing users to select and
6504    /// inspect UI elements by clicking on them.
6505    #[cfg(any(feature = "inspector", debug_assertions))]
6506    pub fn insert_inspector_hitbox(
6507        &mut self,
6508        hitbox_id: HitboxId,
6509        inspector_id: Option<&crate::InspectorElementId>,
6510        cx: &App,
6511    ) {
6512        self.invalidator.debug_assert_paint_or_prepaint();
6513        if !self.is_inspector_picking(cx) {
6514            return;
6515        }
6516        if let Some(inspector_id) = inspector_id {
6517            self.next_frame
6518                .inspector_hitboxes
6519                .insert(hitbox_id, inspector_id.clone());
6520        }
6521    }
6522
6523    #[cfg(any(feature = "inspector", debug_assertions))]
6524    fn paint_inspector_hitbox(&mut self, cx: &App) {
6525        if let Some(inspector) = self.inspector.as_ref() {
6526            let inspector = inspector.read(cx);
6527            if let Some((hitbox_id, _)) = self.hovered_inspector_hitbox(inspector, &self.next_frame)
6528                && let Some(hitbox) = self
6529                    .next_frame
6530                    .hitboxes
6531                    .iter()
6532                    .find(|hitbox| hitbox.id == hitbox_id)
6533            {
6534                self.paint_quad(crate::fill(hitbox.bounds, crate::rgba(0x61afef4d)));
6535            }
6536        }
6537    }
6538
6539    #[cfg(any(feature = "inspector", debug_assertions))]
6540    fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
6541        let Some(inspector) = self.inspector.clone() else {
6542            return;
6543        };
6544        if event.downcast_ref::<MouseMoveEvent>().is_some() {
6545            inspector.update(cx, |inspector, _cx| {
6546                if let Some((_, inspector_id)) =
6547                    self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
6548                {
6549                    inspector.hover(inspector_id, self);
6550                }
6551            });
6552        } else if event.downcast_ref::<crate::MouseDownEvent>().is_some() {
6553            inspector.update(cx, |inspector, _cx| {
6554                if let Some((_, inspector_id)) =
6555                    self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
6556                {
6557                    inspector.select(inspector_id, self);
6558                }
6559            });
6560        } else if let Some(event) = event.downcast_ref::<crate::ScrollWheelEvent>() {
6561            // This should be kept in sync with SCROLL_LINES in x11 platform.
6562            const SCROLL_LINES: f32 = 3.0;
6563            const SCROLL_PIXELS_PER_LAYER: f32 = 36.0;
6564            let delta_y = event
6565                .delta
6566                .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES))
6567                .y;
6568            if let Some(inspector) = self.inspector.clone() {
6569                inspector.update(cx, |inspector, _cx| {
6570                    if let Some(depth) = inspector.pick_depth.as_mut() {
6571                        *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER;
6572                        let max_depth = self.mouse_hit_test.ids.len() as f32 - 0.5;
6573                        if *depth < 0.0 {
6574                            *depth = 0.0;
6575                        } else if *depth > max_depth {
6576                            *depth = max_depth;
6577                        }
6578                        if let Some((_, inspector_id)) =
6579                            self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
6580                        {
6581                            inspector.set_active_element_id(inspector_id, self);
6582                        }
6583                    }
6584                });
6585            }
6586        }
6587    }
6588
6589    #[cfg(any(feature = "inspector", debug_assertions))]
6590    fn hovered_inspector_hitbox(
6591        &self,
6592        inspector: &Inspector,
6593        frame: &Frame,
6594    ) -> Option<(HitboxId, crate::InspectorElementId)> {
6595        if let Some(pick_depth) = inspector.pick_depth {
6596            let depth = (pick_depth as i64).try_into().unwrap_or(0);
6597            let max_skipped = self.mouse_hit_test.ids.len().saturating_sub(1);
6598            let skip_count = (depth as usize).min(max_skipped);
6599            for hitbox_id in self.mouse_hit_test.ids.iter().skip(skip_count) {
6600                if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) {
6601                    return Some((*hitbox_id, inspector_id.clone()));
6602                }
6603            }
6604        }
6605        None
6606    }
6607
6608    /// For testing: set the current modifier keys state.
6609    /// This does not generate any events.
6610    #[cfg(any(test, feature = "test-support"))]
6611    pub fn set_modifiers(&mut self, modifiers: Modifiers) {
6612        self.modifiers = modifiers;
6613    }
6614
6615    /// For testing: simulate a mouse move event to the given position.
6616    /// This dispatches the event through the normal event handling path,
6617    /// which will trigger hover states and tooltips.
6618    #[cfg(any(test, feature = "test-support"))]
6619    pub fn simulate_mouse_move(&mut self, position: Point<Pixels>, cx: &mut App) {
6620        let event = PlatformInput::MouseMove(MouseMoveEvent {
6621            position,
6622            modifiers: self.modifiers,
6623            pressed_button: None,
6624        });
6625        let _ = self.dispatch_event(event, cx);
6626    }
6627}
6628
6629// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
6630slotmap::new_key_type! {
6631    /// A unique identifier for a window.
6632    pub struct WindowId;
6633}
6634
6635impl WindowId {
6636    /// Converts this window ID to a `u64`.
6637    pub fn as_u64(&self) -> u64 {
6638        self.0.as_ffi()
6639    }
6640}
6641
6642impl From<u64> for WindowId {
6643    fn from(value: u64) -> Self {
6644        WindowId(slotmap::KeyData::from_ffi(value))
6645    }
6646}
6647
6648/// A handle to a window with a specific root view type.
6649/// Note that this does not keep the window alive on its own.
6650#[derive(Deref, DerefMut)]
6651pub struct WindowHandle<V> {
6652    #[deref]
6653    #[deref_mut]
6654    pub(crate) any_handle: AnyWindowHandle,
6655    state_type: PhantomData<fn(V) -> V>,
6656}
6657
6658impl<V> Debug for WindowHandle<V> {
6659    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6660        f.debug_struct("WindowHandle")
6661            .field("any_handle", &self.any_handle.id.as_u64())
6662            .finish()
6663    }
6664}
6665
6666impl<V: 'static + Render> WindowHandle<V> {
6667    /// Creates a new handle from a window ID.
6668    /// This does not check if the root type of the window is `V`.
6669    pub fn new(id: WindowId) -> Self {
6670        WindowHandle {
6671            any_handle: AnyWindowHandle {
6672                id,
6673                state_type: TypeId::of::<V>(),
6674                root_entity_type_name: std::any::type_name::<V>(),
6675            },
6676            state_type: PhantomData,
6677        }
6678    }
6679
6680    /// Get the root view out of this window.
6681    ///
6682    /// This will fail if the window is closed or if the root view's type does not match `V`.
6683    #[cfg(any(test, feature = "test-support"))]
6684    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>
6685    where
6686        C: AppContext,
6687    {
6688        cx.update_window(self.any_handle, |root_view, _, _| {
6689            root_view
6690                .downcast::<V>()
6691                .map_err(|_| anyhow!("the type of the window's root view has changed"))
6692        })?
6693    }
6694
6695    /// Updates the root view of this window.
6696    ///
6697    /// This will fail if the window has been closed or if the root view's type does not match
6698    pub fn update<C, R>(
6699        &self,
6700        cx: &mut C,
6701        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
6702    ) -> Result<R>
6703    where
6704        C: AppContext,
6705    {
6706        cx.update_window(self.any_handle, |root_view, window, cx| {
6707            let view = root_view
6708                .downcast::<V>()
6709                .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
6710
6711            Ok(view.update(cx, |view, cx| update(view, window, cx)))
6712        })?
6713    }
6714
6715    /// Read the root view out of this window.
6716    ///
6717    /// This will fail if the window is closed or if the root view's type does not match `V`.
6718    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {
6719        let x = cx
6720            .windows
6721            .get(self.id)
6722            .and_then(|window| {
6723                window
6724                    .as_deref()
6725                    .and_then(|window| window.root.clone())
6726                    .map(|root_view| root_view.downcast::<V>())
6727            })
6728            .context("window not found")?
6729            .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
6730
6731        Ok(x.read(cx))
6732    }
6733
6734    /// Read the root view out of this window, with a callback
6735    ///
6736    /// This will fail if the window is closed or if the root view's type does not match `V`.
6737    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>
6738    where
6739        C: AppContext,
6740    {
6741        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
6742    }
6743
6744    /// Read the root view pointer off of this window.
6745    ///
6746    /// This will fail if the window is closed or if the root view's type does not match `V`.
6747    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>
6748    where
6749        C: AppContext,
6750    {
6751        cx.read_window(self, |root_view, _cx| root_view)
6752    }
6753
6754    /// Check if this window is 'active'.
6755    ///
6756    /// Will return `None` if the window is closed or currently
6757    /// borrowed.
6758    pub fn is_active(&self, cx: &mut App) -> Option<bool> {
6759        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())
6760            .ok()
6761    }
6762}
6763
6764impl<V> Copy for WindowHandle<V> {}
6765
6766impl<V> Clone for WindowHandle<V> {
6767    fn clone(&self) -> Self {
6768        *self
6769    }
6770}
6771
6772impl<V> PartialEq for WindowHandle<V> {
6773    fn eq(&self, other: &Self) -> bool {
6774        self.any_handle == other.any_handle
6775    }
6776}
6777
6778impl<V> Eq for WindowHandle<V> {}
6779
6780impl<V> Hash for WindowHandle<V> {
6781    fn hash<H: Hasher>(&self, state: &mut H) {
6782        self.any_handle.hash(state);
6783    }
6784}
6785
6786impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
6787    fn from(val: WindowHandle<V>) -> Self {
6788        val.any_handle
6789    }
6790}
6791
6792/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.
6793#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
6794pub struct AnyWindowHandle {
6795    pub(crate) id: WindowId,
6796    state_type: TypeId,
6797    root_entity_type_name: &'static str,
6798}
6799
6800impl AnyWindowHandle {
6801    /// Get the ID of this window.
6802    pub fn window_id(&self) -> WindowId {
6803        self.id
6804    }
6805
6806    /// Returns the name of the window's declared root entity type.
6807    pub fn root_entity_type_name(&self) -> &'static str {
6808        self.root_entity_type_name
6809    }
6810
6811    /// Attempt to convert this handle to a window handle with a specific root view type.
6812    /// If the types do not match, this will return `None`.
6813    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
6814        if TypeId::of::<T>() == self.state_type {
6815            Some(WindowHandle {
6816                any_handle: *self,
6817                state_type: PhantomData,
6818            })
6819        } else {
6820            None
6821        }
6822    }
6823
6824    /// Updates the state of the root view of this window.
6825    ///
6826    /// This will fail if the window has been closed.
6827    pub fn update<C, R>(
6828        self,
6829        cx: &mut C,
6830        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
6831    ) -> Result<R>
6832    where
6833        C: AppContext,
6834    {
6835        cx.update_window(self, update)
6836    }
6837
6838    /// Read the state of the root view of this window.
6839    ///
6840    /// This will fail if the window has been closed.
6841    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>
6842    where
6843        C: AppContext,
6844        T: 'static,
6845    {
6846        let view = self
6847            .downcast::<T>()
6848            .context("the type of the window's root view has changed")?;
6849
6850        cx.read_window(&view, read)
6851    }
6852}
6853
6854impl HasWindowHandle for Window {
6855    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {
6856        self.platform_window.window_handle()
6857    }
6858}
6859
6860impl HasDisplayHandle for Window {
6861    fn display_handle(
6862        &self,
6863    ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, HandleError> {
6864        self.platform_window.display_handle()
6865    }
6866}
6867
6868/// An identifier for an [`Element`].
6869///
6870/// Can be constructed with a string, a number, or both, as well
6871/// as other internal representations.
6872#[derive(Clone, Debug, Eq, PartialEq, Hash)]
6873pub enum ElementId {
6874    /// The ID of a View element
6875    View(EntityId),
6876    /// An integer ID.
6877    Integer(u64),
6878    /// A string based ID.
6879    Name(SharedString),
6880    /// A UUID.
6881    Uuid(Uuid),
6882    /// An ID that's equated with a focus handle.
6883    FocusHandle(FocusId),
6884    /// A combination of a name and an integer.
6885    NamedInteger(SharedString, u64),
6886    /// A path.
6887    Path(Arc<std::path::Path>),
6888    /// A code location.
6889    CodeLocation(core::panic::Location<'static>),
6890    /// A labeled child of an element.
6891    NamedChild(Arc<ElementId>, SharedString),
6892    /// A byte array ID (used for text-anchors)
6893    OpaqueId([u8; 20]),
6894}
6895
6896impl ElementId {
6897    /// Constructs an `ElementId::NamedInteger` from a name and `usize`.
6898    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {
6899        Self::NamedInteger(name.into(), integer as u64)
6900    }
6901}
6902
6903impl Display for ElementId {
6904    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
6905        match self {
6906            ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
6907            ElementId::Integer(ix) => write!(f, "{}", ix)?,
6908            ElementId::Name(name) => write!(f, "{}", name)?,
6909            ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
6910            ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
6911            ElementId::Uuid(uuid) => write!(f, "{}", uuid)?,
6912            ElementId::Path(path) => write!(f, "{}", path.display())?,
6913            ElementId::CodeLocation(location) => write!(f, "{}", location)?,
6914            ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?,
6915            ElementId::OpaqueId(opaque_id) => write!(f, "{:x?}", opaque_id)?,
6916        }
6917
6918        Ok(())
6919    }
6920}
6921
6922impl TryInto<SharedString> for ElementId {
6923    type Error = anyhow::Error;
6924
6925    fn try_into(self) -> anyhow::Result<SharedString> {
6926        if let ElementId::Name(name) = self {
6927            Ok(name)
6928        } else {
6929            anyhow::bail!("element id is not string")
6930        }
6931    }
6932}
6933
6934impl From<usize> for ElementId {
6935    fn from(id: usize) -> Self {
6936        ElementId::Integer(id as u64)
6937    }
6938}
6939
6940impl From<i32> for ElementId {
6941    fn from(id: i32) -> Self {
6942        Self::Integer(id as u64)
6943    }
6944}
6945
6946impl From<SharedString> for ElementId {
6947    fn from(name: SharedString) -> Self {
6948        ElementId::Name(name)
6949    }
6950}
6951
6952impl From<String> for ElementId {
6953    fn from(name: String) -> Self {
6954        ElementId::Name(name.into())
6955    }
6956}
6957
6958impl From<Arc<str>> for ElementId {
6959    fn from(name: Arc<str>) -> Self {
6960        ElementId::Name(name.into())
6961    }
6962}
6963
6964impl From<Arc<std::path::Path>> for ElementId {
6965    fn from(path: Arc<std::path::Path>) -> Self {
6966        ElementId::Path(path)
6967    }
6968}
6969
6970impl From<&'static str> for ElementId {
6971    fn from(name: &'static str) -> Self {
6972        ElementId::Name(SharedString::new_static(name))
6973    }
6974}
6975
6976impl<'a> From<&'a FocusHandle> for ElementId {
6977    fn from(handle: &'a FocusHandle) -> Self {
6978        ElementId::FocusHandle(handle.id)
6979    }
6980}
6981
6982impl From<(&'static str, EntityId)> for ElementId {
6983    fn from((name, id): (&'static str, EntityId)) -> Self {
6984        ElementId::NamedInteger(SharedString::new_static(name), id.as_u64())
6985    }
6986}
6987
6988impl From<(&'static str, usize)> for ElementId {
6989    fn from((name, id): (&'static str, usize)) -> Self {
6990        ElementId::NamedInteger(SharedString::new_static(name), id as u64)
6991    }
6992}
6993
6994impl From<(SharedString, usize)> for ElementId {
6995    fn from((name, id): (SharedString, usize)) -> Self {
6996        ElementId::NamedInteger(name, id as u64)
6997    }
6998}
6999
7000impl From<(&'static str, u64)> for ElementId {
7001    fn from((name, id): (&'static str, u64)) -> Self {
7002        ElementId::NamedInteger(SharedString::new_static(name), id)
7003    }
7004}
7005
7006impl From<Uuid> for ElementId {
7007    fn from(value: Uuid) -> Self {
7008        Self::Uuid(value)
7009    }
7010}
7011
7012impl From<(&'static str, u32)> for ElementId {
7013    fn from((name, id): (&'static str, u32)) -> Self {
7014        ElementId::NamedInteger(SharedString::new_static(name), u64::from(id))
7015    }
7016}
7017
7018impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
7019    fn from((id, name): (ElementId, T)) -> Self {
7020        ElementId::NamedChild(Arc::new(id), name.into())
7021    }
7022}
7023
7024impl From<&'static core::panic::Location<'static>> for ElementId {
7025    fn from(location: &'static core::panic::Location<'static>) -> Self {
7026        ElementId::CodeLocation(*location)
7027    }
7028}
7029
7030impl From<[u8; 20]> for ElementId {
7031    fn from(opaque_id: [u8; 20]) -> Self {
7032        ElementId::OpaqueId(opaque_id)
7033    }
7034}
7035
7036/// A rectangle to be rendered in the window at the given position and size.
7037/// Passed as an argument [`Window::paint_quad`].
7038#[derive(Clone)]
7039pub struct PaintQuad {
7040    /// The bounds of the quad within the window.
7041    pub bounds: Bounds<Pixels>,
7042    /// The radii of the quad's corners.
7043    pub corner_radii: Corners<Pixels>,
7044    /// The background color of the quad.
7045    pub background: Background,
7046    /// The widths of the quad's borders.
7047    pub border_widths: Edges<Pixels>,
7048    /// The color of the quad's borders.
7049    pub border_color: Hsla,
7050    /// The style of the quad's borders.
7051    pub border_style: BorderStyle,
7052}
7053
7054impl PaintQuad {
7055    /// Sets the corner radii of the quad.
7056    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
7057        PaintQuad {
7058            corner_radii: corner_radii.into(),
7059            ..self
7060        }
7061    }
7062
7063    /// Sets the border widths of the quad.
7064    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
7065        PaintQuad {
7066            border_widths: border_widths.into(),
7067            ..self
7068        }
7069    }
7070
7071    /// Sets the border color of the quad.
7072    pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
7073        PaintQuad {
7074            border_color: border_color.into(),
7075            ..self
7076        }
7077    }
7078
7079    /// Sets the background color of the quad.
7080    pub fn background(self, background: impl Into<Background>) -> Self {
7081        PaintQuad {
7082            background: background.into(),
7083            ..self
7084        }
7085    }
7086}
7087
7088/// Creates a quad with the given parameters.
7089pub fn quad(
7090    bounds: Bounds<Pixels>,
7091    corner_radii: impl Into<Corners<Pixels>>,
7092    background: impl Into<Background>,
7093    border_widths: impl Into<Edges<Pixels>>,
7094    border_color: impl Into<Hsla>,
7095    border_style: BorderStyle,
7096) -> PaintQuad {
7097    PaintQuad {
7098        bounds,
7099        corner_radii: corner_radii.into(),
7100        background: background.into(),
7101        border_widths: border_widths.into(),
7102        border_color: border_color.into(),
7103        border_style,
7104    }
7105}
7106
7107/// Creates a filled quad with the given bounds and background color.
7108pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
7109    PaintQuad {
7110        bounds: bounds.into(),
7111        corner_radii: (0.).into(),
7112        background: background.into(),
7113        border_widths: (0.).into(),
7114        border_color: transparent_black(),
7115        border_style: BorderStyle::default(),
7116    }
7117}
7118
7119/// Creates a rectangle outline with the given bounds, border color, and a 1px border width
7120pub fn outline(
7121    bounds: impl Into<Bounds<Pixels>>,
7122    border_color: impl Into<Hsla>,
7123    border_style: BorderStyle,
7124) -> PaintQuad {
7125    PaintQuad {
7126        bounds: bounds.into(),
7127        corner_radii: (0.).into(),
7128        background: transparent_black().into(),
7129        border_widths: (1.).into(),
7130        border_color: border_color.into(),
7131        border_style,
7132    }
7133}
7134
7135#[cfg(test)]
7136mod tests {
7137    use std::{
7138        cell::{Cell, RefCell},
7139        path::PathBuf,
7140        rc::Rc,
7141        time::Duration,
7142    };
7143
7144    use crate::{
7145        AnyWindowHandle, AppContext as _, Bounds, Context, DispatchPhase, DragMoveEvent, Empty,
7146        ExternalDragPayload, ExternalPaths, FileDragPaths, FileDropEvent, FocusHandle,
7147        InputEvent as _, InteractiveElement as _, IntoElement, LongPressEvent, MouseButton,
7148        MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Point, Render, RequestFrameOptions,
7149        StatefulInteractiveElement as _, Styled, TestAppContext, TouchDragEvent, TouchEvent,
7150        TouchId, TouchPhase, Window, WindowAppearance, WindowOptions, canvas, div, point, px, size,
7151    };
7152
7153    struct EmptyView;
7154
7155    impl Render for EmptyView {
7156        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
7157            div()
7158        }
7159    }
7160
7161    struct OpensWindowOnPaint {
7162        opened: Rc<Cell<bool>>,
7163    }
7164
7165    impl Render for OpensWindowOnPaint {
7166        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
7167            let opened = self.opened.clone();
7168            div()
7169                .size_full()
7170                .child(canvas(
7171                    |_, _, _| {},
7172                    move |_, _, _window, cx| {
7173                        if !opened.replace(true) {
7174                            cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| EmptyView))
7175                                .unwrap();
7176                        }
7177                    },
7178                ))
7179                // Siblings painted after the canvas: their elements were
7180                // allocated in the arena before the nested draw, so they detect
7181                // a mid-draw arena clear when painted afterwards.
7182                .child(div().child("after"))
7183        }
7184    }
7185
7186    /// Opening a window synchronously draws it and requests an element arena
7187    /// clear. When that happens from within another window's draw (here: from
7188    /// an element's paint), the clear must be deferred until the outer draw
7189    /// finishes, or the outer draw's arena-allocated elements would be freed
7190    /// out from under it.
7191    #[test]
7192    fn test_window_opened_during_draw_defers_arena_clear() {
7193        let mut cx = TestAppContext::single();
7194
7195        let opened = Rc::new(Cell::new(false));
7196        // add_window draws once, which runs the nested open_window mid-draw.
7197        let window = cx.add_window({
7198            let opened = opened.clone();
7199            move |_, _| OpensWindowOnPaint { opened }
7200        });
7201
7202        assert!(opened.get());
7203        assert_eq!(cx.windows().len(), 2);
7204
7205        // The deferred clear must actually run once the outer draw unwinds:
7206        // subsequent draws of both windows work against a fresh arena.
7207        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
7208            .unwrap();
7209    }
7210
7211    /// Platforms that stop requesting frames for idle windows (currently web)
7212    /// rely on the frame waker firing whenever frame demand arises; a demand
7213    /// source that skips the waker shows up there as a window that silently
7214    /// stops repainting until unrelated activity wakes it.
7215    #[gpui::test]
7216    fn test_frame_waker_fires_on_frame_demand(cx: &mut TestAppContext) {
7217        let window = cx.add_window(|_, _| EmptyView);
7218        let test_window = cx.test_window(window.into());
7219
7220        // Windows start dirty, and that can predate waker installation;
7221        // installing the waker must deliver the pending wake or the first
7222        // frame would never be requested.
7223        assert!(
7224            test_window.frame_wake_count() >= 1,
7225            "opening a window must wake the frame source for the initial frame"
7226        );
7227
7228        // Serve outstanding demand (present the frame drawn by `add_window`).
7229        test_window.simulate_frame_request(RequestFrameOptions::default());
7230
7231        // An idle window must not wake on clean frames or plain updates, or
7232        // the frame source could never stop.
7233        let baseline = test_window.frame_wake_count();
7234        test_window.simulate_frame_request(RequestFrameOptions::default());
7235        window.update(cx, |_, _, _| {}).unwrap();
7236        assert_eq!(
7237            test_window.frame_wake_count(),
7238            baseline,
7239            "clean frames and non-notifying updates must not wake the frame source"
7240        );
7241
7242        // Notifying a view in an idle window is the core demand signal.
7243        window.update(cx, |_, _, cx| cx.notify()).unwrap();
7244        assert!(
7245            test_window.frame_wake_count() > baseline,
7246            "notifying a view in an idle window must wake the frame source"
7247        );
7248
7249        // Serving that demand returns to idle without further wakes.
7250        test_window.simulate_frame_request(RequestFrameOptions::default());
7251        let baseline = test_window.frame_wake_count();
7252        test_window.simulate_frame_request(RequestFrameOptions::default());
7253        assert_eq!(
7254            test_window.frame_wake_count(),
7255            baseline,
7256            "serving demand must return the window to idle"
7257        );
7258
7259        // Next-frame callbacks create demand without dirtying the window.
7260        window
7261            .update(cx, |_, window, _| window.on_next_frame(|_, _| {}))
7262            .unwrap();
7263        assert!(
7264            test_window.frame_wake_count() > baseline,
7265            "scheduling a next-frame callback in an idle window must wake the frame source"
7266        );
7267    }
7268
7269    /// A frame request that arrives while next-frame callbacks are pending
7270    /// must never strand them: either the frame runs them, or (when the
7271    /// inactive-window frame-rate throttle defers the frame) the waker fires
7272    /// so another request is delivered.
7273    #[gpui::test]
7274    fn test_pending_next_frame_callbacks_are_not_stranded(cx: &mut TestAppContext) {
7275        let window = cx.add_window(|_, _| EmptyView);
7276        let test_window = cx.test_window(window.into());
7277        // Establish a recent last-frame time so the inactive-window throttle
7278        // can engage on the next request.
7279        test_window.simulate_frame_request(RequestFrameOptions::default());
7280
7281        let callback_ran = Rc::new(Cell::new(false));
7282        window
7283            .update(cx, {
7284                let callback_ran = callback_ran.clone();
7285                move |_, window, _| {
7286                    window.on_next_frame(move |_, _| callback_ran.set(true));
7287                }
7288            })
7289            .unwrap();
7290
7291        let baseline = test_window.frame_wake_count();
7292        test_window.simulate_frame_request(RequestFrameOptions::default());
7293        // The test window is inactive, so this request throttles to ~30fps
7294        // when it lands within the throttle interval of the previous frame
7295        // (the common case here, but timing-dependent): the callback is
7296        // deferred and the waker must re-arm the frame source. On a slow run
7297        // the request instead lands outside the interval and runs the
7298        // callback directly.
7299        assert!(
7300            test_window.frame_wake_count() > baseline || callback_ran.get(),
7301            "a frame request with pending next-frame callbacks must either run them or re-arm the frame source"
7302        );
7303    }
7304
7305    #[gpui::test]
7306    fn test_window_reports_no_raw_handle_instead_of_panicking(cx: &mut TestAppContext) {
7307        use raw_window_handle::{HandleError, HasDisplayHandle as _, HasWindowHandle as _};
7308
7309        let window = cx.add_window(|_, _| EmptyView);
7310        window
7311            .update(cx, |_, window, _| {
7312                assert!(matches!(
7313                    window.window_handle(),
7314                    Err(HandleError::NotSupported)
7315                ));
7316                assert!(matches!(
7317                    window.display_handle(),
7318                    Err(HandleError::NotSupported)
7319                ));
7320            })
7321            .unwrap();
7322    }
7323
7324    #[gpui::test]
7325    fn test_appearance_change_runs_after_app_update(cx: &mut TestAppContext) {
7326        let window = cx.add_window(|_, _| EmptyView);
7327        let observed_appearance = Rc::new(Cell::new(None));
7328        let _subscription = window
7329            .update(cx, {
7330                let observed_appearance = observed_appearance.clone();
7331                move |_, window, _| {
7332                    window.observe_window_appearance(move |window, _| {
7333                        observed_appearance.set(Some(window.appearance()));
7334                    })
7335                }
7336            })
7337            .unwrap();
7338        let test_window = cx.test_window(window.into());
7339
7340        cx.update(|_| {
7341            test_window.simulate_appearance_change(WindowAppearance::Dark);
7342            assert_eq!(observed_appearance.get(), None);
7343        });
7344        cx.run_until_parked();
7345
7346        assert_eq!(observed_appearance.get(), Some(WindowAppearance::Dark));
7347    }
7348
7349    #[gpui::test]
7350    fn queued_frame_callback_wakes_a_parked_render_loop(cx: &mut TestAppContext) {
7351        let window = cx.add_window(|_, _| Empty);
7352        let test_window = cx.test_window(window.into());
7353
7354        assert!(test_window.simulate_scheduled_frame());
7355        assert!(test_window.simulate_scheduled_frame());
7356        assert!(!test_window.frame_scheduled());
7357
7358        cx.update_window(window.into(), |_, window, _| {
7359            window.active.set(true);
7360            window.on_next_frame(|_, _| {});
7361        })
7362        .unwrap();
7363        assert!(
7364            test_window.frame_scheduled(),
7365            "queuing work on a parked window must wake the render loop"
7366        );
7367
7368        assert!(test_window.simulate_scheduled_frame());
7369        assert!(
7370            test_window.frame_scheduled(),
7371            "presenting the frame must await one compositor callback"
7372        );
7373        assert!(test_window.simulate_scheduled_frame());
7374        assert!(!test_window.frame_scheduled());
7375    }
7376
7377    #[gpui::test]
7378    fn pending_presentation_wakes_a_parked_render_loop(cx: &mut TestAppContext) {
7379        let window = cx.add_window(|_, _| Empty);
7380        let test_window = cx.test_window(window.into());
7381
7382        assert!(test_window.simulate_scheduled_frame());
7383        assert!(test_window.simulate_scheduled_frame());
7384        assert!(!test_window.frame_scheduled());
7385
7386        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
7387            .unwrap();
7388
7389        assert!(
7390            test_window.frame_scheduled(),
7391            "a rendered scene awaiting presentation must wake the render loop"
7392        );
7393    }
7394
7395    #[gpui::test]
7396    fn callback_queued_during_a_frame_requests_a_follow_up(cx: &mut TestAppContext) {
7397        let window = cx.add_window(|_, _| Empty);
7398        let test_window = cx.test_window(window.into());
7399
7400        let callback_ran = Rc::new(Cell::new(false));
7401        cx.update_window(window.into(), |_, window, _| {
7402            // Inactive windows are frame-rate throttled, which would defer the
7403            // ticks this test drives manually.
7404            window.active.set(true);
7405            let callback_ran = callback_ran.clone();
7406            window.on_next_frame(move |window, _| {
7407                window.on_next_frame(move |_, _| callback_ran.set(true));
7408            });
7409        })
7410        .unwrap();
7411
7412        assert!(test_window.simulate_scheduled_frame());
7413        assert!(!callback_ran.get());
7414        assert!(
7415            test_window.frame_scheduled(),
7416            "a callback queued mid-frame must schedule a follow-up before the loop parks"
7417        );
7418
7419        assert!(test_window.simulate_scheduled_frame());
7420        assert!(callback_ran.get());
7421    }
7422
7423    struct RootView {
7424        explicit_size: bool,
7425        child_bounds: Rc<Cell<Bounds<Pixels>>>,
7426    }
7427
7428    impl Render for RootView {
7429        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
7430            let child_bounds = self.child_bounds.clone();
7431            let root = div().flex().flex_col().child(
7432                canvas(
7433                    move |bounds, _, _| child_bounds.set(bounds),
7434                    |_, _, _, _| {},
7435                )
7436                .size_full(),
7437            );
7438            if self.explicit_size {
7439                root.w(px(300.)).h(px(200.))
7440            } else {
7441                root
7442            }
7443        }
7444    }
7445
7446    #[test]
7447    fn auto_sized_window_root_fills_the_window() {
7448        let mut cx = TestAppContext::single();
7449        let child_bounds = Rc::new(Cell::new(Bounds::default()));
7450        let window = cx.add_window({
7451            let child_bounds = child_bounds.clone();
7452            move |_, _| RootView {
7453                explicit_size: false,
7454                child_bounds,
7455            }
7456        });
7457
7458        let viewport_size = cx
7459            .update_window(window.into(), |_, window, cx| {
7460                window.draw(cx).clear(cx);
7461                window.viewport_size()
7462            })
7463            .unwrap();
7464
7465        assert_eq!(child_bounds.get().size, viewport_size);
7466    }
7467
7468    #[test]
7469    fn explicitly_sized_window_root_keeps_its_size() {
7470        let mut cx = TestAppContext::single();
7471        let child_bounds = Rc::new(Cell::new(Bounds::default()));
7472        let window = cx.add_window({
7473            let child_bounds = child_bounds.clone();
7474            move |_, _| RootView {
7475                explicit_size: true,
7476                child_bounds,
7477            }
7478        });
7479
7480        cx.update_window(window.into(), |_, window, cx| {
7481            window.draw(cx).clear(cx);
7482        })
7483        .unwrap();
7484
7485        assert_eq!(child_bounds.get().size, size(px(300.), px(200.)));
7486    }
7487
7488    struct FileDragView {
7489        path: PathBuf,
7490        observed_drag_moves: Rc<RefCell<Vec<Point<Pixels>>>>,
7491        observed_drops: Rc<RefCell<Vec<PathBuf>>>,
7492    }
7493
7494    impl Render for FileDragView {
7495        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
7496            div()
7497                .id("file-drag")
7498                .size_full()
7499                .on_drag(self.path.clone(), |_, _, _, cx| cx.new(|_| Empty))
7500                .external_drag_payload(|path: &PathBuf, _, _| {
7501                    Some(ExternalDragPayload::Files(FileDragPaths::new([(
7502                        path.clone(),
7503                        true,
7504                    )])))
7505                })
7506                .on_drag_move({
7507                    let observed_drag_moves = self.observed_drag_moves.clone();
7508                    move |event: &DragMoveEvent<PathBuf>, _, _| {
7509                        observed_drag_moves.borrow_mut().push(event.event.position);
7510                    }
7511                })
7512                .on_drop({
7513                    let observed_drops = self.observed_drops.clone();
7514                    move |path: &PathBuf, _, _| observed_drops.borrow_mut().push(path.clone())
7515                })
7516        }
7517    }
7518
7519    #[gpui::test]
7520    fn file_drag_is_promoted_once_and_restored_in_source_window(cx: &mut TestAppContext) {
7521        struct Drag {
7522            window: AnyWindowHandle,
7523            observed_drag_moves: Rc<RefCell<Vec<Point<Pixels>>>>,
7524            observed_drops: Rc<RefCell<Vec<PathBuf>>>,
7525        }
7526
7527        fn start_drag(cx: &mut TestAppContext, path: PathBuf, platform_result: bool) -> Drag {
7528            let observed_drag_moves = Rc::new(RefCell::new(Vec::new()));
7529            let observed_drops = Rc::new(RefCell::new(Vec::new()));
7530            let window: AnyWindowHandle = cx
7531                .add_window({
7532                    let observed_drag_moves = observed_drag_moves.clone();
7533                    let observed_drops = observed_drops.clone();
7534                    move |_, _| FileDragView {
7535                        path,
7536                        observed_drag_moves,
7537                        observed_drops,
7538                    }
7539                })
7540                .into();
7541            cx.test_window(window)
7542                .set_start_external_drag_result(platform_result);
7543
7544            let update_result = cx.update_window(window, |_, window, cx| {
7545                window.draw(cx).clear(cx);
7546                window.dispatch_event(
7547                    MouseDownEvent {
7548                        position: point(px(10.), px(10.)),
7549                        button: MouseButton::Left,
7550                        modifiers: Default::default(),
7551                        click_count: 1,
7552                        first_mouse: false,
7553                    }
7554                    .to_platform_input(),
7555                    cx,
7556                );
7557                window.dispatch_event(
7558                    MouseMoveEvent {
7559                        position: point(px(20.), px(20.)),
7560                        pressed_button: Some(MouseButton::Left),
7561                        modifiers: Default::default(),
7562                    }
7563                    .to_platform_input(),
7564                    cx,
7565                );
7566                assert!(cx.active_drag.is_some());
7567            });
7568            assert!(
7569                update_result.is_ok(),
7570                "failed to start drag: {update_result:?}"
7571            );
7572
7573            assert!(cx.test_window(window).external_drag_files().is_empty());
7574            Drag {
7575                window,
7576                observed_drag_moves,
7577                observed_drops,
7578            }
7579        }
7580
7581        let successful_path = PathBuf::from("/tmp/successful-drag");
7582        let successful = start_drag(cx, successful_path.clone(), true);
7583        let outside_position = point(px(-1.), px(20.));
7584        let update_result = cx.update_window(successful.window, |_, window, cx| {
7585            window.dispatch_event(
7586                MouseMoveEvent {
7587                    position: outside_position,
7588                    pressed_button: Some(MouseButton::Left),
7589                    modifiers: Default::default(),
7590                }
7591                .to_platform_input(),
7592                cx,
7593            );
7594            assert!(cx.active_drag.is_none());
7595        });
7596        assert!(
7597            update_result.is_ok(),
7598            "failed to promote drag: {update_result:?}"
7599        );
7600        assert_eq!(
7601            cx.test_window(successful.window).external_drag_files(),
7602            [(successful_path.clone(), true)]
7603        );
7604        // Views must still see the move that leaves the window, otherwise they never learn to tear
7605        // down the drag state they built up while the pointer was inside.
7606        assert_eq!(
7607            successful.observed_drag_moves.borrow().last(),
7608            Some(&outside_position)
7609        );
7610
7611        let destination: AnyWindowHandle = cx.add_window(|_, _| EmptyView).into();
7612        let reentry_position = point(px(30.), px(30.));
7613        let external_paths = || ExternalPaths([successful_path.clone()].into_iter().collect());
7614        let update_result = cx.update_window(destination, |_, window, cx| {
7615            window.dispatch_event(
7616                FileDropEvent::Entered {
7617                    position: reentry_position,
7618                    paths: external_paths(),
7619                }
7620                .to_platform_input(),
7621                cx,
7622            );
7623            assert!(
7624                cx.active_drag
7625                    .as_ref()
7626                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
7627            );
7628            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
7629            assert!(cx.active_drag.is_none());
7630        });
7631        assert!(
7632            update_result.is_ok(),
7633            "failed to handle drag in destination window: {update_result:?}"
7634        );
7635
7636        let update_result = cx.update_window(successful.window, |_, window, cx| {
7637            window.dispatch_event(
7638                FileDropEvent::Entered {
7639                    position: reentry_position,
7640                    paths: external_paths(),
7641                }
7642                .to_platform_input(),
7643                cx,
7644            );
7645            assert!(
7646                cx.active_drag
7647                    .as_ref()
7648                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
7649            );
7650            assert_eq!(
7651                successful.observed_drag_moves.borrow().last(),
7652                Some(&reentry_position)
7653            );
7654
7655            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
7656            assert!(cx.active_drag.is_none());
7657
7658            window.dispatch_event(
7659                FileDropEvent::Entered {
7660                    position: reentry_position,
7661                    paths: external_paths(),
7662                }
7663                .to_platform_input(),
7664                cx,
7665            );
7666            assert!(
7667                cx.active_drag
7668                    .as_ref()
7669                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
7670            );
7671
7672            window.dispatch_event(
7673                FileDropEvent::Submit {
7674                    position: reentry_position,
7675                }
7676                .to_platform_input(),
7677                cx,
7678            );
7679            assert_eq!(
7680                successful.observed_drops.borrow().as_slice(),
7681                std::slice::from_ref(&successful_path)
7682            );
7683            assert!(cx.active_drag.is_none());
7684
7685            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
7686            assert!(cx.active_drag.is_none());
7687            window.dispatch_event(FileDropEvent::Ended.to_platform_input(), cx);
7688            assert!(cx.active_drag.is_none());
7689
7690            window.dispatch_event(
7691                FileDropEvent::Entered {
7692                    position: reentry_position,
7693                    paths: external_paths(),
7694                }
7695                .to_platform_input(),
7696                cx,
7697            );
7698            assert!(
7699                cx.active_drag
7700                    .as_ref()
7701                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
7702            );
7703            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
7704        });
7705        assert!(
7706            update_result.is_ok(),
7707            "failed to restore drag in source window: {update_result:?}"
7708        );
7709
7710        let cancelled_path = PathBuf::from("/tmp/cancelled-drag");
7711        let cancelled = start_drag(cx, cancelled_path.clone(), true);
7712        let update_result = cx.update_window(cancelled.window, |_, window, cx| {
7713            window.dispatch_event(
7714                MouseMoveEvent {
7715                    position: outside_position,
7716                    pressed_button: Some(MouseButton::Left),
7717                    modifiers: Default::default(),
7718                }
7719                .to_platform_input(),
7720                cx,
7721            );
7722            assert!(cx.active_drag.is_none());
7723
7724            window.dispatch_event(
7725                FileDropEvent::Entered {
7726                    position: reentry_position,
7727                    paths: ExternalPaths([cancelled_path].into_iter().collect()),
7728                }
7729                .to_platform_input(),
7730                cx,
7731            );
7732            assert!(
7733                cx.active_drag
7734                    .as_ref()
7735                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
7736            );
7737            assert!(cx.stop_active_drag(window));
7738            assert!(cx.active_drag.is_none());
7739        });
7740        assert!(
7741            update_result.is_ok(),
7742            "failed to cancel restored drag: {update_result:?}"
7743        );
7744        assert!(!cx.update(|cx| cx.end_platform_drag(cancelled.window.window_id())));
7745
7746        let removed_path = PathBuf::from("/tmp/removed-window-drag");
7747        let removed = start_drag(cx, removed_path, true);
7748        let removed_window_id = removed.window.window_id();
7749        let update_result = cx.update_window(removed.window, |_, window, cx| {
7750            window.dispatch_event(
7751                MouseMoveEvent {
7752                    position: outside_position,
7753                    pressed_button: Some(MouseButton::Left),
7754                    modifiers: Default::default(),
7755                }
7756                .to_platform_input(),
7757                cx,
7758            );
7759            assert!(cx.active_drag.is_none());
7760            window.remove_window();
7761        });
7762        assert!(
7763            update_result.is_ok(),
7764            "failed to remove drag source window: {update_result:?}"
7765        );
7766        assert!(!cx.update(|cx| cx.end_platform_drag(removed_window_id)));
7767
7768        let failed_path = PathBuf::from("/tmp/failed-drag");
7769        let failed = start_drag(cx, failed_path.clone(), false);
7770        let update_result = cx.update_window(failed.window, |_, window, cx| {
7771            for x_position in [-1., -2.] {
7772                window.dispatch_event(
7773                    MouseMoveEvent {
7774                        position: point(px(x_position), px(20.)),
7775                        pressed_button: Some(MouseButton::Left),
7776                        modifiers: Default::default(),
7777                    }
7778                    .to_platform_input(),
7779                    cx,
7780                );
7781            }
7782            assert!(cx.active_drag.is_some());
7783        });
7784        assert!(
7785            update_result.is_ok(),
7786            "failed to retain drag after platform failure: {update_result:?}"
7787        );
7788        assert_eq!(
7789            cx.test_window(failed.window).external_drag_files(),
7790            [(failed_path, true)]
7791        );
7792    }
7793
7794    struct FocusForwarder {
7795        a: FocusHandle,
7796        b: FocusHandle,
7797    }
7798
7799    impl Render for FocusForwarder {
7800        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
7801            div()
7802                .size_full()
7803                .child(div().w(px(50.)).h(px(50.)).track_focus(&self.a))
7804                .child(div().w(px(50.)).h(px(50.)).track_focus(&self.b))
7805        }
7806    }
7807
7808    /// When a focus listener moves focus again (e.g. a dock forwarding focus to its
7809    /// active panel), the resulting focus events must be dispatched without waiting
7810    /// for an unrelated redraw of the window.
7811    #[gpui::test]
7812    fn test_focus_moved_by_focus_listener_is_dispatched(cx: &mut TestAppContext) {
7813        let b_focus_count = Rc::new(Cell::new(0));
7814        let window = cx.add_window({
7815            let b_focus_count = b_focus_count.clone();
7816            move |window, cx| {
7817                let a = cx.focus_handle();
7818                let b = cx.focus_handle();
7819                cx.on_focus(&a, window, |this: &mut FocusForwarder, window, cx| {
7820                    let b = this.b.clone();
7821                    window.focus(&b, cx);
7822                })
7823                .detach();
7824                cx.on_focus(&b, window, move |_, _, _| {
7825                    b_focus_count.set(b_focus_count.get() + 1);
7826                })
7827                .detach();
7828                FocusForwarder { a, b }
7829            }
7830        });
7831
7832        window
7833            .update(cx, |_, window, _| window.activate_window())
7834            .unwrap();
7835        cx.executor().run_until_parked();
7836
7837        window
7838            .update(cx, |this, window, cx| {
7839                let a = this.a.clone();
7840                window.focus(&a, cx);
7841            })
7842            .unwrap();
7843        cx.executor().run_until_parked();
7844
7845        window
7846            .update(cx, |this, window, _| {
7847                assert!(this.b.is_focused(window));
7848            })
7849            .unwrap();
7850        assert_eq!(b_focus_count.get(), 1);
7851    }
7852
7853    #[gpui::test]
7854    fn claimed_touch_drag_receives_movement_and_release(cx: &mut TestAppContext) {
7855        let events = Rc::new(RefCell::new(Vec::new()));
7856        let window = cx.add_window({
7857            let events = events.clone();
7858            move |_, _| TouchDragListener { events }
7859        });
7860        let touch = TouchId(1);
7861
7862        dispatch_touch(window, cx, touch, TouchPhase::Started, 10.);
7863        dispatch_touch(window, cx, touch, TouchPhase::Moved, 30.);
7864        dispatch_touch(window, cx, touch, TouchPhase::Ended, 40.);
7865
7866        assert_eq!(
7867            events.borrow().as_slice(),
7868            [
7869                (TouchPhase::Started, px(10.)),
7870                (TouchPhase::Moved, px(30.)),
7871                (TouchPhase::Ended, px(40.)),
7872            ]
7873        );
7874    }
7875
7876    struct TouchDragListener {
7877        events: Rc<RefCell<Vec<(TouchPhase, Pixels)>>>,
7878    }
7879
7880    impl Render for TouchDragListener {
7881        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
7882            let events = self.events.clone();
7883            canvas(
7884                |_, _, _| {},
7885                move |_, _, window, _| {
7886                    window.on_mouse_event(move |event: &TouchDragEvent, phase, window, _cx| {
7887                        if phase != DispatchPhase::Bubble {
7888                            return;
7889                        }
7890                        events.borrow_mut().push((event.phase, event.position.x));
7891                        if event.phase == TouchPhase::Started {
7892                            window.prevent_default();
7893                        }
7894                    });
7895                },
7896            )
7897        }
7898    }
7899
7900    #[gpui::test]
7901    fn long_press_is_claimed_only_when_started_prevents_default(cx: &mut TestAppContext) {
7902        for response in [
7903            LongPressResponse::PreventDefault,
7904            LongPressResponse::StopPropagation,
7905            LongPressResponse::None,
7906        ] {
7907            let phases = Rc::new(RefCell::new(Vec::new()));
7908            let window = cx.add_window({
7909                let phases = phases.clone();
7910                move |_, _| LongPressListener { phases, response }
7911            });
7912            dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
7913            cx.executor().advance_clock(Duration::from_millis(501));
7914            cx.executor().run_until_parked();
7915            window
7916                .update(cx, |_, window, _| {
7917                    assert_eq!(
7918                        window.long_press_capture.is_some(),
7919                        response == LongPressResponse::PreventDefault
7920                    );
7921                })
7922                .unwrap();
7923            dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.);
7924            dispatch_touch(window, cx, TouchId(1), TouchPhase::Ended, 2.);
7925            window
7926                .update(cx, |_, window, _| {
7927                    assert!(window.long_press_capture.is_none());
7928                })
7929                .unwrap();
7930
7931            let phases = phases.borrow();
7932            if response == LongPressResponse::PreventDefault {
7933                assert_eq!(
7934                    phases.as_slice(),
7935                    [TouchPhase::Started, TouchPhase::Moved, TouchPhase::Ended]
7936                );
7937            } else {
7938                assert_eq!(phases.as_slice(), [TouchPhase::Started]);
7939            }
7940        }
7941    }
7942
7943    #[gpui::test]
7944    fn stale_default_prevention_does_not_claim_long_press(cx: &mut TestAppContext) {
7945        let phases = Rc::new(RefCell::new(Vec::new()));
7946        let window = cx.add_window({
7947            let phases = phases.clone();
7948            move |_, _| LongPressListener {
7949                phases,
7950                response: LongPressResponse::None,
7951            }
7952        });
7953        window
7954            .update(cx, |_, window, _| {
7955                window.prevent_default();
7956            })
7957            .unwrap();
7958
7959        dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
7960        cx.executor().advance_clock(Duration::from_millis(501));
7961        cx.executor().run_until_parked();
7962        dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.);
7963
7964        assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]);
7965    }
7966
7967    #[gpui::test]
7968    fn resolved_touch_cancels_scheduled_long_press(cx: &mut TestAppContext) {
7969        for (phase, position) in [
7970            (TouchPhase::Ended, 0.),
7971            (TouchPhase::Cancelled, 0.),
7972            (TouchPhase::Moved, 20.),
7973        ] {
7974            let phases = Rc::new(RefCell::new(Vec::new()));
7975            let window = cx.add_window({
7976                let phases = phases.clone();
7977                move |_, _| LongPressListener {
7978                    phases,
7979                    response: LongPressResponse::PreventDefault,
7980                }
7981            });
7982            dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
7983            dispatch_touch(window, cx, TouchId(1), phase, position);
7984            cx.executor().advance_clock(Duration::from_millis(501));
7985            cx.executor().run_until_parked();
7986
7987            assert!(phases.borrow().is_empty(), "{phase:?} allowed long press");
7988        }
7989    }
7990
7991    #[gpui::test]
7992    fn stale_long_press_timer_cannot_affect_replacement_touch(cx: &mut TestAppContext) {
7993        let phases = Rc::new(RefCell::new(Vec::new()));
7994        let window = cx.add_window({
7995            let phases = phases.clone();
7996            move |_, _| LongPressListener {
7997                phases,
7998                response: LongPressResponse::PreventDefault,
7999            }
8000        });
8001        let first_touch = TouchId(1);
8002        dispatch_touch(window, cx, first_touch, TouchPhase::Started, 0.);
8003        cx.executor().advance_clock(Duration::from_millis(250));
8004        dispatch_touch(window, cx, first_touch, TouchPhase::Cancelled, 0.);
8005        dispatch_touch(window, cx, TouchId(2), TouchPhase::Started, 10.);
8006
8007        cx.executor().advance_clock(Duration::from_millis(251));
8008        cx.executor().run_until_parked();
8009        assert!(phases.borrow().is_empty());
8010
8011        cx.executor().advance_clock(Duration::from_millis(250));
8012        cx.executor().run_until_parked();
8013        assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]);
8014    }
8015
8016    #[derive(Clone, Copy, PartialEq)]
8017    enum LongPressResponse {
8018        PreventDefault,
8019        StopPropagation,
8020        None,
8021    }
8022
8023    struct LongPressListener {
8024        phases: Rc<RefCell<Vec<TouchPhase>>>,
8025        response: LongPressResponse,
8026    }
8027
8028    impl Render for LongPressListener {
8029        fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
8030            let entity = cx.entity();
8031            let phases = self.phases.clone();
8032            let response = self.response;
8033            canvas(
8034                |_, _, _| {},
8035                move |_, _, window, _| {
8036                    window.on_mouse_event(move |event: &LongPressEvent, phase, window, cx| {
8037                        if phase != DispatchPhase::Bubble {
8038                            return;
8039                        }
8040                        phases.borrow_mut().push(event.phase);
8041                        match response {
8042                            LongPressResponse::PreventDefault => {
8043                                window.capture_long_press(&entity);
8044                                window.prevent_default();
8045                            }
8046                            LongPressResponse::StopPropagation => cx.stop_propagation(),
8047                            LongPressResponse::None => {}
8048                        }
8049                    });
8050                },
8051            )
8052        }
8053    }
8054
8055    fn dispatch_touch<T: 'static>(
8056        window: crate::WindowHandle<T>,
8057        cx: &mut TestAppContext,
8058        id: TouchId,
8059        phase: TouchPhase,
8060        x: f32,
8061    ) {
8062        window
8063            .update(cx, |_, window, cx| {
8064                window.dispatch_event(
8065                    TouchEvent {
8066                        id,
8067                        phase,
8068                        position: point(px(x), px(0.)),
8069                        predicted_position: None,
8070                        force: None,
8071                    }
8072                    .to_platform_input(),
8073                    cx,
8074                );
8075            })
8076            .unwrap();
8077    }
8078}