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