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