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