Skip to main content

gpui_core/
window.rs

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