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, AvailableSpace, Background, BorderStyle, Bounds, BoxShadow, Capslock,
6 Context, Corners, CursorHideMode, CursorStyle, Decorations, DevicePixels,
7 DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity,
8 EntityId, EventEmitter, FileDropEvent, FontId, Global, GlobalElementId, GlyphId, GpuSpecs,
9 Hsla, InputHandler, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke,
10 KeystrokeEvent, LayoutId, LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite,
11 MouseButton, MouseEvent, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas,
12 PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite,
13 Priority, PromptButton, PromptLevel, Quad, Render, RenderGlyphParams, RenderImage,
14 RenderImageParams, RenderSvgParams, Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR,
15 SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y, ScaledPixels, Scene, Shadow, SharedString, Size,
16 StrikethroughStyle, Style, SubpixelSprite, SubscriberSet, Subscription, SystemWindowTab,
17 SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task, TextRenderingMode, TextStyle,
18 TextStyleRefinement, ThermalState, TransformationMatrix, Underline, UnderlineStyle,
19 WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations,
20 WindowOptions, WindowParams, WindowTextSystem, point, prelude::*, profiler, px, rems, size,
21 transparent_black,
22};
23use anyhow::{Context as _, Result, anyhow};
24#[cfg(target_os = "macos")]
25use core_video::pixel_buffer::CVPixelBuffer;
26use derive_more::{Deref, DerefMut};
27use futures::FutureExt;
28use futures::channel::oneshot;
29#[cfg(feature = "input-latency-histogram")]
30use hdrhistogram::Histogram;
31use itertools::FoldWhile::{Continue, Done};
32use itertools::Itertools;
33use open_gpui_collections::{FxHashMap, FxHashSet};
34use open_gpui_core_util::post_inc;
35use open_gpui_core_util::{ResultExt, measure};
36use open_gpui_refineable::Refineable;
37use open_gpui_scheduler::Instant;
38use parking_lot::RwLock;
39use raw_window_handle::{HandleError, HasDisplayHandle, HasWindowHandle};
40use slotmap::SlotMap;
41use smallvec::SmallVec;
42use std::{
43 any::{Any, TypeId},
44 borrow::Cow,
45 cell::{Cell, RefCell},
46 cmp,
47 fmt::{Debug, Display},
48 hash::{Hash, Hasher},
49 marker::PhantomData,
50 mem,
51 ops::{DerefMut, Range},
52 rc::Rc,
53 sync::{
54 Arc, Weak,
55 atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst},
56 },
57 time::Duration,
58};
59use uuid::Uuid;
60
61pub(crate) mod a11y;
62mod prompts;
63
64use self::a11y::A11y;
65#[cfg(not(target_family = "wasm"))]
66use self::a11y::ROOT_NODE_ID;
67use crate::util::{
68 atomic_incr_if_not_zero, ceil_to_device_pixel, floor_to_device_pixel, round_half_toward_zero,
69 round_half_toward_zero_f64, round_stroke_to_device_pixel, round_to_device_pixel,
70};
71pub use prompts::*;
72
73pub const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1536.), px(1095.));
75
76pub const DEFAULT_ADDITIONAL_WINDOW_SIZE: Size<Pixels> = Size {
79 width: Pixels(900.),
80 height: Pixels(750.),
81};
82
83#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
85pub enum DispatchPhase {
86 #[default]
91 Bubble,
92 Capture,
98}
99
100impl DispatchPhase {
101 #[inline]
103 pub fn bubble(self) -> bool {
104 self == DispatchPhase::Bubble
105 }
106
107 #[inline]
109 pub fn capture(self) -> bool {
110 self == DispatchPhase::Capture
111 }
112}
113
114struct WindowInvalidatorInner {
115 pub dirty: bool,
116 pub draw_phase: DrawPhase,
117 pub dirty_views: FxHashSet<EntityId>,
118 pub update_count: usize,
119}
120
121#[derive(Clone)]
122pub(crate) struct WindowInvalidator {
123 inner: Rc<RefCell<WindowInvalidatorInner>>,
124}
125
126impl WindowInvalidator {
127 pub fn new() -> Self {
128 WindowInvalidator {
129 inner: Rc::new(RefCell::new(WindowInvalidatorInner {
130 dirty: true,
131 draw_phase: DrawPhase::None,
132 dirty_views: FxHashSet::default(),
133 update_count: 0,
134 })),
135 }
136 }
137
138 pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {
139 let mut inner = self.inner.borrow_mut();
140 inner.update_count += 1;
141 inner.dirty_views.insert(entity);
142 if inner.draw_phase == DrawPhase::None {
143 inner.dirty = true;
144 cx.push_effect(Effect::Notify { emitter: entity });
145 true
146 } else {
147 false
148 }
149 }
150
151 pub fn is_dirty(&self) -> bool {
152 self.inner.borrow().dirty
153 }
154
155 pub fn set_dirty(&self, dirty: bool) {
156 let mut inner = self.inner.borrow_mut();
157 inner.dirty = dirty;
158 if dirty {
159 inner.update_count += 1;
160 }
161 }
162
163 pub fn set_phase(&self, phase: DrawPhase) {
164 self.inner.borrow_mut().draw_phase = phase
165 }
166
167 pub fn update_count(&self) -> usize {
168 self.inner.borrow().update_count
169 }
170
171 pub fn take_views(&self) -> FxHashSet<EntityId> {
172 mem::take(&mut self.inner.borrow_mut().dirty_views)
173 }
174
175 pub fn replace_views(&self, views: FxHashSet<EntityId>) {
176 self.inner.borrow_mut().dirty_views = views;
177 }
178
179 pub fn not_drawing(&self) -> bool {
180 self.inner.borrow().draw_phase == DrawPhase::None
181 }
182
183 #[track_caller]
184 pub fn debug_assert_paint(&self) {
185 debug_assert!(
186 matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),
187 "this method can only be called during paint"
188 );
189 }
190
191 #[track_caller]
192 pub fn debug_assert_prepaint(&self) {
193 debug_assert!(
194 matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),
195 "this method can only be called during request_layout, or prepaint"
196 );
197 }
198
199 #[track_caller]
200 pub fn debug_assert_paint_or_prepaint(&self) {
201 debug_assert!(
202 matches!(
203 self.inner.borrow().draw_phase,
204 DrawPhase::Paint | DrawPhase::Prepaint
205 ),
206 "this method can only be called during request_layout, prepaint, or paint"
207 );
208 }
209}
210
211type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;
212
213pub(crate) type AnyWindowFocusListener =
214 Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;
215
216pub(crate) struct WindowFocusEvent {
217 pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,
218 pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,
219}
220
221impl WindowFocusEvent {
222 pub fn is_focus_in(&self, focus_id: FocusId) -> bool {
223 !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)
224 }
225
226 pub fn is_focus_out(&self, focus_id: FocusId) -> bool {
227 self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)
228 }
229}
230
231pub struct FocusOutEvent {
233 pub blurred: WeakFocusHandle,
235}
236
237slotmap::new_key_type! {
238 pub struct FocusId;
240}
241
242thread_local! {
243 pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));
246
247 static CURRENT_ELEMENT_ARENA: Cell<Option<*const RefCell<Arena>>> = const { Cell::new(None) };
251}
252
253pub(crate) fn with_element_arena<R>(f: impl FnOnce(&mut Arena) -> R) -> R {
256 CURRENT_ELEMENT_ARENA.with(|current| {
257 if let Some(arena_ptr) = current.get() {
258 let arena_cell = unsafe { &*arena_ptr };
261 f(&mut arena_cell.borrow_mut())
262 } else {
263 ELEMENT_ARENA.with_borrow_mut(f)
264 }
265 })
266}
267
268pub(crate) struct ElementArenaScope {
271 previous: Option<*const RefCell<Arena>>,
272}
273
274impl ElementArenaScope {
275 pub(crate) fn enter(arena: &RefCell<Arena>) -> Self {
277 let previous = CURRENT_ELEMENT_ARENA.with(|current| {
278 let prev = current.get();
279 current.set(Some(arena as *const RefCell<Arena>));
280 prev
281 });
282 Self { previous }
283 }
284}
285
286impl Drop for ElementArenaScope {
287 fn drop(&mut self) {
288 CURRENT_ELEMENT_ARENA.with(|current| {
289 current.set(self.previous);
290 });
291 }
292}
293
294#[must_use]
296pub struct ArenaClearNeeded {
297 arena: *const RefCell<Arena>,
298}
299
300impl ArenaClearNeeded {
301 pub(crate) fn new(arena: &RefCell<Arena>) -> Self {
303 Self {
304 arena: arena as *const RefCell<Arena>,
305 }
306 }
307
308 pub fn clear(self) {
310 let arena_cell = unsafe { &*self.arena };
313 arena_cell.borrow_mut().clear();
314 }
315}
316
317pub(crate) type FocusMap = RwLock<SlotMap<FocusId, FocusRef>>;
318pub(crate) struct FocusRef {
319 pub(crate) ref_count: AtomicUsize,
320 pub(crate) tab_index: isize,
321 pub(crate) tab_stop: bool,
322}
323
324impl FocusId {
325 pub fn is_focused(&self, window: &Window) -> bool {
327 window.focus == Some(*self)
328 }
329
330 pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
333 window
334 .focused(cx)
335 .is_some_and(|focused| self.contains(focused.id, window))
336 }
337
338 pub fn within_focused(&self, window: &Window, cx: &App) -> bool {
341 let focused = window.focused(cx);
342 focused.is_some_and(|focused| focused.id.contains(*self, window))
343 }
344
345 pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {
347 window
348 .rendered_frame
349 .dispatch_tree
350 .focus_contains(*self, other)
351 }
352}
353
354pub struct FocusHandle {
356 pub(crate) id: FocusId,
357 handles: Arc<FocusMap>,
358 pub tab_index: isize,
360 pub tab_stop: bool,
362}
363
364impl std::fmt::Debug for FocusHandle {
365 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
366 f.write_fmt(format_args!("FocusHandle({:?})", self.id))
367 }
368}
369
370impl FocusHandle {
371 pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {
372 let id = handles.write().insert(FocusRef {
373 ref_count: AtomicUsize::new(1),
374 tab_index: 0,
375 tab_stop: false,
376 });
377
378 Self {
379 id,
380 tab_index: 0,
381 tab_stop: false,
382 handles: handles.clone(),
383 }
384 }
385
386 pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {
387 let lock = handles.read();
388 let focus = lock.get(id)?;
389 if atomic_incr_if_not_zero(&focus.ref_count) == 0 {
390 return None;
391 }
392 Some(Self {
393 id,
394 tab_index: focus.tab_index,
395 tab_stop: focus.tab_stop,
396 handles: handles.clone(),
397 })
398 }
399
400 pub fn tab_index(mut self, index: isize) -> Self {
402 self.tab_index = index;
403 if let Some(focus) = self.handles.write().get_mut(self.id) {
404 focus.tab_index = index;
405 }
406 self
407 }
408
409 pub fn tab_stop(mut self, tab_stop: bool) -> Self {
413 self.tab_stop = tab_stop;
414 if let Some(focus) = self.handles.write().get_mut(self.id) {
415 focus.tab_stop = tab_stop;
416 }
417 self
418 }
419
420 pub fn downgrade(&self) -> WeakFocusHandle {
422 WeakFocusHandle {
423 id: self.id,
424 handles: Arc::downgrade(&self.handles),
425 }
426 }
427
428 pub fn focus(&self, window: &mut Window, cx: &mut App) {
430 window.focus(self, cx)
431 }
432
433 pub fn is_focused(&self, window: &Window) -> bool {
435 self.id.is_focused(window)
436 }
437
438 pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
441 self.id.contains_focused(window, cx)
442 }
443
444 pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {
447 self.id.within_focused(window, cx)
448 }
449
450 pub fn contains(&self, other: &Self, window: &Window) -> bool {
452 self.id.contains(other.id, window)
453 }
454
455 pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {
457 if let Some(node_id) = window
458 .rendered_frame
459 .dispatch_tree
460 .focusable_node_id(self.id)
461 {
462 window.dispatch_action_on_node(node_id, action, cx)
463 }
464 }
465}
466
467impl Clone for FocusHandle {
468 fn clone(&self) -> Self {
469 Self::for_id(self.id, &self.handles).unwrap()
470 }
471}
472
473impl PartialEq for FocusHandle {
474 fn eq(&self, other: &Self) -> bool {
475 self.id == other.id
476 }
477}
478
479impl Eq for FocusHandle {}
480
481impl Drop for FocusHandle {
482 fn drop(&mut self) {
483 self.handles
484 .read()
485 .get(self.id)
486 .unwrap()
487 .ref_count
488 .fetch_sub(1, SeqCst);
489 }
490}
491
492#[derive(Clone, Debug)]
494pub struct WeakFocusHandle {
495 pub(crate) id: FocusId,
496 pub(crate) handles: Weak<FocusMap>,
497}
498
499impl WeakFocusHandle {
500 pub fn upgrade(&self) -> Option<FocusHandle> {
502 let handles = self.handles.upgrade()?;
503 FocusHandle::for_id(self.id, &handles)
504 }
505}
506
507impl PartialEq for WeakFocusHandle {
508 fn eq(&self, other: &WeakFocusHandle) -> bool {
509 self.id == other.id
510 }
511}
512
513impl Eq for WeakFocusHandle {}
514
515impl PartialEq<FocusHandle> for WeakFocusHandle {
516 fn eq(&self, other: &FocusHandle) -> bool {
517 self.id == other.id
518 }
519}
520
521impl PartialEq<WeakFocusHandle> for FocusHandle {
522 fn eq(&self, other: &WeakFocusHandle) -> bool {
523 self.id == other.id
524 }
525}
526
527pub trait Focusable: 'static {
530 fn focus_handle(&self, cx: &App) -> FocusHandle;
532}
533
534impl<V: Focusable> Focusable for Entity<V> {
535 fn focus_handle(&self, cx: &App) -> FocusHandle {
536 self.read(cx).focus_handle(cx)
537 }
538}
539
540pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}
543
544impl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}
545
546pub struct DismissEvent;
548
549type FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;
550
551pub(crate) type AnyMouseListener =
552 Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
553
554#[derive(Clone)]
555pub(crate) struct CursorStyleRequest {
556 pub(crate) hitbox_id: Option<HitboxId>,
557 pub(crate) style: CursorStyle,
558}
559
560#[derive(Default, Eq, PartialEq)]
561pub(crate) struct HitTest {
562 pub(crate) ids: SmallVec<[HitboxId; 8]>,
563 pub(crate) hover_hitbox_count: usize,
564}
565
566#[derive(Clone, Copy, Debug, Eq, PartialEq)]
568pub enum WindowControlArea {
569 Drag,
571 Close,
573 Max,
575 Min,
577}
578
579#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
581pub struct HitboxId(u64);
582
583#[cfg(feature = "test-support")]
584impl HitboxId {
585 pub const fn placeholder() -> Self {
590 Self(0)
591 }
592}
593
594impl HitboxId {
595 pub fn is_hovered(self, window: &Window) -> bool {
602 if window.captured_hitbox == Some(self) {
604 return true;
605 }
606 if window.last_input_was_keyboard() {
607 return false;
608 }
609 self.hit_test(window)
610 }
611
612 pub(crate) fn is_hovered_ignoring_last_input(self, window: &Window) -> bool {
617 if window.captured_hitbox == Some(self) {
619 return true;
620 }
621 self.hit_test(window)
622 }
623
624 fn hit_test(self, window: &Window) -> bool {
625 let hit_test = &window.mouse_hit_test;
626 for id in hit_test.ids.iter().take(hit_test.hover_hitbox_count) {
627 if self == *id {
628 return true;
629 }
630 }
631 false
632 }
633
634 pub fn should_handle_scroll(self, window: &Window) -> bool {
639 window.mouse_hit_test.ids.contains(&self)
640 }
641
642 fn next(mut self) -> HitboxId {
643 HitboxId(self.0.wrapping_add(1))
644 }
645}
646
647#[derive(Clone, Debug, Deref)]
650pub struct Hitbox {
651 pub id: HitboxId,
653 #[deref]
655 pub bounds: Bounds<Pixels>,
656 pub content_mask: ContentMask<Pixels>,
658 pub behavior: HitboxBehavior,
660}
661
662impl Hitbox {
663 pub fn is_hovered(&self, window: &Window) -> bool {
680 self.id.is_hovered(window)
681 }
682
683 pub fn should_handle_scroll(&self, window: &Window) -> bool {
690 self.id.should_handle_scroll(window)
691 }
692}
693
694#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
696pub enum HitboxBehavior {
697 #[default]
699 Normal,
700
701 BlockMouse,
723
724 BlockMouseExceptScroll,
751}
752
753#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
755pub struct TooltipId(usize);
756
757impl TooltipId {
758 pub fn is_hovered(&self, window: &Window) -> bool {
760 window
761 .tooltip_bounds
762 .as_ref()
763 .is_some_and(|tooltip_bounds| {
764 tooltip_bounds.id == *self
765 && tooltip_bounds.bounds.contains(&window.mouse_position())
766 })
767 }
768}
769
770pub(crate) struct TooltipBounds {
771 id: TooltipId,
772 bounds: Bounds<Pixels>,
773}
774
775#[derive(Clone)]
776pub(crate) struct TooltipRequest {
777 id: TooltipId,
778 tooltip: AnyTooltip,
779}
780
781pub(crate) struct DeferredDraw {
782 current_view: EntityId,
783 priority: usize,
784 parent_node: DispatchNodeId,
785 element_id_stack: SmallVec<[ElementId; 32]>,
786 text_style_stack: Vec<TextStyleRefinement>,
787 content_mask: Option<ContentMask<Pixels>>,
788 rem_size: Pixels,
789 element: Option<AnyElement>,
790 absolute_offset: Point<Pixels>,
791 prepaint_range: Range<PrepaintStateIndex>,
792 paint_range: Range<PaintIndex>,
793}
794
795pub(crate) struct Frame {
796 pub(crate) focus: Option<FocusId>,
797 pub(crate) window_active: bool,
798 pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
799 accessed_element_states: Vec<(GlobalElementId, TypeId)>,
800 pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
801 pub(crate) dispatch_tree: DispatchTree,
802 pub(crate) scene: Scene,
803 pub(crate) hitboxes: Vec<Hitbox>,
804 pub(crate) window_control_hitboxes: Vec<(WindowControlArea, Hitbox)>,
805 pub(crate) deferred_draws: Vec<DeferredDraw>,
806 pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
807 pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,
808 pub(crate) cursor_styles: Vec<CursorStyleRequest>,
809 #[cfg(any(test, feature = "test-support"))]
810 pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
811 #[cfg(any(feature = "inspector", debug_assertions))]
812 pub(crate) next_inspector_instance_ids: FxHashMap<Rc<crate::InspectorElementPath>, usize>,
813 #[cfg(any(feature = "inspector", debug_assertions))]
814 pub(crate) inspector_hitboxes: FxHashMap<HitboxId, crate::InspectorElementId>,
815 pub(crate) tab_stops: TabStopMap,
816}
817
818#[derive(Clone, Default)]
819pub(crate) struct PrepaintStateIndex {
820 hitboxes_index: usize,
821 tooltips_index: usize,
822 deferred_draws_index: usize,
823 dispatch_tree_index: usize,
824 accessed_element_states_index: usize,
825 line_layout_index: LineLayoutIndex,
826}
827
828#[derive(Clone, Default)]
829pub(crate) struct PaintIndex {
830 scene_index: usize,
831 mouse_listeners_index: usize,
832 input_handlers_index: usize,
833 cursor_styles_index: usize,
834 accessed_element_states_index: usize,
835 tab_handle_index: usize,
836 line_layout_index: LineLayoutIndex,
837}
838
839impl Frame {
840 pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
841 Frame {
842 focus: None,
843 window_active: false,
844 element_states: FxHashMap::default(),
845 accessed_element_states: Vec::new(),
846 mouse_listeners: Vec::new(),
847 dispatch_tree,
848 scene: Scene::default(),
849 hitboxes: Vec::new(),
850 window_control_hitboxes: Vec::new(),
851 deferred_draws: Vec::new(),
852 input_handlers: Vec::new(),
853 tooltip_requests: Vec::new(),
854 cursor_styles: Vec::new(),
855
856 #[cfg(any(test, feature = "test-support"))]
857 debug_bounds: FxHashMap::default(),
858
859 #[cfg(any(feature = "inspector", debug_assertions))]
860 next_inspector_instance_ids: FxHashMap::default(),
861
862 #[cfg(any(feature = "inspector", debug_assertions))]
863 inspector_hitboxes: FxHashMap::default(),
864 tab_stops: TabStopMap::default(),
865 }
866 }
867
868 pub(crate) fn clear(&mut self) {
869 self.element_states.clear();
870 self.accessed_element_states.clear();
871 self.mouse_listeners.clear();
872 self.dispatch_tree.clear();
873 self.scene.clear();
874 self.input_handlers.clear();
875 self.tooltip_requests.clear();
876 self.cursor_styles.clear();
877 self.hitboxes.clear();
878 self.window_control_hitboxes.clear();
879 self.deferred_draws.clear();
880 self.tab_stops.clear();
881 self.focus = None;
882
883 #[cfg(any(test, feature = "test-support"))]
884 {
885 self.debug_bounds.clear();
886 }
887
888 #[cfg(any(feature = "inspector", debug_assertions))]
889 {
890 self.next_inspector_instance_ids.clear();
891 self.inspector_hitboxes.clear();
892 }
893 }
894
895 pub(crate) fn cursor_style(&self, window: &Window) -> Option<CursorStyle> {
896 self.cursor_styles
897 .iter()
898 .rev()
899 .fold_while(None, |style, request| match request.hitbox_id {
900 None => Done(Some(request.style)),
901 Some(hitbox_id) => Continue(style.or_else(|| {
902 hitbox_id
903 .is_hovered_ignoring_last_input(window)
904 .then_some(request.style)
905 })),
906 })
907 .into_inner()
908 }
909
910 pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
911 let mut set_hover_hitbox_count = false;
912 let mut hit_test = HitTest::default();
913 for hitbox in self.hitboxes.iter().rev() {
914 let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);
915 if bounds.contains(&position) {
916 hit_test.ids.push(hitbox.id);
917 if !set_hover_hitbox_count
918 && hitbox.behavior == HitboxBehavior::BlockMouseExceptScroll
919 {
920 hit_test.hover_hitbox_count = hit_test.ids.len();
921 set_hover_hitbox_count = true;
922 }
923 if hitbox.behavior == HitboxBehavior::BlockMouse {
924 break;
925 }
926 }
927 }
928 if !set_hover_hitbox_count {
929 hit_test.hover_hitbox_count = hit_test.ids.len();
930 }
931 hit_test
932 }
933
934 pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
935 self.focus
936 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
937 .unwrap_or_default()
938 }
939
940 pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
941 for element_state_key in &self.accessed_element_states {
942 if let Some((element_state_key, element_state)) =
943 prev_frame.element_states.remove_entry(element_state_key)
944 {
945 self.element_states.insert(element_state_key, element_state);
946 }
947 }
948
949 self.scene.finish();
950 }
951}
952
953#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
954enum InputModality {
955 Mouse,
956 Keyboard,
957}
958
959pub struct Window {
961 pub(crate) handle: AnyWindowHandle,
962 pub(crate) invalidator: WindowInvalidator,
963 pub(crate) removed: bool,
964 pub(crate) platform_window: Box<dyn PlatformWindow>,
965 display_id: Option<DisplayId>,
966 sprite_atlas: Arc<dyn PlatformAtlas>,
967 text_system: Arc<WindowTextSystem>,
968 text_rendering_mode: Rc<Cell<TextRenderingMode>>,
969 rem_size: Pixels,
970 rem_size_override_stack: SmallVec<[Pixels; 8]>,
975 pub(crate) viewport_size: Size<Pixels>,
976 layout_engine: Option<TaffyLayoutEngine>,
977 pub(crate) root: Option<AnyView>,
978 pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,
979 pub(crate) text_style_stack: Vec<TextStyleRefinement>,
980 pub(crate) rendered_entity_stack: Vec<EntityId>,
981 pub(crate) element_offset_stack: Vec<Point<Pixels>>,
982 pub(crate) element_opacity: f32,
983 pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
984 pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,
985 pub(crate) image_cache_stack: Vec<AnyImageCache>,
986 pub(crate) rendered_frame: Frame,
987 pub(crate) next_frame: Frame,
988 next_hitbox_id: HitboxId,
989 pub(crate) next_tooltip_id: TooltipId,
990 pub(crate) tooltip_bounds: Option<TooltipBounds>,
991 next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
992 pub(crate) dirty_views: FxHashSet<EntityId>,
993 focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
994 pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,
995 default_prevented: bool,
996 mouse_position: Point<Pixels>,
997 mouse_hit_test: HitTest,
998 modifiers: Modifiers,
999 capslock: Capslock,
1000 scale_factor: f32,
1001 pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
1002 appearance: WindowAppearance,
1003 pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,
1004 pub(crate) button_layout_observers: SubscriberSet<(), AnyObserver>,
1005 active: Rc<Cell<bool>>,
1006 hovered: Rc<Cell<bool>>,
1007 pub(crate) needs_present: Rc<Cell<bool>>,
1008 pub(crate) input_rate_tracker: Rc<RefCell<InputRateTracker>>,
1011 #[cfg(feature = "input-latency-histogram")]
1012 input_latency_tracker: InputLatencyTracker,
1013 last_input_modality: InputModality,
1014 pub(crate) refreshing: bool,
1015 pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,
1016 pub(crate) focus: Option<FocusId>,
1017 focus_enabled: bool,
1018 pending_input: Option<PendingInput>,
1019 pending_modifier: ModifierState,
1020 pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,
1021 prompt: Option<RenderablePromptHandle>,
1022 pub(crate) client_inset: Option<Pixels>,
1023 captured_hitbox: Option<HitboxId>,
1026 #[cfg(any(feature = "inspector", debug_assertions))]
1027 inspector: Option<Entity<Inspector>>,
1028 pub(crate) a11y: A11y,
1029}
1030
1031#[derive(Clone, Debug, Default)]
1032struct ModifierState {
1033 modifiers: Modifiers,
1034 saw_keystroke: bool,
1035}
1036
1037#[derive(Clone, Debug)]
1040pub(crate) struct InputRateTracker {
1041 timestamps: Vec<Instant>,
1042 window: Duration,
1043 inputs_per_second: u32,
1044 sustain_until: Instant,
1045 sustain_duration: Duration,
1046}
1047
1048impl Default for InputRateTracker {
1049 fn default() -> Self {
1050 Self {
1051 timestamps: Vec::new(),
1052 window: Duration::from_millis(100),
1053 inputs_per_second: 60,
1054 sustain_until: Instant::now(),
1055 sustain_duration: Duration::from_secs(1),
1056 }
1057 }
1058}
1059
1060impl InputRateTracker {
1061 pub fn record_input(&mut self) {
1062 let now = Instant::now();
1063 self.timestamps.push(now);
1064 self.prune_old_timestamps(now);
1065
1066 let min_events = self.inputs_per_second as u128 * self.window.as_millis() / 1000;
1067 if self.timestamps.len() as u128 >= min_events {
1068 self.sustain_until = now + self.sustain_duration;
1069 }
1070 }
1071
1072 pub fn is_high_rate(&self) -> bool {
1073 Instant::now() < self.sustain_until
1074 }
1075
1076 fn prune_old_timestamps(&mut self, now: Instant) {
1077 self.timestamps
1078 .retain(|&t| now.duration_since(t) <= self.window);
1079 }
1080}
1081
1082#[cfg(feature = "input-latency-histogram")]
1085pub struct InputLatencySnapshot {
1086 pub latency_histogram: Histogram<u64>,
1088 pub events_per_frame_histogram: Histogram<u64>,
1090 pub mid_draw_events_dropped: u64,
1093}
1094
1095#[cfg(feature = "input-latency-histogram")]
1099struct InputLatencyTracker {
1100 first_input_at: Option<Instant>,
1103 pending_input_count: u64,
1105 latency_histogram: Histogram<u64>,
1107 events_per_frame_histogram: Histogram<u64>,
1109 mid_draw_events_dropped: u64,
1112}
1113
1114#[cfg(feature = "input-latency-histogram")]
1115impl InputLatencyTracker {
1116 fn new() -> Result<Self> {
1117 Ok(Self {
1118 first_input_at: None,
1119 pending_input_count: 0,
1120 latency_histogram: Histogram::new(3)
1121 .map_err(|e| anyhow!("Failed to create input latency histogram: {e}"))?,
1122 events_per_frame_histogram: Histogram::new(3)
1123 .map_err(|e| anyhow!("Failed to create events per frame histogram: {e}"))?,
1124 mid_draw_events_dropped: 0,
1125 })
1126 }
1127
1128 fn record_input(&mut self, dispatch_time: Instant) {
1131 self.first_input_at.get_or_insert(dispatch_time);
1132 self.pending_input_count += 1;
1133 }
1134
1135 fn record_mid_draw_input(&mut self) {
1138 self.mid_draw_events_dropped += 1;
1139 }
1140
1141 fn record_frame_presented(&mut self) {
1143 if let Some(first_input_at) = self.first_input_at.take() {
1144 let latency_nanos = first_input_at.elapsed().as_nanos() as u64;
1145 self.latency_histogram.record(latency_nanos).ok();
1146 }
1147 if self.pending_input_count > 0 {
1148 self.events_per_frame_histogram
1149 .record(self.pending_input_count)
1150 .ok();
1151 self.pending_input_count = 0;
1152 }
1153 }
1154
1155 fn snapshot(&self) -> InputLatencySnapshot {
1156 InputLatencySnapshot {
1157 latency_histogram: self.latency_histogram.clone(),
1158 events_per_frame_histogram: self.events_per_frame_histogram.clone(),
1159 mid_draw_events_dropped: self.mid_draw_events_dropped,
1160 }
1161 }
1162}
1163
1164#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1165pub(crate) enum DrawPhase {
1166 None,
1167 Prepaint,
1168 Paint,
1169 Focus,
1170}
1171
1172#[derive(Default, Debug)]
1173struct PendingInput {
1174 keystrokes: SmallVec<[Keystroke; 1]>,
1175 focus: Option<FocusId>,
1176 timer: Option<Task<()>>,
1177 needs_timeout: bool,
1178}
1179
1180pub(crate) struct ElementStateBox {
1181 pub(crate) inner: Box<dyn Any>,
1182 #[cfg(debug_assertions)]
1183 pub(crate) type_name: &'static str,
1184}
1185
1186fn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> WindowBounds {
1187 let active_window_bounds = cx
1192 .active_window()
1193 .and_then(|w| w.update(cx, |_, window, _| window.window_bounds()).ok());
1194
1195 const CASCADE_OFFSET: f32 = 25.0;
1196
1197 let display = display_id
1198 .map(|id| cx.find_display(id))
1199 .unwrap_or_else(|| cx.primary_display());
1200
1201 let default_placement = || Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE);
1202
1203 let display_bounds = display
1205 .as_ref()
1206 .map(|d| d.visible_bounds())
1207 .unwrap_or_else(default_placement);
1208
1209 let (
1210 Bounds {
1211 origin: base_origin,
1212 size: base_size,
1213 },
1214 window_bounds_ctor,
1215 ): (_, fn(Bounds<Pixels>) -> WindowBounds) = match active_window_bounds {
1216 Some(bounds) => match bounds {
1217 WindowBounds::Windowed(bounds) => (bounds, WindowBounds::Windowed),
1218 WindowBounds::Maximized(bounds) => (bounds, WindowBounds::Maximized),
1219 WindowBounds::Fullscreen(bounds) => (bounds, WindowBounds::Fullscreen),
1220 },
1221 None => (
1222 display
1223 .as_ref()
1224 .map(|d| d.default_bounds())
1225 .unwrap_or_else(default_placement),
1226 WindowBounds::Windowed,
1227 ),
1228 };
1229
1230 let cascade_offset = point(px(CASCADE_OFFSET), px(CASCADE_OFFSET));
1231 let proposed_origin = base_origin + cascade_offset;
1232 let proposed_bounds = Bounds::new(proposed_origin, base_size);
1233
1234 let display_right = display_bounds.origin.x + display_bounds.size.width;
1235 let display_bottom = display_bounds.origin.y + display_bounds.size.height;
1236 let window_right = proposed_bounds.origin.x + proposed_bounds.size.width;
1237 let window_bottom = proposed_bounds.origin.y + proposed_bounds.size.height;
1238
1239 let fits_horizontally = window_right <= display_right;
1240 let fits_vertically = window_bottom <= display_bottom;
1241
1242 let final_origin = match (fits_horizontally, fits_vertically) {
1243 (true, true) => proposed_origin,
1244 (false, true) => point(display_bounds.origin.x, base_origin.y),
1245 (true, false) => point(base_origin.x, display_bounds.origin.y),
1246 (false, false) => display_bounds.origin,
1247 };
1248 window_bounds_ctor(Bounds::new(final_origin, base_size))
1249}
1250
1251impl Window {
1252 pub(crate) fn new(
1253 handle: AnyWindowHandle,
1254 options: WindowOptions,
1255 cx: &mut App,
1256 ) -> Result<Self> {
1257 let WindowOptions {
1258 window_bounds,
1259 titlebar,
1260 focus,
1261 show,
1262 kind,
1263 is_movable,
1264 is_resizable,
1265 is_minimizable,
1266 display_id,
1267 window_background,
1268 app_id,
1269 window_min_size,
1270 window_decorations,
1271 #[cfg_attr(
1272 not(any(target_os = "linux", target_os = "freebsd")),
1273 allow(unused_variables)
1274 )]
1275 icon,
1276 #[cfg_attr(not(target_os = "macos"), allow(unused_variables))]
1277 tabbing_identifier,
1278 } = options;
1279
1280 let window_bounds = window_bounds.unwrap_or_else(|| default_bounds(display_id, cx));
1281 let mut platform_window = cx.platform.open_window(
1282 handle,
1283 WindowParams {
1284 bounds: window_bounds.get_bounds(),
1285 titlebar,
1286 kind,
1287 is_movable,
1288 is_resizable,
1289 is_minimizable,
1290 focus,
1291 show,
1292 display_id,
1293 window_min_size,
1294 icon,
1295 #[cfg(target_os = "macos")]
1296 tabbing_identifier,
1297 },
1298 )?;
1299
1300 let tab_bar_visible = platform_window.tab_bar_visible();
1301 SystemWindowTabController::init_visible(cx, tab_bar_visible);
1302 if let Some(tabs) = platform_window.tabbed_windows() {
1303 SystemWindowTabController::add_tab(cx, handle.window_id(), tabs);
1304 }
1305
1306 let display_id = platform_window.display().map(|display| display.id());
1307 let sprite_atlas = platform_window.sprite_atlas();
1308 let mouse_position = platform_window.mouse_position();
1309 let modifiers = platform_window.modifiers();
1310 let capslock = platform_window.capslock();
1311 let content_size = platform_window.content_size();
1312 let scale_factor = platform_window.scale_factor();
1313 let appearance = platform_window.appearance();
1314 let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
1315 let invalidator = WindowInvalidator::new();
1316 let active = Rc::new(Cell::new(platform_window.is_active()));
1317 let hovered = Rc::new(Cell::new(platform_window.is_hovered()));
1318 let needs_present = Rc::new(Cell::new(false));
1319 let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
1320 let input_rate_tracker = Rc::new(RefCell::new(InputRateTracker::default()));
1321 let last_frame_time = Rc::new(Cell::new(None));
1322
1323 platform_window
1324 .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));
1325 platform_window.set_background_appearance(window_background);
1326
1327 match window_bounds {
1328 WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),
1329 WindowBounds::Maximized(_) => platform_window.zoom(),
1330 WindowBounds::Windowed(_) => {}
1331 }
1332
1333 let accessibility_force_disabled = cx.accessibility_force_disabled;
1334 let a11y_active_flag = Arc::new(AtomicBool::new(false));
1335
1336 #[cfg(not(target_family = "wasm"))]
1337 if !accessibility_force_disabled {
1338 let initial_tree = accesskit::TreeUpdate {
1339 nodes: vec![(ROOT_NODE_ID, accesskit::Node::new(accesskit::Role::Window))],
1340 tree: Some(accesskit::Tree::new(ROOT_NODE_ID)),
1341 tree_id: accesskit::TreeId::ROOT,
1342 focus: ROOT_NODE_ID,
1343 };
1344 let (activation_sender, activation_receiver) = async_channel::unbounded::<()>();
1345 let (deactivation_sender, deactivation_receiver) = async_channel::unbounded::<()>();
1346 let (action_sender, action_receiver) =
1347 async_channel::unbounded::<accesskit::ActionRequest>();
1348
1349 platform_window.a11y_init(crate::A11yCallbacks {
1350 activation: {
1351 let active_flag = a11y_active_flag.clone();
1352 Box::new(move || {
1353 log::info!("Accessibility activated");
1354 active_flag.store(true, SeqCst);
1355 activation_sender.send_blocking(()).log_err();
1356 Some(initial_tree.clone())
1357 })
1358 },
1359 action: Box::new(move |request| {
1360 action_sender.send_blocking(request).log_err();
1361 }),
1362 deactivation: {
1363 let active_flag = a11y_active_flag.clone();
1364 Box::new(move || {
1365 log::info!("Accessibility deactivated");
1366 active_flag.store(false, SeqCst);
1367 deactivation_sender.send_blocking(()).log_err();
1368 })
1369 },
1370 });
1371
1372 let mut async_cx = cx.to_async();
1378 cx.foreground_executor()
1379 .spawn(async move {
1380 while activation_receiver.recv().await.is_ok() {
1381 handle
1382 .update(&mut async_cx, |_, window, _| window.refresh())
1383 .log_err();
1384 }
1385 })
1386 .detach();
1387
1388 let mut async_cx = cx.to_async();
1389 cx.foreground_executor()
1390 .spawn(async move {
1391 while deactivation_receiver.recv().await.is_ok() {
1392 handle
1393 .update(&mut async_cx, |_, window, _| window.refresh())
1394 .log_err();
1395 }
1396 })
1397 .detach();
1398
1399 let mut async_cx = cx.to_async();
1400 cx.foreground_executor()
1401 .spawn(async move {
1402 while let Ok(request) = action_receiver.recv().await {
1403 handle
1404 .update(&mut async_cx, |_, window, cx| {
1405 window.handle_a11y_action(request, cx);
1406 })
1407 .log_err();
1408 }
1409 })
1410 .detach();
1411 }
1412
1413 platform_window.on_close(Box::new({
1414 let window_id = handle.window_id();
1415 let mut cx = cx.to_async();
1416 move || {
1417 let _ = handle.update(&mut cx, |_, window, _| window.remove_window());
1418 let _ = cx.update(|cx| {
1419 SystemWindowTabController::remove_tab(cx, window_id);
1420 });
1421 }
1422 }));
1423 platform_window.on_request_frame(Box::new({
1424 let mut cx = cx.to_async();
1425 let invalidator = invalidator.clone();
1426 let active = active.clone();
1427 let needs_present = needs_present.clone();
1428 let next_frame_callbacks = next_frame_callbacks.clone();
1429 let input_rate_tracker = input_rate_tracker.clone();
1430 move |request_frame_options| {
1431 let thermal_state = handle
1432 .update(&mut cx, |_, _, cx| cx.thermal_state())
1433 .log_err();
1434
1435 let min_frame_interval = if !request_frame_options.force_render
1439 && !request_frame_options.require_presentation
1440 && next_frame_callbacks.borrow().is_empty()
1441 {
1442 None
1443 } else if !active.get() {
1444 Some(Duration::from_micros(33333))
1445 } else if let Some(ThermalState::Critical | ThermalState::Serious) = thermal_state {
1446 Some(Duration::from_micros(16667))
1447 } else {
1448 None
1449 };
1450
1451 let now = Instant::now();
1452 if let Some(min_interval) = min_frame_interval {
1453 if let Some(last_frame) = last_frame_time.get()
1454 && now.duration_since(last_frame) < min_interval
1455 {
1456 handle
1461 .update(&mut cx, |_, window, _| window.complete_frame())
1462 .log_err();
1463 return;
1464 }
1465 }
1466 last_frame_time.set(Some(now));
1467
1468 let next_frame_callbacks = next_frame_callbacks.take();
1469 if !next_frame_callbacks.is_empty() {
1470 handle
1471 .update(&mut cx, |_, window, cx| {
1472 for callback in next_frame_callbacks {
1473 callback(window, cx);
1474 }
1475 })
1476 .log_err();
1477 }
1478
1479 let needs_present = request_frame_options.require_presentation
1483 || needs_present.get()
1484 || (active.get() && input_rate_tracker.borrow_mut().is_high_rate());
1485
1486 if invalidator.is_dirty() || request_frame_options.force_render {
1487 measure("frame duration", || {
1488 handle
1489 .update(&mut cx, |_, window, cx| {
1490 if request_frame_options.force_render {
1491 window.refresh();
1494 }
1495 let arena_clear_needed = window.draw(cx);
1496 window.present();
1497 arena_clear_needed.clear();
1498 })
1499 .log_err();
1500 })
1501 } else if needs_present {
1502 handle
1503 .update(&mut cx, |_, window, _| window.present())
1504 .log_err();
1505 }
1506
1507 handle
1508 .update(&mut cx, |_, window, _| {
1509 window.complete_frame();
1510 })
1511 .log_err();
1512 }
1513 }));
1514 platform_window.on_resize(Box::new({
1515 let mut cx = cx.to_async();
1516 move |_, _| {
1517 handle
1518 .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1519 .log_err();
1520 }
1521 }));
1522 platform_window.on_moved(Box::new({
1523 let mut cx = cx.to_async();
1524 move || {
1525 handle
1526 .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1527 .log_err();
1528 }
1529 }));
1530 platform_window.on_appearance_changed(Box::new({
1531 let mut cx = cx.to_async();
1532 move || {
1533 handle
1534 .update(&mut cx, |_, window, cx| window.appearance_changed(cx))
1535 .log_err();
1536 }
1537 }));
1538 platform_window.on_button_layout_changed(Box::new({
1539 let mut cx = cx.to_async();
1540 move || {
1541 handle
1542 .update(&mut cx, |_, window, cx| window.button_layout_changed(cx))
1543 .log_err();
1544 }
1545 }));
1546 platform_window.on_active_status_change(Box::new({
1547 let mut cx = cx.to_async();
1548 move |active| {
1549 handle
1550 .update(&mut cx, |_, window, cx| {
1551 window.active.set(active);
1552 window.modifiers = window.platform_window.modifiers();
1553 window.capslock = window.platform_window.capslock();
1554 window
1555 .activation_observers
1556 .clone()
1557 .retain(&(), |callback| callback(window, cx));
1558
1559 window.bounds_changed(cx);
1560 window.refresh();
1561
1562 SystemWindowTabController::update_last_active(cx, window.handle.id);
1563 })
1564 .log_err();
1565 }
1566 }));
1567 platform_window.on_hover_status_change(Box::new({
1568 let mut cx = cx.to_async();
1569 move |active| {
1570 handle
1571 .update(&mut cx, |_, window, _| {
1572 window.hovered.set(active);
1573 window.refresh();
1574 })
1575 .log_err();
1576 }
1577 }));
1578 platform_window.on_input({
1579 let mut cx = cx.to_async();
1580 Box::new(move |event| {
1581 handle
1582 .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))
1583 .log_err()
1584 .unwrap_or(DispatchEventResult::default())
1585 })
1586 });
1587 platform_window.on_hit_test_window_control({
1588 let mut cx = cx.to_async();
1589 Box::new(move || {
1590 handle
1591 .update(&mut cx, |_, window, _cx| {
1592 for (area, hitbox) in &window.rendered_frame.window_control_hitboxes {
1593 if window.mouse_hit_test.ids.contains(&hitbox.id) {
1594 return Some(*area);
1595 }
1596 }
1597 None
1598 })
1599 .log_err()
1600 .unwrap_or(None)
1601 })
1602 });
1603 platform_window.on_move_tab_to_new_window({
1604 let mut cx = cx.to_async();
1605 Box::new(move || {
1606 handle
1607 .update(&mut cx, |_, _window, cx| {
1608 SystemWindowTabController::move_tab_to_new_window(cx, handle.window_id());
1609 })
1610 .log_err();
1611 })
1612 });
1613 platform_window.on_merge_all_windows({
1614 let mut cx = cx.to_async();
1615 Box::new(move || {
1616 handle
1617 .update(&mut cx, |_, _window, cx| {
1618 SystemWindowTabController::merge_all_windows(cx, handle.window_id());
1619 })
1620 .log_err();
1621 })
1622 });
1623 platform_window.on_select_next_tab({
1624 let mut cx = cx.to_async();
1625 Box::new(move || {
1626 handle
1627 .update(&mut cx, |_, _window, cx| {
1628 SystemWindowTabController::select_next_tab(cx, handle.window_id());
1629 })
1630 .log_err();
1631 })
1632 });
1633 platform_window.on_select_previous_tab({
1634 let mut cx = cx.to_async();
1635 Box::new(move || {
1636 handle
1637 .update(&mut cx, |_, _window, cx| {
1638 SystemWindowTabController::select_previous_tab(cx, handle.window_id())
1639 })
1640 .log_err();
1641 })
1642 });
1643 platform_window.on_toggle_tab_bar({
1644 let mut cx = cx.to_async();
1645 Box::new(move || {
1646 handle
1647 .update(&mut cx, |_, window, cx| {
1648 let tab_bar_visible = window.platform_window.tab_bar_visible();
1649 SystemWindowTabController::set_visible(cx, tab_bar_visible);
1650 })
1651 .log_err();
1652 })
1653 });
1654
1655 if let Some(app_id) = app_id {
1656 platform_window.set_app_id(&app_id);
1657 }
1658
1659 platform_window.map_window().unwrap();
1660
1661 Ok(Window {
1662 handle,
1663 invalidator,
1664 removed: false,
1665 platform_window,
1666 display_id,
1667 sprite_atlas,
1668 text_system,
1669 text_rendering_mode: cx.text_rendering_mode.clone(),
1670 rem_size: px(16.),
1671 rem_size_override_stack: SmallVec::new(),
1672 viewport_size: content_size,
1673 layout_engine: Some(TaffyLayoutEngine::new()),
1674 root: None,
1675 element_id_stack: SmallVec::default(),
1676 text_style_stack: Vec::new(),
1677 rendered_entity_stack: Vec::new(),
1678 element_offset_stack: Vec::new(),
1679 content_mask_stack: Vec::new(),
1680 element_opacity: 1.0,
1681 requested_autoscroll: None,
1682 rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1683 next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1684 next_frame_callbacks,
1685 next_hitbox_id: HitboxId(0),
1686 next_tooltip_id: TooltipId::default(),
1687 tooltip_bounds: None,
1688 dirty_views: FxHashSet::default(),
1689 focus_listeners: SubscriberSet::new(),
1690 focus_lost_listeners: SubscriberSet::new(),
1691 default_prevented: true,
1692 mouse_position,
1693 mouse_hit_test: HitTest::default(),
1694 modifiers,
1695 capslock,
1696 scale_factor,
1697 bounds_observers: SubscriberSet::new(),
1698 appearance,
1699 appearance_observers: SubscriberSet::new(),
1700 button_layout_observers: SubscriberSet::new(),
1701 active,
1702 hovered,
1703 needs_present,
1704 input_rate_tracker,
1705 #[cfg(feature = "input-latency-histogram")]
1706 input_latency_tracker: InputLatencyTracker::new()?,
1707 last_input_modality: InputModality::Mouse,
1708 refreshing: false,
1709 activation_observers: SubscriberSet::new(),
1710 focus: None,
1711 focus_enabled: true,
1712 pending_input: None,
1713 pending_modifier: ModifierState::default(),
1714 pending_input_observers: SubscriberSet::new(),
1715 prompt: None,
1716 client_inset: None,
1717 image_cache_stack: Vec::new(),
1718 captured_hitbox: None,
1719 #[cfg(any(feature = "inspector", debug_assertions))]
1720 inspector: None,
1721 a11y: A11y::new(a11y_active_flag, accessibility_force_disabled),
1722 })
1723 }
1724
1725 pub(crate) fn new_focus_listener(
1726 &self,
1727 value: AnyWindowFocusListener,
1728 ) -> (Subscription, impl FnOnce() + use<>) {
1729 self.focus_listeners.insert((), value)
1730 }
1731}
1732
1733#[derive(Clone, Debug, Default, PartialEq, Eq)]
1734#[expect(missing_docs)]
1735pub struct DispatchEventResult {
1736 pub propagate: bool,
1737 pub default_prevented: bool,
1738}
1739
1740#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
1744#[repr(C)]
1745pub struct ContentMask<P: Clone + Debug + Default + PartialEq> {
1746 pub bounds: Bounds<P>,
1748}
1749
1750impl ContentMask<Pixels> {
1751 pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
1753 ContentMask {
1754 bounds: self.bounds.scale(factor),
1755 }
1756 }
1757
1758 pub fn intersect(&self, other: &Self) -> Self {
1760 let bounds = self.bounds.intersect(&other.bounds);
1761 ContentMask { bounds }
1762 }
1763}
1764
1765impl Window {
1766 fn mark_view_dirty(&mut self, view_id: EntityId) {
1767 for view_id in self
1770 .rendered_frame
1771 .dispatch_tree
1772 .view_path_reversed(view_id)
1773 {
1774 if !self.dirty_views.insert(view_id) {
1775 break;
1776 }
1777 }
1778 }
1779
1780 pub fn observe_window_appearance(
1782 &self,
1783 mut callback: impl FnMut(&mut Window, &mut App) + 'static,
1784 ) -> Subscription {
1785 let (subscription, activate) = self.appearance_observers.insert(
1786 (),
1787 Box::new(move |window, cx| {
1788 callback(window, cx);
1789 true
1790 }),
1791 );
1792 activate();
1793 subscription
1794 }
1795
1796 pub fn observe_button_layout_changed(
1798 &self,
1799 mut callback: impl FnMut(&mut Window, &mut App) + 'static,
1800 ) -> Subscription {
1801 let (subscription, activate) = self.button_layout_observers.insert(
1802 (),
1803 Box::new(move |window, cx| {
1804 callback(window, cx);
1805 true
1806 }),
1807 );
1808 activate();
1809 subscription
1810 }
1811
1812 pub fn replace_root<E>(
1814 &mut self,
1815 cx: &mut App,
1816 build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,
1817 ) -> Entity<E>
1818 where
1819 E: 'static + Render,
1820 {
1821 let view = cx.new(|cx| build_view(self, cx));
1822 self.root = Some(view.clone().into());
1823 self.refresh();
1824 view
1825 }
1826
1827 pub fn root<E>(&self) -> Option<Option<Entity<E>>>
1829 where
1830 E: 'static + Render,
1831 {
1832 self.root
1833 .as_ref()
1834 .map(|view| view.clone().downcast::<E>().ok())
1835 }
1836
1837 pub fn window_handle(&self) -> AnyWindowHandle {
1839 self.handle
1840 }
1841
1842 pub fn refresh(&mut self) {
1844 if self.invalidator.not_drawing() {
1845 self.refreshing = true;
1846 self.invalidator.set_dirty(true);
1847 }
1848 }
1849
1850 pub fn remove_window(&mut self) {
1852 self.removed = true;
1853 }
1854
1855 pub fn focused(&self, cx: &App) -> Option<FocusHandle> {
1857 self.focus
1858 .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))
1859 }
1860
1861 pub fn focus(&mut self, handle: &FocusHandle, cx: &mut App) {
1863 if !self.focus_enabled || self.focus == Some(handle.id) {
1864 return;
1865 }
1866
1867 self.focus = Some(handle.id);
1868 self.clear_pending_keystrokes();
1869
1870 let window_handle = self.handle;
1873 cx.defer(move |cx| {
1874 window_handle
1875 .update(cx, |_, window, cx| {
1876 window.pending_input_changed(cx);
1877 })
1878 .ok();
1879 });
1880
1881 self.refresh();
1882 }
1883
1884 pub fn blur(&mut self) {
1886 if !self.focus_enabled {
1887 return;
1888 }
1889
1890 self.focus = None;
1891 self.refresh();
1892 }
1893
1894 pub fn disable_focus(&mut self) {
1896 self.blur();
1897 self.focus_enabled = false;
1898 }
1899
1900 pub fn focus_next(&mut self, cx: &mut App) {
1902 if !self.focus_enabled {
1903 return;
1904 }
1905
1906 if let Some(handle) = self.rendered_frame.tab_stops.next(self.focus.as_ref()) {
1907 self.focus(&handle, cx)
1908 }
1909 }
1910
1911 pub fn focus_prev(&mut self, cx: &mut App) {
1913 if !self.focus_enabled {
1914 return;
1915 }
1916
1917 if let Some(handle) = self.rendered_frame.tab_stops.prev(self.focus.as_ref()) {
1918 self.focus(&handle, cx)
1919 }
1920 }
1921
1922 pub fn text_system(&self) -> &Arc<WindowTextSystem> {
1924 &self.text_system
1925 }
1926
1927 pub fn text_style(&self) -> TextStyle {
1929 let mut style = TextStyle::default();
1930 for refinement in &self.text_style_stack {
1931 style.refine(refinement);
1932 }
1933 style
1934 }
1935
1936 pub fn is_maximized(&self) -> bool {
1940 self.platform_window.is_maximized()
1941 }
1942
1943 pub fn request_decorations(&self, decorations: WindowDecorations) {
1945 self.platform_window.request_decorations(decorations);
1946 }
1947
1948 pub fn start_window_resize(&self, edge: ResizeEdge) {
1950 self.platform_window.start_window_resize(edge);
1951 }
1952
1953 pub fn window_bounds(&self) -> WindowBounds {
1956 self.platform_window.window_bounds()
1957 }
1958
1959 pub fn inner_window_bounds(&self) -> WindowBounds {
1961 self.platform_window.inner_window_bounds()
1962 }
1963
1964 pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {
1966 let focus_id = self.focused(cx).map(|handle| handle.id);
1967
1968 let window = self.handle;
1969 cx.defer(move |cx| {
1970 window
1971 .update(cx, |_, window, cx| {
1972 let node_id = window.focus_node_id_in_rendered_frame(focus_id);
1973 window.dispatch_action_on_node(node_id, action.as_ref(), cx);
1974 })
1975 .log_err();
1976 })
1977 }
1978
1979 pub(crate) fn dispatch_keystroke_observers(
1980 &mut self,
1981 event: &dyn Any,
1982 action: Option<Box<dyn Action>>,
1983 context_stack: Vec<KeyContext>,
1984 cx: &mut App,
1985 ) {
1986 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
1987 return;
1988 };
1989
1990 cx.keystroke_observers.clone().retain(&(), move |callback| {
1991 (callback)(
1992 &KeystrokeEvent {
1993 keystroke: key_down_event.keystroke.clone(),
1994 action: action.as_ref().map(|action| action.boxed_clone()),
1995 context_stack: context_stack.clone(),
1996 },
1997 self,
1998 cx,
1999 )
2000 });
2001 }
2002
2003 pub(crate) fn dispatch_keystroke_interceptors(
2004 &mut self,
2005 event: &dyn Any,
2006 context_stack: Vec<KeyContext>,
2007 cx: &mut App,
2008 ) {
2009 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
2010 return;
2011 };
2012
2013 cx.keystroke_interceptors
2014 .clone()
2015 .retain(&(), move |callback| {
2016 (callback)(
2017 &KeystrokeEvent {
2018 keystroke: key_down_event.keystroke.clone(),
2019 action: None,
2020 context_stack: context_stack.clone(),
2021 },
2022 self,
2023 cx,
2024 )
2025 });
2026 }
2027
2028 pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {
2031 let handle = self.handle;
2032 cx.defer(move |cx| {
2033 handle.update(cx, |_, window, cx| f(window, cx)).ok();
2034 });
2035 }
2036
2037 pub fn observe<T: 'static>(
2041 &mut self,
2042 observed: &Entity<T>,
2043 cx: &mut App,
2044 mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,
2045 ) -> Subscription {
2046 let entity_id = observed.entity_id();
2047 let observed = observed.downgrade();
2048 let window_handle = self.handle;
2049 cx.new_observer(
2050 entity_id,
2051 Box::new(move |cx| {
2052 window_handle
2053 .update(cx, |_, window, cx| {
2054 if let Some(handle) = observed.upgrade() {
2055 on_notify(handle, window, cx);
2056 true
2057 } else {
2058 false
2059 }
2060 })
2061 .unwrap_or(false)
2062 }),
2063 )
2064 }
2065
2066 pub fn subscribe<Emitter, Evt>(
2070 &mut self,
2071 entity: &Entity<Emitter>,
2072 cx: &mut App,
2073 mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,
2074 ) -> Subscription
2075 where
2076 Emitter: EventEmitter<Evt>,
2077 Evt: 'static,
2078 {
2079 let entity_id = entity.entity_id();
2080 let handle = entity.downgrade();
2081 let window_handle = self.handle;
2082 cx.new_subscription(
2083 entity_id,
2084 (
2085 TypeId::of::<Evt>(),
2086 Box::new(move |event, cx| {
2087 window_handle
2088 .update(cx, |_, window, cx| {
2089 if let Some(entity) = handle.upgrade() {
2090 let event = event.downcast_ref().expect("invalid event type");
2091 on_event(entity, event, window, cx);
2092 true
2093 } else {
2094 false
2095 }
2096 })
2097 .unwrap_or(false)
2098 }),
2099 ),
2100 )
2101 }
2102
2103 pub fn observe_release<T>(
2105 &self,
2106 entity: &Entity<T>,
2107 cx: &mut App,
2108 mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
2109 ) -> Subscription
2110 where
2111 T: 'static,
2112 {
2113 let entity_id = entity.entity_id();
2114 let window_handle = self.handle;
2115 let (subscription, activate) = cx.release_listeners.insert(
2116 entity_id,
2117 Box::new(move |entity, cx| {
2118 let entity = entity.downcast_mut().expect("invalid entity type");
2119 let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
2120 }),
2121 );
2122 activate();
2123 subscription
2124 }
2125
2126 pub fn to_async(&self, cx: &App) -> AsyncWindowContext {
2129 AsyncWindowContext::new_context(cx.to_async(), self.handle)
2130 }
2131
2132 pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {
2134 RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));
2135 }
2136
2137 pub fn request_animation_frame(&self) {
2144 let entity = self.current_view();
2145 self.on_next_frame(move |_, cx| cx.notify(entity));
2146 }
2147
2148 #[track_caller]
2152 pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>
2153 where
2154 R: 'static,
2155 AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
2156 {
2157 let handle = self.handle;
2158 cx.spawn(async move |app| {
2159 let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
2160 f(&mut async_window_cx).await
2161 })
2162 }
2163
2164 #[track_caller]
2168 pub fn spawn_with_priority<AsyncFn, R>(
2169 &self,
2170 priority: Priority,
2171 cx: &App,
2172 f: AsyncFn,
2173 ) -> Task<R>
2174 where
2175 R: 'static,
2176 AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
2177 {
2178 let handle = self.handle;
2179 cx.spawn_with_priority(priority, async move |app| {
2180 let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
2181 f(&mut async_window_cx).await
2182 })
2183 }
2184
2185 pub fn bounds_changed(&mut self, cx: &mut App) {
2191 self.scale_factor = self.platform_window.scale_factor();
2192 self.viewport_size = self.platform_window.content_size();
2193 self.display_id = self.platform_window.display().map(|display| display.id());
2194
2195 self.refresh();
2196
2197 self.bounds_observers
2198 .clone()
2199 .retain(&(), |callback| callback(self, cx));
2200 }
2201
2202 pub fn bounds(&self) -> Bounds<Pixels> {
2204 self.platform_window.bounds()
2205 }
2206
2207 #[cfg(any(test, feature = "test-support"))]
2211 pub fn render_to_image(&self) -> anyhow::Result<image::RgbaImage> {
2212 self.platform_window
2213 .render_to_image(&self.rendered_frame.scene)
2214 }
2215
2216 pub fn resize(&mut self, size: Size<Pixels>) {
2218 self.platform_window.resize(size);
2219 }
2220
2221 pub fn is_fullscreen(&self) -> bool {
2223 self.platform_window.is_fullscreen()
2224 }
2225
2226 pub(crate) fn appearance_changed(&mut self, cx: &mut App) {
2227 self.appearance = self.platform_window.appearance();
2228
2229 self.appearance_observers
2230 .clone()
2231 .retain(&(), |callback| callback(self, cx));
2232 }
2233
2234 pub(crate) fn button_layout_changed(&mut self, cx: &mut App) {
2235 self.button_layout_observers
2236 .clone()
2237 .retain(&(), |callback| callback(self, cx));
2238 }
2239
2240 pub fn appearance(&self) -> WindowAppearance {
2242 self.appearance
2243 }
2244
2245 pub fn viewport_size(&self) -> Size<Pixels> {
2247 self.viewport_size
2248 }
2249
2250 pub fn is_window_active(&self) -> bool {
2252 self.active.get()
2253 }
2254
2255 pub fn is_window_hovered(&self) -> bool {
2259 if cfg!(any(
2260 target_os = "windows",
2261 target_os = "linux",
2262 target_os = "freebsd"
2263 )) {
2264 self.hovered.get()
2265 } else {
2266 self.is_window_active()
2267 }
2268 }
2269
2270 pub fn zoom_window(&self) {
2272 self.platform_window.zoom();
2273 }
2274
2275 pub fn show_window_menu(&self, position: Point<Pixels>) {
2277 self.platform_window.show_window_menu(position)
2278 }
2279
2280 pub fn start_window_move(&self) {
2285 self.platform_window.start_window_move()
2286 }
2287
2288 pub fn set_client_inset(&mut self, inset: Pixels) {
2290 self.client_inset = Some(inset);
2291 self.platform_window.set_client_inset(inset);
2292 }
2293
2294 pub fn client_inset(&self) -> Option<Pixels> {
2296 self.client_inset
2297 }
2298
2299 pub fn window_decorations(&self) -> Decorations {
2301 self.platform_window.window_decorations()
2302 }
2303
2304 pub fn window_controls(&self) -> WindowControls {
2306 self.platform_window.window_controls()
2307 }
2308
2309 pub fn set_window_title(&mut self, title: &str) {
2311 self.platform_window.set_title(title);
2312 }
2313
2314 #[cfg(target_os = "macos")]
2316 pub fn set_traffic_light_position(&self, position: Point<Pixels>) {
2317 self.platform_window.set_traffic_light_position(position);
2318 }
2319
2320 pub fn set_app_id(&mut self, app_id: &str) {
2322 self.platform_window.set_app_id(app_id);
2323 }
2324
2325 pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
2327 self.platform_window
2328 .set_background_appearance(background_appearance);
2329 }
2330
2331 pub fn set_window_edited(&mut self, edited: bool) {
2333 self.platform_window.set_edited(edited);
2334 }
2335
2336 pub fn set_document_path(&self, path: Option<&std::path::Path>) {
2339 self.platform_window.set_document_path(path);
2340 }
2341
2342 pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {
2344 cx.platform
2345 .displays()
2346 .into_iter()
2347 .find(|display| Some(display.id()) == self.display_id)
2348 }
2349
2350 pub fn show_character_palette(&self) {
2352 self.platform_window.show_character_palette();
2353 }
2354
2355 pub fn scale_factor(&self) -> f32 {
2359 self.scale_factor
2360 }
2361
2362 pub fn rem_size(&self) -> Pixels {
2365 self.rem_size_override_stack
2366 .last()
2367 .copied()
2368 .unwrap_or(self.rem_size)
2369 }
2370
2371 pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
2374 self.rem_size = rem_size.into();
2375 }
2376
2377 pub fn with_global_id<R>(
2380 &mut self,
2381 element_id: ElementId,
2382 f: impl FnOnce(&GlobalElementId, &mut Self) -> R,
2383 ) -> R {
2384 self.with_id(element_id, |this| {
2385 let global_id = GlobalElementId(Arc::from(&*this.element_id_stack));
2386
2387 f(&global_id, this)
2388 })
2389 }
2390
2391 #[inline]
2393 pub fn with_id<R>(
2394 &mut self,
2395 element_id: impl Into<ElementId>,
2396 f: impl FnOnce(&mut Self) -> R,
2397 ) -> R {
2398 self.element_id_stack.push(element_id.into());
2399 let result = f(self);
2400 self.element_id_stack.pop();
2401 result
2402 }
2403
2404 #[inline]
2410 pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R
2411 where
2412 F: FnOnce(&mut Self) -> R,
2413 {
2414 self.invalidator.debug_assert_paint_or_prepaint();
2415
2416 if let Some(rem_size) = rem_size {
2417 self.rem_size_override_stack.push(rem_size.into());
2418 let result = f(self);
2419 self.rem_size_override_stack.pop();
2420 result
2421 } else {
2422 f(self)
2423 }
2424 }
2425
2426 pub fn line_height(&self) -> Pixels {
2428 self.text_style().line_height_in_pixels(self.rem_size())
2429 }
2430
2431 #[inline]
2433 pub fn pixel_snap(&self, value: Pixels) -> Pixels {
2434 px(round_to_device_pixel(value.0, self.scale_factor()) / self.scale_factor())
2435 }
2436
2437 #[inline]
2439 pub fn pixel_snap_f64(&self, value: f64) -> f64 {
2440 let scale_factor = f64::from(self.scale_factor());
2441 round_half_toward_zero_f64(value * scale_factor) / scale_factor
2442 }
2443
2444 #[inline]
2446 pub fn pixel_snap_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<Pixels> {
2447 bounds.map(|c| self.pixel_snap(c))
2448 }
2449
2450 #[inline]
2452 pub fn pixel_snap_point(&self, position: Point<Pixels>) -> Point<Pixels> {
2453 position.map(|c| self.pixel_snap(c))
2454 }
2455
2456 #[inline]
2457 fn snap_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
2458 let scale_factor = self.scale_factor();
2459 let left = round_to_device_pixel(bounds.left().0, scale_factor);
2460 let top = round_to_device_pixel(bounds.top().0, scale_factor);
2461 let right = round_to_device_pixel(bounds.right().0, scale_factor).max(left);
2462 let bottom = round_to_device_pixel(bounds.bottom().0, scale_factor).max(top);
2463 Bounds::from_corners(
2464 point(ScaledPixels(left), ScaledPixels(top)),
2465 point(ScaledPixels(right), ScaledPixels(bottom)),
2466 )
2467 }
2468
2469 #[inline]
2471 fn snap_stroke(&self, value: Pixels) -> ScaledPixels {
2472 ScaledPixels(round_stroke_to_device_pixel(value.0, self.scale_factor()))
2473 }
2474
2475 #[inline]
2476 fn snap_border_widths(&self, edges: Edges<Pixels>) -> Edges<ScaledPixels> {
2477 edges.map(|e| self.snap_stroke(*e))
2478 }
2479
2480 #[inline]
2482 fn cover_bounds(&self, bounds: Bounds<Pixels>) -> Bounds<ScaledPixels> {
2483 let scale_factor = self.scale_factor();
2484 let left = floor_to_device_pixel(bounds.left().0, scale_factor);
2485 let top = floor_to_device_pixel(bounds.top().0, scale_factor);
2486 let right = ceil_to_device_pixel(bounds.right().0, scale_factor).max(left);
2487 let bottom = ceil_to_device_pixel(bounds.bottom().0, scale_factor).max(top);
2488 Bounds::from_corners(
2489 point(ScaledPixels(left), ScaledPixels(top)),
2490 point(ScaledPixels(right), ScaledPixels(bottom)),
2491 )
2492 }
2493
2494 #[inline]
2495 fn snapped_content_mask(&self) -> ContentMask<ScaledPixels> {
2496 ContentMask {
2497 bounds: self.cover_bounds(self.content_mask().bounds),
2498 }
2499 }
2500
2501 pub fn prevent_default(&mut self) {
2504 self.default_prevented = true;
2505 }
2506
2507 pub fn default_prevented(&self) -> bool {
2509 self.default_prevented
2510 }
2511
2512 pub fn is_action_available(&self, action: &dyn Action, cx: &App) -> bool {
2514 let node_id =
2515 self.focus_node_id_in_rendered_frame(self.focused(cx).map(|handle| handle.id));
2516 self.rendered_frame
2517 .dispatch_tree
2518 .is_action_available(action, node_id)
2519 }
2520
2521 pub fn is_action_available_in(&self, action: &dyn Action, focus_handle: &FocusHandle) -> bool {
2523 let node_id = self.focus_node_id_in_rendered_frame(Some(focus_handle.id));
2524 self.rendered_frame
2525 .dispatch_tree
2526 .is_action_available(action, node_id)
2527 }
2528
2529 pub fn mouse_position(&self) -> Point<Pixels> {
2531 self.mouse_position
2532 }
2533
2534 pub fn capture_pointer(&mut self, hitbox_id: HitboxId) {
2541 self.captured_hitbox = Some(hitbox_id);
2542 }
2543
2544 pub fn release_pointer(&mut self) {
2546 self.captured_hitbox = None;
2547 }
2548
2549 pub fn captured_hitbox(&self) -> Option<HitboxId> {
2551 self.captured_hitbox
2552 }
2553
2554 pub fn modifiers(&self) -> Modifiers {
2556 self.modifiers
2557 }
2558
2559 pub fn last_input_was_keyboard(&self) -> bool {
2562 self.last_input_modality == InputModality::Keyboard
2563 }
2564
2565 pub fn capslock(&self) -> Capslock {
2567 self.capslock
2568 }
2569
2570 fn complete_frame(&self) {
2571 self.platform_window.completed_frame();
2572 }
2573
2574 #[profiling::function]
2577 pub fn draw(&mut self, cx: &mut App) -> ArenaClearNeeded {
2578 let _arena_scope = ElementArenaScope::enter(&cx.element_arena);
2581
2582 self.invalidate_entities();
2583 cx.entities.clear_accessed();
2584 debug_assert!(self.rendered_entity_stack.is_empty());
2585 self.invalidator.set_dirty(false);
2586 self.requested_autoscroll = None;
2587
2588 if let Some(input_handler) = self.platform_window.take_input_handler() {
2593 if let Some(slot) = self
2594 .rendered_frame
2595 .input_handlers
2596 .iter_mut()
2597 .rev()
2598 .find(|h| h.is_none())
2599 {
2600 *slot = Some(input_handler);
2601 } else {
2602 self.rendered_frame.input_handlers.push(Some(input_handler));
2603 }
2604 }
2605 if !cx.mode.skip_drawing() {
2606 self.draw_roots(cx);
2607 }
2608 self.dirty_views.clear();
2609 self.next_frame.window_active = self.active.get();
2610
2611 if let Some(input_handler) = self
2617 .next_frame
2618 .input_handlers
2619 .iter_mut()
2620 .rev()
2621 .find_map(|h| h.take())
2622 {
2623 self.platform_window.set_input_handler(input_handler);
2624 }
2625
2626 self.layout_engine.as_mut().unwrap().clear();
2627 self.text_system().finish_frame();
2628 self.next_frame.finish(&mut self.rendered_frame);
2629
2630 self.invalidator.set_phase(DrawPhase::Focus);
2631 let previous_focus_path = self.rendered_frame.focus_path();
2632 let previous_window_active = self.rendered_frame.window_active;
2633 mem::swap(&mut self.rendered_frame, &mut self.next_frame);
2634 self.next_frame.clear();
2635 let current_focus_path = self.rendered_frame.focus_path();
2636 let current_window_active = self.rendered_frame.window_active;
2637
2638 if previous_focus_path != current_focus_path
2639 || previous_window_active != current_window_active
2640 {
2641 if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
2642 self.focus_lost_listeners
2643 .clone()
2644 .retain(&(), |listener| listener(self, cx));
2645 }
2646
2647 let event = WindowFocusEvent {
2648 previous_focus_path: if previous_window_active {
2649 previous_focus_path
2650 } else {
2651 Default::default()
2652 },
2653 current_focus_path: if current_window_active {
2654 current_focus_path
2655 } else {
2656 Default::default()
2657 },
2658 };
2659 self.focus_listeners
2660 .clone()
2661 .retain(&(), |listener| listener(&event, self, cx));
2662 }
2663
2664 debug_assert!(self.rendered_entity_stack.is_empty());
2665 self.record_entities_accessed(cx);
2666 self.reset_cursor_style(cx);
2667 self.refreshing = false;
2668 self.invalidator.set_phase(DrawPhase::None);
2669 self.needs_present.set(true);
2670
2671 ArenaClearNeeded::new(&cx.element_arena)
2672 }
2673
2674 fn record_entities_accessed(&mut self, cx: &mut App) {
2675 let mut entities_ref = cx.entities.accessed_entities.get_mut();
2676 let mut entities = mem::take(entities_ref.deref_mut());
2677 let handle = self.handle;
2678 cx.record_entities_accessed(
2679 handle,
2680 self.invalidator.clone(),
2682 &entities,
2683 );
2684 let mut entities_ref = cx.entities.accessed_entities.get_mut();
2685 mem::swap(&mut entities, entities_ref.deref_mut());
2686 }
2687
2688 fn invalidate_entities(&mut self) {
2689 let mut views = self.invalidator.take_views();
2690 for entity in views.drain() {
2691 self.mark_view_dirty(entity);
2692 }
2693 self.invalidator.replace_views(views);
2694 }
2695
2696 #[profiling::function]
2697 fn present(&mut self) {
2698 self.platform_window.draw(&self.rendered_frame.scene);
2699 #[cfg(feature = "input-latency-histogram")]
2700 self.input_latency_tracker.record_frame_presented();
2701 self.needs_present.set(false);
2702 profiling::finish_frame!();
2703 }
2704
2705 #[cfg(feature = "input-latency-histogram")]
2707 pub fn input_latency_snapshot(&self) -> InputLatencySnapshot {
2708 self.input_latency_tracker.snapshot()
2709 }
2710
2711 fn draw_roots(&mut self, cx: &mut App) {
2712 self.invalidator.set_phase(DrawPhase::Prepaint);
2713 self.tooltip_bounds.take();
2714
2715 self.a11y.sync_active_flag();
2716 if self.a11y.is_active() {
2717 self.a11y.begin_frame();
2718 }
2719
2720 let _inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size());
2721 let root_size = {
2722 #[cfg(any(feature = "inspector", debug_assertions))]
2723 {
2724 if self.inspector.is_some() {
2725 let mut size = self.viewport_size;
2726 size.width = (size.width - _inspector_width).max(px(0.0));
2727 size
2728 } else {
2729 self.viewport_size
2730 }
2731 }
2732 #[cfg(not(any(feature = "inspector", debug_assertions)))]
2733 {
2734 self.viewport_size
2735 }
2736 };
2737
2738 let mut root_element = self.root.as_ref().unwrap().clone().into_any();
2740 root_element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2741
2742 #[cfg(any(feature = "inspector", debug_assertions))]
2743 let inspector_element = self.prepaint_inspector(_inspector_width, cx);
2744
2745 self.prepaint_deferred_draws(cx);
2746
2747 let mut prompt_element = None;
2748 let mut active_drag_element = None;
2749 let mut tooltip_element = None;
2750 if let Some(prompt) = self.prompt.take() {
2751 let mut element = prompt.view.any_view().into_any();
2752 element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2753 prompt_element = Some(element);
2754 self.prompt = Some(prompt);
2755 } else if let Some(active_drag) = cx.active_drag.take() {
2756 let mut element = active_drag.view.clone().into_any();
2757 let offset = self.mouse_position() - active_drag.cursor_offset;
2758 element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);
2759 active_drag_element = Some(element);
2760 cx.active_drag = Some(active_drag);
2761 } else {
2762 tooltip_element = self.prepaint_tooltip(cx);
2763 }
2764
2765 self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);
2766
2767 self.invalidator.set_phase(DrawPhase::Paint);
2769 root_element.paint(self, cx);
2770
2771 #[cfg(any(feature = "inspector", debug_assertions))]
2772 self.paint_inspector(inspector_element, cx);
2773
2774 self.paint_deferred_draws(cx);
2775
2776 if let Some(mut prompt_element) = prompt_element {
2777 prompt_element.paint(self, cx);
2778 } else if let Some(mut drag_element) = active_drag_element {
2779 drag_element.paint(self, cx);
2780 } else if let Some(mut tooltip_element) = tooltip_element {
2781 tooltip_element.paint(self, cx);
2782 }
2783
2784 #[cfg(any(feature = "inspector", debug_assertions))]
2785 self.paint_inspector_hitbox(cx);
2786
2787 let a11y_active_start_of_frame = self.a11y.is_active();
2789 self.a11y.sync_active_flag();
2790 let a11y_active_end_of_frame = self.a11y.is_active();
2791
2792 let should_send_a11y_update = a11y_active_start_of_frame && a11y_active_end_of_frame;
2793
2794 if a11y_active_start_of_frame {
2795 let tree_update = self.a11y.end_frame();
2797
2798 if should_send_a11y_update {
2799 log::debug!(
2800 "Sending a11y tree update: {} nodes",
2801 tree_update.nodes.len()
2802 );
2803 self.platform_window.a11y_tree_update(tree_update);
2804 }
2805 }
2806 }
2807
2808 fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {
2809 for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {
2811 let Some(Some(tooltip_request)) = self
2812 .next_frame
2813 .tooltip_requests
2814 .get(tooltip_request_index)
2815 .cloned()
2816 else {
2817 log::error!("Unexpectedly absent TooltipRequest");
2818 continue;
2819 };
2820 let mut element = tooltip_request.tooltip.view.clone().into_any();
2821 let mouse_position = tooltip_request.tooltip.mouse_position;
2822 let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);
2823
2824 let mut tooltip_bounds =
2825 Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
2826 let window_bounds = Bounds {
2827 origin: Point::default(),
2828 size: self.viewport_size(),
2829 };
2830
2831 if tooltip_bounds.right() > window_bounds.right() {
2832 let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
2833 if new_x >= Pixels::ZERO {
2834 tooltip_bounds.origin.x = new_x;
2835 } else {
2836 tooltip_bounds.origin.x = cmp::max(
2837 Pixels::ZERO,
2838 tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
2839 );
2840 }
2841 }
2842
2843 if tooltip_bounds.bottom() > window_bounds.bottom() {
2844 let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
2845 if new_y >= Pixels::ZERO {
2846 tooltip_bounds.origin.y = new_y;
2847 } else {
2848 tooltip_bounds.origin.y = cmp::max(
2849 Pixels::ZERO,
2850 tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
2851 );
2852 }
2853 }
2854
2855 let is_visible =
2859 (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);
2860 if !is_visible {
2861 continue;
2862 }
2863
2864 self.with_absolute_element_offset(tooltip_bounds.origin, |window| {
2865 element.prepaint(window, cx)
2866 });
2867
2868 self.tooltip_bounds = Some(TooltipBounds {
2869 id: tooltip_request.id,
2870 bounds: tooltip_bounds,
2871 });
2872 return Some(element);
2873 }
2874 None
2875 }
2876
2877 fn prepaint_deferred_draws(&mut self, cx: &mut App) {
2878 assert_eq!(self.element_id_stack.len(), 0);
2879
2880 let mut completed_draws = Vec::new();
2881
2882 let mut depth = 0;
2885 loop {
2886 assert!(depth < 10, "Exceeded maximum (10) deferred depth");
2888 depth += 1;
2889 let deferred_count = self.next_frame.deferred_draws.len();
2890 if deferred_count == 0 {
2891 break;
2892 }
2893
2894 let traversal_order = self.deferred_draw_traversal_order();
2896 let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
2897
2898 for deferred_draw_ix in traversal_order {
2899 let deferred_draw = &mut deferred_draws[deferred_draw_ix];
2900 self.element_id_stack
2901 .clone_from(&deferred_draw.element_id_stack);
2902 self.text_style_stack
2903 .clone_from(&deferred_draw.text_style_stack);
2904 self.next_frame
2905 .dispatch_tree
2906 .set_active_node(deferred_draw.parent_node);
2907
2908 let prepaint_start = self.prepaint_index();
2909 if let Some(element) = deferred_draw.element.as_mut() {
2910 self.with_rendered_view(deferred_draw.current_view, |window| {
2911 window.with_rem_size(Some(deferred_draw.rem_size), |window| {
2912 window.with_absolute_element_offset(
2913 deferred_draw.absolute_offset,
2914 |window| {
2915 element.prepaint(window, cx);
2916 },
2917 );
2918 });
2919 })
2920 } else {
2921 self.reuse_prepaint(deferred_draw.prepaint_range.clone());
2922 }
2923 let prepaint_end = self.prepaint_index();
2924 deferred_draw.prepaint_range = prepaint_start..prepaint_end;
2925 }
2926
2927 completed_draws.append(&mut deferred_draws);
2929
2930 self.element_id_stack.clear();
2931 self.text_style_stack.clear();
2932 }
2933
2934 self.next_frame.deferred_draws = completed_draws;
2936 }
2937
2938 fn paint_deferred_draws(&mut self, cx: &mut App) {
2939 assert_eq!(self.element_id_stack.len(), 0);
2940
2941 if self.next_frame.deferred_draws.len() == 0 {
2944 return;
2945 }
2946
2947 let traversal_order = self.deferred_draw_traversal_order();
2948 let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
2949 for deferred_draw_ix in traversal_order {
2950 let mut deferred_draw = &mut deferred_draws[deferred_draw_ix];
2951 self.element_id_stack
2952 .clone_from(&deferred_draw.element_id_stack);
2953 self.next_frame
2954 .dispatch_tree
2955 .set_active_node(deferred_draw.parent_node);
2956
2957 let paint_start = self.paint_index();
2958 let content_mask = deferred_draw.content_mask;
2959 if let Some(element) = deferred_draw.element.as_mut() {
2960 self.with_rendered_view(deferred_draw.current_view, |window| {
2961 window.with_content_mask(content_mask, |window| {
2962 window.with_rem_size(Some(deferred_draw.rem_size), |window| {
2963 element.paint(window, cx);
2964 });
2965 })
2966 })
2967 } else {
2968 self.reuse_paint(deferred_draw.paint_range.clone());
2969 }
2970 let paint_end = self.paint_index();
2971 deferred_draw.paint_range = paint_start..paint_end;
2972 }
2973 self.next_frame.deferred_draws = deferred_draws;
2974 self.element_id_stack.clear();
2975 }
2976
2977 fn deferred_draw_traversal_order(&mut self) -> SmallVec<[usize; 8]> {
2978 let deferred_count = self.next_frame.deferred_draws.len();
2979 let mut sorted_indices = (0..deferred_count).collect::<SmallVec<[_; 8]>>();
2980 sorted_indices.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
2981 sorted_indices
2982 }
2983
2984 pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {
2985 PrepaintStateIndex {
2986 hitboxes_index: self.next_frame.hitboxes.len(),
2987 tooltips_index: self.next_frame.tooltip_requests.len(),
2988 deferred_draws_index: self.next_frame.deferred_draws.len(),
2989 dispatch_tree_index: self.next_frame.dispatch_tree.len(),
2990 accessed_element_states_index: self.next_frame.accessed_element_states.len(),
2991 line_layout_index: self.text_system.layout_index(),
2992 }
2993 }
2994
2995 pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {
2996 self.next_frame.hitboxes.extend(
2997 self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
2998 .iter()
2999 .cloned(),
3000 );
3001 self.next_frame.tooltip_requests.extend(
3002 self.rendered_frame.tooltip_requests
3003 [range.start.tooltips_index..range.end.tooltips_index]
3004 .iter_mut()
3005 .map(|request| request.take()),
3006 );
3007 self.next_frame.accessed_element_states.extend(
3008 self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
3009 ..range.end.accessed_element_states_index]
3010 .iter()
3011 .map(|(id, type_id)| (id.clone(), *type_id)),
3012 );
3013 self.text_system
3014 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
3015
3016 let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(
3017 range.start.dispatch_tree_index..range.end.dispatch_tree_index,
3018 &mut self.rendered_frame.dispatch_tree,
3019 self.focus,
3020 );
3021
3022 if reused_subtree.contains_focus() {
3023 self.next_frame.focus = self.focus;
3024 }
3025
3026 self.next_frame.deferred_draws.extend(
3027 self.rendered_frame.deferred_draws
3028 [range.start.deferred_draws_index..range.end.deferred_draws_index]
3029 .iter()
3030 .map(|deferred_draw| DeferredDraw {
3031 current_view: deferred_draw.current_view,
3032 parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
3033 element_id_stack: deferred_draw.element_id_stack.clone(),
3034 text_style_stack: deferred_draw.text_style_stack.clone(),
3035 content_mask: deferred_draw.content_mask,
3036 rem_size: deferred_draw.rem_size,
3037 priority: deferred_draw.priority,
3038 element: None,
3039 absolute_offset: deferred_draw.absolute_offset,
3040 prepaint_range: deferred_draw.prepaint_range.clone(),
3041 paint_range: deferred_draw.paint_range.clone(),
3042 }),
3043 );
3044 }
3045
3046 pub(crate) fn paint_index(&self) -> PaintIndex {
3047 PaintIndex {
3048 scene_index: self.next_frame.scene.len(),
3049 mouse_listeners_index: self.next_frame.mouse_listeners.len(),
3050 input_handlers_index: self.next_frame.input_handlers.len(),
3051 cursor_styles_index: self.next_frame.cursor_styles.len(),
3052 accessed_element_states_index: self.next_frame.accessed_element_states.len(),
3053 tab_handle_index: self.next_frame.tab_stops.paint_index(),
3054 line_layout_index: self.text_system.layout_index(),
3055 }
3056 }
3057
3058 pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
3059 self.next_frame.cursor_styles.extend(
3060 self.rendered_frame.cursor_styles
3061 [range.start.cursor_styles_index..range.end.cursor_styles_index]
3062 .iter()
3063 .cloned(),
3064 );
3065 self.next_frame.input_handlers.extend(
3066 self.rendered_frame.input_handlers
3067 [range.start.input_handlers_index..range.end.input_handlers_index]
3068 .iter_mut()
3069 .map(|handler| handler.take()),
3070 );
3071 self.next_frame.mouse_listeners.extend(
3072 self.rendered_frame.mouse_listeners
3073 [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
3074 .iter_mut()
3075 .map(|listener| listener.take()),
3076 );
3077 self.next_frame.accessed_element_states.extend(
3078 self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
3079 ..range.end.accessed_element_states_index]
3080 .iter()
3081 .map(|(id, type_id)| (id.clone(), *type_id)),
3082 );
3083 self.next_frame.tab_stops.replay(
3084 &self.rendered_frame.tab_stops.insertion_history
3085 [range.start.tab_handle_index..range.end.tab_handle_index],
3086 );
3087
3088 self.text_system
3089 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
3090 self.next_frame.scene.replay(
3091 range.start.scene_index..range.end.scene_index,
3092 &self.rendered_frame.scene,
3093 );
3094 }
3095
3096 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
3100 where
3101 F: FnOnce(&mut Self) -> R,
3102 {
3103 self.invalidator.debug_assert_paint_or_prepaint();
3104 if let Some(style) = style {
3105 self.text_style_stack.push(style);
3106 let result = f(self);
3107 self.text_style_stack.pop();
3108 result
3109 } else {
3110 f(self)
3111 }
3112 }
3113
3114 pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
3117 self.invalidator.debug_assert_paint();
3118 self.next_frame.cursor_styles.push(CursorStyleRequest {
3119 hitbox_id: Some(hitbox.id),
3120 style,
3121 });
3122 }
3123
3124 pub fn set_window_cursor_style(&mut self, style: CursorStyle) {
3129 self.invalidator.debug_assert_paint();
3130 self.next_frame.cursor_styles.push(CursorStyleRequest {
3131 hitbox_id: None,
3132 style,
3133 })
3134 }
3135
3136 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
3139 self.invalidator.debug_assert_prepaint();
3140 let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));
3141 self.next_frame
3142 .tooltip_requests
3143 .push(Some(TooltipRequest { id, tooltip }));
3144 id
3145 }
3146
3147 #[inline]
3152 pub fn with_content_mask<R>(
3153 &mut self,
3154 mask: Option<ContentMask<Pixels>>,
3155 f: impl FnOnce(&mut Self) -> R,
3156 ) -> R {
3157 self.invalidator.debug_assert_paint_or_prepaint();
3158 if let Some(mask) = mask {
3159 let mask = mask.intersect(&self.content_mask());
3160 self.content_mask_stack.push(mask);
3161 let result = f(self);
3162 self.content_mask_stack.pop();
3163 result
3164 } else {
3165 f(self)
3166 }
3167 }
3168
3169 pub fn with_element_offset<R>(
3172 &mut self,
3173 offset: Point<Pixels>,
3174 f: impl FnOnce(&mut Self) -> R,
3175 ) -> R {
3176 self.invalidator.debug_assert_prepaint();
3177
3178 if offset.is_zero() {
3179 return f(self);
3180 };
3181
3182 let abs_offset = self.element_offset() + offset;
3183 self.with_absolute_element_offset(abs_offset, f)
3184 }
3185
3186 pub fn with_absolute_element_offset<R>(
3190 &mut self,
3191 offset: Point<Pixels>,
3192 f: impl FnOnce(&mut Self) -> R,
3193 ) -> R {
3194 self.invalidator.debug_assert_prepaint();
3195 self.element_offset_stack.push(offset);
3196 let result = f(self);
3197 self.element_offset_stack.pop();
3198 result
3199 }
3200
3201 pub(crate) fn with_element_opacity<R>(
3202 &mut self,
3203 opacity: Option<f32>,
3204 f: impl FnOnce(&mut Self) -> R,
3205 ) -> R {
3206 self.invalidator.debug_assert_paint_or_prepaint();
3207
3208 let Some(opacity) = opacity else {
3209 return f(self);
3210 };
3211
3212 let previous_opacity = self.element_opacity;
3213 self.element_opacity = previous_opacity * opacity;
3214 let result = f(self);
3215 self.element_opacity = previous_opacity;
3216 result
3217 }
3218
3219 pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {
3225 self.invalidator.debug_assert_prepaint();
3226 let index = self.prepaint_index();
3227 let result = f(self);
3228 if result.is_err() {
3229 self.next_frame.hitboxes.truncate(index.hitboxes_index);
3230 self.next_frame
3231 .tooltip_requests
3232 .truncate(index.tooltips_index);
3233 self.next_frame
3234 .deferred_draws
3235 .truncate(index.deferred_draws_index);
3236 self.next_frame
3237 .dispatch_tree
3238 .truncate(index.dispatch_tree_index);
3239 self.next_frame
3240 .accessed_element_states
3241 .truncate(index.accessed_element_states_index);
3242 self.text_system.truncate_layouts(index.line_layout_index);
3243 }
3244 result
3245 }
3246
3247 pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {
3253 self.invalidator.debug_assert_prepaint();
3254 self.requested_autoscroll = Some(bounds);
3255 }
3256
3257 pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {
3260 self.invalidator.debug_assert_prepaint();
3261 self.requested_autoscroll.take()
3262 }
3263
3264 pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
3270 let (task, is_first) = cx.fetch_asset::<A>(source);
3271 task.clone().now_or_never().or_else(|| {
3272 if is_first {
3273 let entity_id = self.current_view();
3274 self.spawn(cx, {
3275 let task = task.clone();
3276 async move |cx| {
3277 task.await;
3278
3279 cx.on_next_frame(move |_, cx| {
3280 cx.notify(entity_id);
3281 });
3282 }
3283 })
3284 .detach();
3285 }
3286
3287 None
3288 })
3289 }
3290
3291 pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
3297 let (task, _) = cx.fetch_asset::<A>(source);
3298 task.now_or_never()
3299 }
3300 pub fn element_offset(&self) -> Point<Pixels> {
3303 self.invalidator.debug_assert_prepaint();
3304 self.element_offset_stack
3305 .last()
3306 .copied()
3307 .unwrap_or_default()
3308 }
3309
3310 #[inline]
3313 pub(crate) fn element_opacity(&self) -> f32 {
3314 self.invalidator.debug_assert_paint_or_prepaint();
3315 self.element_opacity
3316 }
3317
3318 pub fn content_mask(&self) -> ContentMask<Pixels> {
3320 self.invalidator.debug_assert_paint_or_prepaint();
3321 self.content_mask_stack
3322 .last()
3323 .cloned()
3324 .unwrap_or_else(|| ContentMask {
3325 bounds: Bounds {
3326 origin: Point::default(),
3327 size: self.viewport_size,
3328 },
3329 })
3330 }
3331
3332 pub fn with_element_namespace<R>(
3335 &mut self,
3336 element_id: impl Into<ElementId>,
3337 f: impl FnOnce(&mut Self) -> R,
3338 ) -> R {
3339 self.element_id_stack.push(element_id.into());
3340 let result = f(self);
3341 self.element_id_stack.pop();
3342 result
3343 }
3344
3345 pub fn use_keyed_state<S: 'static>(
3347 &mut self,
3348 key: impl Into<ElementId>,
3349 cx: &mut App,
3350 init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
3351 ) -> Entity<S> {
3352 let current_view = self.current_view();
3353 self.with_global_id(key.into(), |global_id, window| {
3354 window.with_element_state(global_id, |state: Option<Entity<S>>, window| {
3355 if let Some(state) = state {
3356 (state.clone(), state)
3357 } else {
3358 let new_state = cx.new(|cx| init(window, cx));
3359 cx.observe(&new_state, move |_, cx| {
3360 cx.notify(current_view);
3361 })
3362 .detach();
3363 (new_state.clone(), new_state)
3364 }
3365 })
3366 })
3367 }
3368
3369 #[track_caller]
3375 pub fn use_state<S: 'static>(
3376 &mut self,
3377 cx: &mut App,
3378 init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
3379 ) -> Entity<S> {
3380 self.use_keyed_state(
3381 ElementId::CodeLocation(*core::panic::Location::caller()),
3382 cx,
3383 init,
3384 )
3385 }
3386
3387 pub fn with_element_state<S, R>(
3392 &mut self,
3393 global_id: &GlobalElementId,
3394 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
3395 ) -> R
3396 where
3397 S: 'static,
3398 {
3399 self.invalidator.debug_assert_paint_or_prepaint();
3400
3401 let key = (global_id.clone(), TypeId::of::<S>());
3402 self.next_frame.accessed_element_states.push(key.clone());
3403
3404 if let Some(any) = self
3405 .next_frame
3406 .element_states
3407 .remove(&key)
3408 .or_else(|| self.rendered_frame.element_states.remove(&key))
3409 {
3410 let ElementStateBox {
3411 inner,
3412 #[cfg(debug_assertions)]
3413 type_name,
3414 } = any;
3415 let mut state_box = inner
3417 .downcast::<Option<S>>()
3418 .map_err(|_| {
3419 #[cfg(debug_assertions)]
3420 {
3421 anyhow::anyhow!(
3422 "invalid element state type for id, requested {:?}, actual: {:?}",
3423 std::any::type_name::<S>(),
3424 type_name
3425 )
3426 }
3427
3428 #[cfg(not(debug_assertions))]
3429 {
3430 anyhow::anyhow!(
3431 "invalid element state type for id, requested {:?}",
3432 std::any::type_name::<S>(),
3433 )
3434 }
3435 })
3436 .unwrap();
3437
3438 let state = state_box.take().expect(
3439 "reentrant call to with_element_state for the same state type and element id",
3440 );
3441 let (result, state) = f(Some(state), self);
3442 state_box.replace(state);
3443 self.next_frame.element_states.insert(
3444 key,
3445 ElementStateBox {
3446 inner: state_box,
3447 #[cfg(debug_assertions)]
3448 type_name,
3449 },
3450 );
3451 result
3452 } else {
3453 let (result, state) = f(None, self);
3454 self.next_frame.element_states.insert(
3455 key,
3456 ElementStateBox {
3457 inner: Box::new(Some(state)),
3458 #[cfg(debug_assertions)]
3459 type_name: std::any::type_name::<S>(),
3460 },
3461 );
3462 result
3463 }
3464 }
3465
3466 pub fn with_optional_element_state<S, R>(
3473 &mut self,
3474 global_id: Option<&GlobalElementId>,
3475 f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
3476 ) -> R
3477 where
3478 S: 'static,
3479 {
3480 self.invalidator.debug_assert_paint_or_prepaint();
3481
3482 if let Some(global_id) = global_id {
3483 self.with_element_state(global_id, |state, cx| {
3484 let (result, state) = f(Some(state), cx);
3485 let state =
3486 state.expect("you must return some state when you pass some element id");
3487 (result, state)
3488 })
3489 } else {
3490 let (result, state) = f(None, self);
3491 debug_assert!(
3492 state.is_none(),
3493 "you must not return an element state when passing None for the global id"
3494 );
3495 result
3496 }
3497 }
3498
3499 #[inline]
3501 pub fn with_tab_group<R>(&mut self, index: Option<isize>, f: impl FnOnce(&mut Self) -> R) -> R {
3502 if let Some(index) = index {
3503 self.next_frame.tab_stops.begin_group(index);
3504 let result = f(self);
3505 self.next_frame.tab_stops.end_group();
3506 result
3507 } else {
3508 f(self)
3509 }
3510 }
3511
3512 pub fn defer_draw(
3521 &mut self,
3522 element: AnyElement,
3523 absolute_offset: Point<Pixels>,
3524 priority: usize,
3525 content_mask: Option<ContentMask<Pixels>>,
3526 ) {
3527 self.invalidator.debug_assert_prepaint();
3528 let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();
3529 self.next_frame.deferred_draws.push(DeferredDraw {
3530 current_view: self.current_view(),
3531 parent_node,
3532 element_id_stack: self.element_id_stack.clone(),
3533 text_style_stack: self.text_style_stack.clone(),
3534 content_mask,
3535 rem_size: self.rem_size(),
3536 priority,
3537 element: Some(element),
3538 absolute_offset,
3539 prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),
3540 paint_range: PaintIndex::default()..PaintIndex::default(),
3541 });
3542 }
3543
3544 pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
3550 self.invalidator.debug_assert_paint();
3551
3552 let content_mask = self.content_mask();
3553 let clipped_bounds = bounds.intersect(&content_mask.bounds);
3554 if !clipped_bounds.is_empty() {
3555 self.next_frame
3556 .scene
3557 .push_layer(self.cover_bounds(clipped_bounds));
3558 }
3559
3560 let result = f(self);
3561
3562 if !clipped_bounds.is_empty() {
3563 self.next_frame.scene.pop_layer();
3564 }
3565
3566 result
3567 }
3568
3569 pub fn paint_drop_shadows(
3575 &mut self,
3576 bounds: Bounds<Pixels>,
3577 corner_radii: Corners<Pixels>,
3578 shadows: &[BoxShadow],
3579 ) {
3580 self.invalidator.debug_assert_paint();
3581
3582 let scale_factor = self.scale_factor();
3583 let content_mask = self.snapped_content_mask();
3584 let opacity = self.element_opacity();
3585 let element_bounds = self.cover_bounds(bounds);
3586 let element_corner_radii = corner_radii.scale(scale_factor);
3587 for shadow in shadows {
3588 if shadow.inset {
3589 continue;
3590 }
3591 let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);
3592 self.next_frame.scene.insert_primitive(Shadow {
3593 order: 0,
3594 blur_radius: shadow.blur_radius.scale(scale_factor),
3595 bounds: self.cover_bounds(shadow_bounds),
3596 content_mask,
3597 corner_radii: corner_radii.scale(scale_factor),
3598 color: shadow.color.opacity(opacity),
3599 element_bounds,
3600 element_corner_radii,
3601 inset: 0,
3602 pad: 0,
3603 });
3604 }
3605 }
3606
3607 pub fn paint_inset_shadows(
3611 &mut self,
3612 bounds: Bounds<Pixels>,
3613 corner_radii: Corners<Pixels>,
3614 shadows: &[BoxShadow],
3615 ) {
3616 self.invalidator.debug_assert_paint();
3617
3618 let scale_factor = self.scale_factor();
3619 let content_mask = self.snapped_content_mask();
3620 let opacity = self.element_opacity();
3621 let element_bounds = self.cover_bounds(bounds);
3622 let element_corner_radii = corner_radii.scale(scale_factor);
3623 for shadow in shadows {
3624 if !shadow.inset {
3625 continue;
3626 }
3627 let hole = (bounds + shadow.offset).dilate(-shadow.spread_radius);
3628 let zero = Pixels::ZERO;
3631 let hole_corner_radii = Corners {
3632 top_left: (corner_radii.top_left - shadow.spread_radius).max(zero),
3633 top_right: (corner_radii.top_right - shadow.spread_radius).max(zero),
3634 bottom_right: (corner_radii.bottom_right - shadow.spread_radius).max(zero),
3635 bottom_left: (corner_radii.bottom_left - shadow.spread_radius).max(zero),
3636 };
3637 self.next_frame.scene.insert_primitive(Shadow {
3638 order: 0,
3639 blur_radius: shadow.blur_radius.scale(scale_factor),
3640 bounds: self.cover_bounds(hole),
3641 content_mask,
3642 corner_radii: hole_corner_radii.scale(scale_factor),
3643 color: shadow.color.opacity(opacity),
3644 element_bounds,
3645 element_corner_radii,
3646 inset: 1,
3647 pad: 0,
3648 });
3649 }
3650 }
3651
3652 pub fn paint_quad(&mut self, quad: PaintQuad) {
3662 self.invalidator.debug_assert_paint();
3663
3664 let opacity = self.element_opacity();
3665 let snapped_bounds = self.snap_bounds(quad.bounds);
3666 let snapped_border_widths = self.snap_border_widths(quad.border_widths);
3667 self.next_frame.scene.insert_primitive(Quad {
3668 order: 0,
3669 bounds: snapped_bounds,
3670 content_mask: self.snapped_content_mask(),
3671 background: quad.background.opacity(opacity),
3672 border_color: quad.border_color.opacity(opacity),
3673 corner_radii: quad.corner_radii.scale(self.scale_factor()),
3674 border_widths: snapped_border_widths,
3675 border_style: quad.border_style,
3676 });
3677 }
3678
3679 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {
3683 self.invalidator.debug_assert_paint();
3684
3685 let scale_factor = self.scale_factor();
3686 let content_mask = self.content_mask();
3687 let opacity = self.element_opacity();
3688 path.content_mask = content_mask;
3689 let color: Background = color.into();
3690 path.color = color.opacity(opacity);
3691 self.next_frame
3692 .scene
3693 .insert_primitive(path.scale(scale_factor));
3694 }
3695
3696 pub fn paint_underline(
3700 &mut self,
3701 origin: Point<Pixels>,
3702 width: Pixels,
3703 style: &UnderlineStyle,
3704 ) {
3705 self.invalidator.debug_assert_paint();
3706
3707 let scale_factor = self.scale_factor();
3708 let thickness = self.snap_stroke(style.thickness);
3709 let height = if style.wavy {
3710 ScaledPixels(thickness.0 * 3.)
3711 } else {
3712 thickness
3713 };
3714 let bounds = Bounds {
3715 origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
3716 size: size(self.snap_stroke(width), height),
3717 };
3718 let element_opacity = self.element_opacity();
3719
3720 self.next_frame.scene.insert_primitive(Underline {
3721 order: 0,
3722 pad: 0,
3723 bounds,
3724 content_mask: self.snapped_content_mask(),
3725 color: style.color.unwrap_or_default().opacity(element_opacity),
3726 thickness,
3727 wavy: if style.wavy { 1 } else { 0 },
3728 });
3729 }
3730
3731 pub fn paint_strikethrough(
3735 &mut self,
3736 origin: Point<Pixels>,
3737 width: Pixels,
3738 style: &StrikethroughStyle,
3739 ) {
3740 self.invalidator.debug_assert_paint();
3741
3742 let scale_factor = self.scale_factor();
3743 let height = style.thickness;
3744 let bounds = Bounds {
3745 origin: origin.map(|c| ScaledPixels(round_to_device_pixel(c.0, scale_factor))),
3746 size: size(self.snap_stroke(width), self.snap_stroke(height)),
3747 };
3748 let opacity = self.element_opacity();
3749
3750 self.next_frame.scene.insert_primitive(Underline {
3751 order: 0,
3752 pad: 0,
3753 bounds,
3754 content_mask: self.snapped_content_mask(),
3755 thickness: self.snap_stroke(style.thickness),
3756 color: style.color.unwrap_or_default().opacity(opacity),
3757 wavy: 0,
3758 });
3759 }
3760
3761 pub fn paint_glyph(
3770 &mut self,
3771 origin: Point<Pixels>,
3772 font_id: FontId,
3773 glyph_id: GlyphId,
3774 font_size: Pixels,
3775 color: Hsla,
3776 ) -> Result<()> {
3777 self.invalidator.debug_assert_paint();
3778
3779 let element_opacity = self.element_opacity();
3780 let scale_factor = self.scale_factor();
3781 let glyph_origin = origin.scale(scale_factor);
3782
3783 let quantized_origin = Point::new(
3784 round_half_toward_zero(glyph_origin.x.0 * SUBPIXEL_VARIANTS_X as f32)
3785 / SUBPIXEL_VARIANTS_X as f32,
3786 round_half_toward_zero(glyph_origin.y.0 * SUBPIXEL_VARIANTS_Y as f32)
3787 / SUBPIXEL_VARIANTS_Y as f32,
3788 );
3789 let subpixel_variant = Point::new(
3790 (quantized_origin.x.fract() * SUBPIXEL_VARIANTS_X as f32) as u8,
3791 (quantized_origin.y.fract() * SUBPIXEL_VARIANTS_Y as f32) as u8,
3792 );
3793 let integer_origin = quantized_origin.map(|c| ScaledPixels(c.trunc()));
3794 let subpixel_rendering = self.should_use_subpixel_rendering(font_id, font_size);
3795 let dilation = self.text_system().glyph_dilation_for_color(color);
3796 let params = RenderGlyphParams {
3797 font_id,
3798 glyph_id,
3799 font_size,
3800 subpixel_variant,
3801 scale_factor,
3802 is_emoji: false,
3803 subpixel_rendering,
3804 dilation,
3805 };
3806
3807 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
3808 if !raster_bounds.is_zero() {
3809 let tile = self
3810 .sprite_atlas
3811 .get_or_insert_with(¶ms.clone().into(), &mut || {
3812 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
3813 Ok(Some((size, Cow::Owned(bytes))))
3814 })?
3815 .expect("Callback above only errors or returns Some");
3816 let bounds = Bounds {
3817 origin: integer_origin + raster_bounds.origin.map(Into::into),
3818 size: tile.bounds.size.map(Into::into),
3819 };
3820 let content_mask = self.snapped_content_mask();
3821
3822 if subpixel_rendering {
3823 self.next_frame.scene.insert_primitive(SubpixelSprite {
3824 order: 0,
3825 pad: 0,
3826 bounds,
3827 content_mask,
3828 color: color.opacity(element_opacity),
3829 tile,
3830 transformation: TransformationMatrix::unit(),
3831 });
3832 } else {
3833 self.next_frame.scene.insert_primitive(MonochromeSprite {
3834 order: 0,
3835 pad: 0,
3836 bounds,
3837 content_mask,
3838 color: color.opacity(element_opacity),
3839 tile,
3840 transformation: TransformationMatrix::unit(),
3841 });
3842 }
3843 }
3844 Ok(())
3845 }
3846
3847 fn should_use_subpixel_rendering(&self, font_id: FontId, font_size: Pixels) -> bool {
3848 if self.platform_window.background_appearance() != WindowBackgroundAppearance::Opaque {
3849 return false;
3850 }
3851
3852 if !self.platform_window.is_subpixel_rendering_supported() {
3853 return false;
3854 }
3855
3856 let mode = match self.text_rendering_mode.get() {
3857 TextRenderingMode::PlatformDefault => self
3858 .text_system()
3859 .recommended_rendering_mode(font_id, font_size),
3860 mode => mode,
3861 };
3862
3863 mode == TextRenderingMode::Subpixel
3864 }
3865
3866 pub fn paint_emoji(
3875 &mut self,
3876 origin: Point<Pixels>,
3877 font_id: FontId,
3878 glyph_id: GlyphId,
3879 font_size: Pixels,
3880 ) -> Result<()> {
3881 self.invalidator.debug_assert_paint();
3882
3883 let scale_factor = self.scale_factor();
3884 let glyph_origin = origin.scale(scale_factor);
3885 let integer_origin = glyph_origin.map(|c| ScaledPixels(round_half_toward_zero(c.0)));
3886 let params = RenderGlyphParams {
3887 font_id,
3888 glyph_id,
3889 font_size,
3890 subpixel_variant: Default::default(),
3891 scale_factor,
3892 is_emoji: true,
3893 subpixel_rendering: false,
3894 dilation: 0,
3895 };
3896
3897 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
3898 if !raster_bounds.is_zero() {
3899 let tile = self
3900 .sprite_atlas
3901 .get_or_insert_with(¶ms.clone().into(), &mut || {
3902 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
3903 Ok(Some((size, Cow::Owned(bytes))))
3904 })?
3905 .expect("Callback above only errors or returns Some");
3906
3907 let bounds = Bounds {
3908 origin: integer_origin + raster_bounds.origin.map(Into::into),
3909 size: tile.bounds.size.map(Into::into),
3910 };
3911 let content_mask = self.snapped_content_mask();
3912 let opacity = self.element_opacity();
3913
3914 self.next_frame.scene.insert_primitive(PolychromeSprite {
3915 order: 0,
3916 pad: 0,
3917 grayscale: false,
3918 bounds,
3919 corner_radii: Default::default(),
3920 content_mask,
3921 tile,
3922 opacity,
3923 });
3924 }
3925 Ok(())
3926 }
3927
3928 pub fn paint_svg(
3932 &mut self,
3933 bounds: Bounds<Pixels>,
3934 path: SharedString,
3935 mut data: Option<&[u8]>,
3936 transformation: TransformationMatrix,
3937 color: Hsla,
3938 cx: &App,
3939 ) -> Result<()> {
3940 self.invalidator.debug_assert_paint();
3941
3942 let element_opacity = self.element_opacity();
3943 let bounds = self.snap_bounds(bounds);
3944
3945 let params = RenderSvgParams {
3946 path,
3947 size: bounds.size.map(|pixels| {
3948 DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)
3949 }),
3950 };
3951
3952 let Some(tile) =
3953 self.sprite_atlas
3954 .get_or_insert_with(¶ms.clone().into(), &mut || {
3955 let Some((size, bytes)) = cx.svg_renderer.render_alpha_mask(¶ms, data)?
3956 else {
3957 return Ok(None);
3958 };
3959 Ok(Some((size, Cow::Owned(bytes))))
3960 })?
3961 else {
3962 return Ok(());
3963 };
3964 let content_mask = self.snapped_content_mask();
3965 let svg_bounds = Bounds {
3966 origin: bounds.center()
3967 - Point::new(
3968 ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
3969 ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
3970 ),
3971 size: tile
3972 .bounds
3973 .size
3974 .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)),
3975 };
3976 let final_bounds = svg_bounds
3977 .map_origin(|value| ScaledPixels(round_half_toward_zero(value.0)))
3978 .map_size(|size| size.ceil());
3979
3980 self.next_frame.scene.insert_primitive(MonochromeSprite {
3981 order: 0,
3982 pad: 0,
3983 bounds: final_bounds,
3984 content_mask,
3985 color: color.opacity(element_opacity),
3986 tile,
3987 transformation,
3988 });
3989
3990 Ok(())
3991 }
3992
3993 pub fn paint_image(
3998 &mut self,
3999 bounds: Bounds<Pixels>,
4000 corner_radii: Corners<Pixels>,
4001 data: Arc<RenderImage>,
4002 frame_index: usize,
4003 grayscale: bool,
4004 ) -> Result<()> {
4005 self.invalidator.debug_assert_paint();
4006
4007 let bounds = self.snap_bounds(bounds);
4008 let params = RenderImageParams {
4009 image_id: data.id,
4010 frame_index,
4011 };
4012
4013 let tile = self
4014 .sprite_atlas
4015 .get_or_insert_with(¶ms.into(), &mut || {
4016 Ok(Some((
4017 data.size(frame_index),
4018 Cow::Borrowed(
4019 data.as_bytes(frame_index)
4020 .expect("It's the caller's job to pass a valid frame index"),
4021 ),
4022 )))
4023 })?
4024 .expect("Callback above only returns Some");
4025 let content_mask = self.snapped_content_mask();
4026 let corner_radii = corner_radii.scale(self.scale_factor());
4027 let opacity = self.element_opacity();
4028
4029 self.next_frame.scene.insert_primitive(PolychromeSprite {
4030 order: 0,
4031 pad: 0,
4032 grayscale,
4033 bounds,
4034 content_mask,
4035 corner_radii,
4036 tile,
4037 opacity,
4038 });
4039 Ok(())
4040 }
4041
4042 #[cfg(target_os = "macos")]
4046 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {
4047 use crate::PaintSurface;
4048
4049 self.invalidator.debug_assert_paint();
4050
4051 let bounds = self.snap_bounds(bounds);
4052 let content_mask = self.snapped_content_mask();
4053 self.next_frame.scene.insert_primitive(PaintSurface {
4054 order: 0,
4055 bounds,
4056 content_mask,
4057 image_buffer,
4058 });
4059 }
4060
4061 pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {
4063 for frame_index in 0..data.frame_count() {
4064 let params = RenderImageParams {
4065 image_id: data.id,
4066 frame_index,
4067 };
4068
4069 self.sprite_atlas.remove(¶ms.clone().into());
4070 }
4071
4072 Ok(())
4073 }
4074
4075 #[must_use]
4081 pub fn request_layout(
4082 &mut self,
4083 style: Style,
4084 children: impl IntoIterator<Item = LayoutId>,
4085 cx: &mut App,
4086 ) -> LayoutId {
4087 self.invalidator.debug_assert_prepaint();
4088
4089 cx.layout_id_buffer.clear();
4090 cx.layout_id_buffer.extend(children);
4091 let rem_size = self.rem_size();
4092 let scale_factor = self.scale_factor();
4093
4094 self.layout_engine.as_mut().unwrap().request_layout(
4095 style,
4096 rem_size,
4097 scale_factor,
4098 &cx.layout_id_buffer,
4099 )
4100 }
4101
4102 pub fn request_measured_layout<F>(&mut self, style: Style, measure: F) -> LayoutId
4111 where
4112 F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
4113 + 'static,
4114 {
4115 self.invalidator.debug_assert_prepaint();
4116
4117 let rem_size = self.rem_size();
4118 let scale_factor = self.scale_factor();
4119 self.layout_engine
4120 .as_mut()
4121 .unwrap()
4122 .request_measured_layout(style, rem_size, scale_factor, measure)
4123 }
4124
4125 pub fn compute_layout(
4131 &mut self,
4132 layout_id: LayoutId,
4133 available_space: Size<AvailableSpace>,
4134 cx: &mut App,
4135 ) {
4136 self.invalidator.debug_assert_prepaint();
4137
4138 let mut layout_engine = self.layout_engine.take().unwrap();
4139 layout_engine.compute_layout(layout_id, available_space, self, cx);
4140 self.layout_engine = Some(layout_engine);
4141 }
4142
4143 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
4148 self.invalidator.debug_assert_prepaint();
4149
4150 let scale_factor = self.scale_factor();
4151 let mut bounds = self
4152 .layout_engine
4153 .as_mut()
4154 .unwrap()
4155 .layout_bounds(layout_id, scale_factor)
4156 .map(Into::into);
4157 let snapped_offset = self.pixel_snap_point(self.element_offset());
4158 bounds.origin += snapped_offset;
4159 bounds
4160 }
4161
4162 pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, behavior: HitboxBehavior) -> Hitbox {
4168 self.invalidator.debug_assert_prepaint();
4169
4170 let content_mask = self.content_mask();
4171 let mut id = self.next_hitbox_id;
4172 self.next_hitbox_id = self.next_hitbox_id.next();
4173 let hitbox = Hitbox {
4174 id,
4175 bounds,
4176 content_mask,
4177 behavior,
4178 };
4179 self.next_frame.hitboxes.push(hitbox.clone());
4180 hitbox
4181 }
4182
4183 pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) {
4187 self.invalidator.debug_assert_paint();
4188 self.next_frame.window_control_hitboxes.push((area, hitbox));
4189 }
4190
4191 pub fn set_key_context(&mut self, context: KeyContext) {
4196 self.invalidator.debug_assert_paint();
4197 self.next_frame.dispatch_tree.set_key_context(context);
4198 }
4199
4200 pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {
4205 self.invalidator.debug_assert_prepaint();
4206 if focus_handle.is_focused(self) {
4207 self.next_frame.focus = Some(focus_handle.id);
4208 }
4209 self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);
4210 }
4211
4212 pub fn set_view_id(&mut self, view_id: EntityId) {
4218 self.invalidator.debug_assert_prepaint();
4219 self.next_frame.dispatch_tree.set_view_id(view_id);
4220 }
4221
4222 pub fn current_view(&self) -> EntityId {
4224 self.invalidator.debug_assert_paint_or_prepaint();
4225 self.rendered_entity_stack.last().copied().unwrap()
4226 }
4227
4228 #[inline]
4229 pub(crate) fn with_rendered_view<R>(
4230 &mut self,
4231 id: EntityId,
4232 f: impl FnOnce(&mut Self) -> R,
4233 ) -> R {
4234 self.rendered_entity_stack.push(id);
4235 let result = f(self);
4236 self.rendered_entity_stack.pop();
4237 result
4238 }
4239
4240 pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R
4242 where
4243 F: FnOnce(&mut Self) -> R,
4244 {
4245 if let Some(image_cache) = image_cache {
4246 self.image_cache_stack.push(image_cache);
4247 let result = f(self);
4248 self.image_cache_stack.pop();
4249 result
4250 } else {
4251 f(self)
4252 }
4253 }
4254
4255 pub fn handle_input(
4264 &mut self,
4265 focus_handle: &FocusHandle,
4266 input_handler: impl InputHandler,
4267 cx: &App,
4268 ) {
4269 self.invalidator.debug_assert_paint();
4270
4271 if focus_handle.is_focused(self) {
4272 let cx = self.to_async(cx);
4273 self.next_frame
4274 .input_handlers
4275 .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));
4276 }
4277 }
4278
4279 pub fn on_mouse_event<Event: MouseEvent>(
4285 &mut self,
4286 mut listener: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
4287 ) {
4288 self.invalidator.debug_assert_paint();
4289
4290 self.next_frame.mouse_listeners.push(Some(Box::new(
4291 move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {
4292 if let Some(event) = event.downcast_ref() {
4293 listener(event, phase, window, cx)
4294 }
4295 },
4296 )));
4297 }
4298
4299 pub fn on_key_event<Event: KeyEvent>(
4308 &mut self,
4309 listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
4310 ) {
4311 self.invalidator.debug_assert_paint();
4312
4313 self.next_frame.dispatch_tree.on_key_event(Rc::new(
4314 move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {
4315 if let Some(event) = event.downcast_ref::<Event>() {
4316 listener(event, phase, window, cx)
4317 }
4318 },
4319 ));
4320 }
4321
4322 pub fn on_modifiers_changed(
4329 &mut self,
4330 listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
4331 ) {
4332 self.invalidator.debug_assert_paint();
4333
4334 self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(
4335 move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {
4336 listener(event, window, cx)
4337 },
4338 ));
4339 }
4340
4341 pub fn on_focus_in(
4345 &mut self,
4346 handle: &FocusHandle,
4347 cx: &mut App,
4348 mut listener: impl FnMut(&mut Window, &mut App) + 'static,
4349 ) -> Subscription {
4350 let focus_id = handle.id;
4351 let (subscription, activate) =
4352 self.new_focus_listener(Box::new(move |event, window, cx| {
4353 if event.is_focus_in(focus_id) {
4354 listener(window, cx);
4355 }
4356 true
4357 }));
4358 cx.defer(move |_| activate());
4359 subscription
4360 }
4361
4362 pub fn on_focus_out(
4365 &mut self,
4366 handle: &FocusHandle,
4367 cx: &mut App,
4368 mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,
4369 ) -> Subscription {
4370 let focus_id = handle.id;
4371 let (subscription, activate) =
4372 self.new_focus_listener(Box::new(move |event, window, cx| {
4373 if let Some(blurred_id) = event.previous_focus_path.last().copied()
4374 && event.is_focus_out(focus_id)
4375 {
4376 let event = FocusOutEvent {
4377 blurred: WeakFocusHandle {
4378 id: blurred_id,
4379 handles: Arc::downgrade(&cx.focus_handles),
4380 },
4381 };
4382 listener(event, window, cx)
4383 }
4384 true
4385 }));
4386 cx.defer(move |_| activate());
4387 subscription
4388 }
4389
4390 fn reset_cursor_style(&self, cx: &mut App) {
4391 if self.is_window_hovered() {
4393 let style = self
4394 .rendered_frame
4395 .cursor_style(self)
4396 .unwrap_or(CursorStyle::Arrow);
4397 cx.platform.set_cursor_style(style);
4398 }
4399 }
4400
4401 pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {
4404 let keystroke = keystroke.with_simulated_ime();
4405 let result = self.dispatch_event(
4406 PlatformInput::KeyDown(KeyDownEvent {
4407 keystroke: keystroke.clone(),
4408 is_held: false,
4409 prefer_character_input: false,
4410 }),
4411 cx,
4412 );
4413 if !result.propagate {
4414 return true;
4415 }
4416
4417 if let Some(input) = keystroke.key_char
4418 && let Some(mut input_handler) = self.platform_window.take_input_handler()
4419 {
4420 input_handler.dispatch_input(&input, self, cx);
4421 self.platform_window.set_input_handler(input_handler);
4422 return true;
4423 }
4424
4425 false
4426 }
4427
4428 pub fn keystroke_text_for(&self, action: &dyn Action) -> String {
4431 self.highest_precedence_binding_for_action(action)
4432 .map(|binding| {
4433 binding
4434 .keystrokes()
4435 .iter()
4436 .map(ToString::to_string)
4437 .collect::<Vec<_>>()
4438 .join(" ")
4439 })
4440 .unwrap_or_else(|| action.name().to_string())
4441 }
4442
4443 #[profiling::function]
4445 pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {
4446 #[cfg(feature = "input-latency-histogram")]
4447 let dispatch_time = Instant::now();
4448 let update_count_before = self.invalidator.update_count();
4449 let old_modality = self.last_input_modality;
4453 self.last_input_modality = match &event {
4454 PlatformInput::KeyDown(_) => InputModality::Keyboard,
4455 PlatformInput::MouseMove(_) | PlatformInput::MouseDown(_) => InputModality::Mouse,
4456 _ => self.last_input_modality,
4457 };
4458 if self.last_input_modality != old_modality {
4459 self.refresh();
4460 }
4461
4462 cx.propagate_event = true;
4464 self.default_prevented = false;
4466
4467 let event = match event {
4468 PlatformInput::MouseMove(mouse_move) => {
4471 self.mouse_position = mouse_move.position;
4472 self.modifiers = mouse_move.modifiers;
4473 PlatformInput::MouseMove(mouse_move)
4474 }
4475 PlatformInput::MouseDown(mouse_down) => {
4476 self.mouse_position = mouse_down.position;
4477 self.modifiers = mouse_down.modifiers;
4478 PlatformInput::MouseDown(mouse_down)
4479 }
4480 PlatformInput::MouseUp(mouse_up) => {
4481 self.mouse_position = mouse_up.position;
4482 self.modifiers = mouse_up.modifiers;
4483 PlatformInput::MouseUp(mouse_up)
4484 }
4485 PlatformInput::MousePressure(mouse_pressure) => {
4486 PlatformInput::MousePressure(mouse_pressure)
4487 }
4488 PlatformInput::MouseExited(mouse_exited) => {
4489 self.modifiers = mouse_exited.modifiers;
4490 PlatformInput::MouseExited(mouse_exited)
4491 }
4492 PlatformInput::ModifiersChanged(modifiers_changed) => {
4493 self.modifiers = modifiers_changed.modifiers;
4494 self.capslock = modifiers_changed.capslock;
4495 PlatformInput::ModifiersChanged(modifiers_changed)
4496 }
4497 PlatformInput::ScrollWheel(scroll_wheel) => {
4498 self.mouse_position = scroll_wheel.position;
4499 self.modifiers = scroll_wheel.modifiers;
4500 PlatformInput::ScrollWheel(scroll_wheel)
4501 }
4502 PlatformInput::Pinch(pinch) => {
4503 self.mouse_position = pinch.position;
4504 self.modifiers = pinch.modifiers;
4505 PlatformInput::Pinch(pinch)
4506 }
4507 PlatformInput::FileDrop(file_drop) => match file_drop {
4510 FileDropEvent::Entered { position, paths } => {
4511 self.mouse_position = position;
4512 if cx.active_drag.is_none() {
4513 cx.active_drag = Some(AnyDrag {
4514 value: Arc::new(paths.clone()),
4515 view: cx.new(|_| paths).into(),
4516 cursor_offset: position,
4517 cursor_style: None,
4518 });
4519 }
4520 PlatformInput::MouseMove(MouseMoveEvent {
4521 position,
4522 pressed_button: Some(MouseButton::Left),
4523 modifiers: Modifiers::default(),
4524 })
4525 }
4526 FileDropEvent::Pending { position } => {
4527 self.mouse_position = position;
4528 PlatformInput::MouseMove(MouseMoveEvent {
4529 position,
4530 pressed_button: Some(MouseButton::Left),
4531 modifiers: Modifiers::default(),
4532 })
4533 }
4534 FileDropEvent::Submit { position } => {
4535 cx.activate(true);
4536 self.mouse_position = position;
4537 PlatformInput::MouseUp(MouseUpEvent {
4538 button: MouseButton::Left,
4539 position,
4540 modifiers: Modifiers::default(),
4541 click_count: 1,
4542 })
4543 }
4544 FileDropEvent::Exited => {
4545 cx.active_drag.take();
4546 PlatformInput::FileDrop(FileDropEvent::Exited)
4547 }
4548 },
4549 PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
4550 };
4551
4552 if let Some(any_mouse_event) = event.mouse_event() {
4553 self.dispatch_mouse_event(any_mouse_event, cx);
4554 } else if let Some(any_key_event) = event.keyboard_event() {
4555 self.dispatch_key_event(any_key_event, cx);
4556 }
4557
4558 if self.invalidator.update_count() > update_count_before {
4559 self.input_rate_tracker.borrow_mut().record_input();
4560 #[cfg(feature = "input-latency-histogram")]
4561 if self.invalidator.not_drawing() {
4562 self.input_latency_tracker.record_input(dispatch_time);
4563 } else {
4564 self.input_latency_tracker.record_mid_draw_input();
4565 }
4566 }
4567
4568 DispatchEventResult {
4569 propagate: cx.propagate_event,
4570 default_prevented: self.default_prevented,
4571 }
4572 }
4573
4574 fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
4575 let hit_test = self.rendered_frame.hit_test(self.mouse_position());
4576 if hit_test != self.mouse_hit_test {
4577 self.mouse_hit_test = hit_test;
4578 self.reset_cursor_style(cx);
4579 }
4580
4581 #[cfg(any(feature = "inspector", debug_assertions))]
4582 if self.is_inspector_picking(cx) {
4583 self.handle_inspector_mouse_event(event, cx);
4584 return;
4586 }
4587
4588 let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);
4589
4590 for listener in &mut mouse_listeners {
4593 let listener = listener.as_mut().unwrap();
4594 listener(event, DispatchPhase::Capture, self, cx);
4595 if !cx.propagate_event {
4596 break;
4597 }
4598 }
4599
4600 if cx.propagate_event {
4602 for listener in mouse_listeners.iter_mut().rev() {
4603 let listener = listener.as_mut().unwrap();
4604 listener(event, DispatchPhase::Bubble, self, cx);
4605 if !cx.propagate_event {
4606 break;
4607 }
4608 }
4609 }
4610
4611 self.rendered_frame.mouse_listeners = mouse_listeners;
4612
4613 if cx.has_active_drag() {
4614 if event.is::<MouseMoveEvent>() {
4615 self.refresh();
4618 } else if event.is::<MouseUpEvent>() {
4619 cx.active_drag = None;
4622 self.refresh();
4623 }
4624 }
4625
4626 if event.is::<MouseUpEvent>() && self.captured_hitbox.is_some() {
4628 self.captured_hitbox = None;
4629 }
4630 }
4631
4632 fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {
4633 if self.invalidator.is_dirty() {
4634 self.draw(cx).clear();
4635 }
4636
4637 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4638 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4639
4640 let mut keystroke: Option<Keystroke> = None;
4641
4642 if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {
4643 if event.modifiers.number_of_modifiers() == 0
4644 && self.pending_modifier.modifiers.number_of_modifiers() == 1
4645 && !self.pending_modifier.saw_keystroke
4646 {
4647 let key = match self.pending_modifier.modifiers {
4648 modifiers if modifiers.shift => Some("shift"),
4649 modifiers if modifiers.control => Some("control"),
4650 modifiers if modifiers.alt => Some("alt"),
4651 modifiers if modifiers.platform => Some("platform"),
4652 modifiers if modifiers.function => Some("function"),
4653 _ => None,
4654 };
4655 if let Some(key) = key {
4656 keystroke = Some(Keystroke {
4657 key: key.to_string(),
4658 key_char: None,
4659 modifiers: Modifiers::default(),
4660 });
4661 }
4662 }
4663
4664 if self.pending_modifier.modifiers.number_of_modifiers() == 0
4665 && event.modifiers.number_of_modifiers() == 1
4666 {
4667 self.pending_modifier.saw_keystroke = false
4668 }
4669 self.pending_modifier.modifiers = event.modifiers
4670 } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
4671 self.pending_modifier.saw_keystroke = true;
4672 keystroke = Some(key_down_event.keystroke.clone());
4673 if key_down_event.keystroke.key_char.is_some()
4674 && matches!(
4675 cx.cursor_hide_mode,
4676 CursorHideMode::OnTyping | CursorHideMode::OnTypingAndAction
4677 )
4678 {
4679 cx.platform.hide_cursor_until_mouse_moves();
4680 }
4681 }
4682
4683 let Some(keystroke) = keystroke else {
4684 self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
4685 return;
4686 };
4687
4688 cx.propagate_event = true;
4689 self.dispatch_keystroke_interceptors(event, self.context_stack(), cx);
4690 if !cx.propagate_event {
4691 self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
4692 return;
4693 }
4694
4695 let mut currently_pending = self.pending_input.take().unwrap_or_default();
4696 if currently_pending.focus.is_some() && currently_pending.focus != self.focus {
4697 currently_pending = PendingInput::default();
4698 }
4699
4700 let match_result = self.rendered_frame.dispatch_tree.dispatch_key(
4701 currently_pending.keystrokes,
4702 keystroke,
4703 &dispatch_path,
4704 );
4705
4706 if !match_result.to_replay.is_empty() {
4707 self.replay_pending_input(match_result.to_replay, cx);
4708 cx.propagate_event = true;
4709 }
4710
4711 if !match_result.pending.is_empty() {
4712 currently_pending.timer.take();
4713 currently_pending.keystrokes = match_result.pending;
4714 currently_pending.focus = self.focus;
4715
4716 let text_input_requires_timeout = event
4717 .downcast_ref::<KeyDownEvent>()
4718 .filter(|key_down| key_down.keystroke.key_char.is_some())
4719 .and_then(|_| self.platform_window.take_input_handler())
4720 .map_or(false, |mut input_handler| {
4721 let accepts = input_handler.accepts_text_input(self, cx);
4722 self.platform_window.set_input_handler(input_handler);
4723 accepts
4724 });
4725
4726 currently_pending.needs_timeout |=
4727 match_result.pending_has_binding || text_input_requires_timeout;
4728
4729 if currently_pending.needs_timeout {
4730 currently_pending.timer = Some(self.spawn(cx, async move |cx| {
4731 cx.background_executor.timer(Duration::from_secs(1)).await;
4732 cx.update(move |window, cx| {
4733 let Some(currently_pending) = window
4734 .pending_input
4735 .take()
4736 .filter(|pending| pending.focus == window.focus)
4737 else {
4738 return;
4739 };
4740
4741 let node_id = window.focus_node_id_in_rendered_frame(window.focus);
4742 let dispatch_path =
4743 window.rendered_frame.dispatch_tree.dispatch_path(node_id);
4744
4745 let to_replay = window
4746 .rendered_frame
4747 .dispatch_tree
4748 .flush_dispatch(currently_pending.keystrokes, &dispatch_path);
4749
4750 window.pending_input_changed(cx);
4751 window.replay_pending_input(to_replay, cx)
4752 })
4753 .log_err();
4754 }));
4755 } else {
4756 currently_pending.timer = None;
4757 }
4758 self.pending_input = Some(currently_pending);
4759 self.pending_input_changed(cx);
4760 cx.propagate_event = false;
4761 return;
4762 }
4763
4764 let skip_bindings = event
4765 .downcast_ref::<KeyDownEvent>()
4766 .filter(|key_down_event| key_down_event.prefer_character_input)
4767 .map(|_| {
4768 self.platform_window
4769 .take_input_handler()
4770 .map_or(false, |mut input_handler| {
4771 let accepts = input_handler.accepts_text_input(self, cx);
4772 self.platform_window.set_input_handler(input_handler);
4773 accepts
4776 })
4777 })
4778 .unwrap_or(false);
4779
4780 if !skip_bindings {
4781 for binding in match_result.bindings {
4782 self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
4783 if !cx.propagate_event {
4784 self.dispatch_keystroke_observers(
4785 event,
4786 Some(binding.action),
4787 match_result.context_stack,
4788 cx,
4789 );
4790 self.pending_input_changed(cx);
4791 return;
4792 }
4793 }
4794 }
4795
4796 self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);
4797 self.pending_input_changed(cx);
4798 }
4799
4800 fn finish_dispatch_key_event(
4801 &mut self,
4802 event: &dyn Any,
4803 dispatch_path: SmallVec<[DispatchNodeId; 32]>,
4804 context_stack: Vec<KeyContext>,
4805 cx: &mut App,
4806 ) {
4807 self.dispatch_key_down_up_event(event, &dispatch_path, cx);
4808 if !cx.propagate_event {
4809 return;
4810 }
4811
4812 self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);
4813 if !cx.propagate_event {
4814 return;
4815 }
4816
4817 self.dispatch_keystroke_observers(event, None, context_stack, cx);
4818 }
4819
4820 pub(crate) fn pending_input_changed(&mut self, cx: &mut App) {
4821 self.pending_input_observers
4822 .clone()
4823 .retain(&(), |callback| callback(self, cx));
4824 }
4825
4826 fn dispatch_key_down_up_event(
4827 &mut self,
4828 event: &dyn Any,
4829 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
4830 cx: &mut App,
4831 ) {
4832 for node_id in dispatch_path {
4834 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4835
4836 for key_listener in node.key_listeners.clone() {
4837 key_listener(event, DispatchPhase::Capture, self, cx);
4838 if !cx.propagate_event {
4839 return;
4840 }
4841 }
4842 }
4843
4844 for node_id in dispatch_path.iter().rev() {
4846 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4848 for key_listener in node.key_listeners.clone() {
4849 key_listener(event, DispatchPhase::Bubble, self, cx);
4850 if !cx.propagate_event {
4851 return;
4852 }
4853 }
4854 }
4855 }
4856
4857 fn dispatch_modifiers_changed_event(
4858 &mut self,
4859 event: &dyn Any,
4860 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
4861 cx: &mut App,
4862 ) {
4863 let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {
4864 return;
4865 };
4866 for node_id in dispatch_path.iter().rev() {
4867 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4868 for listener in node.modifiers_changed_listeners.clone() {
4869 listener(event, self, cx);
4870 if !cx.propagate_event {
4871 return;
4872 }
4873 }
4874 }
4875 }
4876
4877 pub fn has_pending_keystrokes(&self) -> bool {
4879 self.pending_input.is_some()
4880 }
4881
4882 pub(crate) fn clear_pending_keystrokes(&mut self) {
4883 self.pending_input.take();
4884 }
4885
4886 pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {
4888 self.pending_input
4889 .as_ref()
4890 .map(|pending_input| pending_input.keystrokes.as_slice())
4891 }
4892
4893 fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {
4894 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4895 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4896
4897 'replay: for replay in replays {
4898 let event = KeyDownEvent {
4899 keystroke: replay.keystroke.clone(),
4900 is_held: false,
4901 prefer_character_input: true,
4902 };
4903
4904 cx.propagate_event = true;
4905 for binding in replay.bindings {
4906 self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
4907 if !cx.propagate_event {
4908 self.dispatch_keystroke_observers(
4909 &event,
4910 Some(binding.action),
4911 Vec::default(),
4912 cx,
4913 );
4914 continue 'replay;
4915 }
4916 }
4917
4918 self.dispatch_key_down_up_event(&event, &dispatch_path, cx);
4919 if !cx.propagate_event {
4920 continue 'replay;
4921 }
4922 if let Some(input) = replay.keystroke.key_char.as_ref().cloned()
4923 && let Some(mut input_handler) = self.platform_window.take_input_handler()
4924 {
4925 input_handler.dispatch_input(&input, self, cx);
4926 self.platform_window.set_input_handler(input_handler)
4927 }
4928 }
4929 }
4930
4931 fn focus_node_id_in_rendered_frame(&self, focus_id: Option<FocusId>) -> DispatchNodeId {
4932 focus_id
4933 .and_then(|focus_id| {
4934 self.rendered_frame
4935 .dispatch_tree
4936 .focusable_node_id(focus_id)
4937 })
4938 .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id())
4939 }
4940
4941 fn dispatch_action_on_node(
4942 &mut self,
4943 node_id: DispatchNodeId,
4944 action: &dyn Action,
4945 cx: &mut App,
4946 ) {
4947 self.dispatch_action_on_node_inner(node_id, action, cx);
4948
4949 if !cx.propagate_event
4950 && cx.cursor_hide_mode == CursorHideMode::OnTypingAndAction
4951 && self.last_input_was_keyboard()
4952 {
4953 cx.platform.hide_cursor_until_mouse_moves();
4954 }
4955 }
4956
4957 fn dispatch_action_on_node_inner(
4958 &mut self,
4959 node_id: DispatchNodeId,
4960 action: &dyn Action,
4961 cx: &mut App,
4962 ) {
4963 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4964
4965 cx.propagate_event = true;
4967 if let Some(mut global_listeners) = cx
4968 .global_action_listeners
4969 .remove(&action.as_any().type_id())
4970 {
4971 for listener in &global_listeners {
4972 profiler::update_running_action(action, cx);
4973 listener(action.as_any(), DispatchPhase::Capture, cx);
4974 profiler::save_action_timing();
4975 if !cx.propagate_event {
4976 break;
4977 }
4978 }
4979
4980 global_listeners.extend(
4981 cx.global_action_listeners
4982 .remove(&action.as_any().type_id())
4983 .unwrap_or_default(),
4984 );
4985
4986 cx.global_action_listeners
4987 .insert(action.as_any().type_id(), global_listeners);
4988 }
4989
4990 if !cx.propagate_event {
4991 return;
4992 }
4993
4994 for node_id in &dispatch_path {
4996 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4997 for DispatchActionListener {
4998 action_type,
4999 listener,
5000 } in node.action_listeners.clone()
5001 {
5002 let any_action = action.as_any();
5003 if action_type == any_action.type_id() {
5004 profiler::update_running_action(action, cx);
5005 listener(any_action, DispatchPhase::Capture, self, cx);
5006 profiler::save_action_timing();
5007
5008 if !cx.propagate_event {
5009 return;
5010 }
5011 }
5012 }
5013 }
5014
5015 for node_id in dispatch_path.iter().rev() {
5017 let node = self.rendered_frame.dispatch_tree.node(*node_id);
5018 for DispatchActionListener {
5019 action_type,
5020 listener,
5021 } in node.action_listeners.clone()
5022 {
5023 let any_action = action.as_any();
5024 if action_type == any_action.type_id() {
5025 cx.propagate_event = false; profiler::update_running_action(action, cx);
5027 listener(any_action, DispatchPhase::Bubble, self, cx);
5028 profiler::save_action_timing();
5029
5030 if !cx.propagate_event {
5031 return;
5032 }
5033 }
5034 }
5035 }
5036
5037 if let Some(mut global_listeners) = cx
5039 .global_action_listeners
5040 .remove(&action.as_any().type_id())
5041 {
5042 for listener in global_listeners.iter().rev() {
5043 cx.propagate_event = false; profiler::update_running_action(action, cx);
5046 listener(action.as_any(), DispatchPhase::Bubble, cx);
5047 profiler::save_action_timing();
5048 if !cx.propagate_event {
5049 break;
5050 }
5051 }
5052
5053 global_listeners.extend(
5054 cx.global_action_listeners
5055 .remove(&action.as_any().type_id())
5056 .unwrap_or_default(),
5057 );
5058
5059 cx.global_action_listeners
5060 .insert(action.as_any().type_id(), global_listeners);
5061 }
5062 }
5063
5064 pub fn observe_global<G: Global>(
5067 &mut self,
5068 cx: &mut App,
5069 f: impl Fn(&mut Window, &mut App) + 'static,
5070 ) -> Subscription {
5071 let window_handle = self.handle;
5072 let (subscription, activate) = cx.global_observers.insert(
5073 TypeId::of::<G>(),
5074 Box::new(move |cx| {
5075 window_handle
5076 .update(cx, |_, window, cx| f(window, cx))
5077 .is_ok()
5078 }),
5079 );
5080 cx.defer(move |_| activate());
5081 subscription
5082 }
5083
5084 pub fn activate_window(&self) {
5086 self.platform_window.activate();
5087 }
5088
5089 pub fn minimize_window(&self) {
5091 self.platform_window.minimize();
5092 }
5093
5094 pub fn toggle_fullscreen(&self) {
5096 self.platform_window.toggle_fullscreen();
5097 }
5098
5099 pub fn invalidate_character_coordinates(&self) {
5101 self.on_next_frame(|window, cx| {
5102 if let Some(mut input_handler) = window.platform_window.take_input_handler() {
5103 if let Some(bounds) = input_handler.selected_bounds(window, cx) {
5104 window.platform_window.update_ime_position(bounds);
5105 }
5106 window.platform_window.set_input_handler(input_handler);
5107 }
5108 });
5109 }
5110
5111 pub fn prompt<T>(
5115 &mut self,
5116 level: PromptLevel,
5117 message: &str,
5118 detail: Option<&str>,
5119 answers: &[T],
5120 cx: &mut App,
5121 ) -> oneshot::Receiver<usize>
5122 where
5123 T: Clone + Into<PromptButton>,
5124 {
5125 let prompt_builder = cx.prompt_builder.take();
5126 let Some(prompt_builder) = prompt_builder else {
5127 unreachable!("Re-entrant window prompting is not supported by GPUI");
5128 };
5129
5130 let answers = answers
5131 .iter()
5132 .map(|answer| answer.clone().into())
5133 .collect::<Vec<_>>();
5134
5135 let receiver = match &prompt_builder {
5136 PromptBuilder::Default => self
5137 .platform_window
5138 .prompt(level, message, detail, &answers)
5139 .unwrap_or_else(|| {
5140 self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
5141 }),
5142 PromptBuilder::Custom(_) => {
5143 self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
5144 }
5145 };
5146
5147 cx.prompt_builder = Some(prompt_builder);
5148
5149 receiver
5150 }
5151
5152 fn build_custom_prompt(
5153 &mut self,
5154 prompt_builder: &PromptBuilder,
5155 level: PromptLevel,
5156 message: &str,
5157 detail: Option<&str>,
5158 answers: &[PromptButton],
5159 cx: &mut App,
5160 ) -> oneshot::Receiver<usize> {
5161 let (sender, receiver) = oneshot::channel();
5162 let handle = PromptHandle::new(sender);
5163 let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);
5164 self.prompt = Some(handle);
5165 receiver
5166 }
5167
5168 pub fn context_stack(&self) -> Vec<KeyContext> {
5170 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
5171 let dispatch_tree = &self.rendered_frame.dispatch_tree;
5172 dispatch_tree
5173 .dispatch_path(node_id)
5174 .iter()
5175 .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())
5176 .collect()
5177 }
5178
5179 pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {
5181 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
5182 let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);
5183 for action_type in cx.global_action_listeners.keys() {
5184 if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {
5185 let action = cx.actions.build_action_type(action_type).ok();
5186 if let Some(action) = action {
5187 actions.insert(ix, action);
5188 }
5189 }
5190 }
5191 actions
5192 }
5193
5194 pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
5197 self.rendered_frame
5198 .dispatch_tree
5199 .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)
5200 }
5201
5202 pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option<KeyBinding> {
5205 self.rendered_frame
5206 .dispatch_tree
5207 .highest_precedence_binding_for_action(
5208 action,
5209 &self.rendered_frame.dispatch_tree.context_stack,
5210 )
5211 }
5212
5213 pub fn bindings_for_action_in_context(
5215 &self,
5216 action: &dyn Action,
5217 context: KeyContext,
5218 ) -> Vec<KeyBinding> {
5219 let dispatch_tree = &self.rendered_frame.dispatch_tree;
5220 dispatch_tree.bindings_for_action(action, &[context])
5221 }
5222
5223 pub fn highest_precedence_binding_for_action_in_context(
5226 &self,
5227 action: &dyn Action,
5228 context: KeyContext,
5229 ) -> Option<KeyBinding> {
5230 let dispatch_tree = &self.rendered_frame.dispatch_tree;
5231 dispatch_tree.highest_precedence_binding_for_action(action, &[context])
5232 }
5233
5234 pub fn bindings_for_action_in(
5238 &self,
5239 action: &dyn Action,
5240 focus_handle: &FocusHandle,
5241 ) -> Vec<KeyBinding> {
5242 let dispatch_tree = &self.rendered_frame.dispatch_tree;
5243 let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else {
5244 return vec![];
5245 };
5246 dispatch_tree.bindings_for_action(action, &context_stack)
5247 }
5248
5249 pub fn highest_precedence_binding_for_action_in(
5253 &self,
5254 action: &dyn Action,
5255 focus_handle: &FocusHandle,
5256 ) -> Option<KeyBinding> {
5257 let dispatch_tree = &self.rendered_frame.dispatch_tree;
5258 let context_stack = self.context_stack_for_focus_handle(focus_handle)?;
5259 dispatch_tree.highest_precedence_binding_for_action(action, &context_stack)
5260 }
5261
5262 pub fn possible_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
5264 self.rendered_frame
5265 .dispatch_tree
5266 .possible_next_bindings_for_input(input, &self.context_stack())
5267 }
5268
5269 fn context_stack_for_focus_handle(
5270 &self,
5271 focus_handle: &FocusHandle,
5272 ) -> Option<Vec<KeyContext>> {
5273 let dispatch_tree = &self.rendered_frame.dispatch_tree;
5274 let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?;
5275 let context_stack: Vec<_> = dispatch_tree
5276 .dispatch_path(node_id)
5277 .into_iter()
5278 .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
5279 .collect();
5280 Some(context_stack)
5281 }
5282
5283 pub fn listener_for<T: 'static, E>(
5285 &self,
5286 view: &Entity<T>,
5287 f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
5288 ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
5289 let view = view.downgrade();
5290 move |e: &E, window: &mut Window, cx: &mut App| {
5291 view.update(cx, |view, cx| f(view, e, window, cx)).ok();
5292 }
5293 }
5294
5295 pub fn handler_for<E: 'static, Callback: Fn(&mut E, &mut Window, &mut Context<E>) + 'static>(
5297 &self,
5298 entity: &Entity<E>,
5299 f: Callback,
5300 ) -> impl Fn(&mut Window, &mut App) + 'static {
5301 let entity = entity.downgrade();
5302 move |window: &mut Window, cx: &mut App| {
5303 entity.update(cx, |entity, cx| f(entity, window, cx)).ok();
5304 }
5305 }
5306
5307 pub fn on_window_should_close(
5310 &self,
5311 cx: &App,
5312 f: impl Fn(&mut Window, &mut App) -> bool + 'static,
5313 ) {
5314 let mut cx = self.to_async(cx);
5315 self.platform_window.on_should_close(Box::new(move || {
5316 cx.update(|window, cx| f(window, cx)).unwrap_or(true)
5317 }))
5318 }
5319
5320 pub fn on_action(
5329 &mut self,
5330 action_type: TypeId,
5331 listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
5332 ) {
5333 self.invalidator.debug_assert_paint();
5334
5335 self.next_frame
5336 .dispatch_tree
5337 .on_action(action_type, Rc::new(listener));
5338 }
5339
5340 pub fn on_action_when(
5349 &mut self,
5350 condition: bool,
5351 action_type: TypeId,
5352 listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
5353 ) {
5354 self.invalidator.debug_assert_paint();
5355
5356 if condition {
5357 self.next_frame
5358 .dispatch_tree
5359 .on_action(action_type, Rc::new(listener));
5360 }
5361 }
5362
5363 pub fn gpu_specs(&self) -> Option<GpuSpecs> {
5366 self.platform_window.gpu_specs()
5367 }
5368
5369 pub fn titlebar_double_click(&self) {
5372 self.platform_window.titlebar_double_click();
5373 }
5374
5375 pub fn window_title(&self) -> String {
5378 self.platform_window.get_title()
5379 }
5380
5381 pub fn tabbed_windows(&self) -> Option<Vec<SystemWindowTab>> {
5384 self.platform_window.tabbed_windows()
5385 }
5386
5387 pub fn tab_bar_visible(&self) -> bool {
5390 self.platform_window.tab_bar_visible()
5391 }
5392
5393 pub fn merge_all_windows(&self) {
5396 self.platform_window.merge_all_windows()
5397 }
5398
5399 pub fn move_tab_to_new_window(&self) {
5402 self.platform_window.move_tab_to_new_window()
5403 }
5404
5405 pub fn toggle_window_tab_overview(&self) {
5408 self.platform_window.toggle_window_tab_overview()
5409 }
5410
5411 pub fn set_tabbing_identifier(&self, tabbing_identifier: Option<String>) {
5414 self.platform_window
5415 .set_tabbing_identifier(tabbing_identifier)
5416 }
5417
5418 pub fn play_system_bell(&self) {
5421 self.platform_window.play_system_bell()
5422 }
5423
5424 pub fn on_a11y_action(
5430 &mut self,
5431 node_id: accesskit::NodeId,
5432 action: accesskit::Action,
5433 listener: impl FnMut(Option<&accesskit::ActionData>, &mut Window, &mut App) + 'static,
5434 ) {
5435 self.a11y
5436 .action_listeners
5437 .entry(node_id)
5438 .or_default()
5439 .push((action, Box::new(listener)));
5440 }
5441
5442 #[cfg(not(target_family = "wasm"))]
5443 pub(crate) fn handle_a11y_action(&mut self, request: accesskit::ActionRequest, cx: &mut App) {
5444 if let Some(mut listeners) = self.a11y.action_listeners.remove(&request.target_node) {
5447 let extra_data = request.data.as_ref();
5448 let mut matched = false;
5449 for (action, listener) in &mut listeners {
5450 if *action == request.action {
5451 listener(extra_data, self, cx);
5452 matched = true;
5453 }
5454 }
5455 self.a11y
5456 .action_listeners
5457 .insert(request.target_node, listeners);
5458 if matched {
5459 return;
5460 }
5461 }
5462
5463 match request.action {
5465 accesskit::Action::Click => {
5466 if let Some(bounds) = self.a11y.node_bounds.get(&request.target_node).copied() {
5467 let center = bounds.center();
5468 let mouse_down = PlatformInput::MouseDown(crate::MouseDownEvent {
5469 button: MouseButton::Left,
5470 position: center,
5471 modifiers: Modifiers::default(),
5472 click_count: 1,
5473 first_mouse: false,
5474 });
5475 let mouse_up = PlatformInput::MouseUp(MouseUpEvent {
5476 button: MouseButton::Left,
5477 position: center,
5478 modifiers: Modifiers::default(),
5479 click_count: 1,
5480 });
5481 self.dispatch_event(mouse_down, cx);
5482 self.dispatch_event(mouse_up, cx);
5483 }
5484 }
5485 accesskit::Action::Focus => {
5486 if let Some(focus_id) = self.a11y.focus_ids.get(&request.target_node).copied()
5487 && let Some(handle) = FocusHandle::for_id(focus_id, &cx.focus_handles)
5488 {
5489 self.focus(&handle, cx);
5490 }
5491 }
5492 accesskit::Action::Blur => {
5493 self.blur();
5494 }
5495 _ => {
5496 log::debug!(
5497 "Unhandled a11y action: {:?} on {:?}",
5498 request.action,
5499 request.target_node
5500 );
5501 }
5502 }
5503 }
5504
5505 #[cfg(any(feature = "inspector", debug_assertions))]
5507 pub fn toggle_inspector(&mut self, cx: &mut App) {
5508 self.inspector = match self.inspector {
5509 None => Some(cx.new(|_| Inspector::new())),
5510 Some(_) => None,
5511 };
5512 self.refresh();
5513 }
5514
5515 pub fn is_inspector_picking(&self, _cx: &App) -> bool {
5517 #[cfg(any(feature = "inspector", debug_assertions))]
5518 {
5519 if let Some(inspector) = &self.inspector {
5520 return inspector.read(_cx).is_picking();
5521 }
5522 }
5523 false
5524 }
5525
5526 #[cfg(any(feature = "inspector", debug_assertions))]
5528 pub fn with_inspector_state<T: 'static, R>(
5529 &mut self,
5530 _inspector_id: Option<&crate::InspectorElementId>,
5531 cx: &mut App,
5532 f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
5533 ) -> R {
5534 if let Some(inspector_id) = _inspector_id
5535 && let Some(inspector) = &self.inspector
5536 {
5537 let inspector = inspector.clone();
5538 let active_element_id = inspector.read(cx).active_element_id();
5539 if Some(inspector_id) == active_element_id {
5540 return inspector.update(cx, |inspector, _cx| {
5541 inspector.with_active_element_state(self, f)
5542 });
5543 }
5544 }
5545 f(&mut None, self)
5546 }
5547
5548 #[cfg(any(feature = "inspector", debug_assertions))]
5549 pub(crate) fn build_inspector_element_id(
5550 &mut self,
5551 path: crate::InspectorElementPath,
5552 ) -> crate::InspectorElementId {
5553 self.invalidator.debug_assert_paint_or_prepaint();
5554 let path = Rc::new(path);
5555 let next_instance_id = self
5556 .next_frame
5557 .next_inspector_instance_ids
5558 .entry(path.clone())
5559 .or_insert(0);
5560 let instance_id = *next_instance_id;
5561 *next_instance_id += 1;
5562 crate::InspectorElementId { path, instance_id }
5563 }
5564
5565 #[cfg(any(feature = "inspector", debug_assertions))]
5566 fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option<AnyElement> {
5567 if let Some(inspector) = self.inspector.take() {
5568 let mut inspector_element = AnyView::from(inspector.clone()).into_any_element();
5569 inspector_element.prepaint_as_root(
5570 point(self.viewport_size.width - inspector_width, px(0.0)),
5571 size(inspector_width, self.viewport_size.height).into(),
5572 self,
5573 cx,
5574 );
5575 self.inspector = Some(inspector);
5576 Some(inspector_element)
5577 } else {
5578 None
5579 }
5580 }
5581
5582 #[cfg(any(feature = "inspector", debug_assertions))]
5583 fn paint_inspector(&mut self, mut inspector_element: Option<AnyElement>, cx: &mut App) {
5584 if let Some(mut inspector_element) = inspector_element {
5585 inspector_element.paint(self, cx);
5586 };
5587 }
5588
5589 #[cfg(any(feature = "inspector", debug_assertions))]
5592 pub fn insert_inspector_hitbox(
5593 &mut self,
5594 hitbox_id: HitboxId,
5595 inspector_id: Option<&crate::InspectorElementId>,
5596 cx: &App,
5597 ) {
5598 self.invalidator.debug_assert_paint_or_prepaint();
5599 if !self.is_inspector_picking(cx) {
5600 return;
5601 }
5602 if let Some(inspector_id) = inspector_id {
5603 self.next_frame
5604 .inspector_hitboxes
5605 .insert(hitbox_id, inspector_id.clone());
5606 }
5607 }
5608
5609 #[cfg(any(feature = "inspector", debug_assertions))]
5610 fn paint_inspector_hitbox(&mut self, cx: &App) {
5611 if let Some(inspector) = self.inspector.as_ref() {
5612 let inspector = inspector.read(cx);
5613 if let Some((hitbox_id, _)) = self.hovered_inspector_hitbox(inspector, &self.next_frame)
5614 && let Some(hitbox) = self
5615 .next_frame
5616 .hitboxes
5617 .iter()
5618 .find(|hitbox| hitbox.id == hitbox_id)
5619 {
5620 self.paint_quad(crate::fill(hitbox.bounds, crate::rgba(0x61afef4d)));
5621 }
5622 }
5623 }
5624
5625 #[cfg(any(feature = "inspector", debug_assertions))]
5626 fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
5627 let Some(inspector) = self.inspector.clone() else {
5628 return;
5629 };
5630 if event.downcast_ref::<MouseMoveEvent>().is_some() {
5631 inspector.update(cx, |inspector, _cx| {
5632 if let Some((_, inspector_id)) =
5633 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
5634 {
5635 inspector.hover(inspector_id, self);
5636 }
5637 });
5638 } else if event.downcast_ref::<crate::MouseDownEvent>().is_some() {
5639 inspector.update(cx, |inspector, _cx| {
5640 if let Some((_, inspector_id)) =
5641 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
5642 {
5643 inspector.select(inspector_id, self);
5644 }
5645 });
5646 } else if let Some(event) = event.downcast_ref::<crate::ScrollWheelEvent>() {
5647 const SCROLL_LINES: f32 = 3.0;
5649 const SCROLL_PIXELS_PER_LAYER: f32 = 36.0;
5650 let delta_y = event
5651 .delta
5652 .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES))
5653 .y;
5654 if let Some(inspector) = self.inspector.clone() {
5655 inspector.update(cx, |inspector, _cx| {
5656 if let Some(depth) = inspector.pick_depth.as_mut() {
5657 *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER;
5658 let max_depth = self.mouse_hit_test.ids.len() as f32 - 0.5;
5659 if *depth < 0.0 {
5660 *depth = 0.0;
5661 } else if *depth > max_depth {
5662 *depth = max_depth;
5663 }
5664 if let Some((_, inspector_id)) =
5665 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
5666 {
5667 inspector.set_active_element_id(inspector_id, self);
5668 }
5669 }
5670 });
5671 }
5672 }
5673 }
5674
5675 #[cfg(any(feature = "inspector", debug_assertions))]
5676 fn hovered_inspector_hitbox(
5677 &self,
5678 inspector: &Inspector,
5679 frame: &Frame,
5680 ) -> Option<(HitboxId, crate::InspectorElementId)> {
5681 if let Some(pick_depth) = inspector.pick_depth {
5682 let depth = (pick_depth as i64).try_into().unwrap_or(0);
5683 let max_skipped = self.mouse_hit_test.ids.len().saturating_sub(1);
5684 let skip_count = (depth as usize).min(max_skipped);
5685 for hitbox_id in self.mouse_hit_test.ids.iter().skip(skip_count) {
5686 if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) {
5687 return Some((*hitbox_id, inspector_id.clone()));
5688 }
5689 }
5690 }
5691 None
5692 }
5693
5694 #[cfg(any(test, feature = "test-support"))]
5697 pub fn set_modifiers(&mut self, modifiers: Modifiers) {
5698 self.modifiers = modifiers;
5699 }
5700
5701 #[cfg(any(test, feature = "test-support"))]
5705 pub fn simulate_mouse_move(&mut self, position: Point<Pixels>, cx: &mut App) {
5706 let event = PlatformInput::MouseMove(MouseMoveEvent {
5707 position,
5708 modifiers: self.modifiers,
5709 pressed_button: None,
5710 });
5711 let _ = self.dispatch_event(event, cx);
5712 }
5713}
5714
5715slotmap::new_key_type! {
5717 pub struct WindowId;
5719}
5720
5721impl WindowId {
5722 pub fn as_u64(&self) -> u64 {
5724 self.0.as_ffi()
5725 }
5726}
5727
5728impl From<u64> for WindowId {
5729 fn from(value: u64) -> Self {
5730 WindowId(slotmap::KeyData::from_ffi(value))
5731 }
5732}
5733
5734#[derive(Deref, DerefMut)]
5737pub struct WindowHandle<V> {
5738 #[deref]
5739 #[deref_mut]
5740 pub(crate) any_handle: AnyWindowHandle,
5741 state_type: PhantomData<fn(V) -> V>,
5742}
5743
5744impl<V> Debug for WindowHandle<V> {
5745 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5746 f.debug_struct("WindowHandle")
5747 .field("any_handle", &self.any_handle.id.as_u64())
5748 .finish()
5749 }
5750}
5751
5752impl<V: 'static + Render> WindowHandle<V> {
5753 pub fn new(id: WindowId) -> Self {
5756 WindowHandle {
5757 any_handle: AnyWindowHandle {
5758 id,
5759 state_type: TypeId::of::<V>(),
5760 },
5761 state_type: PhantomData,
5762 }
5763 }
5764
5765 #[cfg(any(test, feature = "test-support"))]
5769 pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>
5770 where
5771 C: AppContext,
5772 {
5773 cx.update_window(self.any_handle, |root_view, _, _| {
5774 root_view
5775 .downcast::<V>()
5776 .map_err(|_| anyhow!("the type of the window's root view has changed"))
5777 })?
5778 }
5779
5780 pub fn update<C, R>(
5784 &self,
5785 cx: &mut C,
5786 update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
5787 ) -> Result<R>
5788 where
5789 C: AppContext,
5790 {
5791 cx.update_window(self.any_handle, |root_view, window, cx| {
5792 let view = root_view
5793 .downcast::<V>()
5794 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
5795
5796 Ok(view.update(cx, |view, cx| update(view, window, cx)))
5797 })?
5798 }
5799
5800 pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {
5804 let x = cx
5805 .windows
5806 .get(self.id)
5807 .and_then(|window| {
5808 window
5809 .as_deref()
5810 .and_then(|window| window.root.clone())
5811 .map(|root_view| root_view.downcast::<V>())
5812 })
5813 .context("window not found")?
5814 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
5815
5816 Ok(x.read(cx))
5817 }
5818
5819 pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>
5823 where
5824 C: AppContext,
5825 {
5826 cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
5827 }
5828
5829 pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>
5833 where
5834 C: AppContext,
5835 {
5836 cx.read_window(self, |root_view, _cx| root_view)
5837 }
5838
5839 pub fn is_active(&self, cx: &mut App) -> Option<bool> {
5844 cx.update_window(self.any_handle, |_, window, _| window.is_window_active())
5845 .ok()
5846 }
5847}
5848
5849impl<V> Copy for WindowHandle<V> {}
5850
5851impl<V> Clone for WindowHandle<V> {
5852 fn clone(&self) -> Self {
5853 *self
5854 }
5855}
5856
5857impl<V> PartialEq for WindowHandle<V> {
5858 fn eq(&self, other: &Self) -> bool {
5859 self.any_handle == other.any_handle
5860 }
5861}
5862
5863impl<V> Eq for WindowHandle<V> {}
5864
5865impl<V> Hash for WindowHandle<V> {
5866 fn hash<H: Hasher>(&self, state: &mut H) {
5867 self.any_handle.hash(state);
5868 }
5869}
5870
5871impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
5872 fn from(val: WindowHandle<V>) -> Self {
5873 val.any_handle
5874 }
5875}
5876
5877#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
5879pub struct AnyWindowHandle {
5880 pub(crate) id: WindowId,
5881 state_type: TypeId,
5882}
5883
5884impl AnyWindowHandle {
5885 pub fn window_id(&self) -> WindowId {
5887 self.id
5888 }
5889
5890 pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
5893 if TypeId::of::<T>() == self.state_type {
5894 Some(WindowHandle {
5895 any_handle: *self,
5896 state_type: PhantomData,
5897 })
5898 } else {
5899 None
5900 }
5901 }
5902
5903 pub fn update<C, R>(
5907 self,
5908 cx: &mut C,
5909 update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
5910 ) -> Result<R>
5911 where
5912 C: AppContext,
5913 {
5914 cx.update_window(self, update)
5915 }
5916
5917 pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>
5921 where
5922 C: AppContext,
5923 T: 'static,
5924 {
5925 let view = self
5926 .downcast::<T>()
5927 .context("the type of the window's root view has changed")?;
5928
5929 cx.read_window(&view, read)
5930 }
5931}
5932
5933impl HasWindowHandle for Window {
5934 fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {
5935 self.platform_window.window_handle()
5936 }
5937}
5938
5939impl HasDisplayHandle for Window {
5940 fn display_handle(
5941 &self,
5942 ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, HandleError> {
5943 self.platform_window.display_handle()
5944 }
5945}
5946
5947#[derive(Clone, Debug, Eq, PartialEq, Hash)]
5952pub enum ElementId {
5953 View(EntityId),
5955 Integer(u64),
5957 Name(SharedString),
5959 Uuid(Uuid),
5961 FocusHandle(FocusId),
5963 NamedInteger(SharedString, u64),
5965 Path(Arc<std::path::Path>),
5967 CodeLocation(core::panic::Location<'static>),
5969 NamedChild(Arc<ElementId>, SharedString),
5971 OpaqueId([u8; 20]),
5973}
5974
5975impl ElementId {
5976 pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {
5978 Self::NamedInteger(name.into(), integer as u64)
5979 }
5980}
5981
5982impl Display for ElementId {
5983 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5984 match self {
5985 ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
5986 ElementId::Integer(ix) => write!(f, "{}", ix)?,
5987 ElementId::Name(name) => write!(f, "{}", name)?,
5988 ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
5989 ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
5990 ElementId::Uuid(uuid) => write!(f, "{}", uuid)?,
5991 ElementId::Path(path) => write!(f, "{}", path.display())?,
5992 ElementId::CodeLocation(location) => write!(f, "{}", location)?,
5993 ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?,
5994 ElementId::OpaqueId(opaque_id) => write!(f, "{:x?}", opaque_id)?,
5995 }
5996
5997 Ok(())
5998 }
5999}
6000
6001impl TryInto<SharedString> for ElementId {
6002 type Error = anyhow::Error;
6003
6004 fn try_into(self) -> anyhow::Result<SharedString> {
6005 if let ElementId::Name(name) = self {
6006 Ok(name)
6007 } else {
6008 anyhow::bail!("element id is not string")
6009 }
6010 }
6011}
6012
6013impl From<usize> for ElementId {
6014 fn from(id: usize) -> Self {
6015 ElementId::Integer(id as u64)
6016 }
6017}
6018
6019impl From<i32> for ElementId {
6020 fn from(id: i32) -> Self {
6021 Self::Integer(id as u64)
6022 }
6023}
6024
6025impl From<SharedString> for ElementId {
6026 fn from(name: SharedString) -> Self {
6027 ElementId::Name(name)
6028 }
6029}
6030
6031impl From<String> for ElementId {
6032 fn from(name: String) -> Self {
6033 ElementId::Name(name.into())
6034 }
6035}
6036
6037impl From<Arc<str>> for ElementId {
6038 fn from(name: Arc<str>) -> Self {
6039 ElementId::Name(name.into())
6040 }
6041}
6042
6043impl From<Arc<std::path::Path>> for ElementId {
6044 fn from(path: Arc<std::path::Path>) -> Self {
6045 ElementId::Path(path)
6046 }
6047}
6048
6049impl From<&'static str> for ElementId {
6050 fn from(name: &'static str) -> Self {
6051 ElementId::Name(SharedString::new_static(name))
6052 }
6053}
6054
6055impl<'a> From<&'a FocusHandle> for ElementId {
6056 fn from(handle: &'a FocusHandle) -> Self {
6057 ElementId::FocusHandle(handle.id)
6058 }
6059}
6060
6061impl From<(&'static str, EntityId)> for ElementId {
6062 fn from((name, id): (&'static str, EntityId)) -> Self {
6063 ElementId::NamedInteger(SharedString::new_static(name), id.as_u64())
6064 }
6065}
6066
6067impl From<(&'static str, usize)> for ElementId {
6068 fn from((name, id): (&'static str, usize)) -> Self {
6069 ElementId::NamedInteger(SharedString::new_static(name), id as u64)
6070 }
6071}
6072
6073impl From<(SharedString, usize)> for ElementId {
6074 fn from((name, id): (SharedString, usize)) -> Self {
6075 ElementId::NamedInteger(name, id as u64)
6076 }
6077}
6078
6079impl From<(&'static str, u64)> for ElementId {
6080 fn from((name, id): (&'static str, u64)) -> Self {
6081 ElementId::NamedInteger(SharedString::new_static(name), id)
6082 }
6083}
6084
6085impl From<Uuid> for ElementId {
6086 fn from(value: Uuid) -> Self {
6087 Self::Uuid(value)
6088 }
6089}
6090
6091impl From<(&'static str, u32)> for ElementId {
6092 fn from((name, id): (&'static str, u32)) -> Self {
6093 ElementId::NamedInteger(SharedString::new_static(name), u64::from(id))
6094 }
6095}
6096
6097impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
6098 fn from((id, name): (ElementId, T)) -> Self {
6099 ElementId::NamedChild(Arc::new(id), name.into())
6100 }
6101}
6102
6103impl From<&'static core::panic::Location<'static>> for ElementId {
6104 fn from(location: &'static core::panic::Location<'static>) -> Self {
6105 ElementId::CodeLocation(*location)
6106 }
6107}
6108
6109impl From<[u8; 20]> for ElementId {
6110 fn from(opaque_id: [u8; 20]) -> Self {
6111 ElementId::OpaqueId(opaque_id)
6112 }
6113}
6114
6115#[derive(Clone)]
6118pub struct PaintQuad {
6119 pub bounds: Bounds<Pixels>,
6121 pub corner_radii: Corners<Pixels>,
6123 pub background: Background,
6125 pub border_widths: Edges<Pixels>,
6127 pub border_color: Hsla,
6129 pub border_style: BorderStyle,
6131}
6132
6133impl PaintQuad {
6134 pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
6136 PaintQuad {
6137 corner_radii: corner_radii.into(),
6138 ..self
6139 }
6140 }
6141
6142 pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
6144 PaintQuad {
6145 border_widths: border_widths.into(),
6146 ..self
6147 }
6148 }
6149
6150 pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
6152 PaintQuad {
6153 border_color: border_color.into(),
6154 ..self
6155 }
6156 }
6157
6158 pub fn background(self, background: impl Into<Background>) -> Self {
6160 PaintQuad {
6161 background: background.into(),
6162 ..self
6163 }
6164 }
6165}
6166
6167pub fn quad(
6169 bounds: Bounds<Pixels>,
6170 corner_radii: impl Into<Corners<Pixels>>,
6171 background: impl Into<Background>,
6172 border_widths: impl Into<Edges<Pixels>>,
6173 border_color: impl Into<Hsla>,
6174 border_style: BorderStyle,
6175) -> PaintQuad {
6176 PaintQuad {
6177 bounds,
6178 corner_radii: corner_radii.into(),
6179 background: background.into(),
6180 border_widths: border_widths.into(),
6181 border_color: border_color.into(),
6182 border_style,
6183 }
6184}
6185
6186pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
6188 PaintQuad {
6189 bounds: bounds.into(),
6190 corner_radii: (0.).into(),
6191 background: background.into(),
6192 border_widths: (0.).into(),
6193 border_color: transparent_black(),
6194 border_style: BorderStyle::default(),
6195 }
6196}
6197
6198pub fn outline(
6200 bounds: impl Into<Bounds<Pixels>>,
6201 border_color: impl Into<Hsla>,
6202 border_style: BorderStyle,
6203) -> PaintQuad {
6204 PaintQuad {
6205 bounds: bounds.into(),
6206 corner_radii: (0.).into(),
6207 background: transparent_black().into(),
6208 border_widths: (1.).into(),
6209 border_color: border_color.into(),
6210 border_style,
6211 }
6212}