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