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, BackdropBlur, 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, Priority, PromptButton,
13 PromptLevel, Quad, Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams,
14 Replay, ResizeEdge, SMOOTH_SVG_SCALE_FACTOR, SUBPIXEL_VARIANTS_X, SUBPIXEL_VARIANTS_Y,
15 ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet,
16 Subscription, SystemWindowTab, SystemWindowTabController, TabStopMap, TaffyLayoutEngine, Task,
17 TextStyle, TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle,
18 WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations,
19 WindowOptions, WindowParams, WindowTextSystem, point, prelude::*, px, rems, size,
20 transparent_black,
21};
22use anyhow::{Context as _, Result, anyhow};
23use collections::{FxHashMap, FxHashSet};
24#[cfg(target_os = "macos")]
25use core_video::pixel_buffer::CVPixelBuffer;
26use derive_more::{Deref, DerefMut};
27use futures::FutureExt;
28use futures::channel::oneshot;
29use itertools::FoldWhile::{Continue, Done};
30use itertools::Itertools;
31use parking_lot::RwLock;
32use raw_window_handle::{HandleError, HasDisplayHandle, HasWindowHandle};
33use refineable::Refineable;
34use slotmap::SlotMap;
35use smallvec::SmallVec;
36use std::{
37 any::{Any, TypeId},
38 borrow::Cow,
39 cell::{Cell, RefCell},
40 cmp,
41 fmt::{Debug, Display},
42 hash::{Hash, Hasher},
43 marker::PhantomData,
44 mem,
45 ops::{DerefMut, Range},
46 rc::Rc,
47 sync::{
48 Arc, Weak,
49 atomic::{AtomicUsize, Ordering::SeqCst},
50 },
51 time::{Duration, Instant},
52};
53use util::post_inc;
54use util::{ResultExt, measure};
55use uuid::Uuid;
56
57mod prompts;
58
59use crate::util::atomic_incr_if_not_zero;
60pub use prompts::*;
61
62pub(crate) const DEFAULT_WINDOW_SIZE: Size<Pixels> = size(px(1536.), px(864.));
63
64pub const DEFAULT_ADDITIONAL_WINDOW_SIZE: Size<Pixels> = Size {
67 width: Pixels(900.),
68 height: Pixels(750.),
69};
70
71#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
73pub enum DispatchPhase {
74 #[default]
79 Bubble,
80 Capture,
86}
87
88impl DispatchPhase {
89 #[inline]
91 pub fn bubble(self) -> bool {
92 self == DispatchPhase::Bubble
93 }
94
95 #[inline]
97 pub fn capture(self) -> bool {
98 self == DispatchPhase::Capture
99 }
100}
101
102struct WindowInvalidatorInner {
103 pub dirty: bool,
104 pub draw_phase: DrawPhase,
105 pub dirty_views: FxHashSet<EntityId>,
106}
107
108#[derive(Clone)]
109pub(crate) struct WindowInvalidator {
110 inner: Rc<RefCell<WindowInvalidatorInner>>,
111}
112
113impl WindowInvalidator {
114 pub fn new() -> Self {
115 WindowInvalidator {
116 inner: Rc::new(RefCell::new(WindowInvalidatorInner {
117 dirty: true,
118 draw_phase: DrawPhase::None,
119 dirty_views: FxHashSet::default(),
120 })),
121 }
122 }
123
124 pub fn invalidate_view(&self, entity: EntityId, cx: &mut App) -> bool {
125 let mut inner = self.inner.borrow_mut();
126 inner.dirty_views.insert(entity);
127 if inner.draw_phase == DrawPhase::None {
128 inner.dirty = true;
129 cx.push_effect(Effect::Notify { emitter: entity });
130 true
131 } else {
132 false
133 }
134 }
135
136 pub fn is_dirty(&self) -> bool {
137 self.inner.borrow().dirty
138 }
139
140 pub fn set_dirty(&self, dirty: bool) {
141 self.inner.borrow_mut().dirty = dirty
142 }
143
144 pub fn set_phase(&self, phase: DrawPhase) {
145 self.inner.borrow_mut().draw_phase = phase
146 }
147
148 pub fn take_views(&self) -> FxHashSet<EntityId> {
149 mem::take(&mut self.inner.borrow_mut().dirty_views)
150 }
151
152 pub fn replace_views(&self, views: FxHashSet<EntityId>) {
153 self.inner.borrow_mut().dirty_views = views;
154 }
155
156 pub fn not_drawing(&self) -> bool {
157 self.inner.borrow().draw_phase == DrawPhase::None
158 }
159
160 #[track_caller]
161 pub fn debug_assert_paint(&self) {
162 debug_assert!(
163 matches!(self.inner.borrow().draw_phase, DrawPhase::Paint),
164 "this method can only be called during paint"
165 );
166 }
167
168 #[track_caller]
169 pub fn debug_assert_prepaint(&self) {
170 debug_assert!(
171 matches!(self.inner.borrow().draw_phase, DrawPhase::Prepaint),
172 "this method can only be called during request_layout, or prepaint"
173 );
174 }
175
176 #[track_caller]
177 pub fn debug_assert_paint_or_prepaint(&self) {
178 debug_assert!(
179 matches!(
180 self.inner.borrow().draw_phase,
181 DrawPhase::Paint | DrawPhase::Prepaint
182 ),
183 "this method can only be called during request_layout, prepaint, or paint"
184 );
185 }
186}
187
188type AnyObserver = Box<dyn FnMut(&mut Window, &mut App) -> bool + 'static>;
189
190pub(crate) type AnyWindowFocusListener =
191 Box<dyn FnMut(&WindowFocusEvent, &mut Window, &mut App) -> bool + 'static>;
192
193pub(crate) struct WindowFocusEvent {
194 pub(crate) previous_focus_path: SmallVec<[FocusId; 8]>,
195 pub(crate) current_focus_path: SmallVec<[FocusId; 8]>,
196}
197
198impl WindowFocusEvent {
199 pub fn is_focus_in(&self, focus_id: FocusId) -> bool {
200 !self.previous_focus_path.contains(&focus_id) && self.current_focus_path.contains(&focus_id)
201 }
202
203 pub fn is_focus_out(&self, focus_id: FocusId) -> bool {
204 self.previous_focus_path.contains(&focus_id) && !self.current_focus_path.contains(&focus_id)
205 }
206}
207
208pub struct FocusOutEvent {
210 pub blurred: WeakFocusHandle,
212}
213
214slotmap::new_key_type! {
215 pub struct FocusId;
217}
218
219thread_local! {
220 pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(1024 * 1024));
221}
222
223#[must_use]
225pub struct ArenaClearNeeded;
226
227impl ArenaClearNeeded {
228 pub fn clear(self) {
230 ELEMENT_ARENA.with_borrow_mut(|element_arena| {
231 element_arena.clear();
232 });
233 }
234}
235
236pub(crate) type FocusMap = RwLock<SlotMap<FocusId, FocusRef>>;
237pub(crate) struct FocusRef {
238 pub(crate) ref_count: AtomicUsize,
239 pub(crate) tab_index: isize,
240 pub(crate) tab_stop: bool,
241}
242
243impl FocusId {
244 pub fn is_focused(&self, window: &Window) -> bool {
246 window.focus == Some(*self)
247 }
248
249 pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
252 window
253 .focused(cx)
254 .is_some_and(|focused| self.contains(focused.id, window))
255 }
256
257 pub fn within_focused(&self, window: &Window, cx: &App) -> bool {
260 let focused = window.focused(cx);
261 focused.is_some_and(|focused| focused.id.contains(*self, window))
262 }
263
264 pub(crate) fn contains(&self, other: Self, window: &Window) -> bool {
266 window
267 .rendered_frame
268 .dispatch_tree
269 .focus_contains(*self, other)
270 }
271}
272
273pub struct FocusHandle {
275 pub(crate) id: FocusId,
276 handles: Arc<FocusMap>,
277 pub tab_index: isize,
279 pub tab_stop: bool,
281}
282
283impl std::fmt::Debug for FocusHandle {
284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 f.write_fmt(format_args!("FocusHandle({:?})", self.id))
286 }
287}
288
289impl FocusHandle {
290 pub(crate) fn new(handles: &Arc<FocusMap>) -> Self {
291 let id = handles.write().insert(FocusRef {
292 ref_count: AtomicUsize::new(1),
293 tab_index: 0,
294 tab_stop: false,
295 });
296
297 Self {
298 id,
299 tab_index: 0,
300 tab_stop: false,
301 handles: handles.clone(),
302 }
303 }
304
305 pub(crate) fn for_id(id: FocusId, handles: &Arc<FocusMap>) -> Option<Self> {
306 let lock = handles.read();
307 let focus = lock.get(id)?;
308 if atomic_incr_if_not_zero(&focus.ref_count) == 0 {
309 return None;
310 }
311 Some(Self {
312 id,
313 tab_index: focus.tab_index,
314 tab_stop: focus.tab_stop,
315 handles: handles.clone(),
316 })
317 }
318
319 pub fn tab_index(mut self, index: isize) -> Self {
321 self.tab_index = index;
322 if let Some(focus) = self.handles.write().get_mut(self.id) {
323 focus.tab_index = index;
324 }
325 self
326 }
327
328 pub fn tab_stop(mut self, tab_stop: bool) -> Self {
332 self.tab_stop = tab_stop;
333 if let Some(focus) = self.handles.write().get_mut(self.id) {
334 focus.tab_stop = tab_stop;
335 }
336 self
337 }
338
339 pub fn downgrade(&self) -> WeakFocusHandle {
341 WeakFocusHandle {
342 id: self.id,
343 handles: Arc::downgrade(&self.handles),
344 }
345 }
346
347 pub fn focus(&self, window: &mut Window, cx: &mut App) {
349 window.focus(self, cx)
350 }
351
352 pub fn is_focused(&self, window: &Window) -> bool {
354 self.id.is_focused(window)
355 }
356
357 pub fn contains_focused(&self, window: &Window, cx: &App) -> bool {
360 self.id.contains_focused(window, cx)
361 }
362
363 pub fn within_focused(&self, window: &Window, cx: &mut App) -> bool {
366 self.id.within_focused(window, cx)
367 }
368
369 pub fn contains(&self, other: &Self, window: &Window) -> bool {
371 self.id.contains(other.id, window)
372 }
373
374 pub fn dispatch_action(&self, action: &dyn Action, window: &mut Window, cx: &mut App) {
376 if let Some(node_id) = window
377 .rendered_frame
378 .dispatch_tree
379 .focusable_node_id(self.id)
380 {
381 window.dispatch_action_on_node(node_id, action, cx)
382 }
383 }
384}
385
386impl Clone for FocusHandle {
387 fn clone(&self) -> Self {
388 Self::for_id(self.id, &self.handles).unwrap()
389 }
390}
391
392impl PartialEq for FocusHandle {
393 fn eq(&self, other: &Self) -> bool {
394 self.id == other.id
395 }
396}
397
398impl Eq for FocusHandle {}
399
400impl Drop for FocusHandle {
401 fn drop(&mut self) {
402 self.handles
403 .read()
404 .get(self.id)
405 .unwrap()
406 .ref_count
407 .fetch_sub(1, SeqCst);
408 }
409}
410
411#[derive(Clone, Debug)]
413pub struct WeakFocusHandle {
414 pub(crate) id: FocusId,
415 pub(crate) handles: Weak<FocusMap>,
416}
417
418impl WeakFocusHandle {
419 pub fn upgrade(&self) -> Option<FocusHandle> {
421 let handles = self.handles.upgrade()?;
422 FocusHandle::for_id(self.id, &handles)
423 }
424}
425
426impl PartialEq for WeakFocusHandle {
427 fn eq(&self, other: &WeakFocusHandle) -> bool {
428 self.id == other.id
429 }
430}
431
432impl Eq for WeakFocusHandle {}
433
434impl PartialEq<FocusHandle> for WeakFocusHandle {
435 fn eq(&self, other: &FocusHandle) -> bool {
436 self.id == other.id
437 }
438}
439
440impl PartialEq<WeakFocusHandle> for FocusHandle {
441 fn eq(&self, other: &WeakFocusHandle) -> bool {
442 self.id == other.id
443 }
444}
445
446pub trait Focusable: 'static {
449 fn focus_handle(&self, cx: &App) -> FocusHandle;
451}
452
453impl<V: Focusable> Focusable for Entity<V> {
454 fn focus_handle(&self, cx: &App) -> FocusHandle {
455 self.read(cx).focus_handle(cx)
456 }
457}
458
459pub trait ManagedView: Focusable + EventEmitter<DismissEvent> + Render {}
462
463impl<M: Focusable + EventEmitter<DismissEvent> + Render> ManagedView for M {}
464
465pub struct DismissEvent;
467
468type FrameCallback = Box<dyn FnOnce(&mut Window, &mut App)>;
469
470pub(crate) type AnyMouseListener =
471 Box<dyn FnMut(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static>;
472
473#[derive(Clone)]
474pub(crate) struct CursorStyleRequest {
475 pub(crate) hitbox_id: Option<HitboxId>,
476 pub(crate) style: CursorStyle,
477}
478
479#[derive(Default, Eq, PartialEq)]
480pub(crate) struct HitTest {
481 pub(crate) ids: SmallVec<[HitboxId; 8]>,
482 pub(crate) hover_hitbox_count: usize,
483}
484
485#[derive(Clone, Copy, Debug, Eq, PartialEq)]
487pub enum WindowControlArea {
488 Drag,
490 Close,
492 Max,
494 Min,
496}
497
498#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
500pub struct HitboxId(u64);
501
502impl HitboxId {
503 pub fn is_hovered(self, window: &Window) -> bool {
509 let hit_test = &window.mouse_hit_test;
510 for id in hit_test.ids.iter().take(hit_test.hover_hitbox_count) {
511 if self == *id {
512 return true;
513 }
514 }
515 false
516 }
517
518 pub fn should_handle_scroll(self, window: &Window) -> bool {
523 window.mouse_hit_test.ids.contains(&self)
524 }
525
526 fn next(mut self) -> HitboxId {
527 HitboxId(self.0.wrapping_add(1))
528 }
529}
530
531#[derive(Clone, Debug, Deref)]
534pub struct Hitbox {
535 pub id: HitboxId,
537 #[deref]
539 pub bounds: Bounds<Pixels>,
540 pub content_mask: ContentMask<Pixels>,
542 pub behavior: HitboxBehavior,
544}
545
546impl Hitbox {
547 pub fn is_hovered(&self, window: &Window) -> bool {
562 self.id.is_hovered(window)
563 }
564
565 pub fn should_handle_scroll(&self, window: &Window) -> bool {
572 self.id.should_handle_scroll(window)
573 }
574}
575
576#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
578pub enum HitboxBehavior {
579 #[default]
581 Normal,
582
583 BlockMouse,
605
606 BlockMouseExceptScroll,
633}
634
635#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
637pub struct TooltipId(usize);
638
639impl TooltipId {
640 pub fn is_hovered(&self, window: &Window) -> bool {
642 window
643 .tooltip_bounds
644 .as_ref()
645 .is_some_and(|tooltip_bounds| {
646 tooltip_bounds.id == *self
647 && tooltip_bounds.bounds.contains(&window.mouse_position())
648 })
649 }
650}
651
652pub(crate) struct TooltipBounds {
653 id: TooltipId,
654 bounds: Bounds<Pixels>,
655}
656
657#[derive(Clone)]
658pub(crate) struct TooltipRequest {
659 id: TooltipId,
660 tooltip: AnyTooltip,
661}
662
663pub(crate) struct DeferredDraw {
664 current_view: EntityId,
665 priority: usize,
666 parent_node: DispatchNodeId,
667 element_id_stack: SmallVec<[ElementId; 32]>,
668 text_style_stack: Vec<TextStyleRefinement>,
669 element: Option<AnyElement>,
670 absolute_offset: Point<Pixels>,
671 prepaint_range: Range<PrepaintStateIndex>,
672 paint_range: Range<PaintIndex>,
673}
674
675pub(crate) struct Frame {
676 pub(crate) focus: Option<FocusId>,
677 pub(crate) window_active: bool,
678 pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
679 accessed_element_states: Vec<(GlobalElementId, TypeId)>,
680 pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
681 pub(crate) dispatch_tree: DispatchTree,
682 pub(crate) scene: Scene,
683 pub(crate) hitboxes: Vec<Hitbox>,
684 pub(crate) window_control_hitboxes: Vec<(WindowControlArea, Hitbox)>,
685 pub(crate) deferred_draws: Vec<DeferredDraw>,
686 pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
687 pub(crate) tooltip_requests: Vec<Option<TooltipRequest>>,
688 pub(crate) cursor_styles: Vec<CursorStyleRequest>,
689 #[cfg(any(test, feature = "test-support"))]
690 pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
691 #[cfg(any(feature = "inspector", debug_assertions))]
692 pub(crate) next_inspector_instance_ids: FxHashMap<Rc<crate::InspectorElementPath>, usize>,
693 #[cfg(any(feature = "inspector", debug_assertions))]
694 pub(crate) inspector_hitboxes: FxHashMap<HitboxId, crate::InspectorElementId>,
695 pub(crate) tab_stops: TabStopMap,
696}
697
698#[derive(Clone, Default)]
699pub(crate) struct PrepaintStateIndex {
700 hitboxes_index: usize,
701 tooltips_index: usize,
702 deferred_draws_index: usize,
703 dispatch_tree_index: usize,
704 accessed_element_states_index: usize,
705 line_layout_index: LineLayoutIndex,
706}
707
708#[derive(Clone, Default)]
709pub(crate) struct PaintIndex {
710 scene_index: usize,
711 mouse_listeners_index: usize,
712 input_handlers_index: usize,
713 cursor_styles_index: usize,
714 accessed_element_states_index: usize,
715 tab_handle_index: usize,
716 line_layout_index: LineLayoutIndex,
717}
718
719impl Frame {
720 pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
721 Frame {
722 focus: None,
723 window_active: false,
724 element_states: FxHashMap::default(),
725 accessed_element_states: Vec::new(),
726 mouse_listeners: Vec::new(),
727 dispatch_tree,
728 scene: Scene::default(),
729 hitboxes: Vec::new(),
730 window_control_hitboxes: Vec::new(),
731 deferred_draws: Vec::new(),
732 input_handlers: Vec::new(),
733 tooltip_requests: Vec::new(),
734 cursor_styles: Vec::new(),
735
736 #[cfg(any(test, feature = "test-support"))]
737 debug_bounds: FxHashMap::default(),
738
739 #[cfg(any(feature = "inspector", debug_assertions))]
740 next_inspector_instance_ids: FxHashMap::default(),
741
742 #[cfg(any(feature = "inspector", debug_assertions))]
743 inspector_hitboxes: FxHashMap::default(),
744 tab_stops: TabStopMap::default(),
745 }
746 }
747
748 pub(crate) fn clear(&mut self) {
749 self.element_states.clear();
750 self.accessed_element_states.clear();
751 self.mouse_listeners.clear();
752 self.dispatch_tree.clear();
753 self.scene.clear();
754 self.input_handlers.clear();
755 self.tooltip_requests.clear();
756 self.cursor_styles.clear();
757 self.hitboxes.clear();
758 self.window_control_hitboxes.clear();
759 self.deferred_draws.clear();
760 self.tab_stops.clear();
761 self.focus = None;
762
763 #[cfg(any(feature = "inspector", debug_assertions))]
764 {
765 self.next_inspector_instance_ids.clear();
766 self.inspector_hitboxes.clear();
767 }
768 }
769
770 pub(crate) fn cursor_style(&self, window: &Window) -> Option<CursorStyle> {
771 self.cursor_styles
772 .iter()
773 .rev()
774 .fold_while(None, |style, request| match request.hitbox_id {
775 None => Done(Some(request.style)),
776 Some(hitbox_id) => Continue(
777 style.or_else(|| hitbox_id.is_hovered(window).then_some(request.style)),
778 ),
779 })
780 .into_inner()
781 }
782
783 pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
784 let mut set_hover_hitbox_count = false;
785 let mut hit_test = HitTest::default();
786 for hitbox in self.hitboxes.iter().rev() {
787 let bounds = hitbox.bounds.intersect(&hitbox.content_mask.bounds);
788 if bounds.contains(&position) {
789 hit_test.ids.push(hitbox.id);
790 if !set_hover_hitbox_count
791 && hitbox.behavior == HitboxBehavior::BlockMouseExceptScroll
792 {
793 hit_test.hover_hitbox_count = hit_test.ids.len();
794 set_hover_hitbox_count = true;
795 }
796 if hitbox.behavior == HitboxBehavior::BlockMouse {
797 break;
798 }
799 }
800 }
801 if !set_hover_hitbox_count {
802 hit_test.hover_hitbox_count = hit_test.ids.len();
803 }
804 hit_test
805 }
806
807 pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
808 self.focus
809 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
810 .unwrap_or_default()
811 }
812
813 pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
814 for element_state_key in &self.accessed_element_states {
815 if let Some((element_state_key, element_state)) =
816 prev_frame.element_states.remove_entry(element_state_key)
817 {
818 self.element_states.insert(element_state_key, element_state);
819 }
820 }
821
822 self.scene.finish();
823 }
824}
825
826#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
827enum InputModality {
828 Mouse,
829 Keyboard,
830}
831
832pub struct Window {
834 pub(crate) handle: AnyWindowHandle,
835 pub(crate) invalidator: WindowInvalidator,
836 pub(crate) removed: bool,
837 pub(crate) platform_window: Box<dyn PlatformWindow>,
838 display_id: Option<DisplayId>,
839 sprite_atlas: Arc<dyn PlatformAtlas>,
840 text_system: Arc<WindowTextSystem>,
841 rem_size: Pixels,
842 rem_size_override_stack: SmallVec<[Pixels; 8]>,
847 pub(crate) viewport_size: Size<Pixels>,
848 layout_engine: Option<TaffyLayoutEngine>,
849 pub(crate) root: Option<AnyView>,
850 pub(crate) element_id_stack: SmallVec<[ElementId; 32]>,
851 pub(crate) text_style_stack: Vec<TextStyleRefinement>,
852 pub(crate) rendered_entity_stack: Vec<EntityId>,
853 pub(crate) element_offset_stack: Vec<Point<Pixels>>,
854 pub(crate) element_opacity: f32,
855 pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
856 pub(crate) requested_autoscroll: Option<Bounds<Pixels>>,
857 pub(crate) image_cache_stack: Vec<AnyImageCache>,
858 pub(crate) rendered_frame: Frame,
859 pub(crate) next_frame: Frame,
860 next_hitbox_id: HitboxId,
861 pub(crate) next_tooltip_id: TooltipId,
862 pub(crate) tooltip_bounds: Option<TooltipBounds>,
863 next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
864 frame_seq: u64,
865 render_layers: FxHashMap<ElementId, RenderLayerRegistration>,
866 next_render_layer_seq: usize,
867 pub(crate) dirty_views: FxHashSet<EntityId>,
868 focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
869 pub(crate) focus_lost_listeners: SubscriberSet<(), AnyObserver>,
870 default_prevented: bool,
871 mouse_position: Point<Pixels>,
872 mouse_hit_test: HitTest,
873 modifiers: Modifiers,
874 capslock: Capslock,
875 scale_factor: f32,
876 pub(crate) bounds_observers: SubscriberSet<(), AnyObserver>,
877 appearance: WindowAppearance,
878 pub(crate) appearance_observers: SubscriberSet<(), AnyObserver>,
879 active: Rc<Cell<bool>>,
880 hovered: Rc<Cell<bool>>,
881 pub(crate) needs_present: Rc<Cell<bool>>,
882 pub(crate) input_rate_tracker: Rc<RefCell<InputRateTracker>>,
885 last_input_modality: InputModality,
886 pub(crate) refreshing: bool,
887 pub(crate) activation_observers: SubscriberSet<(), AnyObserver>,
888 pub(crate) focus: Option<FocusId>,
889 focus_enabled: bool,
890 pending_input: Option<PendingInput>,
891 pending_modifier: ModifierState,
892 pub(crate) pending_input_observers: SubscriberSet<(), AnyObserver>,
893 prompt: Option<RenderablePromptHandle>,
894 pub(crate) client_inset: Option<Pixels>,
895 #[cfg(any(feature = "inspector", debug_assertions))]
896 inspector: Option<Entity<Inspector>>,
897}
898
899type RenderLayerBuilder = Arc<dyn Fn(&mut Window, &mut App) -> AnyElement + 'static>;
900
901#[derive(Clone)]
902struct RenderLayerRegistration {
903 order: i32,
904 seq: usize,
905 build: RenderLayerBuilder,
906}
907
908#[derive(Clone, Debug, Default)]
909struct ModifierState {
910 modifiers: Modifiers,
911 saw_keystroke: bool,
912}
913
914#[derive(Clone, Debug)]
917pub(crate) struct InputRateTracker {
918 timestamps: Vec<Instant>,
919 window: Duration,
920 inputs_per_second: u32,
921 sustain_until: Instant,
922 sustain_duration: Duration,
923}
924
925impl Default for InputRateTracker {
926 fn default() -> Self {
927 Self {
928 timestamps: Vec::new(),
929 window: Duration::from_millis(100),
930 inputs_per_second: 60,
931 sustain_until: Instant::now(),
932 sustain_duration: Duration::from_secs(1),
933 }
934 }
935}
936
937impl InputRateTracker {
938 pub fn record_input(&mut self) {
939 let now = Instant::now();
940 self.timestamps.push(now);
941 self.prune_old_timestamps(now);
942
943 let min_events = self.inputs_per_second as u128 * self.window.as_millis() / 1000;
944 if self.timestamps.len() as u128 >= min_events {
945 self.sustain_until = now + self.sustain_duration;
946 }
947 }
948
949 pub fn is_high_rate(&self) -> bool {
950 Instant::now() < self.sustain_until
951 }
952
953 fn prune_old_timestamps(&mut self, now: Instant) {
954 self.timestamps
955 .retain(|&t| now.duration_since(t) <= self.window);
956 }
957}
958
959#[derive(Clone, Copy, Debug, Eq, PartialEq)]
960pub(crate) enum DrawPhase {
961 None,
962 Prepaint,
963 Paint,
964 Focus,
965}
966
967#[derive(Default, Debug)]
968struct PendingInput {
969 keystrokes: SmallVec<[Keystroke; 1]>,
970 focus: Option<FocusId>,
971 timer: Option<Task<()>>,
972 needs_timeout: bool,
973}
974
975pub(crate) struct ElementStateBox {
976 pub(crate) inner: Box<dyn Any>,
977 #[cfg(debug_assertions)]
978 pub(crate) type_name: &'static str,
979}
980
981fn default_bounds(display_id: Option<DisplayId>, cx: &mut App) -> WindowBounds {
982 let active_window_bounds = cx
987 .active_window()
988 .and_then(|w| w.update(cx, |_, window, _| window.window_bounds()).ok());
989
990 const CASCADE_OFFSET: f32 = 25.0;
991
992 let display = display_id
993 .map(|id| cx.find_display(id))
994 .unwrap_or_else(|| cx.primary_display());
995
996 let default_placement = || Bounds::new(point(px(0.), px(0.)), DEFAULT_WINDOW_SIZE);
997
998 let display_bounds = display
1000 .as_ref()
1001 .map(|d| d.visible_bounds())
1002 .unwrap_or_else(default_placement);
1003
1004 let (
1005 Bounds {
1006 origin: base_origin,
1007 size: base_size,
1008 },
1009 window_bounds_ctor,
1010 ): (_, fn(Bounds<Pixels>) -> WindowBounds) = match active_window_bounds {
1011 Some(bounds) => match bounds {
1012 WindowBounds::Windowed(bounds) => (bounds, WindowBounds::Windowed),
1013 WindowBounds::Maximized(bounds) => (bounds, WindowBounds::Maximized),
1014 WindowBounds::Fullscreen(bounds) => (bounds, WindowBounds::Fullscreen),
1015 },
1016 None => (
1017 display
1018 .as_ref()
1019 .map(|d| d.default_bounds())
1020 .unwrap_or_else(default_placement),
1021 WindowBounds::Windowed,
1022 ),
1023 };
1024
1025 let cascade_offset = point(px(CASCADE_OFFSET), px(CASCADE_OFFSET));
1026 let proposed_origin = base_origin + cascade_offset;
1027 let proposed_bounds = Bounds::new(proposed_origin, base_size);
1028
1029 let display_right = display_bounds.origin.x + display_bounds.size.width;
1030 let display_bottom = display_bounds.origin.y + display_bounds.size.height;
1031 let window_right = proposed_bounds.origin.x + proposed_bounds.size.width;
1032 let window_bottom = proposed_bounds.origin.y + proposed_bounds.size.height;
1033
1034 let fits_horizontally = window_right <= display_right;
1035 let fits_vertically = window_bottom <= display_bottom;
1036
1037 let final_origin = match (fits_horizontally, fits_vertically) {
1038 (true, true) => proposed_origin,
1039 (false, true) => point(display_bounds.origin.x, base_origin.y),
1040 (true, false) => point(base_origin.x, display_bounds.origin.y),
1041 (false, false) => display_bounds.origin,
1042 };
1043 window_bounds_ctor(Bounds::new(final_origin, base_size))
1044}
1045
1046impl Window {
1047 pub(crate) fn new(
1048 handle: AnyWindowHandle,
1049 options: WindowOptions,
1050 cx: &mut App,
1051 ) -> Result<Self> {
1052 let WindowOptions {
1053 window_bounds,
1054 titlebar,
1055 focus,
1056 show,
1057 kind,
1058 is_movable,
1059 is_resizable,
1060 is_minimizable,
1061 display_id,
1062 window_background,
1063 app_id,
1064 window_min_size,
1065 window_decorations,
1066 #[cfg_attr(not(target_os = "macos"), allow(unused_variables))]
1067 tabbing_identifier,
1068 } = options;
1069
1070 let window_bounds = window_bounds.unwrap_or_else(|| default_bounds(display_id, cx));
1071 let mut platform_window = cx.platform.open_window(
1072 handle,
1073 WindowParams {
1074 bounds: window_bounds.get_bounds(),
1075 titlebar,
1076 kind,
1077 is_movable,
1078 is_resizable,
1079 is_minimizable,
1080 focus,
1081 show,
1082 display_id,
1083 window_min_size,
1084 #[cfg(target_os = "macos")]
1085 tabbing_identifier,
1086 },
1087 )?;
1088
1089 let tab_bar_visible = platform_window.tab_bar_visible();
1090 SystemWindowTabController::init_visible(cx, tab_bar_visible);
1091 if let Some(tabs) = platform_window.tabbed_windows() {
1092 SystemWindowTabController::add_tab(cx, handle.window_id(), tabs);
1093 }
1094
1095 let display_id = platform_window.display().map(|display| display.id());
1096 let sprite_atlas = platform_window.sprite_atlas();
1097 let mouse_position = platform_window.mouse_position();
1098 let modifiers = platform_window.modifiers();
1099 let capslock = platform_window.capslock();
1100 let content_size = platform_window.content_size();
1101 let scale_factor = platform_window.scale_factor();
1102 let appearance = platform_window.appearance();
1103 let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
1104 let invalidator = WindowInvalidator::new();
1105 let active = Rc::new(Cell::new(platform_window.is_active()));
1106 let hovered = Rc::new(Cell::new(platform_window.is_hovered()));
1107 let needs_present = Rc::new(Cell::new(false));
1108 let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
1109 let input_rate_tracker = Rc::new(RefCell::new(InputRateTracker::default()));
1110
1111 platform_window
1112 .request_decorations(window_decorations.unwrap_or(WindowDecorations::Server));
1113 platform_window.set_background_appearance(window_background);
1114
1115 match window_bounds {
1116 WindowBounds::Fullscreen(_) => platform_window.toggle_fullscreen(),
1117 WindowBounds::Maximized(_) => platform_window.zoom(),
1118 WindowBounds::Windowed(_) => {}
1119 }
1120
1121 platform_window.on_close(Box::new({
1122 let window_id = handle.window_id();
1123 let mut cx = cx.to_async();
1124 move || {
1125 let _ = handle.update(&mut cx, |_, window, _| window.remove_window());
1126 let _ = cx.update(|cx| {
1127 SystemWindowTabController::remove_tab(cx, window_id);
1128 });
1129 }
1130 }));
1131 platform_window.on_request_frame(Box::new({
1132 let mut cx = cx.to_async();
1133 let invalidator = invalidator.clone();
1134 let active = active.clone();
1135 let needs_present = needs_present.clone();
1136 let next_frame_callbacks = next_frame_callbacks.clone();
1137 let input_rate_tracker = input_rate_tracker.clone();
1138 move |request_frame_options| {
1139 let next_frame_callbacks = next_frame_callbacks.take();
1140 if !next_frame_callbacks.is_empty() {
1141 handle
1142 .update(&mut cx, |_, window, cx| {
1143 for callback in next_frame_callbacks {
1144 callback(window, cx);
1145 }
1146 })
1147 .log_err();
1148 }
1149
1150 let needs_present = request_frame_options.require_presentation
1154 || needs_present.get()
1155 || (active.get() && input_rate_tracker.borrow_mut().is_high_rate());
1156
1157 if invalidator.is_dirty() || request_frame_options.force_render {
1158 measure("frame duration", || {
1159 handle
1160 .update(&mut cx, |_, window, cx| {
1161 let arena_clear_needed = window.draw(cx);
1162 window.present();
1163 arena_clear_needed.clear();
1164 })
1165 .log_err();
1166 })
1167 } else if needs_present {
1168 handle
1169 .update(&mut cx, |_, window, _| window.present())
1170 .log_err();
1171 }
1172
1173 handle
1174 .update(&mut cx, |_, window, _| {
1175 window.complete_frame();
1176 })
1177 .log_err();
1178 }
1179 }));
1180 platform_window.on_resize(Box::new({
1181 let mut cx = cx.to_async();
1182 move |_, _| {
1183 handle
1184 .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1185 .log_err();
1186 }
1187 }));
1188 platform_window.on_moved(Box::new({
1189 let mut cx = cx.to_async();
1190 move || {
1191 handle
1192 .update(&mut cx, |_, window, cx| window.bounds_changed(cx))
1193 .log_err();
1194 }
1195 }));
1196 platform_window.on_appearance_changed(Box::new({
1197 let mut cx = cx.to_async();
1198 move || {
1199 handle
1200 .update(&mut cx, |_, window, cx| window.appearance_changed(cx))
1201 .log_err();
1202 }
1203 }));
1204 platform_window.on_active_status_change(Box::new({
1205 let mut cx = cx.to_async();
1206 move |active| {
1207 handle
1208 .update(&mut cx, |_, window, cx| {
1209 window.active.set(active);
1210 window.modifiers = window.platform_window.modifiers();
1211 window.capslock = window.platform_window.capslock();
1212 window
1213 .activation_observers
1214 .clone()
1215 .retain(&(), |callback| callback(window, cx));
1216
1217 window.bounds_changed(cx);
1218 window.refresh();
1219
1220 SystemWindowTabController::update_last_active(cx, window.handle.id);
1221 })
1222 .log_err();
1223 }
1224 }));
1225 platform_window.on_hover_status_change(Box::new({
1226 let mut cx = cx.to_async();
1227 move |active| {
1228 handle
1229 .update(&mut cx, |_, window, _| {
1230 window.hovered.set(active);
1231 window.refresh();
1232 })
1233 .log_err();
1234 }
1235 }));
1236 platform_window.on_input({
1237 let mut cx = cx.to_async();
1238 Box::new(move |event| {
1239 handle
1240 .update(&mut cx, |_, window, cx| window.dispatch_event(event, cx))
1241 .log_err()
1242 .unwrap_or(DispatchEventResult::default())
1243 })
1244 });
1245 platform_window.on_hit_test_window_control({
1246 let mut cx = cx.to_async();
1247 Box::new(move || {
1248 handle
1249 .update(&mut cx, |_, window, _cx| {
1250 for (area, hitbox) in &window.rendered_frame.window_control_hitboxes {
1251 if window.mouse_hit_test.ids.contains(&hitbox.id) {
1252 return Some(*area);
1253 }
1254 }
1255 None
1256 })
1257 .log_err()
1258 .unwrap_or(None)
1259 })
1260 });
1261 platform_window.on_move_tab_to_new_window({
1262 let mut cx = cx.to_async();
1263 Box::new(move || {
1264 handle
1265 .update(&mut cx, |_, _window, cx| {
1266 SystemWindowTabController::move_tab_to_new_window(cx, handle.window_id());
1267 })
1268 .log_err();
1269 })
1270 });
1271 platform_window.on_merge_all_windows({
1272 let mut cx = cx.to_async();
1273 Box::new(move || {
1274 handle
1275 .update(&mut cx, |_, _window, cx| {
1276 SystemWindowTabController::merge_all_windows(cx, handle.window_id());
1277 })
1278 .log_err();
1279 })
1280 });
1281 platform_window.on_select_next_tab({
1282 let mut cx = cx.to_async();
1283 Box::new(move || {
1284 handle
1285 .update(&mut cx, |_, _window, cx| {
1286 SystemWindowTabController::select_next_tab(cx, handle.window_id());
1287 })
1288 .log_err();
1289 })
1290 });
1291 platform_window.on_select_previous_tab({
1292 let mut cx = cx.to_async();
1293 Box::new(move || {
1294 handle
1295 .update(&mut cx, |_, _window, cx| {
1296 SystemWindowTabController::select_previous_tab(cx, handle.window_id())
1297 })
1298 .log_err();
1299 })
1300 });
1301 platform_window.on_toggle_tab_bar({
1302 let mut cx = cx.to_async();
1303 Box::new(move || {
1304 handle
1305 .update(&mut cx, |_, window, cx| {
1306 let tab_bar_visible = window.platform_window.tab_bar_visible();
1307 SystemWindowTabController::set_visible(cx, tab_bar_visible);
1308 })
1309 .log_err();
1310 })
1311 });
1312
1313 if let Some(app_id) = app_id {
1314 platform_window.set_app_id(&app_id);
1315 }
1316
1317 platform_window.map_window().unwrap();
1318
1319 Ok(Window {
1320 handle,
1321 invalidator,
1322 removed: false,
1323 platform_window,
1324 display_id,
1325 sprite_atlas,
1326 text_system,
1327 rem_size: px(16.),
1328 rem_size_override_stack: SmallVec::new(),
1329 viewport_size: content_size,
1330 layout_engine: Some(TaffyLayoutEngine::new()),
1331 root: None,
1332 element_id_stack: SmallVec::default(),
1333 text_style_stack: Vec::new(),
1334 rendered_entity_stack: Vec::new(),
1335 element_offset_stack: Vec::new(),
1336 content_mask_stack: Vec::new(),
1337 element_opacity: 1.0,
1338 requested_autoscroll: None,
1339 rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1340 next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
1341 next_frame_callbacks,
1342 next_hitbox_id: HitboxId(0),
1343 next_tooltip_id: TooltipId::default(),
1344 tooltip_bounds: None,
1345 frame_seq: 0,
1346 render_layers: FxHashMap::default(),
1347 next_render_layer_seq: 0,
1348 dirty_views: FxHashSet::default(),
1349 focus_listeners: SubscriberSet::new(),
1350 focus_lost_listeners: SubscriberSet::new(),
1351 default_prevented: true,
1352 mouse_position,
1353 mouse_hit_test: HitTest::default(),
1354 modifiers,
1355 capslock,
1356 scale_factor,
1357 bounds_observers: SubscriberSet::new(),
1358 appearance,
1359 appearance_observers: SubscriberSet::new(),
1360 active,
1361 hovered,
1362 needs_present,
1363 input_rate_tracker,
1364 last_input_modality: InputModality::Mouse,
1365 refreshing: false,
1366 activation_observers: SubscriberSet::new(),
1367 focus: None,
1368 focus_enabled: true,
1369 pending_input: None,
1370 pending_modifier: ModifierState::default(),
1371 pending_input_observers: SubscriberSet::new(),
1372 prompt: None,
1373 client_inset: None,
1374 image_cache_stack: Vec::new(),
1375 #[cfg(any(feature = "inspector", debug_assertions))]
1376 inspector: None,
1377 })
1378 }
1379
1380 pub(crate) fn new_focus_listener(
1381 &self,
1382 value: AnyWindowFocusListener,
1383 ) -> (Subscription, impl FnOnce() + use<>) {
1384 self.focus_listeners.insert((), value)
1385 }
1386}
1387
1388#[derive(Clone, Debug, Default, PartialEq, Eq)]
1389pub(crate) struct DispatchEventResult {
1390 pub propagate: bool,
1391 pub default_prevented: bool,
1392}
1393
1394#[derive(Clone, Debug, Default, PartialEq, Eq)]
1398#[repr(C)]
1399pub struct ContentMask<P: Clone + Debug + Default + PartialEq> {
1400 pub bounds: Bounds<P>,
1402}
1403
1404impl ContentMask<Pixels> {
1405 pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
1407 ContentMask {
1408 bounds: self.bounds.scale(factor),
1409 }
1410 }
1411
1412 pub fn intersect(&self, other: &Self) -> Self {
1414 let bounds = self.bounds.intersect(&other.bounds);
1415 ContentMask { bounds }
1416 }
1417}
1418
1419impl Window {
1420 fn mark_view_dirty(&mut self, view_id: EntityId) {
1421 for view_id in self
1424 .rendered_frame
1425 .dispatch_tree
1426 .view_path_reversed(view_id)
1427 {
1428 if !self.dirty_views.insert(view_id) {
1429 break;
1430 }
1431 }
1432 }
1433
1434 pub fn observe_window_appearance(
1436 &self,
1437 mut callback: impl FnMut(&mut Window, &mut App) + 'static,
1438 ) -> Subscription {
1439 let (subscription, activate) = self.appearance_observers.insert(
1440 (),
1441 Box::new(move |window, cx| {
1442 callback(window, cx);
1443 true
1444 }),
1445 );
1446 activate();
1447 subscription
1448 }
1449
1450 pub fn replace_root<E>(
1452 &mut self,
1453 cx: &mut App,
1454 build_view: impl FnOnce(&mut Window, &mut Context<E>) -> E,
1455 ) -> Entity<E>
1456 where
1457 E: 'static + Render,
1458 {
1459 let view = cx.new(|cx| build_view(self, cx));
1460 self.root = Some(view.clone().into());
1461 self.refresh();
1462 view
1463 }
1464
1465 pub fn root<E>(&self) -> Option<Option<Entity<E>>>
1467 where
1468 E: 'static + Render,
1469 {
1470 self.root
1471 .as_ref()
1472 .map(|view| view.clone().downcast::<E>().ok())
1473 }
1474
1475 pub fn window_handle(&self) -> AnyWindowHandle {
1477 self.handle
1478 }
1479
1480 pub fn refresh(&mut self) {
1482 if self.invalidator.not_drawing() {
1483 self.refreshing = true;
1484 self.invalidator.set_dirty(true);
1485 }
1486 }
1487
1488 pub fn remove_window(&mut self) {
1490 self.removed = true;
1491 }
1492
1493 pub fn focused(&self, cx: &App) -> Option<FocusHandle> {
1495 self.focus
1496 .and_then(|id| FocusHandle::for_id(id, &cx.focus_handles))
1497 }
1498
1499 pub fn focus(&mut self, handle: &FocusHandle, cx: &mut App) {
1501 if !self.focus_enabled || self.focus == Some(handle.id) {
1502 return;
1503 }
1504
1505 self.focus = Some(handle.id);
1506 self.clear_pending_keystrokes();
1507
1508 let window_handle = self.handle;
1511 cx.defer(move |cx| {
1512 window_handle
1513 .update(cx, |_, window, cx| {
1514 window.pending_input_changed(cx);
1515 })
1516 .ok();
1517 });
1518
1519 self.refresh();
1520 }
1521
1522 pub fn blur(&mut self) {
1524 if !self.focus_enabled {
1525 return;
1526 }
1527
1528 self.focus = None;
1529 self.refresh();
1530 }
1531
1532 pub fn disable_focus(&mut self) {
1534 self.blur();
1535 self.focus_enabled = false;
1536 }
1537
1538 pub fn focus_next(&mut self, cx: &mut App) {
1540 if !self.focus_enabled {
1541 return;
1542 }
1543
1544 if let Some(handle) = self.rendered_frame.tab_stops.next(self.focus.as_ref()) {
1545 self.focus(&handle, cx)
1546 }
1547 }
1548
1549 pub fn focus_prev(&mut self, cx: &mut App) {
1551 if !self.focus_enabled {
1552 return;
1553 }
1554
1555 if let Some(handle) = self.rendered_frame.tab_stops.prev(self.focus.as_ref()) {
1556 self.focus(&handle, cx)
1557 }
1558 }
1559
1560 pub fn text_system(&self) -> &Arc<WindowTextSystem> {
1562 &self.text_system
1563 }
1564
1565 pub fn text_style(&self) -> TextStyle {
1567 let mut style = TextStyle::default();
1568 for refinement in &self.text_style_stack {
1569 style.refine(refinement);
1570 }
1571 style
1572 }
1573
1574 pub fn is_maximized(&self) -> bool {
1578 self.platform_window.is_maximized()
1579 }
1580
1581 pub fn request_decorations(&self, decorations: WindowDecorations) {
1583 self.platform_window.request_decorations(decorations);
1584 }
1585
1586 pub fn start_window_resize(&self, edge: ResizeEdge) {
1588 self.platform_window.start_window_resize(edge);
1589 }
1590
1591 pub fn window_bounds(&self) -> WindowBounds {
1594 self.platform_window.window_bounds()
1595 }
1596
1597 pub fn inner_window_bounds(&self) -> WindowBounds {
1599 self.platform_window.inner_window_bounds()
1600 }
1601
1602 pub fn dispatch_action(&mut self, action: Box<dyn Action>, cx: &mut App) {
1604 let focus_id = self.focused(cx).map(|handle| handle.id);
1605
1606 let window = self.handle;
1607 cx.defer(move |cx| {
1608 window
1609 .update(cx, |_, window, cx| {
1610 let node_id = window.focus_node_id_in_rendered_frame(focus_id);
1611 window.dispatch_action_on_node(node_id, action.as_ref(), cx);
1612 })
1613 .log_err();
1614 })
1615 }
1616
1617 pub(crate) fn dispatch_keystroke_observers(
1618 &mut self,
1619 event: &dyn Any,
1620 action: Option<Box<dyn Action>>,
1621 context_stack: Vec<KeyContext>,
1622 cx: &mut App,
1623 ) {
1624 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
1625 return;
1626 };
1627
1628 cx.keystroke_observers.clone().retain(&(), move |callback| {
1629 (callback)(
1630 &KeystrokeEvent {
1631 keystroke: key_down_event.keystroke.clone(),
1632 action: action.as_ref().map(|action| action.boxed_clone()),
1633 context_stack: context_stack.clone(),
1634 },
1635 self,
1636 cx,
1637 )
1638 });
1639 }
1640
1641 pub(crate) fn dispatch_keystroke_interceptors(
1642 &mut self,
1643 event: &dyn Any,
1644 context_stack: Vec<KeyContext>,
1645 cx: &mut App,
1646 ) {
1647 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
1648 return;
1649 };
1650
1651 cx.keystroke_interceptors
1652 .clone()
1653 .retain(&(), move |callback| {
1654 (callback)(
1655 &KeystrokeEvent {
1656 keystroke: key_down_event.keystroke.clone(),
1657 action: None,
1658 context_stack: context_stack.clone(),
1659 },
1660 self,
1661 cx,
1662 )
1663 });
1664 }
1665
1666 pub fn defer(&self, cx: &mut App, f: impl FnOnce(&mut Window, &mut App) + 'static) {
1669 let handle = self.handle;
1670 cx.defer(move |cx| {
1671 handle.update(cx, |_, window, cx| f(window, cx)).ok();
1672 });
1673 }
1674
1675 pub fn observe<T: 'static>(
1679 &mut self,
1680 observed: &Entity<T>,
1681 cx: &mut App,
1682 mut on_notify: impl FnMut(Entity<T>, &mut Window, &mut App) + 'static,
1683 ) -> Subscription {
1684 let entity_id = observed.entity_id();
1685 let observed = observed.downgrade();
1686 let window_handle = self.handle;
1687 cx.new_observer(
1688 entity_id,
1689 Box::new(move |cx| {
1690 window_handle
1691 .update(cx, |_, window, cx| {
1692 if let Some(handle) = observed.upgrade() {
1693 on_notify(handle, window, cx);
1694 true
1695 } else {
1696 false
1697 }
1698 })
1699 .unwrap_or(false)
1700 }),
1701 )
1702 }
1703
1704 pub fn subscribe<Emitter, Evt>(
1708 &mut self,
1709 entity: &Entity<Emitter>,
1710 cx: &mut App,
1711 mut on_event: impl FnMut(Entity<Emitter>, &Evt, &mut Window, &mut App) + 'static,
1712 ) -> Subscription
1713 where
1714 Emitter: EventEmitter<Evt>,
1715 Evt: 'static,
1716 {
1717 let entity_id = entity.entity_id();
1718 let handle = entity.downgrade();
1719 let window_handle = self.handle;
1720 cx.new_subscription(
1721 entity_id,
1722 (
1723 TypeId::of::<Evt>(),
1724 Box::new(move |event, cx| {
1725 window_handle
1726 .update(cx, |_, window, cx| {
1727 if let Some(entity) = handle.upgrade() {
1728 let event = event.downcast_ref().expect("invalid event type");
1729 on_event(entity, event, window, cx);
1730 true
1731 } else {
1732 false
1733 }
1734 })
1735 .unwrap_or(false)
1736 }),
1737 ),
1738 )
1739 }
1740
1741 pub fn observe_release<T>(
1743 &self,
1744 entity: &Entity<T>,
1745 cx: &mut App,
1746 mut on_release: impl FnOnce(&mut T, &mut Window, &mut App) + 'static,
1747 ) -> Subscription
1748 where
1749 T: 'static,
1750 {
1751 let entity_id = entity.entity_id();
1752 let window_handle = self.handle;
1753 let (subscription, activate) = cx.release_listeners.insert(
1754 entity_id,
1755 Box::new(move |entity, cx| {
1756 let entity = entity.downcast_mut().expect("invalid entity type");
1757 let _ = window_handle.update(cx, |_, window, cx| on_release(entity, window, cx));
1758 }),
1759 );
1760 activate();
1761 subscription
1762 }
1763
1764 pub fn to_async(&self, cx: &App) -> AsyncWindowContext {
1767 AsyncWindowContext::new_context(cx.to_async(), self.handle)
1768 }
1769
1770 pub fn on_next_frame(&self, callback: impl FnOnce(&mut Window, &mut App) + 'static) {
1772 RefCell::borrow_mut(&self.next_frame_callbacks).push(Box::new(callback));
1773 }
1774
1775 pub fn request_animation_frame(&self) {
1782 let entity = self.current_view();
1783 self.on_next_frame(move |_, cx| cx.notify(entity));
1784 }
1785
1786 #[track_caller]
1790 pub fn spawn<AsyncFn, R>(&self, cx: &App, f: AsyncFn) -> Task<R>
1791 where
1792 R: 'static,
1793 AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
1794 {
1795 let handle = self.handle;
1796 cx.spawn(async move |app| {
1797 let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
1798 f(&mut async_window_cx).await
1799 })
1800 }
1801
1802 #[track_caller]
1806 pub fn spawn_with_priority<AsyncFn, R>(
1807 &self,
1808 priority: Priority,
1809 cx: &App,
1810 f: AsyncFn,
1811 ) -> Task<R>
1812 where
1813 R: 'static,
1814 AsyncFn: AsyncFnOnce(&mut AsyncWindowContext) -> R + 'static,
1815 {
1816 let handle = self.handle;
1817 cx.spawn_with_priority(priority, async move |app| {
1818 let mut async_window_cx = AsyncWindowContext::new_context(app.clone(), handle);
1819 f(&mut async_window_cx).await
1820 })
1821 }
1822
1823 fn bounds_changed(&mut self, cx: &mut App) {
1824 self.scale_factor = self.platform_window.scale_factor();
1825 self.viewport_size = self.platform_window.content_size();
1826 self.display_id = self.platform_window.display().map(|display| display.id());
1827
1828 self.refresh();
1829
1830 self.bounds_observers
1831 .clone()
1832 .retain(&(), |callback| callback(self, cx));
1833 }
1834
1835 pub fn bounds(&self) -> Bounds<Pixels> {
1837 self.platform_window.bounds()
1838 }
1839
1840 pub fn resize(&mut self, size: Size<Pixels>) {
1842 self.platform_window.resize(size);
1843 }
1844
1845 pub fn is_fullscreen(&self) -> bool {
1847 self.platform_window.is_fullscreen()
1848 }
1849
1850 pub(crate) fn appearance_changed(&mut self, cx: &mut App) {
1851 self.appearance = self.platform_window.appearance();
1852
1853 self.appearance_observers
1854 .clone()
1855 .retain(&(), |callback| callback(self, cx));
1856 }
1857
1858 pub fn appearance(&self) -> WindowAppearance {
1860 self.appearance
1861 }
1862
1863 pub fn viewport_size(&self) -> Size<Pixels> {
1865 self.viewport_size
1866 }
1867
1868 pub fn is_window_active(&self) -> bool {
1870 self.active.get()
1871 }
1872
1873 pub fn is_window_hovered(&self) -> bool {
1877 if cfg!(any(
1878 target_os = "windows",
1879 target_os = "linux",
1880 target_os = "freebsd"
1881 )) {
1882 self.hovered.get()
1883 } else {
1884 self.is_window_active()
1885 }
1886 }
1887
1888 pub fn zoom_window(&self) {
1890 self.platform_window.zoom();
1891 }
1892
1893 pub fn show_window_menu(&self, position: Point<Pixels>) {
1895 self.platform_window.show_window_menu(position)
1896 }
1897
1898 pub fn start_window_move(&self) {
1903 self.platform_window.start_window_move()
1904 }
1905
1906 pub fn set_client_inset(&mut self, inset: Pixels) {
1908 self.client_inset = Some(inset);
1909 self.platform_window.set_client_inset(inset);
1910 }
1911
1912 pub fn client_inset(&self) -> Option<Pixels> {
1914 self.client_inset
1915 }
1916
1917 pub fn window_decorations(&self) -> Decorations {
1919 self.platform_window.window_decorations()
1920 }
1921
1922 pub fn window_controls(&self) -> WindowControls {
1924 self.platform_window.window_controls()
1925 }
1926
1927 pub fn set_window_title(&mut self, title: &str) {
1929 self.platform_window.set_title(title);
1930 }
1931
1932 pub fn set_app_id(&mut self, app_id: &str) {
1934 self.platform_window.set_app_id(app_id);
1935 }
1936
1937 pub fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) {
1939 self.platform_window
1940 .set_background_appearance(background_appearance);
1941 }
1942
1943 pub fn set_window_edited(&mut self, edited: bool) {
1945 self.platform_window.set_edited(edited);
1946 }
1947
1948 pub fn display(&self, cx: &App) -> Option<Rc<dyn PlatformDisplay>> {
1950 cx.platform
1951 .displays()
1952 .into_iter()
1953 .find(|display| Some(display.id()) == self.display_id)
1954 }
1955
1956 pub fn show_character_palette(&self) {
1958 self.platform_window.show_character_palette();
1959 }
1960
1961 pub fn scale_factor(&self) -> f32 {
1965 self.scale_factor
1966 }
1967
1968 pub fn rem_size(&self) -> Pixels {
1971 self.rem_size_override_stack
1972 .last()
1973 .copied()
1974 .unwrap_or(self.rem_size)
1975 }
1976
1977 pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
1980 self.rem_size = rem_size.into();
1981 }
1982
1983 pub fn with_global_id<R>(
1986 &mut self,
1987 element_id: ElementId,
1988 f: impl FnOnce(&GlobalElementId, &mut Self) -> R,
1989 ) -> R {
1990 self.element_id_stack.push(element_id);
1991 let global_id = GlobalElementId(Arc::from(&*self.element_id_stack));
1992
1993 let result = f(&global_id, self);
1994 self.element_id_stack.pop();
1995 result
1996 }
1997
1998 #[inline]
2004 pub fn with_rem_size<F, R>(&mut self, rem_size: Option<impl Into<Pixels>>, f: F) -> R
2005 where
2006 F: FnOnce(&mut Self) -> R,
2007 {
2008 self.invalidator.debug_assert_paint_or_prepaint();
2009
2010 if let Some(rem_size) = rem_size {
2011 self.rem_size_override_stack.push(rem_size.into());
2012 let result = f(self);
2013 self.rem_size_override_stack.pop();
2014 result
2015 } else {
2016 f(self)
2017 }
2018 }
2019
2020 pub fn line_height(&self) -> Pixels {
2022 self.text_style().line_height_in_pixels(self.rem_size())
2023 }
2024
2025 pub fn prevent_default(&mut self) {
2028 self.default_prevented = true;
2029 }
2030
2031 pub fn default_prevented(&self) -> bool {
2033 self.default_prevented
2034 }
2035
2036 pub fn register_render_layer<F>(&mut self, key: impl Into<ElementId>, order: i32, build: F)
2046 where
2047 F: Fn(&mut Window, &mut App) -> AnyElement + 'static,
2048 {
2049 let key = key.into();
2050 let build: RenderLayerBuilder = Arc::new(build);
2051
2052 if let Some(registration) = self.render_layers.get_mut(&key) {
2053 registration.order = order;
2054 registration.build = build;
2055 return;
2056 }
2057
2058 let seq = self.next_render_layer_seq;
2059 self.next_render_layer_seq = self.next_render_layer_seq.saturating_add(1);
2060 self.render_layers.insert(
2061 key,
2062 RenderLayerRegistration {
2063 order,
2064 seq,
2065 build,
2066 },
2067 );
2068 }
2069
2070 pub fn unregister_render_layer(&mut self, key: &ElementId) {
2072 self.render_layers.remove(key);
2073 }
2074
2075 pub fn has_render_layer(&self, key: &ElementId) -> bool {
2077 self.render_layers.contains_key(key)
2078 }
2079
2080 pub fn is_action_available(&self, action: &dyn Action, cx: &App) -> bool {
2082 let node_id =
2083 self.focus_node_id_in_rendered_frame(self.focused(cx).map(|handle| handle.id));
2084 self.rendered_frame
2085 .dispatch_tree
2086 .is_action_available(action, node_id)
2087 }
2088
2089 pub fn is_action_available_in(&self, action: &dyn Action, focus_handle: &FocusHandle) -> bool {
2091 let node_id = self.focus_node_id_in_rendered_frame(Some(focus_handle.id));
2092 self.rendered_frame
2093 .dispatch_tree
2094 .is_action_available(action, node_id)
2095 }
2096
2097 pub fn mouse_position(&self) -> Point<Pixels> {
2099 self.mouse_position
2100 }
2101
2102 pub fn hit_test_ids(&self, position: Point<Pixels>) -> SmallVec<[HitboxId; 8]> {
2106 self.rendered_frame.hit_test(position).ids
2107 }
2108
2109 pub fn modifiers(&self) -> Modifiers {
2111 self.modifiers
2112 }
2113
2114 pub fn last_input_was_keyboard(&self) -> bool {
2117 self.last_input_modality == InputModality::Keyboard
2118 }
2119
2120 pub fn capslock(&self) -> Capslock {
2122 self.capslock
2123 }
2124
2125 fn complete_frame(&self) {
2126 self.platform_window.completed_frame();
2127 }
2128
2129 #[profiling::function]
2132 pub fn draw(&mut self, cx: &mut App) -> ArenaClearNeeded {
2133 self.frame_seq = self.frame_seq.wrapping_add(1);
2134
2135 self.invalidate_entities();
2136 cx.entities.clear_accessed();
2137 debug_assert!(self.rendered_entity_stack.is_empty());
2138 self.invalidator.set_dirty(false);
2139 self.requested_autoscroll = None;
2140
2141 if let Some(input_handler) = self.platform_window.take_input_handler() {
2143 self.rendered_frame.input_handlers.push(Some(input_handler));
2144 }
2145 if !cx.mode.skip_drawing() {
2146 self.draw_roots(cx);
2147 }
2148 self.dirty_views.clear();
2149 self.next_frame.window_active = self.active.get();
2150
2151 if let Some(input_handler) = self.next_frame.input_handlers.pop() {
2153 self.platform_window
2154 .set_input_handler(input_handler.unwrap());
2155 }
2156
2157 self.layout_engine.as_mut().unwrap().clear();
2158 self.text_system().finish_frame();
2159 self.next_frame.finish(&mut self.rendered_frame);
2160
2161 self.invalidator.set_phase(DrawPhase::Focus);
2162 let previous_focus_path = self.rendered_frame.focus_path();
2163 let previous_window_active = self.rendered_frame.window_active;
2164 mem::swap(&mut self.rendered_frame, &mut self.next_frame);
2165 self.next_frame.clear();
2166 let current_focus_path = self.rendered_frame.focus_path();
2167 let current_window_active = self.rendered_frame.window_active;
2168
2169 if previous_focus_path != current_focus_path
2170 || previous_window_active != current_window_active
2171 {
2172 if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
2173 self.focus_lost_listeners
2174 .clone()
2175 .retain(&(), |listener| listener(self, cx));
2176 }
2177
2178 let event = WindowFocusEvent {
2179 previous_focus_path: if previous_window_active {
2180 previous_focus_path
2181 } else {
2182 Default::default()
2183 },
2184 current_focus_path: if current_window_active {
2185 current_focus_path
2186 } else {
2187 Default::default()
2188 },
2189 };
2190 self.focus_listeners
2191 .clone()
2192 .retain(&(), |listener| listener(&event, self, cx));
2193 }
2194
2195 debug_assert!(self.rendered_entity_stack.is_empty());
2196 self.record_entities_accessed(cx);
2197 self.reset_cursor_style(cx);
2198 self.refreshing = false;
2199 self.invalidator.set_phase(DrawPhase::None);
2200 self.needs_present.set(true);
2201
2202 ArenaClearNeeded
2203 }
2204
2205 pub fn frame_seq(&self) -> u64 {
2207 self.frame_seq
2208 }
2209
2210 fn record_entities_accessed(&mut self, cx: &mut App) {
2211 let mut entities_ref = cx.entities.accessed_entities.borrow_mut();
2212 let mut entities = mem::take(entities_ref.deref_mut());
2213 drop(entities_ref);
2214 let handle = self.handle;
2215 cx.record_entities_accessed(
2216 handle,
2217 self.invalidator.clone(),
2219 &entities,
2220 );
2221 let mut entities_ref = cx.entities.accessed_entities.borrow_mut();
2222 mem::swap(&mut entities, entities_ref.deref_mut());
2223 }
2224
2225 fn invalidate_entities(&mut self) {
2226 let mut views = self.invalidator.take_views();
2227 for entity in views.drain() {
2228 self.mark_view_dirty(entity);
2229 }
2230 self.invalidator.replace_views(views);
2231 }
2232
2233 #[profiling::function]
2234 fn present(&self) {
2235 self.platform_window.draw(&self.rendered_frame.scene);
2236 self.needs_present.set(false);
2237 profiling::finish_frame!();
2238 }
2239
2240 fn prepaint_render_layers(
2241 &mut self,
2242 root_size: Size<Pixels>,
2243 cx: &mut App,
2244 ) -> Vec<(ElementId, AnyElement)> {
2245 if self.render_layers.is_empty() {
2246 return Vec::new();
2247 }
2248
2249 let mut layers: Vec<(ElementId, i32, usize, RenderLayerBuilder)> = self
2250 .render_layers
2251 .iter()
2252 .map(|(key, reg)| (key.clone(), reg.order, reg.seq, reg.build.clone()))
2253 .collect();
2254 layers.sort_by_key(|(_, order, seq, _)| (*order, *seq));
2255
2256 let root_view_id = self.root.as_ref().map(|v| v.entity_id());
2259 let mut elements: Vec<(ElementId, AnyElement)> = Vec::with_capacity(layers.len());
2260 if let Some(root_view_id) = root_view_id {
2261 self.with_rendered_view(root_view_id, |window| {
2262 for (key, _order, _seq, build) in layers {
2263 let mut element = (&*build)(window, cx);
2264 window.element_id_stack.push(key.clone());
2265 element.prepaint_as_root(Point::default(), root_size.into(), window, cx);
2266 window.element_id_stack.pop();
2267 elements.push((key, element));
2268 }
2269 });
2270 } else {
2271 for (key, _order, _seq, build) in layers {
2272 let mut element = (&*build)(self, cx);
2273 self.element_id_stack.push(key.clone());
2274 element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2275 self.element_id_stack.pop();
2276 elements.push((key, element));
2277 }
2278 }
2279
2280 elements
2281 }
2282
2283 fn paint_render_layers(&mut self, elements: &mut [(ElementId, AnyElement)], cx: &mut App) {
2284 let root_view_id = self.root.as_ref().map(|v| v.entity_id());
2285 if let Some(root_view_id) = root_view_id {
2286 self.with_rendered_view(root_view_id, |window| {
2287 for (key, element) in elements.iter_mut() {
2288 window.element_id_stack.push(key.clone());
2289 element.paint(window, cx);
2290 window.element_id_stack.pop();
2291 }
2292 });
2293 return;
2294 }
2295
2296 for (key, element) in elements.iter_mut() {
2297 self.element_id_stack.push(key.clone());
2298 element.paint(self, cx);
2299 self.element_id_stack.pop();
2300 }
2301 }
2302
2303 fn draw_roots(&mut self, cx: &mut App) {
2304 self.invalidator.set_phase(DrawPhase::Prepaint);
2305 self.tooltip_bounds.take();
2306
2307 let _inspector_width: Pixels = rems(30.0).to_pixels(self.rem_size());
2308 let root_size = {
2309 #[cfg(any(feature = "inspector", debug_assertions))]
2310 {
2311 if self.inspector.is_some() {
2312 let mut size = self.viewport_size;
2313 size.width = (size.width - _inspector_width).max(px(0.0));
2314 size
2315 } else {
2316 self.viewport_size
2317 }
2318 }
2319 #[cfg(not(any(feature = "inspector", debug_assertions)))]
2320 {
2321 self.viewport_size
2322 }
2323 };
2324
2325 let mut root_element = self.root.as_ref().unwrap().clone().into_any();
2327 root_element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2328
2329 let mut render_layer_elements = self.prepaint_render_layers(root_size, cx);
2330
2331 #[cfg(any(feature = "inspector", debug_assertions))]
2332 let inspector_element = self.prepaint_inspector(_inspector_width, cx);
2333
2334 let mut sorted_deferred_draws =
2335 (0..self.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();
2336 sorted_deferred_draws.sort_by_key(|ix| self.next_frame.deferred_draws[*ix].priority);
2337 self.prepaint_deferred_draws(&sorted_deferred_draws, cx);
2338
2339 let mut prompt_element = None;
2340 let mut active_drag_element = None;
2341 let mut tooltip_element = None;
2342 if let Some(prompt) = self.prompt.take() {
2343 let mut element = prompt.view.any_view().into_any();
2344 element.prepaint_as_root(Point::default(), root_size.into(), self, cx);
2345 prompt_element = Some(element);
2346 self.prompt = Some(prompt);
2347 } else if let Some(active_drag) = cx.active_drag.take() {
2348 let mut element = active_drag.view.clone().into_any();
2349 let offset = self.mouse_position() - active_drag.cursor_offset;
2350 element.prepaint_as_root(offset, AvailableSpace::min_size(), self, cx);
2351 active_drag_element = Some(element);
2352 cx.active_drag = Some(active_drag);
2353 } else {
2354 tooltip_element = self.prepaint_tooltip(cx);
2355 }
2356
2357 self.mouse_hit_test = self.next_frame.hit_test(self.mouse_position);
2358
2359 self.invalidator.set_phase(DrawPhase::Paint);
2361 root_element.paint(self, cx);
2362
2363 self.paint_render_layers(&mut render_layer_elements, cx);
2364
2365 #[cfg(any(feature = "inspector", debug_assertions))]
2366 self.paint_inspector(inspector_element, cx);
2367
2368 self.paint_deferred_draws(&sorted_deferred_draws, cx);
2369
2370 if let Some(mut prompt_element) = prompt_element {
2371 prompt_element.paint(self, cx);
2372 } else if let Some(mut drag_element) = active_drag_element {
2373 drag_element.paint(self, cx);
2374 } else if let Some(mut tooltip_element) = tooltip_element {
2375 tooltip_element.paint(self, cx);
2376 }
2377
2378 #[cfg(any(feature = "inspector", debug_assertions))]
2379 self.paint_inspector_hitbox(cx);
2380 }
2381
2382 fn prepaint_tooltip(&mut self, cx: &mut App) -> Option<AnyElement> {
2383 for tooltip_request_index in (0..self.next_frame.tooltip_requests.len()).rev() {
2385 let Some(Some(tooltip_request)) = self
2386 .next_frame
2387 .tooltip_requests
2388 .get(tooltip_request_index)
2389 .cloned()
2390 else {
2391 log::error!("Unexpectedly absent TooltipRequest");
2392 continue;
2393 };
2394 let mut element = tooltip_request.tooltip.view.clone().into_any();
2395 let mouse_position = tooltip_request.tooltip.mouse_position;
2396 let tooltip_size = element.layout_as_root(AvailableSpace::min_size(), self, cx);
2397
2398 let mut tooltip_bounds =
2399 Bounds::new(mouse_position + point(px(1.), px(1.)), tooltip_size);
2400 let window_bounds = Bounds {
2401 origin: Point::default(),
2402 size: self.viewport_size(),
2403 };
2404
2405 if tooltip_bounds.right() > window_bounds.right() {
2406 let new_x = mouse_position.x - tooltip_bounds.size.width - px(1.);
2407 if new_x >= Pixels::ZERO {
2408 tooltip_bounds.origin.x = new_x;
2409 } else {
2410 tooltip_bounds.origin.x = cmp::max(
2411 Pixels::ZERO,
2412 tooltip_bounds.origin.x - tooltip_bounds.right() - window_bounds.right(),
2413 );
2414 }
2415 }
2416
2417 if tooltip_bounds.bottom() > window_bounds.bottom() {
2418 let new_y = mouse_position.y - tooltip_bounds.size.height - px(1.);
2419 if new_y >= Pixels::ZERO {
2420 tooltip_bounds.origin.y = new_y;
2421 } else {
2422 tooltip_bounds.origin.y = cmp::max(
2423 Pixels::ZERO,
2424 tooltip_bounds.origin.y - tooltip_bounds.bottom() - window_bounds.bottom(),
2425 );
2426 }
2427 }
2428
2429 let is_visible =
2433 (tooltip_request.tooltip.check_visible_and_update)(tooltip_bounds, self, cx);
2434 if !is_visible {
2435 continue;
2436 }
2437
2438 self.with_absolute_element_offset(tooltip_bounds.origin, |window| {
2439 element.prepaint(window, cx)
2440 });
2441
2442 self.tooltip_bounds = Some(TooltipBounds {
2443 id: tooltip_request.id,
2444 bounds: tooltip_bounds,
2445 });
2446 return Some(element);
2447 }
2448 None
2449 }
2450
2451 fn prepaint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {
2452 assert_eq!(self.element_id_stack.len(), 0);
2453
2454 let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
2455 for deferred_draw_ix in deferred_draw_indices {
2456 let deferred_draw = &mut deferred_draws[*deferred_draw_ix];
2457 self.element_id_stack
2458 .clone_from(&deferred_draw.element_id_stack);
2459 self.text_style_stack
2460 .clone_from(&deferred_draw.text_style_stack);
2461 self.next_frame
2462 .dispatch_tree
2463 .set_active_node(deferred_draw.parent_node);
2464
2465 let prepaint_start = self.prepaint_index();
2466 if let Some(element) = deferred_draw.element.as_mut() {
2467 self.with_rendered_view(deferred_draw.current_view, |window| {
2468 window.with_absolute_element_offset(deferred_draw.absolute_offset, |window| {
2469 element.prepaint(window, cx)
2470 });
2471 })
2472 } else {
2473 self.reuse_prepaint(deferred_draw.prepaint_range.clone());
2474 }
2475 let prepaint_end = self.prepaint_index();
2476 deferred_draw.prepaint_range = prepaint_start..prepaint_end;
2477 }
2478 assert_eq!(
2479 self.next_frame.deferred_draws.len(),
2480 0,
2481 "cannot call defer_draw during deferred drawing"
2482 );
2483 self.next_frame.deferred_draws = deferred_draws;
2484 self.element_id_stack.clear();
2485 self.text_style_stack.clear();
2486 }
2487
2488 fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize], cx: &mut App) {
2489 assert_eq!(self.element_id_stack.len(), 0);
2490
2491 let mut deferred_draws = mem::take(&mut self.next_frame.deferred_draws);
2492 for deferred_draw_ix in deferred_draw_indices {
2493 let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];
2494 self.element_id_stack
2495 .clone_from(&deferred_draw.element_id_stack);
2496 self.next_frame
2497 .dispatch_tree
2498 .set_active_node(deferred_draw.parent_node);
2499
2500 let paint_start = self.paint_index();
2501 if let Some(element) = deferred_draw.element.as_mut() {
2502 self.with_rendered_view(deferred_draw.current_view, |window| {
2503 element.paint(window, cx);
2504 })
2505 } else {
2506 self.reuse_paint(deferred_draw.paint_range.clone());
2507 }
2508 let paint_end = self.paint_index();
2509 deferred_draw.paint_range = paint_start..paint_end;
2510 }
2511 self.next_frame.deferred_draws = deferred_draws;
2512 self.element_id_stack.clear();
2513 }
2514
2515 pub(crate) fn prepaint_index(&self) -> PrepaintStateIndex {
2516 PrepaintStateIndex {
2517 hitboxes_index: self.next_frame.hitboxes.len(),
2518 tooltips_index: self.next_frame.tooltip_requests.len(),
2519 deferred_draws_index: self.next_frame.deferred_draws.len(),
2520 dispatch_tree_index: self.next_frame.dispatch_tree.len(),
2521 accessed_element_states_index: self.next_frame.accessed_element_states.len(),
2522 line_layout_index: self.text_system.layout_index(),
2523 }
2524 }
2525
2526 pub(crate) fn reuse_prepaint(&mut self, range: Range<PrepaintStateIndex>) {
2527 self.next_frame.hitboxes.extend(
2528 self.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
2529 .iter()
2530 .cloned(),
2531 );
2532 self.next_frame.tooltip_requests.extend(
2533 self.rendered_frame.tooltip_requests
2534 [range.start.tooltips_index..range.end.tooltips_index]
2535 .iter_mut()
2536 .map(|request| request.take()),
2537 );
2538 self.next_frame.accessed_element_states.extend(
2539 self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
2540 ..range.end.accessed_element_states_index]
2541 .iter()
2542 .map(|(id, type_id)| (id.clone(), *type_id)),
2543 );
2544 self.text_system
2545 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
2546
2547 let reused_subtree = self.next_frame.dispatch_tree.reuse_subtree(
2548 range.start.dispatch_tree_index..range.end.dispatch_tree_index,
2549 &mut self.rendered_frame.dispatch_tree,
2550 self.focus,
2551 );
2552
2553 if reused_subtree.contains_focus() {
2554 self.next_frame.focus = self.focus;
2555 }
2556
2557 self.next_frame.deferred_draws.extend(
2558 self.rendered_frame.deferred_draws
2559 [range.start.deferred_draws_index..range.end.deferred_draws_index]
2560 .iter()
2561 .map(|deferred_draw| DeferredDraw {
2562 current_view: deferred_draw.current_view,
2563 parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
2564 element_id_stack: deferred_draw.element_id_stack.clone(),
2565 text_style_stack: deferred_draw.text_style_stack.clone(),
2566 priority: deferred_draw.priority,
2567 element: None,
2568 absolute_offset: deferred_draw.absolute_offset,
2569 prepaint_range: deferred_draw.prepaint_range.clone(),
2570 paint_range: deferred_draw.paint_range.clone(),
2571 }),
2572 );
2573 }
2574
2575 pub(crate) fn paint_index(&self) -> PaintIndex {
2576 PaintIndex {
2577 scene_index: self.next_frame.scene.len(),
2578 mouse_listeners_index: self.next_frame.mouse_listeners.len(),
2579 input_handlers_index: self.next_frame.input_handlers.len(),
2580 cursor_styles_index: self.next_frame.cursor_styles.len(),
2581 accessed_element_states_index: self.next_frame.accessed_element_states.len(),
2582 tab_handle_index: self.next_frame.tab_stops.paint_index(),
2583 line_layout_index: self.text_system.layout_index(),
2584 }
2585 }
2586
2587 pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
2588 self.next_frame.cursor_styles.extend(
2589 self.rendered_frame.cursor_styles
2590 [range.start.cursor_styles_index..range.end.cursor_styles_index]
2591 .iter()
2592 .cloned(),
2593 );
2594 self.next_frame.input_handlers.extend(
2595 self.rendered_frame.input_handlers
2596 [range.start.input_handlers_index..range.end.input_handlers_index]
2597 .iter_mut()
2598 .map(|handler| handler.take()),
2599 );
2600 self.next_frame.mouse_listeners.extend(
2601 self.rendered_frame.mouse_listeners
2602 [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
2603 .iter_mut()
2604 .map(|listener| listener.take()),
2605 );
2606 self.next_frame.accessed_element_states.extend(
2607 self.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
2608 ..range.end.accessed_element_states_index]
2609 .iter()
2610 .map(|(id, type_id)| (id.clone(), *type_id)),
2611 );
2612 self.next_frame.tab_stops.replay(
2613 &self.rendered_frame.tab_stops.insertion_history
2614 [range.start.tab_handle_index..range.end.tab_handle_index],
2615 );
2616
2617 self.text_system
2618 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
2619 self.next_frame.scene.replay(
2620 range.start.scene_index..range.end.scene_index,
2621 &self.rendered_frame.scene,
2622 );
2623 }
2624
2625 #[inline]
2631 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
2632 where
2633 F: FnOnce(&mut Self) -> R,
2634 {
2635 self.invalidator.debug_assert_paint_or_prepaint();
2636 if let Some(style) = style {
2637 self.text_style_stack.push(style);
2638 let result = f(self);
2639 self.text_style_stack.pop();
2640 result
2641 } else {
2642 f(self)
2643 }
2644 }
2645
2646 pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
2649 self.invalidator.debug_assert_paint();
2650 self.next_frame.cursor_styles.push(CursorStyleRequest {
2651 hitbox_id: Some(hitbox.id),
2652 style,
2653 });
2654 }
2655
2656 pub fn set_window_cursor_style(&mut self, style: CursorStyle) {
2661 self.invalidator.debug_assert_paint();
2662 self.next_frame.cursor_styles.push(CursorStyleRequest {
2663 hitbox_id: None,
2664 style,
2665 })
2666 }
2667
2668 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) -> TooltipId {
2671 self.invalidator.debug_assert_prepaint();
2672 let id = TooltipId(post_inc(&mut self.next_tooltip_id.0));
2673 self.next_frame
2674 .tooltip_requests
2675 .push(Some(TooltipRequest { id, tooltip }));
2676 id
2677 }
2678
2679 #[inline]
2684 pub fn with_content_mask<R>(
2685 &mut self,
2686 mask: Option<ContentMask<Pixels>>,
2687 f: impl FnOnce(&mut Self) -> R,
2688 ) -> R {
2689 self.invalidator.debug_assert_paint_or_prepaint();
2690 if let Some(mask) = mask {
2691 let mask = mask.intersect(&self.content_mask());
2692 self.content_mask_stack.push(mask);
2693 let result = f(self);
2694 self.content_mask_stack.pop();
2695 result
2696 } else {
2697 f(self)
2698 }
2699 }
2700
2701 pub fn with_element_offset<R>(
2704 &mut self,
2705 offset: Point<Pixels>,
2706 f: impl FnOnce(&mut Self) -> R,
2707 ) -> R {
2708 self.invalidator.debug_assert_paint_or_prepaint();
2709
2710 if offset.is_zero() {
2711 return f(self);
2712 };
2713
2714 let abs_offset = self.element_offset() + offset;
2715 self.with_absolute_element_offset(abs_offset, f)
2716 }
2717
2718 pub fn with_absolute_element_offset<R>(
2722 &mut self,
2723 offset: Point<Pixels>,
2724 f: impl FnOnce(&mut Self) -> R,
2725 ) -> R {
2726 self.invalidator.debug_assert_paint_or_prepaint();
2727 self.element_offset_stack.push(offset);
2728 let result = f(self);
2729 self.element_offset_stack.pop();
2730 result
2731 }
2732
2733 pub fn with_element_opacity<R>(
2740 &mut self,
2741 opacity: Option<f32>,
2742 f: impl FnOnce(&mut Self) -> R,
2743 ) -> R {
2744 self.invalidator.debug_assert_paint_or_prepaint();
2745
2746 let Some(opacity) = opacity else {
2747 return f(self);
2748 };
2749
2750 let previous_opacity = self.element_opacity;
2751 self.element_opacity = previous_opacity * opacity;
2752 let result = f(self);
2753 self.element_opacity = previous_opacity;
2754 result
2755 }
2756
2757 pub fn transact<T, U>(&mut self, f: impl FnOnce(&mut Self) -> Result<T, U>) -> Result<T, U> {
2763 self.invalidator.debug_assert_prepaint();
2764 let index = self.prepaint_index();
2765 let result = f(self);
2766 if result.is_err() {
2767 self.next_frame.hitboxes.truncate(index.hitboxes_index);
2768 self.next_frame
2769 .tooltip_requests
2770 .truncate(index.tooltips_index);
2771 self.next_frame
2772 .deferred_draws
2773 .truncate(index.deferred_draws_index);
2774 self.next_frame
2775 .dispatch_tree
2776 .truncate(index.dispatch_tree_index);
2777 self.next_frame
2778 .accessed_element_states
2779 .truncate(index.accessed_element_states_index);
2780 self.text_system.truncate_layouts(index.line_layout_index);
2781 }
2782 result
2783 }
2784
2785 pub fn request_autoscroll(&mut self, bounds: Bounds<Pixels>) {
2791 self.invalidator.debug_assert_prepaint();
2792 self.requested_autoscroll = Some(bounds);
2793 }
2794
2795 pub fn take_autoscroll(&mut self) -> Option<Bounds<Pixels>> {
2798 self.invalidator.debug_assert_prepaint();
2799 self.requested_autoscroll.take()
2800 }
2801
2802 pub fn use_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
2808 let (task, is_first) = cx.fetch_asset::<A>(source);
2809 task.clone().now_or_never().or_else(|| {
2810 if is_first {
2811 let entity_id = self.current_view();
2812 self.spawn(cx, {
2813 let task = task.clone();
2814 async move |cx| {
2815 task.await;
2816
2817 cx.on_next_frame(move |_, cx| {
2818 cx.notify(entity_id);
2819 });
2820 }
2821 })
2822 .detach();
2823 }
2824
2825 None
2826 })
2827 }
2828
2829 pub fn get_asset<A: Asset>(&mut self, source: &A::Source, cx: &mut App) -> Option<A::Output> {
2835 let (task, _) = cx.fetch_asset::<A>(source);
2836 task.now_or_never()
2837 }
2838 pub fn element_offset(&self) -> Point<Pixels> {
2840 self.invalidator.debug_assert_paint_or_prepaint();
2841 self.element_offset_stack
2842 .last()
2843 .copied()
2844 .unwrap_or_default()
2845 }
2846
2847 #[inline]
2850 pub(crate) fn element_opacity(&self) -> f32 {
2851 self.invalidator.debug_assert_paint_or_prepaint();
2852 self.element_opacity
2853 }
2854
2855 pub fn content_mask(&self) -> ContentMask<Pixels> {
2857 self.invalidator.debug_assert_paint_or_prepaint();
2858 self.content_mask_stack
2859 .last()
2860 .cloned()
2861 .unwrap_or_else(|| ContentMask {
2862 bounds: Bounds {
2863 origin: Point::default(),
2864 size: self.viewport_size,
2865 },
2866 })
2867 }
2868
2869 pub fn with_element_namespace<R>(
2872 &mut self,
2873 element_id: impl Into<ElementId>,
2874 f: impl FnOnce(&mut Self) -> R,
2875 ) -> R {
2876 self.element_id_stack.push(element_id.into());
2877 let result = f(self);
2878 self.element_id_stack.pop();
2879 result
2880 }
2881
2882 pub fn use_keyed_state<S: 'static>(
2884 &mut self,
2885 key: impl Into<ElementId>,
2886 cx: &mut App,
2887 init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
2888 ) -> Entity<S> {
2889 let current_view = self.current_view();
2890 self.with_global_id(key.into(), |global_id, window| {
2891 window.with_element_state(global_id, |state: Option<Entity<S>>, window| {
2892 if let Some(state) = state {
2893 (state.clone(), state)
2894 } else {
2895 let new_state = cx.new(|cx| init(window, cx));
2896 cx.observe(&new_state, move |_, cx| {
2897 cx.notify(current_view);
2898 })
2899 .detach();
2900 (new_state.clone(), new_state)
2901 }
2902 })
2903 })
2904 }
2905
2906 pub fn with_id<R>(&mut self, id: impl Into<ElementId>, f: impl FnOnce(&mut Self) -> R) -> R {
2908 self.with_global_id(id.into(), |_, window| f(window))
2909 }
2910
2911 #[track_caller]
2917 pub fn use_state<S: 'static>(
2918 &mut self,
2919 cx: &mut App,
2920 init: impl FnOnce(&mut Self, &mut Context<S>) -> S,
2921 ) -> Entity<S> {
2922 self.use_keyed_state(
2923 ElementId::CodeLocation(*core::panic::Location::caller()),
2924 cx,
2925 init,
2926 )
2927 }
2928
2929 pub fn with_element_state<S, R>(
2934 &mut self,
2935 global_id: &GlobalElementId,
2936 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
2937 ) -> R
2938 where
2939 S: 'static,
2940 {
2941 self.invalidator.debug_assert_paint_or_prepaint();
2942
2943 let key = (global_id.clone(), TypeId::of::<S>());
2944 self.next_frame.accessed_element_states.push(key.clone());
2945
2946 if let Some(any) = self
2947 .next_frame
2948 .element_states
2949 .remove(&key)
2950 .or_else(|| self.rendered_frame.element_states.remove(&key))
2951 {
2952 let ElementStateBox {
2953 inner,
2954 #[cfg(debug_assertions)]
2955 type_name,
2956 } = any;
2957 let mut state_box = inner
2959 .downcast::<Option<S>>()
2960 .map_err(|_| {
2961 #[cfg(debug_assertions)]
2962 {
2963 anyhow::anyhow!(
2964 "invalid element state type for id, requested {:?}, actual: {:?}",
2965 std::any::type_name::<S>(),
2966 type_name
2967 )
2968 }
2969
2970 #[cfg(not(debug_assertions))]
2971 {
2972 anyhow::anyhow!(
2973 "invalid element state type for id, requested {:?}",
2974 std::any::type_name::<S>(),
2975 )
2976 }
2977 })
2978 .unwrap();
2979
2980 let state = state_box.take().expect(
2981 "reentrant call to with_element_state for the same state type and element id",
2982 );
2983 let (result, state) = f(Some(state), self);
2984 state_box.replace(state);
2985 self.next_frame.element_states.insert(
2986 key,
2987 ElementStateBox {
2988 inner: state_box,
2989 #[cfg(debug_assertions)]
2990 type_name,
2991 },
2992 );
2993 result
2994 } else {
2995 let (result, state) = f(None, self);
2996 self.next_frame.element_states.insert(
2997 key,
2998 ElementStateBox {
2999 inner: Box::new(Some(state)),
3000 #[cfg(debug_assertions)]
3001 type_name: std::any::type_name::<S>(),
3002 },
3003 );
3004 result
3005 }
3006 }
3007
3008 pub fn with_optional_element_state<S, R>(
3015 &mut self,
3016 global_id: Option<&GlobalElementId>,
3017 f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
3018 ) -> R
3019 where
3020 S: 'static,
3021 {
3022 self.invalidator.debug_assert_paint_or_prepaint();
3023
3024 if let Some(global_id) = global_id {
3025 self.with_element_state(global_id, |state, cx| {
3026 let (result, state) = f(Some(state), cx);
3027 let state =
3028 state.expect("you must return some state when you pass some element id");
3029 (result, state)
3030 })
3031 } else {
3032 let (result, state) = f(None, self);
3033 debug_assert!(
3034 state.is_none(),
3035 "you must not return an element state when passing None for the global id"
3036 );
3037 result
3038 }
3039 }
3040
3041 #[inline]
3043 pub fn with_tab_group<R>(&mut self, index: Option<isize>, f: impl FnOnce(&mut Self) -> R) -> R {
3044 if let Some(index) = index {
3045 self.next_frame.tab_stops.begin_group(index);
3046 let result = f(self);
3047 self.next_frame.tab_stops.end_group();
3048 result
3049 } else {
3050 f(self)
3051 }
3052 }
3053
3054 pub fn register_tab_stop(&mut self, focus_handle: &FocusHandle, tab_index: isize) {
3058 self.invalidator.debug_assert_paint();
3059 let handle = focus_handle.clone().tab_stop(true).tab_index(tab_index);
3060 self.next_frame.tab_stops.insert(&handle);
3061 }
3062
3063 pub fn defer_draw(
3069 &mut self,
3070 element: AnyElement,
3071 absolute_offset: Point<Pixels>,
3072 priority: usize,
3073 ) {
3074 self.invalidator.debug_assert_prepaint();
3075 let parent_node = self.next_frame.dispatch_tree.active_node_id().unwrap();
3076 self.next_frame.deferred_draws.push(DeferredDraw {
3077 current_view: self.current_view(),
3078 parent_node,
3079 element_id_stack: self.element_id_stack.clone(),
3080 text_style_stack: self.text_style_stack.clone(),
3081 priority,
3082 element: Some(element),
3083 absolute_offset,
3084 prepaint_range: PrepaintStateIndex::default()..PrepaintStateIndex::default(),
3085 paint_range: PaintIndex::default()..PaintIndex::default(),
3086 });
3087 }
3088
3089 pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
3095 self.invalidator.debug_assert_paint();
3096
3097 let scale_factor = self.scale_factor();
3098 let content_mask = self.content_mask();
3099 let clipped_bounds = bounds.intersect(&content_mask.bounds);
3100 if !clipped_bounds.is_empty() {
3101 self.next_frame
3102 .scene
3103 .push_layer(clipped_bounds.scale(scale_factor));
3104 }
3105
3106 let result = f(self);
3107
3108 if !clipped_bounds.is_empty() {
3109 self.next_frame.scene.pop_layer();
3110 }
3111
3112 result
3113 }
3114
3115 pub fn paint_shadows(
3119 &mut self,
3120 bounds: Bounds<Pixels>,
3121 corner_radii: Corners<Pixels>,
3122 shadows: &[BoxShadow],
3123 ) {
3124 self.paint_shadows_with_transform(
3125 bounds,
3126 corner_radii,
3127 shadows,
3128 TransformationMatrix::unit(),
3129 );
3130 }
3131
3132 pub fn paint_shadows_with_transform(
3136 &mut self,
3137 bounds: Bounds<Pixels>,
3138 corner_radii: Corners<Pixels>,
3139 shadows: &[BoxShadow],
3140 transform: TransformationMatrix,
3141 ) {
3142 self.invalidator.debug_assert_paint();
3143
3144 let scale_factor = self.scale_factor();
3145 let content_mask = self.content_mask();
3146 let opacity = self.element_opacity();
3147 let transform = self.scale_transform_for_scene(transform);
3148 for shadow in shadows {
3149 let shadow_bounds = (bounds + shadow.offset).dilate(shadow.spread_radius);
3150 self.next_frame.scene.insert_primitive((
3151 Shadow {
3152 order: 0,
3153 blur_radius: shadow.blur_radius.scale(scale_factor),
3154 bounds: shadow_bounds.scale(scale_factor),
3155 content_mask: content_mask.scale(scale_factor),
3156 corner_radii: corner_radii.scale(scale_factor),
3157 color: shadow.color.opacity(opacity),
3158 },
3159 transform,
3160 ));
3161 }
3162 }
3163
3164 pub fn paint_quad(&mut self, quad: PaintQuad) {
3174 self.paint_quad_with_transform(quad, TransformationMatrix::unit());
3175 }
3176
3177 pub fn paint_quad_with_transform(&mut self, quad: PaintQuad, transform: TransformationMatrix) {
3181 self.invalidator.debug_assert_paint();
3182
3183 let scale_factor = self.scale_factor();
3184 let content_mask = self.content_mask();
3185 let opacity = self.element_opacity();
3186 let transform = self.scale_transform_for_scene(transform);
3187
3188 self.next_frame.scene.insert_primitive((
3189 Quad {
3190 order: 0,
3191 bounds: quad.bounds.scale(scale_factor),
3192 content_mask: content_mask.scale(scale_factor),
3193 background: quad.background.opacity(opacity),
3194 border_color: quad.border_color.opacity(opacity),
3195 corner_radii: quad.corner_radii.scale(scale_factor),
3196 border_widths: quad.border_widths.scale(scale_factor),
3197 border_style: quad.border_style,
3198 },
3199 transform,
3200 ));
3201 }
3202
3203 pub fn paint_backdrop_blur(
3207 &mut self,
3208 bounds: Bounds<Pixels>,
3209 corner_radii: Corners<Pixels>,
3210 blur_radius: Pixels,
3211 tint: Hsla,
3212 ) {
3213 self.paint_backdrop_blur_with_transform(
3214 bounds,
3215 corner_radii,
3216 blur_radius,
3217 tint,
3218 TransformationMatrix::unit(),
3219 );
3220 }
3221
3222 pub fn paint_backdrop_blur_with_transform(
3226 &mut self,
3227 bounds: Bounds<Pixels>,
3228 corner_radii: Corners<Pixels>,
3229 blur_radius: Pixels,
3230 tint: Hsla,
3231 transform: TransformationMatrix,
3232 ) {
3233 self.invalidator.debug_assert_paint();
3234
3235 let scale_factor = self.scale_factor();
3236 let content_mask = self.content_mask();
3237 let opacity = self.element_opacity();
3238 let transform = self.scale_transform_for_scene(transform);
3239
3240 self.next_frame.scene.insert_primitive((
3241 BackdropBlur {
3242 order: 0,
3243 blur_radius: blur_radius.scale(scale_factor),
3244 bounds: bounds.scale(scale_factor),
3245 corner_radii: corner_radii.scale(scale_factor),
3246 content_mask: content_mask.scale(scale_factor),
3247 tint: tint.opacity(opacity),
3248 },
3249 transform,
3250 ));
3251 }
3252
3253 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Background>) {
3257 self.invalidator.debug_assert_paint();
3258
3259 let scale_factor = self.scale_factor();
3260 let content_mask = self.content_mask();
3261 let opacity = self.element_opacity();
3262 path.content_mask = content_mask;
3263 let color: Background = color.into();
3264 path.color = color.opacity(opacity);
3265 self.next_frame
3266 .scene
3267 .insert_primitive(path.scale(scale_factor));
3268 }
3269
3270 pub fn paint_underline(
3274 &mut self,
3275 origin: Point<Pixels>,
3276 width: Pixels,
3277 style: &UnderlineStyle,
3278 ) {
3279 self.paint_underline_with_transform(origin, width, style, TransformationMatrix::unit());
3280 }
3281
3282 pub fn paint_underline_with_transform(
3286 &mut self,
3287 origin: Point<Pixels>,
3288 width: Pixels,
3289 style: &UnderlineStyle,
3290 transform: TransformationMatrix,
3291 ) {
3292 self.invalidator.debug_assert_paint();
3293
3294 let scale_factor = self.scale_factor();
3295 let height = if style.wavy {
3296 style.thickness * 3.
3297 } else {
3298 style.thickness
3299 };
3300 let bounds = Bounds {
3301 origin,
3302 size: size(width, height),
3303 };
3304 let content_mask = self.content_mask();
3305 let element_opacity = self.element_opacity();
3306 let transform = self.scale_transform_for_scene(transform);
3307
3308 self.next_frame.scene.insert_primitive((
3309 Underline {
3310 order: 0,
3311 pad: 0,
3312 bounds: bounds.scale(scale_factor),
3313 content_mask: content_mask.scale(scale_factor),
3314 color: style.color.unwrap_or_default().opacity(element_opacity),
3315 thickness: style.thickness.scale(scale_factor),
3316 wavy: if style.wavy { 1 } else { 0 },
3317 },
3318 transform,
3319 ));
3320 }
3321
3322 pub fn paint_strikethrough(
3326 &mut self,
3327 origin: Point<Pixels>,
3328 width: Pixels,
3329 style: &StrikethroughStyle,
3330 ) {
3331 self.paint_strikethrough_with_transform(origin, width, style, TransformationMatrix::unit());
3332 }
3333
3334 pub fn paint_strikethrough_with_transform(
3338 &mut self,
3339 origin: Point<Pixels>,
3340 width: Pixels,
3341 style: &StrikethroughStyle,
3342 transform: TransformationMatrix,
3343 ) {
3344 self.invalidator.debug_assert_paint();
3345
3346 let scale_factor = self.scale_factor();
3347 let height = style.thickness;
3348 let bounds = Bounds {
3349 origin,
3350 size: size(width, height),
3351 };
3352 let content_mask = self.content_mask();
3353 let opacity = self.element_opacity();
3354 let transform = self.scale_transform_for_scene(transform);
3355
3356 self.next_frame.scene.insert_primitive((
3357 Underline {
3358 order: 0,
3359 pad: 0,
3360 bounds: bounds.scale(scale_factor),
3361 content_mask: content_mask.scale(scale_factor),
3362 thickness: style.thickness.scale(scale_factor),
3363 color: style.color.unwrap_or_default().opacity(opacity),
3364 wavy: 0,
3365 },
3366 transform,
3367 ));
3368 }
3369
3370 pub fn paint_glyph(
3379 &mut self,
3380 origin: Point<Pixels>,
3381 font_id: FontId,
3382 glyph_id: GlyphId,
3383 font_size: Pixels,
3384 color: Hsla,
3385 ) -> Result<()> {
3386 self.paint_glyph_with_transform(
3387 origin,
3388 font_id,
3389 glyph_id,
3390 font_size,
3391 color,
3392 TransformationMatrix::unit(),
3393 )
3394 }
3395
3396 pub fn paint_glyph_with_transform(
3398 &mut self,
3399 origin: Point<Pixels>,
3400 font_id: FontId,
3401 glyph_id: GlyphId,
3402 font_size: Pixels,
3403 color: Hsla,
3404 transform: TransformationMatrix,
3405 ) -> Result<()> {
3406 self.invalidator.debug_assert_paint();
3407
3408 let element_opacity = self.element_opacity();
3409 let scale_factor = self.scale_factor();
3410 let glyph_origin = origin.scale(scale_factor);
3411 let transform = self.scale_transform_for_scene(transform);
3412
3413 let subpixel_variant = Point {
3414 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS_X as f32).floor() as u8,
3415 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS_Y as f32).floor() as u8,
3416 };
3417 let params = RenderGlyphParams {
3418 font_id,
3419 glyph_id,
3420 font_size,
3421 subpixel_variant,
3422 scale_factor,
3423 is_emoji: false,
3424 };
3425
3426 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
3427 if !raster_bounds.is_zero() {
3428 let tile = self
3429 .sprite_atlas
3430 .get_or_insert_with(¶ms.clone().into(), &mut || {
3431 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
3432 Ok(Some((size, Cow::Owned(bytes))))
3433 })?
3434 .expect("Callback above only errors or returns Some");
3435 let bounds = Bounds {
3436 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
3437 size: tile.bounds.size.map(Into::into),
3438 };
3439 let content_mask = self.content_mask().scale(scale_factor);
3440 self.next_frame.scene.insert_primitive(MonochromeSprite {
3441 order: 0,
3442 pad: 0,
3443 bounds,
3444 content_mask,
3445 color: color.opacity(element_opacity),
3446 tile,
3447 transformation: transform,
3448 });
3449 }
3450 Ok(())
3451 }
3452
3453 pub fn paint_emoji(
3462 &mut self,
3463 origin: Point<Pixels>,
3464 font_id: FontId,
3465 glyph_id: GlyphId,
3466 font_size: Pixels,
3467 ) -> Result<()> {
3468 self.paint_emoji_with_transform(
3469 origin,
3470 font_id,
3471 glyph_id,
3472 font_size,
3473 TransformationMatrix::unit(),
3474 )
3475 }
3476
3477 pub fn paint_emoji_with_transform(
3479 &mut self,
3480 origin: Point<Pixels>,
3481 font_id: FontId,
3482 glyph_id: GlyphId,
3483 font_size: Pixels,
3484 transform: TransformationMatrix,
3485 ) -> Result<()> {
3486 self.invalidator.debug_assert_paint();
3487
3488 let scale_factor = self.scale_factor();
3489 let glyph_origin = origin.scale(scale_factor);
3490 let transform = self.scale_transform_for_scene(transform);
3491 let params = RenderGlyphParams {
3492 font_id,
3493 glyph_id,
3494 font_size,
3495 subpixel_variant: Default::default(),
3497 scale_factor,
3498 is_emoji: true,
3499 };
3500
3501 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
3502 if !raster_bounds.is_zero() {
3503 let tile = self
3504 .sprite_atlas
3505 .get_or_insert_with(¶ms.clone().into(), &mut || {
3506 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
3507 Ok(Some((size, Cow::Owned(bytes))))
3508 })?
3509 .expect("Callback above only errors or returns Some");
3510
3511 let bounds = Bounds {
3512 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
3513 size: tile.bounds.size.map(Into::into),
3514 };
3515 let content_mask = self.content_mask().scale(scale_factor);
3516 let opacity = self.element_opacity();
3517
3518 self.next_frame.scene.insert_primitive((
3519 PolychromeSprite {
3520 order: 0,
3521 pad: 0,
3522 grayscale: false,
3523 bounds,
3524 corner_radii: Default::default(),
3525 content_mask,
3526 tile,
3527 opacity,
3528 },
3529 transform,
3530 ));
3531 }
3532 Ok(())
3533 }
3534
3535 pub fn paint_svg(
3539 &mut self,
3540 bounds: Bounds<Pixels>,
3541 path: SharedString,
3542 mut data: Option<&[u8]>,
3543 transformation: TransformationMatrix,
3544 color: Hsla,
3545 cx: &App,
3546 ) -> Result<()> {
3547 self.invalidator.debug_assert_paint();
3548
3549 let element_opacity = self.element_opacity();
3550 let scale_factor = self.scale_factor();
3551
3552 let bounds = bounds.scale(scale_factor);
3553 let params = RenderSvgParams {
3554 path,
3555 size: bounds.size.map(|pixels| {
3556 DevicePixels::from((pixels.0 * SMOOTH_SVG_SCALE_FACTOR).ceil() as i32)
3557 }),
3558 };
3559
3560 let Some(tile) =
3561 self.sprite_atlas
3562 .get_or_insert_with(¶ms.clone().into(), &mut || {
3563 let Some((size, bytes)) = cx.svg_renderer.render_alpha_mask(¶ms, data)?
3564 else {
3565 return Ok(None);
3566 };
3567 Ok(Some((size, Cow::Owned(bytes))))
3568 })?
3569 else {
3570 return Ok(());
3571 };
3572 let content_mask = self.content_mask().scale(scale_factor);
3573 let svg_bounds = Bounds {
3574 origin: bounds.center()
3575 - Point::new(
3576 ScaledPixels(tile.bounds.size.width.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
3577 ScaledPixels(tile.bounds.size.height.0 as f32 / SMOOTH_SVG_SCALE_FACTOR / 2.),
3578 ),
3579 size: tile
3580 .bounds
3581 .size
3582 .map(|value| ScaledPixels(value.0 as f32 / SMOOTH_SVG_SCALE_FACTOR)),
3583 };
3584
3585 self.next_frame.scene.insert_primitive(MonochromeSprite {
3586 order: 0,
3587 pad: 0,
3588 bounds: svg_bounds
3589 .map_origin(|origin| origin.round())
3590 .map_size(|size| size.ceil()),
3591 content_mask,
3592 color: color.opacity(element_opacity),
3593 tile,
3594 transformation,
3595 });
3596
3597 Ok(())
3598 }
3599
3600 pub fn paint_image(
3605 &mut self,
3606 bounds: Bounds<Pixels>,
3607 corner_radii: Corners<Pixels>,
3608 data: Arc<RenderImage>,
3609 frame_index: usize,
3610 grayscale: bool,
3611 ) -> Result<()> {
3612 self.paint_image_with_transform(
3613 bounds,
3614 corner_radii,
3615 data,
3616 frame_index,
3617 grayscale,
3618 TransformationMatrix::unit(),
3619 )
3620 }
3621
3622 pub fn paint_image_with_transform(
3624 &mut self,
3625 bounds: Bounds<Pixels>,
3626 corner_radii: Corners<Pixels>,
3627 data: Arc<RenderImage>,
3628 frame_index: usize,
3629 grayscale: bool,
3630 transform: TransformationMatrix,
3631 ) -> Result<()> {
3632 self.invalidator.debug_assert_paint();
3633
3634 let scale_factor = self.scale_factor();
3635 let bounds = bounds.scale(scale_factor);
3636 let params = RenderImageParams {
3637 image_id: data.id,
3638 frame_index,
3639 };
3640
3641 let tile = self
3642 .sprite_atlas
3643 .get_or_insert_with(¶ms.into(), &mut || {
3644 Ok(Some((
3645 data.size(frame_index),
3646 Cow::Borrowed(
3647 data.as_bytes(frame_index)
3648 .expect("It's the caller's job to pass a valid frame index"),
3649 ),
3650 )))
3651 })?
3652 .expect("Callback above only returns Some");
3653 let content_mask = self.content_mask().scale(scale_factor);
3654 let corner_radii = corner_radii.scale(scale_factor);
3655 let opacity = self.element_opacity();
3656 let transform = self.scale_transform_for_scene(transform);
3657
3658 self.next_frame.scene.insert_primitive((
3659 PolychromeSprite {
3660 order: 0,
3661 pad: 0,
3662 grayscale,
3663 bounds: bounds
3664 .map_origin(|origin| origin.floor())
3665 .map_size(|size| size.ceil()),
3666 content_mask,
3667 corner_radii,
3668 tile,
3669 opacity,
3670 },
3671 transform,
3672 ));
3673 Ok(())
3674 }
3675
3676 fn scale_transform_for_scene(&self, transform: TransformationMatrix) -> TransformationMatrix {
3677 if transform.is_unit() {
3678 return transform;
3679 }
3680 let scale_factor = self.scale_factor();
3681 let mut scaled = transform;
3682 scaled.translation[0] *= scale_factor;
3683 scaled.translation[1] *= scale_factor;
3684 scaled
3685 }
3686
3687 #[cfg(target_os = "macos")]
3691 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVPixelBuffer) {
3692 use crate::PaintSurface;
3693
3694 self.invalidator.debug_assert_paint();
3695
3696 let scale_factor = self.scale_factor();
3697 let bounds = bounds.scale(scale_factor);
3698 let content_mask = self.content_mask().scale(scale_factor);
3699 self.next_frame.scene.insert_primitive(PaintSurface {
3700 order: 0,
3701 bounds,
3702 content_mask,
3703 image_buffer,
3704 });
3705 }
3706
3707 pub fn drop_image(&mut self, data: Arc<RenderImage>) -> Result<()> {
3709 for frame_index in 0..data.frame_count() {
3710 let params = RenderImageParams {
3711 image_id: data.id,
3712 frame_index,
3713 };
3714
3715 self.sprite_atlas.remove(¶ms.clone().into());
3716 }
3717
3718 Ok(())
3719 }
3720
3721 #[must_use]
3727 pub fn request_layout(
3728 &mut self,
3729 style: Style,
3730 children: impl IntoIterator<Item = LayoutId>,
3731 cx: &mut App,
3732 ) -> LayoutId {
3733 self.invalidator.debug_assert_prepaint();
3734
3735 cx.layout_id_buffer.clear();
3736 cx.layout_id_buffer.extend(children);
3737 let rem_size = self.rem_size();
3738 let scale_factor = self.scale_factor();
3739
3740 self.layout_engine.as_mut().unwrap().request_layout(
3741 style,
3742 rem_size,
3743 scale_factor,
3744 &cx.layout_id_buffer,
3745 )
3746 }
3747
3748 pub fn request_measured_layout<F>(&mut self, style: Style, measure: F) -> LayoutId
3757 where
3758 F: Fn(Size<Option<Pixels>>, Size<AvailableSpace>, &mut Window, &mut App) -> Size<Pixels>
3759 + 'static,
3760 {
3761 self.invalidator.debug_assert_prepaint();
3762
3763 let rem_size = self.rem_size();
3764 let scale_factor = self.scale_factor();
3765 self.layout_engine
3766 .as_mut()
3767 .unwrap()
3768 .request_measured_layout(style, rem_size, scale_factor, measure)
3769 }
3770
3771 pub fn compute_layout(
3777 &mut self,
3778 layout_id: LayoutId,
3779 available_space: Size<AvailableSpace>,
3780 cx: &mut App,
3781 ) {
3782 self.invalidator.debug_assert_prepaint();
3783
3784 let mut layout_engine = self.layout_engine.take().unwrap();
3785 layout_engine.compute_layout(layout_id, available_space, self, cx);
3786 self.layout_engine = Some(layout_engine);
3787 }
3788
3789 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
3794 self.invalidator.debug_assert_prepaint();
3795
3796 let scale_factor = self.scale_factor();
3797 let mut bounds = self
3798 .layout_engine
3799 .as_mut()
3800 .unwrap()
3801 .layout_bounds(layout_id, scale_factor)
3802 .map(Into::into);
3803 bounds.origin += self.element_offset();
3804 bounds
3805 }
3806
3807 pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, behavior: HitboxBehavior) -> Hitbox {
3813 self.invalidator.debug_assert_prepaint();
3814
3815 let content_mask = self.content_mask();
3816 let mut id = self.next_hitbox_id;
3817 self.next_hitbox_id = self.next_hitbox_id.next();
3818 let hitbox = Hitbox {
3819 id,
3820 bounds,
3821 content_mask,
3822 behavior,
3823 };
3824 self.next_frame.hitboxes.push(hitbox.clone());
3825 hitbox
3826 }
3827
3828 pub fn insert_window_control_hitbox(&mut self, area: WindowControlArea, hitbox: Hitbox) {
3832 self.invalidator.debug_assert_paint();
3833 self.next_frame.window_control_hitboxes.push((area, hitbox));
3834 }
3835
3836 pub fn set_key_context(&mut self, context: KeyContext) {
3841 self.invalidator.debug_assert_paint();
3842 self.next_frame.dispatch_tree.set_key_context(context);
3843 }
3844
3845 pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle, _: &App) {
3850 self.invalidator.debug_assert_prepaint();
3851 if focus_handle.is_focused(self) {
3852 self.next_frame.focus = Some(focus_handle.id);
3853 }
3854 self.next_frame.dispatch_tree.set_focus_id(focus_handle.id);
3855 }
3856
3857 pub fn set_view_id(&mut self, view_id: EntityId) {
3863 self.invalidator.debug_assert_prepaint();
3864 self.next_frame.dispatch_tree.set_view_id(view_id);
3865 }
3866
3867 pub fn current_view(&self) -> EntityId {
3869 self.invalidator.debug_assert_paint_or_prepaint();
3870 if let Some(id) = self.rendered_entity_stack.last().copied() {
3871 return id;
3872 }
3873
3874 self.root
3879 .as_ref()
3880 .map(|root| root.entity_id())
3881 .expect("Window::current_view called with no rendered view and no root view")
3882 }
3883
3884 pub fn with_rendered_view<R>(
3890 &mut self,
3891 id: EntityId,
3892 f: impl FnOnce(&mut Self) -> R,
3893 ) -> R {
3894 self.rendered_entity_stack.push(id);
3895 let result = f(self);
3896 self.rendered_entity_stack.pop();
3897 result
3898 }
3899
3900 pub fn with_image_cache<F, R>(&mut self, image_cache: Option<AnyImageCache>, f: F) -> R
3902 where
3903 F: FnOnce(&mut Self) -> R,
3904 {
3905 if let Some(image_cache) = image_cache {
3906 self.image_cache_stack.push(image_cache);
3907 let result = f(self);
3908 self.image_cache_stack.pop();
3909 result
3910 } else {
3911 f(self)
3912 }
3913 }
3914
3915 pub fn handle_input(
3924 &mut self,
3925 focus_handle: &FocusHandle,
3926 input_handler: impl InputHandler,
3927 cx: &App,
3928 ) {
3929 self.invalidator.debug_assert_paint();
3930
3931 if focus_handle.is_focused(self) {
3932 let cx = self.to_async(cx);
3933 self.next_frame
3934 .input_handlers
3935 .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));
3936 }
3937 }
3938
3939 pub fn on_mouse_event<Event: MouseEvent>(
3945 &mut self,
3946 mut listener: impl FnMut(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
3947 ) {
3948 self.invalidator.debug_assert_paint();
3949
3950 self.next_frame.mouse_listeners.push(Some(Box::new(
3951 move |event: &dyn Any, phase: DispatchPhase, window: &mut Window, cx: &mut App| {
3952 if let Some(event) = event.downcast_ref() {
3953 listener(event, phase, window, cx)
3954 }
3955 },
3956 )));
3957 }
3958
3959 pub fn on_key_event<Event: KeyEvent>(
3968 &mut self,
3969 listener: impl Fn(&Event, DispatchPhase, &mut Window, &mut App) + 'static,
3970 ) {
3971 self.invalidator.debug_assert_paint();
3972
3973 self.next_frame.dispatch_tree.on_key_event(Rc::new(
3974 move |event: &dyn Any, phase, window: &mut Window, cx: &mut App| {
3975 if let Some(event) = event.downcast_ref::<Event>() {
3976 listener(event, phase, window, cx)
3977 }
3978 },
3979 ));
3980 }
3981
3982 pub fn on_modifiers_changed(
3989 &mut self,
3990 listener: impl Fn(&ModifiersChangedEvent, &mut Window, &mut App) + 'static,
3991 ) {
3992 self.invalidator.debug_assert_paint();
3993
3994 self.next_frame.dispatch_tree.on_modifiers_changed(Rc::new(
3995 move |event: &ModifiersChangedEvent, window: &mut Window, cx: &mut App| {
3996 listener(event, window, cx)
3997 },
3998 ));
3999 }
4000
4001 pub fn on_focus_in(
4005 &mut self,
4006 handle: &FocusHandle,
4007 cx: &mut App,
4008 mut listener: impl FnMut(&mut Window, &mut App) + 'static,
4009 ) -> Subscription {
4010 let focus_id = handle.id;
4011 let (subscription, activate) =
4012 self.new_focus_listener(Box::new(move |event, window, cx| {
4013 if event.is_focus_in(focus_id) {
4014 listener(window, cx);
4015 }
4016 true
4017 }));
4018 cx.defer(move |_| activate());
4019 subscription
4020 }
4021
4022 pub fn on_focus_out(
4025 &mut self,
4026 handle: &FocusHandle,
4027 cx: &mut App,
4028 mut listener: impl FnMut(FocusOutEvent, &mut Window, &mut App) + 'static,
4029 ) -> Subscription {
4030 let focus_id = handle.id;
4031 let (subscription, activate) =
4032 self.new_focus_listener(Box::new(move |event, window, cx| {
4033 if let Some(blurred_id) = event.previous_focus_path.last().copied()
4034 && event.is_focus_out(focus_id)
4035 {
4036 let event = FocusOutEvent {
4037 blurred: WeakFocusHandle {
4038 id: blurred_id,
4039 handles: Arc::downgrade(&cx.focus_handles),
4040 },
4041 };
4042 listener(event, window, cx)
4043 }
4044 true
4045 }));
4046 cx.defer(move |_| activate());
4047 subscription
4048 }
4049
4050 fn reset_cursor_style(&self, cx: &mut App) {
4051 if self.is_window_hovered() {
4053 let style = self
4054 .rendered_frame
4055 .cursor_style(self)
4056 .unwrap_or(CursorStyle::Arrow);
4057 cx.platform.set_cursor_style(style);
4058 }
4059 }
4060
4061 pub fn dispatch_keystroke(&mut self, keystroke: Keystroke, cx: &mut App) -> bool {
4064 let keystroke = keystroke.with_simulated_ime();
4065 let result = self.dispatch_event(
4066 PlatformInput::KeyDown(KeyDownEvent {
4067 keystroke: keystroke.clone(),
4068 is_held: false,
4069 prefer_character_input: false,
4070 }),
4071 cx,
4072 );
4073 if !result.propagate {
4074 return true;
4075 }
4076
4077 if let Some(input) = keystroke.key_char
4078 && let Some(mut input_handler) = self.platform_window.take_input_handler()
4079 {
4080 input_handler.dispatch_input(&input, self, cx);
4081 self.platform_window.set_input_handler(input_handler);
4082 return true;
4083 }
4084
4085 false
4086 }
4087
4088 pub fn keystroke_text_for(&self, action: &dyn Action) -> String {
4091 self.highest_precedence_binding_for_action(action)
4092 .map(|binding| {
4093 binding
4094 .keystrokes()
4095 .iter()
4096 .map(ToString::to_string)
4097 .collect::<Vec<_>>()
4098 .join(" ")
4099 })
4100 .unwrap_or_else(|| action.name().to_string())
4101 }
4102
4103 #[profiling::function]
4105 pub fn dispatch_event(&mut self, event: PlatformInput, cx: &mut App) -> DispatchEventResult {
4106 self.last_input_modality = match &event {
4108 PlatformInput::KeyDown(_) | PlatformInput::ModifiersChanged(_) => {
4109 InputModality::Keyboard
4110 }
4111 PlatformInput::MouseDown(e) if e.is_focusing() => InputModality::Mouse,
4112 _ => self.last_input_modality,
4113 };
4114
4115 cx.propagate_event = true;
4117 self.default_prevented = false;
4119
4120 let event = match event {
4121 PlatformInput::MouseMove(mouse_move) => {
4124 self.mouse_position = mouse_move.position;
4125 self.modifiers = mouse_move.modifiers;
4126 PlatformInput::MouseMove(mouse_move)
4127 }
4128 PlatformInput::MouseDown(mouse_down) => {
4129 self.mouse_position = mouse_down.position;
4130 self.modifiers = mouse_down.modifiers;
4131 PlatformInput::MouseDown(mouse_down)
4132 }
4133 PlatformInput::MouseUp(mouse_up) => {
4134 self.mouse_position = mouse_up.position;
4135 self.modifiers = mouse_up.modifiers;
4136 PlatformInput::MouseUp(mouse_up)
4137 }
4138 PlatformInput::MousePressure(mouse_pressure) => {
4139 PlatformInput::MousePressure(mouse_pressure)
4140 }
4141 PlatformInput::MouseExited(mouse_exited) => {
4142 self.modifiers = mouse_exited.modifiers;
4143 PlatformInput::MouseExited(mouse_exited)
4144 }
4145 PlatformInput::ModifiersChanged(modifiers_changed) => {
4146 self.modifiers = modifiers_changed.modifiers;
4147 self.capslock = modifiers_changed.capslock;
4148 PlatformInput::ModifiersChanged(modifiers_changed)
4149 }
4150 PlatformInput::ScrollWheel(scroll_wheel) => {
4151 self.mouse_position = scroll_wheel.position;
4152 self.modifiers = scroll_wheel.modifiers;
4153 PlatformInput::ScrollWheel(scroll_wheel)
4154 }
4155 PlatformInput::FileDrop(file_drop) => match file_drop {
4158 FileDropEvent::Entered { position, paths } => {
4159 self.mouse_position = position;
4160 if cx.active_drag.is_none() {
4161 cx.active_drag = Some(AnyDrag {
4162 value: Arc::new(paths.clone()),
4163 view: cx.new(|_| paths).into(),
4164 cursor_offset: position,
4165 cursor_style: None,
4166 });
4167 }
4168 PlatformInput::MouseMove(MouseMoveEvent {
4169 position,
4170 pressed_button: Some(MouseButton::Left),
4171 modifiers: Modifiers::default(),
4172 })
4173 }
4174 FileDropEvent::Pending { position } => {
4175 self.mouse_position = position;
4176 PlatformInput::MouseMove(MouseMoveEvent {
4177 position,
4178 pressed_button: Some(MouseButton::Left),
4179 modifiers: Modifiers::default(),
4180 })
4181 }
4182 FileDropEvent::Submit { position } => {
4183 cx.activate(true);
4184 self.mouse_position = position;
4185 PlatformInput::MouseUp(MouseUpEvent {
4186 button: MouseButton::Left,
4187 position,
4188 modifiers: Modifiers::default(),
4189 click_count: 1,
4190 })
4191 }
4192 FileDropEvent::Exited => {
4193 cx.active_drag.take();
4194 PlatformInput::FileDrop(FileDropEvent::Exited)
4195 }
4196 },
4197 PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
4198 };
4199
4200 if let Some(any_mouse_event) = event.mouse_event() {
4201 self.dispatch_mouse_event(any_mouse_event, cx);
4202 } else if let Some(any_key_event) = event.keyboard_event() {
4203 self.dispatch_key_event(any_key_event, cx);
4204 }
4205
4206 if self.invalidator.is_dirty() {
4207 self.input_rate_tracker.borrow_mut().record_input();
4208 }
4209
4210 DispatchEventResult {
4211 propagate: cx.propagate_event,
4212 default_prevented: self.default_prevented,
4213 }
4214 }
4215
4216 fn dispatch_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
4217 let hit_test = self.rendered_frame.hit_test(self.mouse_position());
4218 if hit_test != self.mouse_hit_test {
4219 self.mouse_hit_test = hit_test;
4220 self.reset_cursor_style(cx);
4221 }
4222
4223 #[cfg(any(feature = "inspector", debug_assertions))]
4224 if self.is_inspector_picking(cx) {
4225 self.handle_inspector_mouse_event(event, cx);
4226 return;
4228 }
4229
4230 let mut mouse_listeners = mem::take(&mut self.rendered_frame.mouse_listeners);
4231
4232 for listener in &mut mouse_listeners {
4235 let listener = listener.as_mut().unwrap();
4236 listener(event, DispatchPhase::Capture, self, cx);
4237 if !cx.propagate_event {
4238 break;
4239 }
4240 }
4241
4242 if cx.propagate_event {
4244 for listener in mouse_listeners.iter_mut().rev() {
4245 let listener = listener.as_mut().unwrap();
4246 listener(event, DispatchPhase::Bubble, self, cx);
4247 if !cx.propagate_event {
4248 break;
4249 }
4250 }
4251 }
4252
4253 self.rendered_frame.mouse_listeners = mouse_listeners;
4254
4255 if cx.has_active_drag() {
4256 if event.is::<MouseMoveEvent>() {
4257 self.refresh();
4260 } else if event.is::<MouseUpEvent>() {
4261 cx.active_drag = None;
4264 self.refresh();
4265 }
4266 }
4267 }
4268
4269 fn dispatch_key_event(&mut self, event: &dyn Any, cx: &mut App) {
4270 if self.invalidator.is_dirty() {
4271 self.draw(cx).clear();
4272 }
4273
4274 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4275 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4276
4277 let mut keystroke: Option<Keystroke> = None;
4278
4279 if let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() {
4280 if event.modifiers.number_of_modifiers() == 0
4281 && self.pending_modifier.modifiers.number_of_modifiers() == 1
4282 && !self.pending_modifier.saw_keystroke
4283 {
4284 let key = match self.pending_modifier.modifiers {
4285 modifiers if modifiers.shift => Some("shift"),
4286 modifiers if modifiers.control => Some("control"),
4287 modifiers if modifiers.alt => Some("alt"),
4288 modifiers if modifiers.platform => Some("platform"),
4289 modifiers if modifiers.function => Some("function"),
4290 _ => None,
4291 };
4292 if let Some(key) = key {
4293 keystroke = Some(Keystroke {
4294 key: key.to_string(),
4295 key_char: None,
4296 modifiers: Modifiers::default(),
4297 });
4298 }
4299 }
4300
4301 if self.pending_modifier.modifiers.number_of_modifiers() == 0
4302 && event.modifiers.number_of_modifiers() == 1
4303 {
4304 self.pending_modifier.saw_keystroke = false
4305 }
4306 self.pending_modifier.modifiers = event.modifiers
4307 } else if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
4308 self.pending_modifier.saw_keystroke = true;
4309 keystroke = Some(key_down_event.keystroke.clone());
4310 }
4311
4312 let Some(keystroke) = keystroke else {
4313 self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
4314 return;
4315 };
4316
4317 cx.propagate_event = true;
4318 self.dispatch_keystroke_interceptors(event, self.context_stack(), cx);
4319 if !cx.propagate_event {
4320 self.finish_dispatch_key_event(event, dispatch_path, self.context_stack(), cx);
4321 return;
4322 }
4323
4324 let mut currently_pending = self.pending_input.take().unwrap_or_default();
4325 if currently_pending.focus.is_some() && currently_pending.focus != self.focus {
4326 currently_pending = PendingInput::default();
4327 }
4328
4329 let match_result = self.rendered_frame.dispatch_tree.dispatch_key(
4330 currently_pending.keystrokes,
4331 keystroke,
4332 &dispatch_path,
4333 );
4334
4335 if !match_result.to_replay.is_empty() {
4336 self.replay_pending_input(match_result.to_replay, cx);
4337 cx.propagate_event = true;
4338 }
4339
4340 if !match_result.pending.is_empty() {
4341 currently_pending.timer.take();
4342 currently_pending.keystrokes = match_result.pending;
4343 currently_pending.focus = self.focus;
4344
4345 let text_input_requires_timeout = event
4346 .downcast_ref::<KeyDownEvent>()
4347 .filter(|key_down| key_down.keystroke.key_char.is_some())
4348 .and_then(|_| self.platform_window.take_input_handler())
4349 .map_or(false, |mut input_handler| {
4350 let accepts = input_handler.accepts_text_input(self, cx);
4351 self.platform_window.set_input_handler(input_handler);
4352 accepts
4353 });
4354
4355 currently_pending.needs_timeout |=
4356 match_result.pending_has_binding || text_input_requires_timeout;
4357
4358 if currently_pending.needs_timeout {
4359 currently_pending.timer = Some(self.spawn(cx, async move |cx| {
4360 cx.background_executor.timer(Duration::from_secs(1)).await;
4361 cx.update(move |window, cx| {
4362 let Some(currently_pending) = window
4363 .pending_input
4364 .take()
4365 .filter(|pending| pending.focus == window.focus)
4366 else {
4367 return;
4368 };
4369
4370 let node_id = window.focus_node_id_in_rendered_frame(window.focus);
4371 let dispatch_path =
4372 window.rendered_frame.dispatch_tree.dispatch_path(node_id);
4373
4374 let to_replay = window
4375 .rendered_frame
4376 .dispatch_tree
4377 .flush_dispatch(currently_pending.keystrokes, &dispatch_path);
4378
4379 window.pending_input_changed(cx);
4380 window.replay_pending_input(to_replay, cx)
4381 })
4382 .log_err();
4383 }));
4384 } else {
4385 currently_pending.timer = None;
4386 }
4387 self.pending_input = Some(currently_pending);
4388 self.pending_input_changed(cx);
4389 cx.propagate_event = false;
4390 return;
4391 }
4392
4393 let skip_bindings = event
4394 .downcast_ref::<KeyDownEvent>()
4395 .filter(|key_down_event| key_down_event.prefer_character_input)
4396 .map(|_| {
4397 self.platform_window
4398 .take_input_handler()
4399 .map_or(false, |mut input_handler| {
4400 let accepts = input_handler.accepts_text_input(self, cx);
4401 self.platform_window.set_input_handler(input_handler);
4402 accepts
4405 })
4406 })
4407 .unwrap_or(false);
4408
4409 if !skip_bindings {
4410 for binding in match_result.bindings {
4411 self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
4412 if !cx.propagate_event {
4413 self.dispatch_keystroke_observers(
4414 event,
4415 Some(binding.action),
4416 match_result.context_stack,
4417 cx,
4418 );
4419 self.pending_input_changed(cx);
4420 return;
4421 }
4422 }
4423 }
4424
4425 self.finish_dispatch_key_event(event, dispatch_path, match_result.context_stack, cx);
4426 self.pending_input_changed(cx);
4427 }
4428
4429 fn finish_dispatch_key_event(
4430 &mut self,
4431 event: &dyn Any,
4432 dispatch_path: SmallVec<[DispatchNodeId; 32]>,
4433 context_stack: Vec<KeyContext>,
4434 cx: &mut App,
4435 ) {
4436 self.dispatch_key_down_up_event(event, &dispatch_path, cx);
4437 if !cx.propagate_event {
4438 return;
4439 }
4440
4441 self.dispatch_modifiers_changed_event(event, &dispatch_path, cx);
4442 if !cx.propagate_event {
4443 return;
4444 }
4445
4446 self.dispatch_keystroke_observers(event, None, context_stack, cx);
4447 }
4448
4449 pub(crate) fn pending_input_changed(&mut self, cx: &mut App) {
4450 self.pending_input_observers
4451 .clone()
4452 .retain(&(), |callback| callback(self, cx));
4453 }
4454
4455 fn dispatch_key_down_up_event(
4456 &mut self,
4457 event: &dyn Any,
4458 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
4459 cx: &mut App,
4460 ) {
4461 for node_id in dispatch_path {
4463 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4464
4465 for key_listener in node.key_listeners.clone() {
4466 key_listener(event, DispatchPhase::Capture, self, cx);
4467 if !cx.propagate_event {
4468 return;
4469 }
4470 }
4471 }
4472
4473 for node_id in dispatch_path.iter().rev() {
4475 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4477 for key_listener in node.key_listeners.clone() {
4478 key_listener(event, DispatchPhase::Bubble, self, cx);
4479 if !cx.propagate_event {
4480 return;
4481 }
4482 }
4483 }
4484 }
4485
4486 fn dispatch_modifiers_changed_event(
4487 &mut self,
4488 event: &dyn Any,
4489 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
4490 cx: &mut App,
4491 ) {
4492 let Some(event) = event.downcast_ref::<ModifiersChangedEvent>() else {
4493 return;
4494 };
4495 for node_id in dispatch_path.iter().rev() {
4496 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4497 for listener in node.modifiers_changed_listeners.clone() {
4498 listener(event, self, cx);
4499 if !cx.propagate_event {
4500 return;
4501 }
4502 }
4503 }
4504 }
4505
4506 pub fn has_pending_keystrokes(&self) -> bool {
4508 self.pending_input.is_some()
4509 }
4510
4511 pub(crate) fn clear_pending_keystrokes(&mut self) {
4512 self.pending_input.take();
4513 }
4514
4515 pub fn pending_input_keystrokes(&self) -> Option<&[Keystroke]> {
4517 self.pending_input
4518 .as_ref()
4519 .map(|pending_input| pending_input.keystrokes.as_slice())
4520 }
4521
4522 fn replay_pending_input(&mut self, replays: SmallVec<[Replay; 1]>, cx: &mut App) {
4523 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4524 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4525
4526 'replay: for replay in replays {
4527 let event = KeyDownEvent {
4528 keystroke: replay.keystroke.clone(),
4529 is_held: false,
4530 prefer_character_input: true,
4531 };
4532
4533 cx.propagate_event = true;
4534 for binding in replay.bindings {
4535 self.dispatch_action_on_node(node_id, binding.action.as_ref(), cx);
4536 if !cx.propagate_event {
4537 self.dispatch_keystroke_observers(
4538 &event,
4539 Some(binding.action),
4540 Vec::default(),
4541 cx,
4542 );
4543 continue 'replay;
4544 }
4545 }
4546
4547 self.dispatch_key_down_up_event(&event, &dispatch_path, cx);
4548 if !cx.propagate_event {
4549 continue 'replay;
4550 }
4551 if let Some(input) = replay.keystroke.key_char.as_ref().cloned()
4552 && let Some(mut input_handler) = self.platform_window.take_input_handler()
4553 {
4554 input_handler.dispatch_input(&input, self, cx);
4555 self.platform_window.set_input_handler(input_handler)
4556 }
4557 }
4558 }
4559
4560 fn focus_node_id_in_rendered_frame(&self, focus_id: Option<FocusId>) -> DispatchNodeId {
4561 focus_id
4562 .and_then(|focus_id| {
4563 self.rendered_frame
4564 .dispatch_tree
4565 .focusable_node_id(focus_id)
4566 })
4567 .unwrap_or_else(|| self.rendered_frame.dispatch_tree.root_node_id())
4568 }
4569
4570 fn dispatch_action_on_node(
4571 &mut self,
4572 node_id: DispatchNodeId,
4573 action: &dyn Action,
4574 cx: &mut App,
4575 ) {
4576 let dispatch_path = self.rendered_frame.dispatch_tree.dispatch_path(node_id);
4577
4578 cx.propagate_event = true;
4580 if let Some(mut global_listeners) = cx
4581 .global_action_listeners
4582 .remove(&action.as_any().type_id())
4583 {
4584 for listener in &global_listeners {
4585 listener(action.as_any(), DispatchPhase::Capture, cx);
4586 if !cx.propagate_event {
4587 break;
4588 }
4589 }
4590
4591 global_listeners.extend(
4592 cx.global_action_listeners
4593 .remove(&action.as_any().type_id())
4594 .unwrap_or_default(),
4595 );
4596
4597 cx.global_action_listeners
4598 .insert(action.as_any().type_id(), global_listeners);
4599 }
4600
4601 if !cx.propagate_event {
4602 return;
4603 }
4604
4605 for node_id in &dispatch_path {
4607 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4608 for DispatchActionListener {
4609 action_type,
4610 listener,
4611 } in node.action_listeners.clone()
4612 {
4613 let any_action = action.as_any();
4614 if action_type == any_action.type_id() {
4615 listener(any_action, DispatchPhase::Capture, self, cx);
4616
4617 if !cx.propagate_event {
4618 return;
4619 }
4620 }
4621 }
4622 }
4623
4624 for node_id in dispatch_path.iter().rev() {
4626 let node = self.rendered_frame.dispatch_tree.node(*node_id);
4627 for DispatchActionListener {
4628 action_type,
4629 listener,
4630 } in node.action_listeners.clone()
4631 {
4632 let any_action = action.as_any();
4633 if action_type == any_action.type_id() {
4634 cx.propagate_event = false; listener(any_action, DispatchPhase::Bubble, self, cx);
4636
4637 if !cx.propagate_event {
4638 return;
4639 }
4640 }
4641 }
4642 }
4643
4644 if let Some(mut global_listeners) = cx
4646 .global_action_listeners
4647 .remove(&action.as_any().type_id())
4648 {
4649 for listener in global_listeners.iter().rev() {
4650 cx.propagate_event = false; listener(action.as_any(), DispatchPhase::Bubble, cx);
4653 if !cx.propagate_event {
4654 break;
4655 }
4656 }
4657
4658 global_listeners.extend(
4659 cx.global_action_listeners
4660 .remove(&action.as_any().type_id())
4661 .unwrap_or_default(),
4662 );
4663
4664 cx.global_action_listeners
4665 .insert(action.as_any().type_id(), global_listeners);
4666 }
4667 }
4668
4669 pub fn observe_global<G: Global>(
4672 &mut self,
4673 cx: &mut App,
4674 f: impl Fn(&mut Window, &mut App) + 'static,
4675 ) -> Subscription {
4676 let window_handle = self.handle;
4677 let (subscription, activate) = cx.global_observers.insert(
4678 TypeId::of::<G>(),
4679 Box::new(move |cx| {
4680 window_handle
4681 .update(cx, |_, window, cx| f(window, cx))
4682 .is_ok()
4683 }),
4684 );
4685 cx.defer(move |_| activate());
4686 subscription
4687 }
4688
4689 pub fn activate_window(&self) {
4691 self.platform_window.activate();
4692 }
4693
4694 pub fn minimize_window(&self) {
4696 self.platform_window.minimize();
4697 }
4698
4699 pub fn toggle_fullscreen(&self) {
4701 self.platform_window.toggle_fullscreen();
4702 }
4703
4704 pub fn invalidate_character_coordinates(&self) {
4706 self.on_next_frame(|window, cx| {
4707 if let Some(mut input_handler) = window.platform_window.take_input_handler() {
4708 if let Some(bounds) = input_handler.selected_bounds(window, cx) {
4709 window.platform_window.update_ime_position(bounds);
4710 }
4711 window.platform_window.set_input_handler(input_handler);
4712 }
4713 });
4714 }
4715
4716 pub fn prompt<T>(
4720 &mut self,
4721 level: PromptLevel,
4722 message: &str,
4723 detail: Option<&str>,
4724 answers: &[T],
4725 cx: &mut App,
4726 ) -> oneshot::Receiver<usize>
4727 where
4728 T: Clone + Into<PromptButton>,
4729 {
4730 let prompt_builder = cx.prompt_builder.take();
4731 let Some(prompt_builder) = prompt_builder else {
4732 unreachable!("Re-entrant window prompting is not supported by GPUI");
4733 };
4734
4735 let answers = answers
4736 .iter()
4737 .map(|answer| answer.clone().into())
4738 .collect::<Vec<_>>();
4739
4740 let receiver = match &prompt_builder {
4741 PromptBuilder::Default => self
4742 .platform_window
4743 .prompt(level, message, detail, &answers)
4744 .unwrap_or_else(|| {
4745 self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
4746 }),
4747 PromptBuilder::Custom(_) => {
4748 self.build_custom_prompt(&prompt_builder, level, message, detail, &answers, cx)
4749 }
4750 };
4751
4752 cx.prompt_builder = Some(prompt_builder);
4753
4754 receiver
4755 }
4756
4757 fn build_custom_prompt(
4758 &mut self,
4759 prompt_builder: &PromptBuilder,
4760 level: PromptLevel,
4761 message: &str,
4762 detail: Option<&str>,
4763 answers: &[PromptButton],
4764 cx: &mut App,
4765 ) -> oneshot::Receiver<usize> {
4766 let (sender, receiver) = oneshot::channel();
4767 let handle = PromptHandle::new(sender);
4768 let handle = (prompt_builder)(level, message, detail, answers, handle, self, cx);
4769 self.prompt = Some(handle);
4770 receiver
4771 }
4772
4773 pub fn context_stack(&self) -> Vec<KeyContext> {
4775 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4776 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4777 dispatch_tree
4778 .dispatch_path(node_id)
4779 .iter()
4780 .filter_map(move |&node_id| dispatch_tree.node(node_id).context.clone())
4781 .collect()
4782 }
4783
4784 pub fn available_actions(&self, cx: &App) -> Vec<Box<dyn Action>> {
4786 let node_id = self.focus_node_id_in_rendered_frame(self.focus);
4787 let mut actions = self.rendered_frame.dispatch_tree.available_actions(node_id);
4788 for action_type in cx.global_action_listeners.keys() {
4789 if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id()) {
4790 let action = cx.actions.build_action_type(action_type).ok();
4791 if let Some(action) = action {
4792 actions.insert(ix, action);
4793 }
4794 }
4795 }
4796 actions
4797 }
4798
4799 pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
4802 self.rendered_frame
4803 .dispatch_tree
4804 .bindings_for_action(action, &self.rendered_frame.dispatch_tree.context_stack)
4805 }
4806
4807 pub fn highest_precedence_binding_for_action(&self, action: &dyn Action) -> Option<KeyBinding> {
4810 self.rendered_frame
4811 .dispatch_tree
4812 .highest_precedence_binding_for_action(
4813 action,
4814 &self.rendered_frame.dispatch_tree.context_stack,
4815 )
4816 }
4817
4818 pub fn bindings_for_action_in_context(
4820 &self,
4821 action: &dyn Action,
4822 context: KeyContext,
4823 ) -> Vec<KeyBinding> {
4824 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4825 dispatch_tree.bindings_for_action(action, &[context])
4826 }
4827
4828 pub fn highest_precedence_binding_for_action_in_context(
4831 &self,
4832 action: &dyn Action,
4833 context: KeyContext,
4834 ) -> Option<KeyBinding> {
4835 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4836 dispatch_tree.highest_precedence_binding_for_action(action, &[context])
4837 }
4838
4839 pub fn bindings_for_action_in(
4843 &self,
4844 action: &dyn Action,
4845 focus_handle: &FocusHandle,
4846 ) -> Vec<KeyBinding> {
4847 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4848 let Some(context_stack) = self.context_stack_for_focus_handle(focus_handle) else {
4849 return vec![];
4850 };
4851 dispatch_tree.bindings_for_action(action, &context_stack)
4852 }
4853
4854 pub fn highest_precedence_binding_for_action_in(
4858 &self,
4859 action: &dyn Action,
4860 focus_handle: &FocusHandle,
4861 ) -> Option<KeyBinding> {
4862 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4863 let context_stack = self.context_stack_for_focus_handle(focus_handle)?;
4864 dispatch_tree.highest_precedence_binding_for_action(action, &context_stack)
4865 }
4866
4867 pub fn possible_bindings_for_input(&self, input: &[Keystroke]) -> Vec<KeyBinding> {
4869 self.rendered_frame
4870 .dispatch_tree
4871 .possible_next_bindings_for_input(input, &self.context_stack())
4872 }
4873
4874 fn context_stack_for_focus_handle(
4875 &self,
4876 focus_handle: &FocusHandle,
4877 ) -> Option<Vec<KeyContext>> {
4878 let dispatch_tree = &self.rendered_frame.dispatch_tree;
4879 let node_id = dispatch_tree.focusable_node_id(focus_handle.id)?;
4880 let context_stack: Vec<_> = dispatch_tree
4881 .dispatch_path(node_id)
4882 .into_iter()
4883 .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
4884 .collect();
4885 Some(context_stack)
4886 }
4887
4888 pub fn listener_for<T: 'static, E>(
4890 &self,
4891 view: &Entity<T>,
4892 f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + 'static,
4893 ) -> impl Fn(&E, &mut Window, &mut App) + 'static {
4894 let view = view.downgrade();
4895 move |e: &E, window: &mut Window, cx: &mut App| {
4896 view.update(cx, |view, cx| f(view, e, window, cx)).ok();
4897 }
4898 }
4899
4900 pub fn handler_for<E: 'static, Callback: Fn(&mut E, &mut Window, &mut Context<E>) + 'static>(
4902 &self,
4903 entity: &Entity<E>,
4904 f: Callback,
4905 ) -> impl Fn(&mut Window, &mut App) + 'static {
4906 let entity = entity.downgrade();
4907 move |window: &mut Window, cx: &mut App| {
4908 entity.update(cx, |entity, cx| f(entity, window, cx)).ok();
4909 }
4910 }
4911
4912 pub fn on_window_should_close(
4915 &self,
4916 cx: &App,
4917 f: impl Fn(&mut Window, &mut App) -> bool + 'static,
4918 ) {
4919 let mut cx = self.to_async(cx);
4920 self.platform_window.on_should_close(Box::new(move || {
4921 cx.update(|window, cx| f(window, cx)).unwrap_or(true)
4922 }))
4923 }
4924
4925 pub fn on_action(
4934 &mut self,
4935 action_type: TypeId,
4936 listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
4937 ) {
4938 self.invalidator.debug_assert_paint();
4939
4940 self.next_frame
4941 .dispatch_tree
4942 .on_action(action_type, Rc::new(listener));
4943 }
4944
4945 pub fn on_action_when(
4954 &mut self,
4955 condition: bool,
4956 action_type: TypeId,
4957 listener: impl Fn(&dyn Any, DispatchPhase, &mut Window, &mut App) + 'static,
4958 ) {
4959 self.invalidator.debug_assert_paint();
4960
4961 if condition {
4962 self.next_frame
4963 .dispatch_tree
4964 .on_action(action_type, Rc::new(listener));
4965 }
4966 }
4967
4968 pub fn gpu_specs(&self) -> Option<GpuSpecs> {
4971 self.platform_window.gpu_specs()
4972 }
4973
4974 pub fn titlebar_double_click(&self) {
4977 self.platform_window.titlebar_double_click();
4978 }
4979
4980 pub fn window_title(&self) -> String {
4983 self.platform_window.get_title()
4984 }
4985
4986 pub fn tabbed_windows(&self) -> Option<Vec<SystemWindowTab>> {
4989 self.platform_window.tabbed_windows()
4990 }
4991
4992 pub fn tab_bar_visible(&self) -> bool {
4995 self.platform_window.tab_bar_visible()
4996 }
4997
4998 pub fn merge_all_windows(&self) {
5001 self.platform_window.merge_all_windows()
5002 }
5003
5004 pub fn move_tab_to_new_window(&self) {
5007 self.platform_window.move_tab_to_new_window()
5008 }
5009
5010 pub fn toggle_window_tab_overview(&self) {
5013 self.platform_window.toggle_window_tab_overview()
5014 }
5015
5016 pub fn set_tabbing_identifier(&self, tabbing_identifier: Option<String>) {
5019 self.platform_window
5020 .set_tabbing_identifier(tabbing_identifier)
5021 }
5022
5023 #[cfg(any(feature = "inspector", debug_assertions))]
5025 pub fn toggle_inspector(&mut self, cx: &mut App) {
5026 self.inspector = match self.inspector {
5027 None => Some(cx.new(|_| Inspector::new())),
5028 Some(_) => None,
5029 };
5030 self.refresh();
5031 }
5032
5033 pub fn is_inspector_picking(&self, _cx: &App) -> bool {
5035 #[cfg(any(feature = "inspector", debug_assertions))]
5036 {
5037 if let Some(inspector) = &self.inspector {
5038 return inspector.read(_cx).is_picking();
5039 }
5040 }
5041 false
5042 }
5043
5044 #[cfg(any(feature = "inspector", debug_assertions))]
5046 pub fn with_inspector_state<T: 'static, R>(
5047 &mut self,
5048 _inspector_id: Option<&crate::InspectorElementId>,
5049 cx: &mut App,
5050 f: impl FnOnce(&mut Option<T>, &mut Self) -> R,
5051 ) -> R {
5052 if let Some(inspector_id) = _inspector_id
5053 && let Some(inspector) = &self.inspector
5054 {
5055 let inspector = inspector.clone();
5056 let active_element_id = inspector.read(cx).active_element_id();
5057 if Some(inspector_id) == active_element_id {
5058 return inspector.update(cx, |inspector, _cx| {
5059 inspector.with_active_element_state(self, f)
5060 });
5061 }
5062 }
5063 f(&mut None, self)
5064 }
5065
5066 #[cfg(any(feature = "inspector", debug_assertions))]
5067 pub(crate) fn build_inspector_element_id(
5068 &mut self,
5069 path: crate::InspectorElementPath,
5070 ) -> crate::InspectorElementId {
5071 self.invalidator.debug_assert_paint_or_prepaint();
5072 let path = Rc::new(path);
5073 let next_instance_id = self
5074 .next_frame
5075 .next_inspector_instance_ids
5076 .entry(path.clone())
5077 .or_insert(0);
5078 let instance_id = *next_instance_id;
5079 *next_instance_id += 1;
5080 crate::InspectorElementId { path, instance_id }
5081 }
5082
5083 #[cfg(any(feature = "inspector", debug_assertions))]
5084 fn prepaint_inspector(&mut self, inspector_width: Pixels, cx: &mut App) -> Option<AnyElement> {
5085 if let Some(inspector) = self.inspector.take() {
5086 let mut inspector_element = AnyView::from(inspector.clone()).into_any_element();
5087 inspector_element.prepaint_as_root(
5088 point(self.viewport_size.width - inspector_width, px(0.0)),
5089 size(inspector_width, self.viewport_size.height).into(),
5090 self,
5091 cx,
5092 );
5093 self.inspector = Some(inspector);
5094 Some(inspector_element)
5095 } else {
5096 None
5097 }
5098 }
5099
5100 #[cfg(any(feature = "inspector", debug_assertions))]
5101 fn paint_inspector(&mut self, mut inspector_element: Option<AnyElement>, cx: &mut App) {
5102 if let Some(mut inspector_element) = inspector_element {
5103 inspector_element.paint(self, cx);
5104 };
5105 }
5106
5107 #[cfg(any(feature = "inspector", debug_assertions))]
5110 pub fn insert_inspector_hitbox(
5111 &mut self,
5112 hitbox_id: HitboxId,
5113 inspector_id: Option<&crate::InspectorElementId>,
5114 cx: &App,
5115 ) {
5116 self.invalidator.debug_assert_paint_or_prepaint();
5117 if !self.is_inspector_picking(cx) {
5118 return;
5119 }
5120 if let Some(inspector_id) = inspector_id {
5121 self.next_frame
5122 .inspector_hitboxes
5123 .insert(hitbox_id, inspector_id.clone());
5124 }
5125 }
5126
5127 #[cfg(any(feature = "inspector", debug_assertions))]
5128 fn paint_inspector_hitbox(&mut self, cx: &App) {
5129 if let Some(inspector) = self.inspector.as_ref() {
5130 let inspector = inspector.read(cx);
5131 if let Some((hitbox_id, _)) = self.hovered_inspector_hitbox(inspector, &self.next_frame)
5132 && let Some(hitbox) = self
5133 .next_frame
5134 .hitboxes
5135 .iter()
5136 .find(|hitbox| hitbox.id == hitbox_id)
5137 {
5138 self.paint_quad(crate::fill(hitbox.bounds, crate::rgba(0x61afef4d)));
5139 }
5140 }
5141 }
5142
5143 #[cfg(any(feature = "inspector", debug_assertions))]
5144 fn handle_inspector_mouse_event(&mut self, event: &dyn Any, cx: &mut App) {
5145 let Some(inspector) = self.inspector.clone() else {
5146 return;
5147 };
5148 if event.downcast_ref::<MouseMoveEvent>().is_some() {
5149 inspector.update(cx, |inspector, _cx| {
5150 if let Some((_, inspector_id)) =
5151 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
5152 {
5153 inspector.hover(inspector_id, self);
5154 }
5155 });
5156 } else if event.downcast_ref::<crate::MouseDownEvent>().is_some() {
5157 inspector.update(cx, |inspector, _cx| {
5158 if let Some((_, inspector_id)) =
5159 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
5160 {
5161 inspector.select(inspector_id, self);
5162 }
5163 });
5164 } else if let Some(event) = event.downcast_ref::<crate::ScrollWheelEvent>() {
5165 const SCROLL_LINES: f32 = 3.0;
5167 const SCROLL_PIXELS_PER_LAYER: f32 = 36.0;
5168 let delta_y = event
5169 .delta
5170 .pixel_delta(px(SCROLL_PIXELS_PER_LAYER / SCROLL_LINES))
5171 .y;
5172 if let Some(inspector) = self.inspector.clone() {
5173 inspector.update(cx, |inspector, _cx| {
5174 if let Some(depth) = inspector.pick_depth.as_mut() {
5175 *depth += f32::from(delta_y) / SCROLL_PIXELS_PER_LAYER;
5176 let max_depth = self.mouse_hit_test.ids.len() as f32 - 0.5;
5177 if *depth < 0.0 {
5178 *depth = 0.0;
5179 } else if *depth > max_depth {
5180 *depth = max_depth;
5181 }
5182 if let Some((_, inspector_id)) =
5183 self.hovered_inspector_hitbox(inspector, &self.rendered_frame)
5184 {
5185 inspector.set_active_element_id(inspector_id, self);
5186 }
5187 }
5188 });
5189 }
5190 }
5191 }
5192
5193 #[cfg(any(feature = "inspector", debug_assertions))]
5194 fn hovered_inspector_hitbox(
5195 &self,
5196 inspector: &Inspector,
5197 frame: &Frame,
5198 ) -> Option<(HitboxId, crate::InspectorElementId)> {
5199 if let Some(pick_depth) = inspector.pick_depth {
5200 let depth = (pick_depth as i64).try_into().unwrap_or(0);
5201 let max_skipped = self.mouse_hit_test.ids.len().saturating_sub(1);
5202 let skip_count = (depth as usize).min(max_skipped);
5203 for hitbox_id in self.mouse_hit_test.ids.iter().skip(skip_count) {
5204 if let Some(inspector_id) = frame.inspector_hitboxes.get(hitbox_id) {
5205 return Some((*hitbox_id, inspector_id.clone()));
5206 }
5207 }
5208 }
5209 None
5210 }
5211
5212 #[cfg(any(test, feature = "test-support"))]
5215 pub fn set_modifiers(&mut self, modifiers: Modifiers) {
5216 self.modifiers = modifiers;
5217 }
5218}
5219
5220slotmap::new_key_type! {
5222 pub struct WindowId;
5224}
5225
5226impl WindowId {
5227 pub fn as_u64(&self) -> u64 {
5229 self.0.as_ffi()
5230 }
5231}
5232
5233impl From<u64> for WindowId {
5234 fn from(value: u64) -> Self {
5235 WindowId(slotmap::KeyData::from_ffi(value))
5236 }
5237}
5238
5239#[derive(Deref, DerefMut)]
5242pub struct WindowHandle<V> {
5243 #[deref]
5244 #[deref_mut]
5245 pub(crate) any_handle: AnyWindowHandle,
5246 state_type: PhantomData<fn(V) -> V>,
5247}
5248
5249impl<V> Debug for WindowHandle<V> {
5250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5251 f.debug_struct("WindowHandle")
5252 .field("any_handle", &self.any_handle.id.as_u64())
5253 .finish()
5254 }
5255}
5256
5257impl<V: 'static + Render> WindowHandle<V> {
5258 pub fn new(id: WindowId) -> Self {
5261 WindowHandle {
5262 any_handle: AnyWindowHandle {
5263 id,
5264 state_type: TypeId::of::<V>(),
5265 },
5266 state_type: PhantomData,
5267 }
5268 }
5269
5270 #[cfg(any(test, feature = "test-support"))]
5274 pub fn root<C>(&self, cx: &mut C) -> Result<Entity<V>>
5275 where
5276 C: AppContext,
5277 {
5278 crate::Flatten::flatten(cx.update_window(self.any_handle, |root_view, _, _| {
5279 root_view
5280 .downcast::<V>()
5281 .map_err(|_| anyhow!("the type of the window's root view has changed"))
5282 }))
5283 }
5284
5285 pub fn update<C, R>(
5289 &self,
5290 cx: &mut C,
5291 update: impl FnOnce(&mut V, &mut Window, &mut Context<V>) -> R,
5292 ) -> Result<R>
5293 where
5294 C: AppContext,
5295 {
5296 cx.update_window(self.any_handle, |root_view, window, cx| {
5297 let view = root_view
5298 .downcast::<V>()
5299 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
5300
5301 Ok(view.update(cx, |view, cx| update(view, window, cx)))
5302 })?
5303 }
5304
5305 pub fn read<'a>(&self, cx: &'a App) -> Result<&'a V> {
5309 let x = cx
5310 .windows
5311 .get(self.id)
5312 .and_then(|window| {
5313 window
5314 .as_deref()
5315 .and_then(|window| window.root.clone())
5316 .map(|root_view| root_view.downcast::<V>())
5317 })
5318 .context("window not found")?
5319 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
5320
5321 Ok(x.read(cx))
5322 }
5323
5324 pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &App) -> R) -> Result<R>
5328 where
5329 C: AppContext,
5330 {
5331 cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
5332 }
5333
5334 pub fn entity<C>(&self, cx: &C) -> Result<Entity<V>>
5338 where
5339 C: AppContext,
5340 {
5341 cx.read_window(self, |root_view, _cx| root_view)
5342 }
5343
5344 pub fn is_active(&self, cx: &mut App) -> Option<bool> {
5349 cx.update_window(self.any_handle, |_, window, _| window.is_window_active())
5350 .ok()
5351 }
5352}
5353
5354impl<V> Copy for WindowHandle<V> {}
5355
5356impl<V> Clone for WindowHandle<V> {
5357 fn clone(&self) -> Self {
5358 *self
5359 }
5360}
5361
5362impl<V> PartialEq for WindowHandle<V> {
5363 fn eq(&self, other: &Self) -> bool {
5364 self.any_handle == other.any_handle
5365 }
5366}
5367
5368impl<V> Eq for WindowHandle<V> {}
5369
5370impl<V> Hash for WindowHandle<V> {
5371 fn hash<H: Hasher>(&self, state: &mut H) {
5372 self.any_handle.hash(state);
5373 }
5374}
5375
5376impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
5377 fn from(val: WindowHandle<V>) -> Self {
5378 val.any_handle
5379 }
5380}
5381
5382#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
5384pub struct AnyWindowHandle {
5385 pub(crate) id: WindowId,
5386 state_type: TypeId,
5387}
5388
5389impl AnyWindowHandle {
5390 pub fn window_id(&self) -> WindowId {
5392 self.id
5393 }
5394
5395 pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
5398 if TypeId::of::<T>() == self.state_type {
5399 Some(WindowHandle {
5400 any_handle: *self,
5401 state_type: PhantomData,
5402 })
5403 } else {
5404 None
5405 }
5406 }
5407
5408 pub fn update<C, R>(
5412 self,
5413 cx: &mut C,
5414 update: impl FnOnce(AnyView, &mut Window, &mut App) -> R,
5415 ) -> Result<R>
5416 where
5417 C: AppContext,
5418 {
5419 cx.update_window(self, update)
5420 }
5421
5422 pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(Entity<T>, &App) -> R) -> Result<R>
5426 where
5427 C: AppContext,
5428 T: 'static,
5429 {
5430 let view = self
5431 .downcast::<T>()
5432 .context("the type of the window's root view has changed")?;
5433
5434 cx.read_window(&view, read)
5435 }
5436}
5437
5438impl HasWindowHandle for Window {
5439 fn window_handle(&self) -> Result<raw_window_handle::WindowHandle<'_>, HandleError> {
5440 self.platform_window.window_handle()
5441 }
5442}
5443
5444impl HasDisplayHandle for Window {
5445 fn display_handle(
5446 &self,
5447 ) -> std::result::Result<raw_window_handle::DisplayHandle<'_>, HandleError> {
5448 self.platform_window.display_handle()
5449 }
5450}
5451
5452#[derive(Clone, Debug, Eq, PartialEq, Hash)]
5457pub enum ElementId {
5458 View(EntityId),
5460 Integer(u64),
5462 Name(SharedString),
5464 Uuid(Uuid),
5466 FocusHandle(FocusId),
5468 NamedInteger(SharedString, u64),
5470 Path(Arc<std::path::Path>),
5472 CodeLocation(core::panic::Location<'static>),
5474 NamedChild(Arc<ElementId>, SharedString),
5476}
5477
5478impl ElementId {
5479 pub fn named_usize(name: impl Into<SharedString>, integer: usize) -> ElementId {
5481 Self::NamedInteger(name.into(), integer as u64)
5482 }
5483}
5484
5485impl Display for ElementId {
5486 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
5487 match self {
5488 ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
5489 ElementId::Integer(ix) => write!(f, "{}", ix)?,
5490 ElementId::Name(name) => write!(f, "{}", name)?,
5491 ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
5492 ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
5493 ElementId::Uuid(uuid) => write!(f, "{}", uuid)?,
5494 ElementId::Path(path) => write!(f, "{}", path.display())?,
5495 ElementId::CodeLocation(location) => write!(f, "{}", location)?,
5496 ElementId::NamedChild(id, name) => write!(f, "{}-{}", id, name)?,
5497 }
5498
5499 Ok(())
5500 }
5501}
5502
5503impl TryInto<SharedString> for ElementId {
5504 type Error = anyhow::Error;
5505
5506 fn try_into(self) -> anyhow::Result<SharedString> {
5507 if let ElementId::Name(name) = self {
5508 Ok(name)
5509 } else {
5510 anyhow::bail!("element id is not string")
5511 }
5512 }
5513}
5514
5515impl From<usize> for ElementId {
5516 fn from(id: usize) -> Self {
5517 ElementId::Integer(id as u64)
5518 }
5519}
5520
5521impl From<i32> for ElementId {
5522 fn from(id: i32) -> Self {
5523 Self::Integer(id as u64)
5524 }
5525}
5526
5527impl From<SharedString> for ElementId {
5528 fn from(name: SharedString) -> Self {
5529 ElementId::Name(name)
5530 }
5531}
5532
5533impl From<String> for ElementId {
5534 fn from(name: String) -> Self {
5535 ElementId::Name(name.into())
5536 }
5537}
5538
5539impl From<Arc<str>> for ElementId {
5540 fn from(name: Arc<str>) -> Self {
5541 ElementId::Name(name.into())
5542 }
5543}
5544
5545impl From<Arc<std::path::Path>> for ElementId {
5546 fn from(path: Arc<std::path::Path>) -> Self {
5547 ElementId::Path(path)
5548 }
5549}
5550
5551impl From<&'static str> for ElementId {
5552 fn from(name: &'static str) -> Self {
5553 ElementId::Name(name.into())
5554 }
5555}
5556
5557impl<'a> From<&'a FocusHandle> for ElementId {
5558 fn from(handle: &'a FocusHandle) -> Self {
5559 ElementId::FocusHandle(handle.id)
5560 }
5561}
5562
5563impl From<(&'static str, EntityId)> for ElementId {
5564 fn from((name, id): (&'static str, EntityId)) -> Self {
5565 ElementId::NamedInteger(name.into(), id.as_u64())
5566 }
5567}
5568
5569impl From<(&'static str, usize)> for ElementId {
5570 fn from((name, id): (&'static str, usize)) -> Self {
5571 ElementId::NamedInteger(name.into(), id as u64)
5572 }
5573}
5574
5575impl From<(SharedString, usize)> for ElementId {
5576 fn from((name, id): (SharedString, usize)) -> Self {
5577 ElementId::NamedInteger(name, id as u64)
5578 }
5579}
5580
5581impl From<(&'static str, u64)> for ElementId {
5582 fn from((name, id): (&'static str, u64)) -> Self {
5583 ElementId::NamedInteger(name.into(), id)
5584 }
5585}
5586
5587impl From<Uuid> for ElementId {
5588 fn from(value: Uuid) -> Self {
5589 Self::Uuid(value)
5590 }
5591}
5592
5593impl From<(&'static str, u32)> for ElementId {
5594 fn from((name, id): (&'static str, u32)) -> Self {
5595 ElementId::NamedInteger(name.into(), id.into())
5596 }
5597}
5598
5599impl<T: Into<SharedString>> From<(ElementId, T)> for ElementId {
5600 fn from((id, name): (ElementId, T)) -> Self {
5601 ElementId::NamedChild(Arc::new(id), name.into())
5602 }
5603}
5604
5605impl From<&'static core::panic::Location<'static>> for ElementId {
5606 fn from(location: &'static core::panic::Location<'static>) -> Self {
5607 ElementId::CodeLocation(*location)
5608 }
5609}
5610
5611#[derive(Clone)]
5614pub struct PaintQuad {
5615 pub bounds: Bounds<Pixels>,
5617 pub corner_radii: Corners<Pixels>,
5619 pub background: Background,
5621 pub border_widths: Edges<Pixels>,
5623 pub border_color: Hsla,
5625 pub border_style: BorderStyle,
5627}
5628
5629impl PaintQuad {
5630 pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
5632 PaintQuad {
5633 corner_radii: corner_radii.into(),
5634 ..self
5635 }
5636 }
5637
5638 pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
5640 PaintQuad {
5641 border_widths: border_widths.into(),
5642 ..self
5643 }
5644 }
5645
5646 pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
5648 PaintQuad {
5649 border_color: border_color.into(),
5650 ..self
5651 }
5652 }
5653
5654 pub fn background(self, background: impl Into<Background>) -> Self {
5656 PaintQuad {
5657 background: background.into(),
5658 ..self
5659 }
5660 }
5661}
5662
5663pub fn quad(
5665 bounds: Bounds<Pixels>,
5666 corner_radii: impl Into<Corners<Pixels>>,
5667 background: impl Into<Background>,
5668 border_widths: impl Into<Edges<Pixels>>,
5669 border_color: impl Into<Hsla>,
5670 border_style: BorderStyle,
5671) -> PaintQuad {
5672 PaintQuad {
5673 bounds,
5674 corner_radii: corner_radii.into(),
5675 background: background.into(),
5676 border_widths: border_widths.into(),
5677 border_color: border_color.into(),
5678 border_style,
5679 }
5680}
5681
5682pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Background>) -> PaintQuad {
5684 PaintQuad {
5685 bounds: bounds.into(),
5686 corner_radii: (0.).into(),
5687 background: background.into(),
5688 border_widths: (0.).into(),
5689 border_color: transparent_black(),
5690 border_style: BorderStyle::default(),
5691 }
5692}
5693
5694pub fn outline(
5696 bounds: impl Into<Bounds<Pixels>>,
5697 border_color: impl Into<Hsla>,
5698 border_style: BorderStyle,
5699) -> PaintQuad {
5700 PaintQuad {
5701 bounds: bounds.into(),
5702 corner_radii: (0.).into(),
5703 background: transparent_black().into(),
5704 border_widths: (1.).into(),
5705 border_color: border_color.into(),
5706 border_style,
5707 }
5708}