Skip to main content

gpui/
window.rs

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