Skip to main content

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