Skip to main content

gpui/
window.rs

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