Skip to main content

gpui_core/
window.rs

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