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, BlendMode, BorderStyle, Bounds, BoxShadow,
6 Capslock, Context, Corners, CursorStyle, Decorations, DevicePixels, DispatchActionListener,
7 DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter,
8 FileDropEvent, FontId, Global, GlobalElementId, GlyphId, GpuSpecs, Hsla, InputHandler, IsZero,
9 KeyBinding, KeyContext, KeyDownEvent, KeyEvent, Keystroke, KeystrokeEvent, LayoutId,
10 LineLayoutIndex, Modifiers, ModifiersChangedEvent, MonochromeSprite, MouseButton, MouseEvent,
11 MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
12 PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, ProgressBarState, PromptButton,
13 PromptLevel, Quad,
14 Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge,
15 SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y, ScaledPixels, Scene, Shadow,
16 SharedString, Size, StrikethroughStyle, Style, SubscriberSet, Subscription, SystemWindowTab,
17 SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement,
18 TransformationMatrix, Underline, UnderlineStyle, WindowAppearance, WindowBackgroundAppearance,
19 WindowBounds, WindowControls, WindowDecorations, WindowOptions, WindowParams, WindowState,
20 WindowTextSystem,
21 point, prelude::*, px, rems, size, transparent_black,
22};
23use anyhow::{Context as _, Result, anyhow};
24use collections::{FxHashMap, FxHashSet};
25#[cfg(target_os = "macos")]
26use core_video::pixel_buffer::CVPixelBuffer;
27use derive_more::{Deref, DerefMut};
28use futures::FutureExt;
29use futures::channel::oneshot;
30use itertools::FoldWhile::{Continue, Done};
31use itertools::Itertools;
32use parking_lot::RwLock;
33use raw_window_handle::{HandleError, HasDisplayHandle, HasWindowHandle};
34use refineable::Refineable;
35use slotmap::SlotMap;
36use smallvec::SmallVec;
37use std::{
38 any::{Any, TypeId},
39 borrow::Cow,
40 cell::{Cell, RefCell},
41 cmp,
42 fmt::{Debug, Display},
43 hash::{Hash, Hasher},
44 marker::PhantomData,
45 mem,
46 ops::{DerefMut, Range},
47 rc::Rc,
48 sync::{
49 Arc, Weak,
50 atomic::{AtomicUsize, Ordering::SeqCst},
51 },
52 time::{Duration, Instant},
53};
54use util::post_inc;
55use util::{ResultExt, measure};
56use uuid::Uuid;
57
58mod prompts;
59
60use crate::util::atomic_incr_if_not_zero;
61pub use prompts::*;
62
63pub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1536.), px(864.));
64
65#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
67pub enum DispatchPhase {
68 #[default]
73 Bubble,
74 Capture,
80}
81
82impl DispatchPhase {
83 #[inline]
85 pub fn bubble(self) -> bool {
86 self == DispatchPhase::Bubble
87 }
88
89 #[inline]
91 pub fn capture(self) -> bool {
92 self == DispatchPhase::Capture
93 }
94}
95
96struct WindowInvalidatorInner {
97 pub dirty: bool,
98 pub draw_phase: DrawPhase,
99 pub dirty_views: FxHashSet<EntityId>,
100}
101
102#[derive(Clone)]
103pub(crate) struct WindowInvalidator {
104 inner: Rc<RefCell<WindowInvalidatorInner>>,
105}
106
107impl WindowInvalidator {
108 pub fn new() -> Self {
109 WindowInvalidator {
110 inner: Rc::new(RefCell::new(WindowInvalidatorInner {
111 dirty: true,
112 draw_phase: DrawPhase::None,
113 dirty_views: FxHashSet::default(),
114 })),
115 }
116 }
117
118 pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {
119 let mut inner = self.inner.borrow_mut();
120 inner.dirty_views.insert(entity);
121 if inner.draw_phase == DrawPhase::None {
122 inner.dirty = true;
123 cx.push_effect(Effect::Notify { emitter: entity });
124 true
125 } else {
126 false
127 }
128 }
129
130 pub fn is_dirty(&self) -> bool {
131 self.inner.borrow().dirty
132 }
133
134 pub fn set_dirty(&self, dirty: bool) {
135 self.inner.borrow_mut().dirty = dirty
136 }
137
138 pub fn set_phase(&self, phase: DrawPhase) {
139 self.inner.borrow_mut().draw_phase = phase
140 }
141
142 pub fn take_views(&self) -> FxHashSet<EntityId> {
143 mem::take(&mut self.inner.borrow_mut().dirty_views)
144 }
145
146 pub fn replace_views(&self, views: FxHashSet<EntityId>) {
147 self.inner.borrow_mut().dirty_views = views;
148 }
149
150 pub fn not_drawing(&self) -> bool {
151 self.inner.borrow().draw_phase == DrawPhase::None
152 }
153
154 #[track_caller]
155 pub fn debug_assert_paint(&self) {
156 debug_assert!(
157 matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),
158 "this method can only be called during paint"
159 );
160 }
161
162 #[track_caller]
163 pub fn debug_assert_prepaint(&self) {
164 debug_assert!(
165 matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),
166 "this method can only be called during request_layout, or prepaint"
167 );
168 }
169
170 #[track_caller]
171 pub fn debug_assert_paint_or_prepaint(&self) {
172 debug_assert!(
173 matches!(
174 self.inner.borrow().draw_phase,
175 DrawPhase::Paint | DrawPhase::Prepaint
176 ),
177 "this method can only be called during request_layout, prepaint, or paint"
178 );
179 }
180}
181
182type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;
183
184pub(crate) type AnyWindowFocusListener =
185 Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;
186
187pub(crate) struct WindowFocusEvent {
188 pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,
189 pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,
190}
191
192impl WindowFocusEvent {
193 pub fn is_focus_in(&self, focus_id: FocusId) -> bool {
194 !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)
195 }
196
197 pub fn is_focus_out(&self, focus_id: FocusId) -> bool {
198 self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)
199 }
200}
201
202pub struct FocusOutEvent {
204 pub blurred: WeakFocusHandle,
206}
207
208slotmap::new_key_type! {
209 pub struct FocusId;
211}
212
213thread_local! {
214 pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));
215}
216
217#[must_use]
219pub struct ArenaClearNeeded;
220
221impl ArenaClearNeeded {
222 pub fn clear(self) {
224 ELEMENT_ARENA.with_borrow_mut(|element_arena| {
225 element_arena.clear();
226 });
227 }
228}
229
230pub(crate) type FocusMap = RwLock<SlotMap<FocusId, FocusRef>>;
231pub(crate) struct FocusRef {
232 pub(crate) ref_count: AtomicUsize,
233 pub(crate) tab_index: isize,
234 pub(crate) tab_stop: bool,
235}
236
237impl FocusId {
238 pub fn is_focused(&self, window: &Window) -> bool {
240 window.focus == Some(*self)
241 }
242
243 pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
246 window
247 .focused(cx)
248 .is_some_and(|focused| self.contains(focused.id, window))
249 }
250
251 pub fn within_focused(&self, window: &Window, cx: &App) -> bool {
254 let focused = window.focused(cx);
255 focused.is_some_and(|focused| focused.id.contains(*self, window))
256 }
257
258 pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {
260 window
261 .rendered_frame
262 .dispatch_tree
263 .focus_contains(*self, other)
264 }
265}
266
267pub struct FocusHandle {
269 pub(crate) id: FocusId,
270 handles: Arc<FocusMap>,
271 pub tab_index: isize,
273 pub tab_stop: bool,
275}
276
277impl std::fmt::Debug for FocusHandle {
278 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
279 f.write_fmt(format_args!("FocusHandle({:?})", self.id))
280 }
281}
282
283impl FocusHandle {
284 pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {
285 let id = handles.write().insert(FocusRef {
286 ref_count: AtomicUsize::new(1),
287 tab_index: 0,
288 tab_stop: false,
289 });
290
291 Self {
292 id,
293 tab_index: 0,
294 tab_stop: false,
295 handles: handles.clone(),
296 }
297 }
298
299 pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {
300 let lock = handles.read();
301 let focus = lock.get(id)?;
302 if atomic_incr_if_not_zero(&focus.ref_count) == 0 {
303 return None;
304 }
305 Some(Self {
306 id,
307 tab_index: focus.tab_index,
308 tab_stop: focus.tab_stop,
309 handles: handles.clone(),
310 })
311 }
312
313 pub fn tab_index(mut self, index: isize) -> Self {
315 self.tab_index = index;
316 if let Some(focus) = self.handles.write().get_mut(self.id) {
317 focus.tab_index = index;
318 }
319 self
320 }
321
322 pub fn tab_stop(mut self, tab_stop: bool) -> Self {
326 self.tab_stop = tab_stop;
327 if let Some(focus) = self.handles.write().get_mut(self.id) {
328 focus.tab_stop = tab_stop;
329 }
330 self
331 }
332
333 pub fn downgrade(&self) -> WeakFocusHandle {
335 WeakFocusHandle {
336 id: self.id,
337 handles: Arc::downgrade(&self.handles),
338 }
339 }
340
341 pub fn focus(&self, window: &mut Window) {
343 window.focus(self)
344 }
345
346 pub fn is_focused(&self, window: &Window) -> bool {
348 self.id.is_focused(window)
349 }
350
351 pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
354 self.id.contains_focused(window, cx)
355 }
356
357 pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {
360 self.id.within_focused(window, cx)
361 }
362
363 pub fn contains(&self, other: &Self, window: &Window) -> bool {
365 self.id.contains(other.id, window)
366 }
367
368 pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {
370 if let Some(node_id) = window
371 .rendered_frame
372 .dispatch_tree
373 .focusable_node_id(self.id)
374 {
375 window.dispatch_action_on_node(node_id, action, cx)
376 }
377 }
378}
379
380impl Clone for FocusHandle {
381 fn clone(&self) -> Self {
382 Self::for_id(self.id, &self.handles).unwrap()
383 }
384}
385
386impl PartialEq for FocusHandle {
387 fn eq(&self, other: &Self) -> bool {
388 self.id == other.id
389 }
390}
391
392impl Eq for FocusHandle {}
393
394impl Drop for FocusHandle {
395 fn drop(&mut self) {
396 self.handles
397 .read()
398 .get(self.id)
399 .unwrap()
400 .ref_count
401 .fetch_sub(1, SeqCst);
402 }
403}
404
405#[derive(Clone, Debug)]
407pub struct WeakFocusHandle {
408 pub(crate) id: FocusId,
409 pub(crate) handles: Weak<FocusMap>,
410}
411
412impl WeakFocusHandle {
413 pub fn upgrade(&self) -> Option<FocusHandle> {
415 let handles = self.handles.upgrade()?;
416 FocusHandle::for_id(self.id, &handles)
417 }
418}
419
420impl PartialEq for WeakFocusHandle {
421 fn eq(&self, other: &WeakFocusHandle) -> bool {
422 self.id == other.id
423 }
424}
425
426impl Eq for WeakFocusHandle {}
427
428impl PartialEq<FocusHandle> for WeakFocusHandle {
429 fn eq(&self, other: &FocusHandle) -> bool {
430 self.id == other.id
431 }
432}
433
434impl PartialEq<WeakFocusHandle> for FocusHandle {
435 fn eq(&self, other: &WeakFocusHandle) -> bool {
436 self.id == other.id
437 }
438}
439
440pub trait Focusable: 'static {
443 fn focus_handle(&self, cx: &App) -> FocusHandle;
445}
446
447impl<V: Focusable> Focusable for Entity<V> {
448 fn focus_handle(&self, cx: &App) -> FocusHandle {
449 self.read(cx).focus_handle(cx)
450 }
451}
452
453pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}
456
457impl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}
458
459pub struct DismissEvent;
461
462type FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;
463
464pub(crate) type AnyMouseListener =
465 Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
466
467#[derive(Clone)]
468pub(crate) struct CursorStyleRequest {
469 pub(crate) hitbox_id: Option<HitboxId>,
470 pub(crate) style: CursorStyle,
471}
472
473#[derive(Default, Eq, PartialEq)]
474pub(crate) struct HitTest {
475 pub(crate) ids: SmallVec<[HitboxId; 8]>,
476 pub(crate) hover_hitbox_count: usize,
477}
478
479#[derive(Clone, Copy, Debug, Eq, PartialEq)]
481pub enum WindowControlArea {
482 Drag,
484 Close,
486 Max,
488 Min,
490}
491
492#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
494pub struct HitboxId(u64);
495
496impl HitboxId {
497 pub fn is_hovered(self, window: &Window) -> bool {
503 let hit_test = &window.mouse_hit_test;
504 for id in hit_test.ids.iter().take(hit_test.hover_hitbox_count) {
505 if self == *id {
506 return true;
507 }
508 }
509 false
510 }
511
512 pub fn should_handle_scroll(self, window: &Window) -> bool {
517 window.mouse_hit_test.ids.contains(&self)
518 }
519
520 fn next(mut self) -> HitboxId {
521 HitboxId(self.0.wrapping_add(1))
522 }
523}
524
525#[derive(Clone, Debug, Deref)]
528pub struct Hitbox {
529 pub id: HitboxId,
531 #[deref]
533 pub bounds: Bounds<Pixels>,
534 pub content_mask: ContentMask<Pixels>,
536 pub behavior: HitboxBehavior,
538}
539
540impl Hitbox {
541 pub fn is_hovered(&self, window: &Window) -> bool {
556 self.id.is_hovered(window)
557 }
558
559 pub fn should_handle_scroll(&self, window: &Window) -> bool {
566 self.id.should_handle_scroll(window)
567 }
568}
569
570#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
572pub enum HitboxBehavior {
573 #[default]
575 Normal,
576
577 BlockMouse,
599
600 BlockMouseExceptScroll,
627}
628
629#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
631pub struct TooltipId(usize);
632
633impl TooltipId {
634 pub fn is_hovered(&self, window: &Window) -> bool {
636 window
637 .tooltip_bounds
638 .as_ref()
639 .is_some_and(|tooltip_bounds| {
640 tooltip_bounds.id == *self
641 && tooltip_bounds.bounds.contains(&window.mouse_position())
642 })
643 }
644}
645
646pub(crate) struct TooltipBounds {
647 id: TooltipId,
648 bounds: Bounds<Pixels>,
649}
650
651#[derive(Clone)]
652pub(crate) struct TooltipRequest {
653 id: TooltipId,
654 tooltip: AnyTooltip,
655}
656
657pub(crate) struct DeferredDraw {
658 current_view: EntityId,
659 priority: usize,
660 parent_node: DispatchNodeId,
661 element_id_stack: SmallVec<[ElementId; 32]>,
662 text_style_stack: SmallVec<[TextStyleRefinement; 4]>,
663 element: Option<AnyElement>,
664 absolute_offset: Point<Pixels>,
665 prepaint_range: Range<PrepaintStateIndex>,
666 paint_range: Range<PaintIndex>,
667}
668
669pub(crate) struct Frame {
670 pub(crate) focus: Option<FocusId>,
671 pub(crate) window_active: bool,
672 pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
673 accessed_element_states: Vec<(GlobalElementId, TypeId)>,
674 pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
675 pub(crate) dispatch_tree: DispatchTree,
676 pub(crate) scene: Scene,
677 pub(crate) hitboxes: Vec<Hitbox>,
678 pub(crate) window_control_hitboxes: Vec<(WindowControlArea, Hitbox)>,
679 pub(crate) deferred_draws: Vec<DeferredDraw>,
680 pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
681 pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,
682 pub(crate) cursor_styles: Vec<CursorStyleRequest>,
683 #[cfg(any(test, feature = "test-support"))]
684 pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
685 #[cfg(any(feature = "inspector", debug_assertions))]
686 pub(crate) next_inspector_instance_ids: FxHashMap<Rc<crate::InspectorElementPath>, usize>,
687 #[cfg(any(feature = "inspector", debug_assertions))]
688 pub(crate) inspector_hitboxes: FxHashMap<HitboxId, crate::InspectorElementId>,
689 pub(crate) tab_stops: TabStopMap,
690}
691
692#[derive(Clone, Default)]
693pub(crate) struct PrepaintStateIndex {
694 hitboxes_index: usize,
695 tooltips_index: usize,
696 deferred_draws_index: usize,
697 dispatch_tree_index: usize,
698 accessed_element_states_index: usize,
699 line_layout_index: LineLayoutIndex,
700}
701
702#[derive(Clone, Default)]
703pub(crate) struct PaintIndex {
704 scene_index: usize,
705 mouse_listeners_index: usize,
706 input_handlers_index: usize,
707 cursor_styles_index: usize,
708 accessed_element_states_index: usize,
709 tab_handle_index: usize,
710 line_layout_index: LineLayoutIndex,
711}
712
713impl Frame {
714 pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
715 Frame {
716 focus: None,
717 window_active: false,
718 element_states: FxHashMap::default(),
719 accessed_element_states: Vec::new(),
720 mouse_listeners: Vec::new(),
721 dispatch_tree,
722 scene: Scene::default(),
723 hitboxes: Vec::new(),
724 window_control_hitboxes: Vec::new(),
725 deferred_draws: Vec::new(),
726 input_handlers: Vec::new(),
727 tooltip_requests: Vec::new(),
728 cursor_styles: Vec::new(),
729
730 #[cfg(any(test, feature = "test-support"))]
731 debug_bounds: FxHashMap::default(),
732
733 #[cfg(any(feature = "inspector", debug_assertions))]
734 next_inspector_instance_ids: FxHashMap::default(),
735
736 #[cfg(any(feature = "inspector", debug_assertions))]
737 inspector_hitboxes: FxHashMap::default(),
738 tab_stops: TabStopMap::default(),
739 }
740 }
741
742 pub(crate) fn clear(&mut self) {
743 self.element_states.clear();
744 self.accessed_element_states.clear();
745 self.mouse_listeners.clear();
746 self.dispatch_tree.clear();
747 self.scene.clear();
748 self.input_handlers.clear();
749 self.tooltip_requests.clear();
750 self.cursor_styles.clear();
751 self.hitboxes.clear();
752 self.window_control_hitboxes.clear();
753 self.deferred_draws.clear();
754 self.tab_stops.clear();
755 self.focus = None;
756
757 #[cfg(any(feature = "inspector", debug_assertions))]
758 {
759 self.next_inspector_instance_ids.clear();
760 self.inspector_hitboxes.clear();
761 }
762 }
763
764 pub(crate) fn cursor_style(&self, window: &Window) -> Option<CursorStyle> {
765 self.cursor_styles
766 .iter()
767 .rev()
768 .fold_while(None, |style, request| match request.hitbox_id {
769 None => Done(Some(request.style)),
770 Some(hitbox_id) => Continue(
771 style.or_else(|| hitbox_id.is_hovered(window).then_some(request.style)),
772 ),
773 })
774 .into_inner()
775 }
776
777 pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
778 let mut set_hover_hitbox_count = false;
779 let mut hit_test = HitTest::default();
780 for hitbox in self.hitboxes.iter().rev() {
781 let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);
782 if bounds.contains(&position) {
783 hit_test.ids.push(hitbox.id);
784 if !set_hover_hitbox_count
785 && hitbox.behavior == HitboxBehavior::BlockMouseExceptScroll
786 {
787 hit_test.hover_hitbox_count = hit_test.ids.len();
788 set_hover_hitbox_count = true;
789 }
790 if hitbox.behavior == HitboxBehavior::BlockMouse {
791 break;
792 }
793 }
794 }
795 if !set_hover_hitbox_count {
796 hit_test.hover_hitbox_count = hit_test.ids.len();
797 }
798 hit_test
799 }
800
801 pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
802 self.focus
803 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
804 .unwrap_or_default()
805 }
806
807 pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
808 for element_state_key in &self.accessed_element_states {
809 if let Some((element_state_key, element_state)) =
810 prev_frame.element_states.remove_entry(element_state_key)
811 {
812 self.element_states.insert(element_state_key, element_state);
813 }
814 }
815
816 self.scene.finish();
817 }
818}
819
820pub struct Window {
822 pub(crate) handle: AnyWindowHandle,
823 pub(crate) invalidator: WindowInvalidator,
824 pub(crate) removed: bool,
825 pub(crate) platform_window: Box<dyn PlatformWindow>,
826 display_id: Option<DisplayId>,
827 sprite_atlas: Arc<dyn PlatformAtlas>,
828 text_system: Arc<WindowTextSystem>,
829 rem_size: Pixels,
830 rem_size_override_stack: SmallVec<[Pixels; 8]>,
835 pub(crate) viewport_size: Size<Pixels>,
836 layout_engine: Option<TaffyLayoutEngine>,
837 pub(crate) root: Option<AnyView>,
838 pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,
839 pub(crate) text_style_stack: SmallVec<[TextStyleRefinement; 4]>,
840 pub(crate) rendered_entity_stack: SmallVec<[EntityId; 16]>,
841 pub(crate) element_offset_stack: SmallVec<[Point<Pixels>; 16]>,
842 pub(crate) element_opacity: f32,
843 pub(crate) content_mask_stack: SmallVec<[ContentMask<Pixels>; 16]>,
844 pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,
845 pub(crate) image_cache_stack: SmallVec<[AnyImageCache; 4]>,
846 pub(crate) rendered_frame: Frame,
847 pub(crate) next_frame: Frame,
848 next_hitbox_id: HitboxId,
849 pub(crate) next_tooltip_id: TooltipId,
850 pub(crate) tooltip_bounds: Option<TooltipBounds>,
851 next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
852 pub(crate) dirty_views: FxHashSet<EntityId>,
853 focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
854 pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,
855 default_prevented: bool,
856 mouse_position: Point<Pixels>,
857 mouse_hit_test: HitTest,
858 modifiers: Modifiers,
859 capslock: Capslock,
860 scale_factor: f32,
861 pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
862 appearance: WindowAppearance,
863 pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,
864 active: Rc<Cell<bool>>,
865 hovered: Rc<Cell<bool>>,
866 pub(crate) needs_present: Rc<Cell<bool>>,
867 pub(crate) last_input_timestamp: Rc<Cell<Instant>>,
868 pub(crate) refreshing: bool,
869 pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,
870 pub(crate) focus: Option<FocusId>,
871 focus_enabled: bool,
872 pending_input: Option<PendingInput>,
873 pending_modifier: ModifierState,
874 pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,
875 prompt: Option<RenderablePromptHandle>,
876 pub(crate) client_inset: Option<Pixels>,
877 #[cfg(any(feature = "inspector", debug_assertions))]
878 inspector: Option<Entity<Inspector>>,
879}
880
881#[derive(Clone, Debug, Default)]
882struct ModifierState {
883 modifiers: Modifiers,
884 saw_keystroke: bool,
885}
886
887#[derive(Clone, Copy, Debug, Eq, PartialEq)]
888pub(crate) enum DrawPhase {
889 None,
890 Prepaint,
891 Paint,
892 Focus,
893}
894
895#[derive(Default, Debug)]
896struct PendingInput {
897 keystrokes: SmallVec<[Keystroke; 1]>,
898 focus: Option<FocusId>,
899 timer: Option<Task<()>>,
900}
901
902pub(crate) struct ElementStateBox {
903 pub(crate) inner: Box<dyn Any>,
904 #[cfg(debug_assertions)]
905 pub(crate) type_name: &'static str,
906}
907
908fn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> Bounds<Pixels> {
909 const DEFAULT_WINDOW_OFFSET: Point<Pixels> = point(px(0.), px(35.));
910
911 cx.active_window()
915 .and_then(|w| w.update(cx, |_, window, _| window.bounds()).ok())
916 .map(|mut bounds| {
917 bounds.origin += DEFAULT_WINDOW_OFFSET;
918 bounds
919 })
920 .unwrap_or_else(|| {
921 let display = display_id
922 .map(|id| cx.find_display(id))
923 .unwrap_or_else(|| cx.primary_display());
924
925 display
926 .map(|display| display.default_bounds())
927 .unwrap_or_else(|| Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE))
928 })
929}
930
931impl Window {
932 pub(crate) fn new(
933 handle: AnyWindowHandle,
934 options: WindowOptions,
935 cx: &mut App,
936 ) -> Result<Self> {
937 let WindowOptions {
938 window_bounds,
939 titlebar,
940 focus,
941 show,
942 kind,
943 is_movable,
944 is_resizable,
945 is_minimizable,
946 display_id,
947 window_background,
948 app_id,
949 window_min_size,
950 window_decorations,
951 #[cfg_attr(not(target_os = "macos"), allow(unused_variables))]
952 tabbing_identifier,
953 mouse_passthrough,
954 } = options;
955
956 let bounds = window_bounds
957 .map(|bounds| bounds.get_bounds())
958 .unwrap_or_else(|| default_bounds(display_id, cx));
959 let mut platform_window = cx.platform.open_window(
960 handle,
961 WindowParams {
962 bounds,
963 titlebar,
964 kind,
965 is_movable,
966 is_resizable,
967 is_minimizable,
968 focus,
969 show,
970 display_id,
971 window_min_size,
972 #[cfg(target_os = "macos")]
973 tabbing_identifier,
974 mouse_passthrough,
975 },
976 )?;
977
978 let tab_bar_visible = platform_window.tab_bar_visible();
979 SystemWindowTabController::init_visible(cx, tab_bar_visible);
980 if let Some(tabs) = platform_window.tabbed_windows() {
981 SystemWindowTabController::add_tab(cx, handle.window_id(), tabs);
982 }
983
984 let display_id = platform_window.display().map(|display| display.id());
985 let sprite_atlas = platform_window.sprite_atlas();
986 let mouse_position = platform_window.mouse_position();
987 let modifiers = platform_window.modifiers();
988 let capslock = platform_window.capslock();
989 let content_size = platform_window.content_size();
990 let scale_factor = platform_window.scale_factor();
991 let appearance = platform_window.appearance();
992 let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
993 let invalidator = WindowInvalidator::new();
994 let active = Rc::new(Cell::new(platform_window.is_active()));
995 let hovered = Rc::new(Cell::new(platform_window.is_hovered()));
996 let needs_present = Rc::new(Cell::new(false));
997 let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
998 let last_input_timestamp = Rc::new(Cell::new(Instant::now()));
999
1000 platform_window
1001 .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));
1002 platform_window.set_background_appearance(window_background);
1003
1004 if let Some(ref window_open_state) = window_bounds {
1005 match window_open_state {
1006 WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),
1007 WindowBounds::Maximized(_) => platform_window.zoom(),
1008 WindowBounds::Windowed(_) => {}
1009 }
1010 }
1011
1012 platform_window.on_close(Box::new({
1013 let window_id = handle.window_id();
1014 let mut cx = cx.to_async();
1015 move || {
1016 let _ = handle.update(&mut cx, |_, window, _| window.remove_window());
1017 let _ = cx.update(|cx| {
1018 SystemWindowTabController::remove_tab(cx, window_id);
1019 });
1020 }
1021 }));
1022 platform_window.on_request_frame(Box::new({
1023 let mut cx = cx.to_async();
1024 let invalidator = invalidator.clone();
1025 let active = active.clone();
1026 let needs_present = needs_present.clone();
1027 let next_frame_callbacks = next_frame_callbacks.clone();
1028 let last_input_timestamp = last_input_timestamp.clone();
1029 move |request_frame_options| {
1030 let next_frame_callbacks = next_frame_callbacks.take();
1031 if !next_frame_callbacks.is_empty() {
1032 handle
1033 .update(&mut cx, |_, window, cx| {
1034 for callback in next_frame_callbacks {
1035 callback(window, cx);
1036 }
1037 })
1038 .log_err();
1039 }
1040
1041 let needs_present = request_frame_options.require_presentation
1044 || needs_present.get()
1045 || (active.get()
1046 && last_input_timestamp.get().elapsed() < Duration::from_secs(1));
1047
1048 if invalidator.is_dirty() || request_frame_options.force_render {
1049 measure("frame duration", || {
1050 handle
1051 .update(&mut cx, |_, window, cx| {
1052 let arena_clear_needed = window.draw(cx);
1053 window.present();
1054 arena_clear_needed.clear();
1056 })
1057 .log_err();
1058 })
1059 } else if needs_present {
1060 handle
1061 .update(&mut cx, |_, window, _| window.present())
1062 .log_err();
1063 }
1064
1065 handle
1066 .update(&mut cx, |_, window, _| {
1067 window.complete_frame();
1068 })
1069 .log_err();
1070 }
1071 }));
1072 platform_window.on_resize(Box::new({
1073 let mut cx = cx.to_async();
1074 move |_, _| {
1075 handle
1076 .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1077 .log_err();
1078 }
1079 }));
1080 platform_window.on_moved(Box::new({
1081 let mut cx = cx.to_async();
1082 move || {
1083 handle
1084 .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1085 .log_err();
1086 }
1087 }));
1088 platform_window.on_appearance_changed(Box::new({
1089 let mut cx = cx.to_async();
1090 move || {
1091 handle
1092 .update(&mut cx, |_, window, cx| window.appearance_changed(cx))
1093 .log_err();
1094 }
1095 }));
1096 platform_window.on_active_status_change(Box::new({
1097 let mut cx = cx.to_async();
1098 move |active| {
1099 handle
1100 .update(&mut cx, |_, window, cx| {
1101 window.active.set(active);
1102 window.modifiers = window.platform_window.modifiers();
1103 window.capslock = window.platform_window.capslock();
1104 window
1105 .activation_observers
1106 .clone()
1107 .retain(&(), |callback| callback(window, cx));
1108
1109 window.bounds_changed(cx);
1110 window.refresh();
1111
1112 SystemWindowTabController::update_last_active(cx, window.handle.id);
1113 })
1114 .log_err();
1115 }
1116 }));
1117 platform_window.on_hover_status_change(Box::new({
1118 let mut cx = cx.to_async();
1119 move |active| {
1120 handle
1121 .update(&mut cx, |_, window, _| {
1122 window.hovered.set(active);
1123 window.refresh();
1124 })
1125 .log_err();
1126 }
1127 }));
1128 platform_window.on_input({
1129 let mut cx = cx.to_async();
1130 Box::new(move |event| {
1131 handle
1132 .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))
1133 .log_err()
1134 .unwrap_or(DispatchEventResult::default())
1135 })
1136 });
1137 platform_window.on_hit_test_window_control({
1138 let mut cx = cx.to_async();
1139 Box::new(move || {
1140 handle
1141 .update(&mut cx, |_, window, _cx| {
1142 for (area, hitbox) in &window.rendered_frame.window_control_hitboxes {
1143 if window.mouse_hit_test.ids.contains(&hitbox.id) {
1144 return Some(*area);
1145 }
1146 }
1147 None
1148 })
1149 .log_err()
1150 .unwrap_or(None)
1151 })
1152 });
1153 platform_window.on_move_tab_to_new_window({
1154 let mut cx = cx.to_async();
1155 Box::new(move || {
1156 handle
1157 .update(&mut cx, |_, _window, cx| {
1158 SystemWindowTabController::move_tab_to_new_window(cx, handle.window_id());
1159 })
1160 .log_err();
1161 })
1162 });
1163 platform_window.on_merge_all_windows({
1164 let mut cx = cx.to_async();
1165 Box::new(move || {
1166 handle
1167 .update(&mut cx, |_, _window, cx| {
1168 SystemWindowTabController::merge_all_windows(cx, handle.window_id());
1169 })
1170 .log_err();
1171 })
1172 });
1173 platform_window.on_select_next_tab({
1174 let mut cx = cx.to_async();
1175 Box::new(move || {
1176 handle
1177 .update(&mut cx, |_, _window, cx| {
1178 SystemWindowTabController::select_next_tab(cx, handle.window_id());
1179 })
1180 .log_err();
1181 })
1182 });
1183 platform_window.on_select_previous_tab({
1184 let mut cx = cx.to_async();
1185 Box::new(move || {
1186 handle
1187 .update(&mut cx, |_, _window, cx| {
1188 SystemWindowTabController::select_previous_tab(cx, handle.window_id())
1189 })
1190 .log_err();
1191 })
1192 });
1193 platform_window.on_toggle_tab_bar({
1194 let mut cx = cx.to_async();
1195 Box::new(move || {
1196 handle
1197 .update(&mut cx, |_, window, cx| {
1198 let tab_bar_visible = window.platform_window.tab_bar_visible();
1199 SystemWindowTabController::set_visible(cx, tab_bar_visible);
1200 })
1201 .log_err();
1202 })
1203 });
1204
1205 if let Some(app_id) = app_id {
1206 platform_window.set_app_id(&app_id);
1207 }
1208
1209 platform_window.map_window().unwrap();
1210
1211 Ok(Window {
1212 handle,
1213 invalidator,
1214 removed: false,
1215 platform_window,
1216 display_id,
1217 sprite_atlas,
1218 text_system,
1219 rem_size: px(16.),
1220 rem_size_override_stack: SmallVec::new(),
1221 viewport_size: content_size,
1222 layout_engine: Some(TaffyLayoutEngine::new()),
1223 root: None,
1224 element_id_stack: SmallVec::default(),
1225 text_style_stack: SmallVec::new(),
1226 rendered_entity_stack: SmallVec::new(),
1227 element_offset_stack: SmallVec::new(),
1228 content_mask_stack: SmallVec::new(),
1229 element_opacity: 1.0,
1230 requested_autoscroll: None,
1231 rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1232 next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1233 next_frame_callbacks,
1234 next_hitbox_id: HitboxId(0),
1235 next_tooltip_id: TooltipId::default(),
1236 tooltip_bounds: None,
1237 dirty_views: FxHashSet::default(),
1238 focus_listeners: SubscriberSet::new(),
1239 focus_lost_listeners: SubscriberSet::new(),
1240 default_prevented: true,
1241 mouse_position,
1242 mouse_hit_test: HitTest::default(),
1243 modifiers,
1244 capslock,
1245 scale_factor,
1246 bounds_observers: SubscriberSet::new(),
1247 appearance,
1248 appearance_observers: SubscriberSet::new(),
1249 active,
1250 hovered,
1251 needs_present,
1252 last_input_timestamp,
1253 refreshing: false,
1254 activation_observers: SubscriberSet::new(),
1255 focus: None,
1256 focus_enabled: true,
1257 pending_input: None,
1258 pending_modifier: ModifierState::default(),
1259 pending_input_observers: SubscriberSet::new(),
1260 prompt: None,
1261 client_inset: None,
1262 image_cache_stack: SmallVec::new(),
1263 #[cfg(any(feature = "inspector", debug_assertions))]
1264 inspector: None,
1265 })
1266 }
1267
1268 pub(crate) fn new_focus_listener(
1269 &self,
1270 value: AnyWindowFocusListener,
1271 ) -> (Subscription, impl FnOnce() + use<>) {
1272 self.focus_listeners.insert((), value)
1273 }
1274}
1275
1276#[derive(Clone, Debug, Default, PartialEq, Eq)]
1277pub(crate) struct DispatchEventResult {
1278 pub propagate: bool,
1279 pub default_prevented: bool,
1280}
1281
1282#[derive(Clone, Debug, Default, PartialEq, Eq)]
1286#[repr(C)]
1287pub struct ContentMask<P: Clone + Debug + Default + PartialEq> {
1288 pub bounds: Bounds<P>,
1290}
1291
1292impl ContentMask<Pixels> {
1293 pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
1295 ContentMask {
1296 bounds: self.bounds.scale(factor),
1297 }
1298 }
1299
1300 pub fn intersect(&self, other: &Self) -> Self {
1302 let bounds = self.bounds.intersect(&other.bounds);
1303 ContentMask { bounds }
1304 }
1305}
1306
1307impl Window {
1308 fn mark_view_dirty(&mut self, view_id: EntityId) {
1309 for view_id in self
1312 .rendered_frame
1313 .dispatch_tree
1314 .view_path(view_id)
1315 .into_iter()
1316 .rev()
1317 {
1318 if !self.dirty_views.insert(view_id) {
1319 break;
1320 }
1321 }
1322 }
1323
1324
1325 pub fn observe_window_appearance(
1327 &self,
1328 mut callback: impl FnMut(&mut Window, &mut App) + 'static,
1329 ) -> Subscription {
1330 let (subscription, activate) = self.appearance_observers.insert(
1331 (),
1332 Box::new(move |window, cx| {
1333 callback(window, cx);
1334 true
1335 }),
1336 );
1337 activate();
1338 subscription
1339 }
1340
1341 pub fn replace_root<E>(
1343 &mut self,
1344 cx: &mut App,
1345 build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,
1346 ) -> Entity<E>
1347 where
1348 E: 'static + Render,
1349 {
1350 let view = cx.new(|cx| build_view(self, cx));
1351 self.root = Some(view.clone().into());
1352 self.refresh();
1353 view
1354 }
1355
1356 pub fn root<E>(&self) -> Option<Option<Entity<E>>>
1358 where
1359 E: 'static + Render,
1360 {
1361 self.root
1362 .as_ref()
1363 .map(|view| view.clone().downcast::<E>().ok())
1364 }
1365
1366 pub fn window_handle(&self) -> AnyWindowHandle {
1368 self.handle
1369 }
1370
1371 pub fn refresh(&mut self) {
1373 if self.invalidator.not_drawing() {
1374 self.refreshing = true;
1375 self.invalidator.set_dirty(true);
1376 }
1377 }
1378
1379 pub fn remove_window(&mut self) {
1381 self.removed = true;
1382 }
1383
1384 pub fn focused(&self, cx: &App) -> Option<FocusHandle> {
1386 self.focus
1387 .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))
1388 }
1389
1390 pub fn focus(&mut self, handle: &FocusHandle) {
1392 if !self.focus_enabled || self.focus == Some(handle.id) {
1393 return;
1394 }
1395
1396 self.focus = Some(handle.id);
1397 self.clear_pending_keystrokes();
1398 self.refresh();
1399 }
1400
1401 pub fn blur(&mut self) {
1403 if !self.focus_enabled {
1404 return;
1405 }
1406
1407 self.focus = None;
1408 self.refresh();
1409 }
1410
1411 pub fn disable_focus(&mut self) {
1413 self.blur();
1414 self.focus_enabled = false;
1415 }
1416
1417 pub fn focus_next(&mut self) {
1419 if !self.focus_enabled {
1420 return;
1421 }
1422
1423 if let Some(handle) = self.rendered_frame.tab_stops.next(self.focus.as_ref()) {
1424 self.focus(&handle)
1425 }
1426 }
1427
1428 pub fn focus_prev(&mut self) {
1430 if !self.focus_enabled {
1431 return;
1432 }
1433
1434 if let Some(handle) = self.rendered_frame.tab_stops.prev(self.focus.as_ref()) {
1435 self.focus(&handle)
1436 }
1437 }
1438
1439 pub fn text_system(&self) -> &Arc<WindowTextSystem> {
1441 &self.text_system
1442 }
1443
1444 pub fn text_style(&self) -> TextStyle {
1446 let mut style = TextStyle::default();
1447 for refinement in &self.text_style_stack {
1448 style.refine(refinement);
1449 }
1450 style
1451 }
1452
1453 pub fn is_maximized(&self) -> bool {
1456 self.platform_window.is_maximized()
1457 }
1458
1459 pub fn request_decorations(&self, decorations: WindowDecorations) {
1461 self.platform_window.request_decorations(decorations);
1462 }
1463
1464 pub fn start_window_resize(&self, edge: ResizeEdge) {
1466 self.platform_window.start_window_resize(edge);
1467 }
1468
1469 pub fn window_bounds(&self) -> WindowBounds {
1472 self.platform_window.window_bounds()
1473 }
1474
1475 pub fn inner_window_bounds(&self) -> WindowBounds {
1477 self.platform_window.inner_window_bounds()
1478 }
1479
1480 pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {
1482 let focus_id = self.focused(cx).map(|handle| handle.id);
1483
1484 let window = self.handle;
1485 cx.defer(move |cx| {
1486 window
1487 .update(cx, |_, window, cx| {
1488 let node_id = window.focus_node_id_in_rendered_frame(focus_id);
1489 window.dispatch_action_on_node(node_id, action.as_ref(), cx);
1490 })
1491 .log_err();
1492 })
1493 }
1494
1495 pub(crate) fn dispatch_keystroke_observers(
1496 &mut self,
1497 event: &dyn Any,
1498 action: Option<Box<dyn Action>>,
1499 context_stack: Vec<KeyContext>,
1500 cx: &mut App,
1501 ) {
1502 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
1503 return;
1504 };
1505
1506 cx.keystroke_observers.clone().retain(&(), move |callback| {
1507 (callback)(
1508 &KeystrokeEvent {
1509 keystroke: key_down_event.keystroke.clone(),
1510 action: action.as_ref().map(|action| action.boxed_clone()),
1511 context_stack: context_stack.clone(),
1512 },
1513 self,
1514 cx,
1515 )
1516 });
1517 }
1518
1519 pub(crate) fn dispatch_keystroke_interceptors(
1520 &mut self,
1521 event: &dyn Any,
1522 context_stack: Vec<KeyContext>,
1523 cx: &mut App,
1524 ) {
1525 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
1526 return;
1527 };
1528
1529 cx.keystroke_interceptors
1530 .clone()
1531 .retain(&(), move |callback| {
1532 (callback)(
1533 &KeystrokeEvent {
1534 keystroke: key_down_event.keystroke.clone(),
1535 action: None,
1536 context_stack: context_stack.clone(),
1537 },
1538 self,
1539 cx,
1540 )
1541 });
1542 }
1543
1544 pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {
1547 let handle = self.handle;
1548 cx.defer(move |cx| {
1549 handle.update(cx, |_, window, cx| f(window, cx)).ok();
1550 });
1551 }
1552
1553 pub fn observe<T: 'static>(
1557 &mut self,
1558 observed: &Entity<T>,
1559 cx: &mut App,
1560 mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,
1561 ) -> Subscription {
1562 let entity_id = observed.entity_id();
1563 let observed = observed.downgrade();
1564 let window_handle = self.handle;
1565 cx.new_observer(
1566 entity_id,
1567 Box::new(move |cx| {
1568 window_handle
1569 .update(cx, |_, window, cx| {
1570 if let Some(handle) = observed.upgrade() {
1571 on_notify(handle, window, cx);
1572 true
1573 } else {
1574 false
1575 }
1576 })
1577 .unwrap_or(false)
1578 }),
1579 )
1580 }
1581
1582 pub fn subscribe<Emitter, Evt>(
1586 &mut self,
1587 entity: &Entity<Emitter>,
1588 cx: &mut App,
1589 mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,
1590 ) -> Subscription
1591 where
1592 Emitter: EventEmitter<Evt>,
1593 Evt: 'static,
1594 {
1595 let entity_id = entity.entity_id();
1596 let handle = entity.downgrade();
1597 let window_handle = self.handle;
1598 cx.new_subscription(
1599 entity_id,
1600 (
1601 TypeId::of::<Evt>(),
1602 Box::new(move |event, cx| {
1603 window_handle
1604 .update(cx, |_, window, cx| {
1605 if let Some(entity) = handle.upgrade() {
1606 let event = event.downcast_ref().expect("invalid event type");
1607 on_event(entity, event, window, cx);
1608 true
1609 } else {
1610 false
1611 }
1612 })
1613 .unwrap_or(false)
1614 }),
1615 ),
1616 )
1617 }
1618
1619 pub fn observe_release<T>(
1621 &self,
1622 entity: &Entity<T>,
1623 cx: &mut App,
1624 mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
1625 ) -> Subscription
1626 where
1627 T: 'static,
1628 {
1629 let entity_id = entity.entity_id();
1630 let window_handle = self.handle;
1631 let (subscription, activate) = cx.release_listeners.insert(
1632 entity_id,
1633 Box::new(move |entity, cx| {
1634 let entity = entity.downcast_mut().expect("invalid entity type");
1635 let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
1636 }),
1637 );
1638 activate();
1639 subscription
1640 }
1641
1642 pub fn to_async(&self, cx: &App) -> AsyncWindowContext {
1645 AsyncWindowContext::new_context(cx.to_async(), self.handle)
1646 }
1647
1648 pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {
1650 RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));
1651 }
1652
1653 pub fn request_animation_frame(&self) {
1660 let entity = self.current_view();
1661 self.on_next_frame(move |_, cx| cx.notify(entity));
1662 }
1663
1664 #[track_caller]
1668 pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>
1669 where
1670 R: 'static,
1671 AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
1672 {
1673 let handle = self.handle;
1674 cx.spawn(async move |app| {
1675 let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
1676 f(&mut async_window_cx).await
1677 })
1678 }
1679
1680 fn bounds_changed(&mut self, cx: &mut App) {
1681 self.scale_factor = self.platform_window.scale_factor();
1682 self.viewport_size = self.platform_window.content_size();
1683 self.display_id = self.platform_window.display().map(|display| display.id());
1684
1685 self.refresh();
1686
1687 self.bounds_observers
1688 .clone()
1689 .retain(&(), |callback| callback(self, cx));
1690 }
1691
1692 pub fn bounds(&self) -> Bounds<Pixels> {
1694 self.platform_window.bounds()
1695 }
1696
1697 pub fn resize(&mut self, size: Size<Pixels>) {
1699 self.platform_window.resize(size);
1700 }
1701
1702 pub fn is_fullscreen(&self) -> bool {
1704 self.platform_window.is_fullscreen()
1705 }
1706
1707 pub(crate) fn appearance_changed(&mut self, cx: &mut App) {
1708 self.appearance = self.platform_window.appearance();
1709
1710 self.appearance_observers
1711 .clone()
1712 .retain(&(), |callback| callback(self, cx));
1713 }
1714
1715 pub fn appearance(&self) -> WindowAppearance {
1717 self.appearance
1718 }
1719
1720 pub fn viewport_size(&self) -> Size<Pixels> {
1722 self.viewport_size
1723 }
1724
1725 pub fn is_window_active(&self) -> bool {
1727 self.active.get()
1728 }
1729
1730 pub fn is_window_hovered(&self) -> bool {
1734 if cfg!(any(
1735 target_os = "windows",
1736 target_os = "linux",
1737 target_os = "freebsd"
1738 )) {
1739 self.hovered.get()
1740 } else {
1741 self.is_window_active()
1742 }
1743 }
1744
1745 pub fn zoom_window(&self) {
1747 self.platform_window.zoom();
1748 }
1749
1750 pub fn show_window_menu(&self, position: Point<Pixels>) {
1752 self.platform_window.show_window_menu(position)
1753 }
1754
1755 pub fn start_window_move(&self) {
1759 self.platform_window.start_window_move()
1760 }
1761
1762 pub fn set_client_inset(&mut self, inset: Pixels) {
1764 self.client_inset = Some(inset);
1765 self.platform_window.set_client_inset(inset);
1766 }
1767
1768 pub fn client_inset(&self) -> Option<Pixels> {
1770 self.client_inset
1771 }
1772
1773 pub fn window_decorations(&self) -> Decorations {
1775 self.platform_window.window_decorations()
1776 }
1777
1778 pub fn window_controls(&self) -> WindowControls {
1780 self.platform_window.window_controls()
1781 }
1782
1783 pub fn set_window_title(&mut self, title: &str) {
1785 self.platform_window.set_title(title);
1786 }
1787
1788 pub fn set_app_id(&mut self, app_id: &str) {
1790 self.platform_window.set_app_id(app_id);
1791 }
1792
1793 pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
1795 self.platform_window
1796 .set_background_appearance(background_appearance);
1797 }
1798
1799 pub fn set_window_edited(&mut self, edited: bool) {
1801 self.platform_window.set_edited(edited);
1802 }
1803
1804 pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {
1806 cx.platform
1807 .displays()
1808 .into_iter()
1809 .find(|display| Some(display.id()) == self.display_id)
1810 }
1811
1812 pub fn show_character_palette(&self) {
1814 self.platform_window.show_character_palette();
1815 }
1816
1817 pub fn scale_factor(&self) -> f32 {
1821 self.scale_factor
1822 }
1823
1824 pub fn rem_size(&self) -> Pixels {
1827 self.rem_size_override_stack
1828 .last()
1829 .copied()
1830 .unwrap_or(self.rem_size)
1831 }
1832
1833 pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
1836 self.rem_size = rem_size.into();
1837 }
1838
1839 pub fn with_global_id<R>(
1842 &mut self,
1843 element_id: ElementId,
1844 f: impl FnOnce(&GlobalElementId, &mut Self) -> R,
1845 ) -> R {
1846 self.element_id_stack.push(element_id);
1847 let global_id = GlobalElementId(self.element_id_stack.clone());
1848 let result = f(&global_id, self);
1849 self.element_id_stack.pop();
1850 result
1851 }
1852
1853 pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R
1857 where
1858 F: FnOnce(&mut Self) -> R,
1859 {
1860 self.invalidator.debug_assert_paint_or_prepaint();
1861
1862 if let Some(rem_size) = rem_size {
1863 self.rem_size_override_stack.push(rem_size.into());
1864 let result = f(self);
1865 self.rem_size_override_stack.pop();
1866 result
1867 } else {
1868 f(self)
1869 }
1870 }
1871
1872 pub fn line_height(&self) -> Pixels {
1874 self.text_style().line_height_in_pixels(self.rem_size())
1875 }
1876
1877 pub fn prevent_default(&mut self) {
1880 self.default_prevented = true;
1881 }
1882
1883 pub fn default_prevented(&self) -> bool {
1885 self.default_prevented
1886 }
1887
1888 pub fn is_action_available(&self, action: &dyn Action, cx: &mut App) -> bool {
1890 let node_id =
1891 self.focus_node_id_in_rendered_frame(self.focused(cx).map(|handle| handle.id));
1892 self.rendered_frame
1893 .dispatch_tree
1894 .is_action_available(action, node_id)
1895 }
1896
1897 pub fn mouse_position(&self) -> Point<Pixels> {
1899 self.mouse_position
1900 }
1901
1902 pub fn modifiers(&self) -> Modifiers {
1904 self.modifiers
1905 }
1906
1907 pub fn capslock(&self) -> Capslock {
1909 self.capslock
1910 }
1911
1912 fn complete_frame(&self) {
1913 self.platform_window.completed_frame();
1914 }
1915
1916 #[profiling::function]
1919 pub fn draw(&mut self, cx: &mut App) -> ArenaClearNeeded {
1920 self.invalidate_entities();
1921 cx.entities.clear_accessed();
1922 debug_assert!(self.rendered_entity_stack.is_empty());
1923 self.invalidator.set_dirty(false);
1924 self.requested_autoscroll = None;
1925
1926 if let Some(input_handler) = self.platform_window.take_input_handler() {
1928 self.rendered_frame.input_handlers.push(Some(input_handler));
1929 }
1930 self.draw_roots(cx);
1931 self.dirty_views.clear();
1932 self.next_frame.window_active = self.active.get();
1933
1934 if let Some(input_handler) = self.next_frame.input_handlers.pop() {
1936 self.platform_window
1937 .set_input_handler(input_handler.unwrap());
1938 }
1939
1940 self.layout_engine.as_mut().unwrap().clear();
1941 self.text_system().finish_frame();
1942 self.next_frame.finish(&mut self.rendered_frame);
1943
1944 self.invalidator.set_phase(DrawPhase::Focus);
1945 let previous_focus_path = self.rendered_frame.focus_path();
1946 let previous_window_active = self.rendered_frame.window_active;
1947 mem::swap(&mut self.rendered_frame, &mut self.next_frame);
1948 self.next_frame.clear();
1949 let current_focus_path = self.rendered_frame.focus_path();
1950 let current_window_active = self.rendered_frame.window_active;
1951
1952 if previous_focus_path != current_focus_path
1953 || previous_window_active != current_window_active
1954 {
1955 if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
1956 self.focus_lost_listeners
1957 .clone()
1958 .retain(&(), |listener| listener(self, cx));
1959 }
1960
1961 let event = WindowFocusEvent {
1962 previous_focus_path: if previous_window_active {
1963 previous_focus_path
1964 } else {
1965 Default::default()
1966 },
1967 current_focus_path: if current_window_active {
1968 current_focus_path
1969 } else {
1970 Default::default()
1971 },
1972 };
1973 self.focus_listeners
1974 .clone()
1975 .retain(&(), |listener| listener(&event, self, cx));
1976 }
1977
1978 debug_assert!(self.rendered_entity_stack.is_empty());
1979 self.record_entities_accessed(cx);
1980 self.reset_cursor_style(cx);
1981 self.refreshing = false;
1982 self.invalidator.set_phase(DrawPhase::None);
1983 self.needs_present.set(true);
1984
1985 ArenaClearNeeded
1986 }
1987
1988 fn record_entities_accessed(&mut self, cx: &mut App) {
1989 let mut entities_ref = cx.entities.accessed_entities.borrow_mut();
1990 let mut entities = mem::take(entities_ref.deref_mut());
1991 drop(entities_ref);
1992 let handle = self.handle;
1993 cx.record_entities_accessed(
1994 handle,
1995 self.invalidator.clone(),
1997 &entities,
1998 );
1999 let mut entities_ref = cx.entities.accessed_entities.borrow_mut();
2000 mem::swap(&mut entities, entities_ref.deref_mut());
2001 }
2002
2003 fn invalidate_entities(&mut self) {
2004 let mut views = self.invalidator.take_views();
2005 for entity in views.drain() {
2006 self.mark_view_dirty(entity);
2007 }
2008 self.invalidator.replace_views(views);
2009 }
2010
2011 #[profiling::function]
2012 fn present(&self) {
2013 self.platform_window.draw(&self.rendered_frame.scene);
2014 self.needs_present.set(false);
2015 profiling::finish_frame!();
2016 }
2017
2018 fn draw_roots(&mut self, cx: &mut App) {
2019 self.invalidator.set_phase(DrawPhase::Prepaint);
2020 self.tooltip_bounds.take();
2021
2022 let _inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size());
2023 let root_size = {
2024 #[cfg(any(feature = "inspector", debug_assertions))]
2025 {
2026 if self.inspector.is_some() {
2027 let mut size = self.viewport_size;
2028 size.width = (size.width - _inspector_width).max(px(0.0));
2029 size
2030 } else {
2031 self.viewport_size
2032 }
2033 }
2034 #[cfg(not(any(feature = "inspector", debug_assertions)))]
2035 {
2036 self.viewport_size
2037 }
2038 };
2039
2040 let mut root_element = self.root.as_ref().unwrap().clone().into_any();
2042 root_element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2043
2044 #[cfg(any(feature = "inspector", debug_assertions))]
2045 let inspector_element = self.prepaint_inspector(_inspector_width, cx);
2046
2047 let mut sorted_deferred_draws =
2048 (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();
2049 sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
2050 self.prepaint_deferred_draws(&sorted_deferred_draws, cx);
2051
2052 let mut prompt_element = None;
2053 let mut active_drag_element = None;
2054 let mut tooltip_element = None;
2055 if let Some(prompt) = self.prompt.take() {
2056 let mut element = prompt.view.any_view().into_any();
2057 element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2058 prompt_element = Some(element);
2059 self.prompt = Some(prompt);
2060 } else if let Some(active_drag) = cx.active_drag.take() {
2061 let mut element = active_drag.view.clone().into_any();
2062 let offset = self.mouse_position() - active_drag.cursor_offset;
2063 element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);
2064 active_drag_element = Some(element);
2065 cx.active_drag = Some(active_drag);
2066 } else {
2067 tooltip_element = self.prepaint_tooltip(cx);
2068 }
2069
2070 self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);
2071
2072 self.invalidator.set_phase(DrawPhase::Paint);
2074 root_element.paint(self, cx);
2075
2076 #[cfg(any(feature = "inspector", debug_assertions))]
2077 self.paint_inspector(inspector_element, cx);
2078
2079 self.paint_deferred_draws(&sorted_deferred_draws, cx);
2080
2081 if let Some(mut prompt_element) = prompt_element {
2082 prompt_element.paint(self, cx);
2083 } else if let Some(mut drag_element) = active_drag_element {
2084 drag_element.paint(self, cx);
2085 } else if let Some(mut tooltip_element) = tooltip_element {
2086 tooltip_element.paint(self, cx);
2087 }
2088
2089 #[cfg(any(feature = "inspector", debug_assertions))]
2090 self.paint_inspector_hitbox(cx);
2091 }
2092
2093 fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {
2094 for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {
2096 let Some(Some(tooltip_request)) = self
2097 .next_frame
2098 .tooltip_requests
2099 .get(tooltip_request_index)
2100 .cloned()
2101 else {
2102 log::error!("Unexpectedly absent TooltipRequest");
2103 continue;
2104 };
2105 let mut element = tooltip_request.tooltip.view.clone().into_any();
2106 let mouse_position = tooltip_request.tooltip.mouse_position;
2107 let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);
2108
2109 let mut tooltip_bounds =
2110 Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
2111 let window_bounds = Bounds {
2112 origin: Point::default(),
2113 size: self.viewport_size(),
2114 };
2115
2116 if tooltip_bounds.right() > window_bounds.right() {
2117 let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
2118 if new_x >= Pixels::ZERO {
2119 tooltip_bounds.origin.x = new_x;
2120 } else {
2121 tooltip_bounds.origin.x = cmp::max(
2122 Pixels::ZERO,
2123 tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
2124 );
2125 }
2126 }
2127
2128 if tooltip_bounds.bottom() > window_bounds.bottom() {
2129 let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
2130 if new_y >= Pixels::ZERO {
2131 tooltip_bounds.origin.y = new_y;
2132 } else {
2133 tooltip_bounds.origin.y = cmp::max(
2134 Pixels::ZERO,
2135 tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
2136 );
2137 }
2138 }
2139
2140 let is_visible =
2144 (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);
2145 if !is_visible {
2146 continue;
2147 }
2148
2149 self.with_absolute_element_offset(tooltip_bounds.origin, |window| {
2150 element.prepaint(window, cx)
2151 });
2152
2153 self.tooltip_bounds = Some(TooltipBounds {
2154 id: tooltip_request.id,
2155 bounds: tooltip_bounds,
2156 });
2157 return Some(element);
2158 }
2159 None
2160 }
2161
2162 fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {
2163 assert_eq!(self.element_id_stack.len(), 0);
2164
2165 let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
2166 for deferred_draw_ix in deferred_draw_indices {
2167 let deferred_draw = &mut deferred_draws[*deferred_draw_ix];
2168 self.element_id_stack
2169 .clone_from(&deferred_draw.element_id_stack);
2170 self.text_style_stack
2171 .clone_from(&deferred_draw.text_style_stack);
2172 self.next_frame
2173 .dispatch_tree
2174 .set_active_node(deferred_draw.parent_node);
2175
2176 let prepaint_start = self.prepaint_index();
2177 if let Some(element) = deferred_draw.element.as_mut() {
2178 self.with_rendered_view(deferred_draw.current_view, |window| {
2179 window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {
2180 element.prepaint(window, cx)
2181 });
2182 })
2183 } else {
2184 self.reuse_prepaint(deferred_draw.prepaint_range.clone());
2185 }
2186 let prepaint_end = self.prepaint_index();
2187 deferred_draw.prepaint_range = prepaint_start..prepaint_end;
2188 }
2189 assert_eq!(
2190 self.next_frame.deferred_draws.len(),
2191 0,
2192 "cannot call defer_draw during deferred drawing"
2193 );
2194 self.next_frame.deferred_draws = deferred_draws;
2195 self.element_id_stack.clear();
2196 self.text_style_stack.clear();
2197 }
2198
2199 fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {
2200 assert_eq!(self.element_id_stack.len(), 0);
2201
2202 let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
2203 for deferred_draw_ix in deferred_draw_indices {
2204 let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];
2205 self.element_id_stack
2206 .clone_from(&deferred_draw.element_id_stack);
2207 self.next_frame
2208 .dispatch_tree
2209 .set_active_node(deferred_draw.parent_node);
2210
2211 let paint_start = self.paint_index();
2212 if let Some(element) = deferred_draw.element.as_mut() {
2213 self.with_rendered_view(deferred_draw.current_view, |window| {
2214 element.paint(window, cx);
2215 })
2216 } else {
2217 self.reuse_paint(deferred_draw.paint_range.clone());
2218 }
2219 let paint_end = self.paint_index();
2220 deferred_draw.paint_range = paint_start..paint_end;
2221 }
2222 self.next_frame.deferred_draws = deferred_draws;
2223 self.element_id_stack.clear();
2224 }
2225
2226 pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {
2227 PrepaintStateIndex {
2228 hitboxes_index: self.next_frame.hitboxes.len(),
2229 tooltips_index: self.next_frame.tooltip_requests.len(),
2230 deferred_draws_index: self.next_frame.deferred_draws.len(),
2231 dispatch_tree_index: self.next_frame.dispatch_tree.len(),
2232 accessed_element_states_index: self.next_frame.accessed_element_states.len(),
2233 line_layout_index: self.text_system.layout_index(),
2234 }
2235 }
2236
2237 pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {
2238 self.next_frame.hitboxes.extend(
2239 self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
2240 .iter()
2241 .cloned(),
2242 );
2243 self.next_frame.tooltip_requests.extend(
2244 self.rendered_frame.tooltip_requests
2245 [range.start.tooltips_index..range.end.tooltips_index]
2246 .iter_mut()
2247 .map(|request| request.take()),
2248 );
2249 self.next_frame.accessed_element_states.extend(
2250 self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
2251 ..range.end.accessed_element_states_index]
2252 .iter()
2253 .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),
2254 );
2255 self.text_system
2256 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
2257
2258 let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(
2259 range.start.dispatch_tree_index..range.end.dispatch_tree_index,
2260 &mut self.rendered_frame.dispatch_tree,
2261 self.focus,
2262 );
2263
2264 if reused_subtree.contains_focus() {
2265 self.next_frame.focus = self.focus;
2266 }
2267
2268 self.next_frame.deferred_draws.extend(
2269 self.rendered_frame.deferred_draws
2270 [range.start.deferred_draws_index..range.end.deferred_draws_index]
2271 .iter()
2272 .map(|deferred_draw| DeferredDraw {
2273 current_view: deferred_draw.current_view,
2274 parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
2275 element_id_stack: deferred_draw.element_id_stack.clone(),
2276 text_style_stack: deferred_draw.text_style_stack.clone(),
2277 priority: deferred_draw.priority,
2278 element: None,
2279 absolute_offset: deferred_draw.absolute_offset,
2280 prepaint_range: deferred_draw.prepaint_range.clone(),
2281 paint_range: deferred_draw.paint_range.clone(),
2282 }),
2283 );
2284 }
2285
2286 pub(crate) fn paint_index(&self) -> PaintIndex {
2287 PaintIndex {
2288 scene_index: self.next_frame.scene.len(),
2289 mouse_listeners_index: self.next_frame.mouse_listeners.len(),
2290 input_handlers_index: self.next_frame.input_handlers.len(),
2291 cursor_styles_index: self.next_frame.cursor_styles.len(),
2292 accessed_element_states_index: self.next_frame.accessed_element_states.len(),
2293 tab_handle_index: self.next_frame.tab_stops.paint_index(),
2294 line_layout_index: self.text_system.layout_index(),
2295 }
2296 }
2297
2298 pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
2299 self.next_frame.cursor_styles.extend(
2300 self.rendered_frame.cursor_styles
2301 [range.start.cursor_styles_index..range.end.cursor_styles_index]
2302 .iter()
2303 .cloned(),
2304 );
2305 self.next_frame.input_handlers.extend(
2306 self.rendered_frame.input_handlers
2307 [range.start.input_handlers_index..range.end.input_handlers_index]
2308 .iter_mut()
2309 .map(|handler| handler.take()),
2310 );
2311 self.next_frame.mouse_listeners.extend(
2312 self.rendered_frame.mouse_listeners
2313 [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
2314 .iter_mut()
2315 .map(|listener| listener.take()),
2316 );
2317 self.next_frame.accessed_element_states.extend(
2318 self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
2319 ..range.end.accessed_element_states_index]
2320 .iter()
2321 .map(|(id, type_id)| (GlobalElementId(id.0.clone()), *type_id)),
2322 );
2323 self.next_frame.tab_stops.replay(
2324 &self.rendered_frame.tab_stops.insertion_history
2325 [range.start.tab_handle_index..range.end.tab_handle_index],
2326 );
2327
2328 self.text_system
2329 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
2330 self.next_frame.scene.replay(
2331 range.start.scene_index..range.end.scene_index,
2332 &self.rendered_frame.scene,
2333 );
2334 }
2335
2336 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
2340 where
2341 F: FnOnce(&mut Self) -> R,
2342 {
2343 self.invalidator.debug_assert_paint_or_prepaint();
2344 if let Some(style) = style {
2345 self.text_style_stack.push(style);
2346 let result = f(self);
2347 self.text_style_stack.pop();
2348 result
2349 } else {
2350 f(self)
2351 }
2352 }
2353
2354 pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
2357 self.invalidator.debug_assert_paint();
2358 self.next_frame.cursor_styles.push(CursorStyleRequest {
2359 hitbox_id: Some(hitbox.id),
2360 style,
2361 });
2362 }
2363
2364 pub fn set_window_cursor_style(&mut self, style: CursorStyle) {
2369 self.invalidator.debug_assert_paint();
2370 self.next_frame.cursor_styles.push(CursorStyleRequest {
2371 hitbox_id: None,
2372 style,
2373 })
2374 }
2375
2376 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
2379 self.invalidator.debug_assert_prepaint();
2380 let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));
2381 self.next_frame
2382 .tooltip_requests
2383 .push(Some(TooltipRequest { id, tooltip }));
2384 id
2385 }
2386
2387 pub fn with_content_mask<R>(
2390 &mut self,
2391 mask: Option<ContentMask<Pixels>>,
2392 f: impl FnOnce(&mut Self) -> R,
2393 ) -> R {
2394 self.invalidator.debug_assert_paint_or_prepaint();
2395 if let Some(mask) = mask {
2396 let mask = mask.intersect(&self.content_mask());
2397 self.content_mask_stack.push(mask);
2398 let result = f(self);
2399 self.content_mask_stack.pop();
2400 result
2401 } else {
2402 f(self)
2403 }
2404 }
2405
2406 pub fn with_element_offset<R>(
2409 &mut self,
2410 offset: Point<Pixels>,
2411 f: impl FnOnce(&mut Self) -> R,
2412 ) -> R {
2413 self.invalidator.debug_assert_prepaint();
2414
2415 if offset.is_zero() {
2416 return f(self);
2417 };
2418
2419 let abs_offset = self.element_offset() + offset;
2420 self.with_absolute_element_offset(abs_offset, f)
2421 }
2422
2423 pub fn with_absolute_element_offset<R>(
2427 &mut self,
2428 offset: Point<Pixels>,
2429 f: impl FnOnce(&mut Self) -> R,
2430 ) -> R {
2431 self.invalidator.debug_assert_prepaint();
2432 self.element_offset_stack.push(offset);
2433 let result = f(self);
2434 self.element_offset_stack.pop();
2435 result
2436 }
2437
2438 pub(crate) fn with_element_opacity<R>(
2439 &mut self,
2440 opacity: Option<f32>,
2441 f: impl FnOnce(&mut Self) -> R,
2442 ) -> R {
2443 self.invalidator.debug_assert_paint_or_prepaint();
2444
2445 let Some(opacity) = opacity else {
2446 return f(self);
2447 };
2448
2449 let previous_opacity = self.element_opacity;
2450 self.element_opacity = previous_opacity * opacity;
2451 let result = f(self);
2452 self.element_opacity = previous_opacity;
2453 result
2454 }
2455
2456 pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {
2462 self.invalidator.debug_assert_prepaint();
2463 let index = self.prepaint_index();
2464 let result = f(self);
2465 if result.is_err() {
2466 self.next_frame.hitboxes.truncate(index.hitboxes_index);
2467 self.next_frame
2468 .tooltip_requests
2469 .truncate(index.tooltips_index);
2470 self.next_frame
2471 .deferred_draws
2472 .truncate(index.deferred_draws_index);
2473 self.next_frame
2474 .dispatch_tree
2475 .truncate(index.dispatch_tree_index);
2476 self.next_frame
2477 .accessed_element_states
2478 .truncate(index.accessed_element_states_index);
2479 self.text_system.truncate_layouts(index.line_layout_index);
2480 }
2481 result
2482 }
2483
2484 pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {
2490 self.invalidator.debug_assert_prepaint();
2491 self.requested_autoscroll = Some(bounds);
2492 }
2493
2494 pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {
2497 self.invalidator.debug_assert_prepaint();
2498 self.requested_autoscroll.take()
2499 }
2500
2501 pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
2507 let (task, is_first) = cx.fetch_asset::<A>(source);
2508 task.clone().now_or_never().or_else(|| {
2509 if is_first {
2510 let entity_id = self.current_view();
2511 self.spawn(cx, {
2512 let task = task.clone();
2513 async move |cx| {
2514 task.await;
2515
2516 cx.on_next_frame(move |_, cx| {
2517 cx.notify(entity_id);
2518 });
2519 }
2520 })
2521 .detach();
2522 }
2523
2524 None
2525 })
2526 }
2527
2528 pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
2534 let (task, _) = cx.fetch_asset::<A>(source);
2535 task.now_or_never()
2536 }
2537 pub fn element_offset(&self) -> Point<Pixels> {
2540 self.invalidator.debug_assert_prepaint();
2541 self.element_offset_stack
2542 .last()
2543 .copied()
2544 .unwrap_or_default()
2545 }
2546
2547 #[inline]
2550 pub(crate) fn element_opacity(&self) -> f32 {
2551 self.invalidator.debug_assert_paint_or_prepaint();
2552 self.element_opacity
2553 }
2554
2555 pub fn content_mask(&self) -> ContentMask<Pixels> {
2557 self.invalidator.debug_assert_paint_or_prepaint();
2558 self.content_mask_stack
2559 .last()
2560 .cloned()
2561 .unwrap_or_else(|| ContentMask {
2562 bounds: Bounds {
2563 origin: Point::default(),
2564 size: self.viewport_size,
2565 },
2566 })
2567 }
2568
2569 pub fn with_element_namespace<R>(
2572 &mut self,
2573 element_id: impl Into<ElementId>,
2574 f: impl FnOnce(&mut Self) -> R,
2575 ) -> R {
2576 self.element_id_stack.push(element_id.into());
2577 let result = f(self);
2578 self.element_id_stack.pop();
2579 result
2580 }
2581
2582 pub fn use_keyed_state<S: 'static>(
2584 &mut self,
2585 key: impl Into<ElementId>,
2586 cx: &mut App,
2587 init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
2588 ) -> Entity<S> {
2589 let current_view = self.current_view();
2590 self.with_global_id(key.into(), |global_id, window| {
2591 window.with_element_state(global_id, |state: Option<Entity<S>>, window| {
2592 if let Some(state) = state {
2593 (state.clone(), state)
2594 } else {
2595 let new_state = cx.new(|cx| init(window, cx));
2596 cx.observe(&new_state, move |_, cx| {
2597 cx.notify(current_view);
2598 })
2599 .detach();
2600 (new_state.clone(), new_state)
2601 }
2602 })
2603 })
2604 }
2605
2606 pub fn with_id<R>(&mut self, id: impl Into<ElementId>, f: impl FnOnce(&mut Self) -> R) -> R {
2608 self.with_global_id(id.into(), |_, window| f(window))
2609 }
2610
2611 #[track_caller]
2617 pub fn use_state<S: 'static>(
2618 &mut self,
2619 cx: &mut App,
2620 init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
2621 ) -> Entity<S> {
2622 self.use_keyed_state(
2623 ElementId::CodeLocation(*core::panic::Location::caller()),
2624 cx,
2625 init,
2626 )
2627 }
2628
2629 pub fn with_element_state<S, R>(
2634 &mut self,
2635 global_id: &GlobalElementId,
2636 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
2637 ) -> R
2638 where
2639 S: 'static,
2640 {
2641 self.invalidator.debug_assert_paint_or_prepaint();
2642
2643 let key = (GlobalElementId(global_id.0.clone()), TypeId::of::<S>());
2644 self.next_frame
2645 .accessed_element_states
2646 .push((GlobalElementId(key.0.clone()), TypeId::of::<S>()));
2647
2648 if let Some(any) = self
2649 .next_frame
2650 .element_states
2651 .remove(&key)
2652 .or_else(|| self.rendered_frame.element_states.remove(&key))
2653 {
2654 let ElementStateBox {
2655 inner,
2656 #[cfg(debug_assertions)]
2657 type_name,
2658 } = any;
2659 let mut state_box = inner
2661 .downcast::<Option<S>>()
2662 .map_err(|_| {
2663 #[cfg(debug_assertions)]
2664 {
2665 anyhow::anyhow!(
2666 "invalid element state type for id, requested {:?}, actual: {:?}",
2667 std::any::type_name::<S>(),
2668 type_name
2669 )
2670 }
2671
2672 #[cfg(not(debug_assertions))]
2673 {
2674 anyhow::anyhow!(
2675 "invalid element state type for id, requested {:?}",
2676 std::any::type_name::<S>(),
2677 )
2678 }
2679 })
2680 .unwrap();
2681
2682 let state = state_box.take().expect(
2683 "reentrant call to with_element_state for the same state type and element id",
2684 );
2685 let (result, state) = f(Some(state), self);
2686 state_box.replace(state);
2687 self.next_frame.element_states.insert(
2688 key,
2689 ElementStateBox {
2690 inner: state_box,
2691 #[cfg(debug_assertions)]
2692 type_name,
2693 },
2694 );
2695 result
2696 } else {
2697 let (result, state) = f(None, self);
2698 self.next_frame.element_states.insert(
2699 key,
2700 ElementStateBox {
2701 inner: Box::new(Some(state)),
2702 #[cfg(debug_assertions)]
2703 type_name: std::any::type_name::<S>(),
2704 },
2705 );
2706 result
2707 }
2708 }
2709
2710 pub fn with_optional_element_state<S, R>(
2717 &mut self,
2718 global_id: Option<&GlobalElementId>,
2719 f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
2720 ) -> R
2721 where
2722 S: 'static,
2723 {
2724 self.invalidator.debug_assert_paint_or_prepaint();
2725
2726 if let Some(global_id) = global_id {
2727 self.with_element_state(global_id, |state, cx| {
2728 let (result, state) = f(Some(state), cx);
2729 let state =
2730 state.expect("you must return some state when you pass some element id");
2731 (result, state)
2732 })
2733 } else {
2734 let (result, state) = f(None, self);
2735 debug_assert!(
2736 state.is_none(),
2737 "you must not return an element state when passing None for the global id"
2738 );
2739 result
2740 }
2741 }
2742
2743 #[inline]
2745 pub fn with_tab_group<R>(&mut self, index: Option<isize>, f: impl FnOnce(&mut Self) -> R) -> R {
2746 if let Some(index) = index {
2747 self.next_frame.tab_stops.begin_group(index);
2748 let result = f(self);
2749 self.next_frame.tab_stops.end_group();
2750 result
2751 } else {
2752 f(self)
2753 }
2754 }
2755
2756 pub fn defer_draw(
2762 &mut self,
2763 element: AnyElement,
2764 absolute_offset: Point<Pixels>,
2765 priority: usize,
2766 ) {
2767 self.invalidator.debug_assert_prepaint();
2768 let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();
2769 self.next_frame.deferred_draws.push(DeferredDraw {
2770 current_view: self.current_view(),
2771 parent_node,
2772 element_id_stack: self.element_id_stack.clone(),
2773 text_style_stack: self.text_style_stack.clone(),
2774 priority,
2775 element: Some(element),
2776 absolute_offset,
2777 prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),
2778 paint_range: PaintIndex::default()..PaintIndex::default(),
2779 });
2780 }
2781
2782 pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
2788 self.invalidator.debug_assert_paint();
2789
2790 let scale_factor = self.scale_factor();
2791 let content_mask = self.content_mask();
2792 let clipped_bounds = bounds.intersect(&content_mask.bounds);
2793 if !clipped_bounds.is_empty() {
2794 self.next_frame
2795 .scene
2796 .push_layer(clipped_bounds.scale(scale_factor));
2797 }
2798
2799 let result = f(self);
2800
2801 if !clipped_bounds.is_empty() {
2802 self.next_frame.scene.pop_layer();
2803 }
2804
2805 result
2806 }
2807
2808 pub fn paint_shadows(
2812 &mut self,
2813 bounds: Bounds<Pixels>,
2814 corner_radii: Corners<Pixels>,
2815 shadows: &[BoxShadow],
2816 ) {
2817 self.invalidator.debug_assert_paint();
2818
2819 let scale_factor = self.scale_factor();
2820 let content_mask = self.content_mask();
2821 let opacity = self.element_opacity();
2822 for shadow in shadows {
2823 let shadow_bounds = if shadow.inset {
2824 bounds.contract(shadow.spread_radius)
2825 } else {
2826 (bounds + shadow.offset).dilate(shadow.spread_radius)
2827 };
2828 self.next_frame.scene.insert_primitive(Shadow {
2829 order: 0,
2830 blur_radius: shadow.blur_radius.scale(scale_factor),
2831 bounds: shadow_bounds.scale(scale_factor),
2832 content_mask: if shadow.inset {
2833 ContentMask {
2834 bounds: bounds.scale(scale_factor),
2835 }
2836 } else {
2837 content_mask.scale(scale_factor)
2838 },
2839 corner_radii: corner_radii.scale(scale_factor),
2840 color: shadow.color.opacity(opacity),
2841 inset: if shadow.inset { 1 } else { 0 },
2842 });
2843 }
2844 }
2845
2846 pub fn paint_quad(&mut self, quad: PaintQuad) {
2856 self.invalidator.debug_assert_paint();
2857
2858 let scale_factor = self.scale_factor();
2859 let content_mask = self.content_mask();
2860 let opacity = self.element_opacity();
2861 self.next_frame.scene.insert_primitive(Quad {
2862 order: 0,
2863 bounds: quad.bounds.scale(scale_factor),
2864 content_mask: content_mask.scale(scale_factor),
2865 background: quad.background.opacity(opacity),
2866 border_color: quad.border_color.opacity(opacity),
2867 corner_radii: quad.corner_radii.scale(scale_factor),
2868 border_widths: quad.border_widths.scale(scale_factor),
2869 border_style: quad.border_style,
2870 continuous_corners: if quad.continuous_corners { 1 } else { 0 },
2871 transform: quad.transform,
2872 blend_mode: quad.blend_mode as u32,
2873 });
2874 }
2875
2876 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {
2880 self.invalidator.debug_assert_paint();
2881
2882 let scale_factor = self.scale_factor();
2883 let content_mask = self.content_mask();
2884 let opacity = self.element_opacity();
2885 path.content_mask = content_mask;
2886 let color: Background = color.into();
2887 path.color = color.opacity(opacity);
2888 self.next_frame
2889 .scene
2890 .insert_primitive(path.scale(scale_factor));
2891 }
2892
2893 pub fn paint_underline(
2897 &mut self,
2898 origin: Point<Pixels>,
2899 width: Pixels,
2900 style: &UnderlineStyle,
2901 ) {
2902 self.invalidator.debug_assert_paint();
2903
2904 let scale_factor = self.scale_factor();
2905 let height = if style.wavy {
2906 style.thickness * 3.
2907 } else {
2908 style.thickness
2909 };
2910 let bounds = Bounds {
2911 origin,
2912 size: size(width, height),
2913 };
2914 let content_mask = self.content_mask();
2915 let element_opacity = self.element_opacity();
2916
2917 self.next_frame.scene.insert_primitive(Underline {
2918 order: 0,
2919 pad: 0,
2920 bounds: bounds.scale(scale_factor),
2921 content_mask: content_mask.scale(scale_factor),
2922 color: style.color.unwrap_or_default().opacity(element_opacity),
2923 thickness: style.thickness.scale(scale_factor),
2924 wavy: if style.wavy { 1 } else { 0 },
2925 });
2926 }
2927
2928 pub fn paint_strikethrough(
2932 &mut self,
2933 origin: Point<Pixels>,
2934 width: Pixels,
2935 style: &StrikethroughStyle,
2936 ) {
2937 self.invalidator.debug_assert_paint();
2938
2939 let scale_factor = self.scale_factor();
2940 let height = style.thickness;
2941 let bounds = Bounds {
2942 origin,
2943 size: size(width, height),
2944 };
2945 let content_mask = self.content_mask();
2946 let opacity = self.element_opacity();
2947
2948 self.next_frame.scene.insert_primitive(Underline {
2949 order: 0,
2950 pad: 0,
2951 bounds: bounds.scale(scale_factor),
2952 content_mask: content_mask.scale(scale_factor),
2953 thickness: style.thickness.scale(scale_factor),
2954 color: style.color.unwrap_or_default().opacity(opacity),
2955 wavy: 0,
2956 });
2957 }
2958
2959 pub fn paint_glyph(
2968 &mut self,
2969 origin: Point<Pixels>,
2970 font_id: FontId,
2971 glyph_id: GlyphId,
2972 font_size: Pixels,
2973 color: Hsla,
2974 ) -> Result<()> {
2975 self.invalidator.debug_assert_paint();
2976
2977 let element_opacity = self.element_opacity();
2978 let scale_factor = self.scale_factor();
2979 let glyph_origin = origin.scale(scale_factor);
2980
2981 let subpixel_variant = Point {
2982 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS_X as f32).floor() as u8,
2983 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS_Y as f32).floor() as u8,
2984 };
2985 let params = RenderGlyphParams {
2986 font_id,
2987 glyph_id,
2988 font_size,
2989 subpixel_variant,
2990 scale_factor,
2991 is_emoji: false,
2992 };
2993
2994 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
2995 if !raster_bounds.is_zero() {
2996 let tile = self
2997 .sprite_atlas
2998 .get_or_insert_with(¶ms.clone().into(), &mut || {
2999 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
3000 Ok(Some((size, Cow::Owned(bytes))))
3001 })?
3002 .expect("Callback above only errors or returns Some");
3003 let bounds = Bounds {
3004 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
3005 size: tile.bounds.size.map(Into::into),
3006 };
3007 let content_mask = self.content_mask().scale(scale_factor);
3008 self.next_frame.scene.insert_primitive(MonochromeSprite {
3009 order: 0,
3010 pad: 0,
3011 bounds,
3012 content_mask,
3013 color: color.opacity(element_opacity),
3014 tile,
3015 transformation: TransformationMatrix::unit(),
3016 });
3017 }
3018 Ok(())
3019 }
3020
3021 pub fn paint_emoji(
3030 &mut self,
3031 origin: Point<Pixels>,
3032 font_id: FontId,
3033 glyph_id: GlyphId,
3034 font_size: Pixels,
3035 ) -> Result<()> {
3036 self.invalidator.debug_assert_paint();
3037
3038 let scale_factor = self.scale_factor();
3039 let glyph_origin = origin.scale(scale_factor);
3040 let params = RenderGlyphParams {
3041 font_id,
3042 glyph_id,
3043 font_size,
3044 subpixel_variant: Default::default(),
3046 scale_factor,
3047 is_emoji: true,
3048 };
3049
3050 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
3051 if !raster_bounds.is_zero() {
3052 let tile = self
3053 .sprite_atlas
3054 .get_or_insert_with(¶ms.clone().into(), &mut || {
3055 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
3056 Ok(Some((size, Cow::Owned(bytes))))
3057 })?
3058 .expect("Callback above only errors or returns Some");
3059
3060 let bounds = Bounds {
3061 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
3062 size: tile.bounds.size.map(Into::into),
3063 };
3064 let content_mask = self.content_mask().scale(scale_factor);
3065 let opacity = self.element_opacity();
3066
3067 self.next_frame.scene.insert_primitive(PolychromeSprite {
3068 order: 0,
3069 pad: 0,
3070 grayscale: false,
3071 bounds,
3072 corner_radii: Default::default(),
3073 content_mask,
3074 tile,
3075 opacity,
3076 });
3077 }
3078 Ok(())
3079 }
3080
3081 pub fn paint_svg(
3085 &mut self,
3086 bounds: Bounds<Pixels>,
3087 path: SharedString,
3088 transformation: TransformationMatrix,
3089 color: Hsla,
3090 cx: &App,
3091 ) -> Result<()> {
3092 self.invalidator.debug_assert_paint();
3093
3094 let element_opacity = self.element_opacity();
3095 let scale_factor = self.scale_factor();
3096
3097 let bounds = bounds.scale(scale_factor);
3098 let params = RenderSvgParams {
3099 path,
3100 size: bounds.size.map(|pixels| {
3101 DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)
3102 }),
3103 };
3104
3105 let Some(tile) =
3106 self.sprite_atlas
3107 .get_or_insert_with(¶ms.clone().into(), &mut || {
3108 let Some((size, bytes)) = cx.svg_renderer.render(¶ms)? else {
3109 return Ok(None);
3110 };
3111 Ok(Some((size, Cow::Owned(bytes))))
3112 })?
3113 else {
3114 return Ok(());
3115 };
3116 let content_mask = self.content_mask().scale(scale_factor);
3117 let svg_bounds = Bounds {
3118 origin: bounds.center()
3119 - Point::new(
3120 ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
3121 ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
3122 ),
3123 size: tile
3124 .bounds
3125 .size
3126 .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)),
3127 };
3128
3129 self.next_frame.scene.insert_primitive(MonochromeSprite {
3130 order: 0,
3131 pad: 0,
3132 bounds: svg_bounds
3133 .map_origin(|origin| origin.round())
3134 .map_size(|size| size.ceil()),
3135 content_mask,
3136 color: color.opacity(element_opacity),
3137 tile,
3138 transformation,
3139 });
3140
3141 Ok(())
3142 }
3143
3144 pub fn paint_image(
3149 &mut self,
3150 bounds: Bounds<Pixels>,
3151 corner_radii: Corners<Pixels>,
3152 data: Arc<RenderImage>,
3153 frame_index: usize,
3154 grayscale: bool,
3155 ) -> Result<()> {
3156 self.invalidator.debug_assert_paint();
3157
3158 let scale_factor = self.scale_factor();
3159 let bounds = bounds.scale(scale_factor);
3160 let params = RenderImageParams {
3161 image_id: data.id,
3162 frame_index,
3163 };
3164
3165 let tile = self
3166 .sprite_atlas
3167 .get_or_insert_with(¶ms.into(), &mut || {
3168 Ok(Some((
3169 data.size(frame_index),
3170 Cow::Borrowed(
3171 data.as_bytes(frame_index)
3172 .expect("It's the caller's job to pass a valid frame index"),
3173 ),
3174 )))
3175 })?
3176 .expect("Callback above only returns Some");
3177 let content_mask = self.content_mask().scale(scale_factor);
3178 let corner_radii = corner_radii.scale(scale_factor);
3179 let opacity = self.element_opacity();
3180
3181 self.next_frame.scene.insert_primitive(PolychromeSprite {
3182 order: 0,
3183 pad: 0,
3184 grayscale,
3185 bounds: bounds
3186 .map_origin(|origin| origin.floor())
3187 .map_size(|size| size.ceil()),
3188 content_mask,
3189 corner_radii,
3190 tile,
3191 opacity,
3192 });
3193 Ok(())
3194 }
3195
3196 #[cfg(target_os = "macos")]
3200 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {
3201 use crate::PaintSurface;
3202
3203 self.invalidator.debug_assert_paint();
3204
3205 let scale_factor = self.scale_factor();
3206 let bounds = bounds.scale(scale_factor);
3207 let content_mask = self.content_mask().scale(scale_factor);
3208 self.next_frame.scene.insert_primitive(PaintSurface {
3209 order: 0,
3210 bounds,
3211 content_mask,
3212 image_buffer,
3213 });
3214 }
3215
3216 pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {
3218 for frame_index in 0..data.frame_count() {
3219 let params = RenderImageParams {
3220 image_id: data.id,
3221 frame_index,
3222 };
3223
3224 self.sprite_atlas.remove(¶ms.clone().into());
3225 }
3226
3227 Ok(())
3228 }
3229
3230 #[must_use]
3236 pub fn request_layout(
3237 &mut self,
3238 style: Style,
3239 children: impl IntoIterator<Item = LayoutId>,
3240 cx: &mut App,
3241 ) -> LayoutId {
3242 self.invalidator.debug_assert_prepaint();
3243
3244 cx.layout_id_buffer.clear();
3245 cx.layout_id_buffer.extend(children);
3246 let rem_size = self.rem_size();
3247 let scale_factor = self.scale_factor();
3248
3249 self.layout_engine.as_mut().unwrap().request_layout(
3250 style,
3251 rem_size,
3252 scale_factor,
3253 &cx.layout_id_buffer,
3254 )
3255 }
3256
3257 pub fn request_measured_layout<
3266 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
3267 + 'static,
3268 >(
3269 &mut self,
3270 style: Style,
3271 measure: F,
3272 ) -> LayoutId {
3273 self.invalidator.debug_assert_prepaint();
3274
3275 let rem_size = self.rem_size();
3276 let scale_factor = self.scale_factor();
3277 self.layout_engine
3278 .as_mut()
3279 .unwrap()
3280 .request_measured_layout(style, rem_size, scale_factor, measure)
3281 }
3282
3283 pub fn compute_layout(
3289 &mut self,
3290 layout_id: LayoutId,
3291 available_space: Size<AvailableSpace>,
3292 cx: &mut App,
3293 ) {
3294 self.invalidator.debug_assert_prepaint();
3295
3296 let mut layout_engine = self.layout_engine.take().unwrap();
3297 layout_engine.compute_layout(layout_id, available_space, self, cx);
3298 self.layout_engine = Some(layout_engine);
3299 }
3300
3301 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
3306 self.invalidator.debug_assert_prepaint();
3307
3308 let scale_factor = self.scale_factor();
3309 let mut bounds = self
3310 .layout_engine
3311 .as_mut()
3312 .unwrap()
3313 .layout_bounds(layout_id, scale_factor)
3314 .map(Into::into);
3315 bounds.origin += self.element_offset();
3316 bounds
3317 }
3318
3319 pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, behavior: HitboxBehavior) -> Hitbox {
3325 self.invalidator.debug_assert_prepaint();
3326
3327 let content_mask = self.content_mask();
3328 let mut id = self.next_hitbox_id;
3329 self.next_hitbox_id = self.next_hitbox_id.next();
3330 let hitbox = Hitbox {
3331 id,
3332 bounds,
3333 content_mask,
3334 behavior,
3335 };
3336 self.next_frame.hitboxes.push(hitbox.clone());
3337 hitbox
3338 }
3339
3340 pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) {
3344 self.invalidator.debug_assert_paint();
3345 self.next_frame.window_control_hitboxes.push((area, hitbox));
3346 }
3347
3348 pub fn set_key_context(&mut self, context: KeyContext) {
3353 self.invalidator.debug_assert_paint();
3354 self.next_frame.dispatch_tree.set_key_context(context);
3355 }
3356
3357 pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {
3362 self.invalidator.debug_assert_prepaint();
3363 if focus_handle.is_focused(self) {
3364 self.next_frame.focus = Some(focus_handle.id);
3365 }
3366 self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);
3367 }
3368
3369 pub fn set_view_id(&mut self, view_id: EntityId) {
3375 self.invalidator.debug_assert_prepaint();
3376 self.next_frame.dispatch_tree.set_view_id(view_id);
3377 }
3378
3379 pub fn current_view(&self) -> EntityId {
3381 self.invalidator.debug_assert_paint_or_prepaint();
3382 self.rendered_entity_stack.last().copied().unwrap()
3383 }
3384
3385 pub(crate) fn with_rendered_view<R>(
3386 &mut self,
3387 id: EntityId,
3388 f: impl FnOnce(&mut Self) -> R,
3389 ) -> R {
3390 self.rendered_entity_stack.push(id);
3391 let result = f(self);
3392 self.rendered_entity_stack.pop();
3393 result
3394 }
3395
3396 pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R
3398 where
3399 F: FnOnce(&mut Self) -> R,
3400 {
3401 if let Some(image_cache) = image_cache {
3402 self.image_cache_stack.push(image_cache);
3403 let result = f(self);
3404 self.image_cache_stack.pop();
3405 result
3406 } else {
3407 f(self)
3408 }
3409 }
3410
3411 pub fn handle_input(
3420 &mut self,
3421 focus_handle: &FocusHandle,
3422 input_handler: impl InputHandler,
3423 cx: &App,
3424 ) {
3425 self.invalidator.debug_assert_paint();
3426
3427 if focus_handle.is_focused(self) {
3428 let cx = self.to_async(cx);
3429 self.next_frame
3430 .input_handlers
3431 .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));
3432 }
3433 }
3434
3435 pub fn on_mouse_event<Event: MouseEvent>(
3441 &mut self,
3442 mut handler: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
3443 ) {
3444 self.invalidator.debug_assert_paint();
3445
3446 self.next_frame.mouse_listeners.push(Some(Box::new(
3447 move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {
3448 if let Some(event) = event.downcast_ref() {
3449 handler(event, phase, window, cx)
3450 }
3451 },
3452 )));
3453 }
3454
3455 pub fn on_key_event<Event: KeyEvent>(
3464 &mut self,
3465 listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
3466 ) {
3467 self.invalidator.debug_assert_paint();
3468
3469 self.next_frame.dispatch_tree.on_key_event(Rc::new(
3470 move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {
3471 if let Some(event) = event.downcast_ref::<Event>() {
3472 listener(event, phase, window, cx)
3473 }
3474 },
3475 ));
3476 }
3477
3478 pub fn on_modifiers_changed(
3485 &mut self,
3486 listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
3487 ) {
3488 self.invalidator.debug_assert_paint();
3489
3490 self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(
3491 move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {
3492 listener(event, window, cx)
3493 },
3494 ));
3495 }
3496
3497 pub fn on_focus_in(
3501 &mut self,
3502 handle: &FocusHandle,
3503 cx: &mut App,
3504 mut listener: impl FnMut(&mut Window, &mut App) + 'static,
3505 ) -> Subscription {
3506 let focus_id = handle.id;
3507 let (subscription, activate) =
3508 self.new_focus_listener(Box::new(move |event, window, cx| {
3509 if event.is_focus_in(focus_id) {
3510 listener(window, cx);
3511 }
3512 true
3513 }));
3514 cx.defer(move |_| activate());
3515 subscription
3516 }
3517
3518 pub fn on_focus_out(
3521 &mut self,
3522 handle: &FocusHandle,
3523 cx: &mut App,
3524 mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,
3525 ) -> Subscription {
3526 let focus_id = handle.id;
3527 let (subscription, activate) =
3528 self.new_focus_listener(Box::new(move |event, window, cx| {
3529 if let Some(blurred_id) = event.previous_focus_path.last().copied()
3530 && event.is_focus_out(focus_id)
3531 {
3532 let event = FocusOutEvent {
3533 blurred: WeakFocusHandle {
3534 id: blurred_id,
3535 handles: Arc::downgrade(&cx.focus_handles),
3536 },
3537 };
3538 listener(event, window, cx)
3539 }
3540 true
3541 }));
3542 cx.defer(move |_| activate());
3543 subscription
3544 }
3545
3546 fn reset_cursor_style(&self, cx: &mut App) {
3547 if self.is_window_hovered() {
3549 let style = self
3550 .rendered_frame
3551 .cursor_style(self)
3552 .unwrap_or(CursorStyle::Arrow);
3553 cx.platform.set_cursor_style(style);
3554 }
3555 }
3556
3557 pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {
3560 let keystroke = keystroke.with_simulated_ime();
3561 let result = self.dispatch_event(
3562 PlatformInput::KeyDown(KeyDownEvent {
3563 keystroke: keystroke.clone(),
3564 is_held: false,
3565 }),
3566 cx,
3567 );
3568 if !result.propagate {
3569 return true;
3570 }
3571
3572 if let Some(input) = keystroke.key_char
3573 && let Some(mut input_handler) = self.platform_window.take_input_handler()
3574 {
3575 input_handler.dispatch_input(&input, self, cx);
3576 self.platform_window.set_input_handler(input_handler);
3577 return true;
3578 }
3579
3580 false
3581 }
3582
3583 pub fn keystroke_text_for(&self, action: &dyn Action) -> String {
3586 self.highest_precedence_binding_for_action(action)
3587 .map(|binding| {
3588 binding
3589 .keystrokes()
3590 .iter()
3591 .map(ToString::to_string)
3592 .collect::<Vec<_>>()
3593 .join(" ")
3594 })
3595 .unwrap_or_else(|| action.name().to_string())
3596 }
3597
3598 #[profiling::function]
3600 pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {
3601 self.last_input_timestamp.set(Instant::now());
3602 cx.propagate_event = true;
3604 self.default_prevented = false;
3606
3607 let event = match event {
3608 PlatformInput::MouseMove(mouse_move) => {
3611 self.mouse_position = mouse_move.position;
3612 self.modifiers = mouse_move.modifiers;
3613 PlatformInput::MouseMove(mouse_move)
3614 }
3615 PlatformInput::MouseDown(mouse_down) => {
3616 self.mouse_position = mouse_down.position;
3617 self.modifiers = mouse_down.modifiers;
3618 PlatformInput::MouseDown(mouse_down)
3619 }
3620 PlatformInput::MouseUp(mouse_up) => {
3621 self.mouse_position = mouse_up.position;
3622 self.modifiers = mouse_up.modifiers;
3623 PlatformInput::MouseUp(mouse_up)
3624 }
3625 PlatformInput::MouseExited(mouse_exited) => {
3626 self.modifiers = mouse_exited.modifiers;
3627 PlatformInput::MouseExited(mouse_exited)
3628 }
3629 PlatformInput::ModifiersChanged(modifiers_changed) => {
3630 self.modifiers = modifiers_changed.modifiers;
3631 self.capslock = modifiers_changed.capslock;
3632 PlatformInput::ModifiersChanged(modifiers_changed)
3633 }
3634 PlatformInput::ScrollWheel(scroll_wheel) => {
3635 self.mouse_position = scroll_wheel.position;
3636 self.modifiers = scroll_wheel.modifiers;
3637 PlatformInput::ScrollWheel(scroll_wheel)
3638 }
3639 PlatformInput::FileDrop(file_drop) => match file_drop {
3642 FileDropEvent::Entered { position, paths } => {
3643 self.mouse_position = position;
3644 if cx.active_drag.is_none() {
3645 cx.active_drag = Some(AnyDrag {
3646 value: Arc::new(paths.clone()),
3647 view: cx.new(|_| paths).into(),
3648 cursor_offset: position,
3649 cursor_style: None,
3650 });
3651 }
3652 PlatformInput::MouseMove(MouseMoveEvent {
3653 position,
3654 pressed_button: Some(MouseButton::Left),
3655 modifiers: Modifiers::default(),
3656 })
3657 }
3658 FileDropEvent::Pending { position } => {
3659 self.mouse_position = position;
3660 PlatformInput::MouseMove(MouseMoveEvent {
3661 position,
3662 pressed_button: Some(MouseButton::Left),
3663 modifiers: Modifiers::default(),
3664 })
3665 }
3666 FileDropEvent::Submit { position } => {
3667 cx.activate(true);
3668 self.mouse_position = position;
3669 PlatformInput::MouseUp(MouseUpEvent {
3670 button: MouseButton::Left,
3671 position,
3672 modifiers: Modifiers::default(),
3673 click_count: 1,
3674 })
3675 }
3676 FileDropEvent::Exited => {
3677 cx.active_drag.take();
3678 PlatformInput::FileDrop(FileDropEvent::Exited)
3679 }
3680 },
3681 PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
3682 };
3683
3684 if let Some(any_mouse_event) = event.mouse_event() {
3685 self.dispatch_mouse_event(any_mouse_event, cx);
3686 } else if let Some(any_key_event) = event.keyboard_event() {
3687 self.dispatch_key_event(any_key_event, cx);
3688 }
3689
3690 DispatchEventResult {
3691 propagate: cx.propagate_event,
3692 default_prevented: self.default_prevented,
3693 }
3694 }
3695
3696 fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
3697 let hit_test = self.rendered_frame.hit_test(self.mouse_position());
3698 if hit_test != self.mouse_hit_test {
3699 self.mouse_hit_test = hit_test;
3700 self.reset_cursor_style(cx);
3701 }
3702
3703 #[cfg(any(feature = "inspector", debug_assertions))]
3704 if self.is_inspector_picking(cx) {
3705 self.handle_inspector_mouse_event(event, cx);
3706 return;
3708 }
3709
3710 let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);
3711
3712 for listener in &mut mouse_listeners {
3715 let listener = listener.as_mut().unwrap();
3716 listener(event, DispatchPhase::Capture, self, cx);
3717 if !cx.propagate_event {
3718 break;
3719 }
3720 }
3721
3722 if cx.propagate_event {
3724 for listener in mouse_listeners.iter_mut().rev() {
3725 let listener = listener.as_mut().unwrap();
3726 listener(event, DispatchPhase::Bubble, self, cx);
3727 if !cx.propagate_event {
3728 break;
3729 }
3730 }
3731 }
3732
3733 self.rendered_frame.mouse_listeners = mouse_listeners;
3734
3735 if cx.has_active_drag() {
3736 if event.is::<MouseMoveEvent>() {
3737 self.refresh();
3740 } else if event.is::<MouseUpEvent>() {
3741 cx.active_drag = None;
3744 self.refresh();
3745 }
3746 }
3747 }
3748
3749 fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {
3750 if self.invalidator.is_dirty() {
3751 self.draw(cx).clear();
3752 }
3753
3754 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
3755 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
3756
3757 let mut keystroke: Option<Keystroke> = None;
3758
3759 if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {
3760 if event.modifiers.number_of_modifiers() == 0
3761 && self.pending_modifier.modifiers.number_of_modifiers() == 1
3762 && !self.pending_modifier.saw_keystroke
3763 {
3764 let key = match self.pending_modifier.modifiers {
3765 modifiers if modifiers.shift => Some("shift"),
3766 modifiers if modifiers.control => Some("control"),
3767 modifiers if modifiers.alt => Some("alt"),
3768 modifiers if modifiers.platform => Some("platform"),
3769 modifiers if modifiers.function => Some("function"),
3770 _ => None,
3771 };
3772 if let Some(key) = key {
3773 keystroke = Some(Keystroke {
3774 key: key.to_string(),
3775 key_char: None,
3776 modifiers: Modifiers::default(),
3777 });
3778 }
3779 }
3780
3781 if self.pending_modifier.modifiers.number_of_modifiers() == 0
3782 && event.modifiers.number_of_modifiers() == 1
3783 {
3784 self.pending_modifier.saw_keystroke = false
3785 }
3786 self.pending_modifier.modifiers = event.modifiers
3787 } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
3788 self.pending_modifier.saw_keystroke = true;
3789 keystroke = Some(key_down_event.keystroke.clone());
3790 }
3791
3792 let Some(keystroke) = keystroke else {
3793 self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
3794 return;
3795 };
3796
3797 cx.propagate_event = true;
3798 self.dispatch_keystroke_interceptors(event, self.context_stack(), cx);
3799 if !cx.propagate_event {
3800 self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
3801 return;
3802 }
3803
3804 let mut currently_pending = self.pending_input.take().unwrap_or_default();
3805 if currently_pending.focus.is_some() && currently_pending.focus != self.focus {
3806 currently_pending = PendingInput::default();
3807 }
3808
3809 let match_result = self.rendered_frame.dispatch_tree.dispatch_key(
3810 currently_pending.keystrokes,
3811 keystroke,
3812 &dispatch_path,
3813 );
3814
3815 if !match_result.to_replay.is_empty() {
3816 self.replay_pending_input(match_result.to_replay, cx);
3817 cx.propagate_event = true;
3818 }
3819
3820 if !match_result.pending.is_empty() {
3821 currently_pending.keystrokes = match_result.pending;
3822 currently_pending.focus = self.focus;
3823 currently_pending.timer = Some(self.spawn(cx, async move |cx| {
3824 cx.background_executor.timer(Duration::from_secs(1)).await;
3825 cx.update(move |window, cx| {
3826 let Some(currently_pending) = window
3827 .pending_input
3828 .take()
3829 .filter(|pending| pending.focus == window.focus)
3830 else {
3831 return;
3832 };
3833
3834 let node_id = window.focus_node_id_in_rendered_frame(window.focus);
3835 let dispatch_path = window.rendered_frame.dispatch_tree.dispatch_path(node_id);
3836
3837 let to_replay = window
3838 .rendered_frame
3839 .dispatch_tree
3840 .flush_dispatch(currently_pending.keystrokes, &dispatch_path);
3841
3842 window.pending_input_changed(cx);
3843 window.replay_pending_input(to_replay, cx)
3844 })
3845 .log_err();
3846 }));
3847 self.pending_input = Some(currently_pending);
3848 self.pending_input_changed(cx);
3849 cx.propagate_event = false;
3850 return;
3851 }
3852
3853 for binding in match_result.bindings {
3854 self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
3855 if !cx.propagate_event {
3856 self.dispatch_keystroke_observers(
3857 event,
3858 Some(binding.action),
3859 match_result.context_stack,
3860 cx,
3861 );
3862 self.pending_input_changed(cx);
3863 return;
3864 }
3865 }
3866
3867 self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);
3868 self.pending_input_changed(cx);
3869 }
3870
3871 fn finish_dispatch_key_event(
3872 &mut self,
3873 event: &dyn Any,
3874 dispatch_path: SmallVec<[DispatchNodeId; 32]>,
3875 context_stack: Vec<KeyContext>,
3876 cx: &mut App,
3877 ) {
3878 self.dispatch_key_down_up_event(event, &dispatch_path, cx);
3879 if !cx.propagate_event {
3880 return;
3881 }
3882
3883 self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);
3884 if !cx.propagate_event {
3885 return;
3886 }
3887
3888 self.dispatch_keystroke_observers(event, None, context_stack, cx);
3889 }
3890
3891 fn pending_input_changed(&mut self, cx: &mut App) {
3892 self.pending_input_observers
3893 .clone()
3894 .retain(&(), |callback| callback(self, cx));
3895 }
3896
3897 fn dispatch_key_down_up_event(
3898 &mut self,
3899 event: &dyn Any,
3900 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
3901 cx: &mut App,
3902 ) {
3903 for node_id in dispatch_path {
3905 let node = self.rendered_frame.dispatch_tree.node(*node_id);
3906
3907 for key_listener in node.key_listeners.clone() {
3908 key_listener(event, DispatchPhase::Capture, self, cx);
3909 if !cx.propagate_event {
3910 return;
3911 }
3912 }
3913 }
3914
3915 for node_id in dispatch_path.iter().rev() {
3917 let node = self.rendered_frame.dispatch_tree.node(*node_id);
3919 for key_listener in node.key_listeners.clone() {
3920 key_listener(event, DispatchPhase::Bubble, self, cx);
3921 if !cx.propagate_event {
3922 return;
3923 }
3924 }
3925 }
3926 }
3927
3928 fn dispatch_modifiers_changed_event(
3929 &mut self,
3930 event: &dyn Any,
3931 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
3932 cx: &mut App,
3933 ) {
3934 let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {
3935 return;
3936 };
3937 for node_id in dispatch_path.iter().rev() {
3938 let node = self.rendered_frame.dispatch_tree.node(*node_id);
3939 for listener in node.modifiers_changed_listeners.clone() {
3940 listener(event, self, cx);
3941 if !cx.propagate_event {
3942 return;
3943 }
3944 }
3945 }
3946 }
3947
3948 pub fn has_pending_keystrokes(&self) -> bool {
3950 self.pending_input.is_some()
3951 }
3952
3953 pub(crate) fn clear_pending_keystrokes(&mut self) {
3954 self.pending_input.take();
3955 }
3956
3957 pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {
3959 self.pending_input
3960 .as_ref()
3961 .map(|pending_input| pending_input.keystrokes.as_slice())
3962 }
3963
3964 fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {
3965 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
3966 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
3967
3968 'replay: for replay in replays {
3969 let event = KeyDownEvent {
3970 keystroke: replay.keystroke.clone(),
3971 is_held: false,
3972 };
3973
3974 cx.propagate_event = true;
3975 for binding in replay.bindings {
3976 self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
3977 if !cx.propagate_event {
3978 self.dispatch_keystroke_observers(
3979 &event,
3980 Some(binding.action),
3981 Vec::default(),
3982 cx,
3983 );
3984 continue 'replay;
3985 }
3986 }
3987
3988 self.dispatch_key_down_up_event(&event, &dispatch_path, cx);
3989 if !cx.propagate_event {
3990 continue 'replay;
3991 }
3992 if let Some(input) = replay.keystroke.key_char.as_ref().cloned()
3993 && let Some(mut input_handler) = self.platform_window.take_input_handler()
3994 {
3995 input_handler.dispatch_input(&input, self, cx);
3996 self.platform_window.set_input_handler(input_handler)
3997 }
3998 }
3999 }
4000
4001 fn focus_node_id_in_rendered_frame(&self, focus_id: Option<FocusId>) -> DispatchNodeId {
4002 focus_id
4003 .and_then(|focus_id| {
4004 self.rendered_frame
4005 .dispatch_tree
4006 .focusable_node_id(focus_id)
4007 })
4008 .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id())
4009 }
4010
4011 fn dispatch_action_on_node(
4012 &mut self,
4013 node_id: DispatchNodeId,
4014 action: &dyn Action,
4015 cx: &mut App,
4016 ) {
4017 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4018
4019 cx.propagate_event = true;
4021 if let Some(mut global_listeners) = cx
4022 .global_action_listeners
4023 .remove(&action.as_any().type_id())
4024 {
4025 for listener in &global_listeners {
4026 listener(action.as_any(), DispatchPhase::Capture, cx);
4027 if !cx.propagate_event {
4028 break;
4029 }
4030 }
4031
4032 global_listeners.extend(
4033 cx.global_action_listeners
4034 .remove(&action.as_any().type_id())
4035 .unwrap_or_default(),
4036 );
4037
4038 cx.global_action_listeners
4039 .insert(action.as_any().type_id(), global_listeners);
4040 }
4041
4042 if !cx.propagate_event {
4043 return;
4044 }
4045
4046 for node_id in &dispatch_path {
4048 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4049 for DispatchActionListener {
4050 action_type,
4051 listener,
4052 } in node.action_listeners.clone()
4053 {
4054 let any_action = action.as_any();
4055 if action_type == any_action.type_id() {
4056 listener(any_action, DispatchPhase::Capture, self, cx);
4057
4058 if !cx.propagate_event {
4059 return;
4060 }
4061 }
4062 }
4063 }
4064
4065 for node_id in dispatch_path.iter().rev() {
4067 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4068 for DispatchActionListener {
4069 action_type,
4070 listener,
4071 } in node.action_listeners.clone()
4072 {
4073 let any_action = action.as_any();
4074 if action_type == any_action.type_id() {
4075 cx.propagate_event = false; listener(any_action, DispatchPhase::Bubble, self, cx);
4077
4078 if !cx.propagate_event {
4079 return;
4080 }
4081 }
4082 }
4083 }
4084
4085 if let Some(mut global_listeners) = cx
4087 .global_action_listeners
4088 .remove(&action.as_any().type_id())
4089 {
4090 for listener in global_listeners.iter().rev() {
4091 cx.propagate_event = false; listener(action.as_any(), DispatchPhase::Bubble, cx);
4094 if !cx.propagate_event {
4095 break;
4096 }
4097 }
4098
4099 global_listeners.extend(
4100 cx.global_action_listeners
4101 .remove(&action.as_any().type_id())
4102 .unwrap_or_default(),
4103 );
4104
4105 cx.global_action_listeners
4106 .insert(action.as_any().type_id(), global_listeners);
4107 }
4108 }
4109
4110 pub fn observe_global<G: Global>(
4113 &mut self,
4114 cx: &mut App,
4115 f: impl Fn(&mut Window, &mut App) + 'static,
4116 ) -> Subscription {
4117 let window_handle = self.handle;
4118 let (subscription, activate) = cx.global_observers.insert(
4119 TypeId::of::<G>(),
4120 Box::new(move |cx| {
4121 window_handle
4122 .update(cx, |_, window, cx| f(window, cx))
4123 .is_ok()
4124 }),
4125 );
4126 cx.defer(move |_| activate());
4127 subscription
4128 }
4129
4130 pub fn activate_window(&self) {
4132 self.platform_window.activate();
4133 }
4134
4135 pub fn minimize_window(&self) {
4137 self.platform_window.minimize();
4138 }
4139
4140 pub fn show_window(&self) {
4142 self.platform_window.show();
4143 }
4144
4145 pub fn hide_window(&self) {
4147 self.platform_window.hide();
4148 }
4149
4150 pub fn is_window_visible(&self) -> bool {
4152 self.platform_window.is_visible()
4153 }
4154
4155 pub fn set_mouse_passthrough(&self, passthrough: bool) {
4157 self.platform_window.set_mouse_passthrough(passthrough);
4158 }
4159
4160 pub fn toggle_fullscreen(&self) {
4162 self.platform_window.toggle_fullscreen();
4163 }
4164
4165 pub fn set_progress_bar(&self, state: ProgressBarState) {
4167 self.platform_window.set_progress_bar(state);
4168 }
4169
4170 pub fn window_state(&self) -> WindowState {
4172 let bounds = self.platform_window.window_bounds();
4173 let display_id = self.platform_window.display().map(|d| d.id());
4174 let fullscreen = self.platform_window.is_fullscreen();
4175 WindowState {
4176 bounds,
4177 display_id,
4178 fullscreen,
4179 }
4180 }
4181
4182 pub fn restore_window_state(&self, state: &WindowState) {
4188 let is_fullscreen = self.platform_window.is_fullscreen();
4189 if state.fullscreen != is_fullscreen {
4190 self.platform_window.toggle_fullscreen();
4191 }
4192 }
4193
4194 pub fn invalidate_character_coordinates(&self) {
4196 self.on_next_frame(|window, cx| {
4197 if let Some(mut input_handler) = window.platform_window.take_input_handler() {
4198 if let Some(bounds) = input_handler.selected_bounds(window, cx) {
4199 window.platform_window.update_ime_position(bounds);
4200 }
4201 window.platform_window.set_input_handler(input_handler);
4202 }
4203 });
4204 }
4205
4206 pub fn prompt<T>(
4210 &mut self,
4211 level: PromptLevel,
4212 message: &str,
4213 detail: Option<&str>,
4214 answers: &[T],
4215 cx: &mut App,
4216 ) -> oneshot::Receiver<usize>
4217 where
4218 T: Clone + Into<PromptButton>,
4219 {
4220 let prompt_builder = cx.prompt_builder.take();
4221 let Some(prompt_builder) = prompt_builder else {
4222 unreachable!("Re-entrant window prompting is not supported by GPUI");
4223 };
4224
4225 let answers = answers
4226 .iter()
4227 .map(|answer| answer.clone().into())
4228 .collect::<Vec<_>>();
4229
4230 let receiver = match &prompt_builder {
4231 PromptBuilder::Default => self
4232 .platform_window
4233 .prompt(level, message, detail, &answers)
4234 .unwrap_or_else(|| {
4235 self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
4236 }),
4237 PromptBuilder::Custom(_) => {
4238 self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
4239 }
4240 };
4241
4242 cx.prompt_builder = Some(prompt_builder);
4243
4244 receiver
4245 }
4246
4247 fn build_custom_prompt(
4248 &mut self,
4249 prompt_builder: &PromptBuilder,
4250 level: PromptLevel,
4251 message: &str,
4252 detail: Option<&str>,
4253 answers: &[PromptButton],
4254 cx: &mut App,
4255 ) -> oneshot::Receiver<usize> {
4256 let (sender, receiver) = oneshot::channel();
4257 let handle = PromptHandle::new(sender);
4258 let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);
4259 self.prompt = Some(handle);
4260 receiver
4261 }
4262
4263 pub fn context_stack(&self) -> Vec<KeyContext> {
4265 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4266 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4267 dispatch_tree
4268 .dispatch_path(node_id)
4269 .iter()
4270 .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())
4271 .collect()
4272 }
4273
4274 pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {
4276 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4277 let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);
4278 for action_type in cx.global_action_listeners.keys() {
4279 if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {
4280 let action = cx.actions.build_action_type(action_type).ok();
4281 if let Some(action) = action {
4282 actions.insert(ix, action);
4283 }
4284 }
4285 }
4286 actions
4287 }
4288
4289 pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
4292 self.rendered_frame
4293 .dispatch_tree
4294 .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)
4295 }
4296
4297 pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option<KeyBinding> {
4300 self.rendered_frame
4301 .dispatch_tree
4302 .highest_precedence_binding_for_action(
4303 action,
4304 &self.rendered_frame.dispatch_tree.context_stack,
4305 )
4306 }
4307
4308 pub fn bindings_for_action_in_context(
4310 &self,
4311 action: &dyn Action,
4312 context: KeyContext,
4313 ) -> Vec<KeyBinding> {
4314 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4315 dispatch_tree.bindings_for_action(action, &[context])
4316 }
4317
4318 pub fn highest_precedence_binding_for_action_in_context(
4321 &self,
4322 action: &dyn Action,
4323 context: KeyContext,
4324 ) -> Option<KeyBinding> {
4325 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4326 dispatch_tree.highest_precedence_binding_for_action(action, &[context])
4327 }
4328
4329 pub fn bindings_for_action_in(
4333 &self,
4334 action: &dyn Action,
4335 focus_handle: &FocusHandle,
4336 ) -> Vec<KeyBinding> {
4337 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4338 let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else {
4339 return vec![];
4340 };
4341 dispatch_tree.bindings_for_action(action, &context_stack)
4342 }
4343
4344 pub fn highest_precedence_binding_for_action_in(
4348 &self,
4349 action: &dyn Action,
4350 focus_handle: &FocusHandle,
4351 ) -> Option<KeyBinding> {
4352 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4353 let context_stack = self.context_stack_for_focus_handle(focus_handle)?;
4354 dispatch_tree.highest_precedence_binding_for_action(action, &context_stack)
4355 }
4356
4357 fn context_stack_for_focus_handle(
4358 &self,
4359 focus_handle: &FocusHandle,
4360 ) -> Option<Vec<KeyContext>> {
4361 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4362 let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?;
4363 let context_stack: Vec<_> = dispatch_tree
4364 .dispatch_path(node_id)
4365 .into_iter()
4366 .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
4367 .collect();
4368 Some(context_stack)
4369 }
4370
4371 pub fn listener_for<V: Render, E>(
4373 &self,
4374 view: &Entity<V>,
4375 f: impl Fn(&mut V, &E, &mut Window, &mut Context<V>) + 'static,
4376 ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
4377 let view = view.downgrade();
4378 move |e: &E, window: &mut Window, cx: &mut App| {
4379 view.update(cx, |view, cx| f(view, e, window, cx)).ok();
4380 }
4381 }
4382
4383 pub fn handler_for<V: Render, Callback: Fn(&mut V, &mut Window, &mut Context<V>) + 'static>(
4385 &self,
4386 view: &Entity<V>,
4387 f: Callback,
4388 ) -> impl Fn(&mut Window, &mut App) + use<V, Callback> {
4389 let view = view.downgrade();
4390 move |window: &mut Window, cx: &mut App| {
4391 view.update(cx, |view, cx| f(view, window, cx)).ok();
4392 }
4393 }
4394
4395 pub fn on_window_should_close(
4398 &self,
4399 cx: &App,
4400 f: impl Fn(&mut Window, &mut App) -> bool + 'static,
4401 ) {
4402 let mut cx = self.to_async(cx);
4403 self.platform_window.on_should_close(Box::new(move || {
4404 cx.update(|window, cx| f(window, cx)).unwrap_or(true)
4405 }))
4406 }
4407
4408 pub fn on_action(
4415 &mut self,
4416 action_type: TypeId,
4417 listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
4418 ) {
4419 self.next_frame
4420 .dispatch_tree
4421 .on_action(action_type, Rc::new(listener));
4422 }
4423
4424 pub fn on_action_when(
4431 &mut self,
4432 condition: bool,
4433 action_type: TypeId,
4434 listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
4435 ) {
4436 if condition {
4437 self.next_frame
4438 .dispatch_tree
4439 .on_action(action_type, Rc::new(listener));
4440 }
4441 }
4442
4443 pub fn gpu_specs(&self) -> Option<GpuSpecs> {
4446 self.platform_window.gpu_specs()
4447 }
4448
4449 pub fn titlebar_double_click(&self) {
4452 self.platform_window.titlebar_double_click();
4453 }
4454
4455 pub fn window_title(&self) -> String {
4458 self.platform_window.get_title()
4459 }
4460
4461 pub fn tabbed_windows(&self) -> Option<Vec<SystemWindowTab>> {
4464 self.platform_window.tabbed_windows()
4465 }
4466
4467 pub fn tab_bar_visible(&self) -> bool {
4470 self.platform_window.tab_bar_visible()
4471 }
4472
4473 pub fn merge_all_windows(&self) {
4476 self.platform_window.merge_all_windows()
4477 }
4478
4479 pub fn move_tab_to_new_window(&self) {
4482 self.platform_window.move_tab_to_new_window()
4483 }
4484
4485 pub fn toggle_window_tab_overview(&self) {
4488 self.platform_window.toggle_window_tab_overview()
4489 }
4490
4491 pub fn set_tabbing_identifier(&self, tabbing_identifier: Option<String>) {
4494 self.platform_window
4495 .set_tabbing_identifier(tabbing_identifier)
4496 }
4497
4498 #[cfg(any(feature = "inspector", debug_assertions))]
4500 pub fn toggle_inspector(&mut self, cx: &mut App) {
4501 self.inspector = match self.inspector {
4502 None => Some(cx.new(|_| Inspector::new())),
4503 Some(_) => None,
4504 };
4505 self.refresh();
4506 }
4507
4508 pub fn is_inspector_picking(&self, _cx: &App) -> bool {
4510 #[cfg(any(feature = "inspector", debug_assertions))]
4511 {
4512 if let Some(inspector) = &self.inspector {
4513 return inspector.read(_cx).is_picking();
4514 }
4515 }
4516 false
4517 }
4518
4519 #[cfg(any(feature = "inspector", debug_assertions))]
4521 pub fn with_inspector_state<T: 'static, R>(
4522 &mut self,
4523 _inspector_id: Option<&crate::InspectorElementId>,
4524 cx: &mut App,
4525 f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
4526 ) -> R {
4527 if let Some(inspector_id) = _inspector_id
4528 && let Some(inspector) = &self.inspector
4529 {
4530 let inspector = inspector.clone();
4531 let active_element_id = inspector.read(cx).active_element_id();
4532 if Some(inspector_id) == active_element_id {
4533 return inspector.update(cx, |inspector, _cx| {
4534 inspector.with_active_element_state(self, f)
4535 });
4536 }
4537 }
4538 f(&mut None, self)
4539 }
4540
4541 #[cfg(any(feature = "inspector", debug_assertions))]
4542 pub(crate) fn build_inspector_element_id(
4543 &mut self,
4544 path: crate::InspectorElementPath,
4545 ) -> crate::InspectorElementId {
4546 self.invalidator.debug_assert_paint_or_prepaint();
4547 let path = Rc::new(path);
4548 let next_instance_id = self
4549 .next_frame
4550 .next_inspector_instance_ids
4551 .entry(path.clone())
4552 .or_insert(0);
4553 let instance_id = *next_instance_id;
4554 *next_instance_id += 1;
4555 crate::InspectorElementId { path, instance_id }
4556 }
4557
4558 #[cfg(any(feature = "inspector", debug_assertions))]
4559 fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option<AnyElement> {
4560 if let Some(inspector) = self.inspector.take() {
4561 let mut inspector_element = AnyView::from(inspector.clone()).into_any_element();
4562 inspector_element.prepaint_as_root(
4563 point(self.viewport_size.width - inspector_width, px(0.0)),
4564 size(inspector_width, self.viewport_size.height).into(),
4565 self,
4566 cx,
4567 );
4568 self.inspector = Some(inspector);
4569 Some(inspector_element)
4570 } else {
4571 None
4572 }
4573 }
4574
4575 #[cfg(any(feature = "inspector", debug_assertions))]
4576 fn paint_inspector(&mut self, mut inspector_element: Option<AnyElement>, cx: &mut App) {
4577 if let Some(mut inspector_element) = inspector_element {
4578 inspector_element.paint(self, cx);
4579 };
4580 }
4581
4582 #[cfg(any(feature = "inspector", debug_assertions))]
4585 pub fn insert_inspector_hitbox(
4586 &mut self,
4587 hitbox_id: HitboxId,
4588 inspector_id: Option<&crate::InspectorElementId>,
4589 cx: &App,
4590 ) {
4591 self.invalidator.debug_assert_paint_or_prepaint();
4592 if !self.is_inspector_picking(cx) {
4593 return;
4594 }
4595 if let Some(inspector_id) = inspector_id {
4596 self.next_frame
4597 .inspector_hitboxes
4598 .insert(hitbox_id, inspector_id.clone());
4599 }
4600 }
4601
4602 #[cfg(any(feature = "inspector", debug_assertions))]
4603 fn paint_inspector_hitbox(&mut self, cx: &App) {
4604 if let Some(inspector) = self.inspector.as_ref() {
4605 let inspector = inspector.read(cx);
4606 if let Some((hitbox_id, _)) = self.hovered_inspector_hitbox(inspector, &self.next_frame)
4607 && let Some(hitbox) = self
4608 .next_frame
4609 .hitboxes
4610 .iter()
4611 .find(|hitbox| hitbox.id == hitbox_id)
4612 {
4613 self.paint_quad(crate::fill(hitbox.bounds, crate::rgba(0x61afef4d)));
4614 }
4615 }
4616 }
4617
4618 #[cfg(any(feature = "inspector", debug_assertions))]
4619 fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
4620 let Some(inspector) = self.inspector.clone() else {
4621 return;
4622 };
4623 if event.downcast_ref::<MouseMoveEvent>().is_some() {
4624 inspector.update(cx, |inspector, _cx| {
4625 if let Some((_, inspector_id)) =
4626 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
4627 {
4628 inspector.hover(inspector_id, self);
4629 }
4630 });
4631 } else if event.downcast_ref::<crate::MouseDownEvent>().is_some() {
4632 inspector.update(cx, |inspector, _cx| {
4633 if let Some((_, inspector_id)) =
4634 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
4635 {
4636 inspector.select(inspector_id, self);
4637 }
4638 });
4639 } else if let Some(event) = event.downcast_ref::<crate::ScrollWheelEvent>() {
4640 const SCROLL_LINES: f32 = 3.0;
4642 const SCROLL_PIXELS_PER_LAYER: f32 = 36.0;
4643 let delta_y = event
4644 .delta
4645 .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES))
4646 .y;
4647 if let Some(inspector) = self.inspector.clone() {
4648 inspector.update(cx, |inspector, _cx| {
4649 if let Some(depth) = inspector.pick_depth.as_mut() {
4650 *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER;
4651 let max_depth = self.mouse_hit_test.ids.len() as f32 - 0.5;
4652 if *depth < 0.0 {
4653 *depth = 0.0;
4654 } else if *depth > max_depth {
4655 *depth = max_depth;
4656 }
4657 if let Some((_, inspector_id)) =
4658 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
4659 {
4660 inspector.set_active_element_id(inspector_id, self);
4661 }
4662 }
4663 });
4664 }
4665 }
4666 }
4667
4668 #[cfg(any(feature = "inspector", debug_assertions))]
4669 fn hovered_inspector_hitbox(
4670 &self,
4671 inspector: &Inspector,
4672 frame: &Frame,
4673 ) -> Option<(HitboxId, crate::InspectorElementId)> {
4674 if let Some(pick_depth) = inspector.pick_depth {
4675 let depth = (pick_depth as i64).try_into().unwrap_or(0);
4676 let max_skipped = self.mouse_hit_test.ids.len().saturating_sub(1);
4677 let skip_count = (depth as usize).min(max_skipped);
4678 for hitbox_id in self.mouse_hit_test.ids.iter().skip(skip_count) {
4679 if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) {
4680 return Some((*hitbox_id, inspector_id.clone()));
4681 }
4682 }
4683 }
4684 None
4685 }
4686
4687 #[cfg(any(test, feature = "test-support"))]
4690 pub fn set_modifiers(&mut self, modifiers: Modifiers) {
4691 self.modifiers = modifiers;
4692 }
4693}
4694
4695slotmap::new_key_type! {
4697 pub struct WindowId;
4699}
4700
4701impl WindowId {
4702 pub fn as_u64(&self) -> u64 {
4704 self.0.as_ffi()
4705 }
4706}
4707
4708impl From<u64> for WindowId {
4709 fn from(value: u64) -> Self {
4710 WindowId(slotmap::KeyData::from_ffi(value))
4711 }
4712}
4713
4714#[derive(Deref, DerefMut)]
4717pub struct WindowHandle<V> {
4718 #[deref]
4719 #[deref_mut]
4720 pub(crate) any_handle: AnyWindowHandle,
4721 state_type: PhantomData<V>,
4722}
4723
4724impl<V> Debug for WindowHandle<V> {
4725 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4726 f.debug_struct("WindowHandle")
4727 .field("any_handle", &self.any_handle.id.as_u64())
4728 .finish()
4729 }
4730}
4731
4732impl<V: 'static + Render> WindowHandle<V> {
4733 pub fn new(id: WindowId) -> Self {
4736 WindowHandle {
4737 any_handle: AnyWindowHandle {
4738 id,
4739 state_type: TypeId::of::<V>(),
4740 },
4741 state_type: PhantomData,
4742 }
4743 }
4744
4745 #[cfg(any(test, feature = "test-support"))]
4749 pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>
4750 where
4751 C: AppContext,
4752 {
4753 crate::Flatten::flatten(cx.update_window(self.any_handle, |root_view, _, _| {
4754 root_view
4755 .downcast::<V>()
4756 .map_err(|_| anyhow!("the type of the window's root view has changed"))
4757 }))
4758 }
4759
4760 pub fn update<C, R>(
4764 &self,
4765 cx: &mut C,
4766 update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
4767 ) -> Result<R>
4768 where
4769 C: AppContext,
4770 {
4771 cx.update_window(self.any_handle, |root_view, window, cx| {
4772 let view = root_view
4773 .downcast::<V>()
4774 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
4775
4776 Ok(view.update(cx, |view, cx| update(view, window, cx)))
4777 })?
4778 }
4779
4780 pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {
4784 let x = cx
4785 .windows
4786 .get(self.id)
4787 .and_then(|window| {
4788 window
4789 .as_ref()
4790 .and_then(|window| window.root.clone())
4791 .map(|root_view| root_view.downcast::<V>())
4792 })
4793 .context("window not found")?
4794 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
4795
4796 Ok(x.read(cx))
4797 }
4798
4799 pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>
4803 where
4804 C: AppContext,
4805 {
4806 cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
4807 }
4808
4809 pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>
4813 where
4814 C: AppContext,
4815 {
4816 cx.read_window(self, |root_view, _cx| root_view)
4817 }
4818
4819 pub fn is_active(&self, cx: &mut App) -> Option<bool> {
4824 cx.update_window(self.any_handle, |_, window, _| window.is_window_active())
4825 .ok()
4826 }
4827}
4828
4829impl<V> Copy for WindowHandle<V> {}
4830
4831impl<V> Clone for WindowHandle<V> {
4832 fn clone(&self) -> Self {
4833 *self
4834 }
4835}
4836
4837impl<V> PartialEq for WindowHandle<V> {
4838 fn eq(&self, other: &Self) -> bool {
4839 self.any_handle == other.any_handle
4840 }
4841}
4842
4843impl<V> Eq for WindowHandle<V> {}
4844
4845impl<V> Hash for WindowHandle<V> {
4846 fn hash<H: Hasher>(&self, state: &mut H) {
4847 self.any_handle.hash(state);
4848 }
4849}
4850
4851impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
4852 fn from(val: WindowHandle<V>) -> Self {
4853 val.any_handle
4854 }
4855}
4856
4857unsafe impl<V> Send for WindowHandle<V> {}
4858unsafe impl<V> Sync for WindowHandle<V> {}
4859
4860#[derive(Copy, Clone, PartialEq, Eq, Hash)]
4862pub struct AnyWindowHandle {
4863 pub(crate) id: WindowId,
4864 state_type: TypeId,
4865}
4866
4867impl AnyWindowHandle {
4868 pub fn window_id(&self) -> WindowId {
4870 self.id
4871 }
4872
4873 pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
4876 if TypeId::of::<T>() == self.state_type {
4877 Some(WindowHandle {
4878 any_handle: *self,
4879 state_type: PhantomData,
4880 })
4881 } else {
4882 None
4883 }
4884 }
4885
4886 pub fn update<C, R>(
4890 self,
4891 cx: &mut C,
4892 update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
4893 ) -> Result<R>
4894 where
4895 C: AppContext,
4896 {
4897 cx.update_window(self, update)
4898 }
4899
4900 pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>
4904 where
4905 C: AppContext,
4906 T: 'static,
4907 {
4908 let view = self
4909 .downcast::<T>()
4910 .context("the type of the window's root view has changed")?;
4911
4912 cx.read_window(&view, read)
4913 }
4914}
4915
4916impl HasWindowHandle for Window {
4917 fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {
4918 self.platform_window.window_handle()
4919 }
4920}
4921
4922impl HasDisplayHandle for Window {
4923 fn display_handle(
4924 &self,
4925 ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, HandleError> {
4926 self.platform_window.display_handle()
4927 }
4928}
4929
4930#[derive(Clone, Debug, Eq, PartialEq, Hash)]
4935pub enum ElementId {
4936 View(EntityId),
4938 Integer(u64),
4940 Name(SharedString),
4942 Uuid(Uuid),
4944 FocusHandle(FocusId),
4946 NamedInteger(SharedString, u64),
4948 Path(Arc<std::path::Path>),
4950 CodeLocation(core::panic::Location<'static>),
4952 NamedChild(Box<ElementId>, SharedString),
4954}
4955
4956impl ElementId {
4957 pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {
4959 Self::NamedInteger(name.into(), integer as u64)
4960 }
4961}
4962
4963impl Display for ElementId {
4964 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4965 match self {
4966 ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
4967 ElementId::Integer(ix) => write!(f, "{}", ix)?,
4968 ElementId::Name(name) => write!(f, "{}", name)?,
4969 ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
4970 ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
4971 ElementId::Uuid(uuid) => write!(f, "{}", uuid)?,
4972 ElementId::Path(path) => write!(f, "{}", path.display())?,
4973 ElementId::CodeLocation(location) => write!(f, "{}", location)?,
4974 ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?,
4975 }
4976
4977 Ok(())
4978 }
4979}
4980
4981impl TryInto<SharedString> for ElementId {
4982 type Error = anyhow::Error;
4983
4984 fn try_into(self) -> anyhow::Result<SharedString> {
4985 if let ElementId::Name(name) = self {
4986 Ok(name)
4987 } else {
4988 anyhow::bail!("element id is not string")
4989 }
4990 }
4991}
4992
4993impl From<usize> for ElementId {
4994 fn from(id: usize) -> Self {
4995 ElementId::Integer(id as u64)
4996 }
4997}
4998
4999impl From<i32> for ElementId {
5000 fn from(id: i32) -> Self {
5001 Self::Integer(id as u64)
5002 }
5003}
5004
5005impl From<SharedString> for ElementId {
5006 fn from(name: SharedString) -> Self {
5007 ElementId::Name(name)
5008 }
5009}
5010
5011impl From<Arc<std::path::Path>> for ElementId {
5012 fn from(path: Arc<std::path::Path>) -> Self {
5013 ElementId::Path(path)
5014 }
5015}
5016
5017impl From<&'static str> for ElementId {
5018 fn from(name: &'static str) -> Self {
5019 ElementId::Name(name.into())
5020 }
5021}
5022
5023impl<'a> From<&'a FocusHandle> for ElementId {
5024 fn from(handle: &'a FocusHandle) -> Self {
5025 ElementId::FocusHandle(handle.id)
5026 }
5027}
5028
5029impl From<(&'static str, EntityId)> for ElementId {
5030 fn from((name, id): (&'static str, EntityId)) -> Self {
5031 ElementId::NamedInteger(name.into(), id.as_u64())
5032 }
5033}
5034
5035impl From<(&'static str, usize)> for ElementId {
5036 fn from((name, id): (&'static str, usize)) -> Self {
5037 ElementId::NamedInteger(name.into(), id as u64)
5038 }
5039}
5040
5041impl From<(SharedString, usize)> for ElementId {
5042 fn from((name, id): (SharedString, usize)) -> Self {
5043 ElementId::NamedInteger(name, id as u64)
5044 }
5045}
5046
5047impl From<(&'static str, u64)> for ElementId {
5048 fn from((name, id): (&'static str, u64)) -> Self {
5049 ElementId::NamedInteger(name.into(), id)
5050 }
5051}
5052
5053impl From<Uuid> for ElementId {
5054 fn from(value: Uuid) -> Self {
5055 Self::Uuid(value)
5056 }
5057}
5058
5059impl From<(&'static str, u32)> for ElementId {
5060 fn from((name, id): (&'static str, u32)) -> Self {
5061 ElementId::NamedInteger(name.into(), id.into())
5062 }
5063}
5064
5065impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
5066 fn from((id, name): (ElementId, T)) -> Self {
5067 ElementId::NamedChild(Box::new(id), name.into())
5068 }
5069}
5070
5071impl From<&'static core::panic::Location<'static>> for ElementId {
5072 fn from(location: &'static core::panic::Location<'static>) -> Self {
5073 ElementId::CodeLocation(*location)
5074 }
5075}
5076
5077#[derive(Clone)]
5080pub struct PaintQuad {
5081 pub bounds: Bounds<Pixels>,
5083 pub corner_radii: Corners<Pixels>,
5085 pub background: Background,
5087 pub border_widths: Edges<Pixels>,
5089 pub border_color: Hsla,
5091 pub border_style: BorderStyle,
5093 pub continuous_corners: bool,
5095 pub transform: TransformationMatrix,
5097 pub blend_mode: BlendMode,
5099}
5100
5101impl PaintQuad {
5102 pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
5104 PaintQuad {
5105 corner_radii: corner_radii.into(),
5106 ..self
5107 }
5108 }
5109
5110 pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
5112 PaintQuad {
5113 border_widths: border_widths.into(),
5114 ..self
5115 }
5116 }
5117
5118 pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
5120 PaintQuad {
5121 border_color: border_color.into(),
5122 ..self
5123 }
5124 }
5125
5126 pub fn background(self, background: impl Into<Background>) -> Self {
5128 PaintQuad {
5129 background: background.into(),
5130 ..self
5131 }
5132 }
5133}
5134
5135pub fn quad(
5137 bounds: Bounds<Pixels>,
5138 corner_radii: impl Into<Corners<Pixels>>,
5139 background: impl Into<Background>,
5140 border_widths: impl Into<Edges<Pixels>>,
5141 border_color: impl Into<Hsla>,
5142 border_style: BorderStyle,
5143) -> PaintQuad {
5144 PaintQuad {
5145 bounds,
5146 corner_radii: corner_radii.into(),
5147 background: background.into(),
5148 border_widths: border_widths.into(),
5149 border_color: border_color.into(),
5150 border_style,
5151 continuous_corners: false,
5152 transform: TransformationMatrix::unit(),
5153 blend_mode: BlendMode::Normal,
5154 }
5155}
5156
5157pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
5159 PaintQuad {
5160 bounds: bounds.into(),
5161 corner_radii: (0.).into(),
5162 background: background.into(),
5163 border_widths: (0.).into(),
5164 border_color: transparent_black(),
5165 border_style: BorderStyle::default(),
5166 continuous_corners: false,
5167 transform: TransformationMatrix::unit(),
5168 blend_mode: BlendMode::Normal,
5169 }
5170}
5171
5172pub fn outline(
5174 bounds: impl Into<Bounds<Pixels>>,
5175 border_color: impl Into<Hsla>,
5176 border_style: BorderStyle,
5177) -> PaintQuad {
5178 PaintQuad {
5179 bounds: bounds.into(),
5180 corner_radii: (0.).into(),
5181 background: transparent_black().into(),
5182 border_widths: (1.).into(),
5183 border_color: border_color.into(),
5184 border_style,
5185 continuous_corners: false,
5186 transform: TransformationMatrix::unit(),
5187 blend_mode: BlendMode::Normal,
5188 }
5189}