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