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