Skip to main content

gpui/
window.rs

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