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    /// Presents the most recently drawn frame to the window's renderer.
3865    ///
3866    /// Runtime API: this is the second half of the offscreen/embedded path, where
3867    /// [`Self::draw`] builds a frame and the caller decides when it is shown. An
3868    /// ordinary window never calls it directly — the platform's frame callback
3869    /// draws and presents in one turn — but a host loop that owns its own cadence
3870    /// does, exactly as the visual harnesses do.
3871    #[doc(hidden)]
3872    #[profiling::function]
3873    pub fn present(&mut self) {
3874        #[cfg(feature = "profiler")]
3875        let _foreground_turn = profiler::journal::foreground_turn();
3876        #[cfg(feature = "profiler")]
3877        let present_start = Instant::now();
3878        self.core
3879            .platform_window
3880            .present(&mut |renderer| renderer.draw(&self.frame_state.rendered_frame.scene));
3881        #[cfg(feature = "profiler")]
3882        self.core.window_profiler.record_present(
3883            present_start,
3884            Instant::now(),
3885            self.core.active.get(),
3886            !self.core.next_frame_callbacks.borrow().is_empty(),
3887        );
3888        self.core.needs_present.set(false);
3889        profiling::finish_frame!();
3890    }
3891
3892    /// Presents the most recently drawn frame if it hasn't been presented yet.
3893    #[cfg(all(test, feature = "profiler"))]
3894    pub(crate) fn present_if_needed(&mut self) {
3895        if self.core.needs_present.get() {
3896            self.present();
3897        }
3898    }
3899
3900    /// Returns a snapshot of the current input-latency histograms.
3901    #[cfg(feature = "profiler")]
3902    pub fn input_latency_snapshot(&self) -> profiler::InputLatencySnapshot {
3903        self.core.window_profiler.input_latency_snapshot()
3904    }
3905
3906    /// Returns a snapshot of the current frame-duration histograms.
3907    #[cfg(feature = "profiler")]
3908    pub fn frame_duration_snapshot(&self) -> profiler::FrameDurationSnapshot {
3909        self.core.window_profiler.frame_duration_snapshot()
3910    }
3911
3912    /// Returns the current mode of the debug frame overlay.
3913    #[cfg(feature = "profiler")]
3914    pub fn debug_frame_overlay_mode(&self) -> DebugFrameOverlayMode {
3915        self.core.debug_frame_overlay.mode()
3916    }
3917
3918    /// Sets the mode of the debug frame overlay and schedules a redraw.
3919    #[cfg(feature = "profiler")]
3920    pub fn set_debug_frame_overlay_mode(&mut self, mode: DebugFrameOverlayMode) {
3921        self.core.debug_frame_overlay.set_mode(mode);
3922        self.refresh();
3923    }
3924
3925    /// Advances the debug frame overlay through its hidden, frame-time-only,
3926    /// and detailed modes.
3927    #[cfg(feature = "profiler")]
3928    pub fn cycle_debug_frame_overlay_mode(&mut self) {
3929        self.set_debug_frame_overlay_mode(self.core.debug_frame_overlay.mode().next());
3930    }
3931
3932    /// Clears the debug frame overlay's frame-time statistics, except for the
3933    /// total frame count, and schedules a redraw.
3934    #[cfg(feature = "profiler")]
3935    pub fn reset_debug_frame_overlay_stats(&mut self) {
3936        self.core.debug_frame_overlay.reset_stats();
3937        self.refresh();
3938    }
3939
3940    /// Gathers the roots this frame will draw.
3941    ///
3942    /// The root element is produced here; a view's [`Render`][crate::Render] is
3943    /// not called until [`layout_roots`](Self::layout_roots) lays it out, because
3944    /// an element builds its tree when it is asked for a layout.
3945    pub fn evaluate_roots(&mut self, cx: &mut App) -> PreparedRoots {
3946        #[cfg(debug_assertions)]
3947        self.frame_state.frame_phase.enter(
3948            &[FramePhase::Begun],
3949            FramePhase::Evaluated,
3950            "evaluate_roots",
3951        );
3952        let root = self.core.root.as_ref().unwrap().clone().into_any_element();
3953
3954        // A prompt displaces the other overlays rather than stacking with them,
3955        // so at most one of prompt, drag and tooltip is drawn.
3956        let mut prompt = None;
3957        let mut drag = None;
3958        if let Some(handle) = self.core.prompt.take() {
3959            prompt = Some(handle.view.any_view().into_any_element());
3960            self.core.prompt = Some(handle);
3961        } else if let Some(active_drag) = cx.active_drag.take() {
3962            let origin = self.mouse_position() - active_drag.cursor_offset;
3963            drag = Some((active_drag.view.clone().into_any_element(), origin));
3964            cx.active_drag = Some(active_drag);
3965        }
3966
3967        PreparedRoots {
3968            root,
3969            prompt,
3970            tooltip: None,
3971            drag,
3972            inspector: None,
3973        }
3974    }
3975
3976    /// Lays out and prepaints the roots, then hit tests the pointer against what
3977    /// they registered.
3978    pub fn layout_roots(&mut self, roots: &mut PreparedRoots, cx: &mut App) {
3979        #[cfg(debug_assertions)]
3980        self.frame_state.frame_phase.enter(
3981            &[FramePhase::Evaluated],
3982            FramePhase::LaidOut,
3983            "layout_roots",
3984        );
3985        self.core.invalidator.set_phase(DrawPhase::Prepaint);
3986        self.frame_state.tooltip_bounds.take();
3987
3988        self.core.a11y.sync_active_flag();
3989        if self.core.a11y.is_active() {
3990            self.core.a11y.begin_frame();
3991        }
3992
3993        #[cfg(any(feature = "inspector", debug_assertions))]
3994        let inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size());
3995        let root_size = {
3996            #[cfg(any(feature = "inspector", debug_assertions))]
3997            {
3998                if self.core.inspector.is_some() {
3999                    let mut size = self.core.viewport_size;
4000                    size.width = (size.width - inspector_width).max(px(0.0));
4001                    size
4002                } else {
4003                    self.core.viewport_size
4004                }
4005            }
4006            #[cfg(not(any(feature = "inspector", debug_assertions)))]
4007            {
4008                self.core.viewport_size
4009            }
4010        };
4011
4012        // Layout all root elements. Like the root element on the web, which
4013        // stretches to fill the viewport unless explicitly sized, window roots
4014        // fill the window when their size is `auto`.
4015        let scale_factor = self.scale_factor();
4016        let root_layout_id = roots.root.request_layout(self, cx);
4017        self.frame_state.layout_session.stretch_auto_size_to_fill(
4018            root_layout_id,
4019            root_size,
4020            scale_factor,
4021        );
4022        roots
4023            .root
4024            .prepaint_as_root(Point::default(), root_size.into(), self, cx);
4025
4026        #[cfg(any(feature = "inspector", debug_assertions))]
4027        {
4028            roots.inspector = self.prepaint_inspector(inspector_width, cx);
4029        }
4030
4031        self.prepaint_deferred_draws(cx);
4032
4033        if let Some(prompt) = roots.prompt.as_mut() {
4034            let prompt_layout_id = prompt.request_layout(self, cx);
4035            self.frame_state.layout_session.stretch_auto_size_to_fill(
4036                prompt_layout_id,
4037                root_size,
4038                scale_factor,
4039            );
4040            prompt.prepaint_as_root(Point::default(), root_size.into(), self, cx);
4041        } else if let Some((drag, origin)) = roots.drag.as_mut() {
4042            drag.prepaint_as_root(*origin, AvailableSpace::min_size(), self, cx);
4043        } else {
4044            roots.tooltip = self.prepaint_tooltip(cx);
4045        }
4046
4047        self.core.mouse_hit_test = self
4048            .frame_state
4049            .next_frame
4050            .hit_test(self.core.mouse_position);
4051    }
4052
4053    /// Paints the roots, in the order they stack.
4054    pub fn paint_roots(&mut self, mut roots: PreparedRoots, cx: &mut App) {
4055        #[cfg(debug_assertions)]
4056        self.frame_state.frame_phase.enter(
4057            &[FramePhase::LaidOut],
4058            FramePhase::Painted,
4059            "paint_roots",
4060        );
4061        self.core.invalidator.set_phase(DrawPhase::Paint);
4062        roots.root.paint(self, cx);
4063
4064        #[cfg(any(feature = "inspector", debug_assertions))]
4065        self.paint_inspector(roots.inspector.take(), cx);
4066
4067        self.paint_deferred_draws(cx);
4068
4069        if let Some(mut prompt) = roots.prompt.take() {
4070            prompt.paint(self, cx);
4071        } else if let Some((mut drag, _)) = roots.drag.take() {
4072            drag.paint(self, cx);
4073        } else if let Some(mut tooltip) = roots.tooltip.take() {
4074            tooltip.paint(self, cx);
4075        }
4076
4077        #[cfg(any(feature = "inspector", debug_assertions))]
4078        self.paint_inspector_hitbox(cx);
4079
4080        // a11y may have been activated/deactivated halfway through the frame
4081        let a11y_active_start_of_frame = self.core.a11y.is_active();
4082        self.core.a11y.sync_active_flag();
4083        let a11y_active_end_of_frame = self.core.a11y.is_active();
4084
4085        let should_send_a11y_update = a11y_active_start_of_frame && a11y_active_end_of_frame;
4086
4087        if a11y_active_start_of_frame {
4088            // Harvest frame metadata for the debug dump while the live window
4089            // and frame are still in scope.
4090            let frame_info = crate::window::a11y::debug::FrameDebugInfo {
4091                viewport_size: self.core.viewport_size,
4092                scale_factor: self.core.scale_factor,
4093                tab_stop_count: self.frame_state.next_frame.tab_stops.tab_stop_count(),
4094            };
4095            // clear the builder state regardless
4096            let tree_update = self.core.a11y.end_frame(frame_info);
4097
4098            if should_send_a11y_update {
4099                log::debug!(
4100                    "Sending a11y tree update: {} nodes",
4101                    tree_update.nodes.len()
4102                );
4103                self.core.platform_window.a11y_tree_update(tree_update);
4104            }
4105        }
4106    }
4107
4108    /// Draws the window's roots: everything on screen except the deferred draws.
4109    ///
4110    /// The three passes above, in sequence, with no [`FramePipeline`] between
4111    /// them. A pipeline composes its own passes instead of calling this, which is
4112    /// what [`FramePipeline::draw_roots`] does.
4113    pub fn draw_roots(&mut self, cx: &mut App) {
4114        let mut roots = self.evaluate_roots(cx);
4115        self.layout_roots(&mut roots, cx);
4116        self.paint_roots(roots, cx);
4117    }
4118
4119    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {
4120        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.
4121        for tooltip_request_index in (0..self.frame_state.next_frame.tooltip_requests.len()).rev() {
4122            let Some(Some(tooltip_request)) = self
4123                .frame_state
4124                .next_frame
4125                .tooltip_requests
4126                .get(tooltip_request_index)
4127                .cloned()
4128            else {
4129                log::error!("Unexpectedly absent TooltipRequest");
4130                continue;
4131            };
4132            let mut element = tooltip_request.tooltip.view.clone().into_any_element();
4133            let mouse_position = tooltip_request.tooltip.mouse_position;
4134            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);
4135
4136            let mut tooltip_bounds =
4137                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
4138            let window_bounds = Bounds {
4139                origin: Point::default(),
4140                size: self.viewport_size(),
4141            };
4142
4143            if tooltip_bounds.right() > window_bounds.right() {
4144                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
4145                if new_x >= Pixels::ZERO {
4146                    tooltip_bounds.origin.x = new_x;
4147                } else {
4148                    tooltip_bounds.origin.x = cmp::max(
4149                        Pixels::ZERO,
4150                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
4151                    );
4152                }
4153            }
4154
4155            if tooltip_bounds.bottom() > window_bounds.bottom() {
4156                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
4157                if new_y >= Pixels::ZERO {
4158                    tooltip_bounds.origin.y = new_y;
4159                } else {
4160                    tooltip_bounds.origin.y = cmp::max(
4161                        Pixels::ZERO,
4162                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
4163                    );
4164                }
4165            }
4166
4167            // It's possible for an element to have an active tooltip while not being painted (e.g.
4168            // via the `visible_on_hover` method). Since mouse listeners are not active in this
4169            // case, instead update the tooltip's visibility here.
4170            let is_visible =
4171                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);
4172            if !is_visible {
4173                continue;
4174            }
4175
4176            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {
4177                element.prepaint(window, cx)
4178            });
4179
4180            self.frame_state.tooltip_bounds = Some(TooltipBounds {
4181                id: tooltip_request.id,
4182                bounds: tooltip_bounds,
4183            });
4184            return Some(element);
4185        }
4186        None
4187    }
4188
4189    fn prepaint_deferred_draws(&mut self, cx: &mut App) {
4190        assert_eq!(self.frame_state.element_id_stack.len(), 0);
4191
4192        // Process deferred draws in multiple rounds to support nesting.
4193        // Each round processes all current deferred draws, which may push new ones.
4194        //
4195        // The draws are processed in place rather than being moved out of
4196        // `next_frame.deferred_draws`: `prepaint_index` snapshots that vector's
4197        // length, so any prepaint range recorded during a round (view caches,
4198        // nested deferred draws) must index the same vector `reuse_prepaint`
4199        // slices on the next frame. Moving the draws out and re-appending them
4200        // shifts the indices of nested draws, causing reused subtrees to graft
4201        // the wrong deferred draws and panic in the dispatch tree.
4202        let mut round_start = 0;
4203        let mut depth = 0;
4204        loop {
4205            let round_end = self.frame_state.next_frame.deferred_draws.len();
4206            if round_start == round_end {
4207                break;
4208            }
4209            // Limit maximum nesting depth to prevent infinite loops.
4210            assert!(depth < 10, "Exceeded maximum (10) deferred depth");
4211            depth += 1;
4212
4213            // Sort this round by priority.
4214            let mut traversal_order = (round_start..round_end).collect::<SmallVec<[usize; 8]>>();
4215            traversal_order
4216                .sort_by_key(|ix| self.frame_state.next_frame.deferred_draws[*ix].priority);
4217
4218            for deferred_draw_ix in traversal_order {
4219                let (element, parent_node, current_view, rem_size, absolute_offset, prepaint_range) = {
4220                    let deferred_draw =
4221                        &mut self.frame_state.next_frame.deferred_draws[deferred_draw_ix];
4222                    self.frame_state
4223                        .element_id_stack
4224                        .clone_from(&deferred_draw.element_id_stack);
4225                    self.frame_state
4226                        .text_style_stack
4227                        .clone_from(&deferred_draw.text_style_stack);
4228                    (
4229                        deferred_draw.element.take(),
4230                        deferred_draw.parent_node,
4231                        deferred_draw.current_view,
4232                        deferred_draw.rem_size,
4233                        deferred_draw.absolute_offset,
4234                        deferred_draw.prepaint_range.clone(),
4235                    )
4236                };
4237                self.frame_state
4238                    .next_frame
4239                    .dispatch_tree
4240                    .set_active_node(parent_node);
4241
4242                let prepaint_start = self.prepaint_index();
4243                if let Some(mut element) = element {
4244                    self.with_rendered_view(current_view, |window| {
4245                        window.with_rem_size(Some(rem_size), |window| {
4246                            window.with_absolute_element_offset(absolute_offset, |window| {
4247                                element.prepaint(window, cx);
4248                            });
4249                        });
4250                    });
4251                    self.frame_state.next_frame.deferred_draws[deferred_draw_ix].element =
4252                        Some(element);
4253                } else {
4254                    self.reuse_prepaint(prepaint_range);
4255                }
4256                let prepaint_end = self.prepaint_index();
4257                self.frame_state.next_frame.deferred_draws[deferred_draw_ix].prepaint_range =
4258                    prepaint_start..prepaint_end;
4259            }
4260
4261            self.frame_state.element_id_stack.clear();
4262            self.frame_state.text_style_stack.clear();
4263            round_start = round_end;
4264        }
4265    }
4266
4267    fn paint_deferred_draws(&mut self, cx: &mut App) {
4268        assert_eq!(self.frame_state.element_id_stack.len(), 0);
4269
4270        // Paint all deferred draws in priority order.
4271        // Since prepaint has already processed nested deferreds, we just paint them all.
4272        if self.frame_state.next_frame.deferred_draws.len() == 0 {
4273            return;
4274        }
4275
4276        let traversal_order = self.deferred_draw_traversal_order();
4277        let mut deferred_draws = mem::take(&mut self.frame_state.next_frame.deferred_draws);
4278        for deferred_draw_ix in traversal_order {
4279            let mut deferred_draw = &mut deferred_draws[deferred_draw_ix];
4280            self.frame_state
4281                .element_id_stack
4282                .clone_from(&deferred_draw.element_id_stack);
4283            self.frame_state
4284                .next_frame
4285                .dispatch_tree
4286                .set_active_node(deferred_draw.parent_node);
4287
4288            let paint_start = self.paint_index();
4289            let content_mask = deferred_draw.content_mask;
4290            if let Some(element) = deferred_draw.element.as_mut() {
4291                self.with_rendered_view(deferred_draw.current_view, |window| {
4292                    window.with_content_mask(content_mask, |window| {
4293                        window.with_rem_size(Some(deferred_draw.rem_size), |window| {
4294                            element.paint(window, cx);
4295                        });
4296                    })
4297                })
4298            } else {
4299                self.reuse_paint(deferred_draw.paint_range.clone());
4300            }
4301            let paint_end = self.paint_index();
4302            deferred_draw.paint_range = paint_start..paint_end;
4303        }
4304        self.frame_state.next_frame.deferred_draws = deferred_draws;
4305        self.frame_state.element_id_stack.clear();
4306    }
4307
4308    fn deferred_draw_traversal_order(&mut self) -> SmallVec<[usize; 8]> {
4309        let deferred_count = self.frame_state.next_frame.deferred_draws.len();
4310        let mut sorted_indices = (0..deferred_count).collect::<SmallVec<[_; 8]>>();
4311        sorted_indices.sort_by_key(|ix| self.frame_state.next_frame.deferred_draws[*ix].priority);
4312        sorted_indices
4313    }
4314
4315    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {
4316        PrepaintStateIndex {
4317            hitboxes_index: self.frame_state.next_frame.hitboxes.len(),
4318            tooltips_index: self.frame_state.next_frame.tooltip_requests.len(),
4319            deferred_draws_index: self.frame_state.next_frame.deferred_draws.len(),
4320            dispatch_tree_index: self.frame_state.next_frame.dispatch_tree.len(),
4321            accessed_element_states_index: self
4322                .frame_state
4323                .next_frame
4324                .accessed_element_states
4325                .len(),
4326            line_layout_index: self.core.text_system.layout_index(),
4327        }
4328    }
4329
4330    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {
4331        self.frame_state.next_frame.hitboxes.extend(
4332            self.frame_state.rendered_frame.hitboxes
4333                [range.start.hitboxes_index..range.end.hitboxes_index]
4334                .iter()
4335                .cloned(),
4336        );
4337        self.frame_state.next_frame.hitbox_filters.extend(
4338            self.frame_state.rendered_frame.hitbox_filters
4339                [range.start.hitboxes_index..range.end.hitboxes_index]
4340                .iter()
4341                .cloned(),
4342        );
4343        self.frame_state.next_frame.tooltip_requests.extend(
4344            self.frame_state.rendered_frame.tooltip_requests
4345                [range.start.tooltips_index..range.end.tooltips_index]
4346                .iter_mut()
4347                .map(|request| request.take()),
4348        );
4349        self.frame_state.next_frame.accessed_element_states.extend(
4350            self.frame_state.rendered_frame.accessed_element_states[range
4351                .start
4352                .accessed_element_states_index
4353                ..range.end.accessed_element_states_index]
4354                .iter()
4355                .map(|(id, type_id)| (id.clone(), *type_id)),
4356        );
4357        self.core
4358            .text_system
4359            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
4360
4361        let reused_subtree = self.frame_state.next_frame.dispatch_tree.reuse_subtree(
4362            range.start.dispatch_tree_index..range.end.dispatch_tree_index,
4363            &mut self.frame_state.rendered_frame.dispatch_tree,
4364            self.core.focus,
4365        );
4366
4367        if reused_subtree.contains_focus() {
4368            self.frame_state.next_frame.focus = self.core.focus;
4369        }
4370
4371        self.frame_state.next_frame.deferred_draws.extend(
4372            self.frame_state.rendered_frame.deferred_draws
4373                [range.start.deferred_draws_index..range.end.deferred_draws_index]
4374                .iter()
4375                .map(|deferred_draw| DeferredDraw {
4376                    current_view: deferred_draw.current_view,
4377                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
4378                    element_id_stack: deferred_draw.element_id_stack.clone(),
4379                    text_style_stack: deferred_draw.text_style_stack.clone(),
4380                    content_mask: deferred_draw.content_mask,
4381                    rem_size: deferred_draw.rem_size,
4382                    priority: deferred_draw.priority,
4383                    element: None,
4384                    absolute_offset: deferred_draw.absolute_offset,
4385                    prepaint_range: deferred_draw.prepaint_range.clone(),
4386                    paint_range: deferred_draw.paint_range.clone(),
4387                }),
4388        );
4389    }
4390
4391    pub(crate) fn paint_index(&self) -> PaintIndex {
4392        PaintIndex {
4393            scene_index: self.frame_state.next_frame.scene.len(),
4394            #[cfg(any(test, feature = "test-support"))]
4395            debug_bounds_index: self.frame_state.next_frame.debug_bounds_records.len(),
4396            mouse_listeners_index: self.frame_state.next_frame.mouse_listeners.len(),
4397            input_handlers_index: self.frame_state.next_frame.input_handlers.len(),
4398            cursor_styles_index: self.frame_state.next_frame.cursor_styles.len(),
4399            accessed_element_states_index: self
4400                .frame_state
4401                .next_frame
4402                .accessed_element_states
4403                .len(),
4404            tab_handle_index: self.frame_state.next_frame.tab_stops.paint_index(),
4405            line_layout_index: self.core.text_system.layout_index(),
4406        }
4407    }
4408
4409    pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
4410        // Cached elements still exist in the frame even when their paint methods don't run.
4411        #[cfg(any(test, feature = "test-support"))]
4412        for (selector, bounds) in &self.frame_state.rendered_frame.debug_bounds_records
4413            [range.start.debug_bounds_index..range.end.debug_bounds_index]
4414        {
4415            self.frame_state
4416                .next_frame
4417                .record_debug_bounds(selector.clone(), *bounds);
4418        }
4419        self.frame_state.next_frame.cursor_styles.extend(
4420            self.frame_state.rendered_frame.cursor_styles
4421                [range.start.cursor_styles_index..range.end.cursor_styles_index]
4422                .iter()
4423                .cloned(),
4424        );
4425        self.frame_state.next_frame.input_handlers.extend(
4426            self.frame_state.rendered_frame.input_handlers
4427                [range.start.input_handlers_index..range.end.input_handlers_index]
4428                .iter_mut()
4429                .map(|handler| handler.take()),
4430        );
4431        self.frame_state.next_frame.mouse_listeners.extend(
4432            self.frame_state.rendered_frame.mouse_listeners
4433                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
4434                .iter_mut()
4435                .map(|listener| listener.take()),
4436        );
4437        self.frame_state.next_frame.accessed_element_states.extend(
4438            self.frame_state.rendered_frame.accessed_element_states[range
4439                .start
4440                .accessed_element_states_index
4441                ..range.end.accessed_element_states_index]
4442                .iter()
4443                .map(|(id, type_id)| (id.clone(), *type_id)),
4444        );
4445        self.frame_state.next_frame.tab_stops.replay(
4446            &self.frame_state.rendered_frame.tab_stops.insertion_history
4447                [range.start.tab_handle_index..range.end.tab_handle_index],
4448        );
4449
4450        self.core
4451            .text_system
4452            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
4453        self.frame_state.next_frame.scene.replay(
4454            range.start.scene_index..range.end.scene_index,
4455            &self.frame_state.rendered_frame.scene,
4456        );
4457    }
4458
4459    /// Push a text style onto the stack, and call a function with that style active.
4460    /// Use [`Window::text_style`] to get the current, combined text style. This method
4461    /// should only be called as part of element drawing.
4462    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
4463    where
4464        F: FnOnce(&mut Self) -> R,
4465    {
4466        self.core.invalidator.debug_assert_paint_or_prepaint();
4467        if let Some(style) = style {
4468            self.frame_state.text_style_stack.push(style);
4469            let result = f(self);
4470            self.frame_state.text_style_stack.pop();
4471            result
4472        } else {
4473            f(self)
4474        }
4475    }
4476
4477    /// Updates the cursor style at the platform level. This method should only be called
4478    /// during the paint phase of element drawing.
4479    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
4480        self.core.invalidator.debug_assert_paint();
4481        self.frame_state
4482            .next_frame
4483            .cursor_styles
4484            .push(CursorStyleRequest {
4485                hitbox_id: Some(hitbox.id),
4486                style,
4487            });
4488    }
4489
4490    /// Updates the cursor style for the entire window at the platform level. A cursor
4491    /// style using this method will have precedence over any cursor style set using
4492    /// `set_cursor_style`. This method should only be called during the paint
4493    /// phase of element drawing.
4494    pub fn set_window_cursor_style(&mut self, style: CursorStyle) {
4495        self.core.invalidator.debug_assert_paint();
4496        self.frame_state
4497            .next_frame
4498            .cursor_styles
4499            .push(CursorStyleRequest {
4500                hitbox_id: None,
4501                style,
4502            })
4503    }
4504
4505    /// Sets a tooltip to be rendered for the upcoming frame. This method should only be called
4506    /// during the paint phase of element drawing.
4507    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
4508        self.core.invalidator.debug_assert_prepaint();
4509        let id = TooltipId(post_inc(&mut self.frame_state.next_tooltip_id.0));
4510        self.frame_state
4511            .next_frame
4512            .tooltip_requests
4513            .push(Some(TooltipRequest { id, tooltip }));
4514        id
4515    }
4516
4517    /// Invoke the given function with the given content mask after intersecting it
4518    /// with the current mask. This method should only be called during element drawing.
4519    // This function is called in a highly recursive manner in editor
4520    // prepainting, make sure its inlined to reduce the stack burden
4521    #[inline]
4522    pub fn with_content_mask<R>(
4523        &mut self,
4524        mask: Option<ContentMask<Pixels>>,
4525        f: impl FnOnce(&mut Self) -> R,
4526    ) -> R {
4527        self.core.invalidator.debug_assert_paint_or_prepaint();
4528        if let Some(mask) = mask {
4529            let mask = mask.intersect(&self.content_mask());
4530            self.frame_state.content_mask_stack.push(mask);
4531            let result = f(self);
4532            self.frame_state.content_mask_stack.pop();
4533            result
4534        } else {
4535            f(self)
4536        }
4537    }
4538
4539    /// Updates the global element offset relative to the current offset. This is used to implement
4540    /// scrolling. This method should only be called during the prepaint phase of element drawing.
4541    pub fn with_element_offset<R>(
4542        &mut self,
4543        offset: Point<Pixels>,
4544        f: impl FnOnce(&mut Self) -> R,
4545    ) -> R {
4546        self.core.invalidator.debug_assert_prepaint();
4547
4548        if offset.is_zero() {
4549            return f(self);
4550        };
4551
4552        let abs_offset = self.element_offset() + offset;
4553        self.with_absolute_element_offset(abs_offset, f)
4554    }
4555
4556    /// Updates the global element offset based on the given offset. This is used to implement
4557    /// drag handles and other manual painting of elements. This method should only be called during
4558    /// the prepaint phase of element drawing.
4559    pub fn with_absolute_element_offset<R>(
4560        &mut self,
4561        offset: Point<Pixels>,
4562        f: impl FnOnce(&mut Self) -> R,
4563    ) -> R {
4564        self.core.invalidator.debug_assert_prepaint();
4565        self.frame_state.element_offset_stack.push(offset);
4566        let result = f(self);
4567        self.frame_state.element_offset_stack.pop();
4568        result
4569    }
4570
4571    pub(crate) fn with_element_opacity<R>(
4572        &mut self,
4573        opacity: Option<f32>,
4574        f: impl FnOnce(&mut Self) -> R,
4575    ) -> R {
4576        self.core.invalidator.debug_assert_paint_or_prepaint();
4577
4578        let Some(opacity) = opacity else {
4579            return f(self);
4580        };
4581
4582        let previous_opacity = self.frame_state.element_opacity;
4583        self.frame_state.element_opacity = previous_opacity * opacity;
4584        let result = f(self);
4585        self.frame_state.element_opacity = previous_opacity;
4586        result
4587    }
4588
4589    /// Perform prepaint on child elements in a "retryable" manner, so that any side effects
4590    /// of prepaints can be discarded before prepainting again. This is used to support autoscroll
4591    /// where we need to prepaint children to detect the autoscroll bounds, then adjust the
4592    /// element offset and prepaint again. See [`crate::List`] for an example. This method should only be
4593    /// called during the prepaint phase of element drawing.
4594    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {
4595        self.core.invalidator.debug_assert_prepaint();
4596        let index = self.prepaint_index();
4597        let result = f(self);
4598        if result.is_err() {
4599            self.frame_state
4600                .next_frame
4601                .hitboxes
4602                .truncate(index.hitboxes_index);
4603            self.frame_state
4604                .next_frame
4605                .tooltip_requests
4606                .truncate(index.tooltips_index);
4607            self.frame_state
4608                .next_frame
4609                .deferred_draws
4610                .truncate(index.deferred_draws_index);
4611            self.frame_state
4612                .next_frame
4613                .dispatch_tree
4614                .truncate(index.dispatch_tree_index);
4615            self.frame_state
4616                .next_frame
4617                .accessed_element_states
4618                .truncate(index.accessed_element_states_index);
4619            self.core
4620                .text_system
4621                .truncate_layouts(index.line_layout_index);
4622        }
4623        result
4624    }
4625
4626    /// When you call this method during [`Element::prepaint`], containing elements will attempt to
4627    /// scroll to cause the specified bounds to become visible. When they decide to autoscroll, they will call
4628    /// [`Element::prepaint`] again with a new set of bounds. See [`crate::List`] for an example of an element
4629    /// that supports this method being called on the elements it contains. This method should only be
4630    /// called during the prepaint phase of element drawing.
4631    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {
4632        self.core.invalidator.debug_assert_prepaint();
4633        self.frame_state.requested_autoscroll = Some(bounds);
4634    }
4635
4636    /// This method can be called from a containing element such as [`crate::List`] to support the autoscroll behavior
4637    /// described in [`Self::request_autoscroll`].
4638    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {
4639        self.core.invalidator.debug_assert_prepaint();
4640        self.frame_state.requested_autoscroll.take()
4641    }
4642
4643    /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
4644    /// Your view will be re-drawn once the asset has finished loading.
4645    ///
4646    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
4647    /// time.
4648    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
4649        cx.asset_entry::<A>(source).use_by(self.current_view())
4650    }
4651
4652    /// Asynchronously load an asset, if the asset hasn't finished loading or doesn't exist this will return None.
4653    /// Your view will not be re-drawn once the asset has finished loading.
4654    ///
4655    /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
4656    /// time.
4657    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
4658        cx.fetch_asset::<A>(source)
4659    }
4660    /// Obtain the current element offset. This method should only be called during the
4661    /// prepaint phase of element drawing.
4662    pub fn element_offset(&self) -> Point<Pixels> {
4663        self.core.invalidator.debug_assert_prepaint();
4664        self.frame_state
4665            .element_offset_stack
4666            .last()
4667            .copied()
4668            .unwrap_or_default()
4669    }
4670
4671    /// Obtain the current element opacity. This method should only be called during the
4672    /// prepaint phase of element drawing.
4673    #[inline]
4674    pub(crate) fn element_opacity(&self) -> f32 {
4675        self.core.invalidator.debug_assert_paint_or_prepaint();
4676        self.frame_state.element_opacity
4677    }
4678
4679    /// Obtain the current content mask. This method should only be called during element drawing.
4680    pub fn content_mask(&self) -> ContentMask<Pixels> {
4681        self.core.invalidator.debug_assert_paint_or_prepaint();
4682        self.frame_state
4683            .content_mask_stack
4684            .last()
4685            .cloned()
4686            .unwrap_or_else(|| ContentMask {
4687                bounds: Bounds {
4688                    origin: Point::default(),
4689                    size: self.core.viewport_size,
4690                },
4691            })
4692    }
4693
4694    /// Provide elements in the called function with a new namespace in which their identifiers must be unique.
4695    /// This can be used within a custom element to distinguish multiple sets of child elements.
4696    pub fn with_element_namespace<R>(
4697        &mut self,
4698        element_id: impl Into<ElementId>,
4699        f: impl FnOnce(&mut Self) -> R,
4700    ) -> R {
4701        self.frame_state.element_id_stack.push(element_id.into());
4702        let result = f(self);
4703        self.frame_state.element_id_stack.pop();
4704        result
4705    }
4706
4707    /// Use a piece of state that exists as long this element is being rendered in consecutive frames.
4708    pub fn use_keyed_state<S: 'static>(
4709        &mut self,
4710        key: impl Into<ElementId>,
4711        cx: &mut App,
4712        init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
4713    ) -> Entity<S> {
4714        let current_view = self.current_view();
4715        self.with_global_id(key.into(), |global_id, window| {
4716            window.with_element_state(global_id, |state: Option<Entity<S>>, window| {
4717                if let Some(state) = state {
4718                    (state.clone(), state)
4719                } else {
4720                    let new_state = cx.new(|cx| init(window, cx));
4721                    Self::observe_keyed_state(&new_state, current_view, cx);
4722                    (new_state.clone(), new_state)
4723                }
4724            })
4725        })
4726    }
4727
4728    /// Use a piece of state that exists as long this element is being rendered in consecutive frames, without needing to specify a key
4729    ///
4730    /// NOTE: This method uses the location of the caller to generate an ID for this state.
4731    ///       If this is not sufficient to identify your state (e.g. you're rendering a list item),
4732    ///       you can provide a custom ElementID using the `use_keyed_state` method.
4733    #[track_caller]
4734    pub fn use_state<S: 'static>(
4735        &mut self,
4736        cx: &mut App,
4737        init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
4738    ) -> Entity<S> {
4739        self.use_keyed_state(
4740            ElementId::CodeLocation(*core::panic::Location::caller()),
4741            cx,
4742            init,
4743        )
4744    }
4745
4746    /// Updates or initializes state for an element with the given id that lives across multiple
4747    /// frames. If an element with this ID existed in the rendered frame, its state will be passed
4748    /// to the given closure. The state returned by the closure will be stored so it can be referenced
4749    /// when drawing the next frame. This method should only be called as part of element drawing.
4750    #[inline(always)]
4751    pub fn with_element_state<S, R>(
4752        &mut self,
4753        global_id: &GlobalElementId,
4754        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
4755    ) -> R
4756    where
4757        S: 'static,
4758    {
4759        self.core.invalidator.debug_assert_paint_or_prepaint();
4760
4761        let (key, state) = self.take_element_state(global_id, TypeId::of::<S>());
4762
4763        if let Some(any) = state {
4764            let ElementStateBox {
4765                inner,
4766                #[cfg(debug_assertions)]
4767                type_name,
4768            } = any;
4769            // Using the extra inner option to avoid needing to reallocate a new box.
4770            let mut state_box = inner
4771                .downcast::<Option<S>>()
4772                .map_err(|_| {
4773                    #[cfg(debug_assertions)]
4774                    {
4775                        anyhow::anyhow!(
4776                            "invalid element state type for id, requested {:?}, actual: {:?}",
4777                            std::any::type_name::<S>(),
4778                            type_name
4779                        )
4780                    }
4781
4782                    #[cfg(not(debug_assertions))]
4783                    {
4784                        anyhow::anyhow!(
4785                            "invalid element state type for id, requested {:?}",
4786                            std::any::type_name::<S>(),
4787                        )
4788                    }
4789                })
4790                .unwrap();
4791
4792            let state = state_box.take().expect(
4793                "reentrant call to with_element_state for the same state type and element id",
4794            );
4795            let (result, state) = f(Some(state), self);
4796            state_box.replace(state);
4797            self.insert_element_state(
4798                key,
4799                ElementStateBox {
4800                    inner: state_box,
4801                    #[cfg(debug_assertions)]
4802                    type_name,
4803                },
4804            );
4805            result
4806        } else {
4807            let (result, state) = f(None, self);
4808            self.insert_element_state(
4809                key,
4810                ElementStateBox {
4811                    inner: Box::new(Some(state)),
4812                    #[cfg(debug_assertions)]
4813                    type_name: std::any::type_name::<S>(),
4814                },
4815            );
4816            result
4817        }
4818    }
4819
4820    /// A variant of `with_element_state` that allows the element's id to be optional. This is a convenience
4821    /// method for elements where the element id may or may not be assigned. Prefer using `with_element_state`
4822    /// when the element is guaranteed to have an id.
4823    ///
4824    /// The first option means 'no ID provided'
4825    /// The second option means 'not yet initialized'
4826    pub fn with_optional_element_state<S, R>(
4827        &mut self,
4828        global_id: Option<&GlobalElementId>,
4829        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
4830    ) -> R
4831    where
4832        S: 'static,
4833    {
4834        self.core.invalidator.debug_assert_paint_or_prepaint();
4835
4836        if let Some(global_id) = global_id {
4837            self.with_element_state(global_id, |state, cx| {
4838                let (result, state) = f(Some(state), cx);
4839                let state =
4840                    state.expect("you must return some state when you pass some element id");
4841                (result, state)
4842            })
4843        } else {
4844            let (result, state) = f(None, self);
4845            debug_assert!(
4846                state.is_none(),
4847                "you must not return an element state when passing None for the global id"
4848            );
4849            result
4850        }
4851    }
4852
4853    /// Executes the given closure within the context of a tab group.
4854    #[inline]
4855    pub fn with_tab_group<R>(&mut self, index: Option<isize>, f: impl FnOnce(&mut Self) -> R) -> R {
4856        if let Some(index) = index {
4857            self.frame_state.next_frame.tab_stops.begin_group(index);
4858            let result = f(self);
4859            self.frame_state.next_frame.tab_stops.end_group();
4860            result
4861        } else {
4862            f(self)
4863        }
4864    }
4865
4866    /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree
4867    /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,
4868    /// with higher values being drawn on top.
4869    ///
4870    /// When `content_mask` is provided, the deferred element will be clipped to that region during
4871    /// both prepaint and paint. When `None`, no additional clipping is applied.
4872    ///
4873    /// This method should only be called as part of the prepaint phase of element drawing.
4874    pub fn defer_draw(
4875        &mut self,
4876        element: AnyElement,
4877        absolute_offset: Point<Pixels>,
4878        priority: usize,
4879        content_mask: Option<ContentMask<Pixels>>,
4880    ) {
4881        self.core.invalidator.debug_assert_prepaint();
4882        let parent_node = self
4883            .frame_state
4884            .next_frame
4885            .dispatch_tree
4886            .active_node_id()
4887            .unwrap();
4888        self.frame_state
4889            .next_frame
4890            .deferred_draws
4891            .push(DeferredDraw {
4892                current_view: self.current_view(),
4893                parent_node,
4894                element_id_stack: self.frame_state.element_id_stack.clone(),
4895                text_style_stack: self.frame_state.text_style_stack.clone(),
4896                content_mask,
4897                rem_size: self.rem_size(),
4898                priority,
4899                element: Some(element),
4900                absolute_offset,
4901                prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),
4902                paint_range: PaintIndex::default()..PaintIndex::default(),
4903            });
4904    }
4905
4906    /// Creates a new painting layer for the specified bounds. A "layer" is a batch
4907    /// of geometry that are non-overlapping and have the same draw order. This is typically used
4908    /// for performance reasons.
4909    ///
4910    /// This method should only be called as part of the paint phase of element drawing.
4911    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
4912        self.core.invalidator.debug_assert_paint();
4913
4914        let content_mask = self.content_mask();
4915        let clipped_bounds = bounds.intersect(&content_mask.bounds);
4916        if !clipped_bounds.is_empty() {
4917            self.frame_state
4918                .next_frame
4919                .scene
4920                .push_layer(self.cover_bounds(clipped_bounds));
4921        }
4922
4923        let result = f(self);
4924
4925        if !clipped_bounds.is_empty() {
4926            self.frame_state.next_frame.scene.pop_layer();
4927        }
4928
4929        result
4930    }
4931
4932    /// Paint the drop (non-inset) shadows from `shadows` into the scene at the current
4933    /// z-index. Inset shadows are skipped; paint those with [`Self::paint_inset_shadows`]
4934    /// after the element's background so they layer on top of the fill.
4935    ///
4936    /// This method should only be called as part of the paint phase of element drawing.
4937    /// Part of the [authoring surface](crate::_authoring) for custom elements.
4938    pub fn paint_drop_shadows(
4939        &mut self,
4940        bounds: Bounds<Pixels>,
4941        corner_radii: Corners<Pixels>,
4942        shadows: &[BoxShadow],
4943    ) {
4944        self.core.invalidator.debug_assert_paint();
4945
4946        let scale_factor = self.scale_factor();
4947        let content_mask = self.snapped_content_mask();
4948        let opacity = self.element_opacity();
4949        let element_bounds = self.cover_bounds(bounds);
4950        let element_corner_radii = corner_radii.scale(scale_factor);
4951        for shadow in shadows {
4952            if shadow.inset {
4953                continue;
4954            }
4955            let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);
4956            self.frame_state.next_frame.scene.insert_primitive(Shadow {
4957                order: 0,
4958                blur_radius: shadow.blur_radius.scale(scale_factor),
4959                bounds: self.cover_bounds(shadow_bounds),
4960                content_mask,
4961                corner_radii: corner_radii.scale(scale_factor),
4962                color: shadow.color.opacity(opacity),
4963                element_bounds,
4964                element_corner_radii,
4965                inset: 0,
4966                pad: 0,
4967            });
4968        }
4969    }
4970
4971    /// Paint the inset shadows from `shadows` into the scene at the current z-index. Should
4972    /// be called after the element's background so the shadow layers on top of the fill.
4973    /// Drop shadows are skipped; paint those with [`Self::paint_drop_shadows`] before the background.
4974    /// Part of the [authoring surface](crate::_authoring) for custom elements.
4975    pub fn paint_inset_shadows(
4976        &mut self,
4977        bounds: Bounds<Pixels>,
4978        corner_radii: Corners<Pixels>,
4979        shadows: &[BoxShadow],
4980    ) {
4981        self.core.invalidator.debug_assert_paint();
4982
4983        let scale_factor = self.scale_factor();
4984        let content_mask = self.snapped_content_mask();
4985        let opacity = self.element_opacity();
4986        let element_bounds = self.cover_bounds(bounds);
4987        let element_corner_radii = corner_radii.scale(scale_factor);
4988        for shadow in shadows {
4989            if !shadow.inset {
4990                continue;
4991            }
4992            let hole = (bounds + shadow.offset).dilate(-shadow.spread_radius);
4993            // Clamp at zero so a large spread can't produce negative radii, which would
4994            // break the SDF in the shader.
4995            let zero = Pixels::ZERO;
4996            let hole_corner_radii = Corners {
4997                top_left: (corner_radii.top_left - shadow.spread_radius).max(zero),
4998                top_right: (corner_radii.top_right - shadow.spread_radius).max(zero),
4999                bottom_right: (corner_radii.bottom_right - shadow.spread_radius).max(zero),
5000                bottom_left: (corner_radii.bottom_left - shadow.spread_radius).max(zero),
5001            };
5002            self.frame_state.next_frame.scene.insert_primitive(Shadow {
5003                order: 0,
5004                blur_radius: shadow.blur_radius.scale(scale_factor),
5005                bounds: self.cover_bounds(hole),
5006                content_mask,
5007                corner_radii: hole_corner_radii.scale(scale_factor),
5008                color: shadow.color.opacity(opacity),
5009                element_bounds,
5010                element_corner_radii,
5011                inset: 1,
5012                pad: 0,
5013            });
5014        }
5015    }
5016
5017    fn largest_border_interior(quad: &Quad) -> Bounds<ScaledPixels> {
5018        let radii = &quad.corner_radii;
5019        let widths = &quad.border_widths;
5020        let edge_radii = Edges {
5021            top: radii.top_left.max(radii.top_right),
5022            right: radii.top_right.max(radii.bottom_right),
5023            bottom: radii.bottom_left.max(radii.bottom_right),
5024            left: radii.top_left.max(radii.bottom_left),
5025        };
5026
5027        let antialias_inset = point(ScaledPixels(1.0), ScaledPixels(1.0));
5028        let inset_bounds = |top_left_inset, bottom_right_inset| {
5029            Bounds::from_corners(
5030                quad.bounds.origin + top_left_inset + antialias_inset,
5031                quad.bounds.bottom_right() - bottom_right_inset - antialias_inset,
5032            )
5033        };
5034
5035        // Rounded corners need only be excluded on one axis. Either candidate
5036        // is empty of border pixels, so use the larger interior.
5037        let horizontal_band = inset_bounds(
5038            point(widths.left, widths.top.max(edge_radii.top)),
5039            point(widths.right, widths.bottom.max(edge_radii.bottom)),
5040        );
5041        let vertical_band = inset_bounds(
5042            point(widths.left.max(edge_radii.left), widths.top),
5043            point(widths.right.max(edge_radii.right), widths.bottom),
5044        );
5045
5046        let area = |bounds: &Bounds<ScaledPixels>| {
5047            bounds.size.width.0.max(0.) * bounds.size.height.0.max(0.)
5048        };
5049        if area(&horizontal_band) >= area(&vertical_band) {
5050            horizontal_band
5051        } else {
5052            vertical_band
5053        }
5054    }
5055
5056    /// Paint a texture that was produced outside GPUI, on this window's renderer's own device.
5057    ///
5058    /// This method should only be called as part of the paint phase of element drawing.
5059    /// It is an error to hand over a texture from another device: the renderer's binding will
5060    /// reject it.
5061    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5062    pub(crate) fn paint_imported_texture(
5063        &mut self,
5064        handle: ImportedTextureHandle,
5065        bounds: Bounds<Pixels>,
5066        corner_radii: Corners<Pixels>,
5067        opacity: f32,
5068        flip_v: bool,
5069    ) {
5070        self.core.invalidator.debug_assert_paint();
5071
5072        let primitive = CustomRenderPrimitive::Texture {
5073            order: 0,
5074            handle,
5075            bounds: self.snap_bounds(bounds),
5076            content_mask: self.snapped_content_mask(),
5077            radii: corner_radii.scale(self.scale_factor()),
5078            opacity: opacity * self.element_opacity(),
5079            flip_v,
5080        };
5081        self.frame_state
5082            .next_frame
5083            .scene
5084            .insert_primitive(primitive);
5085    }
5086
5087    /// Paint one or more quads into the scene for the next frame at the current stacking context.
5088    /// Quads are colored rectangular regions with an optional background, border, and corner radius.
5089    /// see [`fill`], [`outline`], and [`quad`] to construct this type.
5090    ///
5091    /// This method should only be called as part of the paint phase of element drawing.
5092    ///
5093    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners
5094    /// where the circular arcs meet. This will not display well when combined with dashed borders.
5095    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.
5096    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5097    pub fn paint_quad(&mut self, quad: PaintQuad) {
5098        self.core.invalidator.debug_assert_paint();
5099
5100        let opacity = self.element_opacity();
5101        let snapped_bounds = self.snap_bounds(quad.bounds);
5102        let snapped_border_widths = self.snap_border_widths(quad.border_widths);
5103        let quad = Quad {
5104            order: 0,
5105            bounds: snapped_bounds,
5106            content_mask: self.snapped_content_mask(),
5107            background: quad.background.opacity(opacity),
5108            border_color: quad.border_color.opacity(opacity),
5109            corner_radii: quad.corner_radii.scale(self.scale_factor()),
5110            border_widths: snapped_border_widths,
5111            border_style: quad.border_style,
5112        };
5113
5114        if !quad.background.is_transparent() {
5115            self.frame_state.next_frame.scene.insert_primitive(quad);
5116            return;
5117        }
5118
5119        // Splitting a border-only quad around its empty interior avoids shading
5120        // every transparent pixel inside large outlines.
5121        let outer_bounds = quad.bounds;
5122        let inner_bounds = Self::largest_border_interior(&quad);
5123
5124        if inner_bounds.is_empty() {
5125            self.frame_state.next_frame.scene.insert_primitive(quad);
5126            return;
5127        }
5128
5129        let strips = [
5130            // Top
5131            Bounds::from_corners(
5132                outer_bounds.origin,
5133                point(outer_bounds.right(), inner_bounds.top()),
5134            ),
5135            // Bottom
5136            Bounds::from_corners(
5137                point(outer_bounds.left(), inner_bounds.bottom()),
5138                outer_bounds.bottom_right(),
5139            ),
5140            // Left
5141            Bounds::from_corners(
5142                point(outer_bounds.left(), inner_bounds.top()),
5143                inner_bounds.bottom_left(),
5144            ),
5145            // Right
5146            Bounds::from_corners(
5147                inner_bounds.top_right(),
5148                point(outer_bounds.right(), inner_bounds.bottom()),
5149            ),
5150        ];
5151
5152        for strip in strips {
5153            let content_mask_bounds = quad.content_mask.bounds.intersect(&strip);
5154            if !content_mask_bounds.is_empty() {
5155                self.frame_state.next_frame.scene.insert_primitive(Quad {
5156                    content_mask: ContentMask {
5157                        bounds: content_mask_bounds,
5158                    },
5159                    ..quad
5160                });
5161            }
5162        }
5163    }
5164
5165    /// Paint the given `Path` into the scene for the next frame at the current z-index.
5166    ///
5167    /// This method should only be called as part of the paint phase of element drawing.
5168    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5169    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {
5170        self.core.invalidator.debug_assert_paint();
5171
5172        let scale_factor = self.scale_factor();
5173        let content_mask = self.content_mask();
5174        let opacity = self.element_opacity();
5175        path.content_mask = content_mask;
5176        let color: Background = color.into();
5177        path.color = color.opacity(opacity);
5178        self.frame_state
5179            .next_frame
5180            .scene
5181            .insert_primitive(path.scale(scale_factor));
5182    }
5183
5184    /// Paint an underline into the scene for the next frame at the current z-index.
5185    ///
5186    /// This method should only be called as part of the paint phase of element drawing.
5187    pub fn paint_underline(
5188        &mut self,
5189        origin: Point<Pixels>,
5190        width: Pixels,
5191        style: &UnderlineStyle,
5192    ) {
5193        self.core.invalidator.debug_assert_paint();
5194        let underline = self.underline(origin, width, style);
5195        self.frame_state
5196            .next_frame
5197            .scene
5198            .insert_primitive(underline);
5199    }
5200
5201    /// Paint a strikethrough into the scene for the next frame at the current z-index.
5202    ///
5203    /// This method should only be called as part of the paint phase of element drawing.
5204    pub fn paint_strikethrough(
5205        &mut self,
5206        origin: Point<Pixels>,
5207        width: Pixels,
5208        style: &StrikethroughStyle,
5209    ) {
5210        self.core.invalidator.debug_assert_paint();
5211
5212        let scale_factor = self.scale_factor();
5213        let height = style.thickness;
5214        let bounds = Bounds {
5215            origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
5216            size: size(self.snap_stroke(width), self.snap_stroke(height)),
5217        };
5218        let opacity = self.element_opacity();
5219
5220        self.frame_state
5221            .next_frame
5222            .scene
5223            .insert_primitive(Underline {
5224                order: 0,
5225                pad: 0,
5226                bounds,
5227                content_mask: self.snapped_content_mask(),
5228                thickness: self.snap_stroke(style.thickness),
5229                color: style.color.unwrap_or_default().opacity(opacity),
5230                wavy: false.into(),
5231            });
5232    }
5233
5234    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
5235    ///
5236    /// The y component of the origin is the baseline of the glyph.
5237    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
5238    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
5239    /// This method is only useful if you need to paint a single glyph that has already been shaped.
5240    ///
5241    /// This method should only be called as part of the paint phase of element drawing.
5242    pub fn paint_glyph(
5243        &mut self,
5244        origin: Point<Pixels>,
5245        font_id: FontId,
5246        glyph_id: GlyphId,
5247        font_size: Pixels,
5248        color: Hsla,
5249    ) -> Result<()> {
5250        self.core.invalidator.debug_assert_paint();
5251
5252        let element_opacity = self.element_opacity();
5253        let scale_factor = self.scale_factor();
5254        let glyph_origin = origin.scale(scale_factor);
5255
5256        let quantized_origin = Point::new(
5257            round_half_toward_zero(glyph_origin.x.0 * SUBPIXEL_VARIANTS_X as f32)
5258                / SUBPIXEL_VARIANTS_X as f32,
5259            round_half_toward_zero(glyph_origin.y.0 * SUBPIXEL_VARIANTS_Y as f32)
5260                / SUBPIXEL_VARIANTS_Y as f32,
5261        );
5262        let subpixel_variant = Point::new(
5263            (quantized_origin.x.fract() * SUBPIXEL_VARIANTS_X as f32) as u8,
5264            (quantized_origin.y.fract() * SUBPIXEL_VARIANTS_Y as f32) as u8,
5265        );
5266        let integer_origin = quantized_origin.map(|c| ScaledPixels(c.trunc()));
5267        let subpixel_rendering = self.should_use_subpixel_rendering(font_id, font_size);
5268        let dilation = self.text_system().glyph_dilation_for_color(color);
5269        let params = RenderGlyphParams {
5270            font_id,
5271            glyph_id,
5272            font_size,
5273            subpixel_variant,
5274            scale_factor,
5275            is_emoji: false,
5276            subpixel_rendering,
5277            dilation,
5278        };
5279
5280        let raster_bounds = self.text_system().raster_bounds(&params)?;
5281        if !raster_bounds.is_zero() {
5282            let tile = self
5283                .core
5284                .sprite_atlas
5285                .get_or_insert_with(params.clone().into(), &mut || {
5286                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;
5287                    Ok(Some((size, Cow::Owned(bytes))))
5288                })?
5289                .expect("Callback above only errors or returns Some");
5290            let bounds = Bounds {
5291                origin: integer_origin + raster_bounds.origin.map(Into::into),
5292                size: tile.bounds.size.map(Into::into),
5293            };
5294            let content_mask = self.snapped_content_mask();
5295
5296            if subpixel_rendering {
5297                self.frame_state
5298                    .next_frame
5299                    .scene
5300                    .insert_primitive(SubpixelSprite {
5301                        order: 0,
5302                        pad: 0,
5303                        bounds,
5304                        content_mask,
5305                        color: color.opacity(element_opacity),
5306                        tile,
5307                        transformation: TransformationMatrix::unit(),
5308                    });
5309            } else {
5310                self.frame_state
5311                    .next_frame
5312                    .scene
5313                    .insert_primitive(MonochromeSprite {
5314                        order: 0,
5315                        pad: 0,
5316                        bounds,
5317                        content_mask,
5318                        color: color.opacity(element_opacity),
5319                        tile,
5320                        transformation: TransformationMatrix::unit(),
5321                    });
5322            }
5323        }
5324        Ok(())
5325    }
5326
5327    fn should_use_subpixel_rendering(&self, font_id: FontId, font_size: Pixels) -> bool {
5328        if self.core.platform_window.background_appearance() != WindowBackgroundAppearance::Opaque {
5329            return false;
5330        }
5331
5332        if !self.core.platform_window.is_subpixel_rendering_supported() {
5333            return false;
5334        }
5335
5336        let mode = match self.core.text_rendering_mode.get() {
5337            TextRenderingMode::PlatformDefault => self
5338                .text_system()
5339                .recommended_rendering_mode(font_id, font_size),
5340            mode => mode,
5341        };
5342
5343        mode == TextRenderingMode::Subpixel
5344    }
5345
5346    /// Paints an emoji glyph into the scene for the next frame at the current z-index.
5347    ///
5348    /// The y component of the origin is the baseline of the glyph.
5349    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
5350    /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
5351    /// This method is only useful if you need to paint a single emoji that has already been shaped.
5352    ///
5353    /// This method should only be called as part of the paint phase of element drawing.
5354    pub fn paint_emoji(
5355        &mut self,
5356        origin: Point<Pixels>,
5357        font_id: FontId,
5358        glyph_id: GlyphId,
5359        font_size: Pixels,
5360    ) -> Result<()> {
5361        self.core.invalidator.debug_assert_paint();
5362
5363        let scale_factor = self.scale_factor();
5364        let glyph_origin = origin.scale(scale_factor);
5365        let integer_origin = glyph_origin.map(|c| ScaledPixels(round_half_toward_zero(c.0)));
5366        let params = RenderGlyphParams {
5367            font_id,
5368            glyph_id,
5369            font_size,
5370            subpixel_variant: Default::default(),
5371            scale_factor,
5372            is_emoji: true,
5373            subpixel_rendering: false,
5374            dilation: 0,
5375        };
5376
5377        let raster_bounds = self.text_system().raster_bounds(&params)?;
5378        if !raster_bounds.is_zero() {
5379            let tile = self
5380                .core
5381                .sprite_atlas
5382                .get_or_insert_with(params.clone().into(), &mut || {
5383                    let (size, bytes) = self.text_system().rasterize_glyph(&params)?;
5384                    Ok(Some((size, Cow::Owned(bytes))))
5385                })?
5386                .expect("Callback above only errors or returns Some");
5387
5388            let bounds = Bounds {
5389                origin: integer_origin + raster_bounds.origin.map(Into::into),
5390                size: tile.bounds.size.map(Into::into),
5391            };
5392            let content_mask = self.snapped_content_mask();
5393            let opacity = self.element_opacity();
5394
5395            self.frame_state
5396                .next_frame
5397                .scene
5398                .insert_primitive(PolychromeSprite {
5399                    order: 0,
5400                    pad: 0,
5401                    grayscale: false.into(),
5402                    bounds,
5403                    corner_radii: Default::default(),
5404                    content_mask,
5405                    tile,
5406                    opacity,
5407                });
5408        }
5409        Ok(())
5410    }
5411
5412    /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
5413    ///
5414    /// This method should only be called as part of the paint phase of element drawing.
5415    pub fn paint_svg(
5416        &mut self,
5417        bounds: Bounds<Pixels>,
5418        path: SharedString,
5419        mut data: Option<&[u8]>,
5420        transformation: TransformationMatrix,
5421        color: Hsla,
5422        cx: &App,
5423    ) -> Result<()> {
5424        self.core.invalidator.debug_assert_paint();
5425
5426        let element_opacity = self.element_opacity();
5427        let bounds = self.snap_bounds(bounds);
5428
5429        let params = RenderSvgParams {
5430            path,
5431            size: bounds.size.map(|pixels| {
5432                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)
5433            }),
5434        };
5435
5436        let Some(tile) =
5437            self.core
5438                .sprite_atlas
5439                .get_or_insert_with(params.clone().into(), &mut || {
5440                    let Some((size, bytes)) = cx.svg_renderer.render_alpha_mask(&params, data)?
5441                    else {
5442                        return Ok(None);
5443                    };
5444                    Ok(Some((size, Cow::Owned(bytes))))
5445                })?
5446        else {
5447            return Ok(());
5448        };
5449        let content_mask = self.snapped_content_mask();
5450        let svg_bounds = Bounds {
5451            origin: bounds.center()
5452                - Point::new(
5453                    ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
5454                    ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
5455                ),
5456            size: tile
5457                .bounds
5458                .size
5459                .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)),
5460        };
5461        let final_bounds = svg_bounds
5462            .map_origin(|value| ScaledPixels(round_half_toward_zero(value.0)))
5463            .map_size(|size| size.ceil());
5464
5465        self.frame_state
5466            .next_frame
5467            .scene
5468            .insert_primitive(MonochromeSprite {
5469                order: 0,
5470                pad: 0,
5471                bounds: final_bounds,
5472                content_mask,
5473                color: color.opacity(element_opacity),
5474                tile,
5475                transformation,
5476            });
5477
5478        Ok(())
5479    }
5480
5481    /// Paint an image into the scene for the next frame at the current z-index.
5482    /// This method will panic if the frame_index is not valid
5483    ///
5484    /// This method should only be called as part of the paint phase of element drawing.
5485    /// Paint an image into `bounds`, positioning and scaling it according to `image_bounds`.
5486    ///
5487    /// The visible region rendered is `bounds.intersect(&image_bounds)`, with `corner_radii`
5488    /// applied to `bounds`.
5489    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5490    pub fn paint_image(
5491        &mut self,
5492        bounds: Bounds<Pixels>,
5493        image_bounds: Bounds<Pixels>,
5494        corner_radii: Corners<Pixels>,
5495        data: Arc<RenderImage>,
5496        frame_index: usize,
5497        grayscale: bool,
5498    ) -> Result<()> {
5499        self.core.invalidator.debug_assert_paint();
5500
5501        let visible_bounds = bounds.intersect(&image_bounds);
5502        if visible_bounds.size.width <= Pixels::ZERO || visible_bounds.size.height <= Pixels::ZERO {
5503            return Ok(());
5504        }
5505        if image_bounds.size.width <= Pixels::ZERO || image_bounds.size.height <= Pixels::ZERO {
5506            return Ok(());
5507        }
5508
5509        let params = RenderImageParams {
5510            image_id: data.id,
5511            frame_index,
5512        };
5513
5514        let tile = self
5515            .core
5516            .sprite_atlas
5517            .get_or_insert_with(params.into(), &mut || {
5518                Ok(Some((
5519                    data.size(frame_index),
5520                    Cow::Borrowed(
5521                        data.as_bytes(frame_index)
5522                            .expect("It's the caller's job to pass a valid frame index"),
5523                    ),
5524                )))
5525            })?
5526            .expect("Callback above only returns Some");
5527
5528        let visible_bounds_snapped = self.snap_bounds(visible_bounds);
5529
5530        let sub_tile = if visible_bounds == image_bounds {
5531            tile
5532        } else {
5533            let x_offset_ratio =
5534                (visible_bounds.origin.x - image_bounds.origin.x) / image_bounds.size.width;
5535            let y_offset_ratio =
5536                (visible_bounds.origin.y - image_bounds.origin.y) / image_bounds.size.height;
5537            let width_ratio = visible_bounds.size.width / image_bounds.size.width;
5538            let height_ratio = visible_bounds.size.height / image_bounds.size.height;
5539
5540            let tile_origin_x = tile.bounds.origin.x.0;
5541            let tile_origin_y = tile.bounds.origin.y.0;
5542            let tile_width = tile.bounds.size.width.0;
5543            let tile_height = tile.bounds.size.height.0;
5544
5545            let sub_origin_x = tile_origin_x + (x_offset_ratio * tile_width as f32).round() as i32;
5546            let sub_origin_y = tile_origin_y + (y_offset_ratio * tile_height as f32).round() as i32;
5547            let sub_width = (width_ratio * tile_width as f32).round() as i32;
5548            let sub_height = (height_ratio * tile_height as f32).round() as i32;
5549
5550            let max_x = tile_origin_x + tile_width;
5551            let max_y = tile_origin_y + tile_height;
5552
5553            let clamped_origin_x = sub_origin_x.clamp(tile_origin_x, max_x);
5554            let clamped_origin_y = sub_origin_y.clamp(tile_origin_y, max_y);
5555            let clamped_width = sub_width.min(max_x - clamped_origin_x).max(0);
5556            let clamped_height = sub_height.min(max_y - clamped_origin_y).max(0);
5557
5558            AtlasTile {
5559                bounds: Bounds {
5560                    origin: point(
5561                        DevicePixels(clamped_origin_x),
5562                        DevicePixels(clamped_origin_y),
5563                    ),
5564                    size: size(DevicePixels(clamped_width), DevicePixels(clamped_height)),
5565                },
5566                ..tile
5567            }
5568        };
5569
5570        let content_mask = self.snapped_content_mask();
5571        let corner_radii = corner_radii
5572            .clamp_radii_for_quad_size(visible_bounds.size)
5573            .scale(self.scale_factor());
5574        let opacity = self.element_opacity();
5575
5576        self.frame_state
5577            .next_frame
5578            .scene
5579            .insert_primitive(PolychromeSprite {
5580                order: 0,
5581                pad: 0,
5582                grayscale: grayscale.into(),
5583                bounds: visible_bounds_snapped,
5584                content_mask,
5585                corner_radii,
5586                tile: sub_tile,
5587                opacity,
5588            });
5589        Ok(())
5590    }
5591
5592    /// Removes an image from the sprite atlas.
5593    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {
5594        for frame_index in 0..data.frame_count() {
5595            let params = RenderImageParams {
5596                image_id: data.id,
5597                frame_index,
5598            };
5599
5600            self.core.sprite_atlas.remove(&params.clone().into());
5601        }
5602
5603        Ok(())
5604    }
5605
5606    /// Returns whether every frame of an image is present in the sprite atlas.
5607    #[cfg(any(test, feature = "test-support"))]
5608    pub fn has_image_atlas_entry(&self, data: &RenderImage) -> bool {
5609        data.frame_count() > 0
5610            && (0..data.frame_count()).all(|frame_index| {
5611                self.core.sprite_atlas.contains(
5612                    &RenderImageParams {
5613                        image_id: data.id,
5614                        frame_index,
5615                    }
5616                    .into(),
5617                )
5618            })
5619    }
5620
5621    /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
5622    /// layout is being requested, along with the layout ids of any children. This method is called during
5623    /// calls to the [`Element::request_layout`] trait method and enables any element to participate in layout.
5624    ///
5625    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.
5626    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5627    #[must_use]
5628    pub fn request_layout(
5629        &mut self,
5630        style: Style,
5631        children: impl IntoIterator<Item = LayoutId>,
5632        cx: &mut App,
5633    ) -> LayoutId {
5634        self.core.invalidator.debug_assert_prepaint();
5635
5636        cx.layout_id_buffer.clear();
5637        cx.layout_id_buffer.extend(children);
5638        let rem_size = self.rem_size();
5639        let scale_factor = self.scale_factor();
5640        let engine_style = to_engine_layout_style(&style);
5641
5642        self.frame_state.layout_session.request_layout(
5643            &engine_style,
5644            rem_size,
5645            scale_factor,
5646            &cx.layout_id_buffer,
5647        )
5648    }
5649
5650    /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
5651    /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
5652    /// determine the element's size. One place this is used internally is when measuring text.
5653    ///
5654    /// The given closure is invoked at layout time with the known dimensions and available space and
5655    /// returns a `Size`.
5656    ///
5657    /// This method should only be called as part of the request_layout or prepaint phase of element drawing.
5658    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5659    pub fn request_measured_layout<F>(&mut self, style: Style, measure: F) -> LayoutId
5660    where
5661        F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
5662            + 'static,
5663    {
5664        self.core.invalidator.debug_assert_prepaint();
5665
5666        let rem_size = self.rem_size();
5667        let scale_factor = self.scale_factor();
5668        let engine_style = to_engine_layout_style(&style);
5669        let measure = move |known_dimensions, available_space, context: &mut dyn MeasureContext| {
5670            let MeasureHandles { window, app } = context.handles();
5671            let (core, frame_state) = window;
5672            let core = core
5673                .downcast_mut::<WindowHostCore>()
5674                .expect("measure context window half should be a window's core");
5675            let frame_state = frame_state
5676                .downcast_mut::<WindowFrameState>()
5677                .expect("measure context window half should be a window's frame state");
5678            let cx = app
5679                .downcast_mut::<App>()
5680                .expect("measure context app should be an App");
5681            measure(
5682                known_dimensions,
5683                available_space,
5684                &mut Window { core, frame_state },
5685                cx,
5686            )
5687        };
5688        self.frame_state.layout_session.request_measured_layout(
5689            &engine_style,
5690            rem_size,
5691            scale_factor,
5692            Box::new(measure),
5693        )
5694    }
5695
5696    /// Compute the layout for the given id within the given available space.
5697    /// This method is called for its side effect, typically by the framework prior to painting.
5698    /// After calling it, you can request the bounds of the given layout node id or any descendant.
5699    ///
5700    /// This method should only be called as part of the prepaint phase of element drawing.
5701    pub(crate) fn compute_layout(
5702        &mut self,
5703        layout_id: LayoutId,
5704        available_space: Size<AvailableSpace>,
5705        cx: &mut App,
5706    ) {
5707        self.core.invalidator.debug_assert_prepaint();
5708
5709        let scale_factor = self.scale_factor();
5710        let layout_session = self.frame_state.layout_session.clone();
5711        let core = &mut *self.core;
5712        let frame_state = &mut *self.frame_state;
5713        layout_session.compute_layout(
5714            layout_id,
5715            available_space,
5716            scale_factor,
5717            &mut WindowMeasureContext {
5718                core,
5719                frame_state,
5720                cx,
5721            },
5722        );
5723    }
5724
5725    /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by
5726    /// GPUI itself automatically in order to pass your element its `Bounds` automatically.
5727    ///
5728    /// This method should only be called as part of element drawing.
5729    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5730    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
5731        self.core.invalidator.debug_assert_prepaint();
5732
5733        let scale_factor = self.scale_factor();
5734        let mut bounds = self
5735            .frame_state
5736            .layout_session
5737            .layout_bounds(layout_id, scale_factor)
5738            .map(Into::into);
5739        let snapped_offset = self.pixel_snap_point(self.element_offset());
5740        bounds.origin += snapped_offset;
5741        bounds
5742    }
5743
5744    /// This method should be called during `prepaint`. You can use
5745    /// the returned [Hitbox] during `paint` or in an event handler
5746    /// to determine whether the inserted hitbox was the topmost.
5747    ///
5748    /// This method should only be called as part of the prepaint phase of element drawing.
5749    /// Part of the [authoring surface](crate::_authoring) for custom elements.
5750    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, behavior: HitboxBehavior) -> Hitbox {
5751        self.insert_hitbox_with_filter(bounds, behavior, None)
5752    }
5753
5754    /// Like [`insert_hitbox`](Self::insert_hitbox), but the hitbox is only hit where `filter` allows
5755    /// the position — everywhere else hit-testing skips it, so the pointer reaches what is drawn
5756    /// behind it. Part of the [authoring surface](crate::_authoring) for a custom element whose
5757    /// content does not fill its bounds (a transparent `gpu_canvas`, say).
5758    pub fn insert_hitbox_with_filter(
5759        &mut self,
5760        bounds: Bounds<Pixels>,
5761        behavior: HitboxBehavior,
5762        filter: Option<HitboxFilter>,
5763    ) -> Hitbox {
5764        self.core.invalidator.debug_assert_prepaint();
5765
5766        let content_mask = self.content_mask();
5767        let mut id = self.frame_state.next_hitbox_id;
5768        self.frame_state.next_hitbox_id = self.frame_state.next_hitbox_id.next();
5769        let hitbox = Hitbox {
5770            id,
5771            bounds,
5772            content_mask,
5773            behavior,
5774        };
5775        self.frame_state.next_frame.hitboxes.push(hitbox.clone());
5776        self.frame_state.next_frame.hitbox_filters.push(filter);
5777        hitbox
5778    }
5779
5780    /// Set a hitbox which will act as a control area of the platform window.
5781    ///
5782    /// This method should only be called as part of the paint phase of element drawing.
5783    pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) {
5784        self.core.invalidator.debug_assert_paint();
5785        self.frame_state
5786            .next_frame
5787            .window_control_hitboxes
5788            .push((area, hitbox));
5789    }
5790
5791    /// Sets the key context for the current element. This context will be used to translate
5792    /// keybindings into actions.
5793    ///
5794    /// This method should only be called as part of the paint phase of element drawing.
5795    pub fn set_key_context(&mut self, context: KeyContext) {
5796        self.core.invalidator.debug_assert_paint();
5797        self.frame_state
5798            .next_frame
5799            .dispatch_tree
5800            .set_key_context(context);
5801    }
5802
5803    /// Sets the focus handle for the current element. This handle will be used to manage focus state
5804    /// and keyboard event dispatch for the element.
5805    ///
5806    /// This method should only be called as part of the prepaint phase of element drawing.
5807    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {
5808        self.core.invalidator.debug_assert_prepaint();
5809        if focus_handle.is_focused(self) {
5810            self.frame_state.next_frame.focus = Some(focus_handle.id);
5811        }
5812        self.frame_state
5813            .next_frame
5814            .dispatch_tree
5815            .set_focus_id(focus_handle.id);
5816    }
5817
5818    /// Sets the view id for the current element, which will be used to manage view caching.
5819    ///
5820    /// This method should only be called as part of element prepaint. We plan on removing this
5821    /// method eventually when we solve some issues that require us to construct editor elements
5822    /// directly instead of always using editors via views.
5823    pub fn set_view_id(&mut self, view_id: EntityId) {
5824        self.core.invalidator.debug_assert_prepaint();
5825        self.frame_state
5826            .next_frame
5827            .dispatch_tree
5828            .set_view_id(view_id);
5829    }
5830
5831    /// Get the entity ID for the currently rendering view
5832    pub fn current_view(&self) -> EntityId {
5833        self.core.invalidator.debug_assert_paint_or_prepaint();
5834        self.frame_state
5835            .rendered_entity_stack
5836            .last()
5837            .copied()
5838            .unwrap()
5839    }
5840
5841    #[inline]
5842    pub(crate) fn with_rendered_view<R>(
5843        &mut self,
5844        id: EntityId,
5845        f: impl FnOnce(&mut Self) -> R,
5846    ) -> R {
5847        self.frame_state.rendered_entity_stack.push(id);
5848        let result = f(self);
5849        self.frame_state.rendered_entity_stack.pop();
5850        result
5851    }
5852
5853    /// Executes the provided function with the specified image cache.
5854    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R
5855    where
5856        F: FnOnce(&mut Self) -> R,
5857    {
5858        if let Some(image_cache) = image_cache {
5859            self.frame_state.image_cache_stack.push(image_cache);
5860            let result = f(self);
5861            self.frame_state.image_cache_stack.pop();
5862            result
5863        } else {
5864            f(self)
5865        }
5866    }
5867
5868    /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
5869    /// platform to receive textual input with proper integration with concerns such
5870    /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
5871    /// rendered.
5872    ///
5873    /// This method should only be called as part of the paint phase of element drawing.
5874    ///
5875    /// [element_input_handler]: crate::ElementInputHandler
5876    pub fn handle_input(
5877        &mut self,
5878        focus_handle: &FocusHandle,
5879        input_handler: impl InputHandler,
5880        cx: &App,
5881    ) {
5882        self.core.invalidator.debug_assert_paint();
5883
5884        if focus_handle.is_focused(self) {
5885            let cx = self.to_async(cx);
5886            self.frame_state
5887                .next_frame
5888                .input_handlers
5889                .push(Some(new_platform_input_handler(
5890                    cx,
5891                    Box::new(input_handler),
5892                )));
5893        }
5894    }
5895
5896    /// Forwards the focused input handler's [`TextInputConfiguration`] to the
5897    /// platform window when it differs from the last forwarded value. With no
5898    /// input handler the default configuration applies, so a field's
5899    /// preferences don't outlive its focus.
5900    fn apply_text_input_configuration(&mut self, cx: &mut App) {
5901        let configuration = match self.core.platform_window.take_input_handler() {
5902            Some(mut input_handler) => {
5903                let configuration = input_handler.text_input_configuration(self, cx);
5904                self.core.platform_window.set_input_handler(input_handler);
5905                configuration
5906            }
5907            None => TextInputConfiguration::default(),
5908        };
5909        if self.core.last_text_input_configuration.as_ref() != Some(&configuration) {
5910            self.core
5911                .platform_window
5912                .set_text_input_configuration(configuration.clone());
5913            self.core.last_text_input_configuration = Some(configuration);
5914        }
5915    }
5916
5917    /// Register a mouse event listener on the window for the next frame. The type of event
5918    /// is determined by the first parameter of the given listener. When the next frame is rendered
5919    /// the listener will be cleared.
5920    ///
5921    /// This method should only be called as part of the paint phase of element drawing.
5922    pub fn on_mouse_event<Event: MouseEvent>(
5923        &mut self,
5924        mut listener: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
5925    ) {
5926        self.core.invalidator.debug_assert_paint();
5927
5928        self.frame_state
5929            .next_frame
5930            .mouse_listeners
5931            .push(Some(Box::new(
5932                move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {
5933                    if let Some(event) = event.downcast_ref() {
5934                        listener(event, phase, window, cx)
5935                    }
5936                },
5937            )));
5938    }
5939
5940    /// Register a key event listener on this node for the next frame. The type of event
5941    /// is determined by the first parameter of the given listener. When the next frame is rendered
5942    /// the listener will be cleared.
5943    ///
5944    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
5945    /// a specific need to register a listener yourself.
5946    ///
5947    /// This method should only be called as part of the paint phase of element drawing.
5948    pub fn on_key_event<Event: KeyEvent>(
5949        &mut self,
5950        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
5951    ) {
5952        self.core.invalidator.debug_assert_paint();
5953
5954        self.frame_state
5955            .next_frame
5956            .dispatch_tree
5957            .on_key_event(Rc::new(
5958                move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {
5959                    if let Some(event) = event.downcast_ref::<Event>() {
5960                        listener(event, phase, window, cx)
5961                    }
5962                },
5963            ));
5964    }
5965
5966    /// Register a modifiers changed event listener on the window for the next frame.
5967    ///
5968    /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
5969    /// a specific need to register a global listener.
5970    ///
5971    /// This method should only be called as part of the paint phase of element drawing.
5972    pub fn on_modifiers_changed(
5973        &mut self,
5974        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
5975    ) {
5976        self.core.invalidator.debug_assert_paint();
5977
5978        self.frame_state
5979            .next_frame
5980            .dispatch_tree
5981            .on_modifiers_changed(Rc::new(
5982                move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {
5983                    listener(event, window, cx)
5984                },
5985            ));
5986    }
5987
5988    /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
5989    /// This does not fire if the given focus handle - or one of its descendants - was previously focused.
5990    /// Returns a subscription and persists until the subscription is dropped.
5991    pub fn on_focus_in(
5992        &mut self,
5993        handle: &FocusHandle,
5994        cx: &mut App,
5995        mut listener: impl FnMut(&mut Window, &mut App) + 'static,
5996    ) -> Subscription {
5997        let focus_id = handle.id;
5998        let (subscription, activate) =
5999            self.new_focus_listener(Box::new(move |event, window, cx| {
6000                if event.is_focus_in(focus_id) {
6001                    listener(window, cx);
6002                }
6003                true
6004            }));
6005        cx.defer(move |_| activate());
6006        subscription
6007    }
6008
6009    /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
6010    /// Returns a subscription and persists until the subscription is dropped.
6011    pub fn on_focus_out(
6012        &mut self,
6013        handle: &FocusHandle,
6014        cx: &mut App,
6015        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,
6016    ) -> Subscription {
6017        let focus_id = handle.id;
6018        let (subscription, activate) =
6019            self.new_focus_listener(Box::new(move |event, window, cx| {
6020                if let Some(blurred_id) = event.previous_focus_path.last().copied()
6021                    && event.is_focus_out(focus_id)
6022                {
6023                    let event = FocusOutEvent {
6024                        blurred: WeakFocusHandle {
6025                            id: blurred_id,
6026                            handles: Arc::downgrade(&cx.focus_handles),
6027                        },
6028                    };
6029                    listener(event, window, cx)
6030                }
6031                true
6032            }));
6033        cx.defer(move |_| activate());
6034        subscription
6035    }
6036
6037    fn reset_cursor_style(&self, cx: &mut App) {
6038        // Set the cursor only if we're the active window.
6039        if self.is_window_hovered() {
6040            let style = self
6041                .frame_state
6042                .rendered_frame
6043                .cursor_style(self)
6044                .unwrap_or(CursorStyle::Arrow);
6045            cx.platform.set_cursor_style(style);
6046        }
6047    }
6048
6049    /// Dispatch a given keystroke as though the user had typed it.
6050    /// You can create a keystroke with Keystroke::parse("").
6051    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {
6052        let keystroke = keystroke.with_simulated_ime();
6053        let result = self.dispatch_event(
6054            PlatformInput::KeyDown(KeyDownEvent {
6055                keystroke: keystroke.clone(),
6056                is_held: false,
6057                prefer_character_input: false,
6058            }),
6059            cx,
6060        );
6061        if !result.propagate {
6062            return true;
6063        }
6064
6065        if let Some(input) = keystroke.key_char
6066            && let Some(mut input_handler) = self.core.platform_window.take_input_handler()
6067        {
6068            input_handler.dispatch_input(&input, self, cx);
6069            self.core.platform_window.set_input_handler(input_handler);
6070            return true;
6071        }
6072
6073        false
6074    }
6075
6076    /// Return a key binding string for an action, to display in the UI. Uses the highest precedence
6077    /// binding for the action (last binding added to the keymap).
6078    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {
6079        self.highest_precedence_binding_for_action(action)
6080            .map(|binding| {
6081                binding
6082                    .keystrokes()
6083                    .iter()
6084                    .map(ToString::to_string)
6085                    .collect::<Vec<_>>()
6086                    .join(" ")
6087            })
6088            .unwrap_or_else(|| action.name().to_string())
6089    }
6090
6091    /// Dispatch a mouse, keyboard, or touch event on the window.
6092    #[profiling::function]
6093    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {
6094        #[cfg(feature = "profiler")]
6095        self.core.window_profiler.begin_input(event.kind_name());
6096        let update_count_before = self.core.invalidator.update_count();
6097        // Track input modality for focus-visible styling and hover suppression.
6098        // Hover is suppressed during keyboard modality so that keyboard navigation
6099        // doesn't show hover highlights on the item under the mouse cursor.
6100        let old_modality = self.core.last_input_modality;
6101        self.core.last_input_modality = match &event {
6102            PlatformInput::KeyDown(_) => InputModality::Keyboard,
6103            PlatformInput::MouseMove(_) | PlatformInput::MouseDown(_) => InputModality::Mouse,
6104            PlatformInput::Touch(_) => InputModality::Touch,
6105            _ => self.core.last_input_modality,
6106        };
6107        if self.core.last_input_modality != old_modality {
6108            self.refresh();
6109        }
6110
6111        // Handlers may set this to false by calling `stop_propagation`.
6112        cx.propagate_event = true;
6113        // Handlers may set this to true by calling `prevent_default`.
6114        self.core.default_prevented = false;
6115
6116        let event = match event {
6117            // Track the mouse position with our own state, since accessing the platform
6118            // API for the mouse position can only occur on the main thread.
6119            PlatformInput::MouseMove(mouse_move) => {
6120                self.core.mouse_position = mouse_move.position;
6121                self.core.modifiers = mouse_move.modifiers;
6122                PlatformInput::MouseMove(mouse_move)
6123            }
6124            PlatformInput::MouseDown(mouse_down) => {
6125                self.core.mouse_position = mouse_down.position;
6126                self.core.modifiers = mouse_down.modifiers;
6127                PlatformInput::MouseDown(mouse_down)
6128            }
6129            PlatformInput::MouseUp(mouse_up) => {
6130                self.core.mouse_position = mouse_up.position;
6131                self.core.modifiers = mouse_up.modifiers;
6132                PlatformInput::MouseUp(mouse_up)
6133            }
6134            PlatformInput::MousePressure(mouse_pressure) => {
6135                PlatformInput::MousePressure(mouse_pressure)
6136            }
6137            PlatformInput::MouseExited(mouse_exited) => {
6138                self.core.modifiers = mouse_exited.modifiers;
6139                PlatformInput::MouseExited(mouse_exited)
6140            }
6141            PlatformInput::ModifiersChanged(modifiers_changed) => {
6142                self.core.modifiers = modifiers_changed.modifiers;
6143                self.core.capslock = modifiers_changed.capslock;
6144                PlatformInput::ModifiersChanged(modifiers_changed)
6145            }
6146            PlatformInput::ScrollWheel(scroll_wheel) => {
6147                self.core.mouse_position = scroll_wheel.position;
6148                self.core.modifiers = scroll_wheel.modifiers;
6149                PlatformInput::ScrollWheel(scroll_wheel)
6150            }
6151            PlatformInput::Pinch(pinch) => {
6152                self.core.mouse_position = pinch.position;
6153                self.core.modifiers = pinch.modifiers;
6154                PlatformInput::Pinch(pinch)
6155            }
6156            // Translate dragging and dropping of external files from the operating system
6157            // to internal drag and drop events.
6158            PlatformInput::FileDrop(file_drop) => match file_drop {
6159                FileDropEvent::Entered { position, paths } => {
6160                    self.core.mouse_position = position;
6161                    let source_window = self.core.handle.window_id();
6162                    if !cx.restore_platform_drag(source_window) && cx.active_drag.is_none() {
6163                        cx.active_drag = Some(AnyDrag {
6164                            value: Arc::new(paths.clone()),
6165                            view: cx.new(|_| paths).into(),
6166                            cursor_offset: position,
6167                            cursor_style: None,
6168                            external_payload_source: None,
6169                        });
6170                    }
6171                    PlatformInput::MouseMove(MouseMoveEvent {
6172                        position,
6173                        pressed_button: Some(MouseButton::Left),
6174                        modifiers: Modifiers::default(),
6175                    })
6176                }
6177                FileDropEvent::Pending { position } => {
6178                    self.core.mouse_position = position;
6179                    PlatformInput::MouseMove(MouseMoveEvent {
6180                        position,
6181                        pressed_button: Some(MouseButton::Left),
6182                        modifiers: Modifiers::default(),
6183                    })
6184                }
6185                FileDropEvent::Submit { position } => {
6186                    cx.activate(true);
6187                    self.core.mouse_position = position;
6188                    PlatformInput::MouseUp(MouseUpEvent {
6189                        button: MouseButton::Left,
6190                        position,
6191                        modifiers: Modifiers::default(),
6192                        click_count: 1,
6193                    })
6194                }
6195                FileDropEvent::Exited => {
6196                    if !cx.hand_restored_drag_to_platform(self.core.handle.window_id()) {
6197                        cx.active_drag.take();
6198                    }
6199                    self.refresh();
6200                    PlatformInput::FileDrop(FileDropEvent::Exited)
6201                }
6202                FileDropEvent::Ended => {
6203                    cx.end_platform_drag(self.core.handle.window_id());
6204                    self.refresh();
6205                    PlatformInput::FileDrop(FileDropEvent::Ended)
6206                }
6207            },
6208            PlatformInput::Touch(touch) => PlatformInput::Touch(touch),
6209            PlatformInput::LongPress(long_press) => {
6210                self.core.mouse_position = if long_press.phase == crate::TouchPhase::Started {
6211                    long_press.start_position
6212                } else {
6213                    long_press.position
6214                };
6215                if long_press.phase == crate::TouchPhase::Started {
6216                    self.core.long_press_capture = None;
6217                }
6218                PlatformInput::LongPress(long_press)
6219            }
6220            PlatformInput::TouchDrag(touch_drag) => {
6221                self.core.mouse_position = touch_drag.start_position;
6222                PlatformInput::TouchDrag(touch_drag)
6223            }
6224            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
6225        };
6226
6227        if let Some(any_mouse_event) = event.mouse_event() {
6228            self.dispatch_mouse_event(any_mouse_event, cx);
6229        } else if let Some(any_key_event) = event.keyboard_event() {
6230            self.dispatch_key_event(any_key_event, cx);
6231        } else if let Some(touch_event) = event.touch_event() {
6232            self.dispatch_touch_event(touch_event, cx);
6233        }
6234        if let PlatformInput::LongPress(long_press) = &event {
6235            match long_press.phase {
6236                crate::TouchPhase::Started if !self.core.default_prevented => {
6237                    self.core.long_press_capture = None;
6238                }
6239                crate::TouchPhase::Ended | crate::TouchPhase::Cancelled => {
6240                    self.core.long_press_capture = None;
6241                }
6242                crate::TouchPhase::Started | crate::TouchPhase::Moved => {}
6243            }
6244        }
6245
6246        // Must run after the move is dispatched: the platform owns the gesture afterwards, so this
6247        // is the last chance for drag listeners to see the pointer leave and reset their state.
6248        self.promote_external_drag_to_platform(&event, cx);
6249
6250        let caused_invalidation = self.core.invalidator.update_count() > update_count_before;
6251        if caused_invalidation {
6252            self.core.input_rate_tracker.borrow_mut().record_input();
6253        }
6254        #[cfg(feature = "profiler")]
6255        self.core.window_profiler.end_input(caused_invalidation);
6256
6257        DispatchEventResult {
6258            propagate: cx.propagate_event,
6259            default_prevented: self.core.default_prevented,
6260        }
6261    }
6262
6263    fn promote_external_drag_to_platform(&mut self, event: &PlatformInput, cx: &mut App) {
6264        let PlatformInput::MouseMove(mouse_move) = event else {
6265            return;
6266        };
6267        if mouse_move.pressed_button != Some(MouseButton::Left) {
6268            return;
6269        }
6270        if Bounds::new(Point::default(), self.core.viewport_size).contains(&mouse_move.position) {
6271            return;
6272        }
6273        if !self.core.platform_window.can_start_external_drag() {
6274            return;
6275        }
6276        let Some(payload_source) = cx
6277            .active_drag
6278            .as_mut()
6279            .and_then(|drag| drag.external_payload_source.take())
6280        else {
6281            return;
6282        };
6283        let Some(payload) = payload_source(self, cx) else {
6284            return;
6285        };
6286        if self.core.platform_window.start_external_drag(&payload)
6287            && cx.hand_active_drag_to_platform(self.core.handle.window_id())
6288        {
6289            self.refresh();
6290        }
6291    }
6292
6293    /// Whether recognized touch pans may use the platform's predicted touch
6294    /// positions ([`TouchEvent::predicted_position`]) to compensate for input
6295    /// latency. Defaults to true.
6296    pub fn touch_prediction_enabled(&self) -> bool {
6297        self.core.touch_prediction_enabled
6298    }
6299
6300    /// Sets whether recognized touch pans may use the platform's predicted
6301    /// touch positions. Disabling drops [`TouchEvent::predicted_position`]
6302    /// before gesture recognition, so pans track only raw touch positions.
6303    pub fn set_touch_prediction_enabled(&mut self, enabled: bool) {
6304        self.core.touch_prediction_enabled = enabled;
6305    }
6306
6307    /// Runs the portable gesture recognizer over a raw touch event and
6308    /// dispatches whatever it resolves (scroll steps, synthesized taps)
6309    /// through the ordinary mouse-event path.
6310    fn dispatch_touch_event(&mut self, event: &TouchEvent, cx: &mut App) {
6311        let mut event = event.clone();
6312        if !self.core.touch_prediction_enabled {
6313            event.predicted_position = None;
6314        }
6315        let recognized_gestures = self.core.touch_gestures.handle_event(&event);
6316        if event.phase == crate::TouchPhase::Started
6317            && let Some(touch_drag) = self.core.touch_gestures.offer_touch_drag(event.id)
6318        {
6319            self.dispatch_recognized_touch_gesture(touch_drag, cx);
6320        }
6321        if event.phase == crate::TouchPhase::Started
6322            && self.core.touch_gestures.pending_long_press().is_some()
6323        {
6324            self.core.long_press_capture = None;
6325        }
6326        let mut tapped = false;
6327        for gesture in recognized_gestures {
6328            tapped |= matches!(gesture, RecognizedTouchGesture::Tap { .. });
6329            self.dispatch_recognized_touch_gesture(gesture, cx);
6330        }
6331        if event.phase == crate::TouchPhase::Started {
6332            self.schedule_long_press_timer(cx);
6333        } else if self.core.touch_gestures.pending_long_press().is_none() {
6334            self.core.long_press_timer.take();
6335        }
6336        // The platform's touch-release handler may inspect the input handler
6337        // as soon as this dispatch returns (the web platform decides virtual
6338        // keyboard visibility there, inside the user gesture). Input handlers
6339        // are registered during draw, so draw now to make them reflect any
6340        // focus change the tap just caused.
6341        if tapped && self.core.invalidator.is_dirty() {
6342            self.draw(cx).clear(cx);
6343        }
6344        if self.core.touch_gestures.has_momentum() {
6345            self.schedule_touch_momentum_tick();
6346        }
6347    }
6348
6349    fn dispatch_recognized_touch_gesture(&mut self, gesture: RecognizedTouchGesture, cx: &mut App) {
6350        match gesture {
6351            RecognizedTouchGesture::Scroll(scroll_wheel) => {
6352                self.core.mouse_position = scroll_wheel.position;
6353                cx.propagate_event = true;
6354                self.dispatch_mouse_event(&scroll_wheel, cx);
6355            }
6356            RecognizedTouchGesture::Tap { down, up } => {
6357                self.core.mouse_position = up.position;
6358                cx.propagate_event = true;
6359                self.dispatch_mouse_event(&down, cx);
6360                cx.propagate_event = true;
6361                self.dispatch_mouse_event(&up, cx);
6362            }
6363            RecognizedTouchGesture::TouchDrag(touch_drag) => {
6364                self.core.mouse_position = touch_drag.start_position;
6365                cx.propagate_event = true;
6366                self.core.default_prevented = false;
6367                let started = touch_drag.phase == crate::TouchPhase::Started;
6368                self.dispatch_mouse_event(&touch_drag, cx);
6369                if started {
6370                    self.core
6371                        .touch_gestures
6372                        .resolve_touch_drag(self.core.default_prevented);
6373                }
6374            }
6375            RecognizedTouchGesture::LongPress(long_press) => {
6376                self.core.mouse_position = if long_press.phase == crate::TouchPhase::Started {
6377                    long_press.start_position
6378                } else {
6379                    long_press.position
6380                };
6381                cx.propagate_event = true;
6382                self.core.default_prevented = false;
6383                let started = long_press.phase == crate::TouchPhase::Started;
6384                let ended = matches!(
6385                    long_press.phase,
6386                    crate::TouchPhase::Ended | crate::TouchPhase::Cancelled
6387                );
6388                self.dispatch_mouse_event(&long_press, cx);
6389                if started {
6390                    let claimed = self.core.default_prevented;
6391                    self.core.touch_gestures.resolve_long_press(claimed);
6392                    if !claimed {
6393                        self.core.long_press_capture = None;
6394                    }
6395                }
6396                if ended {
6397                    self.core.long_press_capture = None;
6398                }
6399            }
6400        }
6401    }
6402
6403    fn schedule_long_press_timer(&mut self, cx: &mut App) {
6404        self.core.long_press_timer.take();
6405        let Some((touch_id, duration)) = self.core.touch_gestures.pending_long_press() else {
6406            return;
6407        };
6408        self.core.long_press_timer = Some(self.spawn(cx, async move |cx| {
6409            cx.background_executor.timer(duration).await;
6410            cx.update(move |window, cx| {
6411                window.core.long_press_timer.take();
6412                if let Some(gesture) = window.core.touch_gestures.offer_long_press(touch_id) {
6413                    window.dispatch_recognized_touch_gesture(gesture, cx);
6414                }
6415            })
6416            .log_err();
6417        }));
6418    }
6419
6420    fn schedule_touch_momentum_tick(&mut self) {
6421        self.on_next_frame(|window, cx| {
6422            if let Some(gesture) = window.core.touch_gestures.tick_momentum() {
6423                window.dispatch_recognized_touch_gesture(gesture, cx);
6424            }
6425            if window.core.touch_gestures.has_momentum() {
6426                window.schedule_touch_momentum_tick();
6427            }
6428        });
6429    }
6430
6431    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
6432        let hit_test = self
6433            .frame_state
6434            .rendered_frame
6435            .hit_test(self.mouse_position());
6436        if hit_test != self.core.mouse_hit_test {
6437            self.core.mouse_hit_test = hit_test;
6438            self.reset_cursor_style(cx);
6439        }
6440
6441        #[cfg(any(feature = "inspector", debug_assertions))]
6442        if self.is_inspector_picking(cx) {
6443            self.handle_inspector_mouse_event(event, cx);
6444            // When inspector is picking, all other mouse handling is skipped.
6445            return;
6446        }
6447
6448        let mut mouse_listeners = mem::take(&mut self.frame_state.rendered_frame.mouse_listeners);
6449
6450        // Capture phase, events bubble from back to front. Handlers for this phase are used for
6451        // special purposes, such as detecting events outside of a given Bounds.
6452        for listener in &mut mouse_listeners {
6453            let listener = listener.as_mut().unwrap();
6454            listener(event, DispatchPhase::Capture, self, cx);
6455            if !cx.propagate_event {
6456                break;
6457            }
6458        }
6459
6460        // Bubble phase, where most normal handlers do their work.
6461        if cx.propagate_event {
6462            for listener in mouse_listeners.iter_mut().rev() {
6463                let listener = listener.as_mut().unwrap();
6464                listener(event, DispatchPhase::Bubble, self, cx);
6465                if !cx.propagate_event {
6466                    break;
6467                }
6468            }
6469        }
6470
6471        self.frame_state.rendered_frame.mouse_listeners = mouse_listeners;
6472
6473        if cx.has_active_drag() {
6474            if event.is::<MouseMoveEvent>() {
6475                // If this was a mouse move event, redraw the window so that the
6476                // active drag can follow the mouse cursor.
6477                self.refresh();
6478            } else if event.is::<MouseUpEvent>() {
6479                // If this was a mouse up event, cancel the active drag and redraw
6480                // the window.
6481                cx.active_drag = None;
6482                self.refresh();
6483            }
6484        }
6485
6486        // Auto-release pointer capture on mouse up
6487        if event.is::<MouseUpEvent>() && self.core.captured_hitbox.is_some() {
6488            self.core.captured_hitbox = None;
6489        }
6490    }
6491
6492    // If modifiers are not excessive (e.g. AltGr), and the input handler is accepting text input,
6493    // we prefer the text input over bindings.
6494    fn input_preference(&mut self, event: &dyn Any, cx: &mut App) -> InputPreference {
6495        let prefer_character_input = event
6496            .downcast_ref::<KeyDownEvent>()
6497            .is_some_and(|key_down_event| key_down_event.prefer_character_input);
6498        if !prefer_character_input {
6499            return InputPreference::KeyBindings;
6500        }
6501        let Some(mut input_handler) = self.core.platform_window.take_input_handler() else {
6502            return InputPreference::KeyBindings;
6503        };
6504        let accepts_text_input = input_handler.accepts_text_input(self, cx);
6505        self.core.platform_window.set_input_handler(input_handler);
6506        if accepts_text_input {
6507            InputPreference::CharacterInput
6508        } else {
6509            InputPreference::KeyBindings
6510        }
6511    }
6512
6513    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {
6514        if self.core.invalidator.is_dirty() {
6515            self.draw(cx).clear(cx);
6516        }
6517
6518        let node_id = self.focus_node_id_in_rendered_frame(self.core.focus);
6519        let dispatch_path = self
6520            .frame_state
6521            .rendered_frame
6522            .dispatch_tree
6523            .dispatch_path(node_id);
6524
6525        let mut keystroke: Option<Keystroke> = None;
6526
6527        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {
6528            if event.modifiers.number_of_modifiers() == 0
6529                && self.core.pending_modifier.modifiers.number_of_modifiers() == 1
6530                && !self.core.pending_modifier.saw_other_input
6531            {
6532                let key = match self.core.pending_modifier.modifiers {
6533                    modifiers if modifiers.shift => Some("shift"),
6534                    modifiers if modifiers.control => Some("control"),
6535                    modifiers if modifiers.alt => Some("alt"),
6536                    modifiers if modifiers.platform => Some("platform"),
6537                    modifiers if modifiers.function => Some("function"),
6538                    _ => None,
6539                };
6540                if let Some(key) = key {
6541                    keystroke = Some(Keystroke {
6542                        key: key.to_string(),
6543                        key_char: None,
6544                        modifiers: Modifiers::default(),
6545                    });
6546                }
6547            }
6548
6549            if self.core.pending_modifier.modifiers.number_of_modifiers() == 0
6550                && event.modifiers.number_of_modifiers() == 1
6551            {
6552                self.core.pending_modifier.saw_other_input = false
6553            } else if event.modifiers.number_of_modifiers() > 1 {
6554                self.core.pending_modifier.saw_other_input = true
6555            }
6556            self.core.pending_modifier.modifiers = event.modifiers
6557        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
6558            self.core.pending_modifier.saw_other_input = true;
6559            keystroke = Some(key_down_event.keystroke.clone());
6560            if key_down_event.keystroke.key_char.is_some()
6561                && matches!(
6562                    cx.cursor_hide_mode,
6563                    CursorHideMode::OnTyping | CursorHideMode::OnTypingAndAction
6564                )
6565            {
6566                cx.platform.hide_cursor_until_mouse_moves();
6567            }
6568        }
6569
6570        let Some(keystroke) = keystroke else {
6571            self.finish_dispatch_key_event(
6572                event,
6573                None,
6574                InputPreference::KeyBindings,
6575                dispatch_path,
6576                self.context_stack(),
6577                cx,
6578            );
6579            return;
6580        };
6581
6582        let input_preference = self.input_preference(event, cx);
6583
6584        cx.propagate_event = true;
6585        self.dispatch_keystroke_interceptors(
6586            &keystroke,
6587            input_preference,
6588            self.context_stack(),
6589            cx,
6590        );
6591        if !cx.propagate_event {
6592            self.finish_dispatch_key_event(
6593                event,
6594                Some(&keystroke),
6595                input_preference,
6596                dispatch_path,
6597                self.context_stack(),
6598                cx,
6599            );
6600            return;
6601        }
6602
6603        let mut currently_pending = self.core.pending_input.take().unwrap_or_default();
6604        if currently_pending.focus.is_some() && currently_pending.focus != self.core.focus {
6605            currently_pending = PendingInput::default();
6606        }
6607
6608        let match_result = self.frame_state.rendered_frame.dispatch_tree.dispatch_key(
6609            currently_pending.keystrokes,
6610            keystroke.clone(),
6611            &dispatch_path,
6612        );
6613
6614        if !match_result.to_replay.is_empty() {
6615            self.replay_pending_input(match_result.to_replay, cx);
6616            cx.propagate_event = true;
6617        }
6618
6619        if !match_result.pending.is_empty() {
6620            let previous_timeout = currently_pending.timeout.take();
6621            currently_pending.keystrokes = match_result.pending;
6622            currently_pending.focus = self.core.focus;
6623
6624            let text_input_requires_timeout = event
6625                .downcast_ref::<KeyDownEvent>()
6626                .filter(|key_down| key_down.keystroke.key_char.is_some())
6627                .and_then(|_| self.core.platform_window.take_input_handler())
6628                .map_or(false, |mut input_handler| {
6629                    let accepts = input_handler.accepts_text_input(self, cx);
6630                    self.core.platform_window.set_input_handler(input_handler);
6631                    accepts
6632                });
6633
6634            let needs_timeout = previous_timeout.is_some()
6635                || match_result.pending_has_binding
6636                || text_input_requires_timeout;
6637            currently_pending.timeout = if needs_timeout {
6638                match previous_timeout {
6639                    Some(mut timeout) if timeout.is_paused() => {
6640                        timeout.reset_duration(PENDING_INPUT_TIMEOUT);
6641                        Some(timeout)
6642                    }
6643                    previous_timeout => {
6644                        drop(previous_timeout);
6645                        Some(self.new_pending_input_timeout(PENDING_INPUT_TIMEOUT, cx))
6646                    }
6647                }
6648            } else {
6649                None
6650            };
6651            self.core.pending_input = Some(currently_pending);
6652            self.pending_input_changed(cx);
6653            cx.propagate_event = false;
6654            return;
6655        }
6656
6657        // Interceptors or replayed actions may have changed whether the input handler accepts text.
6658        let input_preference = self.input_preference(event, cx);
6659        if input_preference == InputPreference::KeyBindings {
6660            for binding in match_result.bindings {
6661                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
6662                if !cx.propagate_event {
6663                    self.dispatch_keystroke_observers(
6664                        &keystroke,
6665                        input_preference,
6666                        Some(binding.action.as_ref()),
6667                        match_result.context_stack,
6668                        cx,
6669                    );
6670                    self.pending_input_changed(cx);
6671                    return;
6672                }
6673            }
6674        }
6675
6676        self.finish_dispatch_key_event(
6677            event,
6678            Some(&keystroke),
6679            input_preference,
6680            dispatch_path,
6681            match_result.context_stack,
6682            cx,
6683        );
6684        self.pending_input_changed(cx);
6685    }
6686
6687    fn new_pending_input_timeout(&self, duration: Duration, cx: &App) -> PendingInputTimeout {
6688        let (started_at, task) = self.start_pending_input_timeout(duration, cx);
6689        PendingInputTimeout {
6690            duration,
6691            remaining: duration,
6692            state: PendingInputTimeoutState::Running { started_at, task },
6693        }
6694    }
6695
6696    fn start_pending_input_timeout(&self, remaining: Duration, cx: &App) -> (Instant, Task<()>) {
6697        let started_at = cx.background_executor().now();
6698        let task = self.spawn(cx, async move |cx| {
6699            cx.background_executor.timer(remaining).await;
6700            cx.update(move |window, cx| {
6701                let Some(currently_pending) = window
6702                    .core
6703                    .pending_input
6704                    .take()
6705                    .filter(|pending| pending.focus == window.core.focus)
6706                else {
6707                    return;
6708                };
6709
6710                let node_id = window.focus_node_id_in_rendered_frame(window.core.focus);
6711                let dispatch_path = window
6712                    .frame_state
6713                    .rendered_frame
6714                    .dispatch_tree
6715                    .dispatch_path(node_id);
6716
6717                let to_replay = window
6718                    .frame_state
6719                    .rendered_frame
6720                    .dispatch_tree
6721                    .flush_dispatch(currently_pending.keystrokes, &dispatch_path);
6722
6723                window.pending_input_changed(cx);
6724                window.replay_pending_input(to_replay, cx)
6725            })
6726            .log_err();
6727        });
6728        (started_at, task)
6729    }
6730
6731    fn finish_dispatch_key_event(
6732        &mut self,
6733        event: &dyn Any,
6734        recognized_keystroke: Option<&Keystroke>,
6735        input_preference: InputPreference,
6736        dispatch_path: SmallVec<[DispatchNodeId; 32]>,
6737        context_stack: Vec<KeyContext>,
6738        cx: &mut App,
6739    ) {
6740        self.dispatch_key_down_up_event(event, &dispatch_path, cx);
6741        if !cx.propagate_event {
6742            return;
6743        }
6744
6745        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);
6746        if !cx.propagate_event {
6747            return;
6748        }
6749
6750        if let Some(keystroke) = recognized_keystroke {
6751            self.dispatch_keystroke_observers(keystroke, input_preference, None, context_stack, cx);
6752        }
6753    }
6754
6755    pub(crate) fn pending_input_changed(&mut self, cx: &mut App) {
6756        self.core
6757            .pending_input_observers
6758            .clone()
6759            .retain(&(), |callback| callback(self, cx));
6760    }
6761
6762    fn defer_pending_input_changed(&self, cx: &mut App) {
6763        // Avoid re-entrant entity updates by deferring observer notifications to the end of the
6764        // current effect cycle, and only for this window.
6765        let window_handle = self.core.handle;
6766        cx.defer(move |cx| {
6767            window_handle
6768                .update(cx, |_, window, cx| {
6769                    window.pending_input_changed(cx);
6770                })
6771                .ok();
6772        });
6773    }
6774
6775    fn dispatch_key_down_up_event(
6776        &mut self,
6777        event: &dyn Any,
6778        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
6779        cx: &mut App,
6780    ) {
6781        // Capture phase
6782        for node_id in dispatch_path {
6783            let node = self.frame_state.rendered_frame.dispatch_tree.node(*node_id);
6784
6785            for key_listener in node.key_listeners.clone() {
6786                key_listener(event, DispatchPhase::Capture, self, cx);
6787                if !cx.propagate_event {
6788                    return;
6789                }
6790            }
6791        }
6792
6793        // Bubble phase
6794        for node_id in dispatch_path.iter().rev() {
6795            // Handle low level key events
6796            let node = self.frame_state.rendered_frame.dispatch_tree.node(*node_id);
6797            for key_listener in node.key_listeners.clone() {
6798                key_listener(event, DispatchPhase::Bubble, self, cx);
6799                if !cx.propagate_event {
6800                    return;
6801                }
6802            }
6803        }
6804    }
6805
6806    fn dispatch_modifiers_changed_event(
6807        &mut self,
6808        event: &dyn Any,
6809        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
6810        cx: &mut App,
6811    ) {
6812        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {
6813            return;
6814        };
6815        for node_id in dispatch_path.iter().rev() {
6816            let node = self.frame_state.rendered_frame.dispatch_tree.node(*node_id);
6817            for listener in node.modifiers_changed_listeners.clone() {
6818                listener(event, self, cx);
6819                if !cx.propagate_event {
6820                    return;
6821                }
6822            }
6823        }
6824    }
6825
6826    /// Determine whether a potential multi-stroke key binding is in progress on this window.
6827    pub fn has_pending_keystrokes(&self) -> bool {
6828        self.pending_input().is_some()
6829    }
6830
6831    #[cfg(test)]
6832    pub(crate) fn pending_input_is_none(&self) -> bool {
6833        self.core.pending_input.is_none()
6834    }
6835
6836    pub(crate) fn clear_pending_keystrokes(&mut self, cx: &mut App) {
6837        if self.core.pending_input.take().is_some() {
6838            self.defer_pending_input_changed(cx);
6839        }
6840    }
6841
6842    /// Returns pending input that can still complete a multi-stroke key binding. Input left over
6843    /// from a previous focus can never complete one.
6844    pub fn pending_input(&self) -> Option<PendingInputStatus<'_>> {
6845        self.core
6846            .pending_input
6847            .as_ref()
6848            .filter(|pending_input| pending_input.focus == self.core.focus)
6849            .map(|pending_input| PendingInputStatus {
6850                keystrokes: pending_input.keystrokes.as_slice(),
6851                timeout: pending_input
6852                    .timeout
6853                    .as_ref()
6854                    .map(PendingInputTimeout::status),
6855            })
6856    }
6857
6858    /// Pauses or resumes the current pending input timeout on behalf of `owner`.
6859    ///
6860    /// A paused timeout resumes automatically if `owner` is released. Returns whether the timeout
6861    /// state changed. A timeout paused by one owner cannot be resumed by another.
6862    pub fn set_pending_input_timeout_paused<T: 'static>(
6863        &mut self,
6864        owner: &Entity<T>,
6865        paused: bool,
6866        cx: &mut App,
6867    ) -> bool {
6868        let owner_id = owner.entity_id();
6869        if !paused {
6870            return self.resume_pending_input_timeout(owner_id, cx);
6871        }
6872
6873        let timeout = self
6874            .core
6875            .pending_input
6876            .as_ref()
6877            .filter(|pending_input| pending_input.focus == self.core.focus)
6878            .and_then(|pending_input| pending_input.timeout.as_ref());
6879        let Some(timeout) = timeout else {
6880            return false;
6881        };
6882        if timeout.is_paused() {
6883            return false;
6884        }
6885
6886        let release_subscription = self.observe_release(owner, cx, move |_, window, cx| {
6887            window.resume_pending_input_timeout(owner_id, cx);
6888        });
6889        let now = cx.background_executor().now();
6890        let changed = self
6891            .core
6892            .pending_input
6893            .as_mut()
6894            .filter(|pending_input| pending_input.focus == self.core.focus)
6895            .and_then(|pending_input| pending_input.timeout.as_mut())
6896            .is_some_and(|timeout| {
6897                timeout.pause(
6898                    PendingInputTimeoutPause {
6899                        owner_id,
6900                        _release_subscription: release_subscription,
6901                    },
6902                    now,
6903                )
6904            });
6905
6906        if changed {
6907            self.defer_pending_input_changed(cx);
6908        }
6909        changed
6910    }
6911
6912    fn resume_pending_input_timeout(&mut self, owner_id: EntityId, cx: &mut App) -> bool {
6913        let Some(remaining) = self
6914            .core
6915            .pending_input
6916            .as_ref()
6917            .and_then(|pending_input| pending_input.timeout.as_ref())
6918            .filter(|timeout| timeout.pause_owner_id() == Some(owner_id))
6919            .map(|timeout| timeout.remaining)
6920        else {
6921            return false;
6922        };
6923
6924        let (started_at, task) = self.start_pending_input_timeout(remaining, cx);
6925        let changed = self
6926            .core
6927            .pending_input
6928            .as_mut()
6929            .and_then(|pending_input| pending_input.timeout.as_mut())
6930            .is_some_and(|timeout| timeout.resume(owner_id, started_at, task));
6931
6932        if changed {
6933            self.defer_pending_input_changed(cx);
6934        }
6935        changed
6936    }
6937
6938    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.
6939    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {
6940        self.pending_input()
6941            .map(|pending_input| pending_input.keystrokes())
6942    }
6943
6944    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {
6945        let node_id = self.focus_node_id_in_rendered_frame(self.core.focus);
6946        let dispatch_path = self
6947            .frame_state
6948            .rendered_frame
6949            .dispatch_tree
6950            .dispatch_path(node_id);
6951
6952        'replay: for replay in replays {
6953            let event = KeyDownEvent {
6954                keystroke: replay.keystroke.clone(),
6955                is_held: false,
6956                prefer_character_input: true,
6957            };
6958
6959            cx.propagate_event = true;
6960            for binding in replay.bindings {
6961                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
6962                if !cx.propagate_event {
6963                    self.dispatch_keystroke_observers(
6964                        &replay.keystroke,
6965                        InputPreference::KeyBindings,
6966                        Some(binding.action.as_ref()),
6967                        Vec::default(),
6968                        cx,
6969                    );
6970                    continue 'replay;
6971                }
6972            }
6973
6974            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);
6975            if !cx.propagate_event {
6976                continue 'replay;
6977            }
6978            if let Some(input) = replay.keystroke.key_char.as_ref().cloned()
6979                && let Some(mut input_handler) = self.core.platform_window.take_input_handler()
6980            {
6981                input_handler.dispatch_input(&input, self, cx);
6982                self.core.platform_window.set_input_handler(input_handler)
6983            }
6984        }
6985    }
6986
6987    fn focus_node_id_in_rendered_frame(&self, focus_id: Option<FocusId>) -> DispatchNodeId {
6988        focus_id
6989            .and_then(|focus_id| {
6990                self.frame_state
6991                    .rendered_frame
6992                    .dispatch_tree
6993                    .focusable_node_id(focus_id)
6994            })
6995            .unwrap_or_else(|| self.frame_state.rendered_frame.dispatch_tree.root_node_id())
6996    }
6997
6998    fn dispatch_action_on_node(
6999        &mut self,
7000        node_id: DispatchNodeId,
7001        action: &dyn Action,
7002        cx: &mut App,
7003    ) {
7004        self.dispatch_action_on_node_inner(node_id, action, cx);
7005
7006        if !cx.propagate_event
7007            && cx.cursor_hide_mode == CursorHideMode::OnTypingAndAction
7008            && self.last_input_was_keyboard()
7009        {
7010            cx.platform.hide_cursor_until_mouse_moves();
7011        }
7012    }
7013
7014    fn dispatch_action_on_node_inner(
7015        &mut self,
7016        node_id: DispatchNodeId,
7017        action: &dyn Action,
7018        cx: &mut App,
7019    ) {
7020        let dispatch_path = self
7021            .frame_state
7022            .rendered_frame
7023            .dispatch_tree
7024            .dispatch_path(node_id);
7025
7026        // Capture phase for global actions.
7027        cx.propagate_event = true;
7028        if let Some(mut global_listeners) = cx
7029            .global_action_listeners
7030            .remove(&action.as_any().type_id())
7031        {
7032            for listener in &global_listeners {
7033                #[cfg(feature = "profiler")]
7034                self.core.window_profiler.begin_action_handler(action, cx);
7035                listener(action.as_any(), DispatchPhase::Capture, cx);
7036                #[cfg(feature = "profiler")]
7037                self.core.window_profiler.end_action_handler();
7038                if !cx.propagate_event {
7039                    break;
7040                }
7041            }
7042
7043            global_listeners.extend(
7044                cx.global_action_listeners
7045                    .remove(&action.as_any().type_id())
7046                    .unwrap_or_default(),
7047            );
7048
7049            cx.global_action_listeners
7050                .insert(action.as_any().type_id(), global_listeners);
7051        }
7052
7053        if !cx.propagate_event {
7054            return;
7055        }
7056
7057        // Capture phase for window actions.
7058        for node_id in &dispatch_path {
7059            let node = self.frame_state.rendered_frame.dispatch_tree.node(*node_id);
7060            for DispatchActionListener {
7061                action_type,
7062                listener,
7063            } in node.action_listeners.clone()
7064            {
7065                let any_action = action.as_any();
7066                if action_type == any_action.type_id() {
7067                    #[cfg(feature = "profiler")]
7068                    self.core.window_profiler.begin_action_handler(action, cx);
7069                    listener(any_action, DispatchPhase::Capture, self, cx);
7070                    #[cfg(feature = "profiler")]
7071                    self.core.window_profiler.end_action_handler();
7072
7073                    if !cx.propagate_event {
7074                        return;
7075                    }
7076                }
7077            }
7078        }
7079
7080        // Bubble phase for window actions.
7081        for node_id in dispatch_path.iter().rev() {
7082            let node = self.frame_state.rendered_frame.dispatch_tree.node(*node_id);
7083            for DispatchActionListener {
7084                action_type,
7085                listener,
7086            } in node.action_listeners.clone()
7087            {
7088                let any_action = action.as_any();
7089                if action_type == any_action.type_id() {
7090                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
7091                    #[cfg(feature = "profiler")]
7092                    self.core.window_profiler.begin_action_handler(action, cx);
7093                    listener(any_action, DispatchPhase::Bubble, self, cx);
7094                    #[cfg(feature = "profiler")]
7095                    self.core.window_profiler.end_action_handler();
7096
7097                    if !cx.propagate_event {
7098                        return;
7099                    }
7100                }
7101            }
7102        }
7103
7104        // Bubble phase for global actions.
7105        if let Some(mut global_listeners) = cx
7106            .global_action_listeners
7107            .remove(&action.as_any().type_id())
7108        {
7109            for listener in global_listeners.iter().rev() {
7110                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
7111
7112                #[cfg(feature = "profiler")]
7113                self.core.window_profiler.begin_action_handler(action, cx);
7114                listener(action.as_any(), DispatchPhase::Bubble, cx);
7115                #[cfg(feature = "profiler")]
7116                self.core.window_profiler.end_action_handler();
7117                if !cx.propagate_event {
7118                    break;
7119                }
7120            }
7121
7122            global_listeners.extend(
7123                cx.global_action_listeners
7124                    .remove(&action.as_any().type_id())
7125                    .unwrap_or_default(),
7126            );
7127
7128            cx.global_action_listeners
7129                .insert(action.as_any().type_id(), global_listeners);
7130        }
7131    }
7132
7133    /// Register the given handler to be invoked whenever the global of the given type
7134    /// is updated.
7135    pub fn observe_global<G: Global>(
7136        &mut self,
7137        cx: &mut App,
7138        f: impl Fn(&mut Window, &mut App) + 'static,
7139    ) -> Subscription {
7140        let window_handle = self.core.handle;
7141        let (subscription, activate) = cx.global_observers.insert(
7142            TypeId::of::<G>(),
7143            Box::new(move |cx| {
7144                window_handle
7145                    .update(cx, |_, window, cx| f(window, cx))
7146                    .is_ok()
7147            }),
7148        );
7149        cx.defer(move |_| activate());
7150        subscription
7151    }
7152
7153    /// Focus the current window and bring it to the foreground at the platform level.
7154    pub fn activate_window(&self) {
7155        self.core.platform_window.activate();
7156    }
7157
7158    /// Requests that the operating system draw attention to this window.
7159    pub fn request_attention(&self) {
7160        self.core.platform_window.request_attention();
7161    }
7162
7163    /// Minimize the current window at the platform level.
7164    pub fn minimize_window(&self) {
7165        self.core.platform_window.minimize();
7166    }
7167
7168    /// Toggle full screen status on the current window at the platform level.
7169    pub fn toggle_fullscreen(&self) {
7170        self.core.platform_window.toggle_fullscreen();
7171    }
7172
7173    /// Toggle simple (borderless) fullscreen, where the window covers the entire
7174    /// screen including the menu bar and, on notched displays, the area around the
7175    /// notch. Unlike [`Window::toggle_fullscreen`], this does not move the window
7176    /// into its own Mission Control space. Only has an effect on macOS.
7177    pub fn toggle_simple_fullscreen(&self) {
7178        self.core.platform_window.toggle_simple_fullscreen();
7179    }
7180
7181    /// Updates the IME panel position suggestions for languages like japanese, chinese.
7182    pub fn invalidate_character_coordinates(&self) {
7183        self.on_next_frame(|window, cx| {
7184            if let Some(mut input_handler) = window.core.platform_window.take_input_handler() {
7185                if let Some(bounds) = input_handler.selected_bounds(window, cx) {
7186                    window.core.platform_window.update_ime_position(bounds);
7187                }
7188                window.core.platform_window.set_input_handler(input_handler);
7189            }
7190        });
7191    }
7192
7193    /// Present a platform dialog.
7194    /// The provided message will be presented, along with buttons for each answer.
7195    /// When a button is clicked, the returned Receiver will receive the index of the clicked button.
7196    pub fn prompt<T>(
7197        &mut self,
7198        level: PromptLevel,
7199        message: &str,
7200        detail: Option<&str>,
7201        answers: &[T],
7202        cx: &mut App,
7203    ) -> oneshot::Receiver<usize>
7204    where
7205        T: Clone + Into<PromptButton>,
7206    {
7207        let prompt_builder = cx.prompt_builder.take();
7208        let Some(prompt_builder) = prompt_builder else {
7209            unreachable!("Re-entrant window prompting is not supported by GPUI");
7210        };
7211
7212        let answers = answers
7213            .iter()
7214            .map(|answer| answer.clone().into())
7215            .collect::<Vec<_>>();
7216
7217        let receiver = match &prompt_builder {
7218            PromptBuilder::Default => self
7219                .core
7220                .platform_window
7221                .prompt(level, message, detail, &answers)
7222                .unwrap_or_else(|| {
7223                    self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
7224                }),
7225            PromptBuilder::Custom(_) => {
7226                self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
7227            }
7228        };
7229
7230        cx.prompt_builder = Some(prompt_builder);
7231
7232        receiver
7233    }
7234
7235    fn build_custom_prompt(
7236        &mut self,
7237        prompt_builder: &PromptBuilder,
7238        level: PromptLevel,
7239        message: &str,
7240        detail: Option<&str>,
7241        answers: &[PromptButton],
7242        cx: &mut App,
7243    ) -> oneshot::Receiver<usize> {
7244        let (sender, receiver) = oneshot::channel();
7245        let handle = PromptHandle::new(sender);
7246        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);
7247        self.core.prompt = Some(handle);
7248        receiver
7249    }
7250
7251    /// Returns whether a prompt rendered by GPUI is currently active in this window.
7252    ///
7253    /// This is only true for prompts rendered in the window (see
7254    /// [`App::set_prompt_builder`]), not for platform-native prompt dialogs.
7255    pub fn has_active_prompt(&self) -> bool {
7256        self.core.prompt.is_some()
7257    }
7258
7259    /// Returns the current context stack.
7260    pub fn context_stack(&self) -> Vec<KeyContext> {
7261        let node_id = self.focus_node_id_in_rendered_frame(self.core.focus);
7262        let dispatch_tree = &self.frame_state.rendered_frame.dispatch_tree;
7263        dispatch_tree
7264            .dispatch_path(node_id)
7265            .iter()
7266            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())
7267            .collect()
7268    }
7269
7270    /// Returns all available actions for the focused element.
7271    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {
7272        let node_id = self.focus_node_id_in_rendered_frame(self.core.focus);
7273        let mut actions = self
7274            .frame_state
7275            .rendered_frame
7276            .dispatch_tree
7277            .available_actions(node_id);
7278        for action_type in cx.global_action_listeners.keys() {
7279            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {
7280                let action = cx.actions.build_action_type(action_type).ok();
7281                if let Some(action) = action {
7282                    actions.insert(ix, action);
7283                }
7284            }
7285        }
7286        actions
7287    }
7288
7289    /// Returns key bindings that invoke an action on the currently focused element. Bindings are
7290    /// returned in the order they were added. For display, the last binding should take precedence.
7291    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
7292        self.frame_state
7293            .rendered_frame
7294            .dispatch_tree
7295            .bindings_for_action(
7296                action,
7297                &self.frame_state.rendered_frame.dispatch_tree.context_stack,
7298            )
7299    }
7300
7301    /// Returns the highest precedence key binding that invokes an action on the currently focused
7302    /// element. This is more efficient than getting the last result of `bindings_for_action`.
7303    pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option<KeyBinding> {
7304        self.frame_state
7305            .rendered_frame
7306            .dispatch_tree
7307            .highest_precedence_binding_for_action(
7308                action,
7309                &self.frame_state.rendered_frame.dispatch_tree.context_stack,
7310            )
7311    }
7312
7313    /// Returns the key bindings for an action in a context.
7314    pub fn bindings_for_action_in_context(
7315        &self,
7316        action: &dyn Action,
7317        context: KeyContext,
7318    ) -> Vec<KeyBinding> {
7319        let dispatch_tree = &self.frame_state.rendered_frame.dispatch_tree;
7320        dispatch_tree.bindings_for_action(action, &[context])
7321    }
7322
7323    /// Returns the highest precedence key binding for an action in a context. This is more
7324    /// efficient than getting the last result of `bindings_for_action_in_context`.
7325    pub fn highest_precedence_binding_for_action_in_context(
7326        &self,
7327        action: &dyn Action,
7328        context: KeyContext,
7329    ) -> Option<KeyBinding> {
7330        let dispatch_tree = &self.frame_state.rendered_frame.dispatch_tree;
7331        dispatch_tree.highest_precedence_binding_for_action(action, &[context])
7332    }
7333
7334    /// Returns any bindings that would invoke an action on the given focus handle if it were
7335    /// focused. Bindings are returned in the order they were added. For display, the last binding
7336    /// should take precedence.
7337    pub fn bindings_for_action_in(
7338        &self,
7339        action: &dyn Action,
7340        focus_handle: &FocusHandle,
7341    ) -> Vec<KeyBinding> {
7342        let dispatch_tree = &self.frame_state.rendered_frame.dispatch_tree;
7343        let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else {
7344            return vec![];
7345        };
7346        dispatch_tree.bindings_for_action(action, &context_stack)
7347    }
7348
7349    /// Returns the highest precedence key binding that would invoke an action on the given focus
7350    /// handle if it were focused. This is more efficient than getting the last result of
7351    /// `bindings_for_action_in`.
7352    pub fn highest_precedence_binding_for_action_in(
7353        &self,
7354        action: &dyn Action,
7355        focus_handle: &FocusHandle,
7356    ) -> Option<KeyBinding> {
7357        let dispatch_tree = &self.frame_state.rendered_frame.dispatch_tree;
7358        let context_stack = self.context_stack_for_focus_handle(focus_handle)?;
7359        dispatch_tree.highest_precedence_binding_for_action(action, &context_stack)
7360    }
7361
7362    /// Find the bindings that can follow the current input sequence for the current context stack.
7363    pub fn possible_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
7364        self.frame_state
7365            .rendered_frame
7366            .dispatch_tree
7367            .possible_next_bindings_for_input(input, &self.context_stack())
7368    }
7369
7370    fn context_stack_for_focus_handle(
7371        &self,
7372        focus_handle: &FocusHandle,
7373    ) -> Option<Vec<KeyContext>> {
7374        let dispatch_tree = &self.frame_state.rendered_frame.dispatch_tree;
7375        let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?;
7376        let context_stack: Vec<_> = dispatch_tree
7377            .dispatch_path(node_id)
7378            .into_iter()
7379            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
7380            .collect();
7381        Some(context_stack)
7382    }
7383
7384    /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.
7385    pub fn listener_for<T: 'static, E>(
7386        &self,
7387        view: &Entity<T>,
7388        f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
7389    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
7390        let view = view.downgrade();
7391        move |e: &E, window: &mut Window, cx: &mut App| {
7392            view.update(cx, |view, cx| f(view, e, window, cx)).ok();
7393        }
7394    }
7395
7396    /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.
7397    pub fn handler_for<E: 'static, Callback: Fn(&mut E, &mut Window, &mut Context<E>) + 'static>(
7398        &self,
7399        entity: &Entity<E>,
7400        f: Callback,
7401    ) -> impl Fn(&mut Window, &mut App) + 'static {
7402        let entity = entity.downgrade();
7403        move |window: &mut Window, cx: &mut App| {
7404            entity.update(cx, |entity, cx| f(entity, window, cx)).ok();
7405        }
7406    }
7407
7408    /// Register a callback that can interrupt the closing of the current window based the returned boolean.
7409    /// If the callback returns false, the window won't be closed.
7410    pub fn on_window_should_close(
7411        &self,
7412        cx: &App,
7413        f: impl Fn(&mut Window, &mut App) -> bool + 'static,
7414    ) {
7415        let mut cx = self.to_async(cx);
7416        self.core.platform_window.on_should_close(Box::new(move || {
7417            cx.update(|window, cx| f(window, cx)).unwrap_or(true)
7418        }))
7419    }
7420
7421    /// Register an action listener on this node for the next frame. The type of action
7422    /// is determined by the first parameter of the given listener. When the next frame is rendered
7423    /// the listener will be cleared.
7424    ///
7425    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
7426    /// a specific need to register a listener yourself.
7427    ///
7428    /// This method should only be called as part of the paint phase of element drawing.
7429    pub fn on_action(
7430        &mut self,
7431        action_type: TypeId,
7432        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
7433    ) {
7434        self.core.invalidator.debug_assert_paint();
7435
7436        self.frame_state
7437            .next_frame
7438            .dispatch_tree
7439            .on_action(action_type, Rc::new(listener));
7440    }
7441
7442    /// Register a capturing action listener on this node for the next frame if the condition is true.
7443    /// The type of action is determined by the first parameter of the given listener. When the next
7444    /// frame is rendered the listener will be cleared.
7445    ///
7446    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
7447    /// a specific need to register a listener yourself.
7448    ///
7449    /// This method should only be called as part of the paint phase of element drawing.
7450    pub fn on_action_when(
7451        &mut self,
7452        condition: bool,
7453        action_type: TypeId,
7454        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
7455    ) {
7456        self.core.invalidator.debug_assert_paint();
7457
7458        if condition {
7459            self.frame_state
7460                .next_frame
7461                .dispatch_tree
7462                .on_action(action_type, Rc::new(listener));
7463        }
7464    }
7465
7466    /// Read information about the GPU backing this window.
7467    /// Currently returns None on Mac and Windows.
7468    pub fn gpu_specs(&self) -> Option<GpuSpecs> {
7469        self.core.platform_window.gpu_specs()
7470    }
7471
7472    /// Perform titlebar double-click action.
7473    /// This is macOS specific.
7474    pub fn titlebar_double_click(&self) {
7475        self.core
7476            .platform_window
7477            .titlebar_double_click(self.core.is_resizable, self.core.is_minimizable);
7478    }
7479
7480    /// Gets the window's title at the platform level.
7481    /// This is macOS specific.
7482    pub fn window_title(&self) -> String {
7483        self.core.platform_window.get_title()
7484    }
7485
7486    /// Returns a list of all tabbed windows and their titles.
7487    /// This is macOS specific.
7488    pub fn tabbed_windows(&self) -> Option<Vec<SystemWindowTab>> {
7489        self.core.platform_window.tabbed_windows()
7490    }
7491
7492    /// Returns the tab bar visibility.
7493    /// This is macOS specific.
7494    pub fn tab_bar_visible(&self) -> bool {
7495        self.core.platform_window.tab_bar_visible()
7496    }
7497
7498    /// Merges all open windows into a single tabbed window.
7499    /// This is macOS specific.
7500    pub fn merge_all_windows(&self) {
7501        self.core.platform_window.merge_all_windows()
7502    }
7503
7504    /// Moves the tab to a new containing window.
7505    /// This is macOS specific.
7506    pub fn move_tab_to_new_window(&self) {
7507        self.core.platform_window.move_tab_to_new_window()
7508    }
7509
7510    /// Shows or hides the window tab overview.
7511    /// This is macOS specific.
7512    pub fn toggle_window_tab_overview(&self) {
7513        self.core.platform_window.toggle_window_tab_overview()
7514    }
7515
7516    /// Sets the tabbing identifier for the window.
7517    /// This is macOS specific.
7518    pub fn set_tabbing_identifier(&self, tabbing_identifier: Option<String>) {
7519        self.core
7520            .platform_window
7521            .set_tabbing_identifier(tabbing_identifier)
7522    }
7523
7524    /// Request the OS to play an alert sound. On some platforms this is associated
7525    /// with the window, for others it's just a simple global function call.
7526    pub fn play_system_bell(&self) {
7527        self.core.platform_window.play_system_bell()
7528    }
7529
7530    /// Returns whether accessibility support is enabled for this window.
7531    ///
7532    /// This is false when the app was created with [`crate::Application::new_inaccessible`].
7533    /// Unlike [`Self::is_a11y_active`], this does not depend on whether assistive
7534    /// technology is currently connected, so it can be used to gate subscriptions
7535    /// that are only needed for accessibility.
7536    pub fn is_a11y_enabled(&self) -> bool {
7537        self.core.a11y.is_enabled()
7538    }
7539
7540    /// Returns whether accessibility features are active for this frame,
7541    /// i.e. whether assistive technology (such as a screen reader) is
7542    /// connected and an accessibility tree is being built.
7543    ///
7544    /// Use this to skip computing data during rendering that is only
7545    /// observable through the accessibility tree. When accessibility is
7546    /// activated, a redraw is forced, so gated work is recomputed before the
7547    /// next tree update is sent to the platform.
7548    ///
7549    /// See the [accessibility guide](crate::_accessibility) for an overview.
7550    pub fn is_a11y_active(&self) -> bool {
7551        self.core.a11y.is_active()
7552    }
7553
7554    /// Debug representation of the last frame's accessibility information.
7555    pub fn debug_a11y_tree_json(&self) -> Option<String> {
7556        self.core.a11y.debug_tree_json()
7557    }
7558
7559    /// Register a listener for an accessibility action on a specific node.
7560    /// The listener will be called when a screen reader requests the given
7561    /// action on the node identified by `node_id`.
7562    ///
7563    /// See the [accessibility guide](crate::_accessibility) for an overview.
7564    pub fn on_a11y_action(
7565        &mut self,
7566        node_id: accesskit::NodeId,
7567        action: accesskit::Action,
7568        listener: impl FnMut(Option<&accesskit::ActionData>, &mut Window, &mut App) + 'static,
7569    ) {
7570        self.core
7571            .a11y
7572            .action_listeners
7573            .entry(node_id)
7574            .or_default()
7575            .push((action, Box::new(listener)));
7576    }
7577
7578    #[cfg(not(target_family = "wasm"))]
7579    pub(crate) fn handle_a11y_action(&mut self, request: accesskit::ActionRequest, cx: &mut App) {
7580        // Take listeners out temporarily so the closures can borrow Window
7581        // mutably, then restore them afterward.
7582        if let Some(mut listeners) = self.core.a11y.action_listeners.remove(&request.target_node) {
7583            let extra_data = request.data.as_ref();
7584            let mut matched = false;
7585            for (action, listener) in &mut listeners {
7586                if *action == request.action {
7587                    listener(extra_data, self, cx);
7588                    matched = true;
7589                }
7590            }
7591            self.core
7592                .a11y
7593                .action_listeners
7594                .insert(request.target_node, listeners);
7595            if matched {
7596                return;
7597            }
7598        }
7599
7600        // Fall back to built-in action handling.
7601        match request.action {
7602            accesskit::Action::Click => {
7603                if let Some(bounds) = self
7604                    .core
7605                    .a11y
7606                    .node_bounds
7607                    .get(&request.target_node)
7608                    .copied()
7609                {
7610                    let center = bounds.center();
7611                    let mouse_down = PlatformInput::MouseDown(crate::MouseDownEvent {
7612                        button: MouseButton::Left,
7613                        position: center,
7614                        modifiers: Modifiers::default(),
7615                        click_count: 1,
7616                        first_mouse: false,
7617                    });
7618                    let mouse_up = PlatformInput::MouseUp(MouseUpEvent {
7619                        button: MouseButton::Left,
7620                        position: center,
7621                        modifiers: Modifiers::default(),
7622                        click_count: 1,
7623                    });
7624                    self.dispatch_event(mouse_down, cx);
7625                    self.dispatch_event(mouse_up, cx);
7626                }
7627            }
7628            accesskit::Action::Focus => {
7629                if let Some(focus_id) = self.core.a11y.focus_ids.get(&request.target_node).copied()
7630                    && let Some(handle) = FocusHandle::for_id(focus_id, &cx.focus_handles)
7631                {
7632                    self.focus(&handle, cx);
7633                }
7634            }
7635            accesskit::Action::Blur => {
7636                self.blur(cx);
7637            }
7638            _ => {
7639                log::debug!(
7640                    "Unhandled a11y action: {:?} on {:?}",
7641                    request.action,
7642                    request.target_node
7643                );
7644            }
7645        }
7646    }
7647
7648    /// Toggles the inspector mode on this window.
7649    #[cfg(any(feature = "inspector", debug_assertions))]
7650    pub fn toggle_inspector(&mut self, cx: &mut App) {
7651        self.core.inspector = match self.core.inspector {
7652            None => Some(cx.new(|_| Inspector::new())),
7653            Some(_) => {
7654                self.frame_state.rendered_frame.next_inspector_instance_ids = FxHashMap::default();
7655                self.frame_state.rendered_frame.inspector_hitboxes = FxHashMap::default();
7656                self.frame_state.next_frame.next_inspector_instance_ids = FxHashMap::default();
7657                self.frame_state.next_frame.inspector_hitboxes = FxHashMap::default();
7658                None
7659            }
7660        };
7661        self.refresh();
7662    }
7663
7664    /// Returns true if the window is in inspector mode.
7665    pub fn is_inspector_picking(&self, _cx: &App) -> bool {
7666        #[cfg(any(feature = "inspector", debug_assertions))]
7667        {
7668            if let Some(inspector) = &self.core.inspector {
7669                return inspector.read(_cx).is_picking();
7670            }
7671        }
7672        false
7673    }
7674
7675    /// Publishes `inspector_element_id` as the identity of the element being
7676    /// laid out or painted, returning the previous value so the caller can put
7677    /// it back once the element returns.
7678    pub(crate) fn set_inspector_element_id(
7679        &mut self,
7680        inspector_element_id: Option<crate::InspectorElementId>,
7681    ) -> Option<crate::InspectorElementId> {
7682        std::mem::replace(
7683            &mut self.frame_state.inspector_element_id,
7684            inspector_element_id,
7685        )
7686    }
7687
7688    /// Executes the provided function with mutable access to the inspector state
7689    /// of the element with `inspector_id`, if that element is the one the
7690    /// inspector has active. The inspector UI itself uses this to read and edit
7691    /// a selected element's state.
7692    #[cfg(any(feature = "inspector", debug_assertions))]
7693    pub fn with_inspector_state<T: 'static, R>(
7694        &mut self,
7695        inspector_id: Option<&crate::InspectorElementId>,
7696        cx: &mut App,
7697        f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
7698    ) -> Option<R> {
7699        let inspector_id = inspector_id?;
7700        let inspector = self.core.inspector.as_ref()?;
7701        if inspector.read(cx).active_element_id() != Some(inspector_id) {
7702            return None;
7703        }
7704        let inspector = inspector.clone();
7705        Some(inspector.update(cx, |inspector, _cx| {
7706            inspector.with_active_element_state(self, f)
7707        }))
7708    }
7709
7710    #[cfg(any(feature = "inspector", debug_assertions))]
7711    pub(crate) fn inspector_enabled(&self) -> bool {
7712        self.core.inspector.is_some()
7713    }
7714
7715    /// Executes the provided function with mutable access to the inspector state
7716    /// of the element the runtime is currently laying out or painting.
7717    ///
7718    /// This is the form elements use: the runtime publishes their identity
7719    /// around each lifecycle call, so they never handle the token themselves.
7720    #[cfg(any(feature = "inspector", debug_assertions))]
7721    pub fn with_current_inspector_state<T: 'static, R>(
7722        &mut self,
7723        cx: &mut App,
7724        f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
7725    ) -> Option<R> {
7726        let inspector_id = self.frame_state.inspector_element_id.clone();
7727        self.with_inspector_state(inspector_id.as_ref(), cx, f)
7728    }
7729
7730    #[cfg(any(feature = "inspector", debug_assertions))]
7731    pub(crate) fn build_inspector_element_id(
7732        &mut self,
7733        path: crate::InspectorElementPath,
7734    ) -> crate::InspectorElementId {
7735        self.core.invalidator.debug_assert_paint_or_prepaint();
7736        let path = Rc::new(path);
7737        let next_instance_id = self
7738            .frame_state
7739            .next_frame
7740            .next_inspector_instance_ids
7741            .entry(path.clone())
7742            .or_insert(0);
7743        let instance_id = *next_instance_id;
7744        *next_instance_id += 1;
7745        crate::InspectorElementId { path, instance_id }
7746    }
7747
7748    #[cfg(any(feature = "inspector", debug_assertions))]
7749    fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option<AnyElement> {
7750        if let Some(inspector) = self.core.inspector.take() {
7751            let mut inspector_element = AnyView::from(inspector.clone()).into_any_element();
7752            inspector_element.prepaint_as_root(
7753                point(self.core.viewport_size.width - inspector_width, px(0.0)),
7754                size(inspector_width, self.core.viewport_size.height).into(),
7755                self,
7756                cx,
7757            );
7758            self.core.inspector = Some(inspector);
7759            Some(inspector_element)
7760        } else {
7761            None
7762        }
7763    }
7764
7765    #[cfg(any(feature = "inspector", debug_assertions))]
7766    fn paint_inspector(&mut self, mut inspector_element: Option<AnyElement>, cx: &mut App) {
7767        if let Some(mut inspector_element) = inspector_element {
7768            inspector_element.paint(self, cx);
7769        };
7770    }
7771
7772    /// Registers a hitbox that can be used for inspector picking mode, allowing users to select and
7773    /// inspect UI elements by clicking on them.
7774    ///
7775    /// The runtime does this for an element as it paints it; elements do not call
7776    /// it themselves.
7777    #[cfg(any(feature = "inspector", debug_assertions))]
7778    pub(crate) fn insert_inspector_hitbox(&mut self, hitbox_id: HitboxId, cx: &App) {
7779        self.core.invalidator.debug_assert_paint_or_prepaint();
7780        if !self.is_inspector_picking(cx) {
7781            return;
7782        }
7783        if let Some(inspector_id) = self.frame_state.inspector_element_id.clone() {
7784            self.frame_state
7785                .next_frame
7786                .inspector_hitboxes
7787                .insert(hitbox_id, inspector_id);
7788        }
7789    }
7790
7791    #[cfg(any(feature = "inspector", debug_assertions))]
7792    fn paint_inspector_hitbox(&mut self, cx: &App) {
7793        if let Some(inspector) = self.core.inspector.as_ref() {
7794            let inspector = inspector.read(cx);
7795            if let Some((hitbox_id, _)) =
7796                self.hovered_inspector_hitbox(inspector, &self.frame_state.next_frame)
7797                && let Some(hitbox) = self
7798                    .frame_state
7799                    .next_frame
7800                    .hitboxes
7801                    .iter()
7802                    .find(|hitbox| hitbox.id == hitbox_id)
7803            {
7804                self.paint_quad(crate::fill(hitbox.bounds, crate::rgba(0x61afef4d)));
7805            }
7806        }
7807    }
7808
7809    #[cfg(any(feature = "inspector", debug_assertions))]
7810    fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
7811        let Some(inspector) = self.core.inspector.clone() else {
7812            return;
7813        };
7814        if event.downcast_ref::<MouseMoveEvent>().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.hover(inspector_id, self);
7820                }
7821            });
7822        } else if event.downcast_ref::<crate::MouseDownEvent>().is_some() {
7823            inspector.update(cx, |inspector, _cx| {
7824                if let Some((_, inspector_id)) =
7825                    self.hovered_inspector_hitbox(inspector, &self.frame_state.rendered_frame)
7826                {
7827                    inspector.select(inspector_id, self);
7828                }
7829            });
7830        } else if let Some(event) = event.downcast_ref::<crate::ScrollWheelEvent>() {
7831            // This should be kept in sync with SCROLL_LINES in x11 platform.
7832            const SCROLL_LINES: f32 = 3.0;
7833            const SCROLL_PIXELS_PER_LAYER: f32 = 36.0;
7834            let delta_y = event
7835                .delta
7836                .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES))
7837                .y;
7838            if let Some(inspector) = self.core.inspector.clone() {
7839                inspector.update(cx, |inspector, _cx| {
7840                    if let Some(depth) = inspector.pick_depth.as_mut() {
7841                        *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER;
7842                        let max_depth = self.core.mouse_hit_test.ids.len() as f32 - 0.5;
7843                        if *depth < 0.0 {
7844                            *depth = 0.0;
7845                        } else if *depth > max_depth {
7846                            *depth = max_depth;
7847                        }
7848                        if let Some((_, inspector_id)) = self
7849                            .hovered_inspector_hitbox(inspector, &self.frame_state.rendered_frame)
7850                        {
7851                            inspector.set_active_element_id(inspector_id, self);
7852                        }
7853                    }
7854                });
7855            }
7856        }
7857    }
7858
7859    #[cfg(any(feature = "inspector", debug_assertions))]
7860    fn hovered_inspector_hitbox(
7861        &self,
7862        inspector: &Inspector,
7863        frame: &Frame,
7864    ) -> Option<(HitboxId, crate::InspectorElementId)> {
7865        if let Some(pick_depth) = inspector.pick_depth {
7866            let depth = (pick_depth as i64).try_into().unwrap_or(0);
7867            let max_skipped = self.core.mouse_hit_test.ids.len().saturating_sub(1);
7868            let skip_count = (depth as usize).min(max_skipped);
7869            for hitbox_id in self.core.mouse_hit_test.ids.iter().skip(skip_count) {
7870                if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) {
7871                    return Some((*hitbox_id, inspector_id.clone()));
7872                }
7873            }
7874        }
7875        None
7876    }
7877
7878    /// For testing: set the current modifier keys state.
7879    /// This does not generate any events.
7880    #[cfg(any(test, feature = "test-support"))]
7881    pub fn set_modifiers(&mut self, modifiers: Modifiers) {
7882        self.core.modifiers = modifiers;
7883    }
7884
7885    /// For testing: simulate a mouse move event to the given position.
7886    /// This dispatches the event through the normal event handling path,
7887    /// which will trigger hover states and tooltips.
7888    #[cfg(any(test, feature = "test-support"))]
7889    pub fn simulate_mouse_move(&mut self, position: Point<Pixels>, cx: &mut App) {
7890        let event = PlatformInput::MouseMove(MouseMoveEvent {
7891            position,
7892            modifiers: self.core.modifiers,
7893            pressed_button: None,
7894        });
7895        let _ = self.dispatch_event(event, cx);
7896    }
7897
7898    #[inline(never)]
7899    fn take_element_state(
7900        &mut self,
7901        global_id: &GlobalElementId,
7902        state_type: TypeId,
7903    ) -> ((GlobalElementId, TypeId), Option<ElementStateBox>) {
7904        let key = (global_id.clone(), state_type);
7905        self.frame_state
7906            .next_frame
7907            .accessed_element_states
7908            .push(key.clone());
7909        let state = self
7910            .frame_state
7911            .next_frame
7912            .element_states
7913            .remove(&key)
7914            .or_else(|| self.frame_state.rendered_frame.element_states.remove(&key));
7915        (key, state)
7916    }
7917
7918    #[inline(never)]
7919    fn insert_element_state(
7920        &mut self,
7921        key: (GlobalElementId, TypeId),
7922        state: ElementStateBox,
7923    ) -> Option<ElementStateBox> {
7924        self.frame_state
7925            .next_frame
7926            .element_states
7927            .insert(key, state)
7928    }
7929
7930    #[inline(never)]
7931    fn observe_keyed_state<S: 'static>(state: &Entity<S>, current_view: EntityId, cx: &mut App) {
7932        cx.observe(state, move |_, cx| {
7933            cx.notify(current_view);
7934        })
7935        .detach();
7936    }
7937}
7938
7939/// A handle to a window with a specific root view type.
7940/// Note that this does not keep the window alive on its own.
7941#[derive(Deref, DerefMut)]
7942pub struct WindowHandle<V> {
7943    #[deref]
7944    #[deref_mut]
7945    pub(crate) any_handle: AnyWindowHandle,
7946    state_type: PhantomData<fn(V) -> V>,
7947}
7948
7949impl<V> Debug for WindowHandle<V> {
7950    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7951        f.debug_struct("WindowHandle")
7952            .field("any_handle", &self.any_handle.id.as_u64())
7953            .finish()
7954    }
7955}
7956
7957impl<V: 'static + Render> WindowHandle<V> {
7958    /// Creates a new handle from a window ID.
7959    /// This does not check if the root type of the window is `V`.
7960    pub fn new(id: WindowId) -> Self {
7961        WindowHandle {
7962            any_handle: AnyWindowHandle {
7963                id,
7964                state_type: TypeId::of::<V>(),
7965                root_entity_type_name: std::any::type_name::<V>(),
7966            },
7967            state_type: PhantomData,
7968        }
7969    }
7970
7971    /// Get the root view out of this window.
7972    ///
7973    /// This will fail if the window is closed or if the root view's type does not match `V`.
7974    #[cfg(any(test, feature = "test-support"))]
7975    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>
7976    where
7977        C: AppContext,
7978    {
7979        cx.update_window(self.any_handle, |root_view, _, _| {
7980            root_view
7981                .downcast::<V>()
7982                .map_err(|_| anyhow!("the type of the window's root view has changed"))
7983        })?
7984    }
7985
7986    /// Updates the root view of this window.
7987    ///
7988    /// This will fail if the window has been closed or if the root view's type does not match
7989    pub fn update<C, R>(
7990        &self,
7991        cx: &mut C,
7992        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
7993    ) -> Result<R>
7994    where
7995        C: AppContext,
7996    {
7997        cx.update_window(self.any_handle, |root_view, window, cx| {
7998            let view = root_view
7999                .downcast::<V>()
8000                .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
8001
8002            Ok(view.update(cx, |view, cx| update(view, window, cx)))
8003        })?
8004    }
8005
8006    /// Read the root view out of this window.
8007    ///
8008    /// This will fail if the window is closed or if the root view's type does not match `V`.
8009    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {
8010        let x = cx
8011            .windows
8012            .cell(self.id)
8013            .and_then(|cell| cell.borrow().core.root.clone())
8014            .map(|root_view| root_view.downcast::<V>())
8015            .context("window not found")?
8016            .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
8017
8018        Ok(x.read(cx))
8019    }
8020
8021    /// Read the root view out of this window, with a callback
8022    ///
8023    /// This will fail if the window is closed or if the root view's type does not match `V`.
8024    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>
8025    where
8026        C: AppContext,
8027    {
8028        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
8029    }
8030
8031    /// Read the root view pointer off of this window.
8032    ///
8033    /// This will fail if the window is closed or if the root view's type does not match `V`.
8034    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>
8035    where
8036        C: AppContext,
8037    {
8038        cx.read_window(self, |root_view, _cx| root_view)
8039    }
8040
8041    /// Check if this window is 'active'.
8042    ///
8043    /// Will return `None` if the window is closed or currently
8044    /// borrowed.
8045    pub fn is_active(&self, cx: &mut App) -> Option<bool> {
8046        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())
8047            .ok()
8048    }
8049}
8050
8051impl<V> Copy for WindowHandle<V> {}
8052
8053impl<V> Clone for WindowHandle<V> {
8054    fn clone(&self) -> Self {
8055        *self
8056    }
8057}
8058
8059impl<V> PartialEq for WindowHandle<V> {
8060    fn eq(&self, other: &Self) -> bool {
8061        self.any_handle == other.any_handle
8062    }
8063}
8064
8065impl<V> Eq for WindowHandle<V> {}
8066
8067impl<V> Hash for WindowHandle<V> {
8068    fn hash<H: Hasher>(&self, state: &mut H) {
8069        self.any_handle.hash(state);
8070    }
8071}
8072
8073impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
8074    fn from(val: WindowHandle<V>) -> Self {
8075        val.any_handle
8076    }
8077}
8078
8079/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.
8080#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
8081pub struct AnyWindowHandle {
8082    pub(crate) id: WindowId,
8083    state_type: TypeId,
8084    root_entity_type_name: &'static str,
8085}
8086
8087impl AnyWindowHandle {
8088    /// Get the ID of this window.
8089    pub fn window_id(&self) -> WindowId {
8090        self.id
8091    }
8092
8093    /// A handle for reading this window's metrics without borrowing it.
8094    ///
8095    /// Returns `None` if the window has been closed. Unlike
8096    /// [`WindowHandle::is_active`], this needs only a shared borrow of the app
8097    /// and reads the last published snapshot, so it succeeds even while the
8098    /// window is borrowed and never blocks on the UI thread.
8099    pub fn metrics(&self, cx: &App) -> Option<WindowMetricsHandle> {
8100        cx.windows
8101            .cell(self.id)
8102            .map(|cell| cell.borrow().core.metrics_handle())
8103    }
8104
8105    /// Returns the name of the window's declared root entity type.
8106    pub fn root_entity_type_name(&self) -> &'static str {
8107        self.root_entity_type_name
8108    }
8109
8110    /// Attempt to convert this handle to a window handle with a specific root view type.
8111    /// If the types do not match, this will return `None`.
8112    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
8113        if TypeId::of::<T>() == self.state_type {
8114            Some(WindowHandle {
8115                any_handle: *self,
8116                state_type: PhantomData,
8117            })
8118        } else {
8119            None
8120        }
8121    }
8122
8123    /// Updates the state of the root view of this window.
8124    ///
8125    /// This will fail if the window has been closed.
8126    pub fn update<C, R>(
8127        self,
8128        cx: &mut C,
8129        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
8130    ) -> Result<R>
8131    where
8132        C: AppContext,
8133    {
8134        cx.update_window(self, update)
8135    }
8136
8137    /// Read the state of the root view of this window.
8138    ///
8139    /// This will fail if the window has been closed.
8140    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>
8141    where
8142        C: AppContext,
8143        T: 'static,
8144    {
8145        let view = self
8146            .downcast::<T>()
8147            .context("the type of the window's root view has changed")?;
8148
8149        cx.read_window(&view, read)
8150    }
8151}
8152
8153impl HasWindowHandle for Window<'_> {
8154    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {
8155        self.core.platform_window.window_handle()
8156    }
8157}
8158
8159impl HasDisplayHandle for Window<'_> {
8160    fn display_handle(
8161        &self,
8162    ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, HandleError> {
8163        self.core.platform_window.display_handle()
8164    }
8165}
8166
8167/// An identifier for an [`Element`].
8168///
8169/// Can be constructed with a string, a number, or both, as well
8170/// as other internal representations.
8171#[derive(Clone, Debug, Eq, PartialEq, Hash)]
8172pub enum ElementId {
8173    /// The ID of a View element
8174    View(EntityId),
8175    /// An integer ID.
8176    Integer(u64),
8177    /// A string based ID.
8178    Name(SharedString),
8179    /// A UUID.
8180    Uuid(Uuid),
8181    /// An ID that's equated with a focus handle.
8182    FocusHandle(FocusId),
8183    /// A combination of a name and an integer.
8184    NamedInteger(SharedString, u64),
8185    /// A path.
8186    Path(Arc<std::path::Path>),
8187    /// A code location.
8188    CodeLocation(core::panic::Location<'static>),
8189    /// A labeled child of an element.
8190    NamedChild(Arc<ElementId>, SharedString),
8191    /// A byte array ID (used for text-anchors)
8192    OpaqueId([u8; 20]),
8193}
8194
8195impl ElementId {
8196    /// Constructs an `ElementId::NamedInteger` from a name and `usize`.
8197    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {
8198        Self::NamedInteger(name.into(), integer as u64)
8199    }
8200}
8201
8202impl Display for ElementId {
8203    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
8204        match self {
8205            ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
8206            ElementId::Integer(ix) => write!(f, "{}", ix)?,
8207            ElementId::Name(name) => write!(f, "{}", name)?,
8208            ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
8209            ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
8210            ElementId::Uuid(uuid) => write!(f, "{}", uuid)?,
8211            ElementId::Path(path) => write!(f, "{}", path.display())?,
8212            ElementId::CodeLocation(location) => write!(f, "{}", location)?,
8213            ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?,
8214            ElementId::OpaqueId(opaque_id) => write!(f, "{:x?}", opaque_id)?,
8215        }
8216
8217        Ok(())
8218    }
8219}
8220
8221impl TryInto<SharedString> for ElementId {
8222    type Error = anyhow::Error;
8223
8224    fn try_into(self) -> anyhow::Result<SharedString> {
8225        if let ElementId::Name(name) = self {
8226            Ok(name)
8227        } else {
8228            anyhow::bail!("element id is not string")
8229        }
8230    }
8231}
8232
8233impl From<u64> for ElementId {
8234    fn from(id: u64) -> Self {
8235        ElementId::Integer(id)
8236    }
8237}
8238
8239impl From<usize> for ElementId {
8240    fn from(id: usize) -> Self {
8241        ElementId::Integer(id as u64)
8242    }
8243}
8244
8245impl From<i32> for ElementId {
8246    fn from(id: i32) -> Self {
8247        Self::Integer(id as u64)
8248    }
8249}
8250
8251impl From<SharedString> for ElementId {
8252    fn from(name: SharedString) -> Self {
8253        ElementId::Name(name)
8254    }
8255}
8256
8257impl From<String> for ElementId {
8258    fn from(name: String) -> Self {
8259        ElementId::Name(name.into())
8260    }
8261}
8262
8263impl From<Arc<str>> for ElementId {
8264    fn from(name: Arc<str>) -> Self {
8265        ElementId::Name(name.into())
8266    }
8267}
8268
8269impl From<Arc<std::path::Path>> for ElementId {
8270    fn from(path: Arc<std::path::Path>) -> Self {
8271        ElementId::Path(path)
8272    }
8273}
8274
8275impl From<&'static str> for ElementId {
8276    fn from(name: &'static str) -> Self {
8277        ElementId::Name(SharedString::new_static(name))
8278    }
8279}
8280
8281impl<'a> From<&'a FocusHandle> for ElementId {
8282    fn from(handle: &'a FocusHandle) -> Self {
8283        ElementId::FocusHandle(handle.id)
8284    }
8285}
8286
8287impl From<(&'static str, EntityId)> for ElementId {
8288    fn from((name, id): (&'static str, EntityId)) -> Self {
8289        ElementId::NamedInteger(SharedString::new_static(name), id.as_u64())
8290    }
8291}
8292
8293impl From<(&'static str, usize)> for ElementId {
8294    fn from((name, id): (&'static str, usize)) -> Self {
8295        ElementId::NamedInteger(SharedString::new_static(name), id as u64)
8296    }
8297}
8298
8299impl From<(SharedString, usize)> for ElementId {
8300    fn from((name, id): (SharedString, usize)) -> Self {
8301        ElementId::NamedInteger(name, id as u64)
8302    }
8303}
8304
8305impl From<(&'static str, u64)> for ElementId {
8306    fn from((name, id): (&'static str, u64)) -> Self {
8307        ElementId::NamedInteger(SharedString::new_static(name), id)
8308    }
8309}
8310
8311impl From<Uuid> for ElementId {
8312    fn from(value: Uuid) -> Self {
8313        Self::Uuid(value)
8314    }
8315}
8316
8317impl From<(&'static str, u32)> for ElementId {
8318    fn from((name, id): (&'static str, u32)) -> Self {
8319        ElementId::NamedInteger(SharedString::new_static(name), u64::from(id))
8320    }
8321}
8322
8323impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
8324    fn from((id, name): (ElementId, T)) -> Self {
8325        ElementId::NamedChild(Arc::new(id), name.into())
8326    }
8327}
8328
8329impl From<&'static core::panic::Location<'static>> for ElementId {
8330    fn from(location: &'static core::panic::Location<'static>) -> Self {
8331        ElementId::CodeLocation(*location)
8332    }
8333}
8334
8335impl From<[u8; 20]> for ElementId {
8336    fn from(opaque_id: [u8; 20]) -> Self {
8337        ElementId::OpaqueId(opaque_id)
8338    }
8339}
8340
8341/// A rectangle to be rendered in the window at the given position and size.
8342/// Passed as an argument [`Window::paint_quad`].
8343#[derive(Clone)]
8344pub struct PaintQuad {
8345    /// The bounds of the quad within the window.
8346    pub bounds: Bounds<Pixels>,
8347    /// The radii of the quad's corners.
8348    pub corner_radii: Corners<Pixels>,
8349    /// The background color of the quad.
8350    pub background: Background,
8351    /// The widths of the quad's borders.
8352    pub border_widths: Edges<Pixels>,
8353    /// The color of the quad's borders.
8354    pub border_color: Hsla,
8355    /// The style of the quad's borders.
8356    pub border_style: BorderStyle,
8357}
8358
8359impl PaintQuad {
8360    /// Sets the corner radii of the quad.
8361    pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
8362        PaintQuad {
8363            corner_radii: corner_radii.into(),
8364            ..self
8365        }
8366    }
8367
8368    /// Sets the border widths of the quad.
8369    pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
8370        PaintQuad {
8371            border_widths: border_widths.into(),
8372            ..self
8373        }
8374    }
8375
8376    /// Sets the border color of the quad.
8377    pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
8378        PaintQuad {
8379            border_color: border_color.into(),
8380            ..self
8381        }
8382    }
8383
8384    /// Sets the background color of the quad.
8385    pub fn background(self, background: impl Into<Background>) -> Self {
8386        PaintQuad {
8387            background: background.into(),
8388            ..self
8389        }
8390    }
8391}
8392
8393/// Creates a quad with the given parameters.
8394pub fn quad(
8395    bounds: Bounds<Pixels>,
8396    corner_radii: impl Into<Corners<Pixels>>,
8397    background: impl Into<Background>,
8398    border_widths: impl Into<Edges<Pixels>>,
8399    border_color: impl Into<Hsla>,
8400    border_style: BorderStyle,
8401) -> PaintQuad {
8402    PaintQuad {
8403        bounds,
8404        corner_radii: corner_radii.into(),
8405        background: background.into(),
8406        border_widths: border_widths.into(),
8407        border_color: border_color.into(),
8408        border_style,
8409    }
8410}
8411
8412/// Creates a filled quad with the given bounds and background color.
8413pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
8414    PaintQuad {
8415        bounds: bounds.into(),
8416        corner_radii: (0.).into(),
8417        background: background.into(),
8418        border_widths: (0.).into(),
8419        border_color: transparent_black(),
8420        border_style: BorderStyle::default(),
8421    }
8422}
8423
8424/// Creates a rectangle outline with the given bounds, border color, and a 1px border width
8425pub fn outline(
8426    bounds: impl Into<Bounds<Pixels>>,
8427    border_color: impl Into<Hsla>,
8428    border_style: BorderStyle,
8429) -> PaintQuad {
8430    PaintQuad {
8431        bounds: bounds.into(),
8432        corner_radii: (0.).into(),
8433        background: transparent_black().into(),
8434        border_widths: (1.).into(),
8435        border_color: border_color.into(),
8436        border_style,
8437    }
8438}
8439
8440#[inline(never)]
8441fn with_element_arena_erased(callback: &mut dyn FnMut(&mut Arena)) -> Result<(), AccessError> {
8442    if let Some(arena_pointer) = CURRENT_ELEMENT_ARENA.try_with(Cell::get)? {
8443        // SAFETY: The pointer is valid for the duration of the draw operation
8444        // that set it, and we're being called during that same draw.
8445        let arena_cell = unsafe { &*arena_pointer };
8446        callback(&mut arena_cell.borrow_mut());
8447        Ok(())
8448    } else {
8449        ELEMENT_ARENA.try_with(|arena| callback(&mut arena.borrow_mut()))
8450    }
8451}
8452
8453#[cfg(test)]
8454mod tests {
8455    use std::{
8456        cell::{Cell, RefCell},
8457        path::PathBuf,
8458        rc::Rc,
8459        time::Duration,
8460    };
8461
8462    use crate::{
8463        AnyWindowHandle, App, AppContext as _, ArenaClearNeeded, Bounds, ContentMask, Context,
8464        Corners, CustomRenderPrimitive, DispatchPhase, DragMoveEvent, Empty, ExternalDragPayload,
8465        ExternalPaths, FileDragPaths, FileDropEvent, FocusHandle, FocusId, FramePipeline,
8466        ImportedTextureHandle, InputEvent as _, InteractiveElement as _, IntoElement,
8467        KeyDownEvent, Keystroke, LongPressEvent, MouseButton, MouseDownEvent, MouseMoveEvent,
8468        ParentElement, Pixels, PlatformInput, Point, Render, RequestFrameOptions, ScaledPixels,
8469        StandardImmediatePipeline, StatefulInteractiveElement as _, Styled, TestAppContext,
8470        TouchDragEvent, TouchEvent, TouchId, TouchPhase, Underline, UnderlineStyle, Window,
8471        WindowAppearance, WindowMetrics, WindowOptions, canvas, div, gpu_canvas, hsla, point, px,
8472        size,
8473    };
8474
8475    /// Visibility transitions reach observers exactly once each, with the new
8476    /// state already stored on the window, and never wake the platform for a
8477    /// frame: the platform requests one itself when it resumes presenting.
8478    #[gpui::test]
8479    fn test_window_visibility(cx: &mut TestAppContext) {
8480        use crate::WindowVisibility;
8481
8482        let window = cx.add_window(|_, _| EmptyView);
8483        let observed = Rc::new(RefCell::new(Vec::new()));
8484        let _subscription = window
8485            .update(cx, {
8486                let observed = observed.clone();
8487                move |_, window, _| {
8488                    assert_eq!(window.visibility(), WindowVisibility::Visible);
8489                    assert!(window.is_visible());
8490                    window.observe_window_visibility(move |visibility, window, _| {
8491                        assert_eq!(window.visibility(), visibility);
8492                        observed.borrow_mut().push(visibility);
8493                    })
8494                }
8495            })
8496            .unwrap();
8497        let test_window = cx.test_window(window.into());
8498        let frame_wake_count = test_window.frame_wake_count();
8499
8500        test_window.simulate_visibility_change(WindowVisibility::Hidden);
8501        assert_eq!(*observed.borrow(), [WindowVisibility::Hidden]);
8502        window
8503            .update(cx, |_, window, _| assert!(!window.is_visible()))
8504            .unwrap();
8505
8506        // Platforms may report the same state again; observers only see changes.
8507        test_window.simulate_visibility_change(WindowVisibility::Hidden);
8508        assert_eq!(observed.borrow().len(), 1);
8509
8510        test_window.simulate_visibility_change(WindowVisibility::Visible);
8511        assert_eq!(
8512            *observed.borrow(),
8513            [WindowVisibility::Hidden, WindowVisibility::Visible]
8514        );
8515        window
8516            .update(cx, |_, window, _| assert!(window.is_visible()))
8517            .unwrap();
8518        assert_eq!(test_window.frame_wake_count(), frame_wake_count);
8519    }
8520
8521    /// A window draws through whatever pipeline its app installs, running the
8522    /// phases in order.
8523    #[gpui::test]
8524    fn a_window_draws_through_its_frame_pipeline(cx: &mut TestAppContext) {
8525        let recorded: Rc<RefCell<Vec<&'static str>>> = Rc::new(RefCell::new(Vec::new()));
8526        let recorder = recorded.clone();
8527        cx.update(move |cx| {
8528            cx.set_frame_pipeline_factory(Rc::new(move |_| {
8529                Box::new(RecordingPipeline(recorder.clone()))
8530            }));
8531        });
8532
8533        let window = cx.add_window(|_, _| EmptyView);
8534        recorded.borrow_mut().clear();
8535        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
8536            .unwrap();
8537
8538        let phases = recorded.borrow();
8539        assert!(
8540            phases.starts_with(&[
8541                "begin_frame",
8542                "draw_roots",
8543                "finish_frame",
8544                "complete_frame",
8545                "end_frame"
8546            ]),
8547            "frame ran {phases:?}"
8548        );
8549    }
8550
8551    /// Records the phases it is asked to run, then delegates to the standard
8552    /// implementation of each one.
8553    struct RecordingPipeline(Rc<RefCell<Vec<&'static str>>>);
8554
8555    impl FramePipeline for RecordingPipeline {
8556        fn begin_frame(&mut self, window: &mut Window, cx: &mut App) {
8557            self.0.borrow_mut().push("begin_frame");
8558            window.begin_frame(cx);
8559        }
8560
8561        fn draw_roots(&mut self, window: &mut Window, cx: &mut App) {
8562            self.0.borrow_mut().push("draw_roots");
8563            window.draw_roots(cx);
8564        }
8565
8566        fn finish_frame(&mut self, window: &mut Window, cx: &mut App) {
8567            self.0.borrow_mut().push("finish_frame");
8568            window.finish_frame(cx);
8569        }
8570
8571        fn complete_frame(&mut self, window: &mut Window, cx: &mut App) -> Option<FocusId> {
8572            self.0.borrow_mut().push("complete_frame");
8573            window.complete_frame(cx)
8574        }
8575
8576        fn end_frame(
8577            &mut self,
8578            window: &mut Window,
8579            cx: &mut App,
8580            focus_before_listeners: Option<FocusId>,
8581        ) {
8582            self.0.borrow_mut().push("end_frame");
8583            window.end_frame(cx, focus_before_listeners);
8584        }
8585    }
8586
8587    /// A frame that skips drawing its roots goes straight from opening the frame
8588    /// to finishing it, without running the root passes.
8589    #[gpui::test]
8590    fn a_frame_that_skips_drawing_still_completes(cx: &mut TestAppContext) {
8591        cx.skip_drawing();
8592        let window = cx.add_window(|_, _| EmptyView);
8593
8594        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
8595            .unwrap();
8596    }
8597
8598    /// The passes have to run in order: one that is skipped is reported, rather
8599    /// than leaving the frame half-built.
8600    #[cfg(debug_assertions)]
8601    #[gpui::test]
8602    #[should_panic(expected = "paint_roots ran while the frame was Evaluated")]
8603    fn a_frame_pass_out_of_order_is_rejected(cx: &mut TestAppContext) {
8604        let window = cx.add_window(|_, _| EmptyView);
8605
8606        cx.update_window(window.into(), |_, window, cx| {
8607            window.begin_frame(cx);
8608            let roots = window.evaluate_roots(cx);
8609            // Laying the roots out is what registers their hitboxes, so painting
8610            // them now has nothing to paint.
8611            window.paint_roots(roots, cx);
8612        })
8613        .unwrap();
8614    }
8615
8616    /// Counts the frames it renders, and defers them when told to.
8617    struct PacingPipeline {
8618        frames: Rc<Cell<usize>>,
8619        asks: Rc<Cell<usize>>,
8620        allow: bool,
8621    }
8622
8623    impl FramePipeline for PacingPipeline {
8624        fn should_render(&mut self, is_dirty: bool, _metrics: &WindowMetrics) -> bool {
8625            self.asks.set(self.asks.get() + 1);
8626            self.allow && is_dirty
8627        }
8628
8629        fn draw(&mut self, window: &mut Window, cx: &mut App) -> ArenaClearNeeded {
8630            self.frames.set(self.frames.get() + 1);
8631            FramePipeline::draw(&mut StandardImmediatePipeline, window, cx)
8632        }
8633    }
8634
8635    /// Installs a [`PacingPipeline`] over the app's windows.
8636    fn install_pacing_pipeline(
8637        cx: &mut TestAppContext,
8638        frames: Rc<Cell<usize>>,
8639        asks: Rc<Cell<usize>>,
8640        allow: bool,
8641    ) {
8642        cx.update(move |cx| {
8643            cx.set_frame_pipeline_factory(Rc::new(move |_| {
8644                Box::new(PacingPipeline {
8645                    frames: frames.clone(),
8646                    asks: asks.clone(),
8647                    allow,
8648                })
8649            }));
8650        });
8651    }
8652
8653    /// A pipeline that defers a frame stops it before any of its work starts.
8654    #[gpui::test]
8655    fn a_pipeline_can_defer_a_frame(cx: &mut TestAppContext) {
8656        let frames = Rc::new(Cell::new(0));
8657        let asks = Rc::new(Cell::new(0));
8658        install_pacing_pipeline(cx, frames.clone(), asks.clone(), false);
8659        let window = cx.add_window(|_, _| EmptyView);
8660        let test_window = cx.test_window(window.into());
8661        frames.set(0);
8662        asks.set(0);
8663
8664        window.update(cx, |_, _, cx| cx.notify()).unwrap();
8665        test_window.simulate_frame_request(RequestFrameOptions::default());
8666
8667        assert!(asks.get() > 0, "the pipeline was asked about the frame");
8668        assert_eq!(frames.get(), 0, "the deferred frame was never drawn");
8669    }
8670
8671    /// The same window draws once the pipeline allows the frame.
8672    #[gpui::test]
8673    fn a_pipeline_can_allow_a_frame(cx: &mut TestAppContext) {
8674        let frames = Rc::new(Cell::new(0));
8675        let asks = Rc::new(Cell::new(0));
8676        install_pacing_pipeline(cx, frames.clone(), asks, true);
8677        let window = cx.add_window(|_, _| EmptyView);
8678        frames.set(0);
8679
8680        window.update(cx, |_, _, cx| cx.notify()).unwrap();
8681
8682        assert!(frames.get() > 0, "the allowed frame was drawn");
8683    }
8684
8685    #[gpui::test]
8686    fn test_fully_visible_bounds_preserve_layout_viewport(cx: &mut TestAppContext) {
8687        let window = cx.add_window(|_, _| EmptyView);
8688        let mut platform_window = cx.test_window(window.into());
8689        platform_window.simulate_resize(size(px(400.), px(800.)));
8690        window
8691            .update(cx, |_, window, _| {
8692                assert_eq!(
8693                    window.visual_viewport_bounds(),
8694                    Bounds::new(Point::default(), size(px(400.), px(800.)))
8695                );
8696                assert_eq!(
8697                    window.fully_visible_bounds(),
8698                    window.visual_viewport_bounds()
8699                );
8700            })
8701            .unwrap();
8702
8703        platform_window.simulate_frame_request(RequestFrameOptions::default());
8704        let wakes = platform_window.frame_wake_count();
8705        let visual_bounds = Bounds::new(point(px(10.), px(40.)), size(px(380.), px(460.)));
8706        platform_window.simulate_visual_viewport_change(visual_bounds);
8707        assert!(platform_window.frame_wake_count() > wakes);
8708        platform_window.simulate_frame_request(RequestFrameOptions::default());
8709        let wakes = platform_window.frame_wake_count();
8710        platform_window.simulate_insets_change(crate::WindowInsets {
8711            safe_area: crate::Edges {
8712                top: px(60.),
8713                right: px(20.),
8714                bottom: px(30.),
8715                left: px(-10.),
8716            },
8717            ime: crate::Edges {
8718                bottom: px(350.),
8719                ..Default::default()
8720            },
8721        });
8722        assert!(platform_window.frame_wake_count() > wakes);
8723        window
8724            .update(cx, |_, window, _| {
8725                assert_eq!(window.viewport_size(), size(px(400.), px(800.)));
8726                assert_eq!(window.visual_viewport_bounds(), visual_bounds);
8727                assert_eq!(
8728                    window.fully_visible_bounds(),
8729                    Bounds::new(point(px(10.), px(60.)), size(px(370.), px(390.)))
8730                );
8731                window.request_virtual_keyboard();
8732                window.dismiss_virtual_keyboard();
8733                assert_eq!(window.viewport_size(), size(px(400.), px(800.)));
8734            })
8735            .unwrap();
8736        assert_eq!(platform_window.virtual_keyboard_requests(), 1);
8737        assert_eq!(platform_window.virtual_keyboard_dismissals(), 1);
8738
8739        platform_window.simulate_insets_change(crate::WindowInsets {
8740            safe_area: crate::Edges {
8741                top: px(900.),
8742                left: px(500.),
8743                ..Default::default()
8744            },
8745            ..Default::default()
8746        });
8747        window
8748            .update(cx, |_, window, _| {
8749                assert_eq!(
8750                    window.fully_visible_bounds().size,
8751                    size(Pixels::ZERO, Pixels::ZERO)
8752                );
8753            })
8754            .unwrap();
8755    }
8756
8757    struct EmptyView;
8758
8759    impl Render for EmptyView {
8760        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
8761            div()
8762        }
8763    }
8764
8765    struct OpensWindowOnPaint {
8766        opened: Rc<Cell<bool>>,
8767    }
8768
8769    impl Render for OpensWindowOnPaint {
8770        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
8771            let opened = self.opened.clone();
8772            div()
8773                .size_full()
8774                .child(canvas(
8775                    |_, _, _| {},
8776                    move |_, _, _window, cx| {
8777                        if !opened.replace(true) {
8778                            cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| EmptyView))
8779                                .unwrap();
8780                        }
8781                    },
8782                ))
8783                // Siblings painted after the canvas: their elements were
8784                // allocated in the arena before the nested draw, so they detect
8785                // a mid-draw arena clear when painted afterwards.
8786                .child(div().child("after"))
8787        }
8788    }
8789
8790    /// Opening a window synchronously draws it and requests an element arena
8791    /// clear. When that happens from within another window's draw (here: from
8792    /// an element's paint), the clear must be deferred until the outer draw
8793    /// finishes, or the outer draw's arena-allocated elements would be freed
8794    /// out from under it.
8795    #[test]
8796    fn test_window_opened_during_draw_defers_arena_clear() {
8797        let mut cx = TestAppContext::single();
8798
8799        let opened = Rc::new(Cell::new(false));
8800        // add_window draws once, which runs the nested open_window mid-draw.
8801        let window = cx.add_window({
8802            let opened = opened.clone();
8803            move |_, _| OpensWindowOnPaint { opened }
8804        });
8805
8806        assert!(opened.get());
8807        assert_eq!(cx.windows().len(), 2);
8808
8809        // The deferred clear must actually run once the outer draw unwinds:
8810        // subsequent draws of both windows work against a fresh arena.
8811        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
8812            .unwrap();
8813    }
8814
8815    #[test]
8816    fn test_scale_factor_change_preserves_bounds_and_survives_resize() {
8817        let mut cx = TestAppContext::single();
8818        let window = cx.add_window(|_, _| EmptyView);
8819        let handle: AnyWindowHandle = window.into();
8820        let window_state = |cx: &mut TestAppContext| {
8821            cx.update_window(handle, |_, window, _| {
8822                (
8823                    window.scale_factor(),
8824                    window.bounds(),
8825                    window.viewport_size(),
8826                )
8827            })
8828            .unwrap()
8829        };
8830
8831        let (scale_factor, mut expected_bounds, _) = window_state(&mut cx);
8832        assert_eq!(scale_factor, 2.0);
8833
8834        for (scale_factor, resized_size) in [
8835            (1.0, size(px(800.), px(600.))),
8836            (1.25, size(px(640.), px(480.))),
8837            (2.0, size(px(1024.), px(768.))),
8838        ] {
8839            cx.simulate_window_scale_factor_change(handle, scale_factor);
8840            assert_eq!(
8841                window_state(&mut cx),
8842                (scale_factor, expected_bounds, expected_bounds.size)
8843            );
8844
8845            cx.simulate_window_resize(handle, resized_size);
8846            expected_bounds.size = resized_size;
8847            assert_eq!(
8848                window_state(&mut cx),
8849                (scale_factor, expected_bounds, resized_size)
8850            );
8851        }
8852    }
8853
8854    #[gpui::test]
8855    fn metrics_handle_agrees_with_the_window_and_tracks_resizes(cx: &mut TestAppContext) {
8856        let window = cx.add_window(|_, _| EmptyView);
8857        let handle: AnyWindowHandle = window.into();
8858
8859        let metrics = cx.read(|app| handle.metrics(app).expect("window is open"));
8860        assert_eq!(metrics.id(), handle.window_id());
8861        assert!(metrics.display_id().is_some());
8862
8863        // Every field of the snapshot agrees with the window it was sampled from.
8864        let window_state = |cx: &mut TestAppContext| {
8865            cx.update_window(handle, |_, window, _| {
8866                assert_eq!(metrics.bounds(), window.bounds());
8867                assert_eq!(metrics.viewport(), window.visual_viewport_bounds());
8868                assert_eq!(metrics.content_size(), window.viewport_size());
8869                assert_eq!(metrics.scale_factor(), window.scale_factor());
8870                assert_eq!(metrics.is_active(), window.is_window_active());
8871                assert_eq!(metrics.is_fullscreen(), window.is_fullscreen());
8872            })
8873            .unwrap();
8874        };
8875        window_state(cx);
8876
8877        cx.simulate_window_resize(handle, size(px(800.), px(600.)));
8878        cx.simulate_window_scale_factor_change(handle, 1.25);
8879
8880        // The snapshot is shared with the window, so a handle obtained before
8881        // the change observes it.
8882        assert_eq!(metrics.content_size(), size(px(800.), px(600.)));
8883        assert_eq!(metrics.scale_factor(), 1.25);
8884        window_state(cx);
8885    }
8886
8887    /// Geometry the platform changes without resizing the window reaches the
8888    /// snapshot too. The visual viewport only marks the window dirty, so the
8889    /// draw that follows the update is what publishes it.
8890    #[gpui::test]
8891    fn metrics_track_viewport_changes_that_do_not_resize(cx: &mut TestAppContext) {
8892        let window = cx.add_window(|_, _| EmptyView);
8893        let handle: AnyWindowHandle = window.into();
8894        let metrics = cx.read(|app| handle.metrics(app).expect("window is open"));
8895
8896        let narrow = Bounds::new(point(px(0.), px(120.)), size(px(400.), px(680.)));
8897        assert_ne!(metrics.viewport(), narrow);
8898
8899        cx.simulate_window_visual_viewport_change(handle, narrow);
8900        assert_eq!(metrics.viewport(), narrow);
8901
8902        cx.update_window(handle, |_, window, _| {
8903            assert_eq!(metrics.viewport(), window.visual_viewport_bounds());
8904            // Shrinking the visual viewport leaves the layout size alone.
8905            assert_eq!(metrics.content_size(), window.viewport_size());
8906        })
8907        .unwrap();
8908    }
8909
8910    /// A window cannot be updated from within its own update. Callers that
8911    /// reach for a window from inside a frame land here, and they get an error
8912    /// rather than a panic or a second borrow of the same host.
8913    #[gpui::test]
8914    fn updating_a_window_from_within_its_own_update_reports_an_error(cx: &mut TestAppContext) {
8915        let window = cx.add_window(|_, _| EmptyView);
8916        let handle: AnyWindowHandle = window.into();
8917
8918        let nested_error = cx
8919            .update_window(handle, |_, _window, cx| {
8920                cx.update_window(handle, |_, _, _| ())
8921                    .map_err(|error| error.to_string())
8922                    .unwrap_err()
8923            })
8924            .expect("the outer update completes");
8925
8926        assert!(
8927            nested_error.contains("already being updated"),
8928            "unexpected error: {nested_error}"
8929        );
8930    }
8931
8932    /// Updating one window while another's update is in progress is fine, which
8933    /// is what a paint that opens a window relies on.
8934    #[gpui::test]
8935    fn a_window_can_be_updated_from_within_another_windows_update(cx: &mut TestAppContext) {
8936        let first: AnyWindowHandle = cx.add_window(|_, _| EmptyView).into();
8937        let second: AnyWindowHandle = cx.add_window(|_, _| EmptyView).into();
8938
8939        let expected = cx
8940            .update_window(second, |_, window, _| window.viewport_size())
8941            .expect("the window can be updated on its own");
8942
8943        let from_inner = cx
8944            .update_window(first, |_, _window, cx| {
8945                cx.update_window(second, |_, window, _| window.viewport_size())
8946                    .expect("the inner update succeeds")
8947            })
8948            .expect("the outer update completes");
8949
8950        assert_eq!(from_inner, expected);
8951    }
8952
8953    /// The handle borrows nothing from the window, so it can be read off the UI
8954    /// thread while the window is otherwise occupied.
8955    #[gpui::test]
8956    fn metrics_handle_is_readable_from_another_thread(cx: &mut TestAppContext) {
8957        let window = cx.add_window(|_, _| EmptyView);
8958        let handle: AnyWindowHandle = window.into();
8959        cx.simulate_window_resize(handle, size(px(640.), px(480.)));
8960        let metrics = cx.read(|app| handle.metrics(app).expect("window is open"));
8961
8962        let (id, content_size, scale_factor) = std::thread::spawn(move || {
8963            (metrics.id(), metrics.content_size(), metrics.scale_factor())
8964        })
8965        .join()
8966        .expect("the metrics reader did not panic");
8967
8968        assert_eq!(id, handle.window_id());
8969        assert_eq!(content_size, size(px(640.), px(480.)));
8970        assert_eq!(scale_factor, 2.0);
8971    }
8972
8973    /// Platforms that stop requesting frames for idle windows (currently web)
8974    /// rely on the frame waker firing whenever frame demand arises; a demand
8975    /// source that skips the waker shows up there as a window that silently
8976    /// stops repainting until unrelated activity wakes it.
8977    #[gpui::test]
8978    fn test_frame_waker_fires_on_frame_demand(cx: &mut TestAppContext) {
8979        let window = cx.add_window(|_, _| EmptyView);
8980        let test_window = cx.test_window(window.into());
8981
8982        // Windows start dirty, and that can predate waker installation;
8983        // installing the waker must deliver the pending wake or the first
8984        // frame would never be requested.
8985        assert!(
8986            test_window.frame_wake_count() >= 1,
8987            "opening a window must wake the frame source for the initial frame"
8988        );
8989
8990        // Serve outstanding demand (present the frame drawn by `add_window`).
8991        test_window.simulate_frame_request(RequestFrameOptions::default());
8992
8993        // An idle window must not wake on clean frames or plain updates, or
8994        // the frame source could never stop.
8995        let baseline = test_window.frame_wake_count();
8996        test_window.simulate_frame_request(RequestFrameOptions::default());
8997        window.update(cx, |_, _, _| {}).unwrap();
8998        assert_eq!(
8999            test_window.frame_wake_count(),
9000            baseline,
9001            "clean frames and non-notifying updates must not wake the frame source"
9002        );
9003
9004        // Notifying a view in an idle window is the core demand signal.
9005        window.update(cx, |_, _, cx| cx.notify()).unwrap();
9006        assert!(
9007            test_window.frame_wake_count() > baseline,
9008            "notifying a view in an idle window must wake the frame source"
9009        );
9010
9011        // Serving that demand returns to idle without further wakes.
9012        test_window.simulate_frame_request(RequestFrameOptions::default());
9013        let baseline = test_window.frame_wake_count();
9014        test_window.simulate_frame_request(RequestFrameOptions::default());
9015        assert_eq!(
9016            test_window.frame_wake_count(),
9017            baseline,
9018            "serving demand must return the window to idle"
9019        );
9020
9021        // Next-frame callbacks create demand without dirtying the window.
9022        window
9023            .update(cx, |_, window, _| window.on_next_frame(|_, _| {}))
9024            .unwrap();
9025        assert!(
9026            test_window.frame_wake_count() > baseline,
9027            "scheduling a next-frame callback in an idle window must wake the frame source"
9028        );
9029    }
9030
9031    /// A frame request that arrives while next-frame callbacks are pending
9032    /// must never strand them: either the frame runs them, or (when the
9033    /// inactive-window frame-rate throttle defers the frame) the waker fires
9034    /// so another request is delivered.
9035    #[gpui::test]
9036    fn test_pending_next_frame_callbacks_are_not_stranded(cx: &mut TestAppContext) {
9037        let window = cx.add_window(|_, _| EmptyView);
9038        let test_window = cx.test_window(window.into());
9039        // Establish a recent last-frame time so the inactive-window throttle
9040        // can engage on the next request.
9041        test_window.simulate_frame_request(RequestFrameOptions::default());
9042
9043        let callback_ran = Rc::new(Cell::new(false));
9044        window
9045            .update(cx, {
9046                let callback_ran = callback_ran.clone();
9047                move |_, window, _| {
9048                    window.on_next_frame(move |_, _| callback_ran.set(true));
9049                }
9050            })
9051            .unwrap();
9052
9053        let baseline = test_window.frame_wake_count();
9054        test_window.simulate_frame_request(RequestFrameOptions::default());
9055        // The test window is inactive, so this request throttles to ~30fps
9056        // when it lands within the throttle interval of the previous frame
9057        // (the common case here, but timing-dependent): the callback is
9058        // deferred and the waker must re-arm the frame source. On a slow run
9059        // the request instead lands outside the interval and runs the
9060        // callback directly.
9061        assert!(
9062            test_window.frame_wake_count() > baseline || callback_ran.get(),
9063            "a frame request with pending next-frame callbacks must either run them or re-arm the frame source"
9064        );
9065    }
9066
9067    #[gpui::test]
9068    fn test_window_reports_no_raw_handle_instead_of_panicking(cx: &mut TestAppContext) {
9069        use raw_window_handle::{HandleError, HasDisplayHandle as _, HasWindowHandle as _};
9070
9071        let window = cx.add_window(|_, _| EmptyView);
9072        window
9073            .update(cx, |_, window, _| {
9074                assert!(matches!(
9075                    window.window_handle(),
9076                    Err(HandleError::NotSupported)
9077                ));
9078                assert!(matches!(
9079                    window.display_handle(),
9080                    Err(HandleError::NotSupported)
9081                ));
9082            })
9083            .unwrap();
9084    }
9085
9086    #[gpui::test]
9087    fn test_appearance_change_runs_after_app_update(cx: &mut TestAppContext) {
9088        let window = cx.add_window(|_, _| EmptyView);
9089        let observed_appearance = Rc::new(Cell::new(None));
9090        let _subscription = window
9091            .update(cx, {
9092                let observed_appearance = observed_appearance.clone();
9093                move |_, window, _| {
9094                    window.observe_window_appearance(move |window, _| {
9095                        observed_appearance.set(Some(window.appearance()));
9096                    })
9097                }
9098            })
9099            .unwrap();
9100        let test_window = cx.test_window(window.into());
9101
9102        cx.update(|_| {
9103            test_window.simulate_appearance_change(WindowAppearance::Dark);
9104            assert_eq!(observed_appearance.get(), None);
9105        });
9106        cx.run_until_parked();
9107
9108        assert_eq!(observed_appearance.get(), Some(WindowAppearance::Dark));
9109    }
9110
9111    #[gpui::test]
9112    fn queued_frame_callback_wakes_a_parked_render_loop(cx: &mut TestAppContext) {
9113        let window = cx.add_window(|_, _| Empty);
9114        let test_window = cx.test_window(window.into());
9115
9116        assert!(test_window.simulate_scheduled_frame());
9117        assert!(test_window.simulate_scheduled_frame());
9118        assert!(!test_window.frame_scheduled());
9119
9120        cx.update_window(window.into(), |_, window, _| {
9121            window.core.active.set(true);
9122            window.on_next_frame(|_, _| {});
9123        })
9124        .unwrap();
9125        assert!(
9126            test_window.frame_scheduled(),
9127            "queuing work on a parked window must wake the render loop"
9128        );
9129
9130        assert!(test_window.simulate_scheduled_frame());
9131        assert!(
9132            test_window.frame_scheduled(),
9133            "presenting the frame must await one compositor callback"
9134        );
9135        assert!(test_window.simulate_scheduled_frame());
9136        assert!(!test_window.frame_scheduled());
9137    }
9138
9139    #[gpui::test]
9140    fn pending_presentation_wakes_a_parked_render_loop(cx: &mut TestAppContext) {
9141        let window = cx.add_window(|_, _| Empty);
9142        let test_window = cx.test_window(window.into());
9143
9144        assert!(test_window.simulate_scheduled_frame());
9145        assert!(test_window.simulate_scheduled_frame());
9146        assert!(!test_window.frame_scheduled());
9147
9148        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
9149            .unwrap();
9150
9151        assert!(
9152            test_window.frame_scheduled(),
9153            "a rendered scene awaiting presentation must wake the render loop"
9154        );
9155    }
9156
9157    #[gpui::test]
9158    fn callback_queued_during_a_frame_requests_a_follow_up(cx: &mut TestAppContext) {
9159        let window = cx.add_window(|_, _| Empty);
9160        let test_window = cx.test_window(window.into());
9161
9162        let callback_ran = Rc::new(Cell::new(false));
9163        cx.update_window(window.into(), |_, window, _| {
9164            // Inactive windows are frame-rate throttled, which would defer the
9165            // ticks this test drives manually.
9166            window.core.active.set(true);
9167            let callback_ran = callback_ran.clone();
9168            window.on_next_frame(move |window, _| {
9169                window.on_next_frame(move |_, _| callback_ran.set(true));
9170            });
9171        })
9172        .unwrap();
9173
9174        assert!(test_window.simulate_scheduled_frame());
9175        assert!(!callback_ran.get());
9176        assert!(
9177            test_window.frame_scheduled(),
9178            "a callback queued mid-frame must schedule a follow-up before the loop parks"
9179        );
9180
9181        assert!(test_window.simulate_scheduled_frame());
9182        assert!(callback_ran.get());
9183    }
9184
9185    struct RootView {
9186        explicit_size: bool,
9187        child_bounds: Rc<Cell<Bounds<Pixels>>>,
9188    }
9189
9190    impl Render for RootView {
9191        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
9192            let child_bounds = self.child_bounds.clone();
9193            let root = div().flex().flex_col().child(
9194                canvas(
9195                    move |bounds, _, _| child_bounds.set(bounds),
9196                    |_, _, _, _| {},
9197                )
9198                .size_full(),
9199            );
9200            if self.explicit_size {
9201                root.w(px(300.)).h(px(200.))
9202            } else {
9203                root
9204            }
9205        }
9206    }
9207
9208    #[test]
9209    fn auto_sized_window_root_fills_the_window() {
9210        let mut cx = TestAppContext::single();
9211        let child_bounds = Rc::new(Cell::new(Bounds::default()));
9212        let window = cx.add_window({
9213            let child_bounds = child_bounds.clone();
9214            move |_, _| RootView {
9215                explicit_size: false,
9216                child_bounds,
9217            }
9218        });
9219
9220        let viewport_size = cx
9221            .update_window(window.into(), |_, window, cx| {
9222                window.draw(cx).clear(cx);
9223                window.viewport_size()
9224            })
9225            .unwrap();
9226
9227        assert_eq!(child_bounds.get().size, viewport_size);
9228    }
9229
9230    #[test]
9231    fn explicitly_sized_window_root_keeps_its_size() {
9232        let mut cx = TestAppContext::single();
9233        let child_bounds = Rc::new(Cell::new(Bounds::default()));
9234        let window = cx.add_window({
9235            let child_bounds = child_bounds.clone();
9236            move |_, _| RootView {
9237                explicit_size: true,
9238                child_bounds,
9239            }
9240        });
9241
9242        cx.update_window(window.into(), |_, window, cx| {
9243            window.draw(cx).clear(cx);
9244        })
9245        .unwrap();
9246
9247        assert_eq!(child_bounds.get().size, size(px(300.), px(200.)));
9248    }
9249
9250    struct FileDragView {
9251        path: PathBuf,
9252        observed_drag_moves: Rc<RefCell<Vec<Point<Pixels>>>>,
9253        observed_drops: Rc<RefCell<Vec<PathBuf>>>,
9254    }
9255
9256    struct FileDropExitView(Rc<Cell<usize>>);
9257
9258    impl Render for FileDropExitView {
9259        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
9260            div().size_full().on_file_drop_exit({
9261                let observed_file_drop_exit = self.0.clone();
9262                move |_, _, _| observed_file_drop_exit.set(observed_file_drop_exit.get() + 1)
9263            })
9264        }
9265    }
9266
9267    impl Render for FileDragView {
9268        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
9269            div()
9270                .id("file-drag")
9271                .size_full()
9272                .on_drag(self.path.clone(), |_, _, _, cx| cx.new(|_| Empty))
9273                .external_drag_payload(|path: &PathBuf, _, _| {
9274                    Some(ExternalDragPayload::Files(FileDragPaths::new([(
9275                        path.clone(),
9276                        true,
9277                    )])))
9278                })
9279                .on_drag_move({
9280                    let observed_drag_moves = self.observed_drag_moves.clone();
9281                    move |event: &DragMoveEvent<PathBuf>, _, _| {
9282                        observed_drag_moves.borrow_mut().push(event.event.position);
9283                    }
9284                })
9285                .on_drop({
9286                    let observed_drops = self.observed_drops.clone();
9287                    move |path: &PathBuf, _, _| observed_drops.borrow_mut().push(path.clone())
9288                })
9289        }
9290    }
9291
9292    #[gpui::test]
9293    fn file_drag_is_promoted_once_and_restored_in_source_window(cx: &mut TestAppContext) {
9294        struct Drag {
9295            window: AnyWindowHandle,
9296            observed_drag_moves: Rc<RefCell<Vec<Point<Pixels>>>>,
9297            observed_drops: Rc<RefCell<Vec<PathBuf>>>,
9298        }
9299
9300        fn start_drag(cx: &mut TestAppContext, path: PathBuf, platform_result: bool) -> Drag {
9301            let observed_drag_moves = Rc::new(RefCell::new(Vec::new()));
9302            let observed_drops = Rc::new(RefCell::new(Vec::new()));
9303            let window: AnyWindowHandle = cx
9304                .add_window({
9305                    let observed_drag_moves = observed_drag_moves.clone();
9306                    let observed_drops = observed_drops.clone();
9307                    move |_, _| FileDragView {
9308                        path,
9309                        observed_drag_moves,
9310                        observed_drops,
9311                    }
9312                })
9313                .into();
9314            cx.test_window(window)
9315                .set_start_external_drag_result(platform_result);
9316
9317            let update_result = cx.update_window(window, |_, window, cx| {
9318                window.draw(cx).clear(cx);
9319                window.dispatch_event(
9320                    MouseDownEvent {
9321                        position: point(px(10.), px(10.)),
9322                        button: MouseButton::Left,
9323                        modifiers: Default::default(),
9324                        click_count: 1,
9325                        first_mouse: false,
9326                    }
9327                    .to_platform_input(),
9328                    cx,
9329                );
9330                window.dispatch_event(
9331                    MouseMoveEvent {
9332                        position: point(px(20.), px(20.)),
9333                        pressed_button: Some(MouseButton::Left),
9334                        modifiers: Default::default(),
9335                    }
9336                    .to_platform_input(),
9337                    cx,
9338                );
9339                assert!(cx.active_drag.is_some());
9340            });
9341            assert!(
9342                update_result.is_ok(),
9343                "failed to start drag: {update_result:?}"
9344            );
9345
9346            assert!(cx.test_window(window).external_drag_files().is_empty());
9347            Drag {
9348                window,
9349                observed_drag_moves,
9350                observed_drops,
9351            }
9352        }
9353
9354        let successful_path = PathBuf::from("/tmp/successful-drag");
9355        let successful = start_drag(cx, successful_path.clone(), true);
9356        let outside_position = point(px(-1.), px(20.));
9357        let update_result = cx.update_window(successful.window, |_, window, cx| {
9358            window.dispatch_event(
9359                MouseMoveEvent {
9360                    position: outside_position,
9361                    pressed_button: Some(MouseButton::Left),
9362                    modifiers: Default::default(),
9363                }
9364                .to_platform_input(),
9365                cx,
9366            );
9367            assert!(cx.active_drag.is_none());
9368        });
9369        assert!(
9370            update_result.is_ok(),
9371            "failed to promote drag: {update_result:?}"
9372        );
9373        assert_eq!(
9374            cx.test_window(successful.window).external_drag_files(),
9375            [(successful_path.clone(), true)]
9376        );
9377        // Views must still see the move that leaves the window, otherwise they never learn to tear
9378        // down the drag state they built up while the pointer was inside.
9379        assert_eq!(
9380            successful.observed_drag_moves.borrow().last(),
9381            Some(&outside_position)
9382        );
9383
9384        let first_destination_exit_count = Rc::new(Cell::new(0));
9385        let first_destination: AnyWindowHandle = cx
9386            .add_window({
9387                let first_destination_exit_count = first_destination_exit_count.clone();
9388                move |_, _| FileDropExitView(first_destination_exit_count)
9389            })
9390            .into();
9391        let second_destination_exit_count = Rc::new(Cell::new(0));
9392        let second_destination: AnyWindowHandle = cx
9393            .add_window({
9394                let second_destination_exit_count = second_destination_exit_count.clone();
9395                move |_, _| FileDropExitView(second_destination_exit_count)
9396            })
9397            .into();
9398        let reentry_position = point(px(30.), px(30.));
9399        let external_paths = || ExternalPaths([successful_path.clone()].into_iter().collect());
9400        let update_result = cx.update_window(first_destination, |_, window, cx| {
9401            window.draw(cx).clear(cx);
9402            window.dispatch_event(
9403                FileDropEvent::Entered {
9404                    position: reentry_position,
9405                    paths: external_paths(),
9406                }
9407                .to_platform_input(),
9408                cx,
9409            );
9410            assert!(
9411                cx.active_drag
9412                    .as_ref()
9413                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
9414            );
9415            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
9416            assert!(cx.active_drag.is_none());
9417            assert_eq!(first_destination_exit_count.get(), 1);
9418            assert_eq!(second_destination_exit_count.get(), 0);
9419        });
9420        assert!(
9421            update_result.is_ok(),
9422            "failed to handle drag in first destination window: {update_result:?}"
9423        );
9424
9425        let update_result = cx.update_window(second_destination, |_, window, cx| {
9426            window.draw(cx).clear(cx);
9427            window.dispatch_event(
9428                PlatformInput::KeyDown(KeyDownEvent {
9429                    keystroke: Keystroke::parse("down").expect("valid keystroke"),
9430                    is_held: false,
9431                    prefer_character_input: false,
9432                }),
9433                cx,
9434            );
9435            window.dispatch_event(
9436                FileDropEvent::Entered {
9437                    position: reentry_position,
9438                    paths: external_paths(),
9439                }
9440                .to_platform_input(),
9441                cx,
9442            );
9443            assert!(
9444                cx.active_drag
9445                    .as_ref()
9446                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
9447            );
9448            assert_eq!(first_destination_exit_count.get(), 1);
9449            assert_eq!(second_destination_exit_count.get(), 0);
9450
9451            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
9452            assert!(cx.active_drag.is_none());
9453            assert_eq!(first_destination_exit_count.get(), 1);
9454            assert_eq!(second_destination_exit_count.get(), 1);
9455        });
9456        assert!(
9457            update_result.is_ok(),
9458            "failed to handle drag in second destination window: {update_result:?}"
9459        );
9460
9461        let update_result = cx.update_window(successful.window, |_, window, cx| {
9462            window.dispatch_event(
9463                FileDropEvent::Entered {
9464                    position: reentry_position,
9465                    paths: external_paths(),
9466                }
9467                .to_platform_input(),
9468                cx,
9469            );
9470            assert!(
9471                cx.active_drag
9472                    .as_ref()
9473                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
9474            );
9475            assert_eq!(
9476                successful.observed_drag_moves.borrow().last(),
9477                Some(&reentry_position)
9478            );
9479
9480            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
9481            assert!(cx.active_drag.is_none());
9482
9483            window.dispatch_event(
9484                FileDropEvent::Entered {
9485                    position: reentry_position,
9486                    paths: external_paths(),
9487                }
9488                .to_platform_input(),
9489                cx,
9490            );
9491            assert!(
9492                cx.active_drag
9493                    .as_ref()
9494                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
9495            );
9496
9497            window.dispatch_event(
9498                FileDropEvent::Submit {
9499                    position: reentry_position,
9500                }
9501                .to_platform_input(),
9502                cx,
9503            );
9504            assert_eq!(
9505                successful.observed_drops.borrow().as_slice(),
9506                std::slice::from_ref(&successful_path)
9507            );
9508            assert!(cx.active_drag.is_none());
9509
9510            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
9511            assert!(cx.active_drag.is_none());
9512            window.dispatch_event(FileDropEvent::Ended.to_platform_input(), cx);
9513            assert!(cx.active_drag.is_none());
9514
9515            window.dispatch_event(
9516                FileDropEvent::Entered {
9517                    position: reentry_position,
9518                    paths: external_paths(),
9519                }
9520                .to_platform_input(),
9521                cx,
9522            );
9523            assert!(
9524                cx.active_drag
9525                    .as_ref()
9526                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
9527            );
9528            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
9529        });
9530        assert!(
9531            update_result.is_ok(),
9532            "failed to restore drag in source window: {update_result:?}"
9533        );
9534
9535        let cancelled_path = PathBuf::from("/tmp/cancelled-drag");
9536        let cancelled = start_drag(cx, cancelled_path.clone(), true);
9537        let update_result = cx.update_window(cancelled.window, |_, window, cx| {
9538            window.dispatch_event(
9539                MouseMoveEvent {
9540                    position: outside_position,
9541                    pressed_button: Some(MouseButton::Left),
9542                    modifiers: Default::default(),
9543                }
9544                .to_platform_input(),
9545                cx,
9546            );
9547            assert!(cx.active_drag.is_none());
9548
9549            window.dispatch_event(
9550                FileDropEvent::Entered {
9551                    position: reentry_position,
9552                    paths: ExternalPaths([cancelled_path].into_iter().collect()),
9553                }
9554                .to_platform_input(),
9555                cx,
9556            );
9557            assert!(
9558                cx.active_drag
9559                    .as_ref()
9560                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
9561            );
9562            assert!(cx.stop_active_drag(window));
9563            assert!(cx.active_drag.is_none());
9564        });
9565        assert!(
9566            update_result.is_ok(),
9567            "failed to cancel restored drag: {update_result:?}"
9568        );
9569        assert!(!cx.update(|cx| cx.end_platform_drag(cancelled.window.window_id())));
9570
9571        let removed_path = PathBuf::from("/tmp/removed-window-drag");
9572        let removed = start_drag(cx, removed_path, true);
9573        let removed_window_id = removed.window.window_id();
9574        let update_result = cx.update_window(removed.window, |_, window, cx| {
9575            window.dispatch_event(
9576                MouseMoveEvent {
9577                    position: outside_position,
9578                    pressed_button: Some(MouseButton::Left),
9579                    modifiers: Default::default(),
9580                }
9581                .to_platform_input(),
9582                cx,
9583            );
9584            assert!(cx.active_drag.is_none());
9585            window.remove_window();
9586        });
9587        assert!(
9588            update_result.is_ok(),
9589            "failed to remove drag source window: {update_result:?}"
9590        );
9591        assert!(!cx.update(|cx| cx.end_platform_drag(removed_window_id)));
9592
9593        let failed_path = PathBuf::from("/tmp/failed-drag");
9594        let failed = start_drag(cx, failed_path.clone(), false);
9595        let update_result = cx.update_window(failed.window, |_, window, cx| {
9596            for x_position in [-1., -2.] {
9597                window.dispatch_event(
9598                    MouseMoveEvent {
9599                        position: point(px(x_position), px(20.)),
9600                        pressed_button: Some(MouseButton::Left),
9601                        modifiers: Default::default(),
9602                    }
9603                    .to_platform_input(),
9604                    cx,
9605                );
9606            }
9607            assert!(cx.active_drag.is_some());
9608        });
9609        assert!(
9610            update_result.is_ok(),
9611            "failed to retain drag after platform failure: {update_result:?}"
9612        );
9613        assert_eq!(
9614            cx.test_window(failed.window).external_drag_files(),
9615            [(failed_path, true)]
9616        );
9617    }
9618
9619    struct FocusForwarder {
9620        a: FocusHandle,
9621        b: FocusHandle,
9622    }
9623
9624    impl Render for FocusForwarder {
9625        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
9626            div()
9627                .size_full()
9628                .child(div().w(px(50.)).h(px(50.)).track_focus(&self.a))
9629                .child(div().w(px(50.)).h(px(50.)).track_focus(&self.b))
9630        }
9631    }
9632
9633    /// When a focus listener moves focus again (e.g. a dock forwarding focus to its
9634    /// active panel), the resulting focus events must be dispatched without waiting
9635    /// for an unrelated redraw of the window.
9636    #[gpui::test]
9637    fn test_focus_moved_by_focus_listener_is_dispatched(cx: &mut TestAppContext) {
9638        let b_focus_count = Rc::new(Cell::new(0));
9639        let window = cx.add_window({
9640            let b_focus_count = b_focus_count.clone();
9641            move |window, cx| {
9642                let a = cx.focus_handle();
9643                let b = cx.focus_handle();
9644                cx.on_focus(&a, window, |this: &mut FocusForwarder, window, cx| {
9645                    let b = this.b.clone();
9646                    window.focus(&b, cx);
9647                })
9648                .detach();
9649                cx.on_focus(&b, window, move |_, _, _| {
9650                    b_focus_count.set(b_focus_count.get() + 1);
9651                })
9652                .detach();
9653                FocusForwarder { a, b }
9654            }
9655        });
9656
9657        window
9658            .update(cx, |_, window, _| window.activate_window())
9659            .unwrap();
9660        cx.executor().run_until_parked();
9661
9662        window
9663            .update(cx, |this, window, cx| {
9664                let a = this.a.clone();
9665                window.focus(&a, cx);
9666            })
9667            .unwrap();
9668        cx.executor().run_until_parked();
9669
9670        window
9671            .update(cx, |this, window, _| {
9672                assert!(this.b.is_focused(window));
9673            })
9674            .unwrap();
9675        assert_eq!(b_focus_count.get(), 1);
9676    }
9677
9678    #[gpui::test]
9679    fn claimed_touch_drag_receives_movement_and_release(cx: &mut TestAppContext) {
9680        let events = Rc::new(RefCell::new(Vec::new()));
9681        let window = cx.add_window({
9682            let events = events.clone();
9683            move |_, _| TouchDragListener { events }
9684        });
9685        let touch = TouchId(1);
9686
9687        dispatch_touch(window, cx, touch, TouchPhase::Started, 10.);
9688        dispatch_touch(window, cx, touch, TouchPhase::Moved, 30.);
9689        dispatch_touch(window, cx, touch, TouchPhase::Ended, 40.);
9690
9691        assert_eq!(
9692            events.borrow().as_slice(),
9693            [
9694                (TouchPhase::Started, px(10.)),
9695                (TouchPhase::Moved, px(30.)),
9696                (TouchPhase::Ended, px(40.)),
9697            ]
9698        );
9699    }
9700
9701    struct TouchDragListener {
9702        events: Rc<RefCell<Vec<(TouchPhase, Pixels)>>>,
9703    }
9704
9705    impl Render for TouchDragListener {
9706        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
9707            let events = self.events.clone();
9708            canvas(
9709                |_, _, _| {},
9710                move |_, _, window, _| {
9711                    window.on_mouse_event(move |event: &TouchDragEvent, phase, window, _cx| {
9712                        if phase != DispatchPhase::Bubble {
9713                            return;
9714                        }
9715                        events.borrow_mut().push((event.phase, event.position.x));
9716                        if event.phase == TouchPhase::Started {
9717                            window.prevent_default();
9718                        }
9719                    });
9720                },
9721            )
9722        }
9723    }
9724
9725    #[gpui::test]
9726    fn long_press_is_claimed_only_when_started_prevents_default(cx: &mut TestAppContext) {
9727        for response in [
9728            LongPressResponse::PreventDefault,
9729            LongPressResponse::StopPropagation,
9730            LongPressResponse::None,
9731        ] {
9732            let phases = Rc::new(RefCell::new(Vec::new()));
9733            let window = cx.add_window({
9734                let phases = phases.clone();
9735                move |_, _| LongPressListener { phases, response }
9736            });
9737            dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
9738            cx.executor().advance_clock(Duration::from_millis(501));
9739            cx.executor().run_until_parked();
9740            window
9741                .update(cx, |_, window, _| {
9742                    assert_eq!(
9743                        window.core.long_press_capture.is_some(),
9744                        response == LongPressResponse::PreventDefault
9745                    );
9746                })
9747                .unwrap();
9748            dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.);
9749            dispatch_touch(window, cx, TouchId(1), TouchPhase::Ended, 2.);
9750            window
9751                .update(cx, |_, window, _| {
9752                    assert!(window.core.long_press_capture.is_none());
9753                })
9754                .unwrap();
9755
9756            let phases = phases.borrow();
9757            if response == LongPressResponse::PreventDefault {
9758                assert_eq!(
9759                    phases.as_slice(),
9760                    [TouchPhase::Started, TouchPhase::Moved, TouchPhase::Ended]
9761                );
9762            } else {
9763                assert_eq!(phases.as_slice(), [TouchPhase::Started]);
9764            }
9765        }
9766    }
9767
9768    #[gpui::test]
9769    fn stale_default_prevention_does_not_claim_long_press(cx: &mut TestAppContext) {
9770        let phases = Rc::new(RefCell::new(Vec::new()));
9771        let window = cx.add_window({
9772            let phases = phases.clone();
9773            move |_, _| LongPressListener {
9774                phases,
9775                response: LongPressResponse::None,
9776            }
9777        });
9778        window
9779            .update(cx, |_, window, _| {
9780                window.prevent_default();
9781            })
9782            .unwrap();
9783
9784        dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
9785        cx.executor().advance_clock(Duration::from_millis(501));
9786        cx.executor().run_until_parked();
9787        dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.);
9788
9789        assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]);
9790    }
9791
9792    #[gpui::test]
9793    fn resolved_touch_cancels_scheduled_long_press(cx: &mut TestAppContext) {
9794        for (phase, position) in [
9795            (TouchPhase::Ended, 0.),
9796            (TouchPhase::Cancelled, 0.),
9797            (TouchPhase::Moved, 20.),
9798        ] {
9799            let phases = Rc::new(RefCell::new(Vec::new()));
9800            let window = cx.add_window({
9801                let phases = phases.clone();
9802                move |_, _| LongPressListener {
9803                    phases,
9804                    response: LongPressResponse::PreventDefault,
9805                }
9806            });
9807            dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
9808            dispatch_touch(window, cx, TouchId(1), phase, position);
9809            cx.executor().advance_clock(Duration::from_millis(501));
9810            cx.executor().run_until_parked();
9811
9812            assert!(phases.borrow().is_empty(), "{phase:?} allowed long press");
9813        }
9814    }
9815
9816    #[gpui::test]
9817    fn stale_long_press_timer_cannot_affect_replacement_touch(cx: &mut TestAppContext) {
9818        let phases = Rc::new(RefCell::new(Vec::new()));
9819        let window = cx.add_window({
9820            let phases = phases.clone();
9821            move |_, _| LongPressListener {
9822                phases,
9823                response: LongPressResponse::PreventDefault,
9824            }
9825        });
9826        let first_touch = TouchId(1);
9827        dispatch_touch(window, cx, first_touch, TouchPhase::Started, 0.);
9828        cx.executor().advance_clock(Duration::from_millis(250));
9829        dispatch_touch(window, cx, first_touch, TouchPhase::Cancelled, 0.);
9830        dispatch_touch(window, cx, TouchId(2), TouchPhase::Started, 10.);
9831
9832        cx.executor().advance_clock(Duration::from_millis(251));
9833        cx.executor().run_until_parked();
9834        assert!(phases.borrow().is_empty());
9835
9836        cx.executor().advance_clock(Duration::from_millis(250));
9837        cx.executor().run_until_parked();
9838        assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]);
9839    }
9840
9841    #[gpui::test]
9842    fn test_underline_exclusions_preserve_device_geometry(cx: &mut TestAppContext) {
9843        test_underline_paint_at_scales(cx, |window| {
9844            let (numerator, denominator) = match window.scale_factor() {
9845                1.0 => (1, 1),
9846                1.25 => (5, 4),
9847                1.5 => (3, 2),
9848                2.0 => (2, 1),
9849                3.0 => (3, 1),
9850                scale => panic!("unexpected scale {scale}"),
9851            };
9852            let snap = |quarters: i32| {
9853                let scaled = quarters * numerator;
9854                let divisor = 4 * denominator;
9855                let rounded =
9856                    scaled.abs() / divisor + i32::from(2 * (scaled.abs() % divisor) > divisor);
9857                ScaledPixels((scaled.signum() * rounded) as f32)
9858            };
9859            let stroke = |quarters| {
9860                if quarters == 0 {
9861                    ScaledPixels(0.)
9862                } else {
9863                    snap(quarters).max(ScaledPixels(1.))
9864                }
9865            };
9866
9867            for origin in [-101, -3, -2, -1, 0, 1, 2, 3, 101] {
9868                for width in [0, 1, 3, 84] {
9869                    for thickness in [0, 1, 4, 7] {
9870                        for wavy in [false, true] {
9871                            let style = UnderlineStyle {
9872                                thickness: px(thickness as f32 / 4.),
9873                                color: Some(hsla(0.25, 0.5, 0.75, 0.5)),
9874                                wavy,
9875                            };
9876                            let bounds = Bounds::new(
9877                                point(snap(origin), snap(-origin)),
9878                                size(
9879                                    stroke(width),
9880                                    stroke(thickness) * if wavy { 3. } else { 1. },
9881                                ),
9882                            );
9883                            let origin = point(px(origin as f32 / 4.), px(-origin as f32 / 4.));
9884                            let width = px(width as f32 / 4.);
9885                            assert_eq!(window.underline_bounds(origin, width, &style), bounds);
9886                            let original = paint_test_underlines(window, |window| {
9887                                window.paint_underline(origin, width, &style);
9888                            })
9889                            .to_vec();
9890                            assert_eq!(original.len(), usize::from(!bounds.is_empty()));
9891                            if let Some(underline) = original.first() {
9892                                assert_eq!(underline.bounds, bounds);
9893                                assert_eq!(underline.thickness, stroke(thickness));
9894                                assert_eq!(underline.wavy, wavy.into());
9895                                assert_eq!(underline.color, hsla(0.25, 0.5, 0.75, 0.5));
9896                            }
9897
9898                            let underlines = paint_test_underlines(window, |window| {
9899                                window.paint_underline_with_exclusions(origin, width, &style, &[]);
9900                            });
9901                            assert_eq!(underlines.len(), original.len());
9902                            for (actual, original) in underlines.iter().zip(&original) {
9903                                assert_same_underline_geometry(actual, original);
9904                                assert_eq!(actual.content_mask, original.content_mask);
9905                            }
9906
9907                            let left = bounds.left().0 as i32;
9908                            let right = bounds.right().0 as i32;
9909                            let exclusions = [
9910                                (15, 25),
9911                                (3, 7),
9912                                (5, 10),
9913                                (10, 12),
9914                                (0, 0),
9915                                (4, 2),
9916                                (-50, -1),
9917                                (70, 100),
9918                            ]
9919                            .map(|(start, end)| {
9920                                ScaledPixels((left + start) as f32)
9921                                    ..ScaledPixels((left + end) as f32)
9922                            });
9923                            let underlines = paint_test_underlines(window, |window| {
9924                                window.paint_underline_with_exclusions(
9925                                    origin,
9926                                    width,
9927                                    &style,
9928                                    &exclusions,
9929                                );
9930                            });
9931                            let expected = (left..right)
9932                                .filter(|column| {
9933                                    !bounds.is_empty()
9934                                        && !exclusions.iter().any(|span| {
9935                                            span.contains(&ScaledPixels(*column as f32))
9936                                        })
9937                                })
9938                                .collect::<Vec<_>>();
9939                            assert_eq!(underline_device_columns(underlines), expected);
9940                            for underline in underlines {
9941                                assert_same_underline_geometry(underline, &original[0]);
9942                            }
9943                        }
9944                    }
9945                }
9946            }
9947        });
9948    }
9949
9950    #[gpui::test]
9951    fn test_underline_exclusions_preserve_helvetica_warning_edge(cx: &mut TestAppContext) {
9952        test_underline_paint_at_scales(cx, |window| {
9953            if window.scale_factor() != 2.0 {
9954                return;
9955            }
9956            let style = UnderlineStyle {
9957                thickness: px(1.),
9958                color: None,
9959                wavy: true,
9960            };
9961            let origin = point(px(2.888_183_8), px(15.357_917));
9962            let width = px(23.848_145) - origin.x;
9963            let original = paint_test_underlines(window, |window| {
9964                window.paint_underline(origin, width, &style);
9965            })[0];
9966            assert_eq!(original.bounds.left(), ScaledPixels(6.));
9967            assert_eq!(original.bounds.right(), ScaledPixels(48.));
9968            let point_bounds = window.underline_bounds(origin, px(10.829_102), &style);
9969            assert_eq!(point_bounds.left(), ScaledPixels(6.));
9970            assert_eq!(point_bounds.right(), ScaledPixels(28.));
9971
9972            let underlines = paint_test_underlines(window, |window| {
9973                window.paint_underline_with_exclusions(
9974                    origin,
9975                    width,
9976                    &style,
9977                    &[point_bounds.left()..point_bounds.right()],
9978                );
9979            });
9980            assert_eq!(underlines.len(), 1);
9981            assert_same_underline_geometry(&underlines[0], &original);
9982            assert_eq!(
9983                underline_device_columns(underlines),
9984                (28..48).collect::<Vec<_>>()
9985            );
9986        });
9987    }
9988
9989    #[gpui::test]
9990    fn test_underline_exclusions_preserve_content_mask_and_opacity(cx: &mut TestAppContext) {
9991        test_underline_paint_at_scales(cx, |window| {
9992            let scale = window.scale_factor();
9993            let original_mask = window.content_mask();
9994            let original_opacity = window.element_opacity();
9995            let mask = ContentMask {
9996                bounds: Bounds::from_corners(point(px(4.), px(10.)), point(px(16.), px(12.))),
9997            };
9998            let style = UnderlineStyle {
9999                thickness: px(2.),
10000                color: Some(hsla(0.25, 0.5, 0.75, 0.5)),
10001                wavy: true,
10002            };
10003            let origin = point(px(-1.25), px(9.25));
10004            let width = px(24.);
10005            window.with_content_mask(Some(mask), |window| {
10006                window.with_element_opacity(Some(0.5), |window| {
10007                    window.with_element_opacity(Some(0.5), |window| {
10008                        let original = paint_test_underlines(window, |window| {
10009                            window.paint_underline(origin, width, &style);
10010                        })[0];
10011                        assert_eq!(original.color, hsla(0.25, 0.5, 0.75, 0.125));
10012                        let underlines = paint_test_underlines(window, |window| {
10013                            window.paint_underline_with_exclusions(
10014                                origin,
10015                                width,
10016                                &style,
10017                                &[ScaledPixels(6. * scale)..ScaledPixels(8. * scale)],
10018                            );
10019                        });
10020                        assert_eq!(underlines.len(), 2);
10021                        let expected = [(4. * scale, 6. * scale), (8. * scale, 16. * scale)].map(
10022                            |(left, right)| {
10023                                Bounds::from_corners(
10024                                    point(ScaledPixels(left), ScaledPixels((10. * scale).floor())),
10025                                    point(ScaledPixels(right), ScaledPixels((12. * scale).ceil())),
10026                                )
10027                            },
10028                        );
10029                        assert_eq!(
10030                            underlines
10031                                .iter()
10032                                .map(|underline| underline.content_mask.bounds)
10033                                .collect::<Vec<_>>(),
10034                            expected
10035                        );
10036                        for underline in underlines {
10037                            assert_same_underline_geometry(underline, &original);
10038                        }
10039                    });
10040                });
10041            });
10042            assert_eq!(window.content_mask(), original_mask);
10043            assert_eq!(window.element_opacity(), original_opacity);
10044        });
10045    }
10046
10047    #[gpui::test]
10048    fn test_underline_exclusions_adversarial_permutations(cx: &mut TestAppContext) {
10049        test_underline_paint_at_scales(cx, |window| {
10050            let style = UnderlineStyle {
10051                thickness: px(1.),
10052                color: None,
10053                wavy: true,
10054            };
10055            let origin = point(px(-4.), px(-1.));
10056            let width = px(8.);
10057            let left = (-4. * window.scale_factor()) as i32;
10058            let right = (4. * window.scale_factor()) as i32;
10059            let endpoints = [-16, -8, -1, 0, 1, 8, 16];
10060            for first_start in endpoints {
10061                for first_end in endpoints {
10062                    for second_start in endpoints {
10063                        for second_end in endpoints {
10064                            let exclusions = [first_start..first_end, second_start..second_end];
10065                            let expected = (left..right)
10066                                .filter(|column| {
10067                                    !exclusions.iter().any(|span| span.contains(column))
10068                                })
10069                                .collect::<Vec<_>>();
10070                            let exclusions = exclusions.map(|span| {
10071                                ScaledPixels(span.start as f32)..ScaledPixels(span.end as f32)
10072                            });
10073                            let underlines = paint_test_underlines(window, |window| {
10074                                window.paint_underline_with_exclusions(
10075                                    origin,
10076                                    width,
10077                                    &style,
10078                                    &exclusions,
10079                                );
10080                            });
10081                            assert_eq!(
10082                                underline_device_columns(underlines),
10083                                expected,
10084                                "{exclusions:?}"
10085                            );
10086                        }
10087                    }
10088                }
10089            }
10090        });
10091    }
10092
10093    #[derive(Clone, Copy, PartialEq)]
10094    enum LongPressResponse {
10095        PreventDefault,
10096        StopPropagation,
10097        None,
10098    }
10099
10100    struct LongPressListener {
10101        phases: Rc<RefCell<Vec<TouchPhase>>>,
10102        response: LongPressResponse,
10103    }
10104
10105    impl Render for LongPressListener {
10106        fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
10107            let entity = cx.entity();
10108            let phases = self.phases.clone();
10109            let response = self.response;
10110            canvas(
10111                |_, _, _| {},
10112                move |_, _, window, _| {
10113                    window.on_mouse_event(move |event: &LongPressEvent, phase, window, cx| {
10114                        if phase != DispatchPhase::Bubble {
10115                            return;
10116                        }
10117                        phases.borrow_mut().push(event.phase);
10118                        match response {
10119                            LongPressResponse::PreventDefault => {
10120                                window.capture_long_press(&entity);
10121                                window.prevent_default();
10122                            }
10123                            LongPressResponse::StopPropagation => cx.stop_propagation(),
10124                            LongPressResponse::None => {}
10125                        }
10126                    });
10127                },
10128            )
10129        }
10130    }
10131
10132    struct UnderlineTestView(Rc<dyn Fn(&mut Window)>);
10133
10134    impl Render for UnderlineTestView {
10135        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
10136            let paint = self.0.clone();
10137            canvas(
10138                |_, _, _| {},
10139                move |_, _, window, _| {
10140                    window.frame_state.content_mask_stack.push(ContentMask {
10141                        bounds: Bounds::from_corners(
10142                            point(px(-1000.), px(-1000.)),
10143                            point(px(1000.), px(1000.)),
10144                        ),
10145                    });
10146                    paint(window);
10147                    window.frame_state.content_mask_stack.pop();
10148                },
10149            )
10150            .size_full()
10151        }
10152    }
10153
10154    fn test_underline_paint_at_scales(
10155        cx: &mut TestAppContext,
10156        paint: impl Fn(&mut Window) + 'static,
10157    ) {
10158        let window = cx.add_window(move |_, _| UnderlineTestView(Rc::new(paint)));
10159        for scale in [1., 1.25, 1.5, 2., 3.] {
10160            cx.simulate_window_scale_factor_change(window.into(), scale);
10161            cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
10162                .unwrap();
10163        }
10164    }
10165
10166    fn paint_test_underlines<'a>(
10167        window: &'a mut Window<'_>,
10168        paint: impl FnOnce(&mut Window),
10169    ) -> &'a [Underline] {
10170        window.frame_state.next_frame.scene.clear();
10171        paint(window);
10172        &window.frame_state.next_frame.scene.underlines
10173    }
10174
10175    fn assert_same_underline_geometry(actual: &Underline, expected: &Underline) {
10176        assert_eq!(actual.bounds, expected.bounds);
10177        assert_eq!(actual.thickness, expected.thickness);
10178        assert_eq!(actual.wavy, expected.wavy);
10179        assert_eq!(actual.color, expected.color);
10180        assert_eq!(actual.pad, expected.pad);
10181    }
10182
10183    fn underline_device_columns(underlines: &[Underline]) -> Vec<i32> {
10184        underlines
10185            .iter()
10186            .flat_map(|underline| {
10187                let bounds = underline.bounds.intersect(&underline.content_mask.bounds);
10188                bounds.left().0 as i32..bounds.right().0 as i32
10189            })
10190            .collect()
10191    }
10192
10193    fn dispatch_touch<T: 'static>(
10194        window: crate::WindowHandle<T>,
10195        cx: &mut TestAppContext,
10196        id: TouchId,
10197        phase: TouchPhase,
10198        x: f32,
10199    ) {
10200        window
10201            .update(cx, |_, window, cx| {
10202                window.dispatch_event(
10203                    TouchEvent {
10204                        id,
10205                        phase,
10206                        position: point(px(x), px(0.)),
10207                        predicted_position: None,
10208                        force: None,
10209                    }
10210                    .to_platform_input(),
10211                    cx,
10212                );
10213            })
10214            .unwrap();
10215    }
10216
10217    /// The paint path is where a primitive's radii stop being `Pixels`. A renderer is handed
10218    /// scaled pixels and has no scale factor of its own, so the element has to convert -- as
10219    /// `paint_quad` does -- or a rounded corner is drawn too tight on a HiDPI display. The test
10220    /// platform reports a scale factor of 2, so a radius of 4 is drawn as 8.
10221    #[gpui::test]
10222    fn a_painted_imported_texture_converts_its_radii_at_paint_time(cx: &mut TestAppContext) {
10223        struct PaintedTexture {
10224            handle: ImportedTextureHandle,
10225            bounds: Bounds<Pixels>,
10226            corner_radii: Corners<Pixels>,
10227            opacity: f32,
10228            flip_v: bool,
10229        }
10230
10231        impl Render for PaintedTexture {
10232            fn render(
10233                &mut self,
10234                _window: &mut Window,
10235                _cx: &mut Context<Self>,
10236            ) -> impl IntoElement {
10237                let handle = self.handle.clone();
10238                let bounds = self.bounds;
10239                let corner_radii = self.corner_radii;
10240                let opacity = self.opacity;
10241                let flip_v = self.flip_v;
10242                gpu_canvas(move |ctx| {
10243                    ctx.paint_texture(handle.clone(), corner_radii, opacity, flip_v);
10244                })
10245                .w(bounds.size.width)
10246                .h(bounds.size.height)
10247            }
10248        }
10249
10250        let corner_radii = Corners {
10251            top_left: px(4.),
10252            top_right: px(0.),
10253            bottom_right: px(0.),
10254            bottom_left: px(0.),
10255        };
10256        let window = cx.add_window(|_, _| PaintedTexture {
10257            handle: ImportedTextureHandle::new(()),
10258            bounds: Bounds::new(point(px(10.), px(20.)), size(px(30.), px(40.))),
10259            corner_radii,
10260            opacity: 0.5,
10261            flip_v: true,
10262        });
10263        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
10264            .unwrap();
10265
10266        cx.update_window(window.into(), |_, window, _| {
10267            let painted = window.painted_imported_textures();
10268            assert_eq!(painted.len(), 1, "the window should have painted the texture");
10269
10270            let CustomRenderPrimitive::Texture {
10271                radii,
10272                opacity,
10273                flip_v,
10274                bounds,
10275                ..
10276            } = &painted[0];
10277            assert_eq!(
10278                *radii,
10279                corner_radii.scale(window.scale_factor()),
10280                "the radii must be converted to scaled pixels at paint time"
10281            );
10282            assert_eq!(*opacity, 0.5);
10283            assert!(*flip_v);
10284            assert_eq!(bounds.size.width, ScaledPixels(30. * window.scale_factor()));
10285            assert_eq!(bounds.size.height, ScaledPixels(40. * window.scale_factor()));
10286        })
10287        .unwrap();
10288    }
10289}
10290
10291#[cfg(all(test, any(feature = "inspector", debug_assertions)))]
10292mod inspector_tests {
10293    use super::*;
10294    use crate::{
10295        DivInspectorState, InspectorElementId, MouseDownEvent, StyleRefinement, TestAppContext, div,
10296    };
10297
10298    #[gpui::test]
10299    fn inspector_only_tracks_its_open_window(cx: &mut TestAppContext) {
10300        let windows = [
10301            cx.add_window(|_, cx| InspectorTestRoot {
10302                child: cx.new(|_| InspectorTestView::default()),
10303            }),
10304            cx.add_window(|_, cx| InspectorTestRoot {
10305                child: cx.new(|_| InspectorTestView::default()),
10306            }),
10307        ];
10308        for window in windows {
10309            assert_closed_inspector(window.into(), cx);
10310        }
10311        for _ in 0..2 {
10312            cx.update_window(windows[0].into(), |root, window, cx| {
10313                let root = root.downcast::<InspectorTestRoot>().expect("test root");
10314                let child_widths = root.read(cx).child.read(cx).child_widths.clone();
10315                window.toggle_inspector(cx);
10316                window.draw(cx).clear(cx);
10317                assert_eq!(child_widths.borrow().as_slice(), &[px(10.); 3]);
10318                let path = window
10319                    .frame_state
10320                    .rendered_frame
10321                    .next_inspector_instance_ids
10322                    .iter()
10323                    .find_map(|(path, count)| (*count == 3).then(|| path.clone()))
10324                    .expect("anonymous siblings share an inspector path");
10325                let selected_id = InspectorElementId {
10326                    path,
10327                    instance_id: 1,
10328                };
10329                let position = window
10330                    .frame_state
10331                    .rendered_frame
10332                    .hitboxes
10333                    .iter()
10334                    .find(|hitbox| {
10335                        window
10336                            .frame_state
10337                            .rendered_frame
10338                            .inspector_hitboxes
10339                            .get(&hitbox.id)
10340                            == Some(&selected_id)
10341                    })
10342                    .expect("middle sibling is pickable")
10343                    .bounds
10344                    .center();
10345                window.simulate_mouse_move(position, cx);
10346                window.dispatch_event(
10347                    PlatformInput::MouseDown(MouseDownEvent {
10348                        position,
10349                        button: MouseButton::Left,
10350                        modifiers: Modifiers::default(),
10351                        click_count: 1,
10352                        first_mouse: false,
10353                    }),
10354                    cx,
10355                );
10356                window.dispatch_event(
10357                    PlatformInput::MouseUp(MouseUpEvent {
10358                        position,
10359                        button: MouseButton::Left,
10360                        modifiers: Modifiers::default(),
10361                        click_count: 1,
10362                    }),
10363                    cx,
10364                );
10365                assert!(!window.is_inspector_picking(cx));
10366                assert_eq!(
10367                    window
10368                        .core
10369                        .inspector
10370                        .as_ref()
10371                        .expect("open inspector")
10372                        .read(cx)
10373                        .active_element_id(),
10374                    Some(&selected_id)
10375                );
10376                window.draw(cx).clear(cx);
10377                window.with_inspector_state::<DivInspectorState, _>(
10378                    Some(&selected_id),
10379                    cx,
10380                    |state, _| {
10381                        let state = state.as_mut().expect("selected div has style state");
10382                        assert_eq!(
10383                            state.base_style.size.width,
10384                            Some(crate::Length::from(px(10.)))
10385                        );
10386                        state.base_style.size.width = Some(crate::Length::from(px(25.)));
10387                    },
10388                );
10389                window.refresh();
10390                window.draw(cx).clear(cx);
10391                assert_eq!(
10392                    child_widths.borrow().as_slice(),
10393                    &[px(10.), px(25.), px(10.)]
10394                );
10395            })
10396            .expect("pick and edit a cached child");
10397            assert_closed_inspector(windows[1].into(), cx);
10398            windows[0]
10399                .update(cx, |_, window, cx| window.toggle_inspector(cx))
10400                .expect("close inspector");
10401            assert_closed_inspector(windows[0].into(), cx);
10402        }
10403    }
10404
10405    struct InspectorTestRoot {
10406        child: Entity<InspectorTestView>,
10407    }
10408
10409    impl Render for InspectorTestRoot {
10410        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10411            self.child
10412                .clone()
10413                .cached(StyleRefinement::default().size(px(100.)))
10414        }
10415    }
10416
10417    #[derive(Default)]
10418    struct InspectorTestView {
10419        child_widths: Rc<RefCell<Vec<Pixels>>>,
10420    }
10421
10422    impl Render for InspectorTestView {
10423        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10424            let child_widths = self.child_widths.clone();
10425            div()
10426                .on_children_prepainted(move |bounds, _, _| {
10427                    *child_widths.borrow_mut() =
10428                        bounds.iter().map(|bounds| bounds.size.width).collect();
10429                })
10430                .with_dynamic_prepaint_order(|_, _| SmallVec::from_iter([2, 0, 1]))
10431                .id("inspector-root")
10432                .flex()
10433                .children((0..3).map(|_| div().size(px(10.)).flex_shrink_0()))
10434        }
10435    }
10436
10437    fn assert_closed_inspector(window: AnyWindowHandle, cx: &mut TestAppContext) {
10438        cx.update_window(window, |root, window, cx| {
10439            window.draw(cx).clear(cx);
10440            window.draw(cx).clear(cx);
10441            let root = root.downcast::<InspectorTestRoot>().expect("test root");
10442            assert_eq!(
10443                root.read(cx)
10444                    .child
10445                    .read(cx)
10446                    .child_widths
10447                    .borrow()
10448                    .as_slice(),
10449                &[px(10.); 3]
10450            );
10451            for frame in [
10452                &window.frame_state.rendered_frame,
10453                &window.frame_state.next_frame,
10454            ] {
10455                assert_eq!(frame.next_inspector_instance_ids.capacity(), 0);
10456                assert_eq!(frame.inspector_hitboxes.capacity(), 0);
10457            }
10458        })
10459        .expect("closed inspector has no bookkeeping and no style overrides");
10460    }
10461}