Skip to main content

gpui/
window.rs

1use crate::{
2    Action, AnyDrag, AnyElement, AnyImageCache, AnyTooltip, AnyView, App, AppContext, Arena, Asset,
3    AsyncWindowContext, AtlasTile, AvailableSpace, BackdropFilter, Background, BorderStyle, Bounds,
4    BoxShadow, Capslock, Context, Corners, CursorHideMode, CursorStyle, Decorations, DevicePixels,
5    DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity,
6    EntityId, EventEmitter, FileDropEvent, Filter, FilterBoundary, FontId, Global, GlobalElementId,
7    GlyphId, GlyphRenderMode, GpuSpecs, InputHandler, InputPreference, IntoElement, IsZero,
8    KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId, Lerp,
9    LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite, Motion, MouseButton,
10    MouseEvent, MouseMoveEvent, MouseUpEvent, PaintSurface, Path, Pixels, PlatformAtlas,
11    PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite,
12    Priority, PromptButton, PromptLevel, Quad, RasterizedGlyphFormat, Render, RenderGlyphParams,
13    RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, ResolvedDirection,
14    SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y, ScaledFilter, ScaledPixels,
15    Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubpixelSprite, SubscriberSet,
16    Subscription, SystemWindowTab, SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task,
17    TextInputConfiguration, TextInputStateChange, TextRenderingMode, TextStyle,
18    TextStyleRefinement, ThermalState, TransformationMatrix, Transition, TransitionState,
19    Underline, UnderlineStyle, UnicodeBidi, WindowAppearance, WindowBackgroundAppearance,
20    WindowBounds, WindowControls, WindowDecorations, WindowInsets, WindowOptions, WindowParams,
21    WindowTextSystem, WindowVisibility,
22    gestures::{GestureTuning, RecognizedTouchGesture, TouchGestureRecognizer},
23    interactive::TouchEvent,
24    point, px, rems, size, transparent_black,
25    util::{
26        atomic_incr_if_not_zero, ceil_to_device_pixel, floor_to_device_pixel,
27        round_half_toward_zero, round_half_toward_zero_f64, round_stroke_to_device_pixel,
28        round_to_device_pixel,
29    },
30    white,
31};
32use anyhow::{Context as _, Result, anyhow};
33use collections::{FxHashMap, FxHashSet};
34use derive_more::{Deref, DerefMut};
35use futures::channel::oneshot;
36use gpui_util::post_inc;
37use gpui_util::{ResultExt, measure};
38use itertools::Itertools;
39use palette::Hsla;
40use parking_lot::{RwLock, RwLockUpgradableReadGuard};
41use raw_window_handle::{HandleError, HasDisplayHandle, HasWindowHandle};
42use refineable::Refineable;
43use scheduler::Instant;
44use slotmap::SlotMap;
45use smallvec::SmallVec;
46use std::{
47    any::{Any, TypeId},
48    borrow::Cow,
49    cell::{Cell, RefCell},
50    cmp,
51    fmt::{Debug, Display},
52    hash::{Hash, Hasher},
53    marker::PhantomData,
54    mem,
55    ops::{DerefMut, Range},
56    rc::Rc,
57    sync::{
58        Arc, Weak,
59        atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
60    },
61    thread::AccessError,
62    time::Duration,
63};
64use uuid::Uuid;
65
66#[cfg(not(target_family = "wasm"))]
67use self::a11y::ROOT_NODE_ID;
68#[cfg(feature = "profiler")]
69use crate::DebugFrameOverlayMode;
70#[cfg(any(feature = "inspector", debug_assertions))]
71use crate::Inspector;
72#[cfg(feature = "profiler")]
73use crate::profiler;
74
75pub(crate) mod a11y;
76mod prompts;
77
78use a11y::A11y;
79pub use a11y::A11ySubtreeBuilder;
80pub use prompts::*;
81
82fn quantize_glyph_origin(origin: Point<ScaledPixels>) -> (Point<ScaledPixels>, Point<u8>) {
83    fn axis(value: ScaledPixels, variants: u8) -> (ScaledPixels, u8) {
84        let quantized = round_half_toward_zero(value.0 * variants as f32) / variants as f32;
85        let integer = quantized.floor();
86        let variant = ((quantized - integer) * variants as f32).round() as u8;
87        (ScaledPixels(integer), variant.min(variants - 1))
88    }
89
90    let (integer_x, variant_x) = axis(origin.x, SUBPIXEL_VARIANTS_X);
91    let (integer_y, variant_y) = axis(origin.y, SUBPIXEL_VARIANTS_Y);
92    (point(integer_x, integer_y), point(variant_x, variant_y))
93}
94
95fn quantize_color_glyph_origin(origin: Point<ScaledPixels>) -> (Point<ScaledPixels>, Point<u8>) {
96    (
97        origin.map(|coordinate| ScaledPixels(round_half_toward_zero(coordinate.0))),
98        Point::default(),
99    )
100}
101
102/// The size, in logical pixels, of a window whose bounds were not set.
103///
104/// Platforms fall back to this size when a window opens without explicit
105/// bounds, and it is clamped to the display when the display is smaller.
106pub const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1536.), px(1095.));
107
108/// A 6:5 minimum window size in logical pixels, for secondary windows such
109/// as settings or document-library windows.
110pub const DEFAULT_ADDITIONAL_WINDOW_SIZE: Size<Pixels> = Size {
111    width: Pixels(900.),
112    height: Pixels(750.),
113};
114
115/// The two passes an event makes through the element tree.
116///
117/// Each event is offered first in the capture phase and then in the bubble
118/// phase. Listeners receive the phase as an argument, so one listener can
119/// check which pass it is in. See [input dispatch](crate::_documentation::concepts::input_dispatch).
120#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
121pub enum DispatchPhase {
122    /// The bubble phase, which runs after capture.
123    ///
124    /// Mouse listeners run front to back, and key listeners run from the
125    /// focused element up to the root. Most listeners you register belong
126    /// in this phase.
127    #[default]
128    Bubble,
129    /// The capture phase, which runs before bubble.
130    ///
131    /// Mouse listeners run back to front, and key listeners run from the
132    /// root down to the focused element. Use it for special cases, such as
133    /// clearing a pressed state when a click starts outside an element. If
134    /// you stop propagation here, the bubble phase never runs for that event.
135    Capture,
136}
137
138impl DispatchPhase {
139    /// Returns `true` if this is the bubble phase.
140    #[inline]
141    pub fn bubble(self) -> bool {
142        self == DispatchPhase::Bubble
143    }
144
145    /// Returns `true` if this is the capture phase.
146    #[inline]
147    pub fn capture(self) -> bool {
148        self == DispatchPhase::Capture
149    }
150}
151
152struct WindowInvalidatorInner {
153    #[cfg(feature = "profiler")]
154    pub window_id: WindowId,
155    pub dirty: bool,
156    pub draw_phase: DrawPhase,
157    pub dirty_views: FxHashSet<EntityId>,
158    pub update_count: usize,
159    #[cfg(feature = "profiler")]
160    pub frame_dirty: FrameDirtyAccumulator,
161    pub platform_waker: Option<Rc<dyn Fn()>>,
162}
163
164/// Per-frame invalidation bookkeeping, drained at draw time and emitted to the
165/// frame profiler. Tracks when the current frame first became dirty and how
166/// many invalidations were coalesced into it, whenever the profiler is
167/// compiled in. Retention of the resulting per-frame records is what
168/// `profiler::trace_enabled()` controls, not this measurement.
169#[cfg(feature = "profiler")]
170#[derive(Default)]
171struct FrameDirtyAccumulator {
172    dirty_at: Option<Instant>,
173    invalidations: u64,
174}
175
176/// Why GPUI capped a window's frame rate.
177#[derive(Clone, Copy)]
178enum FrameRateLimit {
179    /// The window isn't focused.
180    Inactive,
181    /// The system is under thermal pressure.
182    Thermal,
183}
184
185#[derive(Clone)]
186pub(crate) struct WindowInvalidator {
187    inner: Rc<RefCell<WindowInvalidatorInner>>,
188}
189
190impl WindowInvalidator {
191    pub fn new(#[allow(unused_variables)] window_id: WindowId) -> Self {
192        WindowInvalidator {
193            inner: Rc::new(RefCell::new(WindowInvalidatorInner {
194                #[cfg(feature = "profiler")]
195                window_id,
196                dirty: true,
197                draw_phase: DrawPhase::None,
198                dirty_views: FxHashSet::default(),
199                update_count: 0,
200                #[cfg(feature = "profiler")]
201                frame_dirty: FrameDirtyAccumulator::default(),
202                platform_waker: None,
203            })),
204        }
205    }
206
207    pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {
208        let mut inner = self.inner.borrow_mut();
209        inner.update_count += 1;
210        inner.dirty_views.insert(entity);
211        if inner.draw_phase == DrawPhase::None {
212            #[cfg(feature = "profiler")]
213            let dirty_at = Self::record_frame_dirty(&mut inner);
214            let became_dirty = !inner.dirty;
215            inner.dirty = true;
216            let waker = became_dirty.then(|| inner.platform_waker.clone()).flatten();
217            #[cfg(feature = "profiler")]
218            let window_id = inner.window_id;
219            drop(inner);
220            #[cfg(feature = "profiler")]
221            if became_dirty {
222                profiler::journal::record_frame_pending(window_id, dirty_at);
223            }
224            cx.push_effect(Effect::Notify { emitter: entity });
225            if let Some(waker) = waker {
226                waker();
227            }
228            true
229        } else {
230            false
231        }
232    }
233
234    pub fn is_dirty(&self) -> bool {
235        self.inner.borrow().dirty
236    }
237
238    pub fn set_dirty(&self, dirty: bool) {
239        let mut inner = self.inner.borrow_mut();
240        let became_dirty = dirty && !inner.dirty;
241        inner.dirty = dirty;
242        if dirty {
243            inner.update_count += 1;
244        }
245        #[cfg(feature = "profiler")]
246        let dirty_at = dirty.then(|| Self::record_frame_dirty(&mut inner));
247        let waker = became_dirty.then(|| inner.platform_waker.clone()).flatten();
248        #[cfg(feature = "profiler")]
249        let window_id = inner.window_id;
250        drop(inner);
251        #[cfg(feature = "profiler")]
252        if became_dirty && let Some(dirty_at) = dirty_at {
253            profiler::journal::record_frame_pending(window_id, dirty_at);
254        }
255        if let Some(waker) = waker {
256            waker();
257        }
258    }
259
260    pub fn set_platform_waker(&self, waker: Option<Rc<dyn Fn()>>) {
261        let mut inner = self.inner.borrow_mut();
262        inner.platform_waker = waker;
263        let waker = inner.dirty.then(|| inner.platform_waker.clone()).flatten();
264        drop(inner);
265        if let Some(waker) = waker {
266            waker();
267        }
268    }
269
270    /// Wakes the platform's frame-request source so a frame request is
271    /// delivered even if the platform stops requesting frames for idle
272    /// windows. No-op on platforms without a frame waker.
273    pub fn wake_platform(&self) {
274        let waker = self.inner.borrow().platform_waker.clone();
275        if let Some(waker) = waker {
276            waker();
277        }
278    }
279
280    pub fn set_phase(&self, phase: DrawPhase) {
281        self.inner.borrow_mut().draw_phase = phase
282    }
283
284    pub fn update_count(&self) -> usize {
285        self.inner.borrow().update_count
286    }
287
288    #[cfg(feature = "profiler")]
289    fn record_frame_dirty(inner: &mut WindowInvalidatorInner) -> Instant {
290        let dirty_at = *inner.frame_dirty.dirty_at.get_or_insert_with(Instant::now);
291        inner.frame_dirty.invalidations += 1;
292        dirty_at
293    }
294
295    #[cfg(feature = "profiler")]
296    fn take_frame_dirty(&self) -> FrameDirtyAccumulator {
297        mem::take(&mut self.inner.borrow_mut().frame_dirty)
298    }
299
300    /// Marks `entity` dirty for the next draw without requesting one.
301    fn mark_dirty_for_next_draw(&self, entity: EntityId) {
302        self.inner.borrow_mut().dirty_views.insert(entity);
303    }
304
305    pub fn take_views(&self) -> FxHashSet<EntityId> {
306        mem::take(&mut self.inner.borrow_mut().dirty_views)
307    }
308
309    pub fn replace_views(&self, views: FxHashSet<EntityId>) {
310        self.inner.borrow_mut().dirty_views = views;
311    }
312
313    pub fn not_drawing(&self) -> bool {
314        self.inner.borrow().draw_phase == DrawPhase::None
315    }
316
317    #[track_caller]
318    pub fn debug_assert_paint(&self) {
319        debug_assert!(
320            matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),
321            "this method can only be called during paint"
322        );
323    }
324
325    #[track_caller]
326    pub fn debug_assert_prepaint(&self) {
327        debug_assert!(
328            matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),
329            "this method can only be called during request_layout, or prepaint"
330        );
331    }
332
333    #[track_caller]
334    pub fn debug_assert_paint_or_prepaint(&self) {
335        debug_assert!(
336            matches!(
337                self.inner.borrow().draw_phase,
338                DrawPhase::Paint | DrawPhase::Prepaint
339            ),
340            "this method can only be called during request_layout, prepaint, or paint"
341        );
342    }
343}
344
345type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;
346
347pub(crate) type AnyWindowFocusListener =
348    Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;
349
350pub(crate) struct WindowFocusEvent {
351    pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,
352    pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,
353}
354
355impl WindowFocusEvent {
356    pub fn is_focus_in(&self, focus_id: FocusId) -> bool {
357        !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)
358    }
359
360    pub fn is_focus_out(&self, focus_id: FocusId) -> bool {
361        self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)
362    }
363}
364
365/// The event passed to listeners registered with [`Context::on_focus_out`].
366pub struct FocusOutEvent {
367    /// A weak handle to the focus handle that lost focus.
368    ///
369    /// Upgrade it with [`WeakFocusHandle::upgrade`] if the element still exists.
370    pub blurred: WeakFocusHandle,
371}
372
373slotmap::new_key_type! {
374    /// A key that identifies one focusable element within the focus map of a window.
375    ///
376    /// Each id is generational, so a stale id never matches a different element.
377    pub struct FocusId;
378}
379
380thread_local! {
381    /// Fallback arena used when no app-specific arena is active.
382    /// In production, each window draw sets CURRENT_ELEMENT_ARENA to the app's arena.
383    pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));
384
385    /// Points to the current App's element arena during draw operations.
386    /// This allows multiple test Apps to have isolated arenas, preventing
387    /// cross-session corruption when the scheduler interleaves their tasks.
388    static CURRENT_ELEMENT_ARENA: Cell<Option<*const RefCell<Arena>>> = const { Cell::new(None) };
389}
390
391/// Whether a window draw is currently in progress on this thread.
392///
393/// This holds exactly while an `ElementArenaScope` is active: nested scopes
394/// restore the previous (still set) arena pointer, so `CURRENT_ELEMENT_ARENA`
395/// is `Some` from the outermost draw's start to its end.
396///
397/// The `on_request_frame` callback uses this to defer draw requests that
398/// arrive re-entrantly while a draw is already on the stack (e.g. via nested
399/// message pumping in the Windows window procedure), instead of running a
400/// nested draw or panicking on the already-borrowed App.
401fn draw_in_progress() -> bool {
402    CURRENT_ELEMENT_ARENA.with(|current| current.get().is_some())
403}
404
405/// Allocates an element in the current arena. Uses the app-specific arena if one
406/// is active (during draw), otherwise falls back to the thread-local ELEMENT_ARENA.
407#[inline(always)]
408pub(crate) fn with_element_arena<R>(callback: impl FnOnce(&mut Arena) -> R) -> R {
409    let mut callback = Some(callback);
410    let mut result = None;
411    let access = with_element_arena_erased(&mut |arena| {
412        result = Some(callback.take().expect("arena callback runs once")(arena));
413    });
414    drop(callback);
415    access.expect("cannot access a Thread Local Storage value during or after destruction");
416    result.expect("arena callback produces a result")
417}
418
419/// Scope guard that sets CURRENT_ELEMENT_ARENA for the duration of a draw
420/// operation and tracks the arena's scope depth, so that a nested draw's
421/// `ArenaClearNeeded::clear` is deferred rather than freeing memory the outer
422/// draw still references (see `Arena::clear`).
423///
424/// Call [`ElementArenaScope::exit`] with the same arena that was entered to
425/// obtain the [`ArenaClearNeeded`] token the draw now owes; requiring `exit`
426/// makes it impossible to request a clear before the scope has ended. The
427/// scope's teardown — restoring the thread-local and balancing `begin_scope`
428/// with `end_scope` — happens in `Drop`, so the arena's scope depth stays
429/// balanced on every path, including when a panic unwinds a draw before `exit`
430/// is reached. (If teardown lived only in `exit`, such a panic would leave the
431/// scope depth permanently elevated and defer every future clear, leaking
432/// memory unboundedly.)
433pub(crate) struct ElementArenaScope {
434    /// The entered arena: compared against the argument in `exit`, and
435    /// dereferenced in `Drop` to end its scope (see the SAFETY note there).
436    entered: *const RefCell<Arena>,
437    previous: Option<*const RefCell<Arena>>,
438    exited: bool,
439}
440
441impl ElementArenaScope {
442    /// Enter a scope where element allocations use the given arena.
443    pub(crate) fn enter(arena: &RefCell<Arena>) -> Self {
444        arena.borrow_mut().begin_scope();
445        let previous = CURRENT_ELEMENT_ARENA.with(|current| {
446            let prev = current.get();
447            current.set(Some(arena as *const RefCell<Arena>));
448            prev
449        });
450        Self {
451            entered: arena as *const RefCell<Arena>,
452            previous,
453            exited: false,
454        }
455    }
456
457    /// End the scope: restores the previously-current arena and ends the
458    /// arena's clear-deferral scope. Returns the token for the arena clear the
459    /// draw now owes; producing it here makes it impossible to request a clear
460    /// before the scope has ended (which would be silently deferred forever).
461    ///
462    /// Panics if passed a different arena than was entered: ending the scope
463    /// of the wrong arena would unbalance two arenas' scope depths, allowing
464    /// one of them to clear while a draw still references its memory.
465    pub(crate) fn exit(mut self, arena: &RefCell<Arena>) -> ArenaClearNeeded {
466        assert!(
467            std::ptr::eq(self.entered, arena),
468            "ElementArenaScope::exit called with a different arena than was entered"
469        );
470        self.exited = true;
471        // Teardown (restoring the thread-local and ending the arena's
472        // clear-deferral scope) runs in `Drop`, which fires both here — `self`
473        // is dropped as `exit` returns, before the token reaches the caller —
474        // and when a panic unwinds the draw before `exit` is reached.
475        ArenaClearNeeded::new(arena)
476    }
477}
478
479impl Drop for ElementArenaScope {
480    fn drop(&mut self) {
481        // Teardown lives here (rather than in `exit`) so it runs exactly once on
482        // every path: `exit` consumes and drops the guard on the normal path,
483        // and unwinding drops it on the panic path. Balancing `begin_scope` here
484        // keeps the arena's scope depth correct even when a draw panics; if this
485        // only happened in `exit`, a panic between `enter` and `exit` would leave
486        // the depth elevated and defer every future clear.
487        CURRENT_ELEMENT_ARENA.with(|current| {
488            current.set(self.previous);
489        });
490        // SAFETY: `entered` came from a `&RefCell<Arena>` in `enter`, and the
491        // arena (owned by the `App` being drawn) outlives this guard on both the
492        // normal and unwinding paths, since the guard is a local of the draw.
493        unsafe { &*self.entered }.borrow_mut().end_scope();
494        if !self.exited && !std::thread::panicking() {
495            debug_assert!(false, "ElementArenaScope dropped without calling exit()");
496            log::error!(
497                "ElementArenaScope dropped without calling exit(); \
498                 the arena clear for this draw was never requested"
499            );
500        }
501    }
502}
503
504/// Returned when the element arena has been used and so must be cleared before the next draw.
505#[must_use]
506pub struct ArenaClearNeeded {
507    /// Identity of the arena that was drawn into. Only ever compared against
508    /// another pointer in `clear`; never dereferenced.
509    arena: *const RefCell<Arena>,
510}
511
512impl ArenaClearNeeded {
513    /// Create a new ArenaClearNeeded token for the App whose arena was drawn
514    /// into. Private: the only way to obtain one is [`ElementArenaScope::exit`].
515    fn new(arena: &RefCell<Arena>) -> Self {
516        Self {
517            arena: arena as *const RefCell<Arena>,
518        }
519    }
520
521    /// Clear the element arena of the App the draw ran against. If an enclosing
522    /// draw is still in progress (this draw was nested inside it), the clear is
523    /// deferred to the enclosing draw's own `ArenaClearNeeded` so that its live
524    /// allocations aren't freed.
525    ///
526    /// Panics if passed a different App than the draw ran against, since
527    /// clearing another App's arena could free memory its draws still
528    /// reference.
529    pub fn clear(self, cx: &mut App) {
530        assert!(
531            std::ptr::eq(self.arena, &cx.element_arena),
532            "ArenaClearNeeded::clear called with a different App than the draw ran against"
533        );
534        cx.element_arena.borrow_mut().clear();
535    }
536}
537
538#[derive(Default)]
539pub(crate) struct FocusMap {
540    pub(crate) handles: SlotMap<FocusId, FocusRef>,
541    pub(crate) dropped_handles: Vec<FocusId>,
542}
543
544pub(crate) struct FocusRef {
545    pub(crate) ref_count: AtomicUsize,
546    pub(crate) tab_index: isize,
547    pub(crate) tab_stop: bool,
548}
549
550impl FocusId {
551    /// Returns whether this id is the window's focused element.
552    pub fn is_focused(&self, window: &Window) -> bool {
553        window.focus == Some(*self)
554    }
555
556    /// Returns whether the focused element is this element or one of its descendants.
557    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
558        window
559            .focused(cx)
560            .is_some_and(|focused| self.contains(focused.id, window))
561    }
562
563    /// Returns whether the focused element is this element's ancestor or the element itself.
564    pub fn within_focused(&self, window: &Window, cx: &App) -> bool {
565        let focused = window.focused(cx);
566        focused.is_some_and(|focused| focused.id.contains(*self, window))
567    }
568
569    /// Returns whether `other` is this element or a descendant of it, using the last rendered frame.
570    pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {
571        window
572            .rendered_frame
573            .dispatch_tree
574            .focus_contains(*self, other)
575    }
576}
577
578/// A handle that makes an element focusable and tracks whether it has focus.
579///
580/// Create one with [`App::focus_handle`] in the view that owns the element,
581/// store it in the view, and attach it to the element with
582/// [`InteractiveElement::track_focus`](crate::InteractiveElement::track_focus). While a clone of the handle is alive, the
583/// window keeps the element's focus id.
584///
585/// Use [`Window::focus`] to move focus to a handle and [`Window::focused`] to
586/// find the handle that has focus. [`FocusHandle::downgrade`] returns a
587/// [`WeakFocusHandle`], which doesn't keep the focus id alive.
588///
589/// # Examples
590///
591/// ```
592/// # use gpui::{TestApp, Window, Context, FocusHandle, div, prelude::*};
593/// # struct Field { focus_handle: FocusHandle }
594/// # impl Render for Field {
595/// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
596/// #         div().track_focus(&self.focus_handle)
597/// #     }
598/// # }
599/// # let mut app = TestApp::new();
600/// # let mut window = app.open_window(|window, cx| {
601/// let focus_handle = cx.focus_handle();
602/// window.focus(&focus_handle, cx);
603/// Field { focus_handle }
604/// # });
605/// window.update(|field, window, _cx| assert!(field.focus_handle.is_focused(window)));
606/// ```
607///
608/// See the [focus guide](crate::_documentation::guides::focus) and
609/// [input dispatch](crate::_documentation::concepts::input_dispatch).
610pub struct FocusHandle {
611    pub(crate) id: FocusId,
612    handles: Arc<RwLock<FocusMap>>,
613    /// The index of this element in the tab order.
614    pub tab_index: isize,
615    /// Whether this element can be focused by tab navigation.
616    pub tab_stop: bool,
617}
618
619impl std::fmt::Debug for FocusHandle {
620    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
621        f.write_fmt(format_args!("FocusHandle({:?})", self.id))
622    }
623}
624
625impl FocusHandle {
626    pub(crate) fn new(handles: &Arc<RwLock<FocusMap>>) -> Self {
627        let id = handles.write().handles.insert(FocusRef {
628            ref_count: AtomicUsize::new(1),
629            tab_index: 0,
630            tab_stop: false,
631        });
632
633        Self {
634            id,
635            tab_index: 0,
636            tab_stop: false,
637            handles: handles.clone(),
638        }
639    }
640
641    pub(crate) fn for_id(id: FocusId, handles: &Arc<RwLock<FocusMap>>) -> Option<Self> {
642        let lock = handles.read();
643        let focus = lock.handles.get(id)?;
644        if atomic_incr_if_not_zero(&focus.ref_count) == 0 {
645            return None;
646        }
647        Some(Self {
648            id,
649            tab_index: focus.tab_index,
650            tab_stop: focus.tab_stop,
651            handles: handles.clone(),
652        })
653    }
654
655    /// Sets the index that orders this handle among tab stops.
656    ///
657    /// The index is stored in the window's focus map, so it applies to every
658    /// clone of this handle. It affects only the order used by [`Window::focus_next`]
659    /// and [`Window::focus_prev`].
660    ///
661    /// # Examples
662    ///
663    /// ```
664    /// # use gpui::TestApp;
665    /// # let mut app = TestApp::new();
666    /// # app.update(|cx| {
667    /// let handle = cx.focus_handle().tab_index(2).tab_stop(true);
668    /// assert_eq!(handle.tab_index, 2);
669    /// assert!(handle.tab_stop);
670    /// # });
671    /// ```
672    pub fn tab_index(mut self, index: isize) -> Self {
673        self.tab_index = index;
674        if let Some(focus) = self.handles.write().handles.get_mut(self.id) {
675            focus.tab_index = index;
676        }
677        self
678    }
679
680    /// Sets whether this handle is a tab stop.
681    ///
682    /// When `false`, [`Window::focus_next`] and [`Window::focus_prev`] skip this element.
683    /// Programmatic focus with [`Window::focus`] still works.
684    pub fn tab_stop(mut self, tab_stop: bool) -> Self {
685        self.tab_stop = tab_stop;
686        if let Some(focus) = self.handles.write().handles.get_mut(self.id) {
687            focus.tab_stop = tab_stop;
688        }
689        self
690    }
691
692    /// Returns a [`WeakFocusHandle`] that doesn't keep the focus id alive.
693    pub fn downgrade(&self) -> WeakFocusHandle {
694        WeakFocusHandle {
695            id: self.id,
696            handles: Arc::downgrade(&self.handles),
697        }
698    }
699
700    /// Moves focus to this handle's element. Same as [`Window::focus`].
701    pub fn focus(&self, window: &mut Window, cx: &mut App) {
702        window.focus(self, cx)
703    }
704
705    /// Returns whether this handle's element has focus.
706    pub fn is_focused(&self, window: &Window) -> bool {
707        self.id.is_focused(window)
708    }
709
710    /// Returns whether the focused element is this element or one of its descendants.
711    pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
712        self.id.contains_focused(window, cx)
713    }
714
715    /// Returns whether the focused element is this element's ancestor or the element itself.
716    pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {
717        self.id.within_focused(window, cx)
718    }
719
720    /// Returns whether `other` is this element or a descendant of it, using the last rendered frame.
721    pub fn contains(&self, other: &Self, window: &Window) -> bool {
722        self.id.contains(other.id, window)
723    }
724
725    /// Dispatches `action` along the element that rendered this handle.
726    ///
727    /// The action runs through the element's capture and bubble listeners,
728    /// the same way a keybinding would dispatch it. Nothing happens if the
729    /// element isn't in the last rendered frame.
730    pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {
731        if let Some(node_id) = window
732            .rendered_frame
733            .dispatch_tree
734            .focusable_node_id(self.id)
735        {
736            window.dispatch_action_on_node(node_id, action, cx)
737        }
738    }
739}
740
741impl Clone for FocusHandle {
742    fn clone(&self) -> Self {
743        Self::for_id(self.id, &self.handles).unwrap()
744    }
745}
746
747impl PartialEq for FocusHandle {
748    fn eq(&self, other: &Self) -> bool {
749        self.id == other.id
750    }
751}
752
753impl Eq for FocusHandle {}
754
755impl Drop for FocusHandle {
756    fn drop(&mut self) {
757        let handles = self.handles.upgradable_read();
758        let focus = handles.handles.get(self.id).expect("focus handle missing");
759        let previous_count = focus.ref_count.fetch_sub(1, SeqCst);
760        assert_ne!(previous_count, 0, "over-released focus handle");
761        if previous_count == 1 {
762            RwLockUpgradableReadGuard::upgrade(handles)
763                .dropped_handles
764                .push(self.id);
765        }
766    }
767}
768
769/// A focus handle that doesn't keep its element focusable.
770///
771/// Use it to remember which element had focus, such as in a [`FocusOutEvent`],
772/// without keeping that element alive. Create one with [`FocusHandle::downgrade`].
773#[derive(Clone, Debug)]
774pub struct WeakFocusHandle {
775    pub(crate) id: FocusId,
776    pub(crate) handles: Weak<RwLock<FocusMap>>,
777}
778
779impl WeakFocusHandle {
780    /// Returns a [`FocusHandle`] for the same element, or `None` if every strong handle is gone.
781    pub fn upgrade(&self) -> Option<FocusHandle> {
782        let handles = self.handles.upgrade()?;
783        FocusHandle::for_id(self.id, &handles)
784    }
785}
786
787impl PartialEq for WeakFocusHandle {
788    fn eq(&self, other: &WeakFocusHandle) -> bool {
789        self.id == other.id
790    }
791}
792
793impl Eq for WeakFocusHandle {}
794
795impl PartialEq<FocusHandle> for WeakFocusHandle {
796    fn eq(&self, other: &FocusHandle) -> bool {
797        self.id == other.id
798    }
799}
800
801impl PartialEq<WeakFocusHandle> for FocusHandle {
802    fn eq(&self, other: &WeakFocusHandle) -> bool {
803        self.id == other.id
804    }
805}
806
807/// A view that owns a [`FocusHandle`] and can be focused as a whole.
808///
809/// Implement it on views that should receive keyboard focus. [`Context::focus_view`]
810/// then moves focus to the view's handle, so callers don't need to keep the handle
811/// themselves.
812///
813/// # Examples
814///
815/// ```
816/// # use gpui::{App, Context, FocusHandle, Focusable, Render, TestApp, Window, div, prelude::*};
817/// struct Search {
818///     focus_handle: FocusHandle,
819/// }
820///
821/// impl Focusable for Search {
822///     fn focus_handle(&self, _cx: &App) -> FocusHandle {
823///         self.focus_handle.clone()
824///     }
825/// }
826/// impl Render for Search {
827///     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
828///         div().track_focus(&self.focus_handle)
829///     }
830/// }
831///
832/// # let mut app = TestApp::new();
833/// # let mut window = app.open_window(|_, cx| Search { focus_handle: cx.focus_handle() });
834/// window.update(|search, window, cx| window.focus(&search.focus_handle(cx), cx));
835/// window.update(|search, window, _| assert!(search.focus_handle.is_focused(window)));
836/// ```
837pub trait Focusable: 'static {
838    /// Returns the focus handle for this view.
839    ///
840    /// Return a clone of a handle you stored, not a new one. A new handle has a
841    /// new focus id, so focus moved to it would not match the element you render.
842    fn focus_handle(&self, cx: &App) -> FocusHandle;
843}
844
845impl<V: Focusable> Focusable for Entity<V> {
846    fn focus_handle(&self, cx: &App) -> FocusHandle {
847        self.read(cx).focus_handle(cx)
848    }
849}
850
851/// A view whose lifetime is controlled by a parent view, such as a modal, popover or menu.
852///
853/// The parent creates the view, focuses it, and drops it when the view emits
854/// [`DismissEvent`]. Any type that implements [`Focusable`], [`Render`] and
855/// `EventEmitter<DismissEvent>` implements this trait automatically.
856pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}
857
858impl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}
859
860/// The event a [`ManagedView`] emits to ask its owner to close it.
861///
862/// Emit it with `cx.emit(DismissEvent)` from the view, and subscribe to it in the
863/// parent with `cx.subscribe`. The parent decides what dismissal means, such as
864/// dropping the view or restoring focus.
865pub struct DismissEvent;
866
867type FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;
868
869pub(crate) type AnyMouseListener =
870    Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
871
872#[derive(Clone, Copy)]
873pub(crate) struct PointerChange {
874    pub(crate) position: Option<Point<Pixels>>,
875    pub(crate) cause: PointerChangeCause,
876}
877
878#[derive(Clone, Copy, PartialEq, Eq)]
879pub(crate) enum PointerChangeCause {
880    Input,
881    Layout,
882}
883
884type PointerObserver = Rc<dyn Fn(PointerChange, &mut Window, &mut App)>;
885
886#[derive(Clone)]
887enum CursorStyleRequest {
888    Window(CursorStyleSource),
889    Hitbox {
890        id: HitboxId,
891        style: CursorStyleSource,
892    },
893}
894
895#[derive(Clone)]
896enum CursorStyleSource {
897    Fixed(CursorStyle),
898    Position(Rc<dyn Fn(Point<Pixels>) -> Option<CursorStyle>>),
899}
900
901impl CursorStyleSource {
902    fn resolve(&self, position: Point<Pixels>) -> Option<CursorStyle> {
903        match self {
904            Self::Fixed(style) => Some(*style),
905            Self::Position(resolve) => resolve(position),
906        }
907    }
908}
909
910/// The hitboxes under the mouse, from front to back, as of the last frame.
911///
912/// Returned by [`Window::mouse_hit_test`]. Hitboxes behind one with
913/// [`HitboxBehavior::BlockMouse`] are excluded from the hovered list.
914#[derive(Default, Eq, PartialEq)]
915pub struct HitTest {
916    // HitboxIds which were included in the test's click path (the last of which will be the box that caused occlusion)
917    ordered_ids: SmallVec<[HitboxId; 8]>,
918    // metadata about all hitboxes, even those outside the test's path
919    entries: FxHashMap<HitboxId, HitTestEntry>,
920    // the number of hitbox ids in `ordered_ids` which support mouse. anything after this amount only support scroll.
921    hover_hitbox_count: usize,
922}
923
924impl HitTest {
925    /// Creates a new hit-test by iterating the provided hitboxes to find all those which are not occluded.
926    fn new<'a>(
927        hitboxes: impl ExactSizeIterator<Item = &'a Hitbox>,
928        position: Point<Pixels>,
929    ) -> Self {
930        let mut num_until_mouse_blocked = None::<usize>;
931        let mut ids_until_occlusion = SmallVec::default();
932        let mut entries = FxHashMap::with_capacity_and_hasher(hitboxes.len(), Default::default());
933        let mut found_hit_occlusion = false;
934        // index is 0=closest to viewer, n=farthest from viewer
935        for (index, hitbox) in hitboxes.enumerate() {
936            entries.insert(
937                hitbox.id,
938                HitTestEntry {
939                    depth: index,
940                    tags: hitbox.tags.clone(),
941                },
942            );
943
944            if found_hit_occlusion {
945                continue;
946            }
947
948            if !hitbox.contains(&position) {
949                continue;
950            }
951
952            ids_until_occlusion.push(hitbox.id);
953
954            // Identify the threshold at which mouse is blocked in any way (BlockMouseExceptScroll or BlockMouse)
955            if num_until_mouse_blocked.is_none() && hitbox.behavior.blocks_mouse() {
956                num_until_mouse_blocked = Some(ids_until_occlusion.len());
957            }
958
959            // Found a hitbox that fully occludes boxes behind it. Can now stop iterating.
960            if hitbox.behavior.occludes() {
961                found_hit_occlusion = true;
962            }
963        }
964        Self {
965            hover_hitbox_count: num_until_mouse_blocked.unwrap_or(ids_until_occlusion.len()),
966            ordered_ids: ids_until_occlusion,
967            entries,
968        }
969    }
970
971    /// Returns the hitboxes that receive hover and mouse input, front to back.
972    ///
973    /// The list stops at the first hitbox whose behavior blocks the mouse, which
974    /// is included as the last item. Hitboxes behind it are not hovered.
975    pub fn iter_hovered(&self) -> impl Iterator<Item = &HitboxId> {
976        self.ordered_ids.iter().take(self.hover_hitbox_count)
977    }
978
979    /// Returns the hitboxes that receive scroll events, front to back.
980    ///
981    /// The list runs past hitboxes with [`HitboxBehavior::BlockMouseExceptScroll`],
982    /// and stops after the first one with [`HitboxBehavior::BlockMouse`], which is
983    /// included as the last item.
984    pub fn iter_scrollable(&self) -> impl Iterator<Item = &HitboxId> {
985        self.ordered_ids.iter()
986    }
987
988    /// Returns the metadata of a hitbox in this frame, whether or not it is under the mouse.
989    pub fn entry(&self, id: &HitboxId) -> Option<&HitTestEntry> {
990        self.entries.get(id)
991    }
992}
993
994/// An entry in a [`HitTest`] which represents a [`Hitbox`]. Contains some metadata about the
995/// hitbox in the frame the HitTest was evaluated on.
996#[derive(Debug, PartialEq, Eq)]
997pub struct HitTestEntry {
998    /// The depth of the hitbox in the ordered list from the Frame.
999    /// A smaller number is closer to the viewer, and a larger number is farther from the viewer.
1000    depth: usize,
1001    tags: Vec<SharedString>,
1002}
1003
1004impl HitTestEntry {
1005    /// Returns the position of the [`Hitbox`] in the frame's front-to-back order.
1006    ///
1007    /// Zero is the frontmost hitbox. Larger values are farther from the viewer.
1008    pub fn depth(&self) -> usize {
1009        self.depth
1010    }
1011
1012    /// Returns the tags that were attached to the [`Hitbox`] when it was inserted.
1013    pub fn tags(&self) -> &Vec<SharedString> {
1014        &self.tags
1015    }
1016}
1017
1018/// A region of a custom title bar that the operating system treats as a window control.
1019///
1020/// Register a region with [`Window::insert_window_control_hitbox`] so that the
1021/// platform can drag, maximize, minimize or close the window from your title bar.
1022#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1023pub enum WindowControlArea {
1024    /// Dragging this area moves the window.
1025    Drag,
1026    /// Clicking this area closes the window.
1027    Close,
1028    /// Clicking this area maximizes the window.
1029    Max,
1030    /// Clicking this area minimizes the window.
1031    Min,
1032}
1033
1034/// Identifies a [`Hitbox`] in the frame that inserted it.
1035///
1036/// Ids are assigned in insertion order during prepaint, so they are stable within
1037/// one frame but not across frames. Compare them only with ids from the same frame.
1038#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1039pub struct HitboxId(u64);
1040
1041#[cfg(feature = "test-support")]
1042impl HitboxId {
1043    /// Returns an id that is valid for tests which need a [`HitboxId`] but don't use its value.
1044    ///
1045    /// Only available with the `test-support` feature. Don't pass it to window methods
1046    /// that look up a real hitbox.
1047    pub const fn placeholder() -> Self {
1048        Self(0)
1049    }
1050}
1051
1052impl HitboxId {
1053    /// Returns whether the mouse is over this hitbox and it isn't covered by a blocking hitbox.
1054    ///
1055    /// Always `true` if this hitbox has captured the pointer. Returns `false`
1056    /// during keyboard input, so keyboard navigation hides hover styles. See
1057    /// [`Hitbox::is_hovered`] for details.
1058    pub fn is_hovered(self, window: &Window) -> bool {
1059        // If this hitbox has captured the pointer, it's always considered hovered
1060        if window.captured_hitbox == Some(self) {
1061            return true;
1062        }
1063        if window.last_input_was_keyboard() {
1064            return false;
1065        }
1066        self.hit_test(window)
1067    }
1068
1069    /// Checks if the hitbox with this ID is currently hovered, regardless of the last
1070    /// input modality used.
1071    ///
1072    /// See [`HitboxId::is_hovered`] for more details.
1073    pub(crate) fn is_hovered_ignoring_last_input(self, window: &Window) -> bool {
1074        // If this hitbox has captured the pointer, it's always considered hovered
1075        if window.captured_hitbox == Some(self) {
1076            return true;
1077        }
1078        self.hit_test(window)
1079    }
1080
1081    fn hit_test(self, window: &Window) -> bool {
1082        window.mouse_hit_test().iter_hovered().contains(&self)
1083    }
1084
1085    /// Returns whether the mouse is over this hitbox and it should handle scroll events.
1086    ///
1087    /// Use this for `ScrollWheelEvent` handlers, and [`HitboxId::is_hovered`] for
1088    /// everything else. See [`Hitbox::is_hovered`] for why the two differ.
1089    pub fn should_handle_scroll(self, window: &Window) -> bool {
1090        window.mouse_hit_test().iter_scrollable().contains(&self)
1091    }
1092
1093    fn next(mut self) -> HitboxId {
1094        HitboxId(self.0.wrapping_add(1))
1095    }
1096}
1097
1098/// A region that receives mouse input for the frame it was inserted in.
1099///
1100/// Create one with [`Window::insert_hitbox`] during prepaint. Hitboxes are how
1101/// GPUI decides which element is under the pointer: the pointer is tested against
1102/// the hitboxes of the last frame, and listeners registered during paint are
1103/// offered the event only when their element's hitbox was hit. A `Hitbox`
1104/// derefs to its [`bounds`](Hitbox::bounds), so `hitbox.size` and
1105/// `hitbox.origin` work directly.
1106///
1107/// See [input dispatch](crate::_documentation::concepts::input_dispatch) for the
1108/// full order of events and [the frame](crate::_documentation::concepts::the_frame)
1109/// for when hitboxes are created.
1110#[derive(Clone, Debug, Deref)]
1111pub struct Hitbox {
1112    /// The unique id of this hitbox in its frame.
1113    pub id: HitboxId,
1114    /// The rectangle this hitbox covers, in window coordinates.
1115    #[deref]
1116    pub bounds: Bounds<Pixels>,
1117    /// The content mask that was active when the hitbox was inserted.
1118    ///
1119    /// Parts of the hitbox outside this mask, such as an area scrolled out of a
1120    /// container, don't receive input.
1121    pub content_mask: ContentMask<Pixels>,
1122    /// How this hitbox affects hitboxes behind it.
1123    pub behavior: HitboxBehavior,
1124    /// The disjoint rectangles of an inline element, when it spans several lines.
1125    ///
1126    /// When this is `Some`, the hitbox covers these rectangles instead of `bounds`,
1127    /// which is their bounding box.
1128    pub fragments: Option<Arc<[Bounds<Pixels>]>>,
1129    /// Tags attached to this hitbox, which you can read back with [`HitTestEntry::tags`].
1130    pub tags: Vec<SharedString>,
1131}
1132
1133impl Hitbox {
1134    /// Returns whether `point` lies inside this hitbox's content mask and its bounds.
1135    ///
1136    /// This check ignores occlusion, so a point can be inside a hitbox that is
1137    /// covered by another one. Use [`Hitbox::is_hovered`] to check what the
1138    /// mouse is actually over.
1139    pub fn contains(&self, point: &Point<Pixels>) -> bool {
1140        self.content_mask.bounds.contains(point)
1141            && self.fragments.as_ref().map_or_else(
1142                || self.bounds.contains(point),
1143                |fragments| fragments.iter().any(|bounds| bounds.contains(point)),
1144            )
1145    }
1146
1147    /// Returns whether the mouse is over this hitbox, for hover styles and mouse handlers.
1148    ///
1149    /// This returns `false` when a hitbox in front of this one blocks the mouse,
1150    /// with [`InteractiveElement::occlude`](crate::InteractiveElement::occlude) or [`InteractiveElement::block_mouse_except_scroll`](crate::InteractiveElement::block_mouse_except_scroll).
1151    /// It also returns `false` during keyboard input, so keyboard navigation doesn't
1152    /// show hover styles. Use this for clicks, moves and hover styling. For scroll
1153    /// handling, use [`Hitbox::should_handle_scroll`], because a scrollable container
1154    /// under an overlay should still scroll.
1155    pub fn is_hovered(&self, window: &Window) -> bool {
1156        self.id.is_hovered(window)
1157    }
1158
1159    /// Checks whether this hitbox would be hovered at `position`, regardless of the current input
1160    /// modality or mouse position.
1161    pub fn is_hovered_at(&self, position: Point<Pixels>, window: &Window) -> bool {
1162        let hit_test = window.rendered_frame.hit_test(position);
1163        hit_test.iter_hovered().any(|id| self.id == *id)
1164    }
1165
1166    /// Returns whether the mouse is over this hitbox and this hitbox should handle scroll events.
1167    ///
1168    /// Use it in `ScrollWheelEvent` handlers. It returns `false` only when a
1169    /// [`HitboxBehavior::BlockMouse`] hitbox is in front of this one, so overlays
1170    /// can block clicks without blocking scrolling underneath.
1171    pub fn should_handle_scroll(&self, window: &Window) -> bool {
1172        self.id.should_handle_scroll(window)
1173    }
1174}
1175
1176/// How a hitbox affects the hitboxes behind it.
1177///
1178/// Set it with the `behavior` argument of [`Window::insert_hitbox`]. A hitbox
1179/// with [`HitboxBehavior::BlockMouse`] or [`HitboxBehavior::BlockMouseExceptScroll`]
1180/// is the last one that can be hovered in its area, so hover styles, tooltips and
1181/// mouse listeners don't reach the elements behind it.
1182#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1183pub enum HitboxBehavior {
1184    /// The hitbox doesn't change what is hovered behind it.
1185    ///
1186    /// Hitboxes behind it remain hovered and receive mouse events, as well as
1187    /// this one.
1188    #[default]
1189    Normal,
1190
1191    /// Hitboxes behind this one are neither hovered nor scrollable.
1192    ///
1193    /// Clicks, moves, hover styles and tooltips all skip the hitboxes behind
1194    /// it. Set by [`InteractiveElement::occlude`](crate::InteractiveElement::occlude). Use it for overlays such as
1195    /// popovers and modals.
1196    BlockMouse,
1197
1198    /// Hitboxes behind this one are not hovered, but they still scroll.
1199    ///
1200    /// Clicks, moves, hover styles and tooltips skip the hitboxes behind it, but
1201    /// [`Hitbox::should_handle_scroll`] still returns `true` for them. Set by
1202    /// [`InteractiveElement::block_mouse_except_scroll`](crate::InteractiveElement::block_mouse_except_scroll). Use it for a panel
1203    /// over a scrollable list that should keep scrolling.
1204    BlockMouseExceptScroll,
1205}
1206
1207impl HitboxBehavior {
1208    /// Returns `true` if hitboxes behind this one can't be hovered.
1209    pub fn blocks_mouse(&self) -> bool {
1210        matches!(self, Self::BlockMouse | Self::BlockMouseExceptScroll)
1211    }
1212
1213    /// Returns `true` if hitboxes behind this one can't be hovered or scrolled.
1214    pub fn occludes(&self) -> bool {
1215        matches!(self, Self::BlockMouse)
1216    }
1217}
1218
1219/// Identifies a tooltip set during prepaint with [`Window::set_tooltip`].
1220#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
1221pub struct TooltipId(usize);
1222
1223impl TooltipId {
1224    /// Returns whether the mouse is over the tooltip shown for this id in the last frame.
1225    pub fn is_hovered(&self, window: &Window) -> bool {
1226        window
1227            .tooltip_bounds
1228            .as_ref()
1229            .is_some_and(|tooltip_bounds| {
1230                tooltip_bounds.id == *self
1231                    && tooltip_bounds.bounds.contains(&window.mouse_position())
1232            })
1233    }
1234}
1235
1236pub(crate) struct TooltipBounds {
1237    id: TooltipId,
1238    bounds: Bounds<Pixels>,
1239}
1240
1241#[derive(Clone)]
1242pub(crate) struct TooltipRequest {
1243    id: TooltipId,
1244    tooltip: AnyTooltip,
1245}
1246
1247/// The ids of the elements being drawn, root first, with the hash of every
1248/// prefix alongside: a [`GlobalElementId`] for the current element is then
1249/// the ids cloned out and the hash on top of the stack, without walking the
1250/// path — the ids of every ancestor, string names byte by byte — for each
1251/// element on every frame.
1252#[derive(Clone, Default)]
1253pub(crate) struct ElementIdStack {
1254    ids: SmallVec<[ElementId; 32]>,
1255    hashes: SmallVec<[u64; 32]>,
1256}
1257
1258impl ElementIdStack {
1259    pub(crate) fn push(&mut self, id: ElementId) {
1260        self.hashes.push(crate::extend_path_hash(self.hash(), &id));
1261        self.ids.push(id);
1262    }
1263
1264    pub(crate) fn pop(&mut self) -> Option<ElementId> {
1265        self.hashes.pop();
1266        self.ids.pop()
1267    }
1268
1269    pub(crate) fn clear(&mut self) {
1270        self.ids.clear();
1271        self.hashes.clear();
1272    }
1273
1274    /// The hash of the whole path on the stack.
1275    fn hash(&self) -> u64 {
1276        self.hashes
1277            .last()
1278            .copied()
1279            .unwrap_or(crate::EMPTY_PATH_HASH)
1280    }
1281
1282    pub(crate) fn global_id(&self) -> GlobalElementId {
1283        GlobalElementId::with_hash(&self.ids, self.hash())
1284    }
1285}
1286
1287impl std::ops::Deref for ElementIdStack {
1288    type Target = [ElementId];
1289
1290    fn deref(&self) -> &Self::Target {
1291        &self.ids
1292    }
1293}
1294
1295pub(crate) struct DeferredDraw {
1296    current_view: EntityId,
1297    priority: usize,
1298    parent_node: DispatchNodeId,
1299    element_id_stack: ElementIdStack,
1300    text_style_stack: Vec<TextStyleRefinement>,
1301    content_mask: Option<ContentMask<Pixels>>,
1302    rem_size: Pixels,
1303    element: Option<AnyElement>,
1304    absolute_offset: Point<Pixels>,
1305    prepaint_range: Range<PrepaintStateIndex>,
1306    paint_range: Range<PaintIndex>,
1307}
1308
1309pub(crate) struct Frame {
1310    pub(crate) focus: Option<FocusId>,
1311    pub(crate) window_active: bool,
1312    pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
1313    accessed_element_states: Vec<(GlobalElementId, TypeId)>,
1314    pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
1315    pointer_observers: Rc<Vec<PointerObserver>>,
1316    pub(crate) dispatch_tree: DispatchTree,
1317    pub(crate) scene: Scene,
1318    pub(crate) hitboxes: Vec<Hitbox>,
1319    pub(crate) window_control_hitboxes: Vec<(WindowControlArea, Hitbox)>,
1320    pub(crate) deferred_draws: Vec<DeferredDraw>,
1321    pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
1322    pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,
1323    cursor_styles: Vec<CursorStyleRequest>,
1324    #[cfg(any(test, feature = "test-support"))]
1325    pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
1326    #[cfg(any(test, feature = "test-support"))]
1327    debug_bounds_records: Vec<(String, Bounds<Pixels>)>,
1328    #[cfg(any(feature = "inspector", debug_assertions))]
1329    pub(crate) next_inspector_instance_ids: FxHashMap<Rc<crate::InspectorElementPath>, usize>,
1330    #[cfg(any(feature = "inspector", debug_assertions))]
1331    pub(crate) inspector_hitboxes: FxHashMap<HitboxId, crate::InspectorElementId>,
1332    pub(crate) tab_stops: TabStopMap,
1333}
1334
1335#[derive(Clone, Default)]
1336pub(crate) struct PrepaintStateIndex {
1337    hitboxes_index: usize,
1338    tooltips_index: usize,
1339    deferred_draws_index: usize,
1340    dispatch_tree_index: usize,
1341    accessed_element_states_index: usize,
1342    line_layout_index: LineLayoutIndex,
1343}
1344
1345#[derive(Clone, Default)]
1346pub(crate) struct PaintIndex {
1347    scene_index: usize,
1348    #[cfg(any(test, feature = "test-support"))]
1349    debug_bounds_index: usize,
1350    mouse_listeners_index: usize,
1351    pointer_observers_index: usize,
1352    input_handlers_index: usize,
1353    cursor_styles_index: usize,
1354    accessed_element_states_index: usize,
1355    tab_handle_index: usize,
1356    line_layout_index: LineLayoutIndex,
1357}
1358
1359impl PrepaintStateIndex {
1360    /// Whether every lane of `inner` lies inside `outer`.
1361    pub(crate) fn within(inner: &Range<Self>, outer: &Range<Self>) -> bool {
1362        let lanes = |index: &Self| {
1363            [
1364                index.hitboxes_index,
1365                index.tooltips_index,
1366                index.deferred_draws_index,
1367                index.dispatch_tree_index,
1368                index.accessed_element_states_index,
1369            ]
1370        };
1371        within_lanes(
1372            lanes(&inner.start),
1373            lanes(&inner.end),
1374            lanes(&outer.start),
1375            lanes(&outer.end),
1376        )
1377    }
1378
1379    /// Where this index, inside `source`, lands when `source` is copied to `destination`.
1380    pub(crate) fn rebased(&self, source: &Range<Self>, destination: &Self) -> Self {
1381        let shift = |index: usize, start: usize, to: usize| index - start + to;
1382        let (from, to) = (&source.start, destination);
1383        Self {
1384            hitboxes_index: shift(self.hitboxes_index, from.hitboxes_index, to.hitboxes_index),
1385            tooltips_index: shift(self.tooltips_index, from.tooltips_index, to.tooltips_index),
1386            deferred_draws_index: shift(
1387                self.deferred_draws_index,
1388                from.deferred_draws_index,
1389                to.deferred_draws_index,
1390            ),
1391            dispatch_tree_index: shift(
1392                self.dispatch_tree_index,
1393                from.dispatch_tree_index,
1394                to.dispatch_tree_index,
1395            ),
1396            accessed_element_states_index: shift(
1397                self.accessed_element_states_index,
1398                from.accessed_element_states_index,
1399                to.accessed_element_states_index,
1400            ),
1401            line_layout_index: self
1402                .line_layout_index
1403                .rebased(&from.line_layout_index, &to.line_layout_index),
1404        }
1405    }
1406}
1407
1408fn within_lanes<const N: usize>(
1409    inner_start: [usize; N],
1410    inner_end: [usize; N],
1411    outer_start: [usize; N],
1412    outer_end: [usize; N],
1413) -> bool {
1414    (0..N).all(|lane| {
1415        outer_start[lane] <= inner_start[lane]
1416            && inner_start[lane] <= inner_end[lane]
1417            && inner_end[lane] <= outer_end[lane]
1418    })
1419}
1420
1421impl PaintIndex {
1422    /// Whether every lane of `inner` lies inside `outer`.
1423    pub(crate) fn within(inner: &Range<Self>, outer: &Range<Self>) -> bool {
1424        let lanes = |index: &Self| {
1425            [
1426                index.scene_index,
1427                index.mouse_listeners_index,
1428                index.pointer_observers_index,
1429                index.input_handlers_index,
1430                index.cursor_styles_index,
1431                index.accessed_element_states_index,
1432                index.tab_handle_index,
1433            ]
1434        };
1435        within_lanes(
1436            lanes(&inner.start),
1437            lanes(&inner.end),
1438            lanes(&outer.start),
1439            lanes(&outer.end),
1440        )
1441    }
1442
1443    /// Where this index, inside `source`, lands when `source` is copied to `destination`.
1444    pub(crate) fn rebased(&self, source: &Range<Self>, destination: &Self) -> Self {
1445        let shift = |index: usize, start: usize, to: usize| index - start + to;
1446        let (from, to) = (&source.start, destination);
1447        Self {
1448            scene_index: shift(self.scene_index, from.scene_index, to.scene_index),
1449            #[cfg(any(test, feature = "test-support"))]
1450            debug_bounds_index: shift(
1451                self.debug_bounds_index,
1452                from.debug_bounds_index,
1453                to.debug_bounds_index,
1454            ),
1455            mouse_listeners_index: shift(
1456                self.mouse_listeners_index,
1457                from.mouse_listeners_index,
1458                to.mouse_listeners_index,
1459            ),
1460            pointer_observers_index: shift(
1461                self.pointer_observers_index,
1462                from.pointer_observers_index,
1463                to.pointer_observers_index,
1464            ),
1465            input_handlers_index: shift(
1466                self.input_handlers_index,
1467                from.input_handlers_index,
1468                to.input_handlers_index,
1469            ),
1470            cursor_styles_index: shift(
1471                self.cursor_styles_index,
1472                from.cursor_styles_index,
1473                to.cursor_styles_index,
1474            ),
1475            accessed_element_states_index: shift(
1476                self.accessed_element_states_index,
1477                from.accessed_element_states_index,
1478                to.accessed_element_states_index,
1479            ),
1480            tab_handle_index: shift(
1481                self.tab_handle_index,
1482                from.tab_handle_index,
1483                to.tab_handle_index,
1484            ),
1485            line_layout_index: self
1486                .line_layout_index
1487                .rebased(&from.line_layout_index, &to.line_layout_index),
1488        }
1489    }
1490}
1491
1492impl Frame {
1493    #[cfg(any(test, feature = "test-support"))]
1494    pub(crate) fn record_debug_bounds(&mut self, selector: String, bounds: Bounds<Pixels>) {
1495        self.debug_bounds.insert(selector.clone(), bounds);
1496        self.debug_bounds_records.push((selector, bounds));
1497    }
1498
1499    pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
1500        Frame {
1501            focus: None,
1502            window_active: false,
1503            element_states: FxHashMap::default(),
1504            accessed_element_states: Vec::new(),
1505            mouse_listeners: Vec::new(),
1506            pointer_observers: Rc::default(),
1507            dispatch_tree,
1508            scene: Scene::default(),
1509            hitboxes: Vec::new(),
1510            window_control_hitboxes: Vec::new(),
1511            deferred_draws: Vec::new(),
1512            input_handlers: Vec::new(),
1513            tooltip_requests: Vec::new(),
1514            cursor_styles: Vec::new(),
1515
1516            #[cfg(any(test, feature = "test-support"))]
1517            debug_bounds: FxHashMap::default(),
1518            #[cfg(any(test, feature = "test-support"))]
1519            debug_bounds_records: Vec::new(),
1520
1521            #[cfg(any(feature = "inspector", debug_assertions))]
1522            next_inspector_instance_ids: FxHashMap::default(),
1523
1524            #[cfg(any(feature = "inspector", debug_assertions))]
1525            inspector_hitboxes: FxHashMap::default(),
1526            tab_stops: TabStopMap::default(),
1527        }
1528    }
1529
1530    pub(crate) fn clear(&mut self) {
1531        self.element_states.clear();
1532        self.accessed_element_states.clear();
1533        self.mouse_listeners.clear();
1534        Rc::make_mut(&mut self.pointer_observers).clear();
1535        self.dispatch_tree.clear();
1536        self.scene.clear();
1537        self.input_handlers.clear();
1538        self.tooltip_requests.clear();
1539        self.cursor_styles.clear();
1540        self.hitboxes.clear();
1541        self.window_control_hitboxes.clear();
1542        self.deferred_draws.clear();
1543        self.tab_stops.clear();
1544        self.focus = None;
1545
1546        #[cfg(any(test, feature = "test-support"))]
1547        {
1548            self.debug_bounds.clear();
1549            self.debug_bounds_records.clear();
1550        }
1551
1552        #[cfg(any(feature = "inspector", debug_assertions))]
1553        {
1554            self.next_inspector_instance_ids.clear();
1555            self.inspector_hitboxes.clear();
1556        }
1557    }
1558
1559    pub(crate) fn cursor_style(&self, window: &Window) -> Option<CursorStyle> {
1560        // Resolve window-wide requests first, regardless of paint order.
1561        self.cursor_styles
1562            .iter()
1563            .rev()
1564            .find_map(|request| match request {
1565                CursorStyleRequest::Window(style) => style.resolve(window.mouse_position()),
1566                CursorStyleRequest::Hitbox { .. } => None,
1567            })
1568            .or_else(|| {
1569                if !window.pointer_inside_window {
1570                    return None;
1571                }
1572                self.cursor_styles
1573                    .iter()
1574                    .rev()
1575                    .find_map(|request| match request {
1576                        CursorStyleRequest::Hitbox { id, style }
1577                            if id.is_hovered_ignoring_last_input(window) =>
1578                        {
1579                            style.resolve(window.mouse_position())
1580                        }
1581                        _ => None,
1582                    })
1583            })
1584    }
1585
1586    pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
1587        HitTest::new(self.hitboxes.iter().rev(), position)
1588    }
1589
1590    pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
1591        self.focus
1592            .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
1593            .unwrap_or_default()
1594    }
1595
1596    pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
1597        for element_state_key in &self.accessed_element_states {
1598            if let Some((element_state_key, element_state)) =
1599                prev_frame.element_states.remove_entry(element_state_key)
1600            {
1601                self.element_states.insert(element_state_key, element_state);
1602            }
1603        }
1604
1605        self.scene.finish();
1606    }
1607}
1608
1609#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
1610pub(crate) enum InputModality {
1611    Mouse,
1612    Keyboard,
1613    Touch,
1614}
1615
1616bitflags::bitflags! {
1617    /// Which window input a view read while drawing, so it is drawn again when that changes.
1618    #[derive(Clone, Copy, Default)]
1619    pub(crate) struct InputReads: u8 {
1620        const POINTER = 1;
1621        const MODIFIERS = 1 << 1;
1622        const MODALITY = 1 << 2;
1623    }
1624}
1625
1626/// The state of one platform window: its focus, input, bounds, frame and drawing.
1627///
1628/// You get a `&mut Window` in [`Render::render`], in event listeners such as
1629/// [`StatefulInteractiveElement::on_click`](crate::StatefulInteractiveElement::on_click), and in [`WindowHandle::update`]. Methods
1630/// group by the job they do:
1631///
1632/// * **Focus and keyboard**: [`Window::focus`], [`Window::focused`],
1633///   [`Window::focus_next`], [`Window::dispatch_keystroke`].
1634/// * **Size and display**: [`Window::bounds`], [`Window::viewport_size`],
1635///   [`Window::scale_factor`], [`Window::rem_size`], [`Window::appearance`].
1636/// * **Mouse and hover**: [`Window::mouse_position`], [`Window::insert_hitbox`],
1637///   [`Window::on_mouse_event`].
1638/// * **Painting** (during paint only): [`Window::paint_quad`], [`Window::paint_path`],
1639///   [`Window::paint_svg`], [`Window::paint_image`], and the other `paint_*` methods.
1640/// * **Layout** (during request layout only): [`Window::request_layout`].
1641/// * **Per-element state**: [`Window::use_state`], [`Window::use_keyed_state`].
1642/// * **Scheduling a frame**: [`Window::refresh`], [`Window::on_next_frame`],
1643///   [`Window::request_animation_frame`].
1644///
1645/// # Examples
1646///
1647/// ```
1648/// # use gpui::{TestApp, Window, Context, div, prelude::*};
1649/// # struct Root;
1650/// # impl Render for Root {
1651/// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
1652/// #         div()
1653/// #     }
1654/// # }
1655/// # let mut app = TestApp::new();
1656/// # let mut window = app.open_window(|_, _| Root);
1657/// window.update(|_, window, cx| {
1658///     let handle = cx.focus_handle();
1659///     window.focus(&handle, cx);
1660///     assert!(window.focused(cx).is_some());
1661/// });
1662/// ```
1663///
1664/// # Phases
1665///
1666/// Several methods may only be called during one phase of a frame. The phase
1667/// names below match the [frame](crate::_documentation::concepts::the_frame):
1668///
1669/// * **Request layout** and **prepaint** are separate phases. [`Render::render`]
1670///   runs during request layout for its view, so `render` may call methods
1671///   marked "request layout or prepaint" but not paint methods.
1672/// * **Paint** runs after prepaint. Only paint methods, and the listener
1673///   registration methods, are valid here.
1674///
1675/// Calling a method in the wrong phase panics in debug builds. Release builds
1676/// don't check, so keep to the phase the method's docs name.
1677///
1678/// See [the frame](crate::_documentation::concepts::the_frame) for the full
1679/// sequence, and the [windows guide](crate::_documentation::guides::windows).
1680pub struct Window {
1681    pub(crate) handle: AnyWindowHandle,
1682    pub(crate) invalidator: WindowInvalidator,
1683    pub(crate) removed: bool,
1684    pub(crate) platform_window: Box<dyn PlatformWindow>,
1685    pub(crate) display_id: Option<DisplayId>,
1686    pub(crate) display_observers: SubscriberSet<(), AnyObserver>,
1687    is_resizable: bool,
1688    is_minimizable: bool,
1689    sprite_atlas: Arc<dyn PlatformAtlas>,
1690    text_system: Arc<WindowTextSystem>,
1691    text_rendering_mode: Rc<Cell<TextRenderingMode>>,
1692    rem_size: Pixels,
1693    /// The stack of override values for the window's rem size.
1694    ///
1695    /// This is used by `with_rem_size` to allow rendering an element tree with
1696    /// a given rem size.
1697    rem_size_override_stack: SmallVec<[Pixels; 8]>,
1698    pub(crate) viewport_size: Size<Pixels>,
1699    layout_engine: Option<TaffyLayoutEngine>,
1700    pub(crate) collecting_inline: bool,
1701    pub(crate) current_inline_fragments: Option<Arc<[Bounds<Pixels>]>>,
1702    pub(crate) root: Option<AnyView>,
1703    pub(crate) element_id_stack: ElementIdStack,
1704    pub(crate) text_style_stack: Vec<TextStyleRefinement>,
1705    pub(crate) measurement_direction: ResolvedDirection,
1706    pub(crate) measurement_unicode_bidi: UnicodeBidi,
1707    pub(crate) rendered_entity_stack: Vec<EntityId>,
1708    pub(crate) element_offset_stack: Vec<Point<Pixels>>,
1709    /// Bounds of the parent `Div` currently prepainting this element as one of its children.
1710    /// Inset transitions use these bounds to resolve `auto` from the child's rendered position.
1711    style_transition_containing_bounds: Option<Bounds<Pixels>>,
1712    pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
1713    pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,
1714    /// The [`TextInputConfiguration`] most recently forwarded to the platform
1715    /// window, so that only actual changes are forwarded (reconfiguring a live
1716    /// input session can restart the IME connection).
1717    last_text_input_configuration: Option<TextInputConfiguration>,
1718    focused_text_input: Option<FocusId>,
1719    pub(crate) image_cache_stack: Vec<AnyImageCache>,
1720    pub(crate) rendered_frame: Frame,
1721    pub(crate) next_frame: Frame,
1722    next_hitbox_id: HitboxId,
1723    pub(crate) next_tooltip_id: TooltipId,
1724    pub(crate) tooltip_bounds: Option<TooltipBounds>,
1725    pub(crate) next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
1726    pub(crate) dirty_views: FxHashSet<EntityId>,
1727    focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
1728    pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,
1729    focus_lost_path: SmallVec<[FocusId; 8]>,
1730    default_prevented: bool,
1731    pub(crate) mouse_position: Point<Pixels>,
1732    pointer_inside_window: bool,
1733    mouse_hit_test: HitTest,
1734    pub(crate) modifiers: Modifiers,
1735    capslock: Capslock,
1736    /// The input read since the drawing view last reset it. See [`InputReads`].
1737    pub(crate) input_reads: Cell<InputReads>,
1738    deferred_priority_stack: Vec<usize>,
1739    /// Counts draws, so retained output knows which frame its ranges index into.
1740    pub(crate) frame_number: u64,
1741    scale_factor: f32,
1742    pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
1743    appearance: WindowAppearance,
1744    pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,
1745    pub(crate) button_layout_observers: SubscriberSet<(), AnyObserver>,
1746    active: Rc<Cell<bool>>,
1747    visibility: WindowVisibility,
1748    pub(crate) visibility_observers:
1749        SubscriberSet<(), Box<dyn FnMut(WindowVisibility, &mut Window, &mut App) -> bool>>,
1750    hovered: Rc<Cell<bool>>,
1751    pub(crate) needs_present: Rc<Cell<bool>>,
1752    /// Tracks recent input event timestamps to determine if input is arriving at a high rate.
1753    /// Used to selectively enable VRR optimization only when input rate exceeds 60fps.
1754    pub(crate) input_rate_tracker: Rc<RefCell<InputRateTracker>>,
1755    #[cfg(feature = "profiler")]
1756    pub(crate) window_profiler: profiler::WindowProfiler,
1757    pub(crate) last_input_modality: InputModality,
1758    touch_gestures: TouchGestureRecognizer,
1759    touch_prediction_enabled: bool,
1760    long_press_timer: Option<Task<()>>,
1761    long_press_capture: Option<EntityId>,
1762    pub(crate) refreshing: bool,
1763    pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,
1764    pub(crate) focus: Option<FocusId>,
1765    focus_enabled: bool,
1766    /// Incremented every time focus moves. Used to invalidate a
1767    /// pending keyboard activation state when focus changes.
1768    pub(crate) focus_generation: u64,
1769    pending_input: Option<PendingInput>,
1770    pending_modifier: ModifierState,
1771    pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,
1772    prompt: Option<RenderablePromptHandle>,
1773    pub(crate) client_inset: Option<Pixels>,
1774    /// The hitbox that has captured the pointer, if any.
1775    /// While captured, mouse events route to this hitbox regardless of hit testing.
1776    captured_hitbox: Option<HitboxId>,
1777    #[cfg(any(feature = "inspector", debug_assertions))]
1778    inspector: Option<Entity<Inspector>>,
1779    #[cfg(feature = "profiler")]
1780    debug_frame_overlay: crate::debug_overlay::DebugFrameOverlay,
1781    pub(crate) a11y: A11y,
1782}
1783
1784#[derive(Clone, Debug, Default)]
1785struct ModifierState {
1786    modifiers: Modifiers,
1787    saw_other_input: bool,
1788}
1789
1790/// Tracks input event timestamps to determine if input is arriving at a high rate.
1791/// Used for selective VRR (Variable Refresh Rate) optimization.
1792#[derive(Clone, Debug)]
1793pub(crate) struct InputRateTracker {
1794    timestamps: Vec<Instant>,
1795    window: Duration,
1796    inputs_per_second: u32,
1797    sustain_until: Instant,
1798    sustain_duration: Duration,
1799}
1800
1801impl Default for InputRateTracker {
1802    fn default() -> Self {
1803        Self {
1804            timestamps: Vec::new(),
1805            window: Duration::from_millis(100),
1806            inputs_per_second: 60,
1807            sustain_until: Instant::now(),
1808            sustain_duration: Duration::from_secs(1),
1809        }
1810    }
1811}
1812
1813impl InputRateTracker {
1814    pub fn record_input(&mut self) {
1815        let now = Instant::now();
1816        self.timestamps.push(now);
1817        self.prune_old_timestamps(now);
1818
1819        let min_events = self.inputs_per_second as u128 * self.window.as_millis() / 1000;
1820        if self.timestamps.len() as u128 >= min_events {
1821            self.sustain_until = now + self.sustain_duration;
1822        }
1823    }
1824
1825    pub fn is_high_rate(&self) -> bool {
1826        Instant::now() < self.sustain_until
1827    }
1828
1829    fn prune_old_timestamps(&mut self, now: Instant) {
1830        self.timestamps
1831            .retain(|&t| now.duration_since(t) <= self.window);
1832    }
1833}
1834
1835#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1836pub(crate) enum DrawPhase {
1837    None,
1838    Prepaint,
1839    Paint,
1840    Focus,
1841}
1842
1843pub(crate) const PENDING_INPUT_TIMEOUT: Duration = Duration::from_secs(1);
1844
1845/// Pending input for a potential multi-stroke key binding.
1846pub struct PendingInputStatus<'a> {
1847    keystrokes: &'a [Keystroke],
1848    timeout: Option<PendingInputTimeoutStatus>,
1849}
1850
1851impl<'a> PendingInputStatus<'a> {
1852    /// Returns the keystrokes entered so far.
1853    pub fn keystrokes(&self) -> &'a [Keystroke] {
1854        self.keystrokes
1855    }
1856
1857    /// Returns the timeout state for flushing this input, if it needs a timeout.
1858    pub fn timeout(&self) -> Option<PendingInputTimeoutStatus> {
1859        self.timeout
1860    }
1861}
1862
1863/// The timeout state for pending input.
1864#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1865pub struct PendingInputTimeoutStatus {
1866    duration: Duration,
1867    remaining: Duration,
1868    started_at: Option<Instant>,
1869    paused: bool,
1870}
1871
1872impl PendingInputTimeoutStatus {
1873    /// Returns the full timeout duration.
1874    pub fn duration(&self) -> Duration {
1875        self.duration
1876    }
1877
1878    /// Returns the duration remaining before pending input is flushed.
1879    pub fn remaining(&self, cx: &App) -> Duration {
1880        self.started_at
1881            .map(|started_at| {
1882                self.remaining
1883                    .saturating_sub(cx.background_executor().now() - started_at)
1884            })
1885            .unwrap_or(self.remaining)
1886    }
1887
1888    /// Returns whether the timeout is paused.
1889    pub fn is_paused(&self) -> bool {
1890        self.paused
1891    }
1892}
1893
1894#[derive(Debug)]
1895struct PendingInputTimeout {
1896    duration: Duration,
1897    remaining: Duration,
1898    state: PendingInputTimeoutState,
1899}
1900
1901#[derive(Debug)]
1902enum PendingInputTimeoutState {
1903    Running { started_at: Instant, task: Task<()> },
1904    Paused { pause: PendingInputTimeoutPause },
1905}
1906
1907#[derive(Debug)]
1908struct PendingInputTimeoutPause {
1909    owner_id: EntityId,
1910    _release_subscription: Subscription,
1911}
1912
1913impl PendingInputTimeout {
1914    fn is_paused(&self) -> bool {
1915        matches!(&self.state, PendingInputTimeoutState::Paused { .. })
1916    }
1917
1918    fn pause(&mut self, pause: PendingInputTimeoutPause, now: Instant) -> bool {
1919        match std::mem::replace(&mut self.state, PendingInputTimeoutState::Paused { pause }) {
1920            PendingInputTimeoutState::Running { started_at, task } => {
1921                self.remaining = self.remaining.saturating_sub(now - started_at);
1922                drop(task);
1923                true
1924            }
1925            previous_state @ PendingInputTimeoutState::Paused { .. } => {
1926                self.state = previous_state;
1927                false
1928            }
1929        }
1930    }
1931
1932    fn pause_owner_id(&self) -> Option<EntityId> {
1933        match &self.state {
1934            PendingInputTimeoutState::Running { .. } => None,
1935            PendingInputTimeoutState::Paused { pause } => Some(pause.owner_id),
1936        }
1937    }
1938
1939    fn resume(&mut self, owner_id: EntityId, started_at: Instant, task: Task<()>) -> bool {
1940        match std::mem::replace(
1941            &mut self.state,
1942            PendingInputTimeoutState::Running { started_at, task },
1943        ) {
1944            PendingInputTimeoutState::Paused { pause } if pause.owner_id == owner_id => true,
1945            previous_state => {
1946                self.state = previous_state;
1947                false
1948            }
1949        }
1950    }
1951
1952    fn reset_duration(&mut self, duration: Duration) {
1953        self.duration = duration;
1954        self.remaining = duration;
1955    }
1956
1957    fn status(&self) -> PendingInputTimeoutStatus {
1958        let (started_at, paused) = match &self.state {
1959            PendingInputTimeoutState::Running { started_at, .. } => (Some(*started_at), false),
1960            PendingInputTimeoutState::Paused { .. } => (None, true),
1961        };
1962        PendingInputTimeoutStatus {
1963            duration: self.duration,
1964            remaining: self.remaining,
1965            started_at,
1966            paused,
1967        }
1968    }
1969}
1970
1971#[derive(Default, Debug)]
1972struct PendingInput {
1973    keystrokes: SmallVec<[Keystroke; 1]>,
1974    focus: Option<FocusId>,
1975    timeout: Option<PendingInputTimeout>,
1976}
1977
1978pub(crate) struct ElementStateBox {
1979    pub(crate) inner: Box<dyn Any>,
1980    #[cfg(debug_assertions)]
1981    pub(crate) type_name: &'static str,
1982}
1983
1984fn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> WindowBounds {
1985    // TODO, BUG: if you open a window with the currently active window
1986    // on the stack, this will erroneously fall back to `None`
1987    //
1988    // TODO these should be the initial window bounds not considering maximized/fullscreen
1989    let active_window_bounds = cx
1990        .active_window()
1991        .and_then(|w| w.update(cx, |_, window, _| window.window_bounds()).ok());
1992
1993    const CASCADE_OFFSET: f32 = 25.0;
1994
1995    let display = display_id
1996        .map(|id| cx.find_display(id))
1997        .unwrap_or_else(|| cx.primary_display());
1998
1999    let default_placement = || Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE);
2000
2001    // Use visible_bounds to exclude taskbar/dock areas
2002    let display_bounds = display
2003        .as_ref()
2004        .map(|d| d.visible_bounds())
2005        .unwrap_or_else(default_placement);
2006
2007    let (
2008        Bounds {
2009            origin: base_origin,
2010            size: base_size,
2011        },
2012        window_bounds_ctor,
2013    ): (_, fn(Bounds<Pixels>) -> WindowBounds) = match active_window_bounds {
2014        Some(bounds) => match bounds {
2015            WindowBounds::Windowed(bounds) => (bounds, WindowBounds::Windowed),
2016            WindowBounds::Maximized(bounds) => (bounds, WindowBounds::Maximized),
2017            WindowBounds::Fullscreen(bounds) => (bounds, WindowBounds::Fullscreen),
2018        },
2019        None => (
2020            display
2021                .as_ref()
2022                .map(|d| d.default_bounds())
2023                .unwrap_or_else(default_placement),
2024            WindowBounds::Windowed,
2025        ),
2026    };
2027
2028    let cascade_offset = point(px(CASCADE_OFFSET), px(CASCADE_OFFSET));
2029    let proposed_origin = base_origin + cascade_offset;
2030    let proposed_bounds = Bounds::new(proposed_origin, base_size);
2031
2032    let display_right = display_bounds.origin.x + display_bounds.size.width;
2033    let display_bottom = display_bounds.origin.y + display_bounds.size.height;
2034    let window_right = proposed_bounds.origin.x + proposed_bounds.size.width;
2035    let window_bottom = proposed_bounds.origin.y + proposed_bounds.size.height;
2036
2037    let fits_horizontally = window_right <= display_right;
2038    let fits_vertically = window_bottom <= display_bottom;
2039
2040    let final_origin = match (fits_horizontally, fits_vertically) {
2041        (true, true) => proposed_origin,
2042        (false, true) => point(display_bounds.origin.x, base_origin.y),
2043        (true, false) => point(base_origin.x, display_bounds.origin.y),
2044        (false, false) => display_bounds.origin,
2045    };
2046    window_bounds_ctor(Bounds::new(final_origin, base_size))
2047}
2048
2049impl Window {
2050    pub(crate) fn new(
2051        handle: AnyWindowHandle,
2052        options: WindowOptions,
2053        cx: &mut App,
2054    ) -> Result<Self> {
2055        let background_appearance = options.background_appearance();
2056        let WindowOptions {
2057            window_bounds,
2058            titlebar,
2059            focus,
2060            show,
2061            kind,
2062            is_movable,
2063            app_owns_titlebar_drag,
2064            inactive_frame_interval,
2065            is_resizable,
2066            is_minimizable,
2067            display_id,
2068            app_id,
2069            window_min_size,
2070            window_decorations,
2071            #[cfg_attr(
2072                not(any(target_os = "linux", target_os = "freebsd")),
2073                allow(unused_variables)
2074            )]
2075            icon,
2076            #[cfg_attr(not(target_os = "macos"), allow(unused_variables))]
2077            tabbing_identifier,
2078            #[cfg_attr(not(target_os = "macos"), allow(unused_variables))]
2079            use_display_p3,
2080            ..
2081        } = options;
2082
2083        let initial_window_title = titlebar
2084            .as_ref()
2085            .and_then(|titlebar| titlebar.title.clone());
2086
2087        let window_bounds = window_bounds.unwrap_or_else(|| default_bounds(display_id, cx));
2088        let mut platform_window = cx.platform.open_window(
2089            handle,
2090            WindowParams {
2091                bounds: window_bounds.get_bounds(),
2092                titlebar,
2093                kind,
2094                is_movable,
2095                app_owns_titlebar_drag,
2096                is_resizable,
2097                is_minimizable,
2098                focus,
2099                show,
2100                display_id,
2101                window_min_size,
2102                app_id: app_id.clone(),
2103                icon,
2104                #[cfg(target_os = "macos")]
2105                tabbing_identifier,
2106                #[cfg(target_os = "macos")]
2107                use_display_p3,
2108            },
2109        )?;
2110
2111        let tab_bar_visible = platform_window.tab_bar_visible();
2112        SystemWindowTabController::init_visible(cx, tab_bar_visible);
2113        if let Some(tabs) = platform_window.tabbed_windows() {
2114            SystemWindowTabController::add_tab(cx, handle.window_id(), tabs);
2115        }
2116
2117        let display_id = platform_window.display().map(|display| display.id());
2118        let sprite_atlas = platform_window.sprite_atlas();
2119        let mouse_position = platform_window.mouse_position();
2120        let modifiers = platform_window.modifiers();
2121        let capslock = platform_window.capslock();
2122        let content_size = platform_window.content_size();
2123        let scale_factor = platform_window.scale_factor();
2124        let appearance = platform_window.appearance();
2125        let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
2126        let invalidator = WindowInvalidator::new(handle.window_id());
2127        let active = Rc::new(Cell::new(platform_window.is_active()));
2128        let visibility = platform_window.visibility();
2129        #[cfg(feature = "profiler")]
2130        profiler::journal::record_window_visibility(handle.window_id(), visibility);
2131        let hovered = Rc::new(Cell::new(platform_window.is_hovered()));
2132        let needs_present = Rc::new(Cell::new(false));
2133        let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
2134        let input_rate_tracker = Rc::new(RefCell::new(InputRateTracker::default()));
2135        let last_frame_time = Rc::new(Cell::new(None));
2136
2137        platform_window
2138            .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));
2139        platform_window.set_background_appearance(background_appearance);
2140
2141        match window_bounds {
2142            WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),
2143            WindowBounds::Maximized(_) => platform_window.zoom(),
2144            WindowBounds::Windowed(_) => {}
2145        }
2146
2147        let accessibility_force_disabled = cx.accessibility_force_disabled;
2148        let accessibility_forced = cx.accessibility_forced;
2149        let a11y_active_flag = Arc::new(AtomicBool::new(false));
2150
2151        #[cfg(not(target_family = "wasm"))]
2152        if !accessibility_force_disabled {
2153            let mut initial_root_node = accesskit::Node::new(accesskit::Role::Window);
2154            if let Some(title) = &initial_window_title {
2155                initial_root_node.set_label(title.to_string());
2156            }
2157            let initial_tree = accesskit::TreeUpdate {
2158                nodes: vec![(ROOT_NODE_ID, initial_root_node)],
2159                tree: Some(accesskit::Tree::new(ROOT_NODE_ID)),
2160                tree_id: accesskit::TreeId::ROOT,
2161                focus: ROOT_NODE_ID,
2162            };
2163            let (activation_sender, activation_receiver) = async_channel::unbounded::<()>();
2164            let (deactivation_sender, deactivation_receiver) = async_channel::unbounded::<()>();
2165            let (action_sender, action_receiver) =
2166                async_channel::unbounded::<accesskit::ActionRequest>();
2167
2168            platform_window.a11y_init(crate::A11yCallbacks {
2169                activation: {
2170                    let active_flag = a11y_active_flag.clone();
2171                    Box::new(move || {
2172                        log::info!("Accessibility activated");
2173                        active_flag.store(true, SeqCst);
2174                        activation_sender.send_blocking(()).log_err();
2175                        Some(initial_tree.clone())
2176                    })
2177                },
2178                action: Box::new(move |request| {
2179                    action_sender.send_blocking(request).log_err();
2180                }),
2181                deactivation: {
2182                    let active_flag = a11y_active_flag.clone();
2183                    Box::new(move || {
2184                        log::info!("Accessibility deactivated");
2185                        active_flag.store(false, SeqCst);
2186                        deactivation_sender.send_blocking(()).log_err();
2187                    })
2188                },
2189            });
2190
2191            // A11y can be activated at any time, and so we cannot compute a
2192            // correct `TreeUpdate` on-demand. When this happens, we return a
2193            // default empty `TreeUpdate`.
2194            //
2195            // So we force a new frame, which will then send a correct `TreeUpdate`.
2196            let mut async_cx = cx.to_async();
2197            cx.foreground_executor()
2198                .spawn(async move {
2199                    while activation_receiver.recv().await.is_ok() {
2200                        handle
2201                            .update(&mut async_cx, |_, window, _| window.refresh())
2202                            .log_err();
2203                    }
2204                })
2205                .detach();
2206
2207            let mut async_cx = cx.to_async();
2208            cx.foreground_executor()
2209                .spawn(async move {
2210                    while deactivation_receiver.recv().await.is_ok() {
2211                        handle
2212                            .update(&mut async_cx, |_, window, _| window.refresh())
2213                            .log_err();
2214                    }
2215                })
2216                .detach();
2217
2218            let mut async_cx = cx.to_async();
2219            cx.foreground_executor()
2220                .spawn(async move {
2221                    while let Ok(request) = action_receiver.recv().await {
2222                        handle
2223                            .update(&mut async_cx, |_, window, cx| {
2224                                window.handle_a11y_action(request, cx);
2225                            })
2226                            .log_err();
2227                    }
2228                })
2229                .detach();
2230        }
2231
2232        #[cfg(all(
2233            feature = "hot-patching",
2234            debug_assertions,
2235            not(target_family = "wasm")
2236        ))]
2237        let (hot_patch_sender, hot_patch_receiver) = async_channel::bounded(1);
2238
2239        platform_window.on_close(Box::new({
2240            let window_id = handle.window_id();
2241            let mut cx = cx.to_async();
2242            #[cfg(all(
2243                feature = "hot-patching",
2244                debug_assertions,
2245                not(target_family = "wasm")
2246            ))]
2247            let hot_patch_sender = hot_patch_sender.clone();
2248            move || {
2249                #[cfg(all(
2250                    feature = "hot-patching",
2251                    debug_assertions,
2252                    not(target_family = "wasm")
2253                ))]
2254                hot_patch_sender.close();
2255                let _ = handle.update(&mut cx, |_, window, _| window.remove_window());
2256                let _ = cx.update(|cx| {
2257                    SystemWindowTabController::remove_tab(cx, window_id);
2258                });
2259            }
2260        }));
2261        #[cfg(all(
2262            feature = "hot-patching",
2263            debug_assertions,
2264            not(target_family = "wasm")
2265        ))]
2266        {
2267            // The patch callback runs off the UI thread. Forward it to the
2268            // foreground executor so refresh can wake demand-driven platforms.
2269            subsecond::register_handler(Arc::new(move || {
2270                let _ = hot_patch_sender.try_send(());
2271            }));
2272            let mut cx = cx.to_async();
2273            let foreground_executor = cx.foreground_executor().clone();
2274            foreground_executor
2275                .spawn(async move {
2276                    while hot_patch_receiver.recv().await.is_ok() {
2277                        if handle
2278                            .update(&mut cx, |_, window, _| window.refresh())
2279                            .is_err()
2280                        {
2281                            break;
2282                        }
2283                    }
2284                })
2285                .detach();
2286        }
2287        platform_window.on_request_frame(Box::new({
2288            let mut cx = cx.to_async();
2289            let invalidator = invalidator.clone();
2290            let active = active.clone();
2291            let needs_present = needs_present.clone();
2292            let next_frame_callbacks = next_frame_callbacks.clone();
2293            let input_rate_tracker = input_rate_tracker.clone();
2294            let mut deferred_force_render = false;
2295            move |request_frame_options| {
2296                #[cfg(feature = "profiler")]
2297                let (_foreground_turn, window_id) = {
2298                    let foreground_turn = profiler::journal::foreground_turn();
2299                    let window_id = handle.window_id();
2300                    profiler::journal::record_platform_signal(profiler::journal::PlatformSignal {
2301                        window_id,
2302                        signal_at: request_frame_options.signal_at,
2303                        handled_at: Instant::now(),
2304                        source: request_frame_options.signal_source,
2305                    });
2306                    (foreground_turn, window_id)
2307                };
2308                // This must be checked before accessing App: if this request
2309                // arrived re-entrantly while a draw is on this thread's stack
2310                // (e.g. via a nested message pump in the Windows window
2311                // procedure), drawing would nest draws, and even touching the
2312                // App would panic on its already-mutable borrow. Skip instead;
2313                // the platform leaves the window invalidated (or re-invalidates
2314                // it), so a fresh request arrives once the in-progress draw
2315                // unwinds. Remember force_render so the deferred frame still
2316                // bypasses the view cache.
2317                //
2318                // Returning here skips `complete_frame`, which on Wayland would
2319                // stall the window's frame callbacks (no `surface.commit()`) —
2320                // but calling it would hit the App borrow panic above, and this
2321                // branch is unreachable there in practice: only Windows pumps
2322                // platform events (and thus requests frames) mid-draw.
2323                if draw_in_progress() {
2324                    log::debug!("deferring re-entrant window draw request");
2325                    deferred_force_render |= request_frame_options.force_render;
2326                    #[cfg(feature = "profiler")]
2327                    profiler::journal::record_reentrant_frame_skipped(window_id, Instant::now());
2328                    return;
2329                }
2330                // Take the deferred flag first: `||` short-circuits, and leaving
2331                // the flag set when this request already forces a render would
2332                // force a second, redundant render on the next frame.
2333                let force_render =
2334                    mem::take(&mut deferred_force_render) || request_frame_options.force_render;
2335
2336                let thermal_state = handle
2337                    .update(&mut cx, |_, _, cx| cx.thermal_state())
2338                    .log_err();
2339
2340                // Throttle frame rate based on conditions:
2341                // - Thermal pressure (Serious/Critical): cap to ~60fps
2342                // - Inactive window (not focused): cap to ~30fps to save energy
2343                let min_frame_interval = if request_frame_options.require_presentation
2344                    || (!request_frame_options.force_render
2345                        && next_frame_callbacks.borrow().is_empty())
2346                {
2347                    None
2348                } else if !active.get() && !input_rate_tracker.borrow_mut().is_high_rate() {
2349                    inactive_frame_interval.map(|interval| (interval, FrameRateLimit::Inactive))
2350                } else if let Some(ThermalState::Critical | ThermalState::Serious) = thermal_state {
2351                    Some((Duration::from_micros(16667), FrameRateLimit::Thermal))
2352                } else {
2353                    None
2354                };
2355
2356                let now = Instant::now();
2357                #[cfg_attr(not(feature = "profiler"), expect(unused_variables))]
2358                if let Some((min_interval, limit)) = min_frame_interval {
2359                    if let Some(last_frame) = last_frame_time.get()
2360                        && now.duration_since(last_frame) < min_interval
2361                    {
2362                        // Don't lose a pending forced render to throttling.
2363                        deferred_force_render |= force_render;
2364                        // Deferred by throttling: ask demand-driven platforms to retry.
2365                        handle
2366                            .update(&mut cx, |_, window, _| {
2367                                window.platform_window.schedule_frame();
2368                            })
2369                            .log_err();
2370                        // The demand that entered this branch (a deferred forced
2371                        // render or pending next-frame callbacks) is still
2372                        // unserved; platforms that stop requesting frames for
2373                        // idle windows need a wakeup to deliver the retry.
2374                        invalidator.wake_platform();
2375                        #[cfg(feature = "profiler")]
2376                        profiler::journal::record_frame_skipped(
2377                            window_id,
2378                            Instant::now(),
2379                            match limit {
2380                                FrameRateLimit::Inactive => {
2381                                    profiler::journal::FrameSkipReason::InactiveFrameRateLimit
2382                                }
2383                                FrameRateLimit::Thermal => {
2384                                    profiler::journal::FrameSkipReason::ThermalFrameRateLimit
2385                                }
2386                            },
2387                        );
2388                        return;
2389                    }
2390                }
2391                last_frame_time.set(Some(now));
2392
2393                let pending_next_frame_callbacks = next_frame_callbacks.take();
2394                if !pending_next_frame_callbacks.is_empty() {
2395                    handle
2396                        .update(&mut cx, |_, window, cx| {
2397                            for callback in pending_next_frame_callbacks {
2398                                callback(window, cx);
2399                            }
2400                        })
2401                        .log_err();
2402                }
2403
2404                // Keep presenting if input was recently arriving at a high rate (>= 60fps).
2405                // Once high-rate input is detected, we sustain presentation for 1 second
2406                // to prevent display underclocking during active input.
2407                let needs_present = request_frame_options.require_presentation
2408                    || needs_present.get()
2409                    || input_rate_tracker.borrow_mut().is_high_rate();
2410
2411                let should_draw = invalidator.is_dirty() || force_render;
2412                if should_draw {
2413                    measure("frame duration", || {
2414                        handle
2415                            .update(&mut cx, |_, window, cx| {
2416                                #[cfg(feature = "profiler")]
2417                                window
2418                                    .window_profiler
2419                                    .record_frame_signal(request_frame_options.signal_at);
2420                                if force_render {
2421                                    // Bypass cached view reuse so we don't replay stale
2422                                    // atlas tile references after a GPU device recovery.
2423                                    window.refresh();
2424                                }
2425                                let arena_clear_needed = window.draw(cx);
2426                                window.present();
2427                                arena_clear_needed.clear(cx);
2428                            })
2429                            .log_err();
2430                    })
2431                } else if needs_present {
2432                    handle
2433                        .update(&mut cx, |_, window, _| window.present())
2434                        .log_err();
2435                }
2436
2437                handle
2438                    .update(&mut cx, |_, window, _| {
2439                        if window.invalidator.is_dirty()
2440                            || !window.next_frame_callbacks.borrow().is_empty()
2441                        {
2442                            window.platform_window.schedule_frame();
2443                        }
2444                    })
2445                    .log_err();
2446
2447                // Platforms that stop requesting frames for idle windows only
2448                // deliver another request after a wakeup. If demand remains
2449                // after this frame (the window was re-invalidated mid-draw, or
2450                // animations scheduled next-frame callbacks), re-arm the frame
2451                // source explicitly.
2452                if invalidator.is_dirty() || !next_frame_callbacks.borrow().is_empty() {
2453                    invalidator.wake_platform();
2454                }
2455                #[cfg(feature = "profiler")]
2456                if !should_draw {
2457                    profiler::journal::record_frame_skipped(
2458                        window_id,
2459                        Instant::now(),
2460                        profiler::journal::FrameSkipReason::NoRenderNeeded,
2461                    );
2462                }
2463            }
2464        }));
2465        invalidator.set_platform_waker(platform_window.frame_waker());
2466        platform_window.on_visual_viewport_changed(Box::new({
2467            let mut cx = cx.to_async();
2468            move || {
2469                handle
2470                    .update(&mut cx, |_, window, _| window.refresh())
2471                    .log_err();
2472            }
2473        }));
2474        platform_window.on_insets_changed(Box::new({
2475            let mut cx = cx.to_async();
2476            move |_| {
2477                handle
2478                    .update(&mut cx, |_, window, _| window.refresh())
2479                    .log_err();
2480            }
2481        }));
2482        platform_window.on_resize(Box::new({
2483            let mut cx = cx.to_async();
2484            move |_, _| {
2485                handle
2486                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
2487                    .log_err();
2488            }
2489        }));
2490        platform_window.on_moved(Box::new({
2491            let mut cx = cx.to_async();
2492            move || {
2493                handle
2494                    .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
2495                    .log_err();
2496            }
2497        }));
2498        platform_window.on_display_changed(Box::new({
2499            let cx = cx.to_async();
2500            move || cx.update(|cx| Window::display_changed(handle, cx))
2501        }));
2502        platform_window.on_appearance_changed(Box::new({
2503            let cx = cx.to_async();
2504            let foreground_executor = cx.foreground_executor().clone();
2505            move || {
2506                let mut cx = cx.clone();
2507                // Defer the update because changing the AppKit appearance may
2508                // synchronously invoke this callback while App is already borrowed.
2509                foreground_executor
2510                    .spawn(async move {
2511                        handle
2512                            .update(&mut cx, |_, window, cx| window.appearance_changed(cx))
2513                            .log_err();
2514                    })
2515                    .detach();
2516            }
2517        }));
2518        platform_window.on_button_layout_changed(Box::new({
2519            let mut cx = cx.to_async();
2520            move || {
2521                handle
2522                    .update(&mut cx, |_, window, cx| window.button_layout_changed(cx))
2523                    .log_err();
2524            }
2525        }));
2526        platform_window.on_active_status_change(Box::new({
2527            let mut cx = cx.to_async();
2528            move |active| {
2529                handle
2530                    .update(&mut cx, |_, window, cx| {
2531                        window.active.set(active);
2532                        window.modifiers = window.platform_window.modifiers();
2533                        window.capslock = window.platform_window.capslock();
2534                        window
2535                            .activation_observers
2536                            .clone()
2537                            .retain(&(), |callback| callback(window, cx));
2538
2539                        window.bounds_changed(cx);
2540                        window.refresh();
2541
2542                        SystemWindowTabController::update_last_active(cx, window.handle.id);
2543                    })
2544                    .log_err();
2545            }
2546        }));
2547        platform_window.on_visibility_change(Box::new({
2548            let mut cx = cx.to_async();
2549            move |_| {
2550                handle
2551                    .update(&mut cx, |_, window, cx| {
2552                        window.refresh_visibility(cx);
2553                    })
2554                    .log_err();
2555            }
2556        }));
2557        platform_window.on_hover_status_change(Box::new({
2558            let mut cx = cx.to_async();
2559            move |active| {
2560                handle
2561                    .update(&mut cx, |_, window, _| {
2562                        window.hovered.set(active);
2563                        window.pointer_inside_window = active;
2564                        window.refresh();
2565                    })
2566                    .log_err();
2567            }
2568        }));
2569        platform_window.on_input({
2570            let mut cx = cx.to_async();
2571            Box::new(move |event| {
2572                handle
2573                    .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))
2574                    .log_err()
2575                    .unwrap_or(DispatchEventResult::default())
2576            })
2577        });
2578        platform_window.on_hit_test_window_control({
2579            let mut cx = cx.to_async();
2580            Box::new(move || {
2581                handle
2582                    .update(&mut cx, |_, window, _cx| {
2583                        for (area, hitbox) in &window.rendered_frame.window_control_hitboxes {
2584                            let mut scrollable_ids = window.mouse_hit_test().iter_scrollable();
2585                            if scrollable_ids.contains(&hitbox.id) {
2586                                return Some(*area);
2587                            }
2588                        }
2589                        None
2590                    })
2591                    .log_err()
2592                    .unwrap_or(None)
2593            })
2594        });
2595        platform_window.on_move_tab_to_new_window({
2596            let mut cx = cx.to_async();
2597            Box::new(move || {
2598                handle
2599                    .update(&mut cx, |_, _window, cx| {
2600                        SystemWindowTabController::move_tab_to_new_window(cx, handle.window_id());
2601                    })
2602                    .log_err();
2603            })
2604        });
2605        platform_window.on_merge_all_windows({
2606            let mut cx = cx.to_async();
2607            Box::new(move || {
2608                handle
2609                    .update(&mut cx, |_, _window, cx| {
2610                        SystemWindowTabController::merge_all_windows(cx, handle.window_id());
2611                    })
2612                    .log_err();
2613            })
2614        });
2615        platform_window.on_select_next_tab({
2616            let mut cx = cx.to_async();
2617            Box::new(move || {
2618                handle
2619                    .update(&mut cx, |_, _window, cx| {
2620                        SystemWindowTabController::select_next_tab(cx, handle.window_id());
2621                    })
2622                    .log_err();
2623            })
2624        });
2625        platform_window.on_select_previous_tab({
2626            let mut cx = cx.to_async();
2627            Box::new(move || {
2628                handle
2629                    .update(&mut cx, |_, _window, cx| {
2630                        SystemWindowTabController::select_previous_tab(cx, handle.window_id())
2631                    })
2632                    .log_err();
2633            })
2634        });
2635        platform_window.on_toggle_tab_bar({
2636            let mut cx = cx.to_async();
2637            Box::new(move || {
2638                handle
2639                    .update(&mut cx, |_, window, cx| {
2640                        let tab_bar_visible = window.platform_window.tab_bar_visible();
2641                        SystemWindowTabController::set_visible(cx, tab_bar_visible);
2642                    })
2643                    .log_err();
2644            })
2645        });
2646
2647        if let Some(app_id) = app_id {
2648            platform_window.set_app_id(&app_id);
2649        }
2650
2651        platform_window.map_window().unwrap();
2652
2653        Ok(Window {
2654            handle,
2655            invalidator,
2656            removed: false,
2657            platform_window,
2658            display_id,
2659            display_observers: SubscriberSet::new(),
2660            is_resizable,
2661            is_minimizable,
2662            sprite_atlas,
2663            text_system,
2664            text_rendering_mode: cx.text_rendering_mode.clone(),
2665            rem_size: px(16.),
2666            rem_size_override_stack: SmallVec::new(),
2667            viewport_size: content_size,
2668            layout_engine: Some(TaffyLayoutEngine::new()),
2669            collecting_inline: false,
2670            current_inline_fragments: None,
2671            root: None,
2672            element_id_stack: ElementIdStack::default(),
2673            text_style_stack: Vec::new(),
2674            measurement_direction: ResolvedDirection::LeftToRight,
2675            measurement_unicode_bidi: UnicodeBidi::Normal,
2676            rendered_entity_stack: Vec::new(),
2677            element_offset_stack: Vec::new(),
2678            style_transition_containing_bounds: None,
2679            content_mask_stack: Vec::new(),
2680            requested_autoscroll: None,
2681            last_text_input_configuration: None,
2682            focused_text_input: None,
2683            rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
2684            next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
2685            next_frame_callbacks,
2686            next_hitbox_id: HitboxId(0),
2687            next_tooltip_id: TooltipId::default(),
2688            tooltip_bounds: None,
2689            dirty_views: FxHashSet::default(),
2690            focus_listeners: SubscriberSet::new(),
2691            focus_lost_listeners: SubscriberSet::new(),
2692            focus_lost_path: SmallVec::new(),
2693            default_prevented: true,
2694            mouse_position,
2695            pointer_inside_window: true,
2696            mouse_hit_test: HitTest::default(),
2697            modifiers,
2698            capslock,
2699            scale_factor,
2700            bounds_observers: SubscriberSet::new(),
2701            appearance,
2702            appearance_observers: SubscriberSet::new(),
2703            button_layout_observers: SubscriberSet::new(),
2704            active,
2705            visibility,
2706            visibility_observers: SubscriberSet::new(),
2707            hovered,
2708            needs_present,
2709            input_rate_tracker,
2710            #[cfg(feature = "profiler")]
2711            window_profiler: profiler::WindowProfiler::new(handle.window_id())?,
2712            last_input_modality: InputModality::Mouse,
2713            input_reads: Cell::default(),
2714            deferred_priority_stack: Vec::new(),
2715            frame_number: 0,
2716            touch_gestures: TouchGestureRecognizer::new(
2717                cx.platform
2718                    .gestures()
2719                    .map_or_else(GestureTuning::default, |gestures| gestures.tuning()),
2720            ),
2721            touch_prediction_enabled: true,
2722            long_press_timer: None,
2723            long_press_capture: None,
2724            refreshing: false,
2725            activation_observers: SubscriberSet::new(),
2726            focus: None,
2727            focus_enabled: true,
2728            focus_generation: 0,
2729            pending_input: None,
2730            pending_modifier: ModifierState::default(),
2731            pending_input_observers: SubscriberSet::new(),
2732            prompt: None,
2733            client_inset: None,
2734            image_cache_stack: Vec::new(),
2735            captured_hitbox: None,
2736            #[cfg(any(feature = "inspector", debug_assertions))]
2737            inspector: None,
2738            #[cfg(feature = "profiler")]
2739            debug_frame_overlay: crate::debug_overlay::DebugFrameOverlay::new(),
2740            a11y: A11y::new(
2741                a11y_active_flag,
2742                accessibility_force_disabled,
2743                accessibility_forced,
2744                initial_window_title,
2745            ),
2746        })
2747    }
2748
2749    pub(crate) fn new_focus_listener(
2750        &self,
2751        value: AnyWindowFocusListener,
2752    ) -> (Subscription, impl FnOnce() + use<>) {
2753        self.focus_listeners.insert((), value)
2754    }
2755}
2756
2757#[derive(Clone, Debug, Default, PartialEq, Eq)]
2758/// The outcome of [`Window::dispatch_event`].
2759///
2760/// Use the fields to tell whether a platform event was consumed and whether its default action
2761/// should still run.
2762pub struct DispatchEventResult {
2763    /// `true` if no listener stopped propagation, so the event reached every listener.
2764    pub propagate: bool,
2765    /// `true` if a listener called [`Window::prevent_default`] for this event.
2766    pub default_prevented: bool,
2767}
2768
2769/// The visible region of the window, which clips what is painted and hit-tested.
2770///
2771/// Anything outside the mask isn't rendered or receives input. Only rectangular
2772/// masks are supported. The `fade_out` distances fade the content toward each
2773/// edge, which scroll containers use to show that more content is available.
2774/// Fades are measured in window space and ignore transforms.
2775///
2776/// GPUI sets the mask with [`Window::with_content_mask`] and reads it with
2777/// [`Window::content_mask`].
2778#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
2779#[repr(C)]
2780pub struct ContentMask<P: Clone + Debug + Default + PartialEq> {
2781    /// The rectangle that stays visible.
2782    pub bounds: Bounds<P>,
2783    /// The distance over which content fades out at each edge of `bounds`.
2784    ///
2785    /// A zero distance leaves that edge fully opaque.
2786    pub fade_out: Edges<P>,
2787}
2788
2789impl ContentMask<Pixels> {
2790    /// Returns this mask in [`ScaledPixels`], with every value multiplied by `factor`.
2791    pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
2792        ContentMask {
2793            bounds: self.bounds.scale(factor),
2794            fade_out: self.fade_out.scale(factor),
2795        }
2796    }
2797
2798    /// Returns the region visible through both this mask and `other`.
2799    ///
2800    /// For each edge, the mask that actually clips at that edge contributes its
2801    /// fade; when both masks clip at the same coordinate, the stronger fade wins.
2802    pub fn intersect(&self, other: &Self) -> Self {
2803        fn edge_fade(
2804            a: Pixels,
2805            b: Pixels,
2806            a_fade: Pixels,
2807            b_fade: Pixels,
2808            a_clips_closer: impl Fn(Pixels, Pixels) -> bool,
2809        ) -> Pixels {
2810            if a_clips_closer(a, b) {
2811                a_fade
2812            } else if a_clips_closer(b, a) {
2813                b_fade
2814            } else {
2815                a_fade.max(b_fade)
2816            }
2817        }
2818
2819        ContentMask {
2820            bounds: self.bounds.intersect(&other.bounds),
2821            fade_out: Edges {
2822                top: edge_fade(
2823                    self.bounds.top(),
2824                    other.bounds.top(),
2825                    self.fade_out.top,
2826                    other.fade_out.top,
2827                    |a, b| a > b,
2828                ),
2829                right: edge_fade(
2830                    self.bounds.right(),
2831                    other.bounds.right(),
2832                    self.fade_out.right,
2833                    other.fade_out.right,
2834                    |a, b| a < b,
2835                ),
2836                bottom: edge_fade(
2837                    self.bounds.bottom(),
2838                    other.bounds.bottom(),
2839                    self.fade_out.bottom,
2840                    other.fade_out.bottom,
2841                    |a, b| a < b,
2842                ),
2843                left: edge_fade(
2844                    self.bounds.left(),
2845                    other.bounds.left(),
2846                    self.fade_out.left,
2847                    other.fade_out.left,
2848                    |a, b| a > b,
2849                ),
2850            },
2851        }
2852    }
2853}
2854
2855#[cfg(test)]
2856mod content_mask_tests {
2857    use super::*;
2858
2859    fn mask(left: f32, width: f32, fade_left: f32) -> ContentMask<Pixels> {
2860        ContentMask {
2861            bounds: Bounds::new(point(px(left), px(0.)), size(px(width), px(10.))),
2862            fade_out: Edges {
2863                left: px(fade_left),
2864                ..Default::default()
2865            },
2866        }
2867    }
2868
2869    #[test]
2870    fn intersect_keeps_only_the_fade_at_the_visible_edge() {
2871        let outer = mask(0., 100., 20.);
2872        let inner = mask(30., 40., 0.);
2873        assert_eq!(outer.intersect(&inner).fade_out.left, px(0.));
2874
2875        let child = mask(0., 40., 0.);
2876        assert_eq!(outer.intersect(&child).fade_out.left, px(20.));
2877    }
2878}
2879
2880impl Window {
2881    fn mark_view_dirty(&mut self, view_id: EntityId) {
2882        // Mark ancestor views as dirty. If already in the `dirty_views` set, then all its ancestors
2883        // should already be dirty.
2884        for ancestor_id in self
2885            .rendered_frame
2886            .dispatch_tree
2887            .view_path_reversed(view_id)
2888        {
2889            if !self.dirty_views.insert(ancestor_id) {
2890                break;
2891            }
2892        }
2893        // Model entities can be dependencies of a view without being represented in the
2894        // dispatch tree. Always mark the notified entity itself after walking any ancestors.
2895        self.dirty_views.insert(view_id);
2896    }
2897
2898    pub(crate) fn refresh_visibility(&mut self, cx: &mut App) {
2899        let visibility = self.platform_window.visibility();
2900        if self.visibility != visibility {
2901            self.visibility = visibility;
2902            #[cfg(feature = "profiler")]
2903            profiler::journal::record_window_visibility(self.handle.window_id(), visibility);
2904            self.visibility_observers
2905                .clone()
2906                .retain(&(), |callback| callback(visibility, self, cx));
2907        }
2908        #[cfg(feature = "profiler")]
2909        if self.invalidator.is_dirty() || self.needs_present.get() {
2910            profiler::journal::record_frame_pending(self.handle.window_id(), Instant::now());
2911        }
2912    }
2913
2914    /// Whether the platform is presenting this window's frames (see
2915    /// [`WindowVisibility`]).
2916    pub fn visibility(&self) -> WindowVisibility {
2917        self.visibility
2918    }
2919
2920    /// Whether frames drawn for this window will be shown.
2921    ///
2922    /// This is not the window's shown/hidden state: a shown window that is
2923    /// fully behind another window, minimized, or on a sleeping display is not
2924    /// visible here.
2925    pub fn is_visible(&self) -> bool {
2926        self.visibility.is_visible()
2927    }
2928
2929    /// Registers a callback to be invoked when the window's visibility changes.
2930    pub fn observe_window_visibility(
2931        &self,
2932        mut callback: impl FnMut(WindowVisibility, &mut Window, &mut App) + 'static,
2933    ) -> Subscription {
2934        let (subscription, activate) = self.visibility_observers.insert(
2935            (),
2936            Box::new(move |visibility, window, cx| {
2937                callback(visibility, window, cx);
2938                true
2939            }),
2940        );
2941        activate();
2942        subscription
2943    }
2944
2945    /// Calls `callback` when the system switches between light and dark appearance.
2946    ///
2947    /// The callback runs during the next update after the change, not inside the
2948    /// platform callback. Keep the returned [`Subscription`] alive for as long as
2949    /// you want to be notified; dropping it unsubscribes. See [`Window::appearance`]
2950    /// to read the current value.
2951    pub fn observe_window_appearance(
2952        &self,
2953        mut callback: impl FnMut(&mut Window, &mut App) + 'static,
2954    ) -> Subscription {
2955        let (subscription, activate) = self.appearance_observers.insert(
2956            (),
2957            Box::new(move |window, cx| {
2958                callback(window, cx);
2959                true
2960            }),
2961        );
2962        activate();
2963        subscription
2964    }
2965
2966    /// Calls `callback` when the platform's window button layout changes.
2967    ///
2968    /// The button layout decides which window controls appear in a custom title bar,
2969    /// and which side they are on. Keep the returned [`Subscription`] alive while you
2970    /// need the callback; dropping it unsubscribes.
2971    pub fn observe_button_layout_changed(
2972        &self,
2973        mut callback: impl FnMut(&mut Window, &mut App) + 'static,
2974    ) -> Subscription {
2975        let (subscription, activate) = self.button_layout_observers.insert(
2976            (),
2977            Box::new(move |window, cx| {
2978                callback(window, cx);
2979                true
2980            }),
2981        );
2982        activate();
2983        subscription
2984    }
2985
2986    /// Replaces the window's root view with a new view built by `build_view`.
2987    ///
2988    /// The window stops referring to the old root and redraws with the new one.
2989    /// The old view is freed once no other [`Entity`] handles to it remain. The
2990    /// returned entity is the new root.
2991    pub fn replace_root<E>(
2992        &mut self,
2993        cx: &mut App,
2994        build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,
2995    ) -> Entity<E>
2996    where
2997        E: 'static + Render,
2998    {
2999        let view = cx.new(|cx| build_view(self, cx));
3000        self.root = Some(view.clone().into());
3001        self.refresh();
3002        view
3003    }
3004
3005    /// Returns the window's root view as an `Entity<E>`.
3006    ///
3007    /// The result has two layers of `Option`. The outer `None` means the window
3008    /// has no root view. The inner `None` means the root is not of type `E`.
3009    ///
3010    /// # Examples
3011    ///
3012    /// ```
3013    /// # use gpui::{TestApp, Window, Context, div, prelude::*};
3014    /// # struct Root;
3015    /// # impl Render for Root {
3016    /// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
3017    /// #         div()
3018    /// #     }
3019    /// # }
3020    /// # let mut app = TestApp::new();
3021    /// # let mut window = app.open_window(|_, _| Root);
3022    /// window.update(|_, window, _| {
3023    ///     assert!(matches!(window.root::<Root>(), Some(Some(_))));
3024    /// });
3025    /// ```
3026    pub fn root<E>(&self) -> Option<Option<Entity<E>>>
3027    where
3028        E: 'static + Render,
3029    {
3030        self.root
3031            .as_ref()
3032            .map(|view| view.clone().downcast::<E>().ok())
3033    }
3034
3035    /// Returns an [`AnyWindowHandle`] for this window, which can be stored and used later.
3036    pub fn window_handle(&self) -> AnyWindowHandle {
3037        self.handle
3038    }
3039
3040    /// Redraws the whole window on the next frame, without notifying any entity.
3041    ///
3042    /// Use it when something outside your entities changes what the window shows,
3043    /// such as a system setting or the contents of a global that views don't observe.
3044    /// Calling it during a draw does nothing, because the window is already drawing.
3045    /// Prefer [`Context::notify`] when an entity changed.
3046    ///
3047    /// # Examples
3048    ///
3049    /// ```
3050    /// # use gpui::{TestApp, Window, Context, div, prelude::*};
3051    /// # struct Root;
3052    /// # impl Render for Root {
3053    /// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
3054    /// #         div()
3055    /// #     }
3056    /// # }
3057    /// # let mut app = TestApp::new();
3058    /// # let mut window = app.open_window(|_, _| Root);
3059    /// window.update(|_, window, _| window.refresh());
3060    /// ```
3061    pub fn refresh(&mut self) {
3062        if self.invalidator.not_drawing() {
3063            self.refreshing = true;
3064            self.invalidator.set_dirty(true);
3065        }
3066    }
3067
3068    /// Closes this window when the current update finishes.
3069    ///
3070    /// The window isn't removed in the middle of the update, so you can keep using
3071    /// the `Window` until the update returns.
3072    pub fn remove_window(&mut self) {
3073        self.removed = true;
3074    }
3075
3076    /// Returns the [`FocusHandle`] of the focused element, or `None` if nothing has focus.
3077    ///
3078    /// Returns `None` if the focused element's handles have all been dropped.
3079    pub fn focused(&self, cx: &App) -> Option<FocusHandle> {
3080        self.focus
3081            .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))
3082    }
3083
3084    /// While focus-lost listeners are being dispatched, returns the closest ancestor of the
3085    /// previously focused element that can still receive focus, making it a suitable target
3086    /// for focus restoration. Returns `None` at all other times, or when no such ancestor exists.
3087    pub fn focus_lost_restore_target(&self, cx: &App) -> Option<FocusHandle> {
3088        let (_leaf, ancestors) = self.focus_lost_path.split_last()?;
3089        ancestors.iter().rev().find_map(|id| {
3090            self.rendered_frame.dispatch_tree.focusable_node_id(*id)?;
3091            FocusHandle::for_id(*id, &cx.focus_handles)
3092        })
3093    }
3094
3095    /// Moves focus to the element that `handle` belongs to.
3096    ///
3097    /// Focus changes right away, and the next frame renders the new focus. Focusing
3098    /// the element that already has focus does nothing. Does nothing after
3099    /// [`Window::disable_focus`]. Pending keystrokes are cleared.
3100    ///
3101    /// # Examples
3102    ///
3103    /// ```
3104    /// # use gpui::{TestApp, Window, Context, div, prelude::*};
3105    /// # struct Root;
3106    /// # impl Render for Root {
3107    /// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
3108    /// #         div()
3109    /// #     }
3110    /// # }
3111    /// # let mut app = TestApp::new();
3112    /// # let mut window = app.open_window(|_, _| Root);
3113    /// window.update(|_, window, cx| {
3114    ///     let handle = cx.focus_handle();
3115    ///     window.focus(&handle, cx);
3116    ///     assert_eq!(window.focused(cx), Some(handle));
3117    /// });
3118    /// ```
3119    pub fn focus(&mut self, handle: &FocusHandle, cx: &mut App) {
3120        if !self.focus_enabled || self.focus == Some(handle.id) {
3121            return;
3122        }
3123
3124        self.focus = Some(handle.id);
3125        self.focus_generation = self.focus_generation.wrapping_add(1);
3126        self.clear_pending_keystrokes(cx);
3127
3128        self.refresh();
3129    }
3130
3131    /// Removes focus from every element in the window.
3132    ///
3133    /// Focus can be given again afterward with [`Window::focus`]. Pending keystrokes
3134    /// are cleared. Does nothing if focus is disabled.
3135    pub fn blur(&mut self, cx: &mut App) {
3136        self.clear_pending_keystrokes(cx);
3137
3138        if !self.focus_enabled {
3139            return;
3140        }
3141
3142        if self.focus.is_some() {
3143            self.focus_generation = self.focus_generation.wrapping_add(1);
3144        }
3145        self.focus = None;
3146        self.refresh();
3147    }
3148
3149    /// Removes focus from the window and stops any element in it from receiving focus.
3150    ///
3151    /// Later calls to [`Window::focus`], [`Window::focus_next`] and [`Window::focus_prev`]
3152    /// do nothing. Use it when the window is being torn down or is only for display.
3153    pub fn disable_focus(&mut self, cx: &mut App) {
3154        self.blur(cx);
3155        self.focus_enabled = false;
3156    }
3157
3158    /// Moves focus to the next tab stop in tab order, wrapping at the end.
3159    ///
3160    /// Tab stops are the focusable elements whose [`FocusHandle::tab_stop`] is `true`,
3161    /// read from the last rendered frame. If nothing has focus, this moves to the first
3162    /// tab stop. Does nothing if focus is disabled or there are no tab stops.
3163    ///
3164    /// GPUI doesn't bind Tab to this method. Bind a key to it with [`App::bind_keys`]
3165    /// and an action handler, as in the [focus guide](crate::_documentation::guides::focus).
3166    pub fn focus_next(&mut self, cx: &mut App) {
3167        if !self.focus_enabled {
3168            return;
3169        }
3170
3171        if let Some(handle) = self.rendered_frame.tab_stops.next(self.focus.as_ref()) {
3172            self.focus(&handle, cx)
3173        }
3174    }
3175
3176    /// Moves focus to the previous tab stop in tab order, wrapping at the start.
3177    ///
3178    /// This is the reverse of [`Window::focus_next`], with the same rules for tab stops
3179    /// and disabled focus.
3180    pub fn focus_prev(&mut self, cx: &mut App) {
3181        if !self.focus_enabled {
3182            return;
3183        }
3184
3185        if let Some(handle) = self.rendered_frame.tab_stops.prev(self.focus.as_ref()) {
3186            self.focus(&handle, cx)
3187        }
3188    }
3189
3190    /// Returns the text system that shapes and rasterizes text for this window.
3191    pub fn text_system(&self) -> &Arc<WindowTextSystem> {
3192        &self.text_system
3193    }
3194
3195    /// Returns the text style in effect, built from the refinements active in [`Window::with_text_style`].
3196    pub fn text_style(&self) -> TextStyle {
3197        let mut style = TextStyle::default();
3198        for refinement in &self.text_style_stack {
3199            style.refine(refinement);
3200        }
3201        style
3202    }
3203
3204    /// Returns the resolved direction of the current measured or prepainted layout node.
3205    ///
3206    /// Custom elements can use this when direction changes intrinsic measurement or a detached
3207    /// sublayout created during prepaint.
3208    pub fn resolved_direction(&self) -> ResolvedDirection {
3209        self.measurement_direction
3210    }
3211
3212    /// Returns the bidirectional formatting mode of the measured layout node.
3213    #[doc(hidden)]
3214    pub fn resolved_unicode_bidi(&self) -> UnicodeBidi {
3215        self.measurement_unicode_bidi
3216    }
3217
3218    /// Returns whether the platform reports this window as maximized.
3219    ///
3220    /// On some platforms, such as Windows, a maximized window is not the same as a
3221    /// window whose bounds match the display's size.
3222    pub fn is_maximized(&self) -> bool {
3223        self.platform_window.is_maximized()
3224    }
3225
3226    /// Requests client-side or server-side window decorations from the platform.
3227    ///
3228    /// The request applies on Wayland.
3229    pub fn request_decorations(&self, decorations: WindowDecorations) {
3230        self.platform_window.request_decorations(decorations);
3231    }
3232
3233    /// Set the exclusive zone for a layer-shell surface: how much screen space it
3234    /// reserves so other surfaces avoid occluding it (e.g. a panel reserving space).
3235    /// Positive values reserve that distance from the anchored edge, 0 lets the
3236    /// surface be moved out of others' exclusive zones, and -1 ignores reserved
3237    /// space and may extend under other surfaces. (Wayland layer-shell windows only)
3238    pub fn set_exclusive_zone(&self, zone: Pixels) {
3239        self.platform_window.set_exclusive_zone(zone);
3240    }
3241
3242    /// Set which anchored edge a layer-shell surface's exclusive zone applies to.
3243    /// This is only needed to disambiguate a corner-anchored surface; otherwise the
3244    /// edge is deduced from the anchor. The edge must be a single edge the surface
3245    /// is anchored to, or it is ignored. (Wayland layer-shell windows only)
3246    #[cfg(all(target_os = "linux", feature = "wayland"))]
3247    pub fn set_exclusive_edge(&self, edge: crate::layer_shell::Anchor) {
3248        self.platform_window.set_exclusive_edge(edge);
3249    }
3250
3251    /// Starts an interactive resize from `edge`, if this window is resizable.
3252    pub fn start_window_resize(&self, edge: ResizeEdge) {
3253        if self.is_resizable {
3254            self.platform_window.start_window_resize(edge);
3255        }
3256    }
3257
3258    /// Linux (wayland) only: Set the window's input region, the area that receives pointer
3259    /// and touch input. Events outside it pass through to whatever is below the window.
3260    ///
3261    /// - `Some(rects)` restricts input to the union of `rects`, in window coordinates.
3262    /// - `Some(&[])` is an empty region, so the window receives no pointer or touch input.
3263    /// - `None` resets the region to the default, so the whole window receives input again.
3264    pub fn set_input_region(&self, region: Option<&[Bounds<Pixels>]>) {
3265        self.platform_window.set_input_region(region);
3266    }
3267
3268    /// Returns the window's bounds and state, such as windowed, maximized or fullscreen.
3269    ///
3270    /// Save this value to reopen the window at the same place later, as
3271    /// [`WindowOptions::window_bounds`] expects.
3272    pub fn window_bounds(&self) -> WindowBounds {
3273        self.platform_window.window_bounds()
3274    }
3275
3276    /// Returns the window's bounds and state without the client-side insets that
3277    /// Wayland and X11 windows draw around their content.
3278    pub fn inner_window_bounds(&self) -> WindowBounds {
3279        self.platform_window.inner_window_bounds()
3280    }
3281
3282    /// Encode the window's native restorable state into an opaque blob.
3283    /// Returns `None` on platforms without native state restoration or if encoding fails.
3284    pub fn native_window_state(&self) -> Option<Vec<u8>> {
3285        self.platform_window.native_window_state()
3286    }
3287
3288    /// Restore the window's native state from a blob previously produced
3289    /// by [`Window::native_window_state`]. A no-op on platforms without native state restoration.
3290    pub fn restore_native_window_state(&self, state: &[u8]) {
3291        self.platform_window.restore_native_window_state(state);
3292    }
3293
3294    /// Dispatches `action` to the focused element, after the current update finishes.
3295    ///
3296    /// The action runs through the focus path, like an action from a keybinding. If
3297    /// nothing has focus, it is dispatched from the root of the window's last
3298    /// rendered frame.
3299    pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {
3300        let focus_id = self.focused(cx).map(|handle| handle.id);
3301
3302        let window = self.handle;
3303        cx.defer(move |cx| {
3304            window
3305                .update(cx, |_, window, cx| {
3306                    let node_id = window.focus_node_id_in_rendered_frame(focus_id);
3307                    window.dispatch_action_on_node(node_id, action.as_ref(), cx);
3308                })
3309                .log_err();
3310        })
3311    }
3312
3313    pub(crate) fn dispatch_keystroke_observers(
3314        &mut self,
3315        keystroke: &Keystroke,
3316        input_preference: InputPreference,
3317        action: Option<&dyn Action>,
3318        context_stack: Vec<KeyContext>,
3319        cx: &mut App,
3320    ) {
3321        cx.keystroke_observers.clone().retain(&(), move |callback| {
3322            (callback)(
3323                &KeystrokeEvent {
3324                    keystroke: keystroke.clone(),
3325                    input_preference,
3326                    action: action.map(|action| action.boxed_clone()),
3327                    context_stack: context_stack.clone(),
3328                },
3329                self,
3330                cx,
3331            )
3332        });
3333    }
3334
3335    pub(crate) fn dispatch_keystroke_interceptors(
3336        &mut self,
3337        keystroke: &Keystroke,
3338        input_preference: InputPreference,
3339        context_stack: Vec<KeyContext>,
3340        cx: &mut App,
3341    ) {
3342        cx.keystroke_interceptors
3343            .clone()
3344            .retain(&(), move |callback| {
3345                (callback)(
3346                    &KeystrokeEvent {
3347                        keystroke: keystroke.clone(),
3348                        input_preference,
3349                        action: None,
3350                        context_stack: context_stack.clone(),
3351                    },
3352                    self,
3353                    cx,
3354                )
3355            });
3356    }
3357
3358    /// Runs `f` with this window after the current update finishes.
3359    ///
3360    /// Use it to act on this window while the entities that are being updated are
3361    /// still borrowed. If the window has closed by then, `f` doesn't run.
3362    pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {
3363        let handle = self.handle;
3364        cx.defer(move |cx| {
3365            handle.update(cx, |_, window, cx| f(window, cx)).ok();
3366        });
3367    }
3368
3369    /// Calls `on_notify` each time `observed` is notified, with a handle to it and this window.
3370    ///
3371    /// This is the window-aware form of [`Context::observe`]. The callback runs
3372    /// when the current update finishes, not during the call to [`Context::notify`].
3373    /// The observation lasts as long as the returned [`Subscription`] is alive, and
3374    /// it ends early once `observed` is released.
3375    pub fn observe<T: 'static>(
3376        &mut self,
3377        observed: &Entity<T>,
3378        cx: &mut App,
3379        mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,
3380    ) -> Subscription {
3381        let entity_id = observed.entity_id();
3382        let observed = observed.downgrade();
3383        let window_handle = self.handle;
3384        cx.new_observer(
3385            entity_id,
3386            Box::new(move |cx| {
3387                window_handle
3388                    .update(cx, |_, window, cx| {
3389                        if let Some(handle) = observed.upgrade() {
3390                            on_notify(handle, window, cx);
3391                            true
3392                        } else {
3393                            false
3394                        }
3395                    })
3396                    .unwrap_or(false)
3397            }),
3398        )
3399    }
3400
3401    /// Calls `on_event` each time `entity` emits an event of type `Evt`.
3402    ///
3403    /// The callback receives a handle to the emitter, the event, and this window. It
3404    /// is the window-aware form of [`Context::subscribe`]. The subscription lasts as
3405    /// long as the returned [`Subscription`] is alive, and it ends early once
3406    /// `entity` is released. `Emitter` must implement [`EventEmitter`] for `Evt`.
3407    pub fn subscribe<Emitter, Evt>(
3408        &mut self,
3409        entity: &Entity<Emitter>,
3410        cx: &mut App,
3411        mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,
3412    ) -> Subscription
3413    where
3414        Emitter: EventEmitter<Evt>,
3415        Evt: 'static,
3416    {
3417        let entity_id = entity.entity_id();
3418        let handle = entity.downgrade();
3419        let window_handle = self.handle;
3420        cx.new_subscription(
3421            entity_id,
3422            (
3423                TypeId::of::<Evt>(),
3424                Box::new(move |event, cx| {
3425                    window_handle
3426                        .update(cx, |_, window, cx| {
3427                            if let Some(entity) = handle.upgrade() {
3428                                let event = event.downcast_ref().expect("invalid event type");
3429                                on_event(entity, event, window, cx);
3430                                true
3431                            } else {
3432                                false
3433                            }
3434                        })
3435                        .unwrap_or(false)
3436                }),
3437            ),
3438        )
3439    }
3440
3441    /// Calls `on_release` once when `entity` is released, with its final state and this window.
3442    ///
3443    /// The callback runs after the last handle to `entity` is dropped. Keep the
3444    /// returned [`Subscription`] alive until the entity is released; dropping it
3445    /// cancels the callback.
3446    pub fn observe_release<T>(
3447        &self,
3448        entity: &Entity<T>,
3449        cx: &mut App,
3450        mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
3451    ) -> Subscription
3452    where
3453        T: 'static,
3454    {
3455        let entity_id = entity.entity_id();
3456        let window_handle = self.handle;
3457        let (subscription, activate) = cx.release_listeners.insert(
3458            entity_id,
3459            Box::new(move |entity, cx| {
3460                let entity = entity.downcast_mut().expect("invalid entity type");
3461                let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
3462            }),
3463        );
3464        activate();
3465        subscription
3466    }
3467
3468    /// Returns an [`AsyncWindowContext`] for this window, which can be held across `.await` points.
3469    ///
3470    /// Use it inside a task spawned with `cx.spawn` when the task needs to update
3471    /// this window later.
3472    pub fn to_async(&self, cx: &App) -> AsyncWindowContext {
3473        AsyncWindowContext::new_context(cx.to_async(), self.handle)
3474    }
3475
3476    /// Runs `callback` once, after the next frame is drawn.
3477    ///
3478    /// The callback runs after the frame has been prepainted and painted, so the
3479    /// frame on screen is already set. If the callback changes state, it draws
3480    /// again on a later frame. Use it to draw a frame that depends on the one
3481    /// before, or to keep a loop going. [`Window::request_animation_frame`] builds on
3482    /// this method.
3483    ///
3484    /// # Examples
3485    ///
3486    /// ```
3487    /// # use gpui::{TestApp, Window, Context, div, prelude::*};
3488    /// # use std::{cell::Cell, rc::Rc};
3489    /// # struct Root;
3490    /// # impl Render for Root {
3491    /// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
3492    /// #         div()
3493    /// #     }
3494    /// # }
3495    /// # let mut app = TestApp::new();
3496    /// # let mut window = app.open_window(|_, _| Root);
3497    /// let ran = Rc::new(Cell::new(false));
3498    /// let flag = ran.clone();
3499    /// window.update(|_, window, _| window.on_next_frame(move |_, _| flag.set(true)));
3500    /// window.update(|_, window, cx| {
3501    ///     window.simulate_next_frame(cx);
3502    /// });
3503    /// assert!(ran.get());
3504    /// ```
3505    pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {
3506        RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));
3507        self.platform_window.schedule_frame();
3508        // Next-frame callbacks create frame demand without dirtying the
3509        // window, so the platform's frame source must be woken explicitly.
3510        self.invalidator.wake_platform();
3511    }
3512
3513    /// Draws the current view again on the next frame, even if nothing changed.
3514    ///
3515    /// Use it for continuous drawing, such as a video or a canvas that updates
3516    /// every frame. Call it while rendering or painting the view that should
3517    /// update. It notifies that view on the next frame, and stops when you stop
3518    /// calling it.
3519    ///
3520    /// Purely decorative motion, such as spinners, should use
3521    /// [`AnimationExt::with_animation`](crate::AnimationExt::with_animation), which
3522    /// respects [`App::reduce_motion`]. If you use this method for decorative motion
3523    /// instead, check [`App::reduce_motion`] first.
3524    ///
3525    /// # Panics
3526    ///
3527    /// Panics if no view is being rendered or painted. Use [`Window::on_next_frame`]
3528    /// instead when you aren't inside a view.
3529    pub fn request_animation_frame(&self) {
3530        let entity = self.current_view();
3531        // The next draw rebuilds this view even if it runs before the frame callback does.
3532        self.invalidator.mark_dirty_for_next_draw(entity);
3533        self.on_next_frame(move |_, cx| cx.notify(entity));
3534    }
3535
3536    /// Runs the callbacks scheduled with [`Window::on_next_frame`] and returns how many ran.
3537    ///
3538    /// Tests have no platform frame loop, so this runs the pending callbacks in place
3539    /// of the next frame. Callbacks scheduled while it runs wait for the next call.
3540    #[cfg(any(test, feature = "test-support"))]
3541    pub fn simulate_next_frame(&mut self, cx: &mut App) -> usize {
3542        let callbacks = self.next_frame_callbacks.take();
3543        let count = callbacks.len();
3544        for callback in callbacks {
3545            callback(self, cx);
3546        }
3547        count
3548    }
3549
3550    /// Spawns a future on the foreground executor, and gives it access to this window.
3551    ///
3552    /// The closure receives an [`AsyncWindowContext`] that the future can use to
3553    /// update the window after `.await` points. The task runs on the main thread,
3554    /// and the returned [`Task`] cancels the work when it is dropped.
3555    #[track_caller]
3556    pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>
3557    where
3558        R: 'static,
3559        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
3560    {
3561        let handle = self.handle;
3562        cx.spawn(async move |app| {
3563            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
3564            f(&mut async_window_cx).await
3565        })
3566    }
3567
3568    /// Like [`Window::spawn`], but schedules the future at the given `priority`.
3569    #[track_caller]
3570    pub fn spawn_with_priority<AsyncFn, R>(
3571        &self,
3572        priority: Priority,
3573        cx: &App,
3574        f: AsyncFn,
3575    ) -> Task<R>
3576    where
3577        R: 'static,
3578        AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
3579    {
3580        let handle = self.handle;
3581        cx.spawn_with_priority(priority, async move |app| {
3582            let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
3583            f(&mut async_window_cx).await
3584        })
3585    }
3586
3587    /// Refreshes the window's cached size, scale and display, and calls the bounds observers.
3588    ///
3589    /// The platform calls this when the window resizes or moves between displays. It
3590    /// reads the new viewport size, scale factor, display and mouse position, redraws
3591    /// the window, and then calls each callback registered with [`Window::observe`]
3592    /// on the window bounds. Tests call it to simulate a resize; use
3593    /// `TestAppWindow::simulate_resize` for that.
3594    pub fn bounds_changed(&mut self, cx: &mut App) {
3595        self.scale_factor = self.platform_window.scale_factor();
3596        self.viewport_size = self.platform_window.content_size();
3597        self.mouse_position = self.platform_window.mouse_position();
3598
3599        self.refresh();
3600
3601        self.bounds_observers
3602            .clone()
3603            .retain(&(), |callback| callback(self, cx));
3604    }
3605
3606    fn display_changed(handle: AnyWindowHandle, cx: &mut App) {
3607        let moved_to = handle
3608            .update(cx, |_, window, _| {
3609                let display_id = window.platform_window.display().map(|display| display.id());
3610                let moved = display_id != window.display_id;
3611                window.display_id = display_id;
3612                moved.then_some(display_id)
3613            })
3614            .log_err()
3615            .flatten();
3616        let Some(display_id) = moved_to else {
3617            return;
3618        };
3619        // The platform's notifications about the window and about displays
3620        // arrive in no guaranteed order, so make sure App knows the display
3621        // before the window's observers read its state.
3622        if let Some(display_id) = display_id
3623            && !cx.knows_display(display_id)
3624        {
3625            cx.displays_changed();
3626        }
3627        handle
3628            .update(cx, |_, window, cx| window.notify_display_observers(cx))
3629            .log_err();
3630    }
3631
3632    pub(crate) fn notify_display_observers(&mut self, cx: &mut App) {
3633        self.display_observers
3634            .clone()
3635            .retain(&(), |callback| callback(self, cx));
3636    }
3637
3638    /// The time between refreshes of the display the window is on, as of the
3639    /// platform's last display change notification. Variable refresh rate
3640    /// displays report their maximum rate. Returns `None` when the platform
3641    /// doesn't report it.
3642    pub fn refresh_interval(&self, cx: &App) -> Option<Duration> {
3643        cx.display_refresh_interval(self.display_id?)
3644    }
3645
3646    /// Registers a callback invoked when the window moves to another display
3647    /// or its display's properties change, for example its refresh
3648    /// interval. [`Self::refresh_interval`] already returns the new value
3649    /// when the callback runs.
3650    pub fn observe_window_display(
3651        &self,
3652        mut callback: impl FnMut(&mut Window, &mut App) + 'static,
3653    ) -> Subscription {
3654        let (subscription, activate) = self.display_observers.insert(
3655            (),
3656            Box::new(move |window, cx| {
3657                callback(window, cx);
3658                true
3659            }),
3660        );
3661        activate();
3662        subscription
3663    }
3664
3665    /// Returns the window's bounds in global screen coordinates, in logical pixels.
3666    ///
3667    /// The window can span several displays, so the origin is in the same global space
3668    /// as the displays. Use [`Window::viewport_size`] for the size of the content area.
3669    pub fn bounds(&self) -> Bounds<Pixels> {
3670        self.platform_window.bounds()
3671    }
3672
3673    /// Returns the regions of this window obscured by system UI and the keyboard.
3674    pub fn insets(&self) -> WindowInsets {
3675        self.platform_window.insets()
3676    }
3677
3678    /// Rasterizes the last rendered frame and returns its pixels as an RGBA image.
3679    ///
3680    /// The frame isn't shown on screen, and the window doesn't need to be visible.
3681    /// Use it for visual tests. Returns an error if the platform can't render to an image.
3682    #[cfg(any(test, feature = "test-support"))]
3683    pub fn render_to_image(&self) -> anyhow::Result<image::RgbaImage> {
3684        self.platform_window
3685            .render_to_image(&self.rendered_frame.scene)
3686    }
3687
3688    /// Returns how many quads, monochrome sprites, subpixel sprites and polychrome sprites the last frame contains.
3689    ///
3690    /// The four counts are in that order. Use them in tests to check that a
3691    /// change painted or removed primitives, without comparing pixels.
3692    #[cfg(any(test, feature = "test-support"))]
3693    pub fn rendered_primitive_counts(&self) -> (usize, usize, usize, usize) {
3694        let scene = &self.rendered_frame.scene;
3695        (
3696            scene.quads.len(),
3697            scene.monochrome_sprites.len(),
3698            scene.subpixel_sprites.len(),
3699            scene.polychrome_sprites.len(),
3700        )
3701    }
3702
3703    /// Returns the quads in the last rendered frame, for tests that check painted output.
3704    ///
3705    /// Quad bounds are in scaled pixels and aren't clipped. Each quad carries the
3706    /// content mask it is clipped to when drawn. Quads whose bounds don't intersect
3707    /// their content mask are skipped while painting, so they don't appear here.
3708    ///
3709    /// # Examples
3710    ///
3711    /// ```
3712    /// # use gpui::{TestApp, Window, Context, Render, IntoElement, canvas, fill, px, rgb, prelude::*};
3713    /// # struct Root;
3714    /// # impl Render for Root {
3715    /// #     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
3716    /// #         canvas(|_, _, _| {}, |bounds, _, window, _| {
3717    /// #             window.paint_quad(fill(bounds, rgb(0x2563eb)));
3718    /// #         })
3719    /// #         .size(px(100.))
3720    /// #     }
3721    /// # }
3722    /// # let mut app = TestApp::new();
3723    /// # let mut window = app.open_window(|_, _| Root);
3724    /// window.draw();
3725    /// window.update(|_, window, _| assert_eq!(window.painted_quads().len(), 1));
3726    /// ```
3727    #[cfg(any(test, feature = "test-support"))]
3728    pub fn painted_quads(&self) -> Vec<Quad> {
3729        self.rendered_frame.scene.quads.clone()
3730    }
3731
3732    /// Returns the underlines in the most recently rendered frame's scene.
3733    #[cfg(any(test, feature = "test-support"))]
3734    pub fn painted_underlines(&self) -> Vec<Underline> {
3735        self.rendered_frame.scene.underlines.clone()
3736    }
3737
3738    /// Resizes the window's content area to `size`, in logical pixels.
3739    pub fn resize(&mut self, size: Size<Pixels>) {
3740        self.platform_window.resize(size);
3741    }
3742
3743    /// Returns whether the window is in fullscreen mode.
3744    pub fn is_fullscreen(&self) -> bool {
3745        self.platform_window.is_fullscreen()
3746    }
3747
3748    /// Returns whether the window is in simple fullscreen, which covers the whole screen
3749    /// including the menu bar.
3750    ///
3751    /// Always `false` on platforms other than macOS.
3752    pub fn is_simple_fullscreen(&self) -> bool {
3753        self.platform_window.is_simple_fullscreen()
3754    }
3755
3756    pub(crate) fn appearance_changed(&mut self, cx: &mut App) {
3757        self.appearance = self.platform_window.appearance();
3758
3759        self.appearance_observers
3760            .clone()
3761            .retain(&(), |callback| callback(self, cx));
3762    }
3763
3764    pub(crate) fn button_layout_changed(&mut self, cx: &mut App) {
3765        self.button_layout_observers
3766            .clone()
3767            .retain(&(), |callback| callback(self, cx));
3768    }
3769
3770    /// Returns whether the system uses a light or dark appearance for this window.
3771    ///
3772    /// Updated before the callbacks from [`Window::observe_window_appearance`] run.
3773    pub fn appearance(&self) -> WindowAppearance {
3774        self.appearance
3775    }
3776
3777    /// Returns the size of the window's content area, in logical pixels.
3778    ///
3779    /// This excludes window decorations, so it is the size your root view lays out in.
3780    pub fn viewport_size(&self) -> Size<Pixels> {
3781        self.viewport_size
3782    }
3783
3784    /// Returns the platform's visible viewport in window-local logical pixels.
3785    ///
3786    /// Unlike `viewport_size`, this can shrink or move when the keyboard opens.
3787    /// During drawing this is a consistent frame snapshot. Outside drawing it
3788    /// reflects the latest platform sample, not a synchronous geometry query.
3789    pub fn visual_viewport_bounds(&self) -> Bounds<Pixels> {
3790        self.platform_window.visual_viewport_bounds()
3791    }
3792
3793    /// Returns a conservative rectangle avoiding platform-known obscured content.
3794    ///
3795    /// Intersects the visual viewport with the full layout area inset by system
3796    /// safe areas and keyboard occlusion. Unknown overlays cannot be excluded.
3797    pub fn fully_visible_bounds(&self) -> Bounds<Pixels> {
3798        let insets = self.platform_window.insets().effective();
3799        let viewport = self.viewport_size();
3800        let left = insets.left.max(Pixels::ZERO).min(viewport.width);
3801        let top = insets.top.max(Pixels::ZERO).min(viewport.height);
3802        let right = (viewport.width - insets.right.max(Pixels::ZERO)).max(left);
3803        let bottom = (viewport.height - insets.bottom.max(Pixels::ZERO)).max(top);
3804        let safe_bounds = Bounds::from_corners(point(left, top), point(right, bottom));
3805        let mut visible = safe_bounds.intersect(&self.visual_viewport_bounds());
3806        visible.size.width = visible.size.width.max(Pixels::ZERO);
3807        visible.size.height = visible.size.height.max(Pixels::ZERO);
3808        visible
3809    }
3810
3811    /// Requests the virtual keyboard for the currently focused text input.
3812    ///
3813    /// Call from a user gesture on platforms that require one. The platform may
3814    /// decline the request; this does not change focus or the layout viewport.
3815    pub fn request_virtual_keyboard(&self) {
3816        self.platform_window.show_soft_keyboard();
3817    }
3818
3819    /// Requests dismissal of the virtual keyboard without changing GPUI focus.
3820    pub fn dismiss_virtual_keyboard(&self) {
3821        self.platform_window.hide_soft_keyboard();
3822    }
3823
3824    /// Returns whether the operating system considers this window active.
3825    ///
3826    /// Key input goes to the focused element only while the window is active.
3827    pub fn is_window_active(&self) -> bool {
3828        self.active.get()
3829    }
3830
3831    /// Returns whether this is the window that the mouse pointer is over.
3832    ///
3833    /// On macOS this is the same as [`Window::is_window_active`].
3834    pub fn is_window_hovered(&self) -> bool {
3835        if cfg!(any(
3836            target_os = "windows",
3837            target_os = "linux",
3838            target_os = "freebsd"
3839        )) {
3840            self.hovered.get()
3841        } else {
3842            self.is_window_active()
3843        }
3844    }
3845
3846    /// Zooms the window using the platform's zoom behavior.
3847    pub fn zoom_window(&self) {
3848        self.platform_window.zoom();
3849    }
3850
3851    /// Opens the platform's title bar menu at `position`, in window coordinates.
3852    ///
3853    /// Use it from a custom title bar with client-side decorations, on Wayland and X11.
3854    pub fn show_window_menu(&self, position: Point<Pixels>) {
3855        self.platform_window.show_window_menu(position)
3856    }
3857
3858    /// Hands window movement to the platform's compositor, so the window follows the pointer.
3859    ///
3860    /// Call it from a mouse-down handler on your custom title bar, on Wayland and X11.
3861    /// Mouse events may not arrive while the move is in progress.
3862    pub fn start_window_move(&self) {
3863        self.platform_window.start_window_move()
3864    }
3865
3866    /// Sets the width of the invisible shadow or border that client-side decorations draw.
3867    ///
3868    /// Use it on Wayland and X11 when your app draws its own decorations. Read it
3869    /// back with [`Window::client_inset`].
3870    pub fn set_client_inset(&mut self, inset: Pixels) {
3871        self.client_inset = Some(inset);
3872        self.platform_window.set_client_inset(inset);
3873    }
3874
3875    /// Returns the inset set by [`Window::set_client_inset`], or `None` if none was set.
3876    pub fn client_inset(&self) -> Option<Pixels> {
3877        self.client_inset
3878    }
3879
3880    /// Returns whether the window uses server-side or client-side decorations.
3881    ///
3882    /// Client-side decorations mean your app must draw the title bar and window controls.
3883    /// This applies on Wayland and X11.
3884    pub fn window_decorations(&self) -> Decorations {
3885        self.platform_window.window_decorations()
3886    }
3887
3888    /// Returns whether the window was opened as resizable in [`WindowOptions::is_resizable`].
3889    pub fn is_resizable(&self) -> bool {
3890        self.is_resizable
3891    }
3892
3893    /// Returns whether the window was opened as minimizable in [`WindowOptions::is_minimizable`].
3894    pub fn is_minimizable(&self) -> bool {
3895        self.is_minimizable
3896    }
3897
3898    /// Returns which window controls, such as minimize and maximize, the platform supports.
3899    pub fn window_controls(&self) -> WindowControls {
3900        self.platform_window.window_controls()
3901    }
3902
3903    /// Sets the window's title in the platform title bar, and in accessibility trees.
3904    pub fn set_window_title(&mut self, title: &str) {
3905        self.platform_window.set_title(title);
3906        self.a11y.set_window_title(title.to_string());
3907    }
3908
3909    /// Moves the macOS traffic light buttons to `position`, in window coordinates.
3910    #[cfg(target_os = "macos")]
3911    pub fn set_traffic_light_position(&self, position: Point<Pixels>) {
3912        self.platform_window.set_traffic_light_position(position);
3913    }
3914
3915    /// Sets the application identifier that the platform uses to group and match windows.
3916    pub fn set_app_id(&mut self, app_id: &str) {
3917        self.platform_window.set_app_id(app_id);
3918    }
3919
3920    /// Sets the window background appearance.
3921    pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
3922        self.platform_window
3923            .set_background_appearance(background_appearance);
3924    }
3925
3926    /// Mark the window as dirty at the platform level.
3927    pub fn set_window_edited(&mut self, edited: bool) {
3928        self.platform_window.set_edited(edited);
3929    }
3930
3931    /// Set the path of the file this window represents.
3932    /// On macOS, this sets the window's accessibility document property (AXDocument).
3933    pub fn set_document_path(&self, path: Option<&std::path::Path>) {
3934        self.platform_window.set_document_path(path);
3935    }
3936
3937    /// Determine the display on which the window is visible.
3938    pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {
3939        cx.platform
3940            .displays()
3941            .into_iter()
3942            .find(|display| Some(display.id()) == self.display_id)
3943    }
3944
3945    /// Show the platform character palette.
3946    ///
3947    /// On macOS and Windows, opens the system character or emoji picker. On Linux,
3948    /// opens an installed desktop picker (Plasma, IBus, GNOME Characters, or
3949    /// KCharSelect); these pickers may require copying and pasting the selection.
3950    /// Logs a warning if the platform has no available picker.
3951    pub fn show_character_palette(&self) {
3952        self.platform_window.show_character_palette();
3953    }
3954
3955    /// Returns the scale factor of the display the window is on.
3956    ///
3957    /// A value of `2.0` means each logical pixel is two device pixels, as on a Retina
3958    /// display. GPUI's coordinates are logical pixels; multiply by this value only when
3959    /// you need device pixels.
3960    pub fn scale_factor(&self) -> f32 {
3961        self.scale_factor
3962    }
3963
3964    /// Overrides the display scale factor, and redraws the window. Only available in tests.
3965    #[cfg(any(test, feature = "test-support"))]
3966    pub fn set_scale_factor(&mut self, scale_factor: f32) {
3967        self.scale_factor = scale_factor;
3968        self.refresh();
3969    }
3970
3971    /// Returns the size of one rem, in logical pixels.
3972    ///
3973    /// Rems are the unit of [`Styled`](crate::Styled) lengths such as `.text_size(rems(1.))`, so changing the
3974    /// rem size scales the whole window. The value is the one set by [`Window::set_rem_size`],
3975    /// or the one from the innermost [`Window::with_rem_size`] while it runs.
3976    pub fn rem_size(&self) -> Pixels {
3977        self.rem_size_override_stack
3978            .last()
3979            .copied()
3980            .unwrap_or(self.rem_size)
3981    }
3982
3983    /// Sets the size of one rem, in logical pixels, for the rest of the window's life.
3984    ///
3985    /// Call it when the user changes the font size. The new size is used the next time the
3986    /// window lays out, and it doesn't redraw the window by itself. Use [`Window::with_rem_size`]
3987    /// to change it for part of an element tree.
3988    pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
3989        self.rem_size = rem_size.into();
3990    }
3991
3992    /// Runs `f` with a global element id made from `element_id` and the ids already on the stack.
3993    ///
3994    /// The id is valid only inside `f`. Element state keyed by it, such as the state
3995    /// behind [`Window::use_state`], is found again on the next frame when the
3996    /// same path of ids is used. Most code calls [`Window::use_state`] instead.
3997    pub fn with_global_id<R>(
3998        &mut self,
3999        element_id: ElementId,
4000        f: impl FnOnce(&GlobalElementId, &mut Self) -> R,
4001    ) -> R {
4002        self.with_id(element_id, |this| {
4003            let global_id = this.element_id_stack.global_id();
4004
4005            f(&global_id, this)
4006        })
4007    }
4008
4009    /// Runs `f` with `element_id` pushed onto the element id stack, then pops it.
4010    ///
4011    /// Ids nest, so the same id under different parents identifies different elements.
4012    /// [`InteractiveElement::id`](crate::InteractiveElement::id) and [`Element`](crate::Element) implementations call this for you.
4013    #[inline]
4014    pub fn with_id<R>(
4015        &mut self,
4016        element_id: impl Into<ElementId>,
4017        f: impl FnOnce(&mut Self) -> R,
4018    ) -> R {
4019        self.element_id_stack.push(element_id.into());
4020        let result = f(self);
4021        self.element_id_stack.pop();
4022        result
4023    }
4024
4025    /// Runs `f` with `rem_size` as the rem size, or with the current rem size if `None`.
4026    ///
4027    /// The override applies to everything `f` lays out, paints or prepaints, and ends when it
4028    /// returns. Use it to render part of a tree at a different text scale.
4029    ///
4030    /// # Panics
4031    ///
4032    /// Panics in debug builds if called outside request layout, prepaint, or paint.
4033    // This function is called in a highly recursive manner in editor
4034    // prepainting, make sure its inlined to reduce the stack burden
4035    #[inline]
4036    pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R
4037    where
4038        F: FnOnce(&mut Self) -> R,
4039    {
4040        self.invalidator.debug_assert_paint_or_prepaint();
4041
4042        if let Some(rem_size) = rem_size {
4043            self.rem_size_override_stack.push(rem_size.into());
4044            let result = f(self);
4045            self.rem_size_override_stack.pop();
4046            result
4047        } else {
4048            f(self)
4049        }
4050    }
4051
4052    /// Returns the line height of the current text style, in logical pixels.
4053    pub fn line_height(&self) -> Pixels {
4054        self.text_style().line_height_in_pixels(self.rem_size())
4055    }
4056
4057    /// Rounds a value in logical pixels to the nearest device pixel.
4058    ///
4059    /// Use it to keep edges crisp when you draw lines or borders at fractional positions.
4060    #[inline]
4061    pub fn pixel_snap(&self, value: Pixels) -> Pixels {
4062        px(round_to_device_pixel(value.0, self.scale_factor()) / self.scale_factor())
4063    }
4064
4065    /// Rounds an `f64` logical value to the nearest device pixel. See [`Window::pixel_snap`].
4066    #[inline]
4067    pub fn pixel_snap_f64(&self, value: f64) -> f64 {
4068        let scale_factor = f64::from(self.scale_factor());
4069        round_half_toward_zero_f64(value * scale_factor) / scale_factor
4070    }
4071
4072    /// Rounds each edge of `bounds` to the nearest device pixel. See [`Window::pixel_snap`].
4073    #[inline]
4074    pub fn pixel_snap_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<Pixels> {
4075        bounds.map(|c| self.pixel_snap(c))
4076    }
4077
4078    /// Rounds each coordinate of `position` to the nearest device pixel. See [`Window::pixel_snap`].
4079    #[inline]
4080    pub fn pixel_snap_point(&self, position: Point<Pixels>) -> Point<Pixels> {
4081        position.map(|c| self.pixel_snap(c))
4082    }
4083
4084    /// Returns the snapped device-space bounds used to paint an underline.
4085    pub fn underline_bounds(
4086        &self,
4087        origin: Point<Pixels>,
4088        width: Pixels,
4089        style: &UnderlineStyle,
4090    ) -> Bounds<ScaledPixels> {
4091        let scale_factor = self.scale_factor();
4092        let thickness = self.snap_stroke(style.thickness);
4093        let height = if style.wavy {
4094            ScaledPixels(thickness.0 * 3.)
4095        } else {
4096            thickness
4097        };
4098        Bounds {
4099            origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
4100            size: size(self.snap_stroke(width), height),
4101        }
4102    }
4103
4104    /// Paints an underline excluding absolute device-space horizontal spans.
4105    pub fn paint_underline_with_exclusions(
4106        &mut self,
4107        origin: Point<Pixels>,
4108        width: Pixels,
4109        style: &UnderlineStyle,
4110        exclusions: &[Range<ScaledPixels>],
4111    ) {
4112        self.invalidator.debug_assert_paint();
4113        let underline = self.underline(origin, width, style);
4114        if exclusions.is_empty() {
4115            self.next_frame.scene.insert_primitive(underline);
4116            return;
4117        }
4118
4119        let bounds = underline.bounds.intersect(&underline.content_mask.bounds);
4120        if bounds.is_empty() {
4121            return;
4122        }
4123
4124        let mut exclusions = exclusions
4125            .iter()
4126            .filter_map(|span| {
4127                let start = span.start.max(bounds.left());
4128                let end = span.end.min(bounds.right());
4129                (start < end).then_some(start..end)
4130            })
4131            .collect::<SmallVec<[_; 4]>>();
4132        if exclusions.is_empty() {
4133            self.next_frame.scene.insert_primitive(underline);
4134            return;
4135        }
4136        exclusions.sort_unstable_by_key(|span| span.start);
4137
4138        let mut paint_span = |start, end| {
4139            let clip_bounds =
4140                Bounds::from_corners(point(start, bounds.top()), point(end, bounds.bottom()));
4141            self.next_frame.scene.insert_primitive(Underline {
4142                clip_bounds,
4143                ..underline
4144            });
4145        };
4146        let mut start = bounds.left();
4147        for exclusion in exclusions {
4148            if start < exclusion.start {
4149                paint_span(start, exclusion.start);
4150            }
4151            start = start.max(exclusion.end);
4152        }
4153        if start < bounds.right() {
4154            paint_span(start, bounds.right());
4155        }
4156    }
4157
4158    fn underline(&self, origin: Point<Pixels>, width: Pixels, style: &UnderlineStyle) -> Underline {
4159        let content_mask = self.snapped_content_mask();
4160        Underline {
4161            order: 0,
4162            padding: 0,
4163            bounds: self.underline_bounds(origin, width, style),
4164            clip_bounds: content_mask.bounds,
4165            content_mask,
4166            color: style.color.unwrap_or_default().into(),
4167            thickness: self.snap_stroke(style.thickness),
4168            wavy: style.wavy.into(),
4169        }
4170    }
4171
4172    #[inline]
4173    fn snap_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
4174        let scale_factor = self.scale_factor();
4175        let left = round_to_device_pixel(bounds.left().0, scale_factor);
4176        let top = round_to_device_pixel(bounds.top().0, scale_factor);
4177        let right = round_to_device_pixel(bounds.right().0, scale_factor).max(left);
4178        let bottom = round_to_device_pixel(bounds.bottom().0, scale_factor).max(top);
4179        Bounds::from_corners(
4180            point(ScaledPixels(left), ScaledPixels(top)),
4181            point(ScaledPixels(right), ScaledPixels(bottom)),
4182        )
4183    }
4184
4185    /// Rounds half-to-zero but clamps any non-zero input up to 1 dp so thin strokes do not disappear.
4186    #[inline]
4187    fn snap_stroke(&self, value: Pixels) -> ScaledPixels {
4188        ScaledPixels(round_stroke_to_device_pixel(value.0, self.scale_factor()))
4189    }
4190
4191    #[inline]
4192    fn snap_border_widths(&self, edges: Edges<Pixels>) -> Edges<ScaledPixels> {
4193        edges.map(|e| self.snap_stroke(*e))
4194    }
4195
4196    /// Floors the near edge and ceils the far edge, producing a strict superset of the raw region.
4197    #[inline]
4198    fn cover_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
4199        let scale_factor = self.scale_factor();
4200        let left = floor_to_device_pixel(bounds.left().0, scale_factor);
4201        let top = floor_to_device_pixel(bounds.top().0, scale_factor);
4202        let right = ceil_to_device_pixel(bounds.right().0, scale_factor).max(left);
4203        let bottom = ceil_to_device_pixel(bounds.bottom().0, scale_factor).max(top);
4204        Bounds::from_corners(
4205            point(ScaledPixels(left), ScaledPixels(top)),
4206            point(ScaledPixels(right), ScaledPixels(bottom)),
4207        )
4208    }
4209
4210    #[inline]
4211    fn snapped_content_mask(&self) -> ContentMask<ScaledPixels> {
4212        let mask = self.content_mask();
4213        ContentMask {
4214            bounds: self.cover_bounds(mask.bounds),
4215            fade_out: mask.fade_out.scale(self.scale_factor()),
4216        }
4217    }
4218
4219    /// Marks the event being dispatched as handled, so default behavior is skipped.
4220    ///
4221    /// Currently it stops parent elements from taking focus on a mouse down. Check
4222    /// the result with [`Window::default_prevented`] in later listeners.
4223    pub fn prevent_default(&mut self) {
4224        self.default_prevented = true;
4225    }
4226
4227    /// Returns whether [`Window::prevent_default`] was called for the event being dispatched.
4228    pub fn default_prevented(&self) -> bool {
4229        self.default_prevented
4230    }
4231
4232    /// Returns whether a listener for `action` is on the dispatch path from the focused element.
4233    ///
4234    /// Use it to enable or disable menu items and buttons that trigger `action`. If nothing has
4235    /// focus, the path starts at the window's root.
4236    pub fn is_action_available(&self, action: &dyn Action, cx: &App) -> bool {
4237        let node_id =
4238            self.focus_node_id_in_rendered_frame(self.focused(cx).map(|handle| handle.id));
4239        self.rendered_frame
4240            .dispatch_tree
4241            .is_action_available(action, node_id)
4242    }
4243
4244    /// Returns whether a listener for `action` is on the dispatch path from `focus_handle`.
4245    ///
4246    /// This is [`Window::is_action_available`] for an element other than the focused one.
4247    pub fn is_action_available_in(&self, action: &dyn Action, focus_handle: &FocusHandle) -> bool {
4248        let node_id = self.focus_node_id_in_rendered_frame(Some(focus_handle.id));
4249        self.rendered_frame
4250            .dispatch_tree
4251            .is_action_available(action, node_id)
4252    }
4253
4254    /// Returns the last known mouse position, in window coordinates.
4255    ///
4256    /// The position is updated from the mouse events the window receives.
4257    pub fn mouse_position(&self) -> Point<Pixels> {
4258        self.note_input_read(InputReads::POINTER);
4259        self.mouse_position
4260    }
4261
4262    /// Captures the pointer for `hitbox_id`. While captured, all mouse move and mouse up
4263    /// events will be routed to listeners that check this hitbox's `is_hovered` status,
4264    /// regardless of actual hit testing. This enables drag operations that continue
4265    /// even when the pointer moves outside the element's bounds.
4266    ///
4267    /// The capture is automatically released on mouse up.
4268    pub fn capture_pointer(&mut self, hitbox_id: HitboxId) {
4269        self.captured_hitbox = Some(hitbox_id);
4270    }
4271
4272    /// Releases the pointer capture set by [`Window::capture_pointer`], if there is one.
4273    pub fn release_pointer(&mut self) {
4274        self.captured_hitbox = None;
4275    }
4276
4277    /// Returns the hitbox that has captured the pointer, or `None` if the pointer isn't captured.
4278    pub fn captured_hitbox(&self) -> Option<HitboxId> {
4279        self.captured_hitbox
4280    }
4281
4282    /// Gives `entity` the current long press. Only the entity that captured it receives its events.
4283    ///
4284    /// The capture is released when the gesture ends or is cancelled, or when
4285    /// a replacement touch begins. A listener must also call
4286    /// [`Self::prevent_default`] on the started event to claim the gesture.
4287    pub fn capture_long_press<T: 'static>(&mut self, entity: &Entity<T>) {
4288        self.long_press_capture = Some(entity.entity_id());
4289    }
4290
4291    /// Returns whether `entity` is the one that captured the current long press.
4292    pub fn has_long_press_capture<T: 'static>(&self, entity: &Entity<T>) -> bool {
4293        self.long_press_capture == Some(entity.entity_id())
4294    }
4295
4296    /// Returns the modifier keys (Shift, Control, Alt, Command and so on) held right now.
4297    pub fn modifiers(&self) -> Modifiers {
4298        self.note_input_read(InputReads::MODIFIERS);
4299        self.modifiers
4300    }
4301
4302    /// Returns whether the most recent input came from the keyboard.
4303    ///
4304    /// Focus rings and hover styles often check this, so they appear only for keyboard
4305    /// navigation. [`HitboxId::is_hovered`] already returns `false` when it is `true`.
4306    pub fn last_input_was_keyboard(&self) -> bool {
4307        self.note_input_read(InputReads::MODALITY);
4308        self.last_input_modality == InputModality::Keyboard
4309    }
4310
4311    /// Returns whether the last input event came from a touch screen.
4312    pub fn last_input_was_touch(&self) -> bool {
4313        self.note_input_read(InputReads::MODALITY);
4314        self.last_input_modality == InputModality::Touch
4315    }
4316
4317    /// Returns the state of the Caps Lock key.
4318    pub fn capslock(&self) -> Capslock {
4319        self.note_input_read(InputReads::MODIFIERS);
4320        self.capslock
4321    }
4322
4323    fn note_input_read(&self, reads: InputReads) {
4324        self.input_reads.set(self.input_reads.get() | reads);
4325    }
4326
4327    /// Builds a new frame from the root view and makes it the rendered frame.
4328    ///
4329    /// This runs the render, request-layout, prepaint and paint phases, then swaps the
4330    /// frame in and delivers focus-change listeners. The frame is not shown until
4331    /// the window presents it to the screen. The returned token must be passed to
4332    /// [`ArenaClearNeeded::clear`], which frees the element arena for the next frame.
4333    /// GPUI calls this for every frame that needs one, so most code doesn't call it directly.
4334    #[profiling::function]
4335    pub fn draw(&mut self, cx: &mut App) -> ArenaClearNeeded {
4336        // Drain every draw in profiler builds so a previous frame's
4337        // first-invalidation timestamp can't be attributed to this one.
4338        #[cfg(feature = "profiler")]
4339        let frame_dirty = self.invalidator.take_frame_dirty();
4340        #[cfg(feature = "profiler")]
4341        self.window_profiler.begin_draw();
4342
4343        // Set up the per-App arena for element allocation during this draw.
4344        // This ensures that multiple test Apps have isolated arenas.
4345        let arena_scope = ElementArenaScope::enter(&cx.element_arena);
4346        self.frame_number += 1;
4347
4348        if self.platform_window.prepare_frame() {
4349            self.refresh();
4350        }
4351        self.invalidate_entities();
4352        cx.entities.clear_accessed();
4353        debug_assert!(self.rendered_entity_stack.is_empty());
4354        self.invalidator.set_dirty(false);
4355        self.requested_autoscroll = None;
4356
4357        // Restore the previously-used input handler. Place it back into a None slot (left by a
4358        // previous .take()) so cached paint-range indices remain valid. A platform can still
4359        // return an adapter from before a focus change, though; never let that stale focused
4360        // adapter replace the current handler stored in a retained paint range.
4361        if let Some(input_handler) = self.platform_window.take_input_handler() {
4362            let stale_focus = input_handler
4363                .focus_id()
4364                .is_some_and(|focus_id| Some(focus_id) != self.focus);
4365            if stale_focus {
4366                // The old handler's slot is None in the rendered frame. Rebuild retained output
4367                // this frame so it installs a handler for the current focus into that slot.
4368                self.refreshing = true;
4369            } else if let Some(slot) = self
4370                .rendered_frame
4371                .input_handlers
4372                .iter_mut()
4373                .rev()
4374                .find(|handler| handler.is_none())
4375            {
4376                *slot = Some(input_handler);
4377            } else {
4378                self.rendered_frame.input_handlers.push(Some(input_handler));
4379            }
4380        }
4381        if !cx.mode.skip_drawing() {
4382            self.draw_roots(cx);
4383            #[cfg(feature = "profiler")]
4384            {
4385                let viewport_size = self.viewport_size;
4386                let scale_factor = self.scale_factor();
4387                self.debug_frame_overlay.paint(
4388                    &mut self.next_frame.scene,
4389                    viewport_size,
4390                    scale_factor,
4391                );
4392            }
4393        }
4394        self.dirty_views.clear();
4395        self.next_frame.window_active = self.active.get();
4396
4397        // Register requested input handler with the platform window.
4398        // Use .take() instead of .pop() to preserve Vec length, so that cached
4399        // paint_range indices remain valid for reuse_paint on the next frame.
4400        // Search backwards to find the last Some entry, since reuse_paint may
4401        // have copied None slots from the previous frame. (Fixes #50456)
4402        let focused_text_input = if let Some(mut input_handler) = self
4403            .next_frame
4404            .input_handlers
4405            .iter_mut()
4406            .rev()
4407            .find_map(|h| h.take())
4408        {
4409            let accepts_text_input = input_handler.accepts_text_input(self, cx);
4410            self.platform_window.set_input_handler(input_handler);
4411            self.focus.filter(|_| accepts_text_input)
4412        } else {
4413            None
4414        };
4415        self.apply_text_input_configuration(cx);
4416        let previous = mem::replace(&mut self.focused_text_input, focused_text_input);
4417        if previous.is_some() != focused_text_input.is_some() {
4418            self.platform_window
4419                .text_input_state_changed(if focused_text_input.is_some() {
4420                    TextInputStateChange::FocusGained
4421                } else {
4422                    TextInputStateChange::FocusLost
4423                });
4424        }
4425
4426        self.layout_engine.as_mut().unwrap().clear();
4427        self.text_system().finish_frame();
4428        self.next_frame.finish(&mut self.rendered_frame);
4429
4430        self.invalidator.set_phase(DrawPhase::Focus);
4431        let previous_focus_path = self.rendered_frame.focus_path();
4432        let previous_window_active = self.rendered_frame.window_active;
4433        mem::swap(&mut self.rendered_frame, &mut self.next_frame);
4434        self.next_frame.clear();
4435        let current_focus_path = self.rendered_frame.focus_path();
4436        let current_window_active = self.rendered_frame.window_active;
4437        let mut focus_before_listeners = self.focus;
4438
4439        if previous_focus_path != current_focus_path
4440            || previous_window_active != current_window_active
4441        {
4442            if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
4443                self.focus_lost_path = previous_focus_path.clone();
4444                self.focus_lost_listeners
4445                    .clone()
4446                    .retain(&(), |listener| listener(self, cx));
4447                self.focus_lost_path = SmallVec::new();
4448                // The focus-lost fallback (e.g. a workspace refocusing itself) may target
4449                // an element that isn't part of the element tree, in which case scheduling
4450                // a redraw below would dispatch focus-lost again, looping forever. Only
4451                // track focus movement caused by the focus listeners.
4452                focus_before_listeners = self.focus;
4453            }
4454
4455            let event = WindowFocusEvent {
4456                previous_focus_path: if previous_window_active {
4457                    previous_focus_path
4458                } else {
4459                    Default::default()
4460                },
4461                current_focus_path: if current_window_active {
4462                    current_focus_path
4463                } else {
4464                    Default::default()
4465                },
4466            };
4467            self.focus_listeners
4468                .clone()
4469                .retain(&(), |listener| listener(&event, self, cx));
4470        }
4471
4472        debug_assert!(self.rendered_entity_stack.is_empty());
4473        self.record_entities_accessed(cx);
4474        self.reset_cursor_style(cx);
4475        self.refreshing = false;
4476        self.invalidator.set_phase(DrawPhase::None);
4477        self.notify_pointer_observers(PointerChangeCause::Layout, cx);
4478        // Focus listeners may move focus (e.g. a dock forwarding focus to its active
4479        // panel). `Window::focus` suppresses `refresh` while a draw is in progress, so
4480        // schedule another frame here to render the new focus state and dispatch the
4481        // resulting focus events.
4482        if self.focus != focus_before_listeners {
4483            self.refresh();
4484        }
4485        self.needs_present.set(true);
4486
4487        #[cfg(feature = "profiler")]
4488        {
4489            self.window_profiler
4490                .set_refresh_interval(self.refresh_interval(cx));
4491            let draw_duration = self
4492                .window_profiler
4493                .end_draw(frame_dirty.dirty_at, frame_dirty.invalidations);
4494            self.debug_frame_overlay.record_frame(draw_duration);
4495        }
4496
4497        // Exit the scope to obtain the arena-clear token this draw owes; the
4498        // scope's teardown itself happens in `ElementArenaScope::drop`.
4499        arena_scope.exit(&cx.element_arena)
4500    }
4501
4502    fn record_entities_accessed(&mut self, cx: &mut App) {
4503        let mut entities_ref = cx.entities.accessed_entities.get_mut();
4504        let mut entities = mem::take(entities_ref.deref_mut());
4505        let handle = self.handle;
4506        cx.record_entities_accessed(
4507            handle,
4508            // Try moving window invalidator into the Window
4509            self.invalidator.clone(),
4510            &entities,
4511        );
4512        let mut entities_ref = cx.entities.accessed_entities.get_mut();
4513        mem::swap(&mut entities, entities_ref.deref_mut());
4514    }
4515
4516    fn invalidate_entities(&mut self) {
4517        let mut views = self.invalidator.take_views();
4518        for entity in views.drain() {
4519            self.mark_view_dirty(entity);
4520        }
4521        self.invalidator.replace_views(views);
4522    }
4523
4524    #[profiling::function]
4525    fn present(&mut self) {
4526        #[cfg(feature = "profiler")]
4527        let _foreground_turn = profiler::journal::foreground_turn();
4528        #[cfg(feature = "profiler")]
4529        let present_start = Instant::now();
4530        self.platform_window.draw(&self.rendered_frame.scene);
4531        #[cfg(feature = "profiler")]
4532        self.window_profiler.record_present(
4533            present_start,
4534            Instant::now(),
4535            self.active.get(),
4536            !self.next_frame_callbacks.borrow().is_empty(),
4537        );
4538        self.needs_present.set(false);
4539        profiling::finish_frame!();
4540    }
4541
4542    /// Presents the most recently drawn frame if it hasn't been presented yet.
4543    #[cfg(all(test, feature = "profiler"))]
4544    pub fn present_if_needed(&mut self) {
4545        if self.needs_present.get() {
4546            self.present();
4547        }
4548    }
4549
4550    /// Returns a snapshot of the current input-latency histograms.
4551    #[cfg(feature = "profiler")]
4552    pub fn input_latency_snapshot(&self) -> profiler::InputLatencySnapshot {
4553        self.window_profiler.input_latency_snapshot()
4554    }
4555
4556    /// Returns a snapshot of the current frame-duration histograms.
4557    #[cfg(feature = "profiler")]
4558    pub fn frame_duration_snapshot(&self) -> profiler::FrameDurationSnapshot {
4559        self.window_profiler.frame_duration_snapshot()
4560    }
4561
4562    /// Returns the current mode of the debug frame overlay.
4563    #[cfg(feature = "profiler")]
4564    pub fn debug_frame_overlay_mode(&self) -> DebugFrameOverlayMode {
4565        self.debug_frame_overlay.mode()
4566    }
4567
4568    /// Sets the mode of the debug frame overlay and schedules a redraw.
4569    #[cfg(feature = "profiler")]
4570    pub fn set_debug_frame_overlay_mode(&mut self, mode: DebugFrameOverlayMode) {
4571        self.debug_frame_overlay.set_mode(mode);
4572        self.refresh();
4573    }
4574
4575    /// Advances the debug frame overlay through its hidden, frame-time-only,
4576    /// and detailed modes.
4577    #[cfg(feature = "profiler")]
4578    pub fn cycle_debug_frame_overlay_mode(&mut self) {
4579        self.set_debug_frame_overlay_mode(self.debug_frame_overlay.mode().next());
4580    }
4581
4582    /// Clears the debug frame overlay's frame-time statistics, except for the
4583    /// total frame count, and schedules a redraw.
4584    #[cfg(feature = "profiler")]
4585    pub fn reset_debug_frame_overlay_stats(&mut self) {
4586        self.debug_frame_overlay.reset_stats();
4587        self.refresh();
4588    }
4589
4590    fn draw_roots(&mut self, cx: &mut App) {
4591        self.invalidator.set_phase(DrawPhase::Prepaint);
4592        self.tooltip_bounds.take();
4593
4594        self.a11y.sync_active_flag();
4595        if self.a11y.is_active() {
4596            self.a11y.begin_frame();
4597        }
4598
4599        let _inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size());
4600        let root_size = {
4601            #[cfg(any(feature = "inspector", debug_assertions))]
4602            {
4603                if self.inspector.is_some() {
4604                    let mut size = self.viewport_size;
4605                    size.width = (size.width - _inspector_width).max(px(0.0));
4606                    size
4607                } else {
4608                    self.viewport_size
4609                }
4610            }
4611            #[cfg(not(any(feature = "inspector", debug_assertions)))]
4612            {
4613                self.viewport_size
4614            }
4615        };
4616
4617        // Layout all root elements. Like the root element on the web, which
4618        // stretches to fill the viewport unless explicitly sized, window roots
4619        // fill the window when their size is `auto`.
4620        let scale_factor = self.scale_factor();
4621        #[cfg(feature = "profiler")]
4622        let request_layout_start = Instant::now();
4623        let mut root_element = self.root.as_ref().unwrap().clone().into_any_element();
4624        let root_layout_id = root_element.request_layout(self, cx);
4625        #[cfg(feature = "profiler")]
4626        let prepaint_start = Instant::now();
4627        self.layout_engine
4628            .as_mut()
4629            .unwrap()
4630            .stretch_auto_size_to_fill(root_layout_id, root_size, scale_factor);
4631        root_element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
4632
4633        #[cfg(any(feature = "inspector", debug_assertions))]
4634        let inspector_element = self.prepaint_inspector(_inspector_width, cx);
4635
4636        self.prepaint_deferred_draws(cx);
4637
4638        let mut prompt_element = None;
4639        let mut active_drag_element = None;
4640        let mut tooltip_element = None;
4641        if let Some(prompt) = self.prompt.take() {
4642            let mut element = prompt.view.any_view().into_any_element();
4643            let prompt_layout_id = element.request_layout(self, cx);
4644            self.layout_engine
4645                .as_mut()
4646                .unwrap()
4647                .stretch_auto_size_to_fill(prompt_layout_id, root_size, scale_factor);
4648            element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
4649            prompt_element = Some(element);
4650            self.prompt = Some(prompt);
4651        } else if let Some(active_drag) = cx.active_drag.take() {
4652            let mut element = active_drag.view.clone().into_any_element();
4653            let offset = self.mouse_position() - active_drag.cursor_offset;
4654            element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);
4655            active_drag_element = Some(element);
4656            cx.active_drag = Some(active_drag);
4657        } else {
4658            tooltip_element = self.prepaint_tooltip(cx);
4659        }
4660
4661        self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);
4662
4663        // Now actually paint the elements.
4664        #[cfg(feature = "profiler")]
4665        let paint_start = Instant::now();
4666        self.invalidator.set_phase(DrawPhase::Paint);
4667        root_element.paint(self, cx);
4668
4669        #[cfg(any(feature = "inspector", debug_assertions))]
4670        self.paint_inspector(inspector_element, cx);
4671
4672        self.paint_deferred_draws(cx);
4673
4674        if let Some(mut prompt_element) = prompt_element {
4675            prompt_element.paint(self, cx);
4676        } else if let Some(mut drag_element) = active_drag_element {
4677            drag_element.paint(self, cx);
4678        } else if let Some(mut tooltip_element) = tooltip_element {
4679            tooltip_element.paint(self, cx);
4680        }
4681
4682        #[cfg(any(feature = "inspector", debug_assertions))]
4683        self.paint_inspector_hitbox(cx);
4684
4685        #[cfg(feature = "profiler")]
4686        self.window_profiler
4687            .record_draw_phases(profiler::DrawPhases {
4688                request_layout: prepaint_start.duration_since(request_layout_start),
4689                prepaint: paint_start.duration_since(prepaint_start),
4690                paint: Instant::now().duration_since(paint_start),
4691            });
4692
4693        // a11y may have been activated/deactivated halfway through the frame
4694        let a11y_active_start_of_frame = self.a11y.is_active();
4695        self.a11y.sync_active_flag();
4696        let a11y_active_end_of_frame = self.a11y.is_active();
4697
4698        let should_send_a11y_update = a11y_active_start_of_frame && a11y_active_end_of_frame;
4699
4700        if a11y_active_start_of_frame {
4701            // Harvest frame metadata for the debug dump while the live window
4702            // and frame are still in scope.
4703            let frame_info = crate::window::a11y::debug::FrameDebugInfo {
4704                viewport_size: self.viewport_size,
4705                scale_factor: self.scale_factor,
4706                tab_stop_count: self.next_frame.tab_stops.tab_stop_count(),
4707            };
4708            // clear the builder state regardless
4709            let tree_update = self.a11y.end_frame(frame_info);
4710
4711            if should_send_a11y_update {
4712                log::debug!(
4713                    "Sending a11y tree update: {} nodes",
4714                    tree_update.nodes.len()
4715                );
4716                self.platform_window.a11y_tree_update(tree_update);
4717            }
4718        }
4719    }
4720
4721    fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {
4722        // Use indexing instead of iteration to avoid borrowing self for the duration of the loop.
4723        for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {
4724            let Some(Some(tooltip_request)) = self
4725                .next_frame
4726                .tooltip_requests
4727                .get(tooltip_request_index)
4728                .cloned()
4729            else {
4730                log::error!("Unexpectedly absent TooltipRequest");
4731                continue;
4732            };
4733            let mut element = tooltip_request.tooltip.view.clone().into_any_element();
4734            let mouse_position = tooltip_request.tooltip.mouse_position;
4735            let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);
4736
4737            let mut tooltip_bounds =
4738                Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
4739            let window_bounds = Bounds {
4740                origin: Point::default(),
4741                size: self.viewport_size(),
4742            };
4743
4744            if tooltip_bounds.right() > window_bounds.right() {
4745                let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
4746                if new_x >= Pixels::ZERO {
4747                    tooltip_bounds.origin.x = new_x;
4748                } else {
4749                    tooltip_bounds.origin.x = cmp::max(
4750                        Pixels::ZERO,
4751                        tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
4752                    );
4753                }
4754            }
4755
4756            if tooltip_bounds.bottom() > window_bounds.bottom() {
4757                let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
4758                if new_y >= Pixels::ZERO {
4759                    tooltip_bounds.origin.y = new_y;
4760                } else {
4761                    tooltip_bounds.origin.y = cmp::max(
4762                        Pixels::ZERO,
4763                        tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
4764                    );
4765                }
4766            }
4767
4768            // It's possible for an element to have an active tooltip while not being painted (e.g.
4769            // via the `visible_on_hover` method). Since mouse listeners are not active in this
4770            // case, instead update the tooltip's visibility here.
4771            let is_visible =
4772                (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);
4773            if !is_visible {
4774                continue;
4775            }
4776
4777            self.with_absolute_element_offset(tooltip_bounds.origin, |window| {
4778                element.prepaint(window, cx)
4779            });
4780
4781            self.tooltip_bounds = Some(TooltipBounds {
4782                id: tooltip_request.id,
4783                bounds: tooltip_bounds,
4784            });
4785            return Some(element);
4786        }
4787        None
4788    }
4789
4790    fn prepaint_deferred_draws(&mut self, cx: &mut App) {
4791        assert_eq!(self.element_id_stack.len(), 0);
4792
4793        // Process deferred draws in multiple rounds to support nesting.
4794        // Each round processes all current deferred draws, which may push new ones.
4795        //
4796        // The draws are processed in place rather than being moved out of
4797        // `next_frame.deferred_draws`: `prepaint_index` snapshots that vector's
4798        // length, so any prepaint range recorded during a round (view caches,
4799        // nested deferred draws) must index the same vector `reuse_prepaint`
4800        // slices on the next frame. Moving the draws out and re-appending them
4801        // shifts the indices of nested draws, causing reused subtrees to graft
4802        // the wrong deferred draws and panic in the dispatch tree.
4803        let mut round_start = 0;
4804        let mut depth = 0;
4805        loop {
4806            let round_end = self.next_frame.deferred_draws.len();
4807            if round_start == round_end {
4808                break;
4809            }
4810            // Limit maximum nesting depth to prevent infinite loops.
4811            assert!(depth < 10, "Exceeded maximum (10) deferred depth");
4812            depth += 1;
4813
4814            // Sort this round by priority.
4815            let mut traversal_order = (round_start..round_end).collect::<SmallVec<[usize; 8]>>();
4816            traversal_order.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
4817
4818            for deferred_draw_ix in traversal_order {
4819                let (
4820                    priority,
4821                    element,
4822                    parent_node,
4823                    current_view,
4824                    rem_size,
4825                    absolute_offset,
4826                    content_mask,
4827                    prepaint_range,
4828                ) = {
4829                    let deferred_draw = &mut self.next_frame.deferred_draws[deferred_draw_ix];
4830                    self.element_id_stack
4831                        .clone_from(&deferred_draw.element_id_stack);
4832                    self.text_style_stack
4833                        .clone_from(&deferred_draw.text_style_stack);
4834                    (
4835                        deferred_draw.priority,
4836                        deferred_draw.element.take(),
4837                        deferred_draw.parent_node,
4838                        deferred_draw.current_view,
4839                        deferred_draw.rem_size,
4840                        deferred_draw.absolute_offset,
4841                        deferred_draw.content_mask,
4842                        deferred_draw.prepaint_range.clone(),
4843                    )
4844                };
4845                self.next_frame.dispatch_tree.set_active_node(parent_node);
4846
4847                let prepaint_start = self.prepaint_index();
4848                if let Some(mut element) = element {
4849                    self.with_rendered_view(current_view, |window| {
4850                        window.with_content_mask(content_mask, |window| {
4851                            window.with_rem_size(Some(rem_size), |window| {
4852                                window.with_absolute_element_offset(absolute_offset, |window| {
4853                                    window.push_deferred_priority(priority);
4854                                    element.prepaint(window, cx);
4855                                    window.pop_deferred_priority();
4856                                });
4857                            });
4858                        });
4859                    });
4860                    self.next_frame.deferred_draws[deferred_draw_ix].element = Some(element);
4861                } else {
4862                    self.reuse_prepaint(prepaint_range);
4863                }
4864                let prepaint_end = self.prepaint_index();
4865                self.next_frame.deferred_draws[deferred_draw_ix].prepaint_range =
4866                    prepaint_start..prepaint_end;
4867            }
4868
4869            self.element_id_stack.clear();
4870            self.text_style_stack.clear();
4871            round_start = round_end;
4872        }
4873    }
4874
4875    fn paint_deferred_draws(&mut self, cx: &mut App) {
4876        assert_eq!(self.element_id_stack.len(), 0);
4877
4878        // Paint all deferred draws in priority order.
4879        // Since prepaint has already processed nested deferreds, we just paint them all.
4880        if self.next_frame.deferred_draws.len() == 0 {
4881            return;
4882        }
4883
4884        // Deferred draws are overlays (tooltips, popovers, drag images) and must sort above the
4885        // whole main scene. Raise the order floor so they do — this also keeps a deferred
4886        // backdrop's order from falling inside a content-filter order range left by the main scene.
4887        self.next_frame.scene.raise_order_floor();
4888
4889        let traversal_order = self.deferred_draw_traversal_order();
4890        let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
4891        for deferred_draw_ix in traversal_order {
4892            let mut deferred_draw = &mut deferred_draws[deferred_draw_ix];
4893            self.element_id_stack
4894                .clone_from(&deferred_draw.element_id_stack);
4895            self.next_frame
4896                .dispatch_tree
4897                .set_active_node(deferred_draw.parent_node);
4898
4899            let paint_start = self.paint_index();
4900            let content_mask = deferred_draw.content_mask;
4901            if let Some(element) = deferred_draw.element.as_mut() {
4902                self.with_rendered_view(deferred_draw.current_view, |window| {
4903                    window.with_content_mask(content_mask, |window| {
4904                        window.with_rem_size(Some(deferred_draw.rem_size), |window| {
4905                            element.paint(window, cx);
4906                        });
4907                    })
4908                })
4909            } else {
4910                self.reuse_paint(deferred_draw.paint_range.clone(), &mut None);
4911            }
4912            let paint_end = self.paint_index();
4913            deferred_draw.paint_range = paint_start..paint_end;
4914        }
4915        self.next_frame.deferred_draws = deferred_draws;
4916        self.element_id_stack.clear();
4917    }
4918
4919    fn deferred_draw_traversal_order(&mut self) -> SmallVec<[usize; 8]> {
4920        let deferred_count = self.next_frame.deferred_draws.len();
4921        let mut sorted_indices = (0..deferred_count).collect::<SmallVec<[_; 8]>>();
4922        sorted_indices.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
4923        sorted_indices
4924    }
4925
4926    pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {
4927        PrepaintStateIndex {
4928            hitboxes_index: self.next_frame.hitboxes.len(),
4929            tooltips_index: self.next_frame.tooltip_requests.len(),
4930            deferred_draws_index: self.next_frame.deferred_draws.len(),
4931            dispatch_tree_index: self.next_frame.dispatch_tree.len(),
4932            accessed_element_states_index: self.next_frame.accessed_element_states.len(),
4933            line_layout_index: self.text_system.layout_index(),
4934        }
4935    }
4936
4937    /// Marks the end of the element state the frame has used so far.
4938    pub(crate) fn element_states_mark(&self) -> usize {
4939        self.next_frame.accessed_element_states.len()
4940    }
4941
4942    /// The element state the frame used since `mark`.
4943    pub(crate) fn element_states_since(&self, mark: usize) -> Vec<(GlobalElementId, TypeId)> {
4944        self.next_frame.accessed_element_states[mark..].to_vec()
4945    }
4946
4947    /// Carries `states` into the next frame, as if this frame had used them.
4948    pub(crate) fn keep_element_states(&mut self, states: &[(GlobalElementId, TypeId)]) {
4949        self.next_frame
4950            .accessed_element_states
4951            .extend_from_slice(states);
4952    }
4953
4954    pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {
4955        let destination = self.prepaint_index();
4956        self.rebase_nested_views(
4957            range.start.accessed_element_states_index..range.end.accessed_element_states_index,
4958            |state, frame| state.rebase_prepaint(&range, &destination, frame),
4959        );
4960        self.next_frame.hitboxes.extend(
4961            self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
4962                .iter()
4963                .cloned(),
4964        );
4965        self.next_frame.tooltip_requests.extend(
4966            self.rendered_frame.tooltip_requests
4967                [range.start.tooltips_index..range.end.tooltips_index]
4968                .iter_mut()
4969                .map(|request| request.take()),
4970        );
4971        self.next_frame.accessed_element_states.extend(
4972            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
4973                ..range.end.accessed_element_states_index]
4974                .iter()
4975                .map(|(id, type_id)| (id.clone(), *type_id)),
4976        );
4977        self.text_system
4978            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
4979
4980        let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(
4981            range.start.dispatch_tree_index..range.end.dispatch_tree_index,
4982            &mut self.rendered_frame.dispatch_tree,
4983            self.focus,
4984        );
4985
4986        if reused_subtree.contains_focus() {
4987            self.next_frame.focus = self.focus;
4988        }
4989
4990        self.next_frame.deferred_draws.extend(
4991            self.rendered_frame.deferred_draws
4992                [range.start.deferred_draws_index..range.end.deferred_draws_index]
4993                .iter()
4994                .map(|deferred_draw| DeferredDraw {
4995                    current_view: deferred_draw.current_view,
4996                    parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
4997                    element_id_stack: deferred_draw.element_id_stack.clone(),
4998                    text_style_stack: deferred_draw.text_style_stack.clone(),
4999                    content_mask: deferred_draw.content_mask,
5000                    rem_size: deferred_draw.rem_size,
5001                    priority: deferred_draw.priority,
5002                    element: None,
5003                    absolute_offset: deferred_draw.absolute_offset,
5004                    prepaint_range: deferred_draw.prepaint_range.clone(),
5005                    paint_range: deferred_draw.paint_range.clone(),
5006                }),
5007        );
5008    }
5009
5010    pub(crate) fn paint_index(&self) -> PaintIndex {
5011        PaintIndex {
5012            scene_index: self.next_frame.scene.len(),
5013            #[cfg(any(test, feature = "test-support"))]
5014            debug_bounds_index: self.next_frame.debug_bounds_records.len(),
5015            mouse_listeners_index: self.next_frame.mouse_listeners.len(),
5016            pointer_observers_index: self.next_frame.pointer_observers.len(),
5017            input_handlers_index: self.next_frame.input_handlers.len(),
5018            cursor_styles_index: self.next_frame.cursor_styles.len(),
5019            accessed_element_states_index: self.next_frame.accessed_element_states.len(),
5020            tab_handle_index: self.next_frame.tab_stops.paint_index(),
5021            line_layout_index: self.text_system.layout_index(),
5022        }
5023    }
5024
5025    pub(crate) fn reuse_paint(
5026        &mut self,
5027        range: Range<PaintIndex>,
5028        summary: &mut Option<crate::scene::ReplaySummary>,
5029    ) {
5030        let destination = self.paint_index();
5031        self.rebase_nested_views(
5032            range.start.accessed_element_states_index..range.end.accessed_element_states_index,
5033            |state, frame| state.rebase_paint(&range, &destination, frame),
5034        );
5035        // Cached elements still exist in the frame even when their paint methods don't run.
5036        #[cfg(any(test, feature = "test-support"))]
5037        for (selector, bounds) in &self.rendered_frame.debug_bounds_records
5038            [range.start.debug_bounds_index..range.end.debug_bounds_index]
5039        {
5040            self.next_frame
5041                .record_debug_bounds(selector.clone(), *bounds);
5042        }
5043        Rc::make_mut(&mut self.next_frame.pointer_observers).extend(
5044            self.rendered_frame.pointer_observers
5045                [range.start.pointer_observers_index..range.end.pointer_observers_index]
5046                .iter()
5047                .cloned(),
5048        );
5049        self.next_frame.cursor_styles.extend(
5050            self.rendered_frame.cursor_styles
5051                [range.start.cursor_styles_index..range.end.cursor_styles_index]
5052                .iter()
5053                .cloned(),
5054        );
5055        self.next_frame.input_handlers.extend(
5056            self.rendered_frame.input_handlers
5057                [range.start.input_handlers_index..range.end.input_handlers_index]
5058                .iter_mut()
5059                .map(|handler| handler.take()),
5060        );
5061        self.next_frame.mouse_listeners.extend(
5062            self.rendered_frame.mouse_listeners
5063                [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
5064                .iter_mut()
5065                .map(|listener| listener.take()),
5066        );
5067        self.next_frame.accessed_element_states.extend(
5068            self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
5069                ..range.end.accessed_element_states_index]
5070                .iter()
5071                .map(|(id, type_id)| (id.clone(), *type_id)),
5072        );
5073        self.next_frame.tab_stops.replay(
5074            &self.rendered_frame.tab_stops.insertion_history
5075                [range.start.tab_handle_index..range.end.tab_handle_index],
5076        );
5077
5078        self.text_system
5079            .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
5080        self.next_frame.scene.replay_with(
5081            range.start.scene_index..range.end.scene_index,
5082            &self.rendered_frame.scene,
5083            summary,
5084        );
5085    }
5086
5087    /// Keeps the output ranges of views nested in a replayed range pointing at where their output
5088    /// now lives, so each can still be reused on its own in a later frame.
5089    fn rebase_nested_views(
5090        &mut self,
5091        accessed: Range<usize>,
5092        mut rebase: impl FnMut(&mut crate::view::ViewState, u64),
5093    ) {
5094        let view_state = TypeId::of::<crate::view::ViewState>();
5095        let frame_number = self.frame_number;
5096        let frame = &mut self.rendered_frame;
5097        for (id, type_id) in &frame.accessed_element_states[accessed] {
5098            if *type_id != view_state {
5099                continue;
5100            }
5101            if let Some(Some(state)) = frame
5102                .element_states
5103                .get_mut(&(id.clone(), view_state))
5104                .and_then(|state| state.inner.downcast_mut::<Option<crate::view::ViewState>>())
5105            {
5106                rebase(state, frame_number);
5107            }
5108        }
5109    }
5110
5111    pub(crate) fn push_deferred_priority(&mut self, priority: usize) {
5112        self.deferred_priority_stack.push(priority);
5113    }
5114
5115    pub(crate) fn pop_deferred_priority(&mut self) {
5116        self.deferred_priority_stack
5117            .pop()
5118            .expect("deferred priority stack must have been pushed");
5119    }
5120
5121    pub(crate) fn deferred_priority(&self) -> Option<usize> {
5122        self.deferred_priority_stack.last().copied()
5123    }
5124
5125    #[cfg(any(test, feature = "test-support"))]
5126    pub(crate) fn record_debug_bounds(
5127        &mut self,
5128        selector: impl Into<String>,
5129        bounds: Bounds<Pixels>,
5130    ) {
5131        self.next_frame.record_debug_bounds(selector.into(), bounds);
5132    }
5133
5134    pub(crate) fn create_layout_island(&mut self) -> crate::taffy::LayoutIsland {
5135        self.layout_engine.as_mut().unwrap().create_island()
5136    }
5137
5138    /// Runs `f` with layout requests going into `island`, after clearing what it held.
5139    pub(crate) fn with_layout_island<R>(
5140        &mut self,
5141        island: crate::taffy::IslandId,
5142        f: impl FnOnce(&mut Self) -> R,
5143    ) -> R {
5144        self.layout_engine.as_mut().unwrap().begin_island(island);
5145        let result = f(self);
5146        self.layout_engine.as_mut().unwrap().end_island();
5147        result
5148    }
5149
5150    pub(crate) fn set_layout_island_root(
5151        &mut self,
5152        island: crate::taffy::IslandId,
5153        root: LayoutId,
5154    ) {
5155        self.layout_engine
5156            .as_mut()
5157            .unwrap()
5158            .set_island_root(island, root);
5159    }
5160
5161    /// Adds a node to the current island that stands for `island`'s root.
5162    pub(crate) fn request_layout_island(&mut self, island: crate::taffy::IslandId) -> LayoutId {
5163        self.layout_engine.as_mut().unwrap().request_island(island)
5164    }
5165
5166    pub(crate) fn anchor_layout_island(
5167        &mut self,
5168        island: crate::taffy::IslandId,
5169        anchor: LayoutId,
5170    ) {
5171        self.layout_engine
5172            .as_mut()
5173            .unwrap()
5174            .anchor_island(island, anchor);
5175    }
5176
5177    /// Lays out `island`'s root at `size`, where its anchor sits this frame.
5178    pub(crate) fn layout_island(
5179        &mut self,
5180        island: crate::taffy::IslandId,
5181        size: Size<Pixels>,
5182        cx: &mut App,
5183    ) {
5184        let mut layout_engine = self.layout_engine.take().unwrap();
5185        layout_engine.layout_island(island, size, self.measurement_direction, self, cx);
5186        self.layout_engine = Some(layout_engine);
5187    }
5188
5189    /// Runs `f` with `style` refined onto the current text style, and restores the previous style afterward.
5190    ///
5191    /// Text painted and measured inside `f` uses the refined style. Pass `None` to run `f` with
5192    /// the current style unchanged. Use [`Window::text_style`] to read the combined style.
5193    /// Call it during request layout, prepaint or paint.
5194    pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
5195    where
5196        F: FnOnce(&mut Self) -> R,
5197    {
5198        self.invalidator.debug_assert_paint_or_prepaint();
5199        if let Some(style) = style {
5200            self.text_style_stack.push(style);
5201            let result = f(self);
5202            self.text_style_stack.pop();
5203            result
5204        } else {
5205            f(self)
5206        }
5207    }
5208
5209    /// Sets the cursor shown while the pointer is over `hitbox`.
5210    ///
5211    /// The style applies only while `hitbox` is hovered. Call it during paint. Set it
5212    /// on a hitbox you inserted during prepaint. Use [`Window::set_window_cursor_style`]
5213    /// to set the cursor for the whole window.
5214    pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
5215        self.invalidator.debug_assert_paint();
5216        self.next_frame
5217            .cursor_styles
5218            .push(CursorStyleRequest::Hitbox {
5219                id: hitbox.id,
5220                style: CursorStyleSource::Fixed(style),
5221            });
5222    }
5223
5224    /// Resolves this hitbox's cursor from window coordinates on pointer input.
5225    /// Return `None` to use the next cursor request. Cached paints retain the resolver.
5226    pub fn set_cursor_style_with(
5227        &mut self,
5228        hitbox: &Hitbox,
5229        resolve: impl Fn(Point<Pixels>) -> Option<CursorStyle> + 'static,
5230    ) {
5231        self.invalidator.debug_assert_paint();
5232        self.next_frame
5233            .cursor_styles
5234            .push(CursorStyleRequest::Hitbox {
5235                id: hitbox.id,
5236                style: CursorStyleSource::Position(Rc::new(resolve)),
5237            });
5238    }
5239
5240    /// Sets the cursor for the whole window, overriding any cursor set with [`Window::set_cursor_style`].
5241    ///
5242    /// Call it during paint.
5243    pub fn set_window_cursor_style(&mut self, style: CursorStyle) {
5244        self.invalidator.debug_assert_paint();
5245        self.next_frame
5246            .cursor_styles
5247            .push(CursorStyleRequest::Window(CursorStyleSource::Fixed(style)));
5248    }
5249
5250    /// Resolves a window-wide cursor from pointer position.
5251    /// Return `None` to defer to hitbox cursor requests.
5252    pub fn set_window_cursor_style_with(
5253        &mut self,
5254        resolve: impl Fn(Point<Pixels>) -> Option<CursorStyle> + 'static,
5255    ) {
5256        self.invalidator.debug_assert_paint();
5257        self.next_frame
5258            .cursor_styles
5259            .push(CursorStyleRequest::Window(CursorStyleSource::Position(
5260                Rc::new(resolve),
5261            )));
5262    }
5263
5264    /// Shows `tooltip` for the upcoming frame and returns its [`TooltipId`].
5265    ///
5266    /// Call it during prepaint. GPUI draws the tooltip above the window's content. Use
5267    /// [`TooltipId::is_hovered`] to check whether the mouse is over the tooltip.
5268    pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
5269        self.invalidator.debug_assert_prepaint();
5270        let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));
5271        self.next_frame
5272            .tooltip_requests
5273            .push(Some(TooltipRequest { id, tooltip }));
5274        id
5275    }
5276
5277    /// Runs `f` with `mask` intersected with the current content mask.
5278    ///
5279    /// Painting and hit-testing inside `f` are clipped to the result, and the previous mask
5280    /// is restored when `f` returns. Passing `None` leaves the mask unchanged. Call it during
5281    /// prepaint or paint.
5282    // This function is called in a highly recursive manner in editor
5283    // prepainting, make sure its inlined to reduce the stack burden
5284    #[inline]
5285    pub fn with_content_mask<R>(
5286        &mut self,
5287        mask: Option<ContentMask<Pixels>>,
5288        f: impl FnOnce(&mut Self) -> R,
5289    ) -> R {
5290        self.invalidator.debug_assert_paint_or_prepaint();
5291        if let Some(mask) = mask {
5292            let mask = mask.intersect(&self.content_mask());
5293            self.content_mask_stack.push(mask);
5294            let result = f(self);
5295            self.content_mask_stack.pop();
5296            result
5297        } else {
5298            f(self)
5299        }
5300    }
5301
5302    /// Runs `f` with `offset` added to the current element offset, then restores it.
5303    ///
5304    /// Bounds that elements compute inside `f` are shifted by `offset`, which is how scroll
5305    /// containers move their children. Call it during prepaint.
5306    pub fn with_element_offset<R>(
5307        &mut self,
5308        offset: Point<Pixels>,
5309        f: impl FnOnce(&mut Self) -> R,
5310    ) -> R {
5311        self.invalidator.debug_assert_prepaint();
5312
5313        if offset.is_zero() {
5314            return f(self);
5315        };
5316
5317        let abs_offset = self.element_offset() + offset;
5318        self.with_absolute_element_offset(abs_offset, f)
5319    }
5320
5321    pub(crate) fn with_style_transition_containing_bounds<R>(
5322        &mut self,
5323        bounds: Bounds<Pixels>,
5324        f: impl FnOnce(&mut Self) -> R,
5325    ) -> R {
5326        self.invalidator.debug_assert_prepaint();
5327        let previous_bounds = self.style_transition_containing_bounds.replace(bounds);
5328        let result = f(self);
5329        self.style_transition_containing_bounds = previous_bounds;
5330        result
5331    }
5332
5333    pub(crate) fn style_transition_containing_bounds(&self) -> Option<Bounds<Pixels>> {
5334        self.style_transition_containing_bounds
5335    }
5336
5337    /// Runs `f` with the element offset set to `offset`, ignoring the current offset.
5338    ///
5339    /// Use it to place an element at a fixed position, such as a drag preview that follows the
5340    /// pointer. The previous offset is restored when `f` returns. Call it during prepaint.
5341    pub fn with_absolute_element_offset<R>(
5342        &mut self,
5343        offset: Point<Pixels>,
5344        f: impl FnOnce(&mut Self) -> R,
5345    ) -> R {
5346        self.invalidator.debug_assert_prepaint();
5347        self.element_offset_stack.push(offset);
5348        let result = f(self);
5349        self.element_offset_stack.pop();
5350        result
5351    }
5352
5353    pub(crate) fn with_element_opacity<R>(
5354        &mut self,
5355        opacity: Option<f32>,
5356        paint: impl FnOnce(&mut Self) -> R,
5357    ) -> R {
5358        self.invalidator.debug_assert_paint();
5359        let opacity = opacity.unwrap_or(1.0).clamp(0.0, 1.0);
5360
5361        if opacity == 1.0 {
5362            return paint(self);
5363        }
5364
5365        // The existing targets cover the viewport, preserving shadows and visible overflow.
5366        // Child paint operations already carry their clipping and edge fades.
5367        let bounds = self.cover_bounds(Bounds::new(Point::default(), self.viewport_size()));
5368        let boundary = FilterBoundary {
5369            order: 0,
5370            bounds,
5371            content_mask: ContentMask {
5372                bounds,
5373                fade_out: Edges::default(),
5374            },
5375            corner_radii: Corners::default(),
5376            corner_smoothing: 0.0,
5377            filters: SmallVec::new(),
5378            opacity,
5379            is_start: true,
5380        };
5381
5382        self.with_filter_boundary(boundary, paint)
5383    }
5384
5385    fn with_filter_boundary<R>(
5386        &mut self,
5387        boundary: FilterBoundary,
5388        paint: impl FnOnce(&mut Self) -> R,
5389    ) -> R {
5390        self.next_frame.scene.insert_primitive(boundary.clone());
5391        let result = paint(self);
5392        self.next_frame.scene.insert_primitive(FilterBoundary {
5393            is_start: false,
5394            ..boundary
5395        });
5396
5397        result
5398    }
5399
5400    /// Runs `f` during prepaint, and discards its hitboxes, tooltips and other frame data if it returns `Err`.
5401    ///
5402    /// Use it to prepaint children, check the result, and try again. A successful `f` keeps
5403    /// everything it registered. The autoscroll support in [`crate::List`] uses this method.
5404    /// Call it during prepaint.
5405    ///
5406    /// # Errors
5407    ///
5408    /// Returns the `Err` value from `f`. Nothing from the failed attempt remains in the frame.
5409    pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {
5410        self.invalidator.debug_assert_prepaint();
5411        let index = self.prepaint_index();
5412        let result = f(self);
5413        if result.is_err() {
5414            self.next_frame.hitboxes.truncate(index.hitboxes_index);
5415            self.next_frame
5416                .tooltip_requests
5417                .truncate(index.tooltips_index);
5418            self.next_frame
5419                .deferred_draws
5420                .truncate(index.deferred_draws_index);
5421            self.next_frame
5422                .dispatch_tree
5423                .truncate(index.dispatch_tree_index);
5424            self.next_frame
5425                .accessed_element_states
5426                .truncate(index.accessed_element_states_index);
5427            self.text_system.truncate_layouts(index.line_layout_index);
5428        }
5429        result
5430    }
5431
5432    /// Asks the scroll containers around the current element to scroll `bounds` into view.
5433    ///
5434    /// Call it from [`Element::prepaint`](crate::Element::prepaint). Scroll containers such as [`crate::List`] read the request
5435    /// with [`Window::take_autoscroll`], scroll, and prepaint their children again. Call it during prepaint.
5436    pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {
5437        self.invalidator.debug_assert_prepaint();
5438        self.requested_autoscroll = Some(bounds);
5439    }
5440
5441    /// Returns and clears the autoscroll request made with [`Window::request_autoscroll`], if any.
5442    ///
5443    /// Scroll containers call it during prepaint to implement autoscroll. Call it during prepaint.
5444    pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {
5445        self.invalidator.debug_assert_prepaint();
5446        self.requested_autoscroll.take()
5447    }
5448
5449    /// Returns the loaded asset, or `None` while it is still loading.
5450    ///
5451    /// The first call starts loading `source`. When loading finishes, the current view is
5452    /// notified and redrawn, and later calls return `Some`. Concurrent calls share one load.
5453    /// Call it during render or paint. See [`Window::get_asset`] for a version that doesn't
5454    /// redraw the view.
5455    pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
5456        cx.asset_entry::<A>(source).use_by(self.current_view())
5457    }
5458
5459    /// Returns the loaded asset if it is ready, or starts loading it and returns `None`.
5460    ///
5461    /// Unlike [`Window::use_asset`], this doesn't redraw the view when loading finishes. Use it
5462    /// when a later redraw from some other cause will pick up the result. Concurrent calls share
5463    /// one load.
5464    pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
5465        cx.fetch_asset::<A>(source)
5466    }
5467    /// Returns the offset that the current element's position is shifted by, in logical pixels.
5468    ///
5469    /// Scroll containers set it with [`Window::with_element_offset`]. Call it during prepaint.
5470    pub fn element_offset(&self) -> Point<Pixels> {
5471        self.invalidator.debug_assert_prepaint();
5472        self.element_offset_stack
5473            .last()
5474            .copied()
5475            .unwrap_or_default()
5476    }
5477
5478    /// Returns the content mask in effect, which is the window's bounds unless a parent has clipped it.
5479    ///
5480    /// Call it during prepaint or paint. See [`Window::with_content_mask`].
5481    pub fn content_mask(&self) -> ContentMask<Pixels> {
5482        self.invalidator.debug_assert_paint_or_prepaint();
5483        self.content_mask_stack
5484            .last()
5485            .cloned()
5486            .unwrap_or_else(|| ContentMask {
5487                bounds: Bounds {
5488                    origin: Point::default(),
5489                    size: self.viewport_size,
5490                },
5491                ..Default::default()
5492            })
5493    }
5494
5495    /// Runs `f` with `element_id` pushed onto the id path, so child ids are unique only within it.
5496    ///
5497    /// Use it inside a custom element to give each group of children its own namespace. For
5498    /// example, a table can namespace each row's cells by the row's id.
5499    pub fn with_element_namespace<R>(
5500        &mut self,
5501        element_id: impl Into<ElementId>,
5502        f: impl FnOnce(&mut Self) -> R,
5503    ) -> R {
5504        self.element_id_stack.push(element_id.into());
5505        let result = f(self);
5506        self.element_id_stack.pop();
5507        result
5508    }
5509
5510    /// Returns an entity that persists across frames for as long as `key` keeps being rendered.
5511    ///
5512    /// The first time `key` is used, `init` creates the entity. On later frames the same entity is
5513    /// returned. GPUI redraws the current view whenever this entity is notified, so the view
5514    /// reflects changes to it. The state is dropped when the element isn't rendered in a frame.
5515    ///
5516    /// Use a different `key` for each element when several share a parent, such as list rows, and
5517    /// use a stable key such as a database id. Call it during `Render::render`, `RenderOnce::render`,
5518    /// or the drawing functions of `Element`. For the same state without a key, see [`Window::use_state`].
5519    ///
5520    /// # Examples
5521    ///
5522    /// ```
5523    /// # use gpui::{Context, Entity, TestApp, Window, div, prelude::*};
5524    /// # use std::{cell::RefCell, rc::Rc};
5525    /// # struct Root {
5526    /// #     values: Rc<RefCell<Vec<usize>>>,
5527    /// #     counter: Rc<RefCell<Option<Entity<usize>>>>,
5528    /// #     counter_ids: Rc<RefCell<Vec<gpui::EntityId>>>,
5529    /// # }
5530    /// # impl Render for Root {
5531    /// #     fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
5532    /// #         let count = window.use_keyed_state("count", cx, |_, _| 0_usize);
5533    /// #         *self.counter.borrow_mut() = Some(count.clone());
5534    /// #         self.counter_ids.borrow_mut().push(count.entity_id());
5535    /// #         self.values.borrow_mut().push(*count.read(cx));
5536    /// #         div()
5537    /// #     }
5538    /// # }
5539    /// # let values = Rc::new(RefCell::new(Vec::new()));
5540    /// # let counter_slot = Rc::new(RefCell::new(None));
5541    /// # let counter_ids = Rc::new(RefCell::new(Vec::new()));
5542    /// # let mut app = TestApp::new();
5543    /// # let mut window = app.open_window(|_, _| Root {
5544    /// #     values: values.clone(),
5545    /// #     counter: counter_slot.clone(),
5546    /// #     counter_ids: counter_ids.clone(),
5547    /// # });
5548    /// # window.draw();
5549    /// assert_eq!(values.borrow().last(), Some(&0));
5550    /// let counter = counter_slot.borrow().as_ref().unwrap().clone();
5551    /// app.update(|cx| {
5552    ///     counter.update(cx, |count, cx| {
5553    ///         *count = 1;
5554    ///         cx.notify();
5555    ///     });
5556    /// });
5557    /// window.draw();
5558    ///
5559    /// assert_eq!(values.borrow().last(), Some(&1));
5560    /// assert!(counter_ids.borrow().iter().all(|id| *id == counter.entity_id()));
5561    /// # drop(counter);
5562    /// # drop(counter_slot.borrow_mut().take());
5563    /// ```
5564    pub fn use_keyed_state<S: 'static>(
5565        &mut self,
5566        key: impl Into<ElementId>,
5567        cx: &mut App,
5568        init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
5569    ) -> Entity<S> {
5570        let current_view = self.current_view();
5571        self.with_global_id(key.into(), |global_id, window| {
5572            window.with_element_state(global_id, |state: Option<Entity<S>>, window| {
5573                if let Some(state) = state {
5574                    (state.clone(), state)
5575                } else {
5576                    let new_state = cx.new(|cx| init(window, cx));
5577                    Self::observe_keyed_state(&new_state, current_view, cx);
5578                    (new_state.clone(), new_state)
5579                }
5580            })
5581        })
5582    }
5583
5584    /// Returns state that persists across frames, identified by the call site of this method.
5585    ///
5586    /// This is [`Window::use_keyed_state`] with a key made from the caller's source location, so
5587    /// each call site in your code gets its own state. Inside a loop, every iteration shares one
5588    /// key, so use `use_keyed_state` with an id for each item instead.
5589    #[track_caller]
5590    pub fn use_state<S: 'static>(
5591        &mut self,
5592        cx: &mut App,
5593        init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
5594    ) -> Entity<S> {
5595        self.use_keyed_state(
5596            ElementId::CodeLocation(*core::panic::Location::caller()),
5597            cx,
5598            init,
5599        )
5600    }
5601
5602    /// Passes the state stored for `global_id` to `f`, and stores the state `f` returns.
5603    ///
5604    /// `f` receives `None` the first time, or after the element wasn't rendered in the previous frame.
5605    /// The state is found by `global_id` and its type `S`, so each type has its own state for the same
5606    /// element. Call it during prepaint or paint, or during `Render::render` and the element drawing methods.
5607    ///
5608    /// # Panics
5609    ///
5610    /// Panics if the state stored for `global_id` has a different type than `S`. A nested call for
5611    /// the same id and type doesn't see the state that `f` is updating. Use
5612    /// [`Window::use_keyed_state`] for ordinary state that needs no type juggling.
5613    pub fn with_element_state<S, R>(
5614        &mut self,
5615        global_id: &GlobalElementId,
5616        f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
5617    ) -> R
5618    where
5619        S: 'static,
5620    {
5621        self.invalidator.debug_assert_paint_or_prepaint();
5622
5623        let (key, state) = self.take_element_state(global_id, TypeId::of::<S>());
5624
5625        if let Some(any) = state {
5626            let ElementStateBox {
5627                inner,
5628                #[cfg(debug_assertions)]
5629                type_name,
5630            } = any;
5631            // Using the extra inner option to avoid needing to reallocate a new box.
5632            let mut state_box = inner
5633                .downcast::<Option<S>>()
5634                .map_err(|_| {
5635                    #[cfg(debug_assertions)]
5636                    {
5637                        anyhow::anyhow!(
5638                            "invalid element state type for id, requested {:?}, actual: {:?}",
5639                            std::any::type_name::<S>(),
5640                            type_name
5641                        )
5642                    }
5643
5644                    #[cfg(not(debug_assertions))]
5645                    {
5646                        anyhow::anyhow!(
5647                            "invalid element state type for id, requested {:?}",
5648                            std::any::type_name::<S>(),
5649                        )
5650                    }
5651                })
5652                .unwrap();
5653
5654            let state = state_box.take().expect(
5655                "reentrant call to with_element_state for the same state type and element id",
5656            );
5657            let (result, state) = f(Some(state), self);
5658            state_box.replace(state);
5659            self.insert_element_state(
5660                key,
5661                ElementStateBox {
5662                    inner: state_box,
5663                    #[cfg(debug_assertions)]
5664                    type_name,
5665                },
5666            );
5667            result
5668        } else {
5669            let (result, state) = f(None, self);
5670            self.insert_element_state(
5671                key,
5672                ElementStateBox {
5673                    inner: Box::new(Some(state)),
5674                    #[cfg(debug_assertions)]
5675                    type_name: std::any::type_name::<S>(),
5676                },
5677            );
5678            result
5679        }
5680    }
5681
5682    /// Like [`Window::with_element_state`], but the element may not have an id.
5683    ///
5684    /// When `global_id` is `None`, `f` receives `None` for the outer option, which means no id was
5685    /// provided. The inner `Option` is `None` the first time the state is used. When `global_id` is
5686    /// `Some`, `f` must return `Some` state; when it is `None`, `f` must return `None`, since there is
5687    /// nothing to store it under. Prefer `with_element_state` when the element always
5688    /// has an id. Call it during prepaint or paint.
5689    pub fn with_optional_element_state<S, R>(
5690        &mut self,
5691        global_id: Option<&GlobalElementId>,
5692        f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
5693    ) -> R
5694    where
5695        S: 'static,
5696    {
5697        self.invalidator.debug_assert_paint_or_prepaint();
5698
5699        if let Some(global_id) = global_id {
5700            self.with_element_state(global_id, |state, cx| {
5701                let (result, state) = f(Some(state), cx);
5702                let state =
5703                    state.expect("you must return some state when you pass some element id");
5704                (result, state)
5705            })
5706        } else {
5707            let (result, state) = f(None, self);
5708            debug_assert!(
5709                state.is_none(),
5710                "you must not return an element state when passing None for the global id"
5711            );
5712            result
5713        }
5714    }
5715
5716    /// Creates a transition whose state persists across frames, identified by the call site.
5717    ///
5718    /// Like [`Window::use_state`], each call site gets its own state, and every iteration of a loop
5719    /// shares one. Use [`use_keyed_transition`](Self::use_keyed_transition) with a key for each item
5720    /// instead.
5721    #[track_caller]
5722    pub fn use_transition<T: Lerp + Clone + PartialEq + 'static>(
5723        &mut self,
5724        cx: &mut App,
5725        motion: impl Into<Motion>,
5726        init: impl Fn(&mut Window, &mut Context<TransitionState<T>>) -> T,
5727    ) -> Transition<T> {
5728        let motion = motion.into();
5729        let state = self.use_state(cx, |window, cx| {
5730            TransitionState::new(init(window, cx), motion.clone())
5731        });
5732
5733        Transition::new(state, motion)
5734    }
5735
5736    /// Creates a new keyed transition with persistent state.
5737    ///
5738    /// The state for this transition is associated with the provided key and will
5739    /// persist across renders as long as the key remains the same. This is the
5740    /// recommended method for most use cases where you want smooth, continuous
5741    /// animations.
5742    ///
5743    /// This method should only be called during `Render::render`, `RenderOnce::render`, or the drawing functions of `Element`.
5744    pub fn use_keyed_transition<T: Lerp + Clone + PartialEq + 'static>(
5745        &mut self,
5746        key: impl Into<ElementId>,
5747        cx: &mut App,
5748        motion: impl Into<Motion>,
5749        init: impl Fn(&mut Window, &mut Context<TransitionState<T>>) -> T,
5750    ) -> Transition<T> {
5751        let motion = motion.into();
5752        let state = self.use_keyed_state(key, cx, |window, cx| {
5753            TransitionState::new(init(window, cx), motion.clone())
5754        });
5755
5756        Transition::new(state, motion)
5757    }
5758
5759    /// Runs `f` as a tab group, so tab navigation visits its focusable elements together.
5760    ///
5761    /// Tab stops registered inside `f` are ordered by `index` relative to other groups. Pass `None`
5762    /// to run `f` without creating a group.
5763    #[inline]
5764    pub fn with_tab_group<R>(&mut self, index: Option<isize>, f: impl FnOnce(&mut Self) -> R) -> R {
5765        if let Some(index) = index {
5766            self.next_frame.tab_stops.begin_group(index);
5767            let result = f(self);
5768            self.next_frame.tab_stops.end_group();
5769            result
5770        } else {
5771            f(self)
5772        }
5773    }
5774
5775    /// Schedules `element` to be drawn on top of the current tree, after the tree is painted.
5776    ///
5777    /// The element is laid out and painted at `absolute_offset` in window coordinates. Deferred
5778    /// elements with a higher `priority` are drawn later, so they appear above the others.
5779    /// Popovers, menus and tooltips use it to escape the clipping of their parents. Pass a
5780    /// `content_mask` to clip the element during both prepaint and paint, or `None` for no clip.
5781    ///
5782    /// Call it during prepaint.
5783    ///
5784    /// # Panics
5785    ///
5786    /// Panics in debug builds if called outside prepaint. Panics if there is no active node in the
5787    /// dispatch tree, which happens when no element is being prepainted.
5788    pub fn defer_draw(
5789        &mut self,
5790        element: AnyElement,
5791        absolute_offset: Point<Pixels>,
5792        priority: usize,
5793        content_mask: Option<ContentMask<Pixels>>,
5794    ) {
5795        self.invalidator.debug_assert_prepaint();
5796        let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();
5797        self.next_frame.deferred_draws.push(DeferredDraw {
5798            current_view: self.current_view(),
5799            parent_node,
5800            element_id_stack: self.element_id_stack.clone(),
5801            text_style_stack: self.text_style_stack.clone(),
5802            content_mask,
5803            rem_size: self.rem_size(),
5804            priority,
5805            element: Some(element),
5806            absolute_offset,
5807            prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),
5808            paint_range: PaintIndex::default()..PaintIndex::default(),
5809        });
5810    }
5811
5812    /// Runs `f` inside a new layer clipped to `bounds`, which groups the primitives `f` paints.
5813    ///
5814    /// A layer is a batch of primitives with the same draw order and no overlaps. Layers
5815    /// are a performance hint that lets the renderer batch the work. Painting outside `bounds`
5816    /// is clipped to the intersection of `bounds` and the content mask. If that intersection is
5817    /// empty, `f` runs with no layer. Call it during paint.
5818    pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
5819        self.invalidator.debug_assert_paint();
5820
5821        let content_mask = self.content_mask();
5822        let clipped_bounds = bounds.intersect(&content_mask.bounds);
5823        if !clipped_bounds.is_empty() {
5824            self.next_frame
5825                .scene
5826                .push_layer(self.cover_bounds(clipped_bounds));
5827        }
5828
5829        let result = f(self);
5830
5831        if !clipped_bounds.is_empty() {
5832            self.next_frame.scene.pop_layer();
5833        }
5834
5835        result
5836    }
5837
5838    /// Paints the outer shadows in `shadows` behind an element of `bounds` and `corner_radii`.
5839    ///
5840    /// Paint these before the element's background, so the shadow sits under it. Inset shadows
5841    /// are skipped; paint those with [`Window::paint_inset_shadows`] after the background.
5842    /// Call it during paint.
5843    pub fn paint_drop_shadows(
5844        &mut self,
5845        bounds: Bounds<Pixels>,
5846        corner_radii: Corners<Pixels>,
5847        corner_smoothing: f32,
5848        shadows: &[BoxShadow],
5849    ) {
5850        self.paint_shadows(bounds, corner_radii, corner_smoothing, shadows, false);
5851    }
5852
5853    /// Paints the inset shadows in `shadows` inside an element of `bounds` and `corner_radii`.
5854    ///
5855    /// Paint these after the element's background, so the shadow sits on top of the fill. Outer
5856    /// shadows are skipped; paint those with [`Window::paint_drop_shadows`] before the background.
5857    /// Call it during paint.
5858    pub fn paint_inset_shadows(
5859        &mut self,
5860        bounds: Bounds<Pixels>,
5861        corner_radii: Corners<Pixels>,
5862        corner_smoothing: f32,
5863        shadows: &[BoxShadow],
5864    ) {
5865        self.paint_shadows(bounds, corner_radii, corner_smoothing, shadows, true);
5866    }
5867
5868    fn paint_shadows(
5869        &mut self,
5870        bounds: Bounds<Pixels>,
5871        corner_radii: Corners<Pixels>,
5872        corner_smoothing: f32,
5873        shadows: &[BoxShadow],
5874        inset: bool,
5875    ) {
5876        self.invalidator.debug_assert_paint();
5877
5878        let scale_factor = self.scale_factor();
5879        let content_mask = self.snapped_content_mask();
5880        let element_bounds = self.cover_bounds(bounds);
5881        let element_corner_radii = corner_radii.scale(scale_factor);
5882        let corner_smoothing = corner_smoothing.clamp(0.0, 1.0);
5883
5884        for shadow in shadows.iter().filter(|shadow| shadow.inset == inset) {
5885            let spread = if inset {
5886                -shadow.spread_radius
5887            } else {
5888                shadow.spread_radius
5889            };
5890
5891            let shadow_bounds = (bounds + shadow.offset).dilate(spread);
5892
5893            let shadow_radii = if inset {
5894                // Large inset spreads must not produce negative radii in the shader.
5895                corner_radii.map(|radius| (*radius - shadow.spread_radius).max(Pixels::ZERO))
5896            } else {
5897                corner_radii
5898            };
5899
5900            self.next_frame.scene.insert_primitive(Shadow {
5901                order: 0,
5902                blur_radius: shadow.blur_radius.scale(scale_factor),
5903                bounds: self.cover_bounds(shadow_bounds),
5904                content_mask,
5905                corner_radii: shadow_radii.scale(scale_factor),
5906                color: shadow.color,
5907                element_bounds,
5908                element_corner_radii,
5909                inset: inset.into(),
5910                corner_smoothing,
5911            });
5912        }
5913    }
5914
5915    /// Paint a backdrop filter into the scene for the next frame at the current z-index. The
5916    /// renderer blurs the content already painted behind `bounds` and composites the result
5917    /// into the rounded rectangle described by `bounds` and `corner_radii` — the CSS
5918    /// `backdrop-filter` effect (frosted glass). Typically the element then paints a translucent
5919    /// background quad on top so its color tints the blurred backdrop.
5920    /// `corner_smoothing` ranges from circular corners at `0.0` to maximum smoothing at `1.0`.
5921    ///
5922    /// Does nothing when `filters` produce no visible blur.
5923    ///
5924    /// This method should only be called as part of the paint phase of element drawing.
5925    pub fn paint_backdrop_filter(
5926        &mut self,
5927        bounds: Bounds<Pixels>,
5928        corner_radii: Corners<Pixels>,
5929        corner_smoothing: f32,
5930        filters: &[Filter],
5931    ) {
5932        self.invalidator.debug_assert_paint();
5933
5934        let scale_factor = self.scale_factor();
5935        let filters: SmallVec<[ScaledFilter; 4]> = filters
5936            .iter()
5937            .filter(|filter| !filter.is_identity())
5938            .map(|filter| filter.scale(scale_factor))
5939            .collect();
5940        if filters.is_empty() {
5941            return;
5942        }
5943
5944        self.next_frame.scene.insert_primitive(BackdropFilter {
5945            order: 0,
5946            bounds: self.snap_bounds(bounds),
5947            content_mask: self.snapped_content_mask(),
5948            corner_radii: corner_radii.scale(scale_factor),
5949            corner_smoothing: corner_smoothing.clamp(0.0, 1.0),
5950            filters,
5951            opacity: 1.0,
5952        });
5953    }
5954
5955    /// Isolate the painting performed by `f` into a content-filter group: the renderer renders
5956    /// everything `f` paints into an offscreen target, blurs it as a single layer, and
5957    /// composites the result back into the rounded rectangle described by `bounds` and
5958    /// `corner_radii` — the CSS `filter` effect (e.g. blurring an element and its children).
5959    /// `corner_smoothing` ranges from circular corners at `0.0` to maximum smoothing at `1.0`.
5960    ///
5961    /// When `filters` produce no visible blur this simply runs `f` with no offscreen
5962    /// indirection.
5963    ///
5964    /// This method should only be called as part of the paint phase of element drawing.
5965    pub fn with_filter_layer<R>(
5966        &mut self,
5967        bounds: Bounds<Pixels>,
5968        corner_radii: Corners<Pixels>,
5969        corner_smoothing: f32,
5970        filters: &[Filter],
5971        f: impl FnOnce(&mut Self) -> R,
5972    ) -> R {
5973        self.invalidator.debug_assert_paint();
5974
5975        let scale_factor = self.scale_factor();
5976        let filters: SmallVec<[ScaledFilter; 4]> = filters
5977            .iter()
5978            .filter(|filter| !filter.is_identity())
5979            .map(|filter| filter.scale(scale_factor))
5980            .collect();
5981        if filters.is_empty() {
5982            return f(self);
5983        }
5984
5985        let boundary = FilterBoundary {
5986            order: 0,
5987            bounds: self.snap_bounds(bounds),
5988            content_mask: self.snapped_content_mask(),
5989            corner_radii: corner_radii.scale(scale_factor),
5990            corner_smoothing: corner_smoothing.clamp(0.0, 1.0),
5991            filters,
5992            opacity: 1.0,
5993            is_start: true,
5994        };
5995
5996        self.with_filter_boundary(boundary, f)
5997    }
5998
5999    fn largest_border_interior(quad: &Quad) -> Bounds<ScaledPixels> {
6000        let radii = &quad.corner_radii;
6001        let widths = &quad.border_widths;
6002        let reach_factor = 1.0 + quad.corner_smoothing;
6003        let edge_reaches = Edges {
6004            top: radii.top_left.max(radii.top_right) * reach_factor,
6005            right: radii.top_right.max(radii.bottom_right) * reach_factor,
6006            bottom: radii.bottom_left.max(radii.bottom_right) * reach_factor,
6007            left: radii.top_left.max(radii.bottom_left) * reach_factor,
6008        };
6009
6010        let antialias_inset = point(ScaledPixels(1.0), ScaledPixels(1.0));
6011        let inset_bounds = |top_left_inset, bottom_right_inset| {
6012            Bounds::from_corners(
6013                quad.bounds.origin + top_left_inset + antialias_inset,
6014                quad.bounds.bottom_right() - bottom_right_inset - antialias_inset,
6015            )
6016        };
6017
6018        // Rounded corners need only be excluded on one axis. Either candidate
6019        // is empty of border pixels, so use the larger interior.
6020        let horizontal_band = inset_bounds(
6021            point(widths.left, widths.top.max(edge_reaches.top)),
6022            point(widths.right, widths.bottom.max(edge_reaches.bottom)),
6023        );
6024        let vertical_band = inset_bounds(
6025            point(widths.left.max(edge_reaches.left), widths.top),
6026            point(widths.right.max(edge_reaches.right), widths.bottom),
6027        );
6028
6029        let area = |bounds: &Bounds<ScaledPixels>| {
6030            bounds.size.width.0.max(0.) * bounds.size.height.0.max(0.)
6031        };
6032        if area(&horizontal_band) >= area(&vertical_band) {
6033            horizontal_band
6034        } else {
6035            vertical_band
6036        }
6037    }
6038
6039    /// Paint one or more quads into the scene for the next frame at the current stacking context.
6040    /// Quads are colored rectangular regions with an optional background, border, and corner radius.
6041    /// Use [`PaintQuad::new`] and its builder methods to construct the quad.
6042    /// `quad.corner_smoothing` ranges from circular corners at `0.0` to maximum smoothing at `1.0`.
6043    ///
6044    /// This method should only be called as part of the paint phase of element drawing.
6045    ///
6046    /// Note that the `quad.corner_radii` are allowed to exceed the bounds, creating sharp corners
6047    /// where the circular arcs meet. This will not display well when combined with dashed borders.
6048    /// Use `Corners::clamp_radii_for_quad_size` if the radii should fit within the bounds.
6049    pub fn paint_quad(&mut self, quad: PaintQuad) {
6050        self.invalidator.debug_assert_paint();
6051
6052        let snapped_bounds = self.snap_bounds(quad.bounds);
6053        let snapped_border_widths = self.snap_border_widths(quad.border_widths);
6054        let quad = Quad {
6055            order: 0,
6056            bounds: snapped_bounds,
6057            content_mask: self.snapped_content_mask(),
6058            background: quad.background,
6059            border_color: quad.border_color,
6060            corner_radii: quad.corner_radii.scale(self.scale_factor()),
6061            border_widths: snapped_border_widths,
6062            border_style: quad.border_style,
6063            border_dashed_length: quad.border_dashed_length,
6064            border_dashed_gap: quad.border_dashed_gap,
6065            corner_smoothing: quad.corner_smoothing.clamp(0.0, 1.0),
6066            padding: 0,
6067        };
6068
6069        if !quad.background.is_transparent() {
6070            self.next_frame.scene.insert_primitive(quad);
6071            return;
6072        }
6073
6074        // Splitting a border-only quad around its empty interior avoids shading
6075        // every transparent pixel inside large outlines.
6076        let outer_bounds = quad.bounds;
6077        let inner_bounds = Self::largest_border_interior(&quad);
6078
6079        if inner_bounds.is_empty() {
6080            self.next_frame.scene.insert_primitive(quad);
6081            return;
6082        }
6083
6084        let strips = [
6085            // Top
6086            Bounds::from_corners(
6087                outer_bounds.origin,
6088                point(outer_bounds.right(), inner_bounds.top()),
6089            ),
6090            // Bottom
6091            Bounds::from_corners(
6092                point(outer_bounds.left(), inner_bounds.bottom()),
6093                outer_bounds.bottom_right(),
6094            ),
6095            // Left
6096            Bounds::from_corners(
6097                point(outer_bounds.left(), inner_bounds.top()),
6098                inner_bounds.bottom_left(),
6099            ),
6100            // Right
6101            Bounds::from_corners(
6102                inner_bounds.top_right(),
6103                point(outer_bounds.right(), inner_bounds.bottom()),
6104            ),
6105        ];
6106
6107        for strip in strips {
6108            let content_mask_bounds = quad.content_mask.bounds.intersect(&strip);
6109            if !content_mask_bounds.is_empty() {
6110                self.next_frame.scene.insert_primitive(Quad {
6111                    content_mask: ContentMask {
6112                        bounds: content_mask_bounds,
6113                        ..Default::default()
6114                    },
6115                    ..quad
6116                });
6117            }
6118        }
6119    }
6120
6121    /// Paints `path` filled with `color`, at the current z-index.
6122    ///
6123    /// The path's coordinates are in logical pixels within the window, and the content mask and
6124    /// element opacity apply to it. Call it during paint.
6125    pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {
6126        self.invalidator.debug_assert_paint();
6127
6128        let scale_factor = self.scale_factor();
6129        let content_mask = self.content_mask();
6130        path.content_mask = content_mask;
6131        let color: Background = color.into();
6132        path.color = color;
6133        self.next_frame
6134            .scene
6135            .insert_primitive(path.scale(scale_factor));
6136    }
6137
6138    /// Paints an underline of `width` starting at `origin`, using `style`.
6139    ///
6140    /// The underline is drawn at the current z-index, and the content mask and element opacity
6141    /// apply to it. `style.wavy` draws a wave instead of a straight line. Call it during paint.
6142    pub fn paint_underline(
6143        &mut self,
6144        origin: Point<Pixels>,
6145        width: Pixels,
6146        style: &UnderlineStyle,
6147    ) {
6148        self.invalidator.debug_assert_paint();
6149
6150        let scale_factor = self.scale_factor();
6151        let thickness = self.snap_stroke(style.thickness);
6152        let height = if style.wavy {
6153            ScaledPixels(thickness.0 * 3.)
6154        } else {
6155            thickness
6156        };
6157        let bounds = Bounds {
6158            origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
6159            size: size(self.snap_stroke(width), height),
6160        };
6161        let content_mask = self.snapped_content_mask();
6162
6163        self.next_frame.scene.insert_primitive(Underline {
6164            order: 0,
6165            padding: 0,
6166            bounds,
6167            clip_bounds: content_mask.bounds,
6168            content_mask,
6169            color: style.color.unwrap_or_default().into(),
6170            thickness,
6171            wavy: style.wavy.into(),
6172        });
6173    }
6174
6175    /// Paints a strikethrough line of `width` starting at `origin`, using `style`.
6176    ///
6177    /// The line is drawn at the current z-index, and the content mask and element opacity apply
6178    /// to it. Call it during paint.
6179    pub fn paint_strikethrough(
6180        &mut self,
6181        origin: Point<Pixels>,
6182        width: Pixels,
6183        style: &StrikethroughStyle,
6184    ) {
6185        self.invalidator.debug_assert_paint();
6186
6187        let scale_factor = self.scale_factor();
6188        let height = style.thickness;
6189        let bounds = Bounds {
6190            origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
6191            size: size(self.snap_stroke(width), self.snap_stroke(height)),
6192        };
6193        let content_mask = self.snapped_content_mask();
6194        let thickness = self.snap_stroke(style.thickness);
6195
6196        self.next_frame.scene.insert_primitive(Underline {
6197            order: 0,
6198            padding: 0,
6199            bounds,
6200            clip_bounds: content_mask.bounds,
6201            content_mask,
6202            thickness,
6203            color: style.color.unwrap_or_default().into(),
6204            wavy: false.into(),
6205        });
6206    }
6207
6208    /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
6209    ///
6210    /// The y component of the origin is the baseline of the glyph.
6211    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
6212    /// [`ShapedText::paint`](crate::ShapedText::paint) methods in the [`TextSystem`](crate::TextSystem).
6213    /// This method is only useful if you need to paint a single glyph that has already been shaped.
6214    ///
6215    /// This method should only be called as part of the paint phase of element drawing.
6216    pub fn paint_glyph(
6217        &mut self,
6218        origin: Point<Pixels>,
6219        font_id: FontId,
6220        glyph_id: GlyphId,
6221        font_size: Pixels,
6222        color: Hsla,
6223    ) -> Result<()> {
6224        self.invalidator.debug_assert_paint();
6225
6226        let scale_factor = self.scale_factor();
6227        let glyph_origin = origin.scale(scale_factor);
6228
6229        let (integer_origin, subpixel_variant) = quantize_glyph_origin(glyph_origin);
6230        let requested_mode = if self.should_use_subpixel_rendering(font_id, font_size) {
6231            GlyphRenderMode::Subpixel
6232        } else {
6233            GlyphRenderMode::Grayscale
6234        };
6235        let raster_style =
6236            self.text_system()
6237                .prepare_raster_style(font_id, glyph_id, color, requested_mode);
6238        let params = RenderGlyphParams {
6239            font_id,
6240            glyph_id,
6241            font_size,
6242            subpixel_variant,
6243            scale_factor,
6244            raster_style,
6245        };
6246
6247        self.paint_glyph_from_atlas(integer_origin, params, color)
6248    }
6249
6250    fn paint_glyph_from_atlas(
6251        &mut self,
6252        integer_origin: Point<ScaledPixels>,
6253        params: RenderGlyphParams,
6254        mask_color: Hsla,
6255    ) -> Result<()> {
6256        let text_system = self.text_system().clone();
6257        let entry = self
6258            .sprite_atlas
6259            .get_or_insert_glyph_with(&params, &mut || text_system.rasterize_glyph(&params))?;
6260        let Some(tile) = entry.tile else {
6261            return Ok(());
6262        };
6263
6264        debug_assert_eq!(entry.bounds.size, tile.bounds.size.map(Into::into));
6265        let bounds = Bounds {
6266            origin: integer_origin + entry.bounds.origin.map(Into::into),
6267            size: tile.bounds.size.map(Into::into),
6268        };
6269        let content_mask = self.snapped_content_mask();
6270
6271        match entry.format {
6272            RasterizedGlyphFormat::AlphaMask => {
6273                self.next_frame.scene.insert_primitive(MonochromeSprite {
6274                    order: 0,
6275                    padding: 0,
6276                    bounds,
6277                    content_mask,
6278                    color: mask_color.into(),
6279                    tile,
6280                    transformation: TransformationMatrix::unit(),
6281                });
6282            }
6283            RasterizedGlyphFormat::BgraSubpixelMask => {
6284                self.next_frame.scene.insert_primitive(SubpixelSprite {
6285                    order: 0,
6286                    padding: 0,
6287                    bounds,
6288                    content_mask,
6289                    color: mask_color.into(),
6290                    tile,
6291                    transformation: TransformationMatrix::unit(),
6292                });
6293            }
6294            RasterizedGlyphFormat::BgraColor => {
6295                self.next_frame.scene.insert_primitive(PolychromeSprite {
6296                    order: 0,
6297                    grayscale: false.into(),
6298                    corner_smoothing: 0.0,
6299                    bounds,
6300                    corner_radii: Default::default(),
6301                    content_mask,
6302                    tile,
6303                    opacity: 1.0,
6304                });
6305            }
6306        }
6307        Ok(())
6308    }
6309
6310    fn should_use_subpixel_rendering(&self, font_id: FontId, font_size: Pixels) -> bool {
6311        if self.next_frame.scene.is_in_filter_group() {
6312            return false;
6313        }
6314
6315        if self
6316            .platform_window
6317            .background_appearance()
6318            .is_transparent()
6319        {
6320            return false;
6321        }
6322
6323        if !self.platform_window.is_subpixel_rendering_supported() {
6324            return false;
6325        }
6326
6327        let mode = match self.text_rendering_mode.get() {
6328            TextRenderingMode::PlatformDefault => self
6329                .text_system()
6330                .recommended_rendering_mode(font_id, font_size),
6331            mode => mode,
6332        };
6333
6334        mode == TextRenderingMode::Subpixel
6335    }
6336
6337    /// Paints an emoji glyph into the scene for the next frame at the current z-index.
6338    ///
6339    /// The y component of the origin is the baseline of the glyph.
6340    /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
6341    /// [`ShapedText::paint`](crate::ShapedText::paint) methods in the [`TextSystem`](crate::TextSystem).
6342    /// This method is only useful if you need to paint a single emoji that has already been shaped.
6343    ///
6344    /// This method should only be called as part of the paint phase of element drawing.
6345    pub fn paint_emoji(
6346        &mut self,
6347        origin: Point<Pixels>,
6348        font_id: FontId,
6349        glyph_id: GlyphId,
6350        font_size: Pixels,
6351    ) -> Result<()> {
6352        self.paint_emoji_with_color(origin, font_id, glyph_id, font_size, white())
6353    }
6354
6355    /// Paints a color glyph with an application foreground for `currentColor` layers.
6356    pub fn paint_emoji_with_color(
6357        &mut self,
6358        origin: Point<Pixels>,
6359        font_id: FontId,
6360        glyph_id: GlyphId,
6361        font_size: Pixels,
6362        color: Hsla,
6363    ) -> Result<()> {
6364        self.invalidator.debug_assert_paint();
6365
6366        let scale_factor = self.scale_factor();
6367        let glyph_origin = origin.scale(scale_factor);
6368        let (integer_origin, subpixel_variant) = quantize_color_glyph_origin(glyph_origin);
6369        let raster_style = self.text_system().prepare_raster_style(
6370            font_id,
6371            glyph_id,
6372            color,
6373            GlyphRenderMode::Color,
6374        );
6375        let params = RenderGlyphParams {
6376            font_id,
6377            glyph_id,
6378            font_size,
6379            subpixel_variant,
6380            scale_factor,
6381            raster_style,
6382        };
6383
6384        self.paint_glyph_from_atlas(integer_origin, params, color)
6385    }
6386
6387    /// Paints a monochrome SVG into `bounds`, tinted with `color`.
6388    ///
6389    /// `path` identifies the SVG for caching. If `data` is `Some`, those bytes are the SVG; if
6390    /// it is `None`, the SVG is loaded from `path` through the app's asset source. `transformation`
6391    /// rotates or flips the SVG within `bounds`. Returns an error if the SVG can't be rendered.
6392    /// Call it during paint.
6393    pub fn paint_svg(
6394        &mut self,
6395        bounds: Bounds<Pixels>,
6396        path: SharedString,
6397        mut data: Option<&[u8]>,
6398        transformation: TransformationMatrix,
6399        color: Hsla,
6400        cx: &App,
6401    ) -> Result<()> {
6402        self.invalidator.debug_assert_paint();
6403
6404        let bounds = self.snap_bounds(bounds);
6405
6406        let params = RenderSvgParams {
6407            path,
6408            size: bounds.size.map(|pixels| {
6409                DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)
6410            }),
6411        };
6412
6413        let Some(tile) =
6414            self.sprite_atlas
6415                .get_or_insert_with(params.clone().into(), &mut || {
6416                    let Some((size, bytes)) = cx.svg_renderer.render_alpha_mask(&params, data)?
6417                    else {
6418                        return Ok(None);
6419                    };
6420                    Ok(Some((size, Cow::Owned(bytes))))
6421                })?
6422        else {
6423            return Ok(());
6424        };
6425        let content_mask = self.snapped_content_mask();
6426        let svg_bounds = Bounds {
6427            origin: bounds.center()
6428                - Point::new(
6429                    ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
6430                    ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
6431                ),
6432            size: tile
6433                .bounds
6434                .size
6435                .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)),
6436        };
6437        let final_bounds = svg_bounds
6438            .map_origin(|value| ScaledPixels(round_half_toward_zero(value.0)))
6439            .map_size(|size| size.ceil());
6440
6441        self.next_frame.scene.insert_primitive(MonochromeSprite {
6442            order: 0,
6443            padding: 0,
6444            bounds: final_bounds,
6445            content_mask,
6446            color: color.into(),
6447            tile,
6448            transformation,
6449        });
6450
6451        Ok(())
6452    }
6453
6454    /// Paints `data` into `bounds`, scaled to fit `image_bounds`.
6455    ///
6456    /// The visible region is `bounds.intersect(&image_bounds)`, and `corner_radii` round the
6457    /// corners of `bounds`. `frame_index` selects a frame of an animated image, and `grayscale`
6458    /// paints the image in grayscale. Returns an error if the image can't be uploaded to the
6459    /// renderer. Call it during paint.
6460    pub fn paint_image(
6461        &mut self,
6462        bounds: Bounds<Pixels>,
6463        image_bounds: Bounds<Pixels>,
6464        corner_radii: Corners<Pixels>,
6465        corner_smoothing: f32,
6466        data: Arc<RenderImage>,
6467        frame_index: usize,
6468        grayscale: bool,
6469    ) -> Result<()> {
6470        self.invalidator.debug_assert_paint();
6471
6472        let visible_bounds = bounds.intersect(&image_bounds);
6473        if visible_bounds.size.width <= Pixels::ZERO || visible_bounds.size.height <= Pixels::ZERO {
6474            return Ok(());
6475        }
6476        if image_bounds.size.width <= Pixels::ZERO || image_bounds.size.height <= Pixels::ZERO {
6477            return Ok(());
6478        }
6479
6480        let params = RenderImageParams {
6481            image_id: data.id,
6482            frame_index,
6483        };
6484
6485        let tile = self
6486            .sprite_atlas
6487            .get_or_insert_with(params.into(), &mut || {
6488                Ok(Some((
6489                    data.size(frame_index),
6490                    Cow::Borrowed(
6491                        data.as_bytes(frame_index)
6492                            .expect("It's the caller's job to pass a valid frame index"),
6493                    ),
6494                )))
6495            })?
6496            .expect("Callback above only returns Some");
6497
6498        let visible_bounds_snapped = self.snap_bounds(visible_bounds);
6499
6500        let sub_tile = if visible_bounds == image_bounds {
6501            tile
6502        } else {
6503            let x_offset_ratio =
6504                (visible_bounds.origin.x - image_bounds.origin.x) / image_bounds.size.width;
6505            let y_offset_ratio =
6506                (visible_bounds.origin.y - image_bounds.origin.y) / image_bounds.size.height;
6507            let width_ratio = visible_bounds.size.width / image_bounds.size.width;
6508            let height_ratio = visible_bounds.size.height / image_bounds.size.height;
6509
6510            let tile_origin_x = tile.bounds.origin.x.0;
6511            let tile_origin_y = tile.bounds.origin.y.0;
6512            let tile_width = tile.bounds.size.width.0;
6513            let tile_height = tile.bounds.size.height.0;
6514
6515            let sub_origin_x = tile_origin_x + (x_offset_ratio * tile_width as f32).round() as i32;
6516            let sub_origin_y = tile_origin_y + (y_offset_ratio * tile_height as f32).round() as i32;
6517            let sub_width = (width_ratio * tile_width as f32).round() as i32;
6518            let sub_height = (height_ratio * tile_height as f32).round() as i32;
6519
6520            let max_x = tile_origin_x + tile_width;
6521            let max_y = tile_origin_y + tile_height;
6522
6523            let clamped_origin_x = sub_origin_x.clamp(tile_origin_x, max_x);
6524            let clamped_origin_y = sub_origin_y.clamp(tile_origin_y, max_y);
6525            let clamped_width = sub_width.min(max_x - clamped_origin_x).max(0);
6526            let clamped_height = sub_height.min(max_y - clamped_origin_y).max(0);
6527
6528            AtlasTile {
6529                bounds: Bounds {
6530                    origin: point(
6531                        DevicePixels(clamped_origin_x),
6532                        DevicePixels(clamped_origin_y),
6533                    ),
6534                    size: size(DevicePixels(clamped_width), DevicePixels(clamped_height)),
6535                },
6536                ..tile
6537            }
6538        };
6539
6540        let content_mask = self.snapped_content_mask();
6541        let corner_radii = corner_radii
6542            .clamp_radii_for_quad_size(visible_bounds.size)
6543            .scale(self.scale_factor());
6544
6545        self.next_frame.scene.insert_primitive(PolychromeSprite {
6546            order: 0,
6547            grayscale: grayscale.into(),
6548            corner_smoothing: corner_smoothing.clamp(0.0, 1.0),
6549            bounds: visible_bounds_snapped,
6550            content_mask,
6551            corner_radii,
6552            tile: sub_tile,
6553            opacity: 1.0,
6554        });
6555        Ok(())
6556    }
6557
6558    /// Paints a platform surface, such as a video frame, into `bounds`.
6559    ///
6560    /// `source` identifies the surface. The content mask applies. Call it during paint.
6561    pub fn paint_surface(
6562        &mut self,
6563        bounds: Bounds<Pixels>,
6564        source: impl Into<crate::SurfaceSource>,
6565    ) {
6566        self.invalidator.debug_assert_paint();
6567
6568        let bounds = self.snap_bounds(bounds);
6569        let content_mask = self.snapped_content_mask();
6570        self.next_frame.scene.insert_primitive(PaintSurface {
6571            order: 0,
6572            bounds,
6573            content_mask,
6574            source: source.into(),
6575        });
6576    }
6577
6578    /// Removes every frame of `data` from the renderer's texture atlas, freeing its GPU memory.
6579    ///
6580    /// Call it when an image is no longer needed. The image is uploaded again the next time it is
6581    /// painted. The `Result` is always `Ok`, and it exists so the method can be extended later.
6582    pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {
6583        for frame_index in 0..data.frame_count() {
6584            let params = RenderImageParams {
6585                image_id: data.id,
6586                frame_index,
6587            };
6588
6589            self.sprite_atlas.remove(&params.clone().into());
6590        }
6591
6592        Ok(())
6593    }
6594
6595    /// Returns whether every frame of `data` is already uploaded to the texture atlas.
6596    ///
6597    /// Use it to check whether painting `data` would need an upload. Images with no frames
6598    /// return `false`.
6599    #[cfg(any(test, feature = "test-support"))]
6600    pub fn has_image_atlas_entry(&self, data: &RenderImage) -> bool {
6601        data.frame_count() > 0
6602            && (0..data.frame_count()).all(|frame_index| {
6603                self.sprite_atlas.contains(
6604                    &RenderImageParams {
6605                        image_id: data.id,
6606                        frame_index,
6607                    }
6608                    .into(),
6609                )
6610            })
6611    }
6612
6613    /// Adds a layout node with `style` and `children` to the frame, and returns its id.
6614    ///
6615    /// Call it from [`Element::request_layout`](crate::Element::request_layout) (or from a view's `render`, which runs during
6616    /// request layout). Pass the ids of the child nodes you created, and use the returned
6617    /// [`LayoutId`] to read the node's bounds later with [`Window::layout_bounds`]. Layout is
6618    /// computed once, after every node is requested, by the framework.
6619    ///
6620    /// Call it during request layout or prepaint.
6621    #[must_use]
6622    pub fn request_layout(
6623        &mut self,
6624        style: Style,
6625        children: impl IntoIterator<Item = LayoutId>,
6626        cx: &mut App,
6627    ) -> LayoutId {
6628        self.invalidator.debug_assert_prepaint();
6629
6630        cx.layout_id_buffer.clear();
6631        cx.layout_id_buffer.extend(children);
6632        let rem_size = self.rem_size();
6633        let scale_factor = self.scale_factor();
6634
6635        self.layout_engine.as_mut().unwrap().request_layout(
6636            style,
6637            rem_size,
6638            scale_factor,
6639            &cx.layout_id_buffer,
6640        )
6641    }
6642
6643    /// Adds a layout node whose size comes from `measure`, which runs during layout.
6644    ///
6645    /// Use it for content whose size depends on what it contains, such as text. `measure` receives
6646    /// the known dimensions (`None` where the size is not yet known), the available space on each
6647    /// axis, the window and the app, and returns the size the node should take. GPUI uses it for
6648    /// text measurement.
6649    ///
6650    /// Call it during request layout or prepaint.
6651    pub fn request_measured_layout<F>(&mut self, style: Style, measure: F) -> LayoutId
6652    where
6653        F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
6654            + 'static,
6655    {
6656        self.invalidator.debug_assert_prepaint();
6657
6658        let rem_size = self.rem_size();
6659        let scale_factor = self.scale_factor();
6660        self.layout_engine
6661            .as_mut()
6662            .unwrap()
6663            .request_measured_layout(style, rem_size, scale_factor, measure)
6664    }
6665
6666    /// [`Window::request_measured_layout`] for content whose size depends only on `key` and the
6667    /// space it gets. When the view renders again with an equal key at the same place, the node
6668    /// keeps its layout, and `measure` runs once, with the sizes of the last measurement.
6669    pub(crate) fn request_keyed_measured_layout<F>(
6670        &mut self,
6671        style: Style,
6672        key: impl crate::taffy::MeasureKey,
6673        measure: F,
6674    ) -> LayoutId
6675    where
6676        F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
6677            + 'static,
6678    {
6679        self.invalidator.debug_assert_prepaint();
6680
6681        let rem_size = self.rem_size();
6682        let scale_factor = self.scale_factor();
6683        self.layout_engine
6684            .as_mut()
6685            .unwrap()
6686            .request_keyed_measured_layout(
6687                style,
6688                rem_size,
6689                scale_factor,
6690                Some(Box::new(key)),
6691                measure,
6692            )
6693    }
6694
6695    /// Computes the layout of `layout_id` and its descendants within `available_space`.
6696    ///
6697    /// GPUI calls this for the root of each frame, before prepaint. After it runs, [`Window::layout_bounds`]
6698    /// returns the bounds of `layout_id` and of any of its descendants. Call it during prepaint.
6699    pub fn compute_layout(
6700        &mut self,
6701        layout_id: LayoutId,
6702        available_space: Size<AvailableSpace>,
6703        cx: &mut App,
6704    ) {
6705        self.invalidator.debug_assert_prepaint();
6706
6707        let mut layout_engine = self.layout_engine.take().unwrap();
6708        layout_engine.compute_layout(
6709            layout_id,
6710            available_space,
6711            self.measurement_direction,
6712            self,
6713            cx,
6714        );
6715        self.layout_engine = Some(layout_engine);
6716    }
6717
6718    /// Returns the bounds of a layout node, in window coordinates, after the element offset is applied.
6719    ///
6720    /// GPUI passes these bounds to [`Element::prepaint`](crate::Element::prepaint) for you, so you rarely need this method
6721    /// directly. It is valid during prepaint, after [`Window::compute_layout`] has run. The offset
6722    /// comes from [`Window::with_element_offset`], such as a scroll position.
6723    pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
6724        self.invalidator.debug_assert_prepaint();
6725
6726        let scale_factor = self.scale_factor();
6727        let mut bounds = self
6728            .layout_engine
6729            .as_mut()
6730            .unwrap()
6731            .layout_bounds(layout_id, scale_factor)
6732            .map(Into::into);
6733        let snapped_offset = self.pixel_snap_point(self.element_offset());
6734        bounds.origin += snapped_offset;
6735        // Both terms are device-pixel aligned, but adding their logical-pixel f32 values can
6736        // produce either adjacent representation of the same device coordinate. Snap the
6737        // combined origin back to its canonical representation before it feeds hitboxes.
6738        bounds.origin = self.pixel_snap_point(bounds.origin);
6739        bounds
6740    }
6741
6742    /// Returns the bounds of a layout node relative to its parent, snapped to device pixels.
6743    ///
6744    /// Unlike [`Window::layout_bounds`], this result doesn't depend on where the parent is in the
6745    /// window, so a child keeps the same sub-pixel position while its parent moves. Text-bearing
6746    /// elements use it so their glyphs don't shift as a parent scrolls. Call it during prepaint.
6747    pub fn parent_relative_layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
6748        self.invalidator.debug_assert_prepaint();
6749
6750        let scale_factor = self.scale_factor();
6751        let mut bounds = self
6752            .layout_engine
6753            .as_mut()
6754            .unwrap()
6755            .parent_relative_layout_bounds(layout_id, scale_factor);
6756        bounds.origin += self.pixel_snap_point(self.element_offset());
6757        bounds
6758    }
6759
6760    pub(crate) fn publish_inline_content(
6761        &mut self,
6762        node_id: LayoutId,
6763        content: crate::InlineContent,
6764    ) -> bool {
6765        let Some(layout_engine) = self.layout_engine.as_mut() else {
6766            return false;
6767        };
6768
6769        if let crate::InlineContent::Text { text, .. } = &content {
6770            layout_engine.set_direction_text(node_id, text.clone());
6771        }
6772
6773        layout_engine.set_inline_content(node_id, content);
6774        true
6775    }
6776
6777    pub(crate) fn set_layout_logical_children(&mut self, node_id: LayoutId, children: &[LayoutId]) {
6778        self.layout_engine
6779            .as_mut()
6780            .unwrap()
6781            .set_logical_children(node_id, children);
6782    }
6783
6784    pub(crate) fn set_layout_auto_direction_hint(
6785        &mut self,
6786        node_id: LayoutId,
6787        direction: Option<ResolvedDirection>,
6788    ) {
6789        self.layout_engine
6790            .as_mut()
6791            .unwrap()
6792            .set_auto_direction_hint(node_id, direction);
6793    }
6794
6795    pub(crate) fn layout_island_direction_contribution(
6796        &self,
6797        island: crate::taffy::IslandId,
6798    ) -> Option<ResolvedDirection> {
6799        self.layout_engine
6800            .as_ref()
6801            .unwrap()
6802            .island_direction_contribution(island)
6803    }
6804
6805    pub(crate) fn layout_direction_handle(
6806        &self,
6807        node_id: LayoutId,
6808    ) -> crate::taffy::LayoutDirectionHandle {
6809        self.layout_engine
6810            .as_ref()
6811            .unwrap()
6812            .direction_handle(node_id)
6813    }
6814
6815    pub(crate) fn layout_directionality(
6816        &self,
6817        node_id: LayoutId,
6818    ) -> (ResolvedDirection, UnicodeBidi) {
6819        self.layout_engine.as_ref().unwrap().directionality(node_id)
6820    }
6821
6822    pub(crate) fn with_layout_direction_context<R>(
6823        &mut self,
6824        node_id: LayoutId,
6825        f: impl FnOnce(&mut Self) -> R,
6826    ) -> R {
6827        let (direction, unicode_bidi) = self.layout_directionality(node_id);
6828        let previous_direction = std::mem::replace(&mut self.measurement_direction, direction);
6829        let previous_unicode_bidi =
6830            std::mem::replace(&mut self.measurement_unicode_bidi, unicode_bidi);
6831        let result = f(self);
6832        self.measurement_direction = previous_direction;
6833        self.measurement_unicode_bidi = previous_unicode_bidi;
6834        result
6835    }
6836
6837    /// Supplies source text used by `LayoutDirection::Auto` for a custom layout node.
6838    ///
6839    /// Built-in text elements register their content automatically. Call this during
6840    /// `request_layout` after obtaining the node's [`LayoutId`].
6841    pub fn set_layout_direction_text(&mut self, node_id: LayoutId, text: impl Into<SharedString>) {
6842        self.layout_engine
6843            .as_mut()
6844            .unwrap()
6845            .set_direction_text(node_id, text.into());
6846    }
6847
6848    pub(crate) fn inline_content(&self, node_id: LayoutId) -> Option<Arc<crate::InlineContent>> {
6849        self.layout_engine.as_ref()?.inline_content(node_id)
6850    }
6851
6852    /// Whether a node kept the layout it had in its view's previous render.
6853    pub(crate) fn layout_inherited(&self, node_id: LayoutId) -> bool {
6854        self.layout_engine
6855            .as_ref()
6856            .is_some_and(|layout_engine| layout_engine.inherited(node_id))
6857    }
6858
6859    pub(crate) fn layout_display_and_position(
6860        &self,
6861        node_id: LayoutId,
6862    ) -> Option<(crate::Display, crate::Position)> {
6863        self.layout_engine
6864            .as_ref()
6865            .map(|layout_engine| layout_engine.display_and_position(node_id))
6866    }
6867
6868    pub(crate) fn inline_fragments(&self, node_id: LayoutId) -> Option<Arc<[Bounds<Pixels>]>> {
6869        self.layout_engine
6870            .as_ref()?
6871            .inline_fragments(node_id)
6872            .map(|fragments| {
6873                let offset = self.pixel_snap_point(self.element_offset());
6874                if offset == Point::default() {
6875                    return fragments;
6876                }
6877
6878                fragments
6879                    .iter()
6880                    .map(|bounds| Bounds::new(bounds.origin + offset, bounds.size))
6881                    .collect()
6882            })
6883    }
6884
6885    pub(crate) fn place_inline(
6886        &mut self,
6887        node_id: LayoutId,
6888        mut bounds: Bounds<Pixels>,
6889        fragments: Option<Vec<Bounds<Pixels>>>,
6890    ) -> bool {
6891        if self.layout_engine.is_none() {
6892            return false;
6893        }
6894
6895        let offset = self.pixel_snap_point(self.element_offset());
6896        bounds.origin -= offset;
6897
6898        let scale = self.scale_factor();
6899        let Some(engine) = self.layout_engine.as_mut() else {
6900            return false;
6901        };
6902
6903        engine.place_inline(node_id, bounds, scale);
6904
6905        if let Some(mut fragments) = fragments {
6906            // A zero offset leaves fragment origins unchanged, so skip those writes.
6907            if offset != Point::default() {
6908                for fragment in &mut fragments {
6909                    fragment.origin -= offset;
6910                }
6911            }
6912
6913            engine.set_inline_fragments(node_id, fragments.into());
6914        }
6915
6916        true
6917    }
6918
6919    pub(crate) fn layout_vertical_align(
6920        &self,
6921        layout_id: LayoutId,
6922    ) -> Option<crate::VerticalAlign> {
6923        self.layout_engine
6924            .as_ref()
6925            .map(|layout_engine| layout_engine.vertical_align(layout_id))
6926    }
6927
6928    /// Inserts a hitbox covering `bounds` for the frame being prepainted, and returns it.
6929    ///
6930    /// The hitbox's content mask is the one active now, so a hitbox inside a scroll container
6931    /// doesn't receive input outside the container. Call it during prepaint. Keep the returned
6932    /// [`Hitbox`] for paint or for event handlers, where [`Hitbox::is_hovered`] tells you whether
6933    /// the pointer is over it.
6934    ///
6935    /// # Examples
6936    ///
6937    /// ```
6938    /// # use gpui::{Context, Hitbox, HitboxBehavior, IntoElement, Render, TestApp, Window, canvas, point, prelude::*, px};
6939    /// # use std::{cell::RefCell, rc::Rc};
6940    /// struct Hovered {
6941    ///     hitbox: Rc<RefCell<Option<Hitbox>>>,
6942    /// }
6943    ///
6944    /// impl Render for Hovered {
6945    ///     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
6946    ///         let slot = self.hitbox.clone();
6947    ///         canvas(
6948    ///             move |bounds, window, _| {
6949    ///                 *slot.borrow_mut() = Some(window.insert_hitbox(bounds, HitboxBehavior::Normal));
6950    ///             },
6951    ///             |_, _, _, _| {},
6952    ///         )
6953    ///         .size(px(100.))
6954    ///     }
6955    /// }
6956    /// # let hitbox = Rc::new(RefCell::new(None));
6957    /// # let mut app = TestApp::new();
6958    /// # let mut window = app.open_window(|_, _| Hovered { hitbox: hitbox.clone() });
6959    /// # window.draw();
6960    /// # window.simulate_mouse_move(point(px(10.), px(10.)));
6961    /// # window.update(|_, window, _| {
6962    /// #     assert!(hitbox.borrow().as_ref().unwrap().is_hovered(window));
6963    /// # });
6964    /// ```
6965    pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, behavior: HitboxBehavior) -> Hitbox {
6966        self.insert_hitbox_mut(bounds, behavior).clone()
6967    }
6968
6969    /// Like [`Window::insert_hitbox`], but returns a mutable reference so you can set the hitbox's
6970    /// [`tags`](Hitbox::tags) before the frame ends.
6971    ///
6972    /// The reference is into this frame's hitbox list, so it stays valid only until the next call
6973    /// that inserts a hitbox. Call it during prepaint.
6974    pub fn insert_hitbox_mut(
6975        &mut self,
6976        bounds: Bounds<Pixels>,
6977        behavior: HitboxBehavior,
6978    ) -> &mut Hitbox {
6979        self.invalidator.debug_assert_prepaint();
6980
6981        let content_mask = self.content_mask();
6982        let hitbox_id = self.next_hitbox_id;
6983        self.next_hitbox_id = self.next_hitbox_id.next();
6984        let hitbox = Hitbox {
6985            id: hitbox_id,
6986            bounds,
6987            content_mask,
6988            behavior,
6989            fragments: self.current_inline_fragments.clone(),
6990            tags: Vec::default(),
6991        };
6992
6993        self.next_frame.hitboxes.push_mut(hitbox)
6994    }
6995
6996    /// Registers `hitbox` as the platform control `area` of a custom title bar.
6997    ///
6998    /// The platform uses the hitbox to drag, maximize, minimize or close the window when the user
6999    /// interacts with it. Call it during paint, and see [`WindowControlArea`] for the areas.
7000    pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) {
7001        self.invalidator.debug_assert_paint();
7002        self.next_frame.window_control_hitboxes.push((area, hitbox));
7003    }
7004
7005    /// Sets the key context of the current element, which key bindings match against.
7006    ///
7007    /// A binding with a context such as `"Editor"` applies only when an element on the focus path has
7008    /// that context. Call it during paint. See [`InteractiveElement::key_context`](crate::InteractiveElement::key_context) for the usual way to set it.
7009    pub fn set_key_context(&mut self, context: KeyContext) {
7010        self.invalidator.debug_assert_paint();
7011        self.next_frame.dispatch_tree.set_key_context(context);
7012    }
7013
7014    /// Connects the current element to `focus_handle` for focus and key dispatch this frame.
7015    ///
7016    /// If the handle is focused, the frame keeps it focused. [`InteractiveElement::track_focus`](crate::InteractiveElement::track_focus)
7017    /// calls this for you. Call it during prepaint.
7018    pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {
7019        self.invalidator.debug_assert_prepaint();
7020        if focus_handle.is_focused(self) {
7021            self.next_frame.focus = Some(focus_handle.id);
7022        }
7023        self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);
7024    }
7025
7026    /// Sets the view that the current element belongs to, for view caching.
7027    ///
7028    /// GPUI sets this for each view it renders, so custom elements rarely need it. It exists for
7029    /// elements built outside a view. The method is expected to go away. Call it during prepaint.
7030    pub fn set_view_id(&mut self, view_id: EntityId) {
7031        self.invalidator.debug_assert_prepaint();
7032        self.next_frame.dispatch_tree.set_view_id(view_id);
7033    }
7034
7035    /// Returns the id of the view whose element is being rendered, prepainted or painted.
7036    ///
7037    /// Use it when a callback needs to notify the view being drawn, such as the callback
7038    /// that [`Window::use_asset`] schedules. Call it during prepaint or paint.
7039    ///
7040    /// # Panics
7041    ///
7042    /// Panics if no view is being rendered, such as in an event listener or outside a frame.
7043    /// Debug builds also panic when called outside prepaint and paint.
7044    pub fn current_view(&self) -> EntityId {
7045        self.invalidator.debug_assert_paint_or_prepaint();
7046        self.rendered_entity_stack.last().copied().unwrap()
7047    }
7048
7049    #[inline]
7050    pub(crate) fn with_rendered_view<R>(
7051        &mut self,
7052        id: EntityId,
7053        f: impl FnOnce(&mut Self) -> R,
7054    ) -> R {
7055        self.rendered_entity_stack.push(id);
7056        let result = f(self);
7057        self.rendered_entity_stack.pop();
7058        result
7059    }
7060
7061    /// Runs `f` with `image_cache` active, so images painted inside `f` load through it.
7062    ///
7063    /// Pass `None` to run `f` with the cache already in effect. The cache applies only while `f` runs.
7064    pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R
7065    where
7066        F: FnOnce(&mut Self) -> R,
7067    {
7068        if let Some(image_cache) = image_cache {
7069            self.image_cache_stack.push(image_cache);
7070            let result = f(self);
7071            self.image_cache_stack.pop();
7072            result
7073        } else {
7074            f(self)
7075        }
7076    }
7077
7078    /// Registers `input_handler` to receive text from the platform, if `focus_handle` is focused.
7079    ///
7080    /// Text input and IME composition go through this handler. It stays
7081    /// active until the next frame is painted, and it is ignored unless `focus_handle` has focus.
7082    /// Use [`ElementInputHandler`](crate::ElementInputHandler) to implement it for an element.
7083    /// Call it during paint.
7084    pub fn handle_input(
7085        &mut self,
7086        focus_handle: &FocusHandle,
7087        input_handler: impl InputHandler,
7088        cx: &App,
7089    ) {
7090        self.invalidator.debug_assert_paint();
7091
7092        if focus_handle.is_focused(self) {
7093            let cx = self.to_async(cx);
7094            self.next_frame.input_handlers.push(Some(
7095                PlatformInputHandler::new(cx, Box::new(input_handler)).with_focus(focus_handle.id),
7096            ));
7097        }
7098    }
7099
7100    /// Notifies native text services that the focused component's text changed.
7101    ///
7102    /// Text components should call this after application-driven edits, in addition
7103    /// to notifying GPUI to redraw. Unfocused or unregistered components are ignored.
7104    pub fn notify_text_input_changed(&self, focus_handle: &FocusHandle) {
7105        if self.focused_text_input == Some(focus_handle.id) && focus_handle.is_focused(self) {
7106            self.platform_window
7107                .text_input_state_changed(TextInputStateChange::ContentChanged);
7108        }
7109    }
7110
7111    /// Notifies native text services that the focused component's selection changed.
7112    ///
7113    /// Text components should call this after application-driven selection changes,
7114    /// in addition to notifying GPUI to redraw.
7115    pub fn notify_text_selection_changed(&self, focus_handle: &FocusHandle) {
7116        if self.focused_text_input == Some(focus_handle.id) && focus_handle.is_focused(self) {
7117            self.platform_window
7118                .text_input_state_changed(TextInputStateChange::SelectionChanged);
7119        }
7120    }
7121
7122    /// Forwards the focused input handler's [`TextInputConfiguration`] to the
7123    /// platform window when it differs from the last forwarded value. With no
7124    /// input handler the default configuration applies, so a field's
7125    /// preferences don't outlive its focus.
7126    fn apply_text_input_configuration(&mut self, cx: &mut App) {
7127        let configuration = match self.platform_window.take_input_handler() {
7128            Some(mut input_handler) => {
7129                let configuration = input_handler.text_input_configuration(self, cx);
7130                self.platform_window.set_input_handler(input_handler);
7131                configuration
7132            }
7133            None => TextInputConfiguration::default(),
7134        };
7135        if self.last_text_input_configuration.as_ref() != Some(&configuration) {
7136            self.platform_window
7137                .set_text_input_configuration(configuration.clone());
7138            self.last_text_input_configuration = Some(configuration);
7139        }
7140    }
7141
7142    /// Registers a listener for every mouse event of type `Event`, for the frame being painted.
7143    ///
7144    /// The listener runs for each event of that type, whether or not the pointer is over an
7145    /// element. `Event` is chosen by the type of the listener's first parameter, such as
7146    /// `MouseDownEvent`. The listener is called in both the capture and the bubble phase, and
7147    /// `phase` says which. Listeners are cleared when the next frame is painted, so register
7148    /// them on every paint. Most code should use the handlers on elements, such as
7149    /// `on_mouse_down`, instead. Call it during paint.
7150    ///
7151    /// # Examples
7152    ///
7153    /// ```
7154    /// # use gpui::{Context, IntoElement, MouseButton, MouseDownEvent, Render, TestApp, Window, canvas, point, prelude::*, px};
7155    /// # use std::{cell::Cell, rc::Rc};
7156    /// struct Root {
7157    ///     clicks: Rc<Cell<usize>>,
7158    /// }
7159    ///
7160    /// impl Render for Root {
7161    ///     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
7162    ///         let clicks = self.clicks.clone();
7163    ///         canvas(
7164    ///             |_, _, _| {},
7165    ///             move |_, _, window, _| {
7166    ///                 window.on_mouse_event(move |_: &MouseDownEvent, phase, _, _| {
7167    ///                     if phase.bubble() {
7168    ///                         clicks.set(clicks.get() + 1);
7169    ///                     }
7170    ///                 });
7171    ///             },
7172    ///         )
7173    ///         .size(px(100.))
7174    ///     }
7175    /// }
7176    /// # let clicks = Rc::new(Cell::new(0));
7177    /// # let mut app = TestApp::new();
7178    /// # let mut window = app.open_window(|_, _| Root { clicks: clicks.clone() });
7179    /// # window.draw();
7180    /// # window.simulate_mouse_down(point(px(5.), px(5.)), MouseButton::Left);
7181    /// # assert_eq!(clicks.get(), 1);
7182    /// ```
7183    pub fn on_mouse_event<Event: MouseEvent>(
7184        &mut self,
7185        mut listener: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
7186    ) {
7187        self.invalidator.debug_assert_paint();
7188
7189        self.next_frame.mouse_listeners.push(Some(Box::new(
7190            move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {
7191                if let Some(event) = event.downcast_ref() {
7192                    listener(event, phase, window, cx)
7193                }
7194            },
7195        )));
7196    }
7197
7198    // Observe completed hit tests independently of event propagation.
7199    pub(crate) fn on_pointer_change(
7200        &mut self,
7201        observer: impl Fn(PointerChange, &mut Window, &mut App) + 'static,
7202    ) {
7203        self.invalidator.debug_assert_paint();
7204        Rc::make_mut(&mut self.next_frame.pointer_observers).push(Rc::new(observer));
7205    }
7206
7207    fn notify_pointer_observers(&mut self, cause: PointerChangeCause, cx: &mut App) {
7208        let change = PointerChange {
7209            position: self.pointer_inside_window.then_some(self.mouse_position),
7210            cause,
7211        };
7212        // Snapshot observers before callbacks can redraw the frame.
7213        let observers = self.rendered_frame.pointer_observers.clone();
7214        let propagate_event = cx.propagate_event;
7215        let default_prevented = self.default_prevented;
7216        for observer in observers.iter() {
7217            observer(change, self, cx);
7218            // Observers must not change the event's dispatch state.
7219            cx.propagate_event = propagate_event;
7220            self.default_prevented = default_prevented;
7221        }
7222    }
7223
7224    /// Registers a listener for key events of type `Event` on the current element, for the frame being painted.
7225    ///
7226    /// `Event` is chosen by the type of the listener's first parameter, such as `KeyDownEvent`.
7227    /// Listeners are cleared when the next frame is painted, so register them on every paint.
7228    /// This is a low-level method. Prefer the handlers on elements, such as `on_key_down`, unless you
7229    /// need to register a listener yourself. Call it during paint.
7230    pub fn on_key_event<Event: KeyEvent>(
7231        &mut self,
7232        listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
7233    ) {
7234        self.invalidator.debug_assert_paint();
7235
7236        self.next_frame.dispatch_tree.on_key_event(Rc::new(
7237            move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {
7238                if let Some(event) = event.downcast_ref::<Event>() {
7239                    listener(event, phase, window, cx)
7240                }
7241            },
7242        ));
7243    }
7244
7245    /// Registers a listener for changes to the modifier keys, for the frame being painted.
7246    ///
7247    /// The listener runs when Shift, Control, Alt or Command goes down or up. Like the other
7248    /// listeners, it is cleared when the next frame is painted. Call it during paint.
7249    pub fn on_modifiers_changed(
7250        &mut self,
7251        listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
7252    ) {
7253        self.invalidator.debug_assert_paint();
7254
7255        self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(
7256            move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {
7257                listener(event, window, cx)
7258            },
7259        ));
7260    }
7261
7262    /// Calls `listener` when `handle`'s element, or one of its descendants, gains focus.
7263    ///
7264    /// It doesn't fire when focus moves between `handle`'s element and its descendants, because
7265    /// `handle` already had focus. The listener runs during the focus phase at the end of the frame.
7266    /// The returned [`Subscription`] keeps the listener active until it is dropped.
7267    /// Keep the subscription in the view that owns the element, or the listener stops firing.
7268    pub fn on_focus_in(
7269        &mut self,
7270        handle: &FocusHandle,
7271        cx: &mut App,
7272        mut listener: impl FnMut(&mut Window, &mut App) + 'static,
7273    ) -> Subscription {
7274        let focus_id = handle.id;
7275        let (subscription, activate) =
7276            self.new_focus_listener(Box::new(move |event, window, cx| {
7277                if event.is_focus_in(focus_id) {
7278                    listener(window, cx);
7279                }
7280                true
7281            }));
7282        cx.defer(move |_| activate());
7283        subscription
7284    }
7285
7286    /// Calls `listener` when `handle`'s element, or one of its descendants, loses focus.
7287    ///
7288    /// The listener gets a [`FocusOutEvent`] whose `blurred` field identifies the element that lost
7289    /// focus. The listener runs during the focus phase at the end of the frame. The returned
7290    /// [`Subscription`] keeps the listener active until it is dropped. [`Context::on_focus_out`]
7291    /// is the same for the view being rendered.
7292    pub fn on_focus_out(
7293        &mut self,
7294        handle: &FocusHandle,
7295        cx: &mut App,
7296        mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,
7297    ) -> Subscription {
7298        let focus_id = handle.id;
7299        let (subscription, activate) =
7300            self.new_focus_listener(Box::new(move |event, window, cx| {
7301                if let Some(blurred_id) = event.previous_focus_path.last().copied()
7302                    && event.is_focus_out(focus_id)
7303                {
7304                    let event = FocusOutEvent {
7305                        blurred: WeakFocusHandle {
7306                            id: blurred_id,
7307                            handles: Arc::downgrade(&cx.focus_handles),
7308                        },
7309                    };
7310                    listener(event, window, cx)
7311                }
7312                true
7313            }));
7314        cx.defer(move |_| activate());
7315        subscription
7316    }
7317
7318    fn reset_cursor_style(&self, cx: &mut App) {
7319        // Set the cursor only if we're the active window.
7320        if self.is_window_hovered() {
7321            let style = self
7322                .rendered_frame
7323                .cursor_style(self)
7324                .unwrap_or(CursorStyle::Arrow);
7325            cx.platform.set_cursor_style(style);
7326        }
7327    }
7328
7329    /// Dispatches `keystroke` as if the user had pressed it, and returns whether it was handled.
7330    ///
7331    /// The keystroke goes through the same path as a real key press: actions from key bindings run
7332    /// first, then key listeners, then the focused input handler receives its text. The return value
7333    /// is `true` if a listener stopped propagation or the input handler accepted the text. Tests use
7334    /// it through [`TestAppWindow::simulate_keystrokes`](crate::TestAppWindow::simulate_keystrokes). Build a keystroke with [`Keystroke::parse`].
7335    pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {
7336        let keystroke = keystroke.with_simulated_ime();
7337        let result = self.dispatch_event(
7338            PlatformInput::KeyDown(KeyDownEvent {
7339                keystroke: keystroke.clone(),
7340                is_held: false,
7341                prefer_character_input: false,
7342            }),
7343            cx,
7344        );
7345        if !result.propagate {
7346            return true;
7347        }
7348
7349        if let Some(input) = keystroke.key_char
7350            && let Some(mut input_handler) = self.platform_window.take_input_handler()
7351        {
7352            input_handler.dispatch_input(&input, self, cx);
7353            self.platform_window.set_input_handler(input_handler);
7354            return true;
7355        }
7356
7357        false
7358    }
7359
7360    /// Returns the keystrokes bound to `action`, formatted for display, such as `"cmd-s"`.
7361    ///
7362    /// Uses the highest-precedence binding, which is the last one added to the keymap. Returns the
7363    /// action's name if it has no binding. Use it for labels on menus and tooltips.
7364    pub fn keystroke_text_for(&self, action: &dyn Action) -> String {
7365        self.highest_precedence_binding_for_action(action)
7366            .map(|binding| {
7367                binding
7368                    .keystrokes()
7369                    .iter()
7370                    .map(ToString::to_string)
7371                    .collect::<Vec<_>>()
7372                    .join(" ")
7373            })
7374            .unwrap_or_else(|| action.name().to_string())
7375    }
7376
7377    /// Dispatches a platform input event to the window and returns how it was handled.
7378    ///
7379    /// Mouse, keyboard and touch events are routed as described in [input dispatch](crate::_documentation::concepts::input_dispatch).
7380    /// The result says whether propagation continued and whether a listener called [`Window::prevent_default`].
7381    /// Platforms call this for every event. Tests normally use the `simulate_*` methods on [`TestAppWindow`](crate::TestAppWindow) instead.
7382    #[profiling::function]
7383    pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {
7384        #[cfg(feature = "profiler")]
7385        self.window_profiler.begin_input(event.kind_name());
7386        let update_count_before = self.invalidator.update_count();
7387        // Track input modality for focus-visible styling and hover suppression.
7388        // Hover is suppressed during keyboard modality so that keyboard navigation
7389        // doesn't show hover highlights on the item under the mouse cursor.
7390        let old_modality = self.last_input_modality;
7391        self.last_input_modality = match &event {
7392            PlatformInput::KeyDown(_) => InputModality::Keyboard,
7393            PlatformInput::MouseMove(_) | PlatformInput::MouseDown(_) => InputModality::Mouse,
7394            PlatformInput::Touch(_) => InputModality::Touch,
7395            _ => self.last_input_modality,
7396        };
7397        if self.last_input_modality != old_modality {
7398            self.refresh();
7399        }
7400
7401        // Handlers may set this to false by calling `stop_propagation`.
7402        cx.propagate_event = true;
7403        // Handlers may set this to true by calling `prevent_default`.
7404        self.default_prevented = false;
7405
7406        let event = match event {
7407            // Track the mouse position with our own state, since accessing the platform
7408            // API for the mouse position can only occur on the main thread.
7409            PlatformInput::MouseMove(mouse_move) => {
7410                self.mouse_position = mouse_move.position;
7411                self.modifiers = mouse_move.modifiers;
7412                PlatformInput::MouseMove(mouse_move)
7413            }
7414            PlatformInput::MouseDown(mouse_down) => {
7415                self.mouse_position = mouse_down.position;
7416                self.modifiers = mouse_down.modifiers;
7417                PlatformInput::MouseDown(mouse_down)
7418            }
7419            PlatformInput::MouseUp(mouse_up) => {
7420                self.mouse_position = mouse_up.position;
7421                self.modifiers = mouse_up.modifiers;
7422                PlatformInput::MouseUp(mouse_up)
7423            }
7424            PlatformInput::MousePressure(mouse_pressure) => {
7425                PlatformInput::MousePressure(mouse_pressure)
7426            }
7427            PlatformInput::MouseExited(mouse_exited) => {
7428                self.modifiers = mouse_exited.modifiers;
7429                PlatformInput::MouseExited(mouse_exited)
7430            }
7431            PlatformInput::ModifiersChanged(modifiers_changed) => {
7432                self.modifiers = modifiers_changed.modifiers;
7433                self.capslock = modifiers_changed.capslock;
7434                PlatformInput::ModifiersChanged(modifiers_changed)
7435            }
7436            PlatformInput::ScrollWheel(scroll_wheel) => {
7437                self.mouse_position = scroll_wheel.position;
7438                self.modifiers = scroll_wheel.modifiers;
7439                PlatformInput::ScrollWheel(scroll_wheel)
7440            }
7441            PlatformInput::Pinch(pinch) => {
7442                self.mouse_position = pinch.position;
7443                self.modifiers = pinch.modifiers;
7444                PlatformInput::Pinch(pinch)
7445            }
7446            // Translate dragging and dropping of external files from the operating system
7447            // to internal drag and drop events.
7448            PlatformInput::FileDrop(file_drop) => match file_drop {
7449                FileDropEvent::Entered { position, paths } => {
7450                    self.mouse_position = position;
7451                    let source_window = self.handle.window_id();
7452                    if !cx.restore_platform_drag(source_window) && cx.active_drag.is_none() {
7453                        cx.active_drag = Some(AnyDrag {
7454                            value: Arc::new(paths.clone()),
7455                            view: cx.new(|_| paths).into(),
7456                            cursor_offset: position,
7457                            cursor_style: None,
7458                            external_payload_source: None,
7459                        });
7460                    }
7461                    PlatformInput::MouseMove(MouseMoveEvent {
7462                        position,
7463                        pressed_button: Some(MouseButton::Left),
7464                        modifiers: Modifiers::default(),
7465                    })
7466                }
7467                FileDropEvent::Pending { position } => {
7468                    self.mouse_position = position;
7469                    PlatformInput::MouseMove(MouseMoveEvent {
7470                        position,
7471                        pressed_button: Some(MouseButton::Left),
7472                        modifiers: Modifiers::default(),
7473                    })
7474                }
7475                FileDropEvent::Submit { position } => {
7476                    cx.activate(true);
7477                    self.mouse_position = position;
7478                    PlatformInput::MouseUp(MouseUpEvent {
7479                        button: MouseButton::Left,
7480                        position,
7481                        modifiers: Modifiers::default(),
7482                        click_count: 1,
7483                    })
7484                }
7485                FileDropEvent::Exited => {
7486                    if !cx.hand_restored_drag_to_platform(self.handle.window_id()) {
7487                        cx.active_drag.take();
7488                    }
7489                    self.refresh();
7490                    PlatformInput::FileDrop(FileDropEvent::Exited)
7491                }
7492                FileDropEvent::Ended => {
7493                    cx.end_platform_drag(self.handle.window_id());
7494                    self.refresh();
7495                    PlatformInput::FileDrop(FileDropEvent::Ended)
7496                }
7497            },
7498            PlatformInput::Touch(touch) => PlatformInput::Touch(touch),
7499            PlatformInput::LongPress(long_press) => {
7500                self.mouse_position = if long_press.phase == crate::TouchPhase::Started {
7501                    long_press.start_position
7502                } else {
7503                    long_press.position
7504                };
7505                if long_press.phase == crate::TouchPhase::Started {
7506                    self.long_press_capture = None;
7507                }
7508                PlatformInput::LongPress(long_press)
7509            }
7510            PlatformInput::TouchDrag(touch_drag) => {
7511                self.mouse_position = touch_drag.start_position;
7512                PlatformInput::TouchDrag(touch_drag)
7513            }
7514            PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
7515        };
7516
7517        if let Some(any_mouse_event) = event.mouse_event() {
7518            self.dispatch_mouse_event(any_mouse_event, cx);
7519        } else if let Some(any_key_event) = event.keyboard_event() {
7520            self.dispatch_key_event(any_key_event, cx);
7521        } else if let Some(touch_event) = event.touch_event() {
7522            self.dispatch_touch_event(touch_event, cx);
7523        }
7524        if let PlatformInput::LongPress(long_press) = &event {
7525            match long_press.phase {
7526                crate::TouchPhase::Started if !self.default_prevented => {
7527                    self.long_press_capture = None;
7528                }
7529                crate::TouchPhase::Ended | crate::TouchPhase::Cancelled => {
7530                    self.long_press_capture = None;
7531                }
7532                crate::TouchPhase::Started | crate::TouchPhase::Moved => {}
7533            }
7534        }
7535
7536        // Must run after the move is dispatched: the platform owns the gesture afterward, so this
7537        // is the last chance for drag listeners to see the pointer leave and reset their state.
7538        self.promote_external_drag_to_platform(&event, cx);
7539
7540        let caused_invalidation = self.invalidator.update_count() > update_count_before;
7541        if caused_invalidation {
7542            self.input_rate_tracker.borrow_mut().record_input();
7543        }
7544        #[cfg(feature = "profiler")]
7545        self.window_profiler.end_input(caused_invalidation);
7546
7547        DispatchEventResult {
7548            propagate: cx.propagate_event,
7549            default_prevented: self.default_prevented,
7550        }
7551    }
7552
7553    fn promote_external_drag_to_platform(&mut self, event: &PlatformInput, cx: &mut App) {
7554        let PlatformInput::MouseMove(mouse_move) = event else {
7555            return;
7556        };
7557        if mouse_move.pressed_button != Some(MouseButton::Left) {
7558            return;
7559        }
7560        if Bounds::new(Point::default(), self.viewport_size).contains(&mouse_move.position) {
7561            return;
7562        }
7563        if !self.platform_window.can_start_external_drag() {
7564            return;
7565        }
7566        let Some(payload_source) = cx
7567            .active_drag
7568            .as_mut()
7569            .and_then(|drag| drag.external_payload_source.take())
7570        else {
7571            return;
7572        };
7573        let Some(payload) = payload_source(self, cx) else {
7574            return;
7575        };
7576        if self.platform_window.start_external_drag(&payload)
7577            && cx.hand_active_drag_to_platform(self.handle.window_id())
7578        {
7579            self.refresh();
7580        }
7581    }
7582
7583    /// Whether recognized touch pans may use the platform's predicted touch
7584    /// positions ([`TouchEvent::predicted_position`]) to compensate for input
7585    /// latency. Defaults to true.
7586    pub fn touch_prediction_enabled(&self) -> bool {
7587        self.touch_prediction_enabled
7588    }
7589
7590    /// Sets whether recognized touch pans may use the platform's predicted
7591    /// touch positions. Disabling drops [`TouchEvent::predicted_position`]
7592    /// before gesture recognition, so pans track only raw touch positions.
7593    pub fn set_touch_prediction_enabled(&mut self, enabled: bool) {
7594        self.touch_prediction_enabled = enabled;
7595    }
7596
7597    /// Runs the portable gesture recognizer over a raw touch event and
7598    /// dispatches whatever it resolves (scroll steps, synthesized taps)
7599    /// through the ordinary mouse-event path.
7600    fn dispatch_touch_event(&mut self, event: &TouchEvent, cx: &mut App) {
7601        let mut event = event.clone();
7602        if !self.touch_prediction_enabled {
7603            event.predicted_position = None;
7604        }
7605        let recognized_gestures = self.touch_gestures.handle_event(&event);
7606        if event.phase == crate::TouchPhase::Started
7607            && let Some(touch_drag) = self.touch_gestures.offer_touch_drag(event.id)
7608        {
7609            self.dispatch_recognized_touch_gesture(touch_drag, cx);
7610        }
7611        if event.phase == crate::TouchPhase::Started
7612            && self.touch_gestures.pending_long_press().is_some()
7613        {
7614            self.long_press_capture = None;
7615        }
7616        let mut tapped = false;
7617        for gesture in recognized_gestures {
7618            tapped |= matches!(gesture, RecognizedTouchGesture::Tap { .. });
7619            self.dispatch_recognized_touch_gesture(gesture, cx);
7620        }
7621        if event.phase == crate::TouchPhase::Started {
7622            self.schedule_long_press_timer(cx);
7623        } else if self.touch_gestures.pending_long_press().is_none() {
7624            self.long_press_timer.take();
7625        }
7626        // The platform's touch-release handler may inspect the input handler
7627        // as soon as this dispatch returns (the web platform decides virtual
7628        // keyboard visibility there, inside the user gesture). Input handlers
7629        // are registered during draw, so draw now to make them reflect any
7630        // focus change the tap just caused.
7631        if tapped && self.invalidator.is_dirty() {
7632            self.draw(cx).clear(cx);
7633        }
7634        if self.touch_gestures.has_momentum() {
7635            self.schedule_touch_momentum_tick();
7636        }
7637    }
7638
7639    fn dispatch_recognized_touch_gesture(&mut self, gesture: RecognizedTouchGesture, cx: &mut App) {
7640        match gesture {
7641            RecognizedTouchGesture::Scroll(scroll_wheel) => {
7642                self.mouse_position = scroll_wheel.position;
7643                cx.propagate_event = true;
7644                self.dispatch_mouse_event(&scroll_wheel, cx);
7645            }
7646            RecognizedTouchGesture::Tap { down, up } => {
7647                self.mouse_position = up.position;
7648                cx.propagate_event = true;
7649                self.dispatch_mouse_event(&down, cx);
7650                cx.propagate_event = true;
7651                self.dispatch_mouse_event(&up, cx);
7652            }
7653            RecognizedTouchGesture::TouchDrag(touch_drag) => {
7654                self.mouse_position = touch_drag.start_position;
7655                cx.propagate_event = true;
7656                self.default_prevented = false;
7657                let started = touch_drag.phase == crate::TouchPhase::Started;
7658                self.dispatch_mouse_event(&touch_drag, cx);
7659                if started {
7660                    self.touch_gestures
7661                        .resolve_touch_drag(self.default_prevented);
7662                }
7663            }
7664            RecognizedTouchGesture::LongPress(long_press) => {
7665                self.mouse_position = if long_press.phase == crate::TouchPhase::Started {
7666                    long_press.start_position
7667                } else {
7668                    long_press.position
7669                };
7670                cx.propagate_event = true;
7671                self.default_prevented = false;
7672                let started = long_press.phase == crate::TouchPhase::Started;
7673                let ended = matches!(
7674                    long_press.phase,
7675                    crate::TouchPhase::Ended | crate::TouchPhase::Cancelled
7676                );
7677                self.dispatch_mouse_event(&long_press, cx);
7678                if started {
7679                    let claimed = self.default_prevented;
7680                    self.touch_gestures.resolve_long_press(claimed);
7681                    if !claimed {
7682                        self.long_press_capture = None;
7683                    }
7684                }
7685                if ended {
7686                    self.long_press_capture = None;
7687                }
7688            }
7689        }
7690    }
7691
7692    fn schedule_long_press_timer(&mut self, cx: &mut App) {
7693        self.long_press_timer.take();
7694        let Some((touch_id, duration)) = self.touch_gestures.pending_long_press() else {
7695            return;
7696        };
7697        self.long_press_timer = Some(self.spawn(cx, async move |cx| {
7698            cx.background_executor.timer(duration).await;
7699            cx.update(move |window, cx| {
7700                window.long_press_timer.take();
7701                if let Some(gesture) = window.touch_gestures.offer_long_press(touch_id) {
7702                    window.dispatch_recognized_touch_gesture(gesture, cx);
7703                }
7704            })
7705            .log_err();
7706        }));
7707    }
7708
7709    fn schedule_touch_momentum_tick(&mut self) {
7710        self.on_next_frame(|window, cx| {
7711            if let Some(gesture) = window.touch_gestures.tick_momentum() {
7712                window.dispatch_recognized_touch_gesture(gesture, cx);
7713            }
7714            if window.touch_gestures.has_momentum() {
7715                window.schedule_touch_momentum_tick();
7716            }
7717        });
7718    }
7719
7720    /// Returns the hit test for the mouse position, computed from the last rendered frame.
7721    ///
7722    /// It lists the hitboxes under the pointer, front to back, with each hitbox's depth and tags.
7723    /// The result is updated when the mouse moves or the frame is redrawn.
7724    pub fn mouse_hit_test(&self) -> &HitTest {
7725        &self.mouse_hit_test
7726    }
7727
7728    fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
7729        if event.is::<crate::MouseExitEvent>() {
7730            self.pointer_inside_window = false;
7731        } else if event.is::<MouseMoveEvent>()
7732            || event.is::<crate::MouseDownEvent>()
7733            || event.is::<MouseUpEvent>()
7734        {
7735            self.pointer_inside_window =
7736                Bounds::new(Point::default(), self.viewport_size).contains(&self.mouse_position);
7737        }
7738        let hit_test = self.rendered_frame.hit_test(self.mouse_position());
7739        if hit_test != self.mouse_hit_test {
7740            self.mouse_hit_test = hit_test;
7741        }
7742        // Resolve on every pointer event, including movement within one hitbox.
7743        self.reset_cursor_style(cx);
7744
7745        #[cfg(any(feature = "inspector", debug_assertions))]
7746        if self.is_inspector_picking(cx) {
7747            self.handle_inspector_mouse_event(event, cx);
7748            // When inspector is picking, all other mouse handling is skipped.
7749            return;
7750        }
7751
7752        let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);
7753
7754        // Capture phase, events bubble from back to front. Handlers for this phase are used for
7755        // special purposes, such as detecting events outside of a given Bounds.
7756        for listener in &mut mouse_listeners {
7757            let listener = listener.as_mut().unwrap();
7758            listener(event, DispatchPhase::Capture, self, cx);
7759            if !cx.propagate_event {
7760                break;
7761            }
7762        }
7763
7764        // Bubble phase, where most normal handlers do their work.
7765        if cx.propagate_event {
7766            for listener in mouse_listeners.iter_mut().rev() {
7767                let listener = listener.as_mut().unwrap();
7768                listener(event, DispatchPhase::Bubble, self, cx);
7769                if !cx.propagate_event {
7770                    break;
7771                }
7772            }
7773        }
7774
7775        self.rendered_frame.mouse_listeners = mouse_listeners;
7776
7777        if cx.has_active_drag() {
7778            if event.is::<MouseMoveEvent>() {
7779                // If this was a mouse move event, redraw the window so that the
7780                // active drag can follow the mouse cursor.
7781                self.refresh();
7782            } else if event.is::<MouseUpEvent>() {
7783                // If this was a mouse up event, cancel the active drag and redraw
7784                // the window.
7785                cx.active_drag = None;
7786                self.refresh();
7787            }
7788        }
7789
7790        // Auto-release pointer capture on mouse up
7791        if event.is::<MouseUpEvent>() && self.captured_hitbox.is_some() {
7792            self.captured_hitbox = None;
7793        }
7794        if event.is::<MouseMoveEvent>()
7795            || event.is::<crate::MouseExitEvent>()
7796            || event.is::<MouseUpEvent>()
7797        {
7798            self.notify_pointer_observers(PointerChangeCause::Input, cx);
7799        }
7800    }
7801
7802    // If modifiers are not excessive (e.g. AltGr), and the input handler is accepting text input,
7803    // we prefer the text input over bindings.
7804    fn input_preference(&mut self, event: &dyn Any, cx: &mut App) -> InputPreference {
7805        let prefer_character_input = event
7806            .downcast_ref::<KeyDownEvent>()
7807            .is_some_and(|key_down_event| key_down_event.prefer_character_input);
7808        if !prefer_character_input {
7809            return InputPreference::KeyBindings;
7810        }
7811        let Some(mut input_handler) = self.platform_window.take_input_handler() else {
7812            return InputPreference::KeyBindings;
7813        };
7814        let accepts_text_input = input_handler.accepts_text_input(self, cx);
7815        self.platform_window.set_input_handler(input_handler);
7816        if accepts_text_input {
7817            InputPreference::CharacterInput
7818        } else {
7819            InputPreference::KeyBindings
7820        }
7821    }
7822
7823    fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {
7824        if self.invalidator.is_dirty() {
7825            self.draw(cx).clear(cx);
7826        }
7827
7828        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
7829        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
7830
7831        let mut keystroke: Option<Keystroke> = None;
7832
7833        if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {
7834            if event.modifiers.number_of_modifiers() == 0
7835                && self.pending_modifier.modifiers.number_of_modifiers() == 1
7836                && !self.pending_modifier.saw_other_input
7837            {
7838                let key = match self.pending_modifier.modifiers {
7839                    modifiers if modifiers.shift => Some("shift"),
7840                    modifiers if modifiers.control => Some("control"),
7841                    modifiers if modifiers.alt => Some("alt"),
7842                    modifiers if modifiers.platform => Some("platform"),
7843                    modifiers if modifiers.function => Some("function"),
7844                    _ => None,
7845                };
7846                if let Some(key) = key {
7847                    keystroke = Some(Keystroke {
7848                        key: key.to_string(),
7849                        key_char: None,
7850                        modifiers: Modifiers::default(),
7851                    });
7852                }
7853            }
7854
7855            if self.pending_modifier.modifiers.number_of_modifiers() == 0
7856                && event.modifiers.number_of_modifiers() == 1
7857            {
7858                self.pending_modifier.saw_other_input = false
7859            } else if event.modifiers.number_of_modifiers() > 1 {
7860                self.pending_modifier.saw_other_input = true
7861            }
7862            self.pending_modifier.modifiers = event.modifiers
7863        } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
7864            self.pending_modifier.saw_other_input = true;
7865            keystroke = Some(key_down_event.keystroke.clone());
7866            if key_down_event.keystroke.key_char.is_some()
7867                && matches!(
7868                    cx.cursor_hide_mode,
7869                    CursorHideMode::OnTyping | CursorHideMode::OnTypingAndAction
7870                )
7871            {
7872                cx.platform.hide_cursor_until_mouse_moves();
7873            }
7874        }
7875
7876        let Some(keystroke) = keystroke else {
7877            self.finish_dispatch_key_event(
7878                event,
7879                None,
7880                InputPreference::KeyBindings,
7881                dispatch_path,
7882                self.context_stack(),
7883                cx,
7884            );
7885            return;
7886        };
7887
7888        let input_preference = self.input_preference(event, cx);
7889
7890        cx.propagate_event = true;
7891        self.dispatch_keystroke_interceptors(
7892            &keystroke,
7893            input_preference,
7894            self.context_stack(),
7895            cx,
7896        );
7897        if !cx.propagate_event {
7898            self.finish_dispatch_key_event(
7899                event,
7900                Some(&keystroke),
7901                input_preference,
7902                dispatch_path,
7903                self.context_stack(),
7904                cx,
7905            );
7906            return;
7907        }
7908
7909        let mut currently_pending = self.pending_input.take().unwrap_or_default();
7910        if currently_pending.focus.is_some() && currently_pending.focus != self.focus {
7911            currently_pending = PendingInput::default();
7912        }
7913
7914        let match_result = self.rendered_frame.dispatch_tree.dispatch_key(
7915            currently_pending.keystrokes,
7916            keystroke.clone(),
7917            &dispatch_path,
7918        );
7919
7920        if !match_result.to_replay.is_empty() {
7921            self.replay_pending_input(match_result.to_replay, cx);
7922            cx.propagate_event = true;
7923        }
7924
7925        if !match_result.pending.is_empty() {
7926            let previous_timeout = currently_pending.timeout.take();
7927            currently_pending.keystrokes = match_result.pending;
7928            currently_pending.focus = self.focus;
7929
7930            let text_input_requires_timeout = event
7931                .downcast_ref::<KeyDownEvent>()
7932                .filter(|key_down| key_down.keystroke.key_char.is_some())
7933                .and_then(|_| self.platform_window.take_input_handler())
7934                .map_or(false, |mut input_handler| {
7935                    let accepts = input_handler.accepts_text_input(self, cx);
7936                    self.platform_window.set_input_handler(input_handler);
7937                    accepts
7938                });
7939
7940            let needs_timeout = previous_timeout.is_some()
7941                || match_result.pending_has_binding
7942                || text_input_requires_timeout;
7943            currently_pending.timeout = if needs_timeout {
7944                match previous_timeout {
7945                    Some(mut timeout) if timeout.is_paused() => {
7946                        timeout.reset_duration(PENDING_INPUT_TIMEOUT);
7947                        Some(timeout)
7948                    }
7949                    previous_timeout => {
7950                        drop(previous_timeout);
7951                        Some(self.new_pending_input_timeout(PENDING_INPUT_TIMEOUT, cx))
7952                    }
7953                }
7954            } else {
7955                None
7956            };
7957            self.pending_input = Some(currently_pending);
7958            self.pending_input_changed(cx);
7959            cx.propagate_event = false;
7960            return;
7961        }
7962
7963        // Interceptors or replayed actions may have changed whether the input handler accepts text.
7964        let input_preference = self.input_preference(event, cx);
7965        if input_preference == InputPreference::KeyBindings {
7966            for binding in match_result.bindings {
7967                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
7968                if !cx.propagate_event {
7969                    self.dispatch_keystroke_observers(
7970                        &keystroke,
7971                        input_preference,
7972                        Some(binding.action.as_ref()),
7973                        match_result.context_stack,
7974                        cx,
7975                    );
7976                    self.pending_input_changed(cx);
7977                    return;
7978                }
7979            }
7980        }
7981
7982        self.finish_dispatch_key_event(
7983            event,
7984            Some(&keystroke),
7985            input_preference,
7986            dispatch_path,
7987            match_result.context_stack,
7988            cx,
7989        );
7990        self.pending_input_changed(cx);
7991    }
7992
7993    fn new_pending_input_timeout(&self, duration: Duration, cx: &App) -> PendingInputTimeout {
7994        let (started_at, task) = self.start_pending_input_timeout(duration, cx);
7995        PendingInputTimeout {
7996            duration,
7997            remaining: duration,
7998            state: PendingInputTimeoutState::Running { started_at, task },
7999        }
8000    }
8001
8002    fn start_pending_input_timeout(&self, remaining: Duration, cx: &App) -> (Instant, Task<()>) {
8003        let started_at = cx.background_executor().now();
8004        let task = self.spawn(cx, async move |cx| {
8005            cx.background_executor.timer(remaining).await;
8006            cx.update(move |window, cx| {
8007                let Some(currently_pending) = window
8008                    .pending_input
8009                    .take()
8010                    .filter(|pending| pending.focus == window.focus)
8011                else {
8012                    return;
8013                };
8014
8015                let node_id = window.focus_node_id_in_rendered_frame(window.focus);
8016                let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id);
8017
8018                let to_replay = window
8019                    .rendered_frame
8020                    .dispatch_tree
8021                    .flush_dispatch(currently_pending.keystrokes, &dispatch_path);
8022
8023                window.pending_input_changed(cx);
8024                window.replay_pending_input(to_replay, cx)
8025            })
8026            .log_err();
8027        });
8028        (started_at, task)
8029    }
8030
8031    fn finish_dispatch_key_event(
8032        &mut self,
8033        event: &dyn Any,
8034        recognized_keystroke: Option<&Keystroke>,
8035        input_preference: InputPreference,
8036        dispatch_path: SmallVec<[DispatchNodeId; 32]>,
8037        context_stack: Vec<KeyContext>,
8038        cx: &mut App,
8039    ) {
8040        self.dispatch_key_down_up_event(event, &dispatch_path, cx);
8041        if !cx.propagate_event {
8042            return;
8043        }
8044
8045        self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);
8046        if !cx.propagate_event {
8047            return;
8048        }
8049
8050        if let Some(keystroke) = recognized_keystroke {
8051            self.dispatch_keystroke_observers(keystroke, input_preference, None, context_stack, cx);
8052        }
8053    }
8054
8055    pub(crate) fn pending_input_changed(&mut self, cx: &mut App) {
8056        self.pending_input_observers
8057            .clone()
8058            .retain(&(), |callback| callback(self, cx));
8059    }
8060
8061    fn defer_pending_input_changed(&self, cx: &mut App) {
8062        // Avoid re-entrant entity updates by deferring observer notifications to the end of the
8063        // current effect cycle, and only for this window.
8064        let window_handle = self.handle;
8065        cx.defer(move |cx| {
8066            window_handle
8067                .update(cx, |_, window, cx| {
8068                    window.pending_input_changed(cx);
8069                })
8070                .ok();
8071        });
8072    }
8073
8074    fn dispatch_key_down_up_event(
8075        &mut self,
8076        event: &dyn Any,
8077        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
8078        cx: &mut App,
8079    ) {
8080        // Capture phase
8081        for node_id in dispatch_path {
8082            let node = self.rendered_frame.dispatch_tree.node(*node_id);
8083
8084            for key_listener in node.key_listeners.clone() {
8085                key_listener(event, DispatchPhase::Capture, self, cx);
8086                if !cx.propagate_event {
8087                    return;
8088                }
8089            }
8090        }
8091
8092        // Bubble phase
8093        for node_id in dispatch_path.iter().rev() {
8094            // Handle low level key events
8095            let node = self.rendered_frame.dispatch_tree.node(*node_id);
8096            for key_listener in node.key_listeners.clone() {
8097                key_listener(event, DispatchPhase::Bubble, self, cx);
8098                if !cx.propagate_event {
8099                    return;
8100                }
8101            }
8102        }
8103    }
8104
8105    fn dispatch_modifiers_changed_event(
8106        &mut self,
8107        event: &dyn Any,
8108        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
8109        cx: &mut App,
8110    ) {
8111        let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {
8112            return;
8113        };
8114        for node_id in dispatch_path.iter().rev() {
8115            let node = self.rendered_frame.dispatch_tree.node(*node_id);
8116            for listener in node.modifiers_changed_listeners.clone() {
8117                listener(event, self, cx);
8118                if !cx.propagate_event {
8119                    return;
8120                }
8121            }
8122        }
8123    }
8124
8125    /// Pending input that can still complete a binding. Input left over from a previous focus can
8126    /// never complete one.
8127    fn active_pending_input(&self) -> Option<&PendingInput> {
8128        self.pending_input
8129            .as_ref()
8130            .filter(|pending_input| pending_input.focus == self.focus)
8131    }
8132
8133    /// Returns whether the window is partway through a multi-keystroke binding, such as `cmd-k cmd-s`.
8134    ///
8135    /// After the first keystroke of such a binding, GPUI waits for the next one. Use this to show
8136    /// that a sequence is pending.
8137    pub fn has_pending_keystrokes(&self) -> bool {
8138        self.pending_input().is_some()
8139    }
8140
8141    #[cfg(test)]
8142    pub(crate) fn pending_input_is_none(&self) -> bool {
8143        self.pending_input.is_none()
8144    }
8145
8146    pub(crate) fn clear_pending_keystrokes(&mut self, cx: &mut App) {
8147        if self.pending_input.take().is_some() {
8148            self.defer_pending_input_changed(cx);
8149        }
8150    }
8151
8152    /// Returns the keystrokes typed so far that could still complete a multi-keystroke binding.
8153    ///
8154    /// Returns `None` when no binding is pending. The list is cleared when the sequence completes,
8155    /// times out, or focus changes.
8156    /// Returns pending input that can still complete a multi-stroke key binding. Input left over
8157    /// from a previous focus can never complete one.
8158    pub fn pending_input(&self) -> Option<PendingInputStatus<'_>> {
8159        self.active_pending_input()
8160            .map(|pending_input| PendingInputStatus {
8161                keystrokes: pending_input.keystrokes.as_slice(),
8162                timeout: pending_input
8163                    .timeout
8164                    .as_ref()
8165                    .map(PendingInputTimeout::status),
8166            })
8167    }
8168
8169    /// Pauses or resumes the current pending input timeout on behalf of `owner`.
8170    ///
8171    /// A paused timeout resumes automatically if `owner` is released. Returns whether the timeout
8172    /// state changed. A timeout paused by one owner cannot be resumed by another.
8173    pub fn set_pending_input_timeout_paused<T: 'static>(
8174        &mut self,
8175        owner: &Entity<T>,
8176        paused: bool,
8177        cx: &mut App,
8178    ) -> bool {
8179        let owner_id = owner.entity_id();
8180        if !paused {
8181            return self.resume_pending_input_timeout(owner_id, cx);
8182        }
8183
8184        let timeout = self
8185            .pending_input
8186            .as_ref()
8187            .filter(|pending_input| pending_input.focus == self.focus)
8188            .and_then(|pending_input| pending_input.timeout.as_ref());
8189        let Some(timeout) = timeout else {
8190            return false;
8191        };
8192        if timeout.is_paused() {
8193            return false;
8194        }
8195
8196        let release_subscription = self.observe_release(owner, cx, move |_, window, cx| {
8197            window.resume_pending_input_timeout(owner_id, cx);
8198        });
8199        let now = cx.background_executor().now();
8200        let changed = self
8201            .pending_input
8202            .as_mut()
8203            .filter(|pending_input| pending_input.focus == self.focus)
8204            .and_then(|pending_input| pending_input.timeout.as_mut())
8205            .is_some_and(|timeout| {
8206                timeout.pause(
8207                    PendingInputTimeoutPause {
8208                        owner_id,
8209                        _release_subscription: release_subscription,
8210                    },
8211                    now,
8212                )
8213            });
8214
8215        if changed {
8216            self.defer_pending_input_changed(cx);
8217        }
8218        changed
8219    }
8220
8221    fn resume_pending_input_timeout(&mut self, owner_id: EntityId, cx: &mut App) -> bool {
8222        let Some(remaining) = self
8223            .pending_input
8224            .as_ref()
8225            .and_then(|pending_input| pending_input.timeout.as_ref())
8226            .filter(|timeout| timeout.pause_owner_id() == Some(owner_id))
8227            .map(|timeout| timeout.remaining)
8228        else {
8229            return false;
8230        };
8231
8232        let (started_at, task) = self.start_pending_input_timeout(remaining, cx);
8233        let changed = self
8234            .pending_input
8235            .as_mut()
8236            .and_then(|pending_input| pending_input.timeout.as_mut())
8237            .is_some_and(|timeout| timeout.resume(owner_id, started_at, task));
8238
8239        if changed {
8240            self.defer_pending_input_changed(cx);
8241        }
8242        changed
8243    }
8244
8245    /// Returns the currently pending input keystrokes that might result in a multi-stroke key binding.
8246    pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {
8247        self.pending_input()
8248            .map(|pending_input| pending_input.keystrokes())
8249    }
8250
8251    fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {
8252        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
8253        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
8254
8255        'replay: for replay in replays {
8256            let event = KeyDownEvent {
8257                keystroke: replay.keystroke.clone(),
8258                is_held: false,
8259                prefer_character_input: true,
8260            };
8261
8262            cx.propagate_event = true;
8263            for binding in replay.bindings {
8264                self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
8265                if !cx.propagate_event {
8266                    self.dispatch_keystroke_observers(
8267                        &replay.keystroke,
8268                        InputPreference::KeyBindings,
8269                        Some(binding.action.as_ref()),
8270                        Vec::default(),
8271                        cx,
8272                    );
8273                    continue 'replay;
8274                }
8275            }
8276
8277            self.dispatch_key_down_up_event(&event, &dispatch_path, cx);
8278            if !cx.propagate_event {
8279                continue 'replay;
8280            }
8281            if let Some(input) = replay.keystroke.key_char.as_ref().cloned()
8282                && let Some(mut input_handler) = self.platform_window.take_input_handler()
8283            {
8284                input_handler.dispatch_input(&input, self, cx);
8285                self.platform_window.set_input_handler(input_handler)
8286            }
8287        }
8288    }
8289
8290    fn focus_node_id_in_rendered_frame(&self, focus_id: Option<FocusId>) -> DispatchNodeId {
8291        focus_id
8292            .and_then(|focus_id| {
8293                self.rendered_frame
8294                    .dispatch_tree
8295                    .focusable_node_id(focus_id)
8296            })
8297            .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id())
8298    }
8299
8300    fn dispatch_action_on_node(
8301        &mut self,
8302        node_id: DispatchNodeId,
8303        action: &dyn Action,
8304        cx: &mut App,
8305    ) {
8306        self.dispatch_action_on_node_inner(node_id, action, cx);
8307
8308        if !cx.propagate_event
8309            && cx.cursor_hide_mode == CursorHideMode::OnTypingAndAction
8310            && self.last_input_was_keyboard()
8311        {
8312            cx.platform.hide_cursor_until_mouse_moves();
8313        }
8314    }
8315
8316    fn dispatch_action_on_node_inner(
8317        &mut self,
8318        node_id: DispatchNodeId,
8319        action: &dyn Action,
8320        cx: &mut App,
8321    ) {
8322        let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
8323
8324        // Capture phase for global actions.
8325        cx.propagate_event = true;
8326        if let Some(mut global_listeners) = cx
8327            .global_action_listeners
8328            .remove(&action.as_any().type_id())
8329        {
8330            for listener in &global_listeners {
8331                #[cfg(feature = "profiler")]
8332                self.window_profiler.begin_action_handler(action, cx);
8333                listener(action.as_any(), DispatchPhase::Capture, cx);
8334                #[cfg(feature = "profiler")]
8335                self.window_profiler.end_action_handler();
8336                if !cx.propagate_event {
8337                    break;
8338                }
8339            }
8340
8341            global_listeners.extend(
8342                cx.global_action_listeners
8343                    .remove(&action.as_any().type_id())
8344                    .unwrap_or_default(),
8345            );
8346
8347            cx.global_action_listeners
8348                .insert(action.as_any().type_id(), global_listeners);
8349        }
8350
8351        if !cx.propagate_event {
8352            return;
8353        }
8354
8355        // Capture phase for window actions.
8356        for node_id in &dispatch_path {
8357            let node = self.rendered_frame.dispatch_tree.node(*node_id);
8358            for DispatchActionListener {
8359                action_type,
8360                listener,
8361            } in node.action_listeners.clone()
8362            {
8363                let any_action = action.as_any();
8364                if action_type == any_action.type_id() {
8365                    #[cfg(feature = "profiler")]
8366                    self.window_profiler.begin_action_handler(action, cx);
8367                    listener(any_action, DispatchPhase::Capture, self, cx);
8368                    #[cfg(feature = "profiler")]
8369                    self.window_profiler.end_action_handler();
8370
8371                    if !cx.propagate_event {
8372                        return;
8373                    }
8374                }
8375            }
8376        }
8377
8378        // Bubble phase for window actions.
8379        for node_id in dispatch_path.iter().rev() {
8380            let node = self.rendered_frame.dispatch_tree.node(*node_id);
8381            for DispatchActionListener {
8382                action_type,
8383                listener,
8384            } in node.action_listeners.clone()
8385            {
8386                let any_action = action.as_any();
8387                if action_type == any_action.type_id() {
8388                    cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
8389                    #[cfg(feature = "profiler")]
8390                    self.window_profiler.begin_action_handler(action, cx);
8391                    listener(any_action, DispatchPhase::Bubble, self, cx);
8392                    #[cfg(feature = "profiler")]
8393                    self.window_profiler.end_action_handler();
8394
8395                    if !cx.propagate_event {
8396                        return;
8397                    }
8398                }
8399            }
8400        }
8401
8402        // Bubble phase for global actions.
8403        if let Some(mut global_listeners) = cx
8404            .global_action_listeners
8405            .remove(&action.as_any().type_id())
8406        {
8407            for listener in global_listeners.iter().rev() {
8408                cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
8409
8410                #[cfg(feature = "profiler")]
8411                self.window_profiler.begin_action_handler(action, cx);
8412                listener(action.as_any(), DispatchPhase::Bubble, cx);
8413                #[cfg(feature = "profiler")]
8414                self.window_profiler.end_action_handler();
8415                if !cx.propagate_event {
8416                    break;
8417                }
8418            }
8419
8420            global_listeners.extend(
8421                cx.global_action_listeners
8422                    .remove(&action.as_any().type_id())
8423                    .unwrap_or_default(),
8424            );
8425
8426            cx.global_action_listeners
8427                .insert(action.as_any().type_id(), global_listeners);
8428        }
8429    }
8430
8431    /// Calls `handler` each time the global `G` is updated, for as long as the subscription is alive.
8432    ///
8433    /// The window-aware form of [`App::observe_global`]. Keep the returned [`Subscription`] in the
8434    /// view that uses the global.
8435    pub fn observe_global<G: Global>(
8436        &mut self,
8437        cx: &mut App,
8438        f: impl Fn(&mut Window, &mut App) + 'static,
8439    ) -> Subscription {
8440        let window_handle = self.handle;
8441        let (subscription, activate) = cx.global_observers.insert(
8442            TypeId::of::<G>(),
8443            Box::new(move |cx| {
8444                window_handle
8445                    .update(cx, |_, window, cx| f(window, cx))
8446                    .is_ok()
8447            }),
8448        );
8449        cx.defer(move |_| activate());
8450        subscription
8451    }
8452
8453    /// Brings the window to the front and focuses it at the platform level.
8454    ///
8455    /// The platform may refuse, such as when the app isn't allowed to steal focus. If you have an
8456    /// activation token from the platform, use [`Window::activate_with_token`] instead.
8457    pub fn activate(&self) {
8458        self.platform_window.activate(None);
8459    }
8460
8461    /// Request focus using a token supplied by the desktop shell, such as a
8462    /// Wayland tray host. Show the window before calling this method.
8463    ///
8464    /// Returns whether the platform submitted the request. The compositor may
8465    /// still deny focus. Returns false for empty tokens or unsupported platforms;
8466    /// callers can then fall back to [`Self::activate`]. Tokens must not
8467    /// be reused for subsequent activations.
8468    pub fn activate_with_token(&self, token: &str) -> bool {
8469        !token.is_empty() && self.platform_window.activate(Some(token))
8470    }
8471
8472    /// Asks the operating system to draw attention to this window, such as by bouncing the dock icon.
8473    pub fn request_attention(&self) {
8474        self.platform_window.request_attention();
8475    }
8476
8477    /// Minimizes the window at the platform level.
8478    pub fn minimize_window(&self) {
8479        self.platform_window.minimize();
8480    }
8481
8482    /// Show or hide the current window at the platform level.
8483    ///
8484    /// Call [`Window::activate`] separately when the window should also receive focus.
8485    /// The window manager may still focus a window when it is shown.
8486    pub fn set_visible(&self, visible: bool) {
8487        self.platform_window.set_visible(visible);
8488    }
8489
8490    /// Enters fullscreen mode, or leaves it if the window is already fullscreen.
8491    pub fn toggle_fullscreen(&self) {
8492        self.platform_window.toggle_fullscreen();
8493    }
8494
8495    /// Toggle simple (borderless) fullscreen, where the window covers the entire
8496    /// screen including the menu bar and, on notched displays, the area around the
8497    /// notch. Unlike [`Window::toggle_fullscreen`], this does not move the window
8498    /// into its own Mission Control space. Only has an effect on macOS.
8499    pub fn toggle_simple_fullscreen(&self) {
8500        self.platform_window.toggle_simple_fullscreen();
8501    }
8502
8503    /// Tells the platform to recompute where the input method candidate window should appear.
8504    ///
8505    /// Call it after the caret moves, so the candidate window follows the text input.
8506    pub fn invalidate_character_coordinates(&self) {
8507        self.on_next_frame(|window, cx| {
8508            if let Some(mut input_handler) = window.platform_window.take_input_handler() {
8509                if let Some(bounds) = input_handler.selected_bounds(window, cx) {
8510                    window.platform_window.update_ime_position(bounds);
8511                }
8512                window.platform_window.set_input_handler(input_handler);
8513            }
8514        });
8515    }
8516
8517    /// Shows a prompt with `message`, `detail` and one button per entry in `answers`.
8518    ///
8519    /// The returned receiver yields the index of the button the user clicked. The `level` sets the
8520    /// prompt's icon and emphasis. Unless the app has set a prompt builder, the platform's native
8521    /// dialog is used. Await the receiver from a task, and don't block on it in a listener.
8522    pub fn prompt<T>(
8523        &mut self,
8524        level: PromptLevel,
8525        message: &str,
8526        detail: Option<&str>,
8527        answers: &[T],
8528        cx: &mut App,
8529    ) -> oneshot::Receiver<usize>
8530    where
8531        T: Clone + Into<PromptButton>,
8532    {
8533        let prompt_builder = cx.prompt_builder.take();
8534        let Some(prompt_builder) = prompt_builder else {
8535            unreachable!("Re-entrant window prompting is not supported by GPUI");
8536        };
8537
8538        let answers = answers
8539            .iter()
8540            .map(|answer| answer.clone().into())
8541            .collect::<Vec<_>>();
8542
8543        let receiver = match &prompt_builder {
8544            PromptBuilder::Default => self
8545                .platform_window
8546                .prompt(level, message, detail, &answers)
8547                .unwrap_or_else(|| {
8548                    self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
8549                }),
8550            PromptBuilder::Custom(_) => {
8551                self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
8552            }
8553        };
8554
8555        cx.prompt_builder = Some(prompt_builder);
8556
8557        receiver
8558    }
8559
8560    fn build_custom_prompt(
8561        &mut self,
8562        prompt_builder: &PromptBuilder,
8563        level: PromptLevel,
8564        message: &str,
8565        detail: Option<&str>,
8566        answers: &[PromptButton],
8567        cx: &mut App,
8568    ) -> oneshot::Receiver<usize> {
8569        let (sender, receiver) = oneshot::channel();
8570        let handle = PromptHandle::new(sender);
8571        let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);
8572        self.prompt = Some(handle);
8573        self.refresh();
8574        receiver
8575    }
8576
8577    /// Returns whether a prompt rendered by GPUI is currently active in this window.
8578    ///
8579    /// This is only true for prompts rendered in the window (see
8580    /// [`App::set_prompt_builder`]), not for platform-native prompt dialogs.
8581    pub fn has_active_prompt(&self) -> bool {
8582        self.prompt.is_some()
8583    }
8584
8585    /// Returns the key contexts on the path from the root to the focused element, outermost first.
8586    ///
8587    /// Key bindings match against this stack. It is empty when nothing has focus.
8588    pub fn context_stack(&self) -> Vec<KeyContext> {
8589        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
8590        let dispatch_tree = &self.rendered_frame.dispatch_tree;
8591        dispatch_tree
8592            .dispatch_path(node_id)
8593            .iter()
8594            .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())
8595            .collect()
8596    }
8597
8598    /// Returns one instance of each action that a listener on the focused element's path handles.
8599    ///
8600    /// Use it to populate a command palette. Actions that need input to build are left out.
8601    pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {
8602        let node_id = self.focus_node_id_in_rendered_frame(self.focus);
8603        let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);
8604        for action_type in cx.global_action_listeners.keys() {
8605            if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {
8606                let action = cx.actions.build_action_type(action_type).ok();
8607                if let Some(action) = action {
8608                    actions.insert(ix, action);
8609                }
8610            }
8611        }
8612        actions
8613    }
8614
8615    /// Returns the key bindings that invoke `action` from the focused element, in the order they were added.
8616    ///
8617    /// For display, use the last binding, which takes precedence. See
8618    /// [`Window::highest_precedence_binding_for_action`] to get that one directly.
8619    pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
8620        self.rendered_frame
8621            .dispatch_tree
8622            .bindings_for_action(action, &self.context_stack())
8623    }
8624
8625    /// Returns the key binding that takes precedence for `action` from the focused element.
8626    ///
8627    /// This is the same as the last result of [`Window::bindings_for_action`], without building the list.
8628    pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option<KeyBinding> {
8629        self.rendered_frame
8630            .dispatch_tree
8631            .highest_precedence_binding_for_action(action, &self.context_stack())
8632    }
8633
8634    /// Returns the key bindings for an action in a context.
8635    pub fn bindings_for_action_in_context(
8636        &self,
8637        action: &dyn Action,
8638        context: KeyContext,
8639    ) -> Vec<KeyBinding> {
8640        let dispatch_tree = &self.rendered_frame.dispatch_tree;
8641        dispatch_tree.bindings_for_action(action, &[context])
8642    }
8643
8644    /// Returns the highest precedence key binding for an action in a context. This is more
8645    /// efficient than getting the last result of `bindings_for_action_in_context`.
8646    pub fn highest_precedence_binding_for_action_in_context(
8647        &self,
8648        action: &dyn Action,
8649        context: KeyContext,
8650    ) -> Option<KeyBinding> {
8651        let dispatch_tree = &self.rendered_frame.dispatch_tree;
8652        dispatch_tree.highest_precedence_binding_for_action(action, &[context])
8653    }
8654
8655    /// Returns any bindings that would invoke an action on the given focus handle if it were
8656    /// focused. Bindings are returned in the order they were added. For display, the last binding
8657    /// should take precedence.
8658    pub fn bindings_for_action_in(
8659        &self,
8660        action: &dyn Action,
8661        focus_handle: &FocusHandle,
8662    ) -> Vec<KeyBinding> {
8663        let dispatch_tree = &self.rendered_frame.dispatch_tree;
8664        let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else {
8665            return vec![];
8666        };
8667        dispatch_tree.bindings_for_action(action, &context_stack)
8668    }
8669
8670    /// Returns the highest precedence key binding that would invoke an action on the given focus
8671    /// handle if it were focused. This is more efficient than getting the last result of
8672    /// `bindings_for_action_in`.
8673    pub fn highest_precedence_binding_for_action_in(
8674        &self,
8675        action: &dyn Action,
8676        focus_handle: &FocusHandle,
8677    ) -> Option<KeyBinding> {
8678        let dispatch_tree = &self.rendered_frame.dispatch_tree;
8679        let context_stack = self.context_stack_for_focus_handle(focus_handle)?;
8680        dispatch_tree.highest_precedence_binding_for_action(action, &context_stack)
8681    }
8682
8683    /// Returns the bindings that could complete the sequence `input`, given the current key contexts.
8684    ///
8685    /// Use it with [`Window::pending_input_keystrokes`] to show the next keys of a sequence.
8686    pub fn possible_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
8687        self.rendered_frame
8688            .dispatch_tree
8689            .possible_next_bindings_for_input(input, &self.context_stack())
8690    }
8691
8692    fn context_stack_for_focus_handle(
8693        &self,
8694        focus_handle: &FocusHandle,
8695    ) -> Option<Vec<KeyContext>> {
8696        let dispatch_tree = &self.rendered_frame.dispatch_tree;
8697        let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?;
8698        let context_stack: Vec<_> = dispatch_tree
8699            .dispatch_path(node_id)
8700            .into_iter()
8701            .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
8702            .collect();
8703        Some(context_stack)
8704    }
8705
8706    /// Wraps `f` as an event listener that updates the entity `view`, if it is still alive.
8707    ///
8708    /// The returned closure takes an event, a window and an app, and calls `f` with the view, the
8709    /// event, the window and a `Context<T>`. If `view` has been released, the call does nothing.
8710    /// It works like [`Context::listener`] for code that has a window but no `Context` at hand.
8711    pub fn listener_for<T: 'static, E>(
8712        &self,
8713        view: &Entity<T>,
8714        f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
8715    ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
8716        let view = view.downgrade();
8717        move |e: &E, window: &mut Window, cx: &mut App| {
8718            view.update(cx, |view, cx| f(view, e, window, cx)).ok();
8719        }
8720    }
8721
8722    /// Wraps `f` as a handler that updates `entity`, if it is still alive.
8723    ///
8724    /// Like [`Window::listener_for`], but the handler takes only a window and an app, with no event.
8725    /// Use it for callbacks such as `on_click` handlers that don't need the event value.
8726    pub fn handler_for<E: 'static, Callback: Fn(&mut E, &mut Window, &mut Context<E>) + 'static>(
8727        &self,
8728        entity: &Entity<E>,
8729        f: Callback,
8730    ) -> impl Fn(&mut Window, &mut App) + 'static {
8731        let entity = entity.downgrade();
8732        move |window: &mut Window, cx: &mut App| {
8733            entity.update(cx, |entity, cx| f(entity, window, cx)).ok();
8734        }
8735    }
8736
8737    /// Registers a callback that runs when the user asks to close the window, and can cancel the close.
8738    ///
8739    /// The callback returns `true` to let the window close and `false` to keep it open, such as when
8740    /// there are unsaved changes. If the window no longer exists when the request arrives, the close
8741    /// proceeds. Call it once per window; it sets the platform's close handler.
8742    pub fn on_window_should_close(
8743        &self,
8744        cx: &App,
8745        f: impl Fn(&mut Window, &mut App) -> bool + 'static,
8746    ) {
8747        let mut cx = self.to_async(cx);
8748        self.platform_window.on_should_close(Box::new(move || {
8749            cx.update(|window, cx| f(window, cx)).unwrap_or(true)
8750        }))
8751    }
8752
8753    /// Register an action listener on this node for the next frame. The type of action
8754    /// is determined by the first parameter of the given listener. When the next frame is rendered
8755    /// the listener will be cleared.
8756    ///
8757    /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
8758    /// a specific need to register a listener yourself.
8759    ///
8760    /// This method should only be called as part of the paint phase of element drawing.
8761    pub fn on_action(
8762        &mut self,
8763        action_type: TypeId,
8764        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
8765    ) {
8766        self.invalidator.debug_assert_paint();
8767
8768        self.next_frame
8769            .dispatch_tree
8770            .on_action(action_type, Rc::new(listener));
8771    }
8772
8773    /// Registers `listener` for `action_type` on the current node, if `condition` is `true`.
8774    ///
8775    /// Works like [`Window::on_action`], but the listener is registered only when `condition` is
8776    /// `true`. The listener is cleared when the next frame is painted. Call it during paint.
8777    pub fn on_action_when(
8778        &mut self,
8779        condition: bool,
8780        action_type: TypeId,
8781        listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
8782    ) {
8783        self.invalidator.debug_assert_paint();
8784
8785        if condition {
8786            self.next_frame
8787                .dispatch_tree
8788                .on_action(action_type, Rc::new(listener));
8789        }
8790    }
8791
8792    /// Returns information about the GPU that renders this window, if the platform reports it.
8793    ///
8794    /// Currently it returns `None` on macOS and Windows.
8795    pub fn gpu_specs(&self) -> Option<GpuSpecs> {
8796        self.platform_window.gpu_specs()
8797    }
8798
8799    /// Returns the GPU device and queue used to render this window, if the backend exposes them.
8800    ///
8801    /// The returned box holds the backend's device and queue, which you downcast to use. Embedders
8802    /// that share the device with their own rendering use this. See also [`Window::gpu_device_lost`].
8803    #[cfg(any(
8804        target_os = "linux",
8805        target_os = "freebsd",
8806        target_os = "windows",
8807        target_os = "macos"
8808    ))]
8809    pub fn gpu_context(&self) -> Option<Box<dyn std::any::Any>> {
8810        self.platform_window.gpu_context()
8811    }
8812
8813    /// Returns backend-specific GPU information for custom controls.
8814    ///
8815    /// The returned box has the rendering backend's own type. Downcast it with `downcast_ref` to
8816    /// read the backend's values.
8817    #[cfg(any(
8818        target_family = "wasm",
8819        target_os = "linux",
8820        target_os = "freebsd",
8821        target_os = "macos"
8822    ))]
8823    pub fn gpu_context_info(&self) -> Option<Box<dyn std::any::Any>> {
8824        self.platform_window.gpu_context_info()
8825    }
8826
8827    /// Whether the GPU device backing this window has been lost (recovery
8828    /// happens on a subsequent platform draw). `None` when the backend
8829    /// cannot know. Embedders that captured the device from
8830    /// [`Self::gpu_context`] should stop submitting while this is
8831    /// `Some(true)` and re-acquire the device once it reads `Some(false)`.
8832    #[cfg(any(
8833        target_os = "linux",
8834        target_os = "freebsd",
8835        target_os = "windows",
8836        target_os = "macos"
8837    ))]
8838    pub fn gpu_device_lost(&self) -> Option<bool> {
8839        self.platform_window.gpu_device_lost()
8840    }
8841
8842    /// Performs the platform's title bar double-click action, such as zooming or minimizing.
8843    ///
8844    /// This is macOS specific. Call it from a double-click handler on a custom title bar.
8845    pub fn titlebar_double_click(&self) {
8846        self.platform_window
8847            .titlebar_double_click(self.is_resizable, self.is_minimizable);
8848    }
8849
8850    /// Returns the window's title as the platform reports it.
8851    ///
8852    /// This is macOS specific. To set the title, use [`Window::set_window_title`].
8853    pub fn window_title(&self) -> String {
8854        self.platform_window.get_title()
8855    }
8856
8857    /// Returns a list of all tabbed windows and their titles.
8858    /// This is macOS specific.
8859    pub fn tabbed_windows(&self) -> Option<Vec<SystemWindowTab>> {
8860        self.platform_window.tabbed_windows()
8861    }
8862
8863    /// Returns the tab bar visibility.
8864    /// This is macOS specific.
8865    pub fn tab_bar_visible(&self) -> bool {
8866        self.platform_window.tab_bar_visible()
8867    }
8868
8869    /// Merges all open windows into a single tabbed window.
8870    /// This is macOS specific.
8871    pub fn merge_all_windows(&self) {
8872        self.platform_window.merge_all_windows()
8873    }
8874
8875    /// Moves the tab to a new containing window.
8876    /// This is macOS specific.
8877    pub fn move_tab_to_new_window(&self) {
8878        self.platform_window.move_tab_to_new_window()
8879    }
8880
8881    /// Shows or hides the window tab overview.
8882    /// This is macOS specific.
8883    pub fn toggle_window_tab_overview(&self) {
8884        self.platform_window.toggle_window_tab_overview()
8885    }
8886
8887    /// Sets the tabbing identifier for the window.
8888    /// This is macOS specific.
8889    pub fn set_tabbing_identifier(&self, tabbing_identifier: Option<String>) {
8890        self.platform_window
8891            .set_tabbing_identifier(tabbing_identifier)
8892    }
8893
8894    /// Request the OS to play an alert sound. On some platforms this is associated
8895    /// with the window, for others it's just a simple global function call.
8896    pub fn play_system_bell(&self) {
8897        self.platform_window.play_system_bell()
8898    }
8899
8900    /// Returns whether accessibility support is enabled for this window.
8901    ///
8902    /// This is false when the app was created with [`crate::Application::new_inaccessible`].
8903    /// Unlike [`Self::is_a11y_active`], this does not depend on whether assistive
8904    /// technology is currently connected, so it can be used to gate subscriptions
8905    /// that are only needed for accessibility.
8906    pub fn is_a11y_enabled(&self) -> bool {
8907        self.a11y.is_enabled()
8908    }
8909
8910    /// Returns whether accessibility features are active for this frame,
8911    /// i.e. whether assistive technology (such as a screen reader) is
8912    /// connected and an accessibility tree is being built.
8913    ///
8914    /// Use this to skip computing data during rendering that is only
8915    /// observable through the accessibility tree. When accessibility is
8916    /// activated, a redraw is forced, so gated work is recomputed before the
8917    /// next tree update is sent to the platform.
8918    ///
8919    /// See the [accessibility guide](crate::_documentation::guides::accessibility) for an overview.
8920    pub fn is_a11y_active(&self) -> bool {
8921        self.a11y.is_active()
8922    }
8923
8924    /// Build this window's accessibility tree every frame, even with no
8925    /// assistive technology connected, so [`Self::debug_a11y_tree_json`] and
8926    /// the accessibility actions work for automation. Forces a redraw, since
8927    /// the tree is built during prepaint. [`crate::Application::new_inaccessible`]
8928    /// still wins.
8929    pub fn set_a11y_forced(&mut self, forced: bool) {
8930        self.a11y.set_forced(forced);
8931        self.refresh();
8932    }
8933
8934    /// Debug representation of the last frame's accessibility information.
8935    pub fn debug_a11y_tree_json(&self) -> Option<String> {
8936        self.a11y.debug_tree_json()
8937    }
8938
8939    /// The accessibility tree built by the last frame, when one was built (see
8940    /// [`Self::is_a11y_active`] and [`Self::set_a11y_forced`]). Node ids are
8941    /// stable while the element identity is; bounds come from
8942    /// [`Self::a11y_node_bounds`].
8943    pub fn a11y_tree(&self) -> Option<&accesskit::TreeUpdate> {
8944        self.a11y.last_tree_update()
8945    }
8946
8947    /// Window-space bounds, in logical pixels, of a node in the last built tree.
8948    pub fn a11y_node_bounds(&self, node: accesskit::NodeId) -> Option<Bounds<Pixels>> {
8949        self.a11y.last_node_bounds(node)
8950    }
8951
8952    /// How many accessibility trees this window has built; zero before the
8953    /// first. Lets a caller tell a fresh tree from the one it already read.
8954    pub fn a11y_frame_number(&self) -> u64 {
8955        self.a11y.frame_number()
8956    }
8957
8958    /// Register a listener for an accessibility action on a specific node.
8959    /// The listener will be called when a screen reader requests the given
8960    /// action on the node identified by `node_id`.
8961    ///
8962    /// See the [accessibility guide](crate::_documentation::guides::accessibility) for an overview.
8963    pub fn on_a11y_action(
8964        &mut self,
8965        node_id: accesskit::NodeId,
8966        action: accesskit::Action,
8967        listener: impl FnMut(Option<&accesskit::ActionData>, &mut Window, &mut App) + 'static,
8968    ) {
8969        self.a11y
8970            .action_listeners
8971            .entry(node_id)
8972            .or_default()
8973            .push((action, Box::new(listener)));
8974    }
8975
8976    /// Perform an accessibility action on a node as assistive technology
8977    /// would: a registered [`Self::on_a11y_action`] listener first, else the
8978    /// built-in handling (`Click` synthesizes a pointer click at the node's
8979    /// bounds, `Focus` focuses it, `Blur` blurs the window).
8980    #[cfg(not(target_family = "wasm"))]
8981    pub fn perform_a11y_action(
8982        &mut self,
8983        target: accesskit::NodeId,
8984        action: accesskit::Action,
8985        data: Option<accesskit::ActionData>,
8986        cx: &mut App,
8987    ) {
8988        self.handle_a11y_action(
8989            accesskit::ActionRequest {
8990                action,
8991                target_tree: accesskit::TreeId::ROOT,
8992                target_node: target,
8993                data,
8994            },
8995            cx,
8996        );
8997    }
8998
8999    #[cfg(not(target_family = "wasm"))]
9000    pub(crate) fn handle_a11y_action(&mut self, request: accesskit::ActionRequest, cx: &mut App) {
9001        // Take listeners out temporarily so the closures can borrow Window
9002        // mutably, then restore them afterward.
9003        if let Some(mut listeners) = self.a11y.action_listeners.remove(&request.target_node) {
9004            let extra_data = request.data.as_ref();
9005            let mut matched = false;
9006            for (action, listener) in &mut listeners {
9007                if *action == request.action {
9008                    listener(extra_data, self, cx);
9009                    matched = true;
9010                }
9011            }
9012            self.a11y
9013                .action_listeners
9014                .insert(request.target_node, listeners);
9015            if matched {
9016                return;
9017            }
9018        }
9019
9020        // Fall back to built-in action handling.
9021        match request.action {
9022            accesskit::Action::Click => {
9023                if let Some(bounds) = self.a11y.node_bounds.get(&request.target_node).copied() {
9024                    let center = bounds.center();
9025                    let mouse_down = PlatformInput::MouseDown(crate::MouseDownEvent {
9026                        button: MouseButton::Left,
9027                        position: center,
9028                        modifiers: Modifiers::default(),
9029                        click_count: 1,
9030                        first_mouse: false,
9031                    });
9032                    let mouse_up = PlatformInput::MouseUp(MouseUpEvent {
9033                        button: MouseButton::Left,
9034                        position: center,
9035                        modifiers: Modifiers::default(),
9036                        click_count: 1,
9037                    });
9038                    self.dispatch_event(mouse_down, cx);
9039                    self.dispatch_event(mouse_up, cx);
9040                }
9041            }
9042            accesskit::Action::Focus => {
9043                if let Some(focus_id) = self.a11y.focus_ids.get(&request.target_node).copied()
9044                    && let Some(handle) = FocusHandle::for_id(focus_id, &cx.focus_handles)
9045                {
9046                    self.focus(&handle, cx);
9047                }
9048            }
9049            accesskit::Action::Blur => {
9050                self.blur(cx);
9051            }
9052            _ => {
9053                log::debug!(
9054                    "Unhandled a11y action: {:?} on {:?}",
9055                    request.action,
9056                    request.target_node
9057                );
9058            }
9059        }
9060    }
9061
9062    /// Turns the element inspector on or off for this window.
9063    ///
9064    /// While on, the window shows the inspector panel, and clicking an element in picking mode selects it.
9065    /// Available with the `inspector` feature or in debug builds.
9066    #[cfg(any(feature = "inspector", debug_assertions))]
9067    pub fn toggle_inspector(&mut self, cx: &mut App) {
9068        self.inspector = match self.inspector {
9069            None => Some(cx.new(|_| Inspector::new())),
9070            Some(_) => {
9071                self.rendered_frame.next_inspector_instance_ids = FxHashMap::default();
9072                self.rendered_frame.inspector_hitboxes = FxHashMap::default();
9073                self.next_frame.next_inspector_instance_ids = FxHashMap::default();
9074                self.next_frame.inspector_hitboxes = FxHashMap::default();
9075                None
9076            }
9077        };
9078        self.refresh();
9079    }
9080
9081    /// Returns whether the inspector is in picking mode, where clicks select elements instead of reaching them.
9082    pub fn is_inspector_picking(&self, _cx: &App) -> bool {
9083        #[cfg(any(feature = "inspector", debug_assertions))]
9084        {
9085            if let Some(inspector) = &self.inspector {
9086                return inspector.read(_cx).is_picking();
9087            }
9088        }
9089        false
9090    }
9091
9092    /// Runs `f` with mutable access to the inspector's state for the element `inspector_id`.
9093    ///
9094    /// The state is `Some` only for the element the inspector has selected. Otherwise `f` gets a
9095    /// temporary `None`. Element code uses it to expose its own state to the inspector.
9096    #[cfg(any(feature = "inspector", debug_assertions))]
9097    pub fn with_inspector_state<T: 'static, R>(
9098        &mut self,
9099        inspector_id: Option<&crate::InspectorElementId>,
9100        cx: &mut App,
9101        f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
9102    ) -> Option<R> {
9103        let inspector_id = inspector_id?;
9104        let inspector = self.inspector.as_ref()?;
9105        if inspector.read(cx).active_element_id() != Some(inspector_id) {
9106            return None;
9107        }
9108        let inspector = inspector.clone();
9109        Some(inspector.update(cx, |inspector, _cx| {
9110            inspector.with_active_element_state(self, f)
9111        }))
9112    }
9113
9114    #[cfg(any(feature = "inspector", debug_assertions))]
9115    pub(crate) fn inspector_enabled(&self) -> bool {
9116        self.inspector.is_some()
9117    }
9118
9119    #[cfg(any(feature = "inspector", debug_assertions))]
9120    pub(crate) fn build_inspector_element_id(
9121        &mut self,
9122        path: crate::InspectorElementPath,
9123    ) -> crate::InspectorElementId {
9124        self.invalidator.debug_assert_paint_or_prepaint();
9125        let path = Rc::new(path);
9126        let next_instance_id = self
9127            .next_frame
9128            .next_inspector_instance_ids
9129            .entry(path.clone())
9130            .or_insert(0);
9131        let instance_id = *next_instance_id;
9132        *next_instance_id += 1;
9133        crate::InspectorElementId { path, instance_id }
9134    }
9135
9136    #[cfg(any(feature = "inspector", debug_assertions))]
9137    fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option<AnyElement> {
9138        if let Some(inspector) = self.inspector.take() {
9139            let mut inspector_element = AnyView::from(inspector.clone()).into_any_element();
9140            inspector_element.prepaint_as_root(
9141                point(self.viewport_size.width - inspector_width, px(0.0)),
9142                size(inspector_width, self.viewport_size.height).into(),
9143                self,
9144                cx,
9145            );
9146            self.inspector = Some(inspector);
9147            Some(inspector_element)
9148        } else {
9149            None
9150        }
9151    }
9152
9153    #[cfg(any(feature = "inspector", debug_assertions))]
9154    fn paint_inspector(&mut self, mut inspector_element: Option<AnyElement>, cx: &mut App) {
9155        if let Some(mut inspector_element) = inspector_element {
9156            inspector_element.paint(self, cx);
9157        };
9158    }
9159
9160    /// Records `hitbox_id` as belonging to `inspector_id`, so picking mode can select that element.
9161    ///
9162    /// Does nothing unless the inspector is in picking mode. Call it during prepaint or paint, after
9163    /// inserting the hitbox.
9164    #[cfg(any(feature = "inspector", debug_assertions))]
9165    pub fn insert_inspector_hitbox(
9166        &mut self,
9167        hitbox_id: HitboxId,
9168        inspector_id: Option<&crate::InspectorElementId>,
9169        cx: &App,
9170    ) {
9171        self.invalidator.debug_assert_paint_or_prepaint();
9172        if !self.is_inspector_picking(cx) {
9173            return;
9174        }
9175        if let Some(inspector_id) = inspector_id {
9176            self.next_frame
9177                .inspector_hitboxes
9178                .insert(hitbox_id, inspector_id.clone());
9179        }
9180    }
9181
9182    #[cfg(any(feature = "inspector", debug_assertions))]
9183    fn paint_inspector_hitbox(&mut self, cx: &App) {
9184        if let Some(inspector) = self.inspector.as_ref() {
9185            let inspector = inspector.read(cx);
9186            if let Some((hitbox_id, _)) = self.hovered_inspector_hitbox(inspector, &self.next_frame)
9187                && let Some(hitbox) = self
9188                    .next_frame
9189                    .hitboxes
9190                    .iter()
9191                    .find(|hitbox| hitbox.id == hitbox_id)
9192            {
9193                self.paint_quad(PaintQuad::new(hitbox.bounds).background(crate::rgba(0x61afef4d)));
9194            }
9195        }
9196    }
9197
9198    #[cfg(any(feature = "inspector", debug_assertions))]
9199    fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
9200        let Some(inspector) = self.inspector.clone() else {
9201            return;
9202        };
9203        if event.downcast_ref::<MouseMoveEvent>().is_some() {
9204            inspector.update(cx, |inspector, _cx| {
9205                if let Some((_, inspector_id)) =
9206                    self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
9207                {
9208                    inspector.hover(inspector_id, self);
9209                }
9210            });
9211        } else if event.downcast_ref::<crate::MouseDownEvent>().is_some() {
9212            inspector.update(cx, |inspector, _cx| {
9213                if let Some((_, inspector_id)) =
9214                    self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
9215                {
9216                    inspector.select(inspector_id, self);
9217                }
9218            });
9219        } else if let Some(event) = event.downcast_ref::<crate::ScrollWheelEvent>() {
9220            // This should be kept in sync with SCROLL_LINES in x11 platform.
9221            const SCROLL_LINES: f32 = 3.0;
9222            const SCROLL_PIXELS_PER_LAYER: f32 = 36.0;
9223            let delta_y = event
9224                .delta
9225                .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES))
9226                .y;
9227            if let Some(inspector) = self.inspector.clone() {
9228                inspector.update(cx, |inspector, _cx| {
9229                    if let Some(depth) = inspector.pick_depth.as_mut() {
9230                        *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER;
9231                        let max_depth = self.mouse_hit_test.entries.len() as f32 - 0.5;
9232                        if *depth < 0.0 {
9233                            *depth = 0.0;
9234                        } else if *depth > max_depth {
9235                            *depth = max_depth;
9236                        }
9237                        if let Some((_, inspector_id)) =
9238                            self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
9239                        {
9240                            inspector.set_active_element_id(inspector_id, self);
9241                        }
9242                    }
9243                });
9244            }
9245        }
9246    }
9247
9248    #[cfg(any(feature = "inspector", debug_assertions))]
9249    fn hovered_inspector_hitbox(
9250        &self,
9251        inspector: &Inspector,
9252        frame: &Frame,
9253    ) -> Option<(HitboxId, crate::InspectorElementId)> {
9254        if let Some(pick_depth) = inspector.pick_depth {
9255            let depth = (pick_depth as i64).try_into().unwrap_or(0);
9256            let max_skipped = self.mouse_hit_test.entries.len().saturating_sub(1);
9257            let skip_count = (depth as usize).min(max_skipped);
9258            for hitbox_id in self.mouse_hit_test.ordered_ids.iter().skip(skip_count) {
9259                if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) {
9260                    return Some((*hitbox_id, inspector_id.clone()));
9261                }
9262            }
9263        }
9264        None
9265    }
9266
9267    /// Sets the modifier keys that the window reports, without sending an event.
9268    ///
9269    /// Tests use it to hold a key, such as Shift, while they simulate a click.
9270    #[cfg(any(test, feature = "test-support"))]
9271    pub fn set_modifiers(&mut self, modifiers: Modifiers) {
9272        self.modifiers = modifiers;
9273    }
9274
9275    /// Sends a mouse move to `position` through normal event dispatch, which updates hover state and tooltips.
9276    ///
9277    /// Use it in tests. It doesn't draw the window, so call `TestAppWindow::draw` first
9278    /// if the frame you're testing has not been drawn yet.
9279    #[cfg(any(test, feature = "test-support"))]
9280    pub fn simulate_mouse_move(&mut self, position: Point<Pixels>, cx: &mut App) {
9281        let event = PlatformInput::MouseMove(MouseMoveEvent {
9282            position,
9283            modifiers: self.modifiers,
9284            pressed_button: None,
9285        });
9286        let _ = self.dispatch_event(event, cx);
9287    }
9288
9289    #[inline(never)]
9290    fn take_element_state(
9291        &mut self,
9292        global_id: &GlobalElementId,
9293        state_type: TypeId,
9294    ) -> ((GlobalElementId, TypeId), Option<ElementStateBox>) {
9295        let key = (global_id.clone(), state_type);
9296        self.next_frame.accessed_element_states.push(key.clone());
9297        let state = self
9298            .next_frame
9299            .element_states
9300            .remove(&key)
9301            .or_else(|| self.rendered_frame.element_states.remove(&key));
9302        (key, state)
9303    }
9304
9305    #[inline(never)]
9306    fn insert_element_state(
9307        &mut self,
9308        key: (GlobalElementId, TypeId),
9309        state: ElementStateBox,
9310    ) -> Option<ElementStateBox> {
9311        self.next_frame.element_states.insert(key, state)
9312    }
9313
9314    #[inline(never)]
9315    fn observe_keyed_state<S: 'static>(state: &Entity<S>, current_view: EntityId, cx: &mut App) {
9316        cx.observe(state, move |_, cx| {
9317            cx.notify(current_view);
9318        })
9319        .detach();
9320    }
9321}
9322
9323// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
9324slotmap::new_key_type! {
9325    /// Identifies an open window. A stale id from a closed window never matches a newer one.
9326    pub struct WindowId;
9327}
9328
9329impl WindowId {
9330    /// Returns this id as a `u64`, which [`WindowId::from`] turns back into an id.
9331    pub fn as_u64(&self) -> u64 {
9332        self.0.as_ffi()
9333    }
9334}
9335
9336impl From<u64> for WindowId {
9337    fn from(value: u64) -> Self {
9338        WindowId(slotmap::KeyData::from_ffi(value))
9339    }
9340}
9341
9342/// A handle to an open window whose root view has type `V`.
9343///
9344/// Use it to read or update the window's root view from outside the window, such as from
9345/// another window or from a task. Handles don't keep the window open: if the window closes,
9346/// the methods return an error. Get one from `App::open_window`, or convert an
9347/// [`AnyWindowHandle`] with [`AnyWindowHandle::downcast`]. The handle derefs to
9348/// [`AnyWindowHandle`], so `window_id()` is available too.
9349///
9350/// # Examples
9351///
9352/// ```
9353/// # use gpui::{Context, IntoElement, Render, TestApp, Window, div, prelude::*};
9354/// struct Counter {
9355///     count: usize,
9356/// }
9357///
9358/// impl Render for Counter {
9359///     fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
9360///         div()
9361///     }
9362/// }
9363///
9364/// # let mut app = TestApp::new();
9365/// # let window = app.open_window(|_, _| Counter { count: 0 });
9366/// let handle = window.handle();
9367/// app.update(|cx| {
9368///     handle.update(cx, |counter, _, _| counter.count += 1).unwrap();
9369/// });
9370/// app.read(|cx| assert_eq!(handle.read(cx).unwrap().count, 1));
9371/// ```
9372#[derive(Deref, DerefMut)]
9373pub struct WindowHandle<V> {
9374    #[deref]
9375    #[deref_mut]
9376    pub(crate) any_handle: AnyWindowHandle,
9377    state_type: PhantomData<fn(V) -> V>,
9378}
9379
9380impl<V> Debug for WindowHandle<V> {
9381    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9382        f.debug_struct("WindowHandle")
9383            .field("any_handle", &self.any_handle.id.as_u64())
9384            .finish()
9385    }
9386}
9387
9388impl<V: 'static + Render> WindowHandle<V> {
9389    /// Creates a handle for the window with `id`, assuming its root view has type `V`.
9390    ///
9391    /// This does not check the live root. Reads and updates fail if its type does not match `V`.
9392    /// [`AnyWindowHandle::downcast`] checks the type recorded in that handle, which may be stale
9393    /// after [`Window::replace_root`].
9394    pub fn new(id: WindowId) -> Self {
9395        WindowHandle {
9396            any_handle: AnyWindowHandle {
9397                id,
9398                state_type: TypeId::of::<V>(),
9399                root_entity_type_name: std::any::type_name::<V>(),
9400            },
9401            state_type: PhantomData,
9402        }
9403    }
9404
9405    /// Returns the window's root view as an entity.
9406    ///
9407    /// # Errors
9408    ///
9409    /// Fails if the window is closed or if the root view's type no longer matches `V`.
9410    #[cfg(any(test, feature = "test-support"))]
9411    pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>
9412    where
9413        C: AppContext,
9414    {
9415        cx.update_window(self.any_handle, |root_view, _, _| {
9416            root_view
9417                .downcast::<V>()
9418                .map_err(|_| anyhow!("the type of the window's root view has changed"))
9419        })?
9420    }
9421
9422    /// Updates the root view, and gives `update` the window and a context for the view.
9423    ///
9424    /// Use it to change the view from outside the window. Calls to `notify` made in the update
9425    /// redraw the window on the next frame.
9426    ///
9427    /// # Errors
9428    ///
9429    /// Fails if the window is closed or if the root view's type no longer matches `V`.
9430    pub fn update<C, R>(
9431        &self,
9432        cx: &mut C,
9433        update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
9434    ) -> Result<R>
9435    where
9436        C: AppContext,
9437    {
9438        cx.update_window(self.any_handle, |root_view, window, cx| {
9439            let view = root_view
9440                .downcast::<V>()
9441                .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
9442
9443            Ok(view.update(cx, |view, cx| update(view, window, cx)))
9444        })?
9445    }
9446
9447    /// Returns a reference to the root view for reading.
9448    ///
9449    /// # Errors
9450    ///
9451    /// Fails if the window is closed or if the root view's type no longer matches `V`.
9452    pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {
9453        let x = cx
9454            .windows
9455            .get(self.id)
9456            .and_then(|window| {
9457                window
9458                    .as_deref()
9459                    .and_then(|window| window.root.clone())
9460                    .map(|root_view| root_view.downcast::<V>())
9461            })
9462            .context("window not found")?
9463            .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
9464
9465        Ok(x.read(cx))
9466    }
9467
9468    /// Passes the root view and the app to `read_with` and returns its result.
9469    ///
9470    /// # Errors
9471    ///
9472    /// Fails if the window is closed or if the root view's type no longer matches `V`.
9473    pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>
9474    where
9475        C: AppContext,
9476    {
9477        cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
9478    }
9479
9480    /// Returns the root view as an [`Entity`], which you can clone and keep.
9481    ///
9482    /// # Errors
9483    ///
9484    /// Fails if the window is closed or if the root view's type no longer matches `V`.
9485    pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>
9486    where
9487        C: AppContext,
9488    {
9489        cx.read_window(self, |root_view, _cx| root_view)
9490    }
9491
9492    /// Returns whether the window is active, or `None` if it is closed or currently borrowed.
9493    ///
9494    /// See [`Window::is_window_active`] for what counts as active.
9495    pub fn is_active(&self, cx: &mut App) -> Option<bool> {
9496        cx.update_window(self.any_handle, |_, window, _| window.is_window_active())
9497            .ok()
9498    }
9499}
9500
9501impl<V> Copy for WindowHandle<V> {}
9502
9503impl<V> Clone for WindowHandle<V> {
9504    fn clone(&self) -> Self {
9505        *self
9506    }
9507}
9508
9509impl<V> PartialEq for WindowHandle<V> {
9510    fn eq(&self, other: &Self) -> bool {
9511        self.any_handle == other.any_handle
9512    }
9513}
9514
9515impl<V> Eq for WindowHandle<V> {}
9516
9517impl<V> Hash for WindowHandle<V> {
9518    fn hash<H: Hasher>(&self, state: &mut H) {
9519        self.any_handle.hash(state);
9520    }
9521}
9522
9523impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
9524    fn from(val: WindowHandle<V>) -> Self {
9525        val.any_handle
9526    }
9527}
9528
9529/// A handle to an open window whose root view type isn't known at compile time.
9530///
9531/// Use it to store handles in collections or to find the window with a given id. Convert it to a
9532/// [`WindowHandle`] with [`AnyWindowHandle::downcast`] when you know the root type.
9533#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
9534pub struct AnyWindowHandle {
9535    pub(crate) id: WindowId,
9536    state_type: TypeId,
9537    root_entity_type_name: &'static str,
9538}
9539
9540impl AnyWindowHandle {
9541    /// Returns the [`WindowId`] of this window.
9542    pub fn window_id(&self) -> WindowId {
9543        self.id
9544    }
9545
9546    /// Returns the root type name recorded when this handle was created.
9547    ///
9548    /// This uses `std::any::type_name`. Replacing the window's root does not change the name
9549    /// stored in an existing handle.
9550    pub fn root_entity_type_name(&self) -> &'static str {
9551        self.root_entity_type_name
9552    }
9553
9554    /// Converts this handle to [`WindowHandle<T>`] if its recorded root type is `T`.
9555    ///
9556    /// This compares the stored type tag without querying the window. After
9557    /// [`Window::replace_root`], a successful downcast can still yield a handle whose reads and
9558    /// updates fail. Use [`AnyWindowHandle::update`] to inspect the live root instead.
9559    pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
9560        if TypeId::of::<T>() == self.state_type {
9561            Some(WindowHandle {
9562                any_handle: *self,
9563                state_type: PhantomData,
9564            })
9565        } else {
9566            None
9567        }
9568    }
9569
9570    /// Updates the state of the root view of this window.
9571    ///
9572    /// This will fail if the window has been closed.
9573    pub fn update<C, R>(
9574        self,
9575        cx: &mut C,
9576        update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
9577    ) -> Result<R>
9578    where
9579        C: AppContext,
9580    {
9581        cx.update_window(self, update)
9582    }
9583
9584    /// Read the state of the root view of this window.
9585    ///
9586    /// This will fail if the window has been closed.
9587    pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>
9588    where
9589        C: AppContext,
9590        T: 'static,
9591    {
9592        let view = self
9593            .downcast::<T>()
9594            .context("the type of the window's root view has changed")?;
9595
9596        cx.read_window(&view, read)
9597    }
9598}
9599
9600impl HasWindowHandle for Window {
9601    fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {
9602        self.platform_window.window_handle()
9603    }
9604}
9605
9606impl HasDisplayHandle for Window {
9607    fn display_handle(
9608        &self,
9609    ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, HandleError> {
9610        self.platform_window.display_handle()
9611    }
9612}
9613
9614/// Identifies an element across frames, so that its element state survives re-renders.
9615///
9616/// Elements that keep state, such as interactive elements and scroll containers, need an id.
9617/// Build one with `.into()` from a string, a number, a tuple such as `(row, 3)`, or a [`FocusHandle`]. An element's identity is its path of ids from the root, so an id only needs to be
9618/// unique among siblings. Use an id that identifies the element's content, such as a database id,
9619/// when the element can move within a list.
9620///
9621/// # Examples
9622///
9623/// ```
9624/// # use gpui::ElementId;
9625/// let save: ElementId = "save".into();
9626/// let row: ElementId = ("row", 3_usize).into();
9627/// assert_eq!(save.to_string(), "save");
9628/// assert_eq!(row.to_string(), "row-3");
9629/// ```
9630///
9631/// See [elements](crate::_documentation::concepts::elements) for how ids are used.
9632#[derive(Clone, Debug, Eq, PartialEq, Hash)]
9633pub enum ElementId {
9634    /// The id of a view, made from its [`EntityId`].
9635    View(EntityId),
9636    /// An integer id, such as a list index.
9637    Integer(u64),
9638    /// A string id.
9639    Name(SharedString),
9640    /// A UUID.
9641    Uuid(Uuid),
9642    /// The id of a focus handle, which keeps the element's focus state.
9643    FocusHandle(FocusId),
9644    /// A string and an integer, such as `("row", 3)`.
9645    NamedInteger(SharedString, u64),
9646    /// A file-system path.
9647    Path(Arc<std::path::Path>),
9648    /// A location in source code, captured with `#[track_caller]`.
9649    CodeLocation(core::panic::Location<'static>),
9650    /// A child of another id, labeled by a name, such as the `"close"` button of a tab.
9651    NamedChild(Arc<ElementId>, SharedString),
9652    /// A 20-byte opaque id, used for text anchors.
9653    OpaqueId([u8; 20]),
9654}
9655
9656impl ElementId {
9657    /// Returns an `ElementId::NamedInteger` made from `name` and `integer`.
9658    ///
9659    /// It is the same as `(name, integer).into()` for a `usize` integer.
9660    pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {
9661        Self::NamedInteger(name.into(), integer as u64)
9662    }
9663}
9664
9665impl Display for ElementId {
9666    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9667        match self {
9668            ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
9669            ElementId::Integer(ix) => write!(f, "{}", ix)?,
9670            ElementId::Name(name) => write!(f, "{}", name)?,
9671            ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
9672            ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
9673            ElementId::Uuid(uuid) => write!(f, "{}", uuid)?,
9674            ElementId::Path(path) => write!(f, "{}", path.display())?,
9675            ElementId::CodeLocation(location) => write!(f, "{}", location)?,
9676            ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?,
9677            ElementId::OpaqueId(opaque_id) => write!(f, "{:x?}", opaque_id)?,
9678        }
9679
9680        Ok(())
9681    }
9682}
9683
9684impl TryInto<SharedString> for ElementId {
9685    type Error = anyhow::Error;
9686
9687    fn try_into(self) -> anyhow::Result<SharedString> {
9688        if let ElementId::Name(name) = self {
9689            Ok(name)
9690        } else {
9691            anyhow::bail!("element id is not string")
9692        }
9693    }
9694}
9695
9696impl From<u64> for ElementId {
9697    fn from(id: u64) -> Self {
9698        ElementId::Integer(id)
9699    }
9700}
9701
9702impl From<usize> for ElementId {
9703    fn from(id: usize) -> Self {
9704        ElementId::Integer(id as u64)
9705    }
9706}
9707
9708impl From<i32> for ElementId {
9709    fn from(id: i32) -> Self {
9710        Self::Integer(id as u64)
9711    }
9712}
9713
9714impl From<SharedString> for ElementId {
9715    fn from(name: SharedString) -> Self {
9716        ElementId::Name(name)
9717    }
9718}
9719
9720impl From<String> for ElementId {
9721    fn from(name: String) -> Self {
9722        ElementId::Name(name.into())
9723    }
9724}
9725
9726impl From<Arc<str>> for ElementId {
9727    fn from(name: Arc<str>) -> Self {
9728        ElementId::Name(name.into())
9729    }
9730}
9731
9732impl From<Arc<std::path::Path>> for ElementId {
9733    fn from(path: Arc<std::path::Path>) -> Self {
9734        ElementId::Path(path)
9735    }
9736}
9737
9738impl From<&'static str> for ElementId {
9739    fn from(name: &'static str) -> Self {
9740        ElementId::Name(SharedString::new_static(name))
9741    }
9742}
9743
9744impl<'a> From<&'a FocusHandle> for ElementId {
9745    fn from(handle: &'a FocusHandle) -> Self {
9746        ElementId::FocusHandle(handle.id)
9747    }
9748}
9749
9750impl From<(&'static str, EntityId)> for ElementId {
9751    fn from((name, id): (&'static str, EntityId)) -> Self {
9752        ElementId::NamedInteger(SharedString::new_static(name), id.as_u64())
9753    }
9754}
9755
9756impl From<(&'static str, usize)> for ElementId {
9757    fn from((name, id): (&'static str, usize)) -> Self {
9758        ElementId::NamedInteger(SharedString::new_static(name), id as u64)
9759    }
9760}
9761
9762impl From<(SharedString, usize)> for ElementId {
9763    fn from((name, id): (SharedString, usize)) -> Self {
9764        ElementId::NamedInteger(name, id as u64)
9765    }
9766}
9767
9768impl From<(&'static str, u64)> for ElementId {
9769    fn from((name, id): (&'static str, u64)) -> Self {
9770        ElementId::NamedInteger(SharedString::new_static(name), id)
9771    }
9772}
9773
9774impl From<Uuid> for ElementId {
9775    fn from(value: Uuid) -> Self {
9776        Self::Uuid(value)
9777    }
9778}
9779
9780impl From<(&'static str, u32)> for ElementId {
9781    fn from((name, id): (&'static str, u32)) -> Self {
9782        ElementId::NamedInteger(SharedString::new_static(name), u64::from(id))
9783    }
9784}
9785
9786impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
9787    fn from((id, name): (ElementId, T)) -> Self {
9788        ElementId::NamedChild(Arc::new(id), name.into())
9789    }
9790}
9791
9792impl From<&'static core::panic::Location<'static>> for ElementId {
9793    fn from(location: &'static core::panic::Location<'static>) -> Self {
9794        ElementId::CodeLocation(*location)
9795    }
9796}
9797
9798impl From<[u8; 20]> for ElementId {
9799    fn from(opaque_id: [u8; 20]) -> Self {
9800        ElementId::OpaqueId(opaque_id)
9801    }
9802}
9803
9804/// A rectangle with a background and optional border, ready for [`Window::paint_quad`].
9805///
9806/// Build one with [`PaintQuad::new`], then set its background, border and corners with the
9807/// builder methods. Its fields are in logical pixels. It is painted into the active opacity group.
9808#[derive(Clone, derive_setters::Setters)]
9809#[setters(into, generate = false)]
9810pub struct PaintQuad {
9811    /// The bounds of the quad within the window.
9812    pub bounds: Bounds<Pixels>,
9813    /// The radii of the quad's corners.
9814    #[setters(generate)]
9815    pub corner_radii: Corners<Pixels>,
9816    /// Corner smoothing, from circular corners at `0.0` to maximum smoothing at `1.0`.
9817    pub corner_smoothing: f32,
9818    /// The background color of the quad.
9819    #[setters(generate)]
9820    pub background: Background,
9821    /// The widths of the quad's borders.
9822    #[setters(generate)]
9823    pub border_widths: Edges<Pixels>,
9824    /// The background painted into the quad's borders.
9825    #[setters(generate)]
9826    pub border_color: Background,
9827    /// The style of the quad's borders.
9828    #[setters(generate)]
9829    pub border_style: BorderStyle,
9830    /// The length of each border dash, as a multiple of the border width.
9831    pub border_dashed_length: f32,
9832    /// The gap between border dashes, as a multiple of the border width.
9833    pub border_dashed_gap: f32,
9834}
9835
9836impl PaintQuad {
9837    /// Creates a transparent quad with no border or rounded corners.
9838    pub fn new(bounds: impl Into<Bounds<Pixels>>) -> Self {
9839        Self {
9840            bounds: bounds.into(),
9841            corner_radii: (0.).into(),
9842            corner_smoothing: 0.0,
9843            background: transparent_black().into(),
9844            border_widths: (0.).into(),
9845            border_color: transparent_black().into(),
9846            border_style: BorderStyle::default(),
9847            border_dashed_length: crate::scene::DEFAULT_BORDER_DASHED_LENGTH,
9848            border_dashed_gap: crate::scene::DEFAULT_BORDER_DASHED_GAP,
9849        }
9850    }
9851
9852    /// Sets the corner smoothing, clamped to the range `0.0..=1.0`.
9853    pub fn corner_smoothing(self, amount: f32) -> Self {
9854        PaintQuad {
9855            corner_smoothing: amount.clamp(0.0, 1.0),
9856            ..self
9857        }
9858    }
9859
9860    /// Returns this quad with dashes of `length_per_border_width` times the border width.
9861    ///
9862    /// Only used when `border_style` is [`BorderStyle::Dashed`].
9863    pub fn border_dashed_length(self, length_per_border_width: f32) -> Self {
9864        PaintQuad {
9865            border_dashed_length: length_per_border_width.max(0.0),
9866            ..self
9867        }
9868    }
9869
9870    /// Returns this quad with gaps of `gap_per_border_width` times the border width between dashes.
9871    ///
9872    /// Only used when `border_style` is [`BorderStyle::Dashed`].
9873    pub fn border_dashed_gap(self, gap_per_border_width: f32) -> Self {
9874        PaintQuad {
9875            border_dashed_gap: gap_per_border_width.max(0.0),
9876            ..self
9877        }
9878    }
9879}
9880
9881/// Returns a quad with bounds, radii, background, border widths, border color and border style.
9882///
9883/// Use fill or outline when you need only some properties. Radii larger than bounds produce sharp
9884/// corners where the arcs meet; clamp radii when that is not wanted.
9885#[deprecated(note = "replaced with builder syntax for PaintQuad")]
9886pub fn quad(
9887    bounds: Bounds<Pixels>,
9888    corner_radii: impl Into<Corners<Pixels>>,
9889    background: impl Into<Background>,
9890    border_widths: impl Into<Edges<Pixels>>,
9891    border_color: impl Into<Background>,
9892    border_style: BorderStyle,
9893) -> PaintQuad {
9894    PaintQuad::new(bounds)
9895        .corner_radii(corner_radii)
9896        .background(background)
9897        .border_widths(border_widths)
9898        .border_color(border_color)
9899        .border_style(border_style)
9900}
9901
9902/// Returns a filled quad with no border and no corner radius.
9903#[deprecated(note = "replaced with builder syntax for PaintQuad")]
9904pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
9905    PaintQuad::new(bounds).background(background)
9906}
9907
9908/// Returns a transparent quad with a 1px border and the given border style.
9909#[deprecated(note = "replaced with builder syntax for PaintQuad")]
9910pub fn outline(
9911    bounds: impl Into<Bounds<Pixels>>,
9912    border_color: impl Into<Background>,
9913    border_style: BorderStyle,
9914) -> PaintQuad {
9915    PaintQuad::new(bounds)
9916        .border_widths(1f32)
9917        .border_color(border_color)
9918        .border_style(border_style)
9919}
9920
9921#[inline(never)]
9922fn with_element_arena_erased(callback: &mut dyn FnMut(&mut Arena)) -> Result<(), AccessError> {
9923    if let Some(arena_pointer) = CURRENT_ELEMENT_ARENA.try_with(Cell::get)? {
9924        // SAFETY: The pointer is valid for the duration of the draw operation
9925        // that set it, and we're being called during that same draw.
9926        let arena_cell = unsafe { &*arena_pointer };
9927        callback(&mut arena_cell.borrow_mut());
9928        Ok(())
9929    } else {
9930        ELEMENT_ARENA.try_with(|arena| callback(&mut arena.borrow_mut()))
9931    }
9932}
9933
9934#[cfg(test)]
9935mod pointer_tests;
9936
9937#[cfg(test)]
9938mod tests {
9939    use super::*;
9940    use crate::util::FluentBuilder;
9941    use crate::{
9942        AnyWindowHandle, Bounds, ColorExt, ContentMask, Context, DispatchPhase, DragMoveEvent,
9943        Empty, ExternalDragPayload, ExternalPaths, FileDragPaths, FileDropEvent, FocusHandle, Font,
9944        FontMetrics, ImageSource, InlineLayout, InlineLayoutRequest, InputEvent,
9945        InteractiveElement, IntoElement, KeyDownEvent, Keystroke, LineLayout, LongPressEvent,
9946        MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, PlatformInput,
9947        PlatformTextSystem, Point, PreparedRasterStyle, RasterColorEffect, RasterStyleRequest,
9948        RasterizedGlyph, Render, RequestFrameOptions, ScaledPixels, ShaderBool,
9949        StatefulInteractiveElement, Styled, TestApp, TestAppContext, TestTextSystem,
9950        TextLayoutRequest, TouchDragEvent, TouchEvent, TouchId, TouchPhase, Underline,
9951        UnderlineStyle, Window, WindowAppearance, WindowOptions, canvas, div, hsla, img,
9952        linear_color_stop, linear_gradient, point, px, size,
9953    };
9954    use image::{Frame as ImageFrame, ImageBuffer, Rgba};
9955    use proptest::prelude::*;
9956    use smallvec::smallvec;
9957    use std::{path::PathBuf, sync::Mutex as StdMutex};
9958
9959    #[test]
9960    fn hit_test_preserves_inline_regions_occlusion_and_metadata() {
9961        let bounds = Bounds::new(Point::default(), size(px(100.), px(80.)));
9962        let background = Hitbox {
9963            id: HitboxId(1),
9964            bounds,
9965            content_mask: ContentMask {
9966                bounds,
9967                ..Default::default()
9968            },
9969            behavior: HitboxBehavior::Normal,
9970            tags: vec!["background".into()],
9971            fragments: None,
9972        };
9973        let mut inline = Hitbox {
9974            id: HitboxId(2),
9975            bounds,
9976            content_mask: ContentMask {
9977                bounds: Bounds::new(Point::default(), size(px(80.), px(80.))),
9978                ..Default::default()
9979            },
9980            behavior: HitboxBehavior::Normal,
9981            tags: vec!["inline".into()],
9982            fragments: Some(Arc::from([
9983                Bounds::new(point(px(60.), px(0.)), size(px(40.), px(40.))),
9984                Bounds::new(point(px(0.), px(40.)), size(px(40.), px(40.))),
9985            ])),
9986        };
9987
9988        for behavior in [
9989            HitboxBehavior::Normal,
9990            HitboxBehavior::BlockMouseExceptScroll,
9991            HitboxBehavior::BlockMouse,
9992        ] {
9993            inline.behavior = behavior;
9994
9995            for (position, inside_inline, inside_background) in [
9996                (point(px(70.), px(20.)), true, true),
9997                (point(px(20.), px(60.)), true, true),
9998                (point(px(20.), px(20.)), false, true),
9999                (point(px(90.), px(20.)), false, true),
10000                (point(px(120.), px(20.)), false, false),
10001            ] {
10002                let hit_test = HitTest::new([&inline, &background].into_iter(), position);
10003                let mut hovered = Vec::new();
10004                let mut scrollable = Vec::new();
10005
10006                if inside_inline {
10007                    hovered.push(inline.id);
10008                    scrollable.push(inline.id);
10009                }
10010
10011                if inside_background && (!inside_inline || behavior == HitboxBehavior::Normal) {
10012                    hovered.push(background.id);
10013                }
10014
10015                if inside_background && (!inside_inline || behavior != HitboxBehavior::BlockMouse) {
10016                    scrollable.push(background.id);
10017                }
10018
10019                assert_eq!(
10020                    hit_test.iter_hovered().copied().collect::<Vec<_>>(),
10021                    hovered
10022                );
10023                assert_eq!(
10024                    hit_test.iter_scrollable().copied().collect::<Vec<_>>(),
10025                    scrollable
10026                );
10027
10028                for (depth, hitbox) in [&inline, &background].into_iter().enumerate() {
10029                    let entry = hit_test.entry(&hitbox.id).unwrap();
10030                    assert_eq!(entry.depth(), depth);
10031                    assert_eq!(entry.tags(), &hitbox.tags);
10032                }
10033            }
10034        }
10035    }
10036
10037    proptest! {
10038        #[test]
10039        fn glyph_origin_quantization_preserves_position_with_bounded_error(
10040            x in -10_000.0f32..10_000.0,
10041            y in -10_000.0f32..10_000.0,
10042        ) {
10043            let (integer, variant) =
10044                quantize_glyph_origin(point(ScaledPixels(x), ScaledPixels(y)));
10045            let reconstructed_x =
10046                integer.x.0 + f32::from(variant.x) / f32::from(SUBPIXEL_VARIANTS_X);
10047            let reconstructed_y =
10048                integer.y.0 + f32::from(variant.y) / f32::from(SUBPIXEL_VARIANTS_Y);
10049            let maximum_error_x = 0.5 / f32::from(SUBPIXEL_VARIANTS_X) + 0.001;
10050            let maximum_error_y = 0.5 / f32::from(SUBPIXEL_VARIANTS_Y) + 0.001;
10051
10052            prop_assert!(variant.x < SUBPIXEL_VARIANTS_X);
10053            prop_assert!(variant.y < SUBPIXEL_VARIANTS_Y);
10054            prop_assert_eq!(variant.y, 0, "vertical glyph variants change baseline snapping");
10055            prop_assert!((reconstructed_x - x).abs() <= maximum_error_x);
10056            prop_assert!((reconstructed_y - y).abs() <= maximum_error_y);
10057
10058            let (color_origin, color_variant) =
10059                quantize_color_glyph_origin(point(ScaledPixels(x), ScaledPixels(y)));
10060            prop_assert_eq!(color_variant, Point::default());
10061            prop_assert!((color_origin.x.0 - x).abs() <= 0.501);
10062            prop_assert!((color_origin.y.0 - y).abs() <= 0.501);
10063        }
10064    }
10065
10066    #[derive(Default)]
10067    struct RasterFormatTextSystem {
10068        rasterized: StdMutex<Vec<RenderGlyphParams>>,
10069        fail_next: AtomicBool,
10070    }
10071
10072    impl PlatformTextSystem for RasterFormatTextSystem {
10073        fn add_fonts(&self, _fonts: Vec<Cow<'static, [u8]>>) -> anyhow::Result<()> {
10074            Ok(())
10075        }
10076
10077        fn all_font_names(&self) -> Vec<String> {
10078            Vec::new()
10079        }
10080
10081        fn font_id(&self, descriptor: &Font) -> anyhow::Result<FontId> {
10082            PlatformTextSystem::font_id(&TestTextSystem, descriptor)
10083        }
10084
10085        fn font_metrics(&self, font_id: FontId) -> FontMetrics {
10086            PlatformTextSystem::font_metrics(&TestTextSystem, font_id)
10087        }
10088
10089        fn typographic_bounds(
10090            &self,
10091            font_id: FontId,
10092            glyph_id: GlyphId,
10093        ) -> anyhow::Result<Bounds<f32>> {
10094            PlatformTextSystem::typographic_bounds(&TestTextSystem, font_id, glyph_id)
10095        }
10096
10097        fn advance(&self, font_id: FontId, glyph_id: GlyphId) -> anyhow::Result<Size<f32>> {
10098            PlatformTextSystem::advance(&TestTextSystem, font_id, glyph_id)
10099        }
10100
10101        fn glyph_for_char(&self, font_id: FontId, character: char) -> Option<GlyphId> {
10102            PlatformTextSystem::glyph_for_char(&TestTextSystem, font_id, character)
10103        }
10104
10105        fn rasterize_glyph(&self, params: &RenderGlyphParams) -> anyhow::Result<RasterizedGlyph> {
10106            self.rasterized.lock().unwrap().push(params.clone());
10107            if self.fail_next.swap(false, SeqCst) {
10108                anyhow::bail!("injected glyph rasterization failure");
10109            }
10110
10111            let (format, pixels) = match params.glyph_id.0 {
10112                1 => (RasterizedGlyphFormat::AlphaMask, vec![0, 255]),
10113                2 => (
10114                    RasterizedGlyphFormat::BgraSubpixelMask,
10115                    vec![1, 2, 3, 0, 4, 5, 6, 0],
10116                ),
10117                3 | 5 => (
10118                    RasterizedGlyphFormat::BgraColor,
10119                    vec![10, 20, 30, 128, 40, 50, 60, 255],
10120                ),
10121                node_id => anyhow::bail!("unexpected scripted glyph {node_id}"),
10122            };
10123            let size = size(DevicePixels(2), DevicePixels(1));
10124            Ok(RasterizedGlyph {
10125                bounds: Bounds {
10126                    origin: point(DevicePixels(-1), DevicePixels(-2)),
10127                    size,
10128                },
10129                size,
10130                format,
10131                pixels,
10132            })
10133        }
10134
10135        fn prepare_raster_style(&self, mut request: RasterStyleRequest) -> PreparedRasterStyle {
10136            if request.requested_mode == GlyphRenderMode::Color {
10137                request.foreground_dependency = match request.glyph_id {
10138                    GlyphId(3) => crate::ForegroundDependency::AlphaOnly,
10139                    _glyph_id => request.foreground_dependency,
10140                };
10141
10142                PreparedRasterStyle::preblend(request)
10143            } else {
10144                PreparedRasterStyle::independent(request.requested_mode)
10145            }
10146        }
10147
10148        fn layout_text(&self, request: TextLayoutRequest<'_>) -> LineLayout {
10149            PlatformTextSystem::layout_text(&TestTextSystem, request)
10150        }
10151
10152        fn layout_inline(&self, request: InlineLayoutRequest<'_>) -> InlineLayout {
10153            PlatformTextSystem::layout_inline(&TestTextSystem, request)
10154        }
10155    }
10156
10157    struct RasterFormatView;
10158
10159    impl Render for RasterFormatView {
10160        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10161            let color = hsla(0.6, 0.7, 0.4, 0.8);
10162            let alternate_color = hsla(0.1, 0.6, 0.3, 0.8);
10163            div().size_full().opacity(0.5).child(
10164                canvas(
10165                    |_, _, _| (),
10166                    move |_, _, window, _| {
10167                        for (index, glyph_id) in [GlyphId(1), GlyphId(2)].into_iter().enumerate() {
10168                            let offset = px(index as f32 * 5.0);
10169                            let mut origin = point(px(5.0) + offset, px(10.0) + offset);
10170
10171                            if index == 0 {
10172                                origin += point(px(0.13), px(0.245));
10173                            }
10174
10175                            window
10176                                .paint_glyph(origin, FontId(7), glyph_id, px(16.0), color)
10177                                .unwrap();
10178                        }
10179
10180                        let mut index = 0;
10181
10182                        for glyph_id in [GlyphId(3), GlyphId(5)] {
10183                            for foreground in [color, alternate_color] {
10184                                let offset = px(index as f32 * 5.0);
10185                                let origin = point(px(15.0) + offset, px(20.0) + offset);
10186
10187                                window
10188                                    .paint_emoji_with_color(
10189                                        origin,
10190                                        FontId(7),
10191                                        glyph_id,
10192                                        px(16.0),
10193                                        foreground,
10194                                    )
10195                                    .unwrap();
10196                                index += 1;
10197                            }
10198                        }
10199                    },
10200                )
10201                .size_full(),
10202            )
10203        }
10204    }
10205
10206    #[test]
10207    fn returned_raster_format_drives_atlas_and_scene_behavior() {
10208        let text_system = Arc::new(RasterFormatTextSystem::default());
10209        let mut app = TestApp::with_text_system(text_system.clone());
10210        let mut test_window = app.open_window(|_, _| RasterFormatView);
10211        test_window.draw();
10212
10213        test_window.update(|_, window, _| {
10214            assert_eq!(window.rendered_primitive_counts(), (0, 2, 0, 4));
10215            let scene = &window.rendered_frame.scene;
10216            let expected_color = hsla(0.6, 0.7, 0.4, 0.8).into();
10217
10218            assert_eq!(scene.monochrome_sprites[0].color, expected_color);
10219            assert_eq!(scene.monochrome_sprites[1].color, expected_color);
10220            assert!(
10221                scene
10222                    .polychrome_sprites
10223                    .iter()
10224                    .all(|sprite| sprite.opacity == 1.0)
10225            );
10226            assert_eq!(
10227                scene.monochrome_sprites[0].bounds.origin,
10228                point(ScaledPixels(9.0), ScaledPixels(18.0))
10229            );
10230            assert_eq!(
10231                scene.monochrome_sprites[0].tile.texture_id.kind,
10232                crate::AtlasTextureKind::Monochrome
10233            );
10234            assert_eq!(
10235                scene.monochrome_sprites[1].tile.texture_id.kind,
10236                crate::AtlasTextureKind::Subpixel
10237            );
10238            assert_eq!(
10239                scene.polychrome_sprites[0].tile.texture_id.kind,
10240                crate::AtlasTextureKind::Polychrome
10241            );
10242            let first_tile = scene.polychrome_sprites[0].tile;
10243            let second_tile = scene.polychrome_sprites[1].tile;
10244            let third_tile = scene.polychrome_sprites[2].tile;
10245            let fourth_tile = scene.polychrome_sprites[3].tile;
10246            assert_eq!(first_tile, second_tile);
10247            assert_ne!(third_tile, fourth_tile);
10248        });
10249
10250        let rasterized = text_system.rasterized.lock().unwrap();
10251        let color_styles = rasterized
10252            .iter()
10253            .filter(|params| params.raster_style.mode == GlyphRenderMode::Color)
10254            .map(|params| params.raster_style.color_effect)
10255            .collect::<Vec<_>>();
10256        assert_eq!(
10257            color_styles,
10258            [
10259                RasterColorEffect::Preblend(crate::Rgba8::new(0, 0, 0, 204)),
10260                RasterColorEffect::Preblend(crate::Rgba8::new(31, 88, 173, 204)),
10261                RasterColorEffect::Preblend(crate::Rgba8::new(122, 86, 31, 204)),
10262            ]
10263        );
10264    }
10265
10266    struct FragmentFailureView;
10267
10268    impl Render for FragmentFailureView {
10269        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10270            div().size_full().child("x😀")
10271        }
10272    }
10273
10274    #[test]
10275    fn a_failed_glyph_does_not_hide_the_rest_of_its_fragment() {
10276        let text_system = Arc::new(RasterFormatTextSystem {
10277            rasterized: StdMutex::default(),
10278            fail_next: AtomicBool::new(true),
10279        });
10280        let mut app = TestApp::with_text_system(text_system.clone());
10281        let mut test_window = app.open_window(|_, _| FragmentFailureView);
10282        test_window.draw();
10283
10284        test_window.update(|_, window, _| {
10285            assert!(!window.rendered_frame.scene.subpixel_sprites.is_empty());
10286        });
10287
10288        let glyph_ids = text_system
10289            .rasterized
10290            .lock()
10291            .unwrap()
10292            .iter()
10293            .map(|params| params.glyph_id)
10294            .collect::<Vec<_>>();
10295        assert!(
10296            glyph_ids.starts_with(&[GlyphId(1), GlyphId(2)]),
10297            "unexpected rasterization sequence: {glyph_ids:?}"
10298        );
10299    }
10300
10301    #[gpui::test]
10302    async fn test_focus_handle_release(cx: &mut TestAppContext) {
10303        let (handle, survivor) = cx.update(|cx| (cx.focus_handle(), cx.focus_handle()));
10304        let handle_id = handle.id;
10305        let weak_handle = handle.downgrade();
10306        let retained = handle.clone();
10307        drop(handle);
10308
10309        cx.update(|_| {});
10310        cx.read(|cx| {
10311            let handles = cx.focus_handles.read();
10312            assert_eq!(handles.handles.len(), 2);
10313            assert!(handles.dropped_handles.is_empty());
10314        });
10315        assert_eq!(weak_handle.upgrade().as_ref(), Some(&retained));
10316
10317        cx.background_spawn(async move { drop(retained) }).await;
10318        assert_eq!(weak_handle.upgrade(), None);
10319        cx.read(|cx| {
10320            assert_eq!(cx.focus_handles.read().dropped_handles, [handle_id]);
10321        });
10322        cx.update(|_| {});
10323        cx.read(|cx| {
10324            let handles = cx.focus_handles.read();
10325            assert_eq!(handles.handles.keys().collect::<Vec<_>>(), [survivor.id]);
10326            assert!(handles.dropped_handles.is_empty());
10327        });
10328
10329        let replacements = cx.update(|cx| [cx.focus_handle(), cx.focus_handle()]);
10330        assert_eq!(weak_handle.upgrade(), None);
10331        cx.update(|cx| {
10332            drop(replacements);
10333            cx.defer(move |_| drop(survivor));
10334        });
10335        cx.read(|cx| {
10336            let handles = cx.focus_handles.read();
10337            assert_eq!(handles.handles.len(), 0);
10338            assert!(handles.dropped_handles.is_empty());
10339        });
10340    }
10341
10342    #[gpui::test]
10343    fn test_dropped_focus_handle_blurs_only_its_windows(cx: &mut TestAppContext) {
10344        let windows = [
10345            cx.add_window(|_, _| EmptyView),
10346            cx.add_window(|_, _| EmptyView),
10347            cx.add_window(|_, _| EmptyView),
10348            cx.add_window(|_, _| EmptyView),
10349            cx.add_window(|_, _| EmptyView),
10350        ];
10351        let (handle, other_handle, survivor) =
10352            cx.update(|cx| (cx.focus_handle(), cx.focus_handle(), cx.focus_handle()));
10353        for window in &windows[..2] {
10354            window
10355                .update(cx, |_, window, cx| window.focus(&handle, cx))
10356                .expect("window exists");
10357        }
10358        windows[2]
10359            .update(cx, |_, window, cx| window.focus(&other_handle, cx))
10360            .expect("window exists");
10361        windows[3]
10362            .update(cx, |_, window, cx| window.focus(&survivor, cx))
10363            .expect("window exists");
10364
10365        cx.update(|cx| {
10366            for _ in 0..1_000 {
10367                drop(cx.focus_handle());
10368            }
10369            drop((handle, other_handle));
10370        });
10371        for window in &windows[..3] {
10372            window
10373                .update(cx, |_, window, _| assert_eq!(window.focus, None))
10374                .expect("window exists");
10375        }
10376        windows[3]
10377            .update(cx, |_, window, cx| {
10378                assert_eq!(window.focused(cx).as_ref(), Some(&survivor));
10379                assert_eq!(window.focus_generation, 1);
10380            })
10381            .expect("window exists");
10382        windows[4]
10383            .update(cx, |_, window, _| {
10384                assert_eq!(window.focus, None);
10385                assert_eq!(window.focus_generation, 0);
10386            })
10387            .expect("window exists");
10388    }
10389
10390    #[cfg(feature = "profiler")]
10391    #[gpui::test]
10392    fn test_frame_requests_and_skips_are_journaled(cx: &mut TestAppContext) {
10393        use crate::FrameRequestSource;
10394        use crate::profiler::journal::{
10395            self, ForegroundJournalEntry, FrameSkipReason, IntervalBoundary,
10396        };
10397        use scheduler::Instant;
10398
10399        cx.app.borrow_mut().mode = crate::app::GpuiMode::Production;
10400        let window = cx.add_window(|_, _| EmptyView);
10401        let platform_window = cx.test_window(window.into());
10402        platform_window.simulate_frame_request(RequestFrameOptions::default());
10403        let (journal, _guard) = journal::install_test_foreground_journal(64, 4);
10404        let mut collector = journal.collector();
10405
10406        for (signal_at, source) in [
10407            (Some(Instant::now()), FrameRequestSource::NativeCallback),
10408            (Some(Instant::now()), FrameRequestSource::LocalSchedule),
10409            (None, FrameRequestSource::NativeCallback),
10410        ] {
10411            platform_window.simulate_frame_request(RequestFrameOptions {
10412                signal_at,
10413                signal_source: source,
10414                require_presentation: true,
10415                ..Default::default()
10416            });
10417            let entries = collector.collect_unseen().entries;
10418            let signal_index = entries
10419                .iter()
10420                .position(|entry| {
10421                    matches!(
10422                        entry,
10423                        ForegroundJournalEntry::PlatformSignal(signal)
10424                            if signal.window_id == window.window_id()
10425                                && signal.signal_at == signal_at
10426                                && signal.source == source
10427                                && signal_at.is_none_or(|at| signal.handled_at >= at)
10428                    )
10429                })
10430                .expect("frame request metadata");
10431            let skip_index = entries
10432                .iter()
10433                .position(|entry| {
10434                    matches!(
10435                        entry,
10436                        ForegroundJournalEntry::Boundary(IntervalBoundary::FrameSkipped(skipped))
10437                            if skipped.window_id == window.window_id()
10438                                && skipped.reason == FrameSkipReason::NoRenderNeeded
10439                    )
10440                })
10441                .expect("completed no-render boundary");
10442            assert!(signal_index < skip_index);
10443        }
10444    }
10445
10446    #[cfg(feature = "profiler")]
10447    #[gpui::test]
10448    fn test_frame_demand_survives_throttling(cx: &mut TestAppContext) {
10449        use crate::profiler::journal::{
10450            self, ForegroundJournalEntry, FrameSkipReason, IntervalBoundary,
10451        };
10452        use scheduler::Instant;
10453
10454        // Test mode draws during effect flushing, bypassing platform frame throttling.
10455        cx.app.borrow_mut().mode = crate::app::GpuiMode::Production;
10456        let (journal, _guard) = journal::install_test_foreground_journal(256, 4);
10457        let mut collector = journal.collector();
10458        for initially_dirty in [true, false] {
10459            // Keep the throttle closed without depending on short wall-clock deadlines.
10460            let window = cx
10461                .app
10462                .borrow_mut()
10463                .open_window(
10464                    WindowOptions {
10465                        inactive_frame_interval: Some(Duration::from_secs(3600)),
10466                        ..Default::default()
10467                    },
10468                    |_, cx| cx.new(|_| EmptyView),
10469                )
10470                .expect("open inactive test window");
10471            let platform_window = cx.test_window(window.into());
10472            platform_window.simulate_active_status_change(false);
10473            platform_window.simulate_frame_request(RequestFrameOptions::default());
10474            let callback_ran = Rc::new(Cell::new(false));
10475            let draws_before = window
10476                .update(cx, |_, window, _| {
10477                    let draws_before = window
10478                        .frame_duration_snapshot()
10479                        .draw_duration_histogram
10480                        .len();
10481                    if initially_dirty {
10482                        window.refresh();
10483                    }
10484                    window.on_next_frame({
10485                        let callback_ran = callback_ran.clone();
10486                        move |window, _| {
10487                            callback_ran.set(true);
10488                            window.refresh();
10489                        }
10490                    });
10491                    draws_before
10492                })
10493                .expect("schedule throttled frame");
10494            // Skips only seal retained work, so give the throttled skip some.
10495            let input_at = Instant::now();
10496            journal::record_input(journal::InputTiming {
10497                kind: "test",
10498                start: input_at,
10499                end: input_at,
10500                caused_invalidation: false,
10501            });
10502            collector.collect_unseen();
10503            platform_window.simulate_frame_request(RequestFrameOptions {
10504                signal_at: Some(Instant::now()),
10505                ..Default::default()
10506            });
10507            window
10508                .update(cx, |_, window, _| {
10509                    assert_eq!(
10510                        window
10511                            .frame_duration_snapshot()
10512                            .draw_duration_histogram
10513                            .len(),
10514                        draws_before,
10515                    );
10516                })
10517                .expect("inspect deferred frame");
10518            assert!(!callback_ran.get());
10519            assert!(collector.collect_unseen().entries.iter().any(|entry| {
10520                matches!(
10521                    entry,
10522                    ForegroundJournalEntry::Boundary(IntervalBoundary::FrameSkipped(skipped))
10523                        if skipped.window_id == window.window_id()
10524                            && skipped.reason == FrameSkipReason::InactiveFrameRateLimit
10525                )
10526            }));
10527            platform_window.simulate_frame_request(RequestFrameOptions {
10528                signal_at: Some(Instant::now()),
10529                require_presentation: true,
10530                ..Default::default()
10531            });
10532            window
10533                .update(cx, |_, window, _| {
10534                    assert_eq!(
10535                        window
10536                            .frame_duration_snapshot()
10537                            .draw_duration_histogram
10538                            .len(),
10539                        draws_before + 1,
10540                    );
10541                })
10542                .expect("inspect presented frame");
10543            assert!(callback_ran.get());
10544        }
10545    }
10546
10547    /// Visibility transitions reach observers exactly once each, with the new
10548    /// state already stored on the window, and never wake the platform for a
10549    /// frame: the platform requests one itself when it resumes presenting.
10550    #[gpui::test]
10551    fn test_window_visibility(cx: &mut TestAppContext) {
10552        use crate::WindowVisibility;
10553
10554        let window = cx.add_window(|_, _| EmptyView);
10555        let observed = Rc::new(RefCell::new(Vec::new()));
10556        let _subscription = window
10557            .update(cx, {
10558                let observed = observed.clone();
10559                move |_, window, _| {
10560                    assert_eq!(window.visibility(), WindowVisibility::Visible);
10561                    assert!(window.is_visible());
10562                    window.observe_window_visibility(move |visibility, window, _| {
10563                        assert_eq!(window.visibility(), visibility);
10564                        observed.borrow_mut().push(visibility);
10565                    })
10566                }
10567            })
10568            .unwrap();
10569        let test_window = cx.test_window(window.into());
10570        let frame_wake_count = test_window.frame_wake_count();
10571
10572        test_window.simulate_visibility_change(WindowVisibility::Hidden);
10573        assert_eq!(*observed.borrow(), [WindowVisibility::Hidden]);
10574        window
10575            .update(cx, |_, window, _| assert!(!window.is_visible()))
10576            .unwrap();
10577
10578        // Platforms may report the same state again; observers only see changes.
10579        test_window.simulate_visibility_change(WindowVisibility::Hidden);
10580        assert_eq!(observed.borrow().len(), 1);
10581
10582        test_window.simulate_visibility_change(WindowVisibility::Visible);
10583        assert_eq!(
10584            *observed.borrow(),
10585            [WindowVisibility::Hidden, WindowVisibility::Visible]
10586        );
10587        window
10588            .update(cx, |_, window, _| assert!(window.is_visible()))
10589            .unwrap();
10590        assert_eq!(test_window.frame_wake_count(), frame_wake_count);
10591    }
10592
10593    /// App learns display state from the platform's display notifications,
10594    /// and a window from the platform's report of which display it is on.
10595    #[gpui::test]
10596    fn test_display_tracking(cx: &mut TestAppContext) {
10597        use crate::{DisplayChanges, DisplayEvent, DisplayId, Subscription};
10598
10599        let sixty_hertz = Duration::from_secs(1) / 60;
10600        let one_hundred_twenty_hertz = Duration::from_secs(1) / 120;
10601        let one_hundred_forty_four_hertz = Duration::from_secs(1) / 144;
10602
10603        let display_events = Rc::new(RefCell::new(Vec::new()));
10604        let _display_subscription = cx.update({
10605            let display_events = display_events.clone();
10606            move |cx| cx.observe_displays(move |event, _| display_events.borrow_mut().push(event))
10607        });
10608
10609        let window = cx.add_window(|window, cx| DisplayTracker {
10610            refresh_intervals: Vec::new(),
10611            _subscription: cx.observe_window_display(
10612                window,
10613                |tracker: &mut DisplayTracker, window, cx| {
10614                    tracker.refresh_intervals.push(window.refresh_interval(cx));
10615                },
10616            ),
10617        });
10618        let window_notifications = Rc::new(RefCell::new(Vec::new()));
10619        let _window_subscription = window
10620            .update(cx, {
10621                let window_notifications = window_notifications.clone();
10622                move |_, window, cx| {
10623                    assert_eq!(window.refresh_interval(cx), Some(sixty_hertz));
10624                    window.observe_window_display(move |window, cx| {
10625                        window_notifications
10626                            .borrow_mut()
10627                            .push((window.display_id, window.refresh_interval(cx)));
10628                    })
10629                }
10630            })
10631            .unwrap();
10632        let test_window = cx.test_window(window.into());
10633
10634        // The window may hear that it moved before App hears the display was
10635        // connected. App learns about the display before the window's
10636        // observers run, and the platform's later notification changes
10637        // nothing.
10638        cx.test_platform()
10639            .connect_display(DisplayId(2), Some(one_hundred_twenty_hertz));
10640        test_window.simulate_move_to_display(DisplayId(2));
10641        assert_eq!(
10642            window_notifications.take(),
10643            [(Some(DisplayId(2)), Some(one_hundred_twenty_hertz))]
10644        );
10645        assert_eq!(display_events.take(), [DisplayEvent::Added(DisplayId(2))]);
10646        cx.simulate_display_refresh_interval_change(DisplayId(2), Some(one_hundred_twenty_hertz));
10647        assert!(window_notifications.borrow().is_empty());
10648
10649        // Platforms may report a move that isn't one.
10650        test_window.simulate_move_to_display(DisplayId(2));
10651        assert!(window_notifications.borrow().is_empty());
10652
10653        cx.simulate_display_refresh_interval_change(
10654            DisplayId(2),
10655            Some(one_hundred_forty_four_hertz),
10656        );
10657        assert_eq!(
10658            window_notifications.take(),
10659            [(Some(DisplayId(2)), Some(one_hundred_forty_four_hertz))]
10660        );
10661
10662        // Changes to a display the window isn't on don't notify it.
10663        cx.simulate_display_refresh_interval_change(DisplayId(1), Some(one_hundred_twenty_hertz));
10664        cx.simulate_display_removed(DisplayId(1));
10665        assert!(window_notifications.borrow().is_empty());
10666
10667        assert_eq!(
10668            display_events.take(),
10669            [
10670                DisplayEvent::Changed {
10671                    id: DisplayId(2),
10672                    changes: DisplayChanges::REFRESH_INTERVAL,
10673                },
10674                DisplayEvent::Changed {
10675                    id: DisplayId(1),
10676                    changes: DisplayChanges::REFRESH_INTERVAL,
10677                },
10678                DisplayEvent::Removed(DisplayId(1)),
10679            ]
10680        );
10681        window
10682            .update(cx, |tracker, _, _| {
10683                assert_eq!(
10684                    tracker.refresh_intervals,
10685                    [
10686                        Some(one_hundred_twenty_hertz),
10687                        Some(one_hundred_forty_four_hertz)
10688                    ]
10689                );
10690            })
10691            .unwrap();
10692
10693        struct DisplayTracker {
10694            refresh_intervals: Vec<Option<Duration>>,
10695            _subscription: Subscription,
10696        }
10697
10698        impl Render for DisplayTracker {
10699            fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
10700                Empty
10701            }
10702        }
10703    }
10704
10705    #[gpui::test]
10706    fn test_fully_visible_bounds_preserve_layout_viewport(cx: &mut TestAppContext) {
10707        struct InsetsProbe(std::rc::Rc<std::cell::Cell<usize>>);
10708
10709        impl Render for InsetsProbe {
10710            fn render(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10711                self.0.set(self.0.get() + 1);
10712                div().child(format!("{:?}", window.insets().ime.bottom))
10713            }
10714        }
10715
10716        let renders = std::rc::Rc::new(std::cell::Cell::new(0));
10717        let window = cx.add_window({
10718            let renders = renders.clone();
10719            move |_, _| InsetsProbe(renders)
10720        });
10721        let mut platform_window = cx.test_window(window.into());
10722        platform_window.simulate_resize(size(px(400.), px(800.)));
10723        window
10724            .update(cx, |_, window, _| {
10725                assert_eq!(
10726                    window.visual_viewport_bounds(),
10727                    Bounds::new(Point::default(), size(px(400.), px(800.)))
10728                );
10729                assert_eq!(
10730                    window.fully_visible_bounds(),
10731                    window.visual_viewport_bounds()
10732                );
10733            })
10734            .unwrap();
10735
10736        platform_window.simulate_frame_request(RequestFrameOptions::default());
10737        let wakes = platform_window.frame_wake_count();
10738        let visual_bounds = Bounds::new(point(px(10.), px(40.)), size(px(380.), px(460.)));
10739        platform_window.simulate_visual_viewport_change(visual_bounds);
10740        assert!(platform_window.frame_wake_count() > wakes);
10741        platform_window.simulate_frame_request(RequestFrameOptions::default());
10742        let wakes = platform_window.frame_wake_count();
10743        let insets = crate::WindowInsets {
10744            safe_area: crate::Edges {
10745                top: px(60.),
10746                right: px(20.),
10747                bottom: px(30.),
10748                left: px(-10.),
10749            },
10750            ime: crate::Edges {
10751                bottom: px(350.),
10752                ..Default::default()
10753            },
10754        };
10755        let renders_before_insets = renders.get();
10756        platform_window.simulate_insets_change(insets.clone());
10757        assert!(platform_window.frame_wake_count() > wakes);
10758        platform_window.simulate_frame_request(RequestFrameOptions::default());
10759        assert!(renders.get() > renders_before_insets);
10760        window
10761            .update(cx, |_, window, cx| {
10762                let focus = cx.focus_handle();
10763                window.focus(&focus, cx);
10764                assert_eq!(window.insets(), insets);
10765                assert_eq!(window.viewport_size(), size(px(400.), px(800.)));
10766                assert_eq!(window.visual_viewport_bounds(), visual_bounds);
10767                assert_eq!(
10768                    window.fully_visible_bounds(),
10769                    Bounds::new(point(px(10.), px(60.)), size(px(370.), px(390.)))
10770                );
10771                window.request_virtual_keyboard();
10772                window.dismiss_virtual_keyboard();
10773                assert!(focus.is_focused(window));
10774                assert_eq!(window.viewport_size(), size(px(400.), px(800.)));
10775            })
10776            .unwrap();
10777        assert_eq!(platform_window.virtual_keyboard_requests(), 1);
10778        assert_eq!(platform_window.virtual_keyboard_dismissals(), 1);
10779
10780        platform_window.simulate_insets_change(crate::WindowInsets {
10781            safe_area: crate::Edges {
10782                top: px(900.),
10783                left: px(500.),
10784                ..Default::default()
10785            },
10786            ..Default::default()
10787        });
10788        window
10789            .update(cx, |_, window, _| {
10790                assert_eq!(
10791                    window.fully_visible_bounds().size,
10792                    size(Pixels::ZERO, Pixels::ZERO)
10793                );
10794            })
10795            .unwrap();
10796
10797        // Some backends update geometry snapshots without delivering inset callbacks.
10798        use crate::PlatformWindow as _;
10799        platform_window.on_insets_changed(Box::new(|_| {}));
10800        platform_window.simulate_insets_change(crate::WindowInsets::default());
10801        window
10802            .update(cx, |_, window, _| {
10803                assert_eq!(window.insets(), crate::WindowInsets::default());
10804            })
10805            .unwrap();
10806    }
10807
10808    struct EmptyView;
10809
10810    impl Render for EmptyView {
10811        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10812            div()
10813        }
10814    }
10815
10816    fn shadow_gradient() -> Background {
10817        linear_gradient(
10818            90.,
10819            linear_color_stop(hsla(0., 1., 0.5, 0.8), 0.),
10820            linear_color_stop(hsla(2. / 3., 1., 0.5, 0.6), 1.),
10821        )
10822    }
10823
10824    struct ShadowBackgroundView;
10825
10826    impl Render for ShadowBackgroundView {
10827        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10828            div()
10829                .m(px(40.))
10830                .w(px(80.))
10831                .h(px(60.))
10832                .rounded(px(8.))
10833                .bg(white())
10834                .opacity(0.5)
10835                .shadow(vec![
10836                    BoxShadow::new(px(4.), px(2.), shadow_gradient())
10837                        .blur_radius(px(6.))
10838                        .spread_radius(px(2.)),
10839                    BoxShadow::new(px(-3.), px(1.), hsla(0.3, 0.7, 0.4, 0.4)),
10840                    BoxShadow::new(px(0.), px(2.), shadow_gradient())
10841                        .blur_radius(px(4.))
10842                        .spread_radius(px(3.))
10843                        .inset(),
10844                ])
10845        }
10846    }
10847
10848    struct CornerSmoothingSceneView {
10849        image: Arc<RenderImage>,
10850    }
10851
10852    fn assert_smoothing(name: &str, minimum_count: usize, values: impl IntoIterator<Item = f32>) {
10853        let values = values.into_iter().collect::<Vec<_>>();
10854        assert!(values.len() >= minimum_count, "missing {name}");
10855        assert!(
10856            values.iter().all(|&value| value == 1.0),
10857            "{name}: {values:?}"
10858        );
10859    }
10860
10861    impl Render for CornerSmoothingSceneView {
10862        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
10863            let mut image = img(ImageSource::Render(self.image.clone()))
10864                .size(px(24.))
10865                .rounded(px(8.));
10866            image.style().corner_smoothing = Some(1.5);
10867
10868            let mut root = div()
10869                .size(px(80.))
10870                .rounded(px(24.))
10871                .bg(crate::blue())
10872                .border_t(px(2.))
10873                .border_r(px(4.))
10874                .border_b(px(6.))
10875                .border_l(px(8.))
10876                .border_color(crate::white())
10877                .shadow(vec![
10878                    BoxShadow::new(px(2.), px(3.), crate::black().opacity(0.5))
10879                        .blur_radius(px(5.))
10880                        .spread_radius(px(1.)),
10881                    BoxShadow::new(px(1.), px(1.), crate::white().opacity(0.4))
10882                        .blur_radius(px(3.))
10883                        .inset(),
10884                ])
10885                .backdrop_blur(px(4.))
10886                .blur(px(2.))
10887                .child(image);
10888            root.style().corner_smoothing = Some(1.5);
10889            root
10890        }
10891    }
10892
10893    #[gpui::test]
10894    fn shadow_backgrounds_survive_painting_with_geometry_and_opacity(cx: &mut TestAppContext) {
10895        let window = cx.add_window(|_, _| ShadowBackgroundView);
10896        let shadows = window
10897            .update(cx, |_, window, _| {
10898                window.rendered_frame.scene.shadows.clone()
10899            })
10900            .unwrap();
10901
10902        assert_eq!(shadows.len(), 3);
10903        let gradient = shadow_gradient();
10904        let drop_gradient = shadows
10905            .iter()
10906            .find(|shadow| shadow.inset == ShaderBool::Disabled && shadow.color == gradient)
10907            .expect("gradient drop shadow should be painted");
10908        let inset_gradient = shadows
10909            .iter()
10910            .find(|shadow| shadow.inset == ShaderBool::Enabled && shadow.color == gradient)
10911            .expect("gradient inset shadow should be painted");
10912        let solid = shadows
10913            .iter()
10914            .find(|shadow| shadow.color.as_solid().is_some())
10915            .expect("solid shadows should remain supported");
10916
10917        assert_eq!(
10918            solid.color.as_solid(),
10919            Some(hsla(0.3, 0.7, 0.4, 0.4)),
10920            "shadow alpha stays intrinsic until the group composite"
10921        );
10922        assert_eq!(drop_gradient.element_bounds, inset_gradient.element_bounds);
10923        assert!(drop_gradient.bounds.size.width > drop_gradient.element_bounds.size.width);
10924        assert!(drop_gradient.bounds.size.height > drop_gradient.element_bounds.size.height);
10925        assert!(inset_gradient.bounds.size.width < inset_gradient.element_bounds.size.width);
10926        assert!(inset_gradient.bounds.size.height < inset_gradient.element_bounds.size.height);
10927        assert!(drop_gradient.order < inset_gradient.order);
10928    }
10929
10930    #[gpui::test]
10931    fn corner_smoothing_reaches_every_styled_scene_primitive(cx: &mut TestAppContext) {
10932        let frame = ImageFrame::new(ImageBuffer::from_pixel(2, 2, Rgba([255, 255, 255, 255])));
10933        let image = Arc::new(RenderImage::new(smallvec![frame]));
10934        let window = cx.add_window(move |_, _| CornerSmoothingSceneView { image });
10935
10936        window
10937            .update(cx, |_, window, _| {
10938                let scene = &window.rendered_frame.scene;
10939                assert_smoothing(
10940                    "quads",
10941                    2,
10942                    scene.quads.iter().map(|quad| quad.corner_smoothing),
10943                );
10944                assert_smoothing(
10945                    "shadows",
10946                    2,
10947                    scene.shadows.iter().map(|shadow| shadow.corner_smoothing),
10948                );
10949                assert_smoothing(
10950                    "backdrop filters",
10951                    1,
10952                    scene
10953                        .backdrop_filters
10954                        .iter()
10955                        .map(|filter| filter.corner_smoothing),
10956                );
10957                assert_smoothing(
10958                    "filter boundaries",
10959                    2,
10960                    scene
10961                        .filter_boundaries
10962                        .iter()
10963                        .filter(|boundary| !boundary.filters.is_empty())
10964                        .map(|boundary| boundary.corner_smoothing),
10965                );
10966                assert_smoothing(
10967                    "images",
10968                    1,
10969                    scene
10970                        .polychrome_sprites
10971                        .iter()
10972                        .map(|image| image.corner_smoothing),
10973                );
10974                for inset in [ShaderBool::Disabled, ShaderBool::Enabled] {
10975                    assert!(scene.shadows.iter().any(|shadow| shadow.inset == inset));
10976                }
10977
10978                let border = scene
10979                    .quads
10980                    .iter()
10981                    .find(|quad| quad.border_widths.top.0 > 0.0)
10982                    .expect("border quad");
10983                let scale = window.scale_factor();
10984                assert_eq!(
10985                    [
10986                        border.border_widths.top.0,
10987                        border.border_widths.right.0,
10988                        border.border_widths.bottom.0,
10989                        border.border_widths.left.0,
10990                    ],
10991                    [2.0, 4.0, 6.0, 8.0].map(|width| width * scale)
10992                );
10993            })
10994            .unwrap();
10995    }
10996
10997    struct OpensWindowOnPaint {
10998        opened: Rc<Cell<bool>>,
10999    }
11000
11001    impl Render for OpensWindowOnPaint {
11002        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
11003            let opened = self.opened.clone();
11004            div()
11005                .size_full()
11006                .child(canvas(
11007                    |_, _, _| {},
11008                    move |_, _, _window, cx| {
11009                        if !opened.replace(true) {
11010                            cx.open_window(WindowOptions::default(), |_, cx| cx.new(|_| EmptyView))
11011                                .unwrap();
11012                        }
11013                    },
11014                ))
11015                // Siblings painted after the canvas: their elements were
11016                // allocated in the arena before the nested draw, so they detect
11017                // a mid-draw arena clear when painted afterward.
11018                .child(div().child("after"))
11019        }
11020    }
11021
11022    /// Opening a window synchronously draws it and requests an element arena
11023    /// clear. When that happens from within another window's draw (here: from
11024    /// an element's paint), the clear must be deferred until the outer draw
11025    /// finishes, or the outer draw's arena-allocated elements would be freed
11026    /// out from under it.
11027    #[test]
11028    fn test_window_opened_during_draw_defers_arena_clear() {
11029        let mut cx = TestAppContext::single();
11030
11031        let opened = Rc::new(Cell::new(false));
11032        // add_window draws once, which runs the nested open_window mid-draw.
11033        let window = cx.add_window({
11034            let opened = opened.clone();
11035            move |_, _| OpensWindowOnPaint { opened }
11036        });
11037
11038        assert!(opened.get());
11039        assert_eq!(cx.windows().len(), 2);
11040
11041        // The deferred clear must actually run once the outer draw unwinds:
11042        // subsequent draws of both windows work against a fresh arena.
11043        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
11044            .unwrap();
11045    }
11046
11047    #[test]
11048    fn test_scale_factor_change_preserves_bounds_and_survives_resize() {
11049        let mut cx = TestAppContext::single();
11050        let window = cx.add_window(|_, _| EmptyView);
11051        let handle: AnyWindowHandle = window.into();
11052        let window_state = |cx: &mut TestAppContext| {
11053            cx.update_window(handle, |_, window, _| {
11054                (
11055                    window.scale_factor(),
11056                    window.bounds(),
11057                    window.viewport_size(),
11058                )
11059            })
11060            .unwrap()
11061        };
11062
11063        let (scale_factor, mut expected_bounds, _) = window_state(&mut cx);
11064        assert_eq!(scale_factor, 2.0);
11065
11066        for (scale_factor, resized_size) in [
11067            (1.0, size(px(800.), px(600.))),
11068            (1.25, size(px(640.), px(480.))),
11069            (2.0, size(px(1024.), px(768.))),
11070        ] {
11071            cx.simulate_window_scale_factor_change(handle, scale_factor);
11072            assert_eq!(
11073                window_state(&mut cx),
11074                (scale_factor, expected_bounds, expected_bounds.size)
11075            );
11076
11077            cx.simulate_window_resize(handle, resized_size);
11078            expected_bounds.size = resized_size;
11079            assert_eq!(
11080                window_state(&mut cx),
11081                (scale_factor, expected_bounds, resized_size)
11082            );
11083        }
11084    }
11085
11086    /// Platforms that stop requesting frames for idle windows (currently web)
11087    /// rely on the frame waker firing whenever frame demand arises; a demand
11088    /// source that skips the waker shows up there as a window that silently
11089    /// stops repainting until unrelated activity wakes it.
11090    #[gpui::test]
11091    fn test_frame_waker_fires_on_frame_demand(cx: &mut TestAppContext) {
11092        let window = cx.add_window(|_, _| EmptyView);
11093        let test_window = cx.test_window(window.into());
11094
11095        // Windows start dirty, and that can predate waker installation;
11096        // installing the waker must deliver the pending wake or the first
11097        // frame would never be requested.
11098        assert!(
11099            test_window.frame_wake_count() >= 1,
11100            "opening a window must wake the frame source for the initial frame"
11101        );
11102
11103        // Serve outstanding demand (present the frame drawn by `add_window`).
11104        test_window.simulate_frame_request(RequestFrameOptions::default());
11105
11106        // An idle window must not wake on clean frames or plain updates, or
11107        // the frame source could never stop.
11108        let baseline = test_window.frame_wake_count();
11109        test_window.simulate_frame_request(RequestFrameOptions::default());
11110        window.update(cx, |_, _, _| {}).unwrap();
11111        assert_eq!(
11112            test_window.frame_wake_count(),
11113            baseline,
11114            "clean frames and non-notifying updates must not wake the frame source"
11115        );
11116
11117        // Notifying a view in an idle window is the core demand signal.
11118        window.update(cx, |_, _, cx| cx.notify()).unwrap();
11119        assert!(
11120            test_window.frame_wake_count() > baseline,
11121            "notifying a view in an idle window must wake the frame source"
11122        );
11123
11124        // Serving that demand returns to idle without further wakes.
11125        test_window.simulate_frame_request(RequestFrameOptions::default());
11126        let baseline = test_window.frame_wake_count();
11127        test_window.simulate_frame_request(RequestFrameOptions::default());
11128        assert_eq!(
11129            test_window.frame_wake_count(),
11130            baseline,
11131            "serving demand must return the window to idle"
11132        );
11133
11134        // Next-frame callbacks create demand without dirtying the window.
11135        window
11136            .update(cx, |_, window, _| window.on_next_frame(|_, _| {}))
11137            .unwrap();
11138        assert!(
11139            test_window.frame_wake_count() > baseline,
11140            "scheduling a next-frame callback in an idle window must wake the frame source"
11141        );
11142    }
11143
11144    /// A frame request that arrives while next-frame callbacks are pending
11145    /// must never strand them: either the frame runs them, or (when the
11146    /// inactive-window frame-rate throttle defers the frame) the waker fires
11147    /// so another request is delivered.
11148    #[gpui::test]
11149    fn test_pending_next_frame_callbacks_are_not_stranded(cx: &mut TestAppContext) {
11150        let window = cx.add_window(|_, _| EmptyView);
11151        let test_window = cx.test_window(window.into());
11152        // Establish a recent last-frame time so the inactive-window throttle
11153        // can engage on the next request.
11154        test_window.simulate_frame_request(RequestFrameOptions::default());
11155
11156        let callback_ran = Rc::new(Cell::new(false));
11157        window
11158            .update(cx, {
11159                let callback_ran = callback_ran.clone();
11160                move |_, window, _| {
11161                    window.on_next_frame(move |_, _| callback_ran.set(true));
11162                }
11163            })
11164            .unwrap();
11165
11166        let baseline = test_window.frame_wake_count();
11167        test_window.simulate_frame_request(RequestFrameOptions::default());
11168        // The test window is inactive, so this request throttles to ~30fps
11169        // when it lands within the throttle interval of the previous frame
11170        // (the common case here, but timing-dependent): the callback is
11171        // deferred and the waker must re-arm the frame source. On a slow run
11172        // the request instead lands outside the interval and runs the
11173        // callback directly.
11174        assert!(
11175            test_window.frame_wake_count() > baseline || callback_ran.get(),
11176            "a frame request with pending next-frame callbacks must either run them or re-arm the frame source"
11177        );
11178    }
11179
11180    #[gpui::test]
11181    fn test_window_reports_no_raw_handle_instead_of_panicking(cx: &mut TestAppContext) {
11182        use raw_window_handle::{HandleError, HasDisplayHandle as _, HasWindowHandle as _};
11183
11184        let window = cx.add_window(|_, _| EmptyView);
11185        window
11186            .update(cx, |_, window, _| {
11187                assert!(matches!(
11188                    window.window_handle(),
11189                    Err(HandleError::NotSupported)
11190                ));
11191                assert!(matches!(
11192                    window.display_handle(),
11193                    Err(HandleError::NotSupported)
11194                ));
11195            })
11196            .unwrap();
11197    }
11198
11199    #[gpui::test]
11200    fn test_window_visibility_can_be_changed(cx: &mut TestAppContext) {
11201        for show in [false, true] {
11202            let window = cx.update(|cx| {
11203                cx.open_window(WindowOptions::new().show(show), |_, cx| {
11204                    cx.new(|_| EmptyView)
11205                })
11206                .unwrap()
11207            });
11208            let platform_window = cx.test_window(window.into());
11209            assert_eq!(platform_window.is_visible(), show);
11210
11211            for visible in [false, false, true, true, false, true] {
11212                window
11213                    .update(cx, |_, window, _| window.set_visible(visible))
11214                    .unwrap();
11215                assert_eq!(platform_window.is_visible(), visible);
11216            }
11217        }
11218    }
11219
11220    #[gpui::test]
11221    fn test_appearance_change_runs_after_app_update(cx: &mut TestAppContext) {
11222        let window = cx.add_window(|_, _| EmptyView);
11223        let observed_appearance = Rc::new(Cell::new(None));
11224        let _subscription = window
11225            .update(cx, {
11226                let observed_appearance = observed_appearance.clone();
11227                move |_, window, _| {
11228                    window.observe_window_appearance(move |window, _| {
11229                        observed_appearance.set(Some(window.appearance()));
11230                    })
11231                }
11232            })
11233            .unwrap();
11234        let test_window = cx.test_window(window.into());
11235
11236        cx.update(|_| {
11237            test_window.simulate_appearance_change(WindowAppearance::Dark);
11238            assert_eq!(observed_appearance.get(), None);
11239        });
11240        cx.run_until_parked();
11241
11242        assert_eq!(observed_appearance.get(), Some(WindowAppearance::Dark));
11243    }
11244
11245    #[gpui::test]
11246    fn queued_frame_callback_wakes_a_parked_render_loop(cx: &mut TestAppContext) {
11247        let window = cx.add_window(|_, _| Empty);
11248        let test_window = cx.test_window(window.into());
11249
11250        assert!(test_window.simulate_scheduled_frame());
11251        assert!(test_window.simulate_scheduled_frame());
11252        assert!(!test_window.frame_scheduled());
11253
11254        cx.update_window(window.into(), |_, window, _| {
11255            window.active.set(true);
11256            window.on_next_frame(|_, _| {});
11257        })
11258        .unwrap();
11259        assert!(
11260            test_window.frame_scheduled(),
11261            "queuing work on a parked window must wake the render loop"
11262        );
11263
11264        assert!(test_window.simulate_scheduled_frame());
11265        assert!(
11266            test_window.frame_scheduled(),
11267            "presenting the frame must await one compositor callback"
11268        );
11269        assert!(test_window.simulate_scheduled_frame());
11270        assert!(!test_window.frame_scheduled());
11271    }
11272
11273    #[gpui::test]
11274    fn pending_presentation_wakes_a_parked_render_loop(cx: &mut TestAppContext) {
11275        let window = cx.add_window(|_, _| Empty);
11276        let test_window = cx.test_window(window.into());
11277
11278        assert!(test_window.simulate_scheduled_frame());
11279        assert!(test_window.simulate_scheduled_frame());
11280        assert!(!test_window.frame_scheduled());
11281
11282        cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
11283            .unwrap();
11284
11285        assert!(
11286            test_window.frame_scheduled(),
11287            "a rendered scene awaiting presentation must wake the render loop"
11288        );
11289    }
11290
11291    #[gpui::test]
11292    fn callback_queued_during_a_frame_requests_a_follow_up(cx: &mut TestAppContext) {
11293        let window = cx.add_window(|_, _| Empty);
11294        let test_window = cx.test_window(window.into());
11295
11296        let callback_ran = Rc::new(Cell::new(false));
11297        cx.update_window(window.into(), |_, window, _| {
11298            // Inactive windows are frame-rate throttled, which would defer the
11299            // ticks this test drives manually.
11300            window.active.set(true);
11301            let callback_ran = callback_ran.clone();
11302            window.on_next_frame(move |window, _| {
11303                window.on_next_frame(move |_, _| callback_ran.set(true));
11304            });
11305        })
11306        .unwrap();
11307
11308        assert!(test_window.simulate_scheduled_frame());
11309        assert!(!callback_ran.get());
11310        assert!(
11311            test_window.frame_scheduled(),
11312            "a callback queued mid-frame must schedule a follow-up before the loop parks"
11313        );
11314
11315        assert!(test_window.simulate_scheduled_frame());
11316        assert!(callback_ran.get());
11317    }
11318
11319    struct RootView {
11320        explicit_size: bool,
11321        child_bounds: Rc<Cell<Bounds<Pixels>>>,
11322    }
11323
11324    impl Render for RootView {
11325        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
11326            let child_bounds = self.child_bounds.clone();
11327            let root = div().flex().flex_col().child(
11328                canvas(
11329                    move |bounds, _, _| child_bounds.set(bounds),
11330                    |_, _, _, _| {},
11331                )
11332                .size_full(),
11333            );
11334            if self.explicit_size {
11335                root.w(px(300.)).h(px(200.))
11336            } else {
11337                root
11338            }
11339        }
11340    }
11341
11342    #[test]
11343    fn auto_sized_window_root_fills_the_window() {
11344        let mut cx = TestAppContext::single();
11345        let child_bounds = Rc::new(Cell::new(Bounds::default()));
11346        let window = cx.add_window({
11347            let child_bounds = child_bounds.clone();
11348            move |_, _| RootView {
11349                explicit_size: false,
11350                child_bounds,
11351            }
11352        });
11353
11354        let viewport_size = cx
11355            .update_window(window.into(), |_, window, cx| {
11356                window.draw(cx).clear(cx);
11357                window.viewport_size()
11358            })
11359            .unwrap();
11360
11361        assert_eq!(child_bounds.get().size, viewport_size);
11362    }
11363
11364    #[test]
11365    fn explicitly_sized_window_root_keeps_its_size() {
11366        let mut cx = TestAppContext::single();
11367        let child_bounds = Rc::new(Cell::new(Bounds::default()));
11368        let window = cx.add_window({
11369            let child_bounds = child_bounds.clone();
11370            move |_, _| RootView {
11371                explicit_size: true,
11372                child_bounds,
11373            }
11374        });
11375
11376        cx.update_window(window.into(), |_, window, cx| {
11377            window.draw(cx).clear(cx);
11378        })
11379        .unwrap();
11380
11381        assert_eq!(child_bounds.get().size, size(px(300.), px(200.)));
11382    }
11383
11384    struct FileDragView {
11385        path: PathBuf,
11386        observed_drag_moves: Rc<RefCell<Vec<Point<Pixels>>>>,
11387        observed_drops: Rc<RefCell<Vec<PathBuf>>>,
11388    }
11389
11390    struct FileDropExitView(Rc<Cell<usize>>);
11391
11392    impl Render for FileDropExitView {
11393        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
11394            div().size_full().on_file_drop_exit({
11395                let observed_file_drop_exit = self.0.clone();
11396                move |_, _, _| observed_file_drop_exit.set(observed_file_drop_exit.get() + 1)
11397            })
11398        }
11399    }
11400
11401    impl Render for FileDragView {
11402        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
11403            div()
11404                .id("file-drag")
11405                .size_full()
11406                .on_drag(self.path.clone(), |_, _, _, cx| cx.new(|_| Empty))
11407                .external_drag_payload(|path: &PathBuf, _, _| {
11408                    Some(ExternalDragPayload::Files(FileDragPaths::new([(
11409                        path.clone(),
11410                        true,
11411                    )])))
11412                })
11413                .on_drag_move({
11414                    let observed_drag_moves = self.observed_drag_moves.clone();
11415                    move |event: &DragMoveEvent<PathBuf>, _, _| {
11416                        observed_drag_moves.borrow_mut().push(event.event.position);
11417                    }
11418                })
11419                .on_drop({
11420                    let observed_drops = self.observed_drops.clone();
11421                    move |path: &PathBuf, _, _| observed_drops.borrow_mut().push(path.clone())
11422                })
11423        }
11424    }
11425
11426    #[gpui::test]
11427    fn file_drag_is_promoted_once_and_restored_in_source_window(cx: &mut TestAppContext) {
11428        struct Drag {
11429            window: AnyWindowHandle,
11430            observed_drag_moves: Rc<RefCell<Vec<Point<Pixels>>>>,
11431            observed_drops: Rc<RefCell<Vec<PathBuf>>>,
11432        }
11433
11434        fn start_drag(cx: &mut TestAppContext, path: PathBuf, platform_result: bool) -> Drag {
11435            let observed_drag_moves = Rc::new(RefCell::new(Vec::new()));
11436            let observed_drops = Rc::new(RefCell::new(Vec::new()));
11437            let window: AnyWindowHandle = cx
11438                .add_window({
11439                    let observed_drag_moves = observed_drag_moves.clone();
11440                    let observed_drops = observed_drops.clone();
11441                    move |_, _| FileDragView {
11442                        path,
11443                        observed_drag_moves,
11444                        observed_drops,
11445                    }
11446                })
11447                .into();
11448            cx.test_window(window)
11449                .set_start_external_drag_result(platform_result);
11450
11451            let update_result = cx.update_window(window, |_, window, cx| {
11452                window.draw(cx).clear(cx);
11453                window.dispatch_event(
11454                    MouseDownEvent {
11455                        position: point(px(10.), px(10.)),
11456                        button: MouseButton::Left,
11457                        modifiers: Default::default(),
11458                        click_count: 1,
11459                        first_mouse: false,
11460                    }
11461                    .to_platform_input(),
11462                    cx,
11463                );
11464                window.dispatch_event(
11465                    MouseMoveEvent {
11466                        position: point(px(20.), px(20.)),
11467                        pressed_button: Some(MouseButton::Left),
11468                        modifiers: Default::default(),
11469                    }
11470                    .to_platform_input(),
11471                    cx,
11472                );
11473                assert!(cx.active_drag.is_some());
11474            });
11475            assert!(
11476                update_result.is_ok(),
11477                "failed to start drag: {update_result:?}"
11478            );
11479
11480            assert!(cx.test_window(window).external_drag_files().is_empty());
11481            Drag {
11482                window,
11483                observed_drag_moves,
11484                observed_drops,
11485            }
11486        }
11487
11488        let successful_path = PathBuf::from("/tmp/successful-drag");
11489        let successful = start_drag(cx, successful_path.clone(), true);
11490        let outside_position = point(px(-1.), px(20.));
11491        let update_result = cx.update_window(successful.window, |_, window, cx| {
11492            window.dispatch_event(
11493                MouseMoveEvent {
11494                    position: outside_position,
11495                    pressed_button: Some(MouseButton::Left),
11496                    modifiers: Default::default(),
11497                }
11498                .to_platform_input(),
11499                cx,
11500            );
11501            assert!(cx.active_drag.is_none());
11502        });
11503        assert!(
11504            update_result.is_ok(),
11505            "failed to promote drag: {update_result:?}"
11506        );
11507        assert_eq!(
11508            cx.test_window(successful.window).external_drag_files(),
11509            [(successful_path.clone(), true)]
11510        );
11511        // Views must still see the move that leaves the window, otherwise they never learn to tear
11512        // down the drag state they built up while the pointer was inside.
11513        assert_eq!(
11514            successful.observed_drag_moves.borrow().last(),
11515            Some(&outside_position)
11516        );
11517
11518        let first_destination_exit_count = Rc::new(Cell::new(0));
11519        let first_destination: AnyWindowHandle = cx
11520            .add_window({
11521                let first_destination_exit_count = first_destination_exit_count.clone();
11522                move |_, _| FileDropExitView(first_destination_exit_count)
11523            })
11524            .into();
11525        let second_destination_exit_count = Rc::new(Cell::new(0));
11526        let second_destination: AnyWindowHandle = cx
11527            .add_window({
11528                let second_destination_exit_count = second_destination_exit_count.clone();
11529                move |_, _| FileDropExitView(second_destination_exit_count)
11530            })
11531            .into();
11532        let reentry_position = point(px(30.), px(30.));
11533        let external_paths = || ExternalPaths([successful_path.clone()].into_iter().collect());
11534        let update_result = cx.update_window(first_destination, |_, window, cx| {
11535            window.draw(cx).clear(cx);
11536            window.dispatch_event(
11537                FileDropEvent::Entered {
11538                    position: reentry_position,
11539                    paths: external_paths(),
11540                }
11541                .to_platform_input(),
11542                cx,
11543            );
11544            assert!(
11545                cx.active_drag
11546                    .as_ref()
11547                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
11548            );
11549            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
11550            assert!(cx.active_drag.is_none());
11551            assert_eq!(first_destination_exit_count.get(), 1);
11552            assert_eq!(second_destination_exit_count.get(), 0);
11553        });
11554        assert!(
11555            update_result.is_ok(),
11556            "failed to handle drag in first destination window: {update_result:?}"
11557        );
11558
11559        let update_result = cx.update_window(second_destination, |_, window, cx| {
11560            window.draw(cx).clear(cx);
11561            window.dispatch_event(
11562                PlatformInput::KeyDown(KeyDownEvent {
11563                    keystroke: Keystroke::parse("down").expect("valid keystroke"),
11564                    is_held: false,
11565                    prefer_character_input: false,
11566                }),
11567                cx,
11568            );
11569            window.dispatch_event(
11570                FileDropEvent::Entered {
11571                    position: reentry_position,
11572                    paths: external_paths(),
11573                }
11574                .to_platform_input(),
11575                cx,
11576            );
11577            assert!(
11578                cx.active_drag
11579                    .as_ref()
11580                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
11581            );
11582            assert_eq!(first_destination_exit_count.get(), 1);
11583            assert_eq!(second_destination_exit_count.get(), 0);
11584
11585            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
11586            assert!(cx.active_drag.is_none());
11587            assert_eq!(first_destination_exit_count.get(), 1);
11588            assert_eq!(second_destination_exit_count.get(), 1);
11589        });
11590        assert!(
11591            update_result.is_ok(),
11592            "failed to handle drag in second destination window: {update_result:?}"
11593        );
11594
11595        let update_result = cx.update_window(successful.window, |_, window, cx| {
11596            window.dispatch_event(
11597                FileDropEvent::Entered {
11598                    position: reentry_position,
11599                    paths: external_paths(),
11600                }
11601                .to_platform_input(),
11602                cx,
11603            );
11604            assert!(
11605                cx.active_drag
11606                    .as_ref()
11607                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
11608            );
11609            assert_eq!(
11610                successful.observed_drag_moves.borrow().last(),
11611                Some(&reentry_position)
11612            );
11613
11614            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
11615            assert!(cx.active_drag.is_none());
11616
11617            window.dispatch_event(
11618                FileDropEvent::Entered {
11619                    position: reentry_position,
11620                    paths: external_paths(),
11621                }
11622                .to_platform_input(),
11623                cx,
11624            );
11625            assert!(
11626                cx.active_drag
11627                    .as_ref()
11628                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
11629            );
11630
11631            window.dispatch_event(
11632                FileDropEvent::Submit {
11633                    position: reentry_position,
11634                }
11635                .to_platform_input(),
11636                cx,
11637            );
11638            assert_eq!(
11639                successful.observed_drops.borrow().as_slice(),
11640                std::slice::from_ref(&successful_path)
11641            );
11642            assert!(cx.active_drag.is_none());
11643
11644            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
11645            assert!(cx.active_drag.is_none());
11646            window.dispatch_event(FileDropEvent::Ended.to_platform_input(), cx);
11647            assert!(cx.active_drag.is_none());
11648
11649            window.dispatch_event(
11650                FileDropEvent::Entered {
11651                    position: reentry_position,
11652                    paths: external_paths(),
11653                }
11654                .to_platform_input(),
11655                cx,
11656            );
11657            assert!(
11658                cx.active_drag
11659                    .as_ref()
11660                    .is_some_and(|drag| drag.value.downcast_ref::<ExternalPaths>().is_some())
11661            );
11662            window.dispatch_event(FileDropEvent::Exited.to_platform_input(), cx);
11663        });
11664        assert!(
11665            update_result.is_ok(),
11666            "failed to restore drag in source window: {update_result:?}"
11667        );
11668
11669        let cancelled_path = PathBuf::from("/tmp/cancelled-drag");
11670        let cancelled = start_drag(cx, cancelled_path.clone(), true);
11671        let update_result = cx.update_window(cancelled.window, |_, window, cx| {
11672            window.dispatch_event(
11673                MouseMoveEvent {
11674                    position: outside_position,
11675                    pressed_button: Some(MouseButton::Left),
11676                    modifiers: Default::default(),
11677                }
11678                .to_platform_input(),
11679                cx,
11680            );
11681            assert!(cx.active_drag.is_none());
11682
11683            window.dispatch_event(
11684                FileDropEvent::Entered {
11685                    position: reentry_position,
11686                    paths: ExternalPaths([cancelled_path].into_iter().collect()),
11687                }
11688                .to_platform_input(),
11689                cx,
11690            );
11691            assert!(
11692                cx.active_drag
11693                    .as_ref()
11694                    .is_some_and(|drag| drag.value.downcast_ref::<PathBuf>().is_some())
11695            );
11696            assert!(cx.stop_active_drag(window));
11697            assert!(cx.active_drag.is_none());
11698        });
11699        assert!(
11700            update_result.is_ok(),
11701            "failed to cancel restored drag: {update_result:?}"
11702        );
11703        assert!(!cx.update(|cx| cx.end_platform_drag(cancelled.window.window_id())));
11704
11705        let removed_path = PathBuf::from("/tmp/removed-window-drag");
11706        let removed = start_drag(cx, removed_path, true);
11707        let removed_window_id = removed.window.window_id();
11708        let update_result = cx.update_window(removed.window, |_, window, cx| {
11709            window.dispatch_event(
11710                MouseMoveEvent {
11711                    position: outside_position,
11712                    pressed_button: Some(MouseButton::Left),
11713                    modifiers: Default::default(),
11714                }
11715                .to_platform_input(),
11716                cx,
11717            );
11718            assert!(cx.active_drag.is_none());
11719            window.remove_window();
11720        });
11721        assert!(
11722            update_result.is_ok(),
11723            "failed to remove drag source window: {update_result:?}"
11724        );
11725        assert!(!cx.update(|cx| cx.end_platform_drag(removed_window_id)));
11726
11727        let failed_path = PathBuf::from("/tmp/failed-drag");
11728        let failed = start_drag(cx, failed_path.clone(), false);
11729        let update_result = cx.update_window(failed.window, |_, window, cx| {
11730            for x_position in [-1., -2.] {
11731                window.dispatch_event(
11732                    MouseMoveEvent {
11733                        position: point(px(x_position), px(20.)),
11734                        pressed_button: Some(MouseButton::Left),
11735                        modifiers: Default::default(),
11736                    }
11737                    .to_platform_input(),
11738                    cx,
11739                );
11740            }
11741            assert!(cx.active_drag.is_some());
11742        });
11743        assert!(
11744            update_result.is_ok(),
11745            "failed to retain drag after platform failure: {update_result:?}"
11746        );
11747        assert_eq!(
11748            cx.test_window(failed.window).external_drag_files(),
11749            [(failed_path, true)]
11750        );
11751    }
11752
11753    crate::actions!(shortcut_lookup_test, [LookupShortcut]);
11754
11755    struct ShortcutTargets {
11756        a: FocusHandle,
11757        b: FocusHandle,
11758    }
11759
11760    impl Render for ShortcutTargets {
11761        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
11762            div()
11763                .key_context("ShortcutRoot")
11764                .child(div().key_context("ShortcutA").track_focus(&self.a))
11765                .child(div().key_context("ShortcutB").track_focus(&self.b))
11766        }
11767    }
11768
11769    #[gpui::test]
11770    fn shortcut_lookup_follows_focus_between_rendered_nodes(cx: &mut TestAppContext) {
11771        cx.update(|cx| {
11772            cx.bind_keys([
11773                KeyBinding::new("ctrl-r", LookupShortcut, Some("ShortcutRoot")),
11774                KeyBinding::new("ctrl-a", LookupShortcut, Some("ShortcutA")),
11775                KeyBinding::new("ctrl-b", LookupShortcut, Some("ShortcutB")),
11776            ])
11777        });
11778        let window = cx.add_window(|window, cx| {
11779            let a = cx.focus_handle();
11780            let b = cx.focus_handle();
11781            window.focus(&a, cx);
11782            ShortcutTargets { a, b }
11783        });
11784        window
11785            .update(cx, |this, window, cx| {
11786                let keys = |window: &Window| {
11787                    window
11788                        .bindings_for_action(&LookupShortcut)
11789                        .iter()
11790                        .map(|binding| binding.keystrokes()[0].key().to_owned())
11791                        .collect::<Vec<_>>()
11792                };
11793                let highest = |window: &Window| {
11794                    window
11795                        .highest_precedence_binding_for_action(&LookupShortcut)
11796                        .map(|binding| binding.keystrokes()[0].key().to_owned())
11797                };
11798                assert_eq!(keys(window), ["r", "a"]);
11799                assert_eq!(highest(window).as_deref(), Some("a"));
11800
11801                window.focus(&this.b, cx);
11802                assert_eq!(keys(window), ["r", "b"]);
11803                assert_eq!(highest(window).as_deref(), Some("b"));
11804
11805                window.blur(cx);
11806                assert!(keys(window).is_empty());
11807                assert_eq!(highest(window), None);
11808            })
11809            .unwrap();
11810    }
11811
11812    struct FocusForwarder {
11813        a: FocusHandle,
11814        b: FocusHandle,
11815    }
11816
11817    impl Render for FocusForwarder {
11818        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
11819            div()
11820                .size_full()
11821                .child(div().w(px(50.)).h(px(50.)).track_focus(&self.a))
11822                .child(div().w(px(50.)).h(px(50.)).track_focus(&self.b))
11823        }
11824    }
11825
11826    /// When a focus listener moves focus again (e.g. a dock forwarding focus to its
11827    /// active panel), the resulting focus events must be dispatched without waiting
11828    /// for an unrelated redraw of the window.
11829    #[gpui::test]
11830    fn test_focus_moved_by_focus_listener_is_dispatched(cx: &mut TestAppContext) {
11831        let b_focus_count = Rc::new(Cell::new(0));
11832        let window = cx.add_window({
11833            let b_focus_count = b_focus_count.clone();
11834            move |window, cx| {
11835                let a = cx.focus_handle();
11836                let b = cx.focus_handle();
11837                cx.on_focus(&a, window, |this: &mut FocusForwarder, window, cx| {
11838                    let b = this.b.clone();
11839                    window.focus(&b, cx);
11840                })
11841                .detach();
11842                cx.on_focus(&b, window, move |_, _, _| {
11843                    b_focus_count.set(b_focus_count.get() + 1);
11844                })
11845                .detach();
11846                FocusForwarder { a, b }
11847            }
11848        });
11849
11850        window.update(cx, |_, window, _| window.activate()).unwrap();
11851        cx.executor().run_until_parked();
11852
11853        window
11854            .update(cx, |this, window, cx| {
11855                let a = this.a.clone();
11856                window.focus(&a, cx);
11857            })
11858            .unwrap();
11859        cx.executor().run_until_parked();
11860
11861        window
11862            .update(cx, |this, window, _| {
11863                assert!(this.b.is_focused(window));
11864            })
11865            .unwrap();
11866        assert_eq!(b_focus_count.get(), 1);
11867    }
11868
11869    #[gpui::test]
11870    fn claimed_touch_drag_receives_movement_and_release(cx: &mut TestAppContext) {
11871        let events = Rc::new(RefCell::new(Vec::new()));
11872        let window = cx.add_window({
11873            let events = events.clone();
11874            move |_, _| TouchDragListener { events }
11875        });
11876        let touch = TouchId(1);
11877
11878        dispatch_touch(window, cx, touch, TouchPhase::Started, 10.);
11879        dispatch_touch(window, cx, touch, TouchPhase::Moved, 30.);
11880        dispatch_touch(window, cx, touch, TouchPhase::Ended, 40.);
11881
11882        assert_eq!(
11883            events.borrow().as_slice(),
11884            [
11885                (TouchPhase::Started, px(10.)),
11886                (TouchPhase::Moved, px(30.)),
11887                (TouchPhase::Ended, px(40.)),
11888            ]
11889        );
11890    }
11891
11892    struct TouchDragListener {
11893        events: Rc<RefCell<Vec<(TouchPhase, Pixels)>>>,
11894    }
11895
11896    impl Render for TouchDragListener {
11897        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
11898            let events = self.events.clone();
11899            canvas(
11900                |_, _, _| {},
11901                move |_, _, window, _| {
11902                    window.on_mouse_event(move |event: &TouchDragEvent, phase, window, _cx| {
11903                        if phase != DispatchPhase::Bubble {
11904                            return;
11905                        }
11906                        events.borrow_mut().push((event.phase, event.position.x));
11907                        if event.phase == TouchPhase::Started {
11908                            window.prevent_default();
11909                        }
11910                    });
11911                },
11912            )
11913        }
11914    }
11915
11916    #[gpui::test]
11917    fn long_press_is_claimed_only_when_started_prevents_default(cx: &mut TestAppContext) {
11918        for response in [
11919            LongPressResponse::PreventDefault,
11920            LongPressResponse::StopPropagation,
11921            LongPressResponse::None,
11922        ] {
11923            let phases = Rc::new(RefCell::new(Vec::new()));
11924            let window = cx.add_window({
11925                let phases = phases.clone();
11926                move |_, _| LongPressListener { phases, response }
11927            });
11928            dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
11929            cx.executor().advance_clock(Duration::from_millis(501));
11930            cx.executor().run_until_parked();
11931            window
11932                .update(cx, |_, window, _| {
11933                    assert_eq!(
11934                        window.long_press_capture.is_some(),
11935                        response == LongPressResponse::PreventDefault
11936                    );
11937                })
11938                .unwrap();
11939            dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.);
11940            dispatch_touch(window, cx, TouchId(1), TouchPhase::Ended, 2.);
11941            window
11942                .update(cx, |_, window, _| {
11943                    assert!(window.long_press_capture.is_none());
11944                })
11945                .unwrap();
11946
11947            let phases = phases.borrow();
11948            if response == LongPressResponse::PreventDefault {
11949                assert_eq!(
11950                    phases.as_slice(),
11951                    [TouchPhase::Started, TouchPhase::Moved, TouchPhase::Ended]
11952                );
11953            } else {
11954                assert_eq!(phases.as_slice(), [TouchPhase::Started]);
11955            }
11956        }
11957    }
11958
11959    #[gpui::test]
11960    fn stale_default_prevention_does_not_claim_long_press(cx: &mut TestAppContext) {
11961        let phases = Rc::new(RefCell::new(Vec::new()));
11962        let window = cx.add_window({
11963            let phases = phases.clone();
11964            move |_, _| LongPressListener {
11965                phases,
11966                response: LongPressResponse::None,
11967            }
11968        });
11969        window
11970            .update(cx, |_, window, _| {
11971                window.prevent_default();
11972            })
11973            .unwrap();
11974
11975        dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
11976        cx.executor().advance_clock(Duration::from_millis(501));
11977        cx.executor().run_until_parked();
11978        dispatch_touch(window, cx, TouchId(1), TouchPhase::Moved, 2.);
11979
11980        assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]);
11981    }
11982
11983    #[gpui::test]
11984    fn resolved_touch_cancels_scheduled_long_press(cx: &mut TestAppContext) {
11985        for (phase, position) in [
11986            (TouchPhase::Ended, 0.),
11987            (TouchPhase::Cancelled, 0.),
11988            (TouchPhase::Moved, 20.),
11989        ] {
11990            let phases = Rc::new(RefCell::new(Vec::new()));
11991            let window = cx.add_window({
11992                let phases = phases.clone();
11993                move |_, _| LongPressListener {
11994                    phases,
11995                    response: LongPressResponse::PreventDefault,
11996                }
11997            });
11998            dispatch_touch(window, cx, TouchId(1), TouchPhase::Started, 0.);
11999            dispatch_touch(window, cx, TouchId(1), phase, position);
12000            cx.executor().advance_clock(Duration::from_millis(501));
12001            cx.executor().run_until_parked();
12002
12003            assert!(phases.borrow().is_empty(), "{phase:?} allowed long press");
12004        }
12005    }
12006
12007    #[gpui::test]
12008    fn stale_long_press_timer_cannot_affect_replacement_touch(cx: &mut TestAppContext) {
12009        let phases = Rc::new(RefCell::new(Vec::new()));
12010        let window = cx.add_window({
12011            let phases = phases.clone();
12012            move |_, _| LongPressListener {
12013                phases,
12014                response: LongPressResponse::PreventDefault,
12015            }
12016        });
12017        let first_touch = TouchId(1);
12018        dispatch_touch(window, cx, first_touch, TouchPhase::Started, 0.);
12019        cx.executor().advance_clock(Duration::from_millis(250));
12020        dispatch_touch(window, cx, first_touch, TouchPhase::Cancelled, 0.);
12021        dispatch_touch(window, cx, TouchId(2), TouchPhase::Started, 10.);
12022
12023        cx.executor().advance_clock(Duration::from_millis(251));
12024        cx.executor().run_until_parked();
12025        assert!(phases.borrow().is_empty());
12026
12027        cx.executor().advance_clock(Duration::from_millis(250));
12028        cx.executor().run_until_parked();
12029        assert_eq!(phases.borrow().as_slice(), [TouchPhase::Started]);
12030    }
12031
12032    #[gpui::test]
12033    fn test_underline_exclusions_preserve_device_geometry(cx: &mut TestAppContext) {
12034        test_underline_paint_at_scales(cx, |window| {
12035            let (numerator, denominator) = match window.scale_factor() {
12036                1.0 => (1, 1),
12037                1.25 => (5, 4),
12038                1.5 => (3, 2),
12039                2.0 => (2, 1),
12040                3.0 => (3, 1),
12041                scale => panic!("unexpected scale {scale}"),
12042            };
12043            let snap = |quarters: i32| {
12044                let scaled = quarters * numerator;
12045                let divisor = 4 * denominator;
12046                let rounded =
12047                    scaled.abs() / divisor + i32::from(2 * (scaled.abs() % divisor) > divisor);
12048                ScaledPixels((scaled.signum() * rounded) as f32)
12049            };
12050            let stroke = |quarters| {
12051                if quarters == 0 {
12052                    ScaledPixels(0.)
12053                } else {
12054                    snap(quarters).max(ScaledPixels(1.))
12055                }
12056            };
12057
12058            for origin in [-101, -3, -2, -1, 0, 1, 2, 3, 101] {
12059                for width in [0, 1, 3, 84] {
12060                    for thickness in [0, 1, 4, 7] {
12061                        for wavy in [false, true] {
12062                            let style = UnderlineStyle {
12063                                thickness: px(thickness as f32 / 4.),
12064                                color: Some(hsla(0.25, 0.5, 0.75, 0.5)),
12065                                wavy,
12066                            };
12067                            let bounds = Bounds::new(
12068                                point(snap(origin), snap(-origin)),
12069                                size(
12070                                    stroke(width),
12071                                    stroke(thickness) * if wavy { 3. } else { 1. },
12072                                ),
12073                            );
12074                            let origin = point(px(origin as f32 / 4.), px(-origin as f32 / 4.));
12075                            let width = px(width as f32 / 4.);
12076                            assert_eq!(window.underline_bounds(origin, width, &style), bounds);
12077                            let original = paint_test_underlines(window, |window| {
12078                                window.paint_underline(origin, width, &style);
12079                            })
12080                            .to_vec();
12081                            assert_eq!(original.len(), usize::from(!bounds.is_empty()));
12082                            if let Some(underline) = original.first() {
12083                                assert_eq!(underline.bounds, bounds);
12084                                assert_eq!(underline.thickness, stroke(thickness));
12085                                assert_eq!(underline.wavy, wavy.into());
12086                                assert_eq!(underline.color, hsla(0.25, 0.5, 0.75, 0.5).into());
12087                            }
12088
12089                            let underlines = paint_test_underlines(window, |window| {
12090                                window.paint_underline_with_exclusions(origin, width, &style, &[]);
12091                            });
12092                            assert_eq!(underlines.len(), original.len());
12093                            for (actual, original) in underlines.iter().zip(&original) {
12094                                assert_same_underline_geometry(actual, original);
12095                                assert_eq!(actual.content_mask, original.content_mask);
12096                                assert_eq!(actual.clip_bounds, original.clip_bounds);
12097                            }
12098
12099                            let left = bounds.left().0 as i32;
12100                            let right = bounds.right().0 as i32;
12101                            let exclusions = [
12102                                (15, 25),
12103                                (3, 7),
12104                                (5, 10),
12105                                (10, 12),
12106                                (0, 0),
12107                                (4, 2),
12108                                (-50, -1),
12109                                (70, 100),
12110                            ]
12111                            .map(|(start, end)| {
12112                                ScaledPixels((left + start) as f32)
12113                                    ..ScaledPixels((left + end) as f32)
12114                            });
12115                            let underlines = paint_test_underlines(window, |window| {
12116                                window.paint_underline_with_exclusions(
12117                                    origin,
12118                                    width,
12119                                    &style,
12120                                    &exclusions,
12121                                );
12122                            });
12123                            let expected = (left..right)
12124                                .filter(|column| {
12125                                    !bounds.is_empty()
12126                                        && !exclusions.iter().any(|span| {
12127                                            span.contains(&ScaledPixels(*column as f32))
12128                                        })
12129                                })
12130                                .collect::<Vec<_>>();
12131                            assert_eq!(underline_device_columns(underlines), expected);
12132                            let mut expected_clip_spans: Vec<(ScaledPixels, ScaledPixels)> =
12133                                Vec::new();
12134                            for column in &expected {
12135                                let start = ScaledPixels(*column as f32);
12136                                let end = ScaledPixels((*column + 1) as f32);
12137                                if let Some((_, previous_end)) = expected_clip_spans.last_mut() {
12138                                    if *previous_end == start {
12139                                        *previous_end = end;
12140                                        continue;
12141                                    }
12142                                }
12143                                expected_clip_spans.push((start, end));
12144                            }
12145                            let actual_clip_spans = underlines
12146                                .iter()
12147                                .filter_map(|underline| {
12148                                    let visible_bounds = underline
12149                                        .bounds
12150                                        .intersect(&underline.content_mask.bounds)
12151                                        .intersect(&underline.clip_bounds);
12152                                    (!visible_bounds.is_empty())
12153                                        .then_some((visible_bounds.left(), visible_bounds.right()))
12154                                })
12155                                .collect::<Vec<_>>();
12156                            assert_eq!(actual_clip_spans, expected_clip_spans);
12157                            for underline in underlines {
12158                                assert_same_underline_geometry(underline, &original[0]);
12159                                assert_eq!(underline.content_mask, original[0].content_mask);
12160                                let visible_bounds = underline
12161                                    .bounds
12162                                    .intersect(&underline.content_mask.bounds)
12163                                    .intersect(&underline.clip_bounds);
12164                                let full_visible_bounds =
12165                                    bounds.intersect(&original[0].content_mask.bounds);
12166                                assert_eq!(visible_bounds.top(), full_visible_bounds.top());
12167                                assert_eq!(visible_bounds.bottom(), full_visible_bounds.bottom());
12168                            }
12169                        }
12170                    }
12171                }
12172            }
12173        });
12174    }
12175
12176    #[gpui::test]
12177    fn test_underline_exclusions_preserve_helvetica_warning_edge(cx: &mut TestAppContext) {
12178        test_underline_paint_at_scales(cx, |window| {
12179            if window.scale_factor() != 2.0 {
12180                return;
12181            }
12182            let style = UnderlineStyle {
12183                thickness: px(1.),
12184                color: None,
12185                wavy: true,
12186            };
12187            let origin = point(px(2.888_183_8), px(15.357_917));
12188            let width = px(23.848_145) - origin.x;
12189            let original = paint_test_underlines(window, |window| {
12190                window.paint_underline(origin, width, &style);
12191            })[0];
12192            assert_eq!(original.bounds.left(), ScaledPixels(6.));
12193            assert_eq!(original.bounds.right(), ScaledPixels(48.));
12194            let point_bounds = window.underline_bounds(origin, px(10.829_102), &style);
12195            assert_eq!(point_bounds.left(), ScaledPixels(6.));
12196            assert_eq!(point_bounds.right(), ScaledPixels(28.));
12197
12198            let underlines = paint_test_underlines(window, |window| {
12199                window.paint_underline_with_exclusions(
12200                    origin,
12201                    width,
12202                    &style,
12203                    &[point_bounds.left()..point_bounds.right()],
12204                );
12205            });
12206            assert_eq!(underlines.len(), 1);
12207            assert_same_underline_geometry(&underlines[0], &original);
12208            assert_eq!(underlines[0].content_mask, original.content_mask);
12209            assert_eq!(underlines[0].clip_bounds.left(), point_bounds.right());
12210            assert_eq!(underlines[0].clip_bounds.right(), original.bounds.right());
12211            assert_eq!(
12212                underline_device_columns(underlines),
12213                (28..48).collect::<Vec<_>>()
12214            );
12215        });
12216    }
12217
12218    #[gpui::test]
12219    fn test_underline_exclusions_preserve_content_mask_and_opacity(cx: &mut TestAppContext) {
12220        test_underline_paint_at_scales(cx, |window| {
12221            let scale = window.scale_factor();
12222            let original_mask = window.content_mask();
12223            let mask = ContentMask {
12224                bounds: Bounds::from_corners(point(px(4.), px(10.)), point(px(16.), px(12.))),
12225                fade_out: Edges {
12226                    left: px(4.),
12227                    top: px(0.5),
12228                    right: px(2.),
12229                    bottom: px(0.25),
12230                },
12231            };
12232            let style = UnderlineStyle {
12233                thickness: px(2.),
12234                color: Some(hsla(0.25, 0.5, 0.75, 0.5)),
12235                wavy: true,
12236            };
12237            let origin = point(px(-1.25), px(9.25));
12238            let width = px(24.);
12239            window.next_frame.scene.clear();
12240            window.with_content_mask(Some(mask), |window| {
12241                window.with_element_opacity(Some(0.5), |window| {
12242                    window.with_element_opacity(Some(0.5), |window| {
12243                        window.paint_underline(origin, width, &style);
12244                        let original = window.next_frame.scene.underlines[0];
12245                        assert_eq!(original.color, hsla(0.25, 0.5, 0.75, 0.5).into());
12246                        window.paint_underline_with_exclusions(
12247                            origin,
12248                            width,
12249                            &style,
12250                            &[ScaledPixels(6. * scale)..ScaledPixels(8. * scale)],
12251                        );
12252                        let underlines = &window.next_frame.scene.underlines[1..];
12253                        assert_eq!(underlines.len(), 2);
12254                        let original_bounds = original.content_mask.bounds;
12255                        let expected_mask = original.content_mask;
12256                        let visible_bounds = original.bounds.intersect(&original_bounds);
12257                        let expected_clip_spans = [(4. * scale, 6. * scale), (8. * scale, 16. * scale)].map(
12258                            |(left, right)| {
12259                                Bounds::from_corners(
12260                                    point(ScaledPixels(left), visible_bounds.top()),
12261                                    point(ScaledPixels(right), visible_bounds.bottom()),
12262                                )
12263                            },
12264                        );
12265                        assert!(expected_mask.fade_out.left > ScaledPixels(0.));
12266                        assert!(expected_mask.fade_out.right > ScaledPixels(0.));
12267                        assert!(expected_mask.fade_out.top > ScaledPixels(0.));
12268                        assert!(expected_mask.fade_out.bottom > ScaledPixels(0.));
12269                        let left_fade_end = expected_mask.bounds.left() + expected_mask.fade_out.left;
12270                        assert!(expected_clip_spans[0].right() > expected_mask.bounds.left());
12271                        assert!(expected_clip_spans[0].right() < left_fade_end);
12272                        assert_eq!(
12273                            underlines.iter().map(|underline| underline.clip_bounds).collect::<Vec<_>>(),
12274                            expected_clip_spans
12275                        );
12276                        assert_eq!(
12277                            underlines.iter().map(|underline| underline.content_mask).collect::<Vec<_>>(),
12278                            vec![expected_mask; 2],
12279                            "a clip boundary inside the 4px left fade must retain the original fade ramp"
12280                        );
12281                        for underline in underlines {
12282                            assert_same_underline_geometry(underline, &original);
12283                            assert_eq!(underline.bounds, original.bounds);
12284                        }
12285                    });
12286                });
12287            });
12288            let boundaries = &window.next_frame.scene.filter_boundaries;
12289            assert_eq!(boundaries.len(), 4);
12290            assert_eq!(
12291                boundaries
12292                    .iter()
12293                    .map(|b| (b.is_start, b.opacity))
12294                    .collect::<Vec<_>>(),
12295                vec![(true, 0.5), (true, 0.5), (false, 0.5), (false, 0.5)],
12296            );
12297            assert_eq!(window.content_mask(), original_mask);
12298        });
12299    }
12300
12301    #[gpui::test]
12302    fn test_underline_exclusions_adversarial_permutations(cx: &mut TestAppContext) {
12303        test_underline_paint_at_scales(cx, |window| {
12304            let style = UnderlineStyle {
12305                thickness: px(1.),
12306                color: None,
12307                wavy: true,
12308            };
12309            let origin = point(px(-4.), px(-1.));
12310            let width = px(8.);
12311            let left = (-4. * window.scale_factor()) as i32;
12312            let right = (4. * window.scale_factor()) as i32;
12313            let endpoints = [-16, -8, -1, 0, 1, 8, 16];
12314            for first_start in endpoints {
12315                for first_end in endpoints {
12316                    for second_start in endpoints {
12317                        for second_end in endpoints {
12318                            let exclusions = [first_start..first_end, second_start..second_end];
12319                            let expected = (left..right)
12320                                .filter(|column| {
12321                                    !exclusions.iter().any(|span| span.contains(column))
12322                                })
12323                                .collect::<Vec<_>>();
12324                            let exclusions = exclusions.map(|span| {
12325                                ScaledPixels(span.start as f32)..ScaledPixels(span.end as f32)
12326                            });
12327                            let underlines = paint_test_underlines(window, |window| {
12328                                window.paint_underline_with_exclusions(
12329                                    origin,
12330                                    width,
12331                                    &style,
12332                                    &exclusions,
12333                                );
12334                            });
12335                            assert_eq!(
12336                                underline_device_columns(underlines),
12337                                expected,
12338                                "{exclusions:?}"
12339                            );
12340                        }
12341                    }
12342                }
12343            }
12344        });
12345    }
12346
12347    #[derive(Clone, Copy, PartialEq)]
12348    enum LongPressResponse {
12349        PreventDefault,
12350        StopPropagation,
12351        None,
12352    }
12353
12354    struct LongPressListener {
12355        phases: Rc<RefCell<Vec<TouchPhase>>>,
12356        response: LongPressResponse,
12357    }
12358
12359    impl Render for LongPressListener {
12360        fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
12361            let entity = cx.entity();
12362            let phases = self.phases.clone();
12363            let response = self.response;
12364            canvas(
12365                |_, _, _| {},
12366                move |_, _, window, _| {
12367                    window.on_mouse_event(move |event: &LongPressEvent, phase, window, cx| {
12368                        if phase != DispatchPhase::Bubble {
12369                            return;
12370                        }
12371                        phases.borrow_mut().push(event.phase);
12372                        match response {
12373                            LongPressResponse::PreventDefault => {
12374                                window.capture_long_press(&entity);
12375                                window.prevent_default();
12376                            }
12377                            LongPressResponse::StopPropagation => cx.stop_propagation(),
12378                            LongPressResponse::None => {}
12379                        }
12380                    });
12381                },
12382            )
12383        }
12384    }
12385
12386    struct UnderlineTestView(Rc<dyn Fn(&mut Window)>);
12387
12388    impl Render for UnderlineTestView {
12389        fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
12390            let paint = self.0.clone();
12391            canvas(
12392                |_, _, _| {},
12393                move |_, _, window, _| {
12394                    window.content_mask_stack.push(ContentMask {
12395                        bounds: Bounds::from_corners(
12396                            point(px(-1000.), px(-1000.)),
12397                            point(px(1000.), px(1000.)),
12398                        ),
12399                        ..Default::default()
12400                    });
12401                    paint(window);
12402                    window.content_mask_stack.pop();
12403                },
12404            )
12405            .size_full()
12406        }
12407    }
12408
12409    fn test_underline_paint_at_scales(
12410        cx: &mut TestAppContext,
12411        paint: impl Fn(&mut Window) + 'static,
12412    ) {
12413        let window = cx.add_window(move |_, _| UnderlineTestView(Rc::new(paint)));
12414        for scale in [1., 1.25, 1.5, 2., 3.] {
12415            cx.simulate_window_scale_factor_change(window.into(), scale);
12416            cx.update_window(window.into(), |_, window, cx| window.draw(cx).clear(cx))
12417                .unwrap();
12418        }
12419    }
12420
12421    fn paint_test_underlines(window: &mut Window, paint: impl FnOnce(&mut Window)) -> &[Underline] {
12422        window.next_frame.scene.clear();
12423        paint(window);
12424        &window.next_frame.scene.underlines
12425    }
12426
12427    fn assert_same_underline_geometry(actual: &Underline, expected: &Underline) {
12428        assert_eq!(actual.bounds, expected.bounds);
12429        assert_eq!(actual.thickness, expected.thickness);
12430        assert_eq!(actual.wavy, expected.wavy);
12431        assert_eq!(actual.color, expected.color);
12432        assert_eq!(actual.padding, expected.padding);
12433    }
12434
12435    fn underline_device_columns(underlines: &[Underline]) -> Vec<i32> {
12436        underlines
12437            .iter()
12438            .flat_map(|underline| {
12439                let bounds = underline
12440                    .bounds
12441                    .intersect(&underline.content_mask.bounds)
12442                    .intersect(&underline.clip_bounds);
12443                bounds.left().0 as i32..bounds.right().0 as i32
12444            })
12445            .collect()
12446    }
12447
12448    fn dispatch_touch<T: 'static>(
12449        window: crate::WindowHandle<T>,
12450        cx: &mut TestAppContext,
12451        id: TouchId,
12452        phase: TouchPhase,
12453        x: f32,
12454    ) {
12455        window
12456            .update(cx, |_, window, cx| {
12457                window.dispatch_event(
12458                    TouchEvent {
12459                        id,
12460                        phase,
12461                        position: point(px(x), px(0.)),
12462                        predicted_position: None,
12463                        force: None,
12464                    }
12465                    .to_platform_input(),
12466                    cx,
12467                );
12468            })
12469            .unwrap();
12470    }
12471
12472    struct CachedOpacityChild {
12473        renders: Rc<Cell<usize>>,
12474        paints: Rc<Cell<usize>>,
12475    }
12476
12477    impl Render for CachedOpacityChild {
12478        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
12479            self.renders.set(self.renders.get() + 1);
12480            let paints = self.paints.clone();
12481
12482            div().size(px(20.0)).bg(crate::red()).child(
12483                canvas(
12484                    |_, _, _| (),
12485                    move |bounds, _, window, _| {
12486                        paints.set(paints.get() + 1);
12487                        window.paint_quad(PaintQuad::new(bounds).background(crate::blue()));
12488                    },
12489                )
12490                .size_full()
12491                .opacity(0.5),
12492            )
12493        }
12494    }
12495
12496    struct CachedOpacityParent {
12497        opacity: Option<f32>,
12498        child: Entity<CachedOpacityChild>,
12499        cached: bool,
12500    }
12501
12502    impl Render for CachedOpacityParent {
12503        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
12504            let mut child_style = div().size(px(20.0));
12505            let child = if self.cached {
12506                self.child
12507                    .clone()
12508                    .cached(child_style.style().clone())
12509                    .into_any_element()
12510            } else {
12511                self.child.clone().into_any_element()
12512            };
12513
12514            div()
12515                .size(px(40.0))
12516                .when_some(self.opacity, |parent, opacity| parent.opacity(opacity))
12517                .child(child)
12518        }
12519    }
12520
12521    #[test]
12522    fn parent_opacity_changes_replay_cached_canvas_groups() {
12523        let renders = Rc::new(Cell::new(0));
12524        let paints = Rc::new(Cell::new(0));
12525        let mut app = TestApp::new();
12526        let mut test_window = app.open_window(|_, cx| CachedOpacityParent {
12527            opacity: None,
12528            cached: true,
12529            child: cx.new(|_| CachedOpacityChild {
12530                renders: renders.clone(),
12531                paints: paints.clone(),
12532            }),
12533        });
12534        test_window.draw();
12535        let initial_renders = renders.get();
12536        let initial_paints = paints.get();
12537        assert!(initial_renders > 0);
12538        assert!(initial_paints > 0);
12539
12540        let scene_snapshot = |scene: &Scene| {
12541            (
12542                scene.render_commands().to_vec(),
12543                scene
12544                    .quads
12545                    .iter()
12546                    .map(|quad| (quad.order, quad.bounds, quad.content_mask, quad.background))
12547                    .collect::<Vec<_>>(),
12548                scene
12549                    .filter_boundaries
12550                    .iter()
12551                    .map(|boundary| {
12552                        (
12553                            boundary.bounds,
12554                            boundary.content_mask,
12555                            boundary.opacity,
12556                            boundary.is_start,
12557                        )
12558                    })
12559                    .collect::<Vec<_>>(),
12560            )
12561        };
12562
12563        for opacity in [Some(0.5), Some(0.25), Some(1.0), Some(0.0), None] {
12564            let mut fresh_app = TestApp::new();
12565            let mut fresh_window = fresh_app.open_window(|_, cx| CachedOpacityParent {
12566                opacity,
12567                cached: false,
12568                child: cx.new(|_| CachedOpacityChild {
12569                    renders: Rc::new(Cell::new(0)),
12570                    paints: Rc::new(Cell::new(0)),
12571                }),
12572            });
12573            fresh_window.draw();
12574            let fresh_scene =
12575                fresh_window.update(|_, window, _| scene_snapshot(&window.rendered_frame.scene));
12576
12577            test_window.update(|view, _, cx| {
12578                view.opacity = opacity;
12579                cx.notify();
12580            });
12581            test_window.draw();
12582            test_window.update(|_, window, _| {
12583                let scene = &window.rendered_frame.scene;
12584                assert_eq!(scene_snapshot(scene), fresh_scene, "opacity {opacity:?}");
12585            });
12586            assert_eq!(renders.get(), initial_renders);
12587            assert_eq!(paints.get(), initial_paints);
12588        }
12589    }
12590}
12591
12592#[cfg(all(test, any(feature = "inspector", debug_assertions)))]
12593mod inspector_tests {
12594    use super::*;
12595    use crate::{
12596        DivInspectorState, InspectorElementId, InteractiveElement as _, MouseDownEvent,
12597        ParentElement as _, StyleRefinement, Styled as _, TestAppContext, div,
12598    };
12599
12600    #[gpui::test]
12601    fn inspector_only_tracks_its_open_window(cx: &mut TestAppContext) {
12602        let windows = [
12603            cx.add_window(|_, cx| InspectorTestRoot {
12604                child: cx.new(|_| InspectorTestView::default()),
12605            }),
12606            cx.add_window(|_, cx| InspectorTestRoot {
12607                child: cx.new(|_| InspectorTestView::default()),
12608            }),
12609        ];
12610        for window in windows {
12611            assert_closed_inspector(window.into(), cx);
12612        }
12613        for _ in 0..2 {
12614            cx.update_window(windows[0].into(), |root, window, cx| {
12615                let root = root.downcast::<InspectorTestRoot>().expect("test root");
12616                let child_widths = root.read(cx).child.read(cx).child_widths.clone();
12617                window.toggle_inspector(cx);
12618                window.draw(cx).clear(cx);
12619                assert_eq!(child_widths.borrow().as_slice(), &[px(10.); 3]);
12620                let path = window
12621                    .rendered_frame
12622                    .next_inspector_instance_ids
12623                    .iter()
12624                    .find_map(|(path, count)| (*count == 3).then(|| path.clone()))
12625                    .expect("anonymous siblings share an inspector path");
12626                let selected_id = InspectorElementId {
12627                    path,
12628                    instance_id: 1,
12629                };
12630                let position = window
12631                    .rendered_frame
12632                    .hitboxes
12633                    .iter()
12634                    .find(|hitbox| {
12635                        window.rendered_frame.inspector_hitboxes.get(&hitbox.id)
12636                            == Some(&selected_id)
12637                    })
12638                    .expect("middle sibling is pickable")
12639                    .bounds
12640                    .center();
12641                window.simulate_mouse_move(position, cx);
12642                window.dispatch_event(
12643                    PlatformInput::MouseDown(MouseDownEvent {
12644                        position,
12645                        button: MouseButton::Left,
12646                        modifiers: Modifiers::default(),
12647                        click_count: 1,
12648                        first_mouse: false,
12649                    }),
12650                    cx,
12651                );
12652                window.dispatch_event(
12653                    PlatformInput::MouseUp(MouseUpEvent {
12654                        position,
12655                        button: MouseButton::Left,
12656                        modifiers: Modifiers::default(),
12657                        click_count: 1,
12658                    }),
12659                    cx,
12660                );
12661                assert!(!window.is_inspector_picking(cx));
12662                assert_eq!(
12663                    window
12664                        .inspector
12665                        .as_ref()
12666                        .expect("open inspector")
12667                        .read(cx)
12668                        .active_element_id(),
12669                    Some(&selected_id)
12670                );
12671                window.draw(cx).clear(cx);
12672                window.with_inspector_state::<DivInspectorState, _>(
12673                    Some(&selected_id),
12674                    cx,
12675                    |state, _| {
12676                        let state = state.as_mut().expect("selected div has style state");
12677                        assert_eq!(
12678                            state.base_style.size.width,
12679                            Some(crate::Length::from(px(10.)))
12680                        );
12681                        state.base_style.size.width = Some(crate::Length::from(px(25.)));
12682                    },
12683                );
12684                window.refresh();
12685                window.draw(cx).clear(cx);
12686                assert_eq!(
12687                    child_widths.borrow().as_slice(),
12688                    &[px(10.), px(25.), px(10.)]
12689                );
12690            })
12691            .expect("pick and edit a cached child");
12692            assert_closed_inspector(windows[1].into(), cx);
12693            windows[0]
12694                .update(cx, |_, window, cx| window.toggle_inspector(cx))
12695                .expect("close inspector");
12696            assert_closed_inspector(windows[0].into(), cx);
12697        }
12698    }
12699
12700    struct InspectorTestRoot {
12701        child: Entity<InspectorTestView>,
12702    }
12703
12704    impl Render for InspectorTestRoot {
12705        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
12706            self.child
12707                .clone()
12708                .cached(StyleRefinement::default().size(px(100.)))
12709        }
12710    }
12711
12712    #[derive(Default)]
12713    struct InspectorTestView {
12714        child_widths: Rc<RefCell<Vec<Pixels>>>,
12715    }
12716
12717    impl Render for InspectorTestView {
12718        fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
12719            let child_widths = self.child_widths.clone();
12720            div()
12721                .on_children_prepainted(move |bounds, _, _| {
12722                    *child_widths.borrow_mut() =
12723                        bounds.iter().map(|bounds| bounds.size.width).collect();
12724                })
12725                .with_dynamic_prepaint_order(|_, _| SmallVec::from_iter([2, 0, 1]))
12726                .id("inspector-root")
12727                .flex()
12728                .children((0..3).map(|_| div().size(px(10.)).flex_shrink_0()))
12729        }
12730    }
12731
12732    fn assert_closed_inspector(window: AnyWindowHandle, cx: &mut TestAppContext) {
12733        cx.update_window(window, |root, window, cx| {
12734            window.draw(cx).clear(cx);
12735            window.draw(cx).clear(cx);
12736            let root = root.downcast::<InspectorTestRoot>().expect("test root");
12737            assert_eq!(
12738                root.read(cx)
12739                    .child
12740                    .read(cx)
12741                    .child_widths
12742                    .borrow()
12743                    .as_slice(),
12744                &[px(10.); 3]
12745            );
12746            for frame in [&window.rendered_frame, &window.next_frame] {
12747                assert_eq!(frame.next_inspector_instance_ids.capacity(), 0);
12748                assert_eq!(frame.inspector_hitboxes.capacity(), 0);
12749            }
12750        })
12751        .expect("closed inspector has no bookkeeping and no style overrides");
12752    }
12753}