Skip to main content

gpui/
window.rs

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