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