1#![deny(missing_docs)]
2
3use crate::{
4 px, size, transparent_black, Action, AnyDrag, AnyTooltip, AnyView, AppContext, Arena,
5 AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
6 DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect,
7 Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, GlobalElementId, GlyphId, Hsla,
8 ImageData, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeyEvent, KeystrokeEvent, LayoutId,
9 Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseEvent, MouseMoveEvent,
10 MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput,
11 PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render,
12 RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, Scene, Shadow,
13 SharedString, Size, Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task,
14 Underline, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions,
15 SUBPIXEL_VARIANTS,
16};
17use anyhow::{anyhow, Context as _, Result};
18use collections::{FxHashMap, FxHashSet};
19use derive_more::{Deref, DerefMut};
20use futures::{
21 channel::{mpsc, oneshot},
22 StreamExt,
23};
24use media::core_video::CVImageBuffer;
25use parking_lot::RwLock;
26use slotmap::SlotMap;
27use smallvec::SmallVec;
28use std::{
29 any::{Any, TypeId},
30 borrow::{Borrow, BorrowMut, Cow},
31 cell::RefCell,
32 collections::hash_map::Entry,
33 fmt::Debug,
34 future::Future,
35 hash::{Hash, Hasher},
36 marker::PhantomData,
37 mem,
38 rc::Rc,
39 sync::{
40 atomic::{AtomicUsize, Ordering::SeqCst},
41 Arc,
42 },
43};
44use util::{post_inc, ResultExt};
45
46const ACTIVE_DRAG_Z_INDEX: u16 = 1;
47
48/// A global stacking order, which is created by stacking successive z-index values.
49/// Each z-index will always be interpreted in the context of its parent z-index.
50#[derive(Debug, Deref, DerefMut, Clone, Ord, PartialOrd, PartialEq, Eq, Default)]
51pub struct StackingOrder(SmallVec<[StackingContext; 64]>);
52
53/// A single entry in a primitive's z-index stacking order
54#[derive(Clone, Ord, PartialOrd, PartialEq, Eq, Default)]
55pub struct StackingContext {
56 z_index: u16,
57 id: u16,
58}
59
60impl std::fmt::Debug for StackingContext {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 write!(f, "{{{}.{}}} ", self.z_index, self.id)
63 }
64}
65
66/// Represents the two different phases when dispatching events.
67#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
68pub enum DispatchPhase {
69 /// After the capture phase comes the bubble phase, in which mouse event listeners are
70 /// invoked front to back and keyboard event listeners are invoked from the focused element
71 /// to the root of the element tree. This is the phase you'll most commonly want to use when
72 /// registering event listeners.
73 #[default]
74 Bubble,
75 /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard
76 /// listeners are invoked from the root of the tree downward toward the focused element. This phase
77 /// is used for special purposes such as clearing the "pressed" state for click events. If
78 /// you stop event propagation during this phase, you need to know what you're doing. Handlers
79 /// outside of the immediate region may rely on detecting non-local events during this phase.
80 Capture,
81}
82
83impl DispatchPhase {
84 /// Returns true if this represents the "bubble" phase.
85 pub fn bubble(self) -> bool {
86 self == DispatchPhase::Bubble
87 }
88
89 /// Returns true if this represents the "capture" phase.
90 pub fn capture(self) -> bool {
91 self == DispatchPhase::Capture
92 }
93}
94
95type AnyObserver = Box<dyn FnMut(&mut WindowContext) -> bool + 'static>;
96type AnyMouseListener = Box<dyn FnMut(&dyn Any, DispatchPhase, &mut WindowContext) + 'static>;
97type AnyWindowFocusListener = Box<dyn FnMut(&FocusEvent, &mut WindowContext) -> bool + 'static>;
98
99struct FocusEvent {
100 previous_focus_path: SmallVec<[FocusId; 8]>,
101 current_focus_path: SmallVec<[FocusId; 8]>,
102}
103
104slotmap::new_key_type! {
105 /// A globally unique identifier for a focusable element.
106 pub struct FocusId;
107}
108
109thread_local! {
110 pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(4 * 1024 * 1024));
111}
112
113impl FocusId {
114 /// Obtains whether the element associated with this handle is currently focused.
115 pub fn is_focused(&self, cx: &WindowContext) -> bool {
116 cx.window.focus == Some(*self)
117 }
118
119 /// Obtains whether the element associated with this handle contains the focused
120 /// element or is itself focused.
121 pub fn contains_focused(&self, cx: &WindowContext) -> bool {
122 cx.focused()
123 .map_or(false, |focused| self.contains(focused.id, cx))
124 }
125
126 /// Obtains whether the element associated with this handle is contained within the
127 /// focused element or is itself focused.
128 pub fn within_focused(&self, cx: &WindowContext) -> bool {
129 let focused = cx.focused();
130 focused.map_or(false, |focused| focused.id.contains(*self, cx))
131 }
132
133 /// Obtains whether this handle contains the given handle in the most recently rendered frame.
134 pub(crate) fn contains(&self, other: Self, cx: &WindowContext) -> bool {
135 cx.window
136 .rendered_frame
137 .dispatch_tree
138 .focus_contains(*self, other)
139 }
140}
141
142/// A handle which can be used to track and manipulate the focused element in a window.
143pub struct FocusHandle {
144 pub(crate) id: FocusId,
145 handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
146}
147
148impl std::fmt::Debug for FocusHandle {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 f.write_fmt(format_args!("FocusHandle({:?})", self.id))
151 }
152}
153
154impl FocusHandle {
155 pub(crate) fn new(handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>) -> Self {
156 let id = handles.write().insert(AtomicUsize::new(1));
157 Self {
158 id,
159 handles: handles.clone(),
160 }
161 }
162
163 pub(crate) fn for_id(
164 id: FocusId,
165 handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
166 ) -> Option<Self> {
167 let lock = handles.read();
168 let ref_count = lock.get(id)?;
169 if ref_count.load(SeqCst) == 0 {
170 None
171 } else {
172 ref_count.fetch_add(1, SeqCst);
173 Some(Self {
174 id,
175 handles: handles.clone(),
176 })
177 }
178 }
179
180 /// Moves the focus to the element associated with this handle.
181 pub fn focus(&self, cx: &mut WindowContext) {
182 cx.focus(self)
183 }
184
185 /// Obtains whether the element associated with this handle is currently focused.
186 pub fn is_focused(&self, cx: &WindowContext) -> bool {
187 self.id.is_focused(cx)
188 }
189
190 /// Obtains whether the element associated with this handle contains the focused
191 /// element or is itself focused.
192 pub fn contains_focused(&self, cx: &WindowContext) -> bool {
193 self.id.contains_focused(cx)
194 }
195
196 /// Obtains whether the element associated with this handle is contained within the
197 /// focused element or is itself focused.
198 pub fn within_focused(&self, cx: &WindowContext) -> bool {
199 self.id.within_focused(cx)
200 }
201
202 /// Obtains whether this handle contains the given handle in the most recently rendered frame.
203 pub fn contains(&self, other: &Self, cx: &WindowContext) -> bool {
204 self.id.contains(other.id, cx)
205 }
206}
207
208impl Clone for FocusHandle {
209 fn clone(&self) -> Self {
210 Self::for_id(self.id, &self.handles).unwrap()
211 }
212}
213
214impl PartialEq for FocusHandle {
215 fn eq(&self, other: &Self) -> bool {
216 self.id == other.id
217 }
218}
219
220impl Eq for FocusHandle {}
221
222impl Drop for FocusHandle {
223 fn drop(&mut self) {
224 self.handles
225 .read()
226 .get(self.id)
227 .unwrap()
228 .fetch_sub(1, SeqCst);
229 }
230}
231
232/// FocusableView allows users of your view to easily
233/// focus it (using cx.focus_view(view))
234pub trait FocusableView: 'static + Render {
235 /// Returns the focus handle associated with this view.
236 fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
237}
238
239/// ManagedView is a view (like a Modal, Popover, Menu, etc.)
240/// where the lifecycle of the view is handled by another view.
241pub trait ManagedView: FocusableView + EventEmitter<DismissEvent> {}
242
243impl<M: FocusableView + EventEmitter<DismissEvent>> ManagedView for M {}
244
245/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.
246pub struct DismissEvent;
247
248// Holds the state for a specific window.
249#[doc(hidden)]
250pub struct Window {
251 pub(crate) handle: AnyWindowHandle,
252 pub(crate) removed: bool,
253 pub(crate) platform_window: Box<dyn PlatformWindow>,
254 display_id: DisplayId,
255 sprite_atlas: Arc<dyn PlatformAtlas>,
256 rem_size: Pixels,
257 viewport_size: Size<Pixels>,
258 layout_engine: Option<TaffyLayoutEngine>,
259 pub(crate) root_view: Option<AnyView>,
260 pub(crate) element_id_stack: GlobalElementId,
261 pub(crate) rendered_frame: Frame,
262 pub(crate) next_frame: Frame,
263 pub(crate) dirty_views: FxHashSet<EntityId>,
264 pub(crate) focus_handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
265 focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
266 focus_lost_listeners: SubscriberSet<(), AnyObserver>,
267 default_prevented: bool,
268 mouse_position: Point<Pixels>,
269 modifiers: Modifiers,
270 scale_factor: f32,
271 bounds: WindowBounds,
272 bounds_observers: SubscriberSet<(), AnyObserver>,
273 active: bool,
274 pub(crate) dirty: bool,
275 pub(crate) refreshing: bool,
276 pub(crate) drawing: bool,
277 activation_observers: SubscriberSet<(), AnyObserver>,
278 pub(crate) focus: Option<FocusId>,
279 focus_enabled: bool,
280
281 #[cfg(any(test, feature = "test-support"))]
282 pub(crate) focus_invalidated: bool,
283}
284
285pub(crate) struct ElementStateBox {
286 inner: Box<dyn Any>,
287 parent_view_id: EntityId,
288 #[cfg(debug_assertions)]
289 type_name: &'static str,
290}
291
292struct RequestedInputHandler {
293 view_id: EntityId,
294 handler: Option<Box<dyn PlatformInputHandler>>,
295}
296
297struct TooltipRequest {
298 view_id: EntityId,
299 tooltip: AnyTooltip,
300}
301
302pub(crate) struct Frame {
303 focus: Option<FocusId>,
304 window_active: bool,
305 pub(crate) element_states: FxHashMap<GlobalElementId, ElementStateBox>,
306 mouse_listeners: FxHashMap<TypeId, Vec<(StackingOrder, EntityId, AnyMouseListener)>>,
307 pub(crate) dispatch_tree: DispatchTree,
308 pub(crate) scene: Scene,
309 pub(crate) depth_map: Vec<(StackingOrder, EntityId, Bounds<Pixels>)>,
310 pub(crate) z_index_stack: StackingOrder,
311 next_stacking_order_id: u16,
312 next_root_z_index: u16,
313 content_mask_stack: Vec<ContentMask<Pixels>>,
314 element_offset_stack: Vec<Point<Pixels>>,
315 requested_input_handler: Option<RequestedInputHandler>,
316 tooltip_request: Option<TooltipRequest>,
317 cursor_styles: FxHashMap<EntityId, CursorStyle>,
318 requested_cursor_style: Option<CursorStyle>,
319 pub(crate) view_stack: Vec<EntityId>,
320 pub(crate) reused_views: FxHashSet<EntityId>,
321}
322
323impl Frame {
324 fn new(dispatch_tree: DispatchTree) -> Self {
325 Frame {
326 focus: None,
327 window_active: false,
328 element_states: FxHashMap::default(),
329 mouse_listeners: FxHashMap::default(),
330 dispatch_tree,
331 scene: Scene::default(),
332 depth_map: Vec::new(),
333 z_index_stack: StackingOrder::default(),
334 next_stacking_order_id: 0,
335 next_root_z_index: 0,
336 content_mask_stack: Vec::new(),
337 element_offset_stack: Vec::new(),
338 requested_input_handler: None,
339 tooltip_request: None,
340 cursor_styles: FxHashMap::default(),
341 requested_cursor_style: None,
342 view_stack: Vec::new(),
343 reused_views: FxHashSet::default(),
344 }
345 }
346
347 fn clear(&mut self) {
348 self.element_states.clear();
349 self.mouse_listeners.values_mut().for_each(Vec::clear);
350 self.dispatch_tree.clear();
351 self.depth_map.clear();
352 self.next_stacking_order_id = 0;
353 self.next_root_z_index = 0;
354 self.reused_views.clear();
355 self.scene.clear();
356 self.requested_input_handler.take();
357 self.tooltip_request.take();
358 self.cursor_styles.clear();
359 self.requested_cursor_style.take();
360 debug_assert_eq!(self.view_stack.len(), 0);
361 }
362
363 fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
364 self.focus
365 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
366 .unwrap_or_default()
367 }
368
369 fn finish(&mut self, prev_frame: &mut Self) {
370 // Reuse mouse listeners that didn't change since the last frame.
371 for (type_id, listeners) in &mut prev_frame.mouse_listeners {
372 let next_listeners = self.mouse_listeners.entry(*type_id).or_default();
373 for (order, view_id, listener) in listeners.drain(..) {
374 if self.reused_views.contains(&view_id) {
375 next_listeners.push((order, view_id, listener));
376 }
377 }
378 }
379
380 // Reuse entries in the depth map that didn't change since the last frame.
381 for (order, view_id, bounds) in prev_frame.depth_map.drain(..) {
382 if self.reused_views.contains(&view_id) {
383 match self
384 .depth_map
385 .binary_search_by(|(level, _, _)| order.cmp(level))
386 {
387 Ok(i) | Err(i) => self.depth_map.insert(i, (order, view_id, bounds)),
388 }
389 }
390 }
391
392 // Retain element states for views that didn't change since the last frame.
393 for (element_id, state) in prev_frame.element_states.drain() {
394 if self.reused_views.contains(&state.parent_view_id) {
395 self.element_states.entry(element_id).or_insert(state);
396 }
397 }
398
399 // Reuse geometry that didn't change since the last frame.
400 self.scene
401 .reuse_views(&self.reused_views, &mut prev_frame.scene);
402 self.scene.finish();
403 }
404}
405
406impl Window {
407 pub(crate) fn new(
408 handle: AnyWindowHandle,
409 options: WindowOptions,
410 cx: &mut AppContext,
411 ) -> Self {
412 let platform_window = cx.platform.open_window(handle, options);
413 let display_id = platform_window.display().id();
414 let sprite_atlas = platform_window.sprite_atlas();
415 let mouse_position = platform_window.mouse_position();
416 let modifiers = platform_window.modifiers();
417 let content_size = platform_window.content_size();
418 let scale_factor = platform_window.scale_factor();
419 let bounds = platform_window.bounds();
420
421 platform_window.on_request_frame(Box::new({
422 let mut cx = cx.to_async();
423 move || {
424 handle.update(&mut cx, |_, cx| cx.draw()).log_err();
425 }
426 }));
427 platform_window.on_resize(Box::new({
428 let mut cx = cx.to_async();
429 move |_, _| {
430 handle
431 .update(&mut cx, |_, cx| cx.window_bounds_changed())
432 .log_err();
433 }
434 }));
435 platform_window.on_moved(Box::new({
436 let mut cx = cx.to_async();
437 move || {
438 handle
439 .update(&mut cx, |_, cx| cx.window_bounds_changed())
440 .log_err();
441 }
442 }));
443 platform_window.on_active_status_change(Box::new({
444 let mut cx = cx.to_async();
445 move |active| {
446 handle
447 .update(&mut cx, |_, cx| {
448 cx.window.active = active;
449 cx.window
450 .activation_observers
451 .clone()
452 .retain(&(), |callback| callback(cx));
453 })
454 .log_err();
455 }
456 }));
457
458 platform_window.on_input({
459 let mut cx = cx.to_async();
460 Box::new(move |event| {
461 handle
462 .update(&mut cx, |_, cx| cx.dispatch_event(event))
463 .log_err()
464 .unwrap_or(false)
465 })
466 });
467
468 Window {
469 handle,
470 removed: false,
471 platform_window,
472 display_id,
473 sprite_atlas,
474 rem_size: px(16.),
475 viewport_size: content_size,
476 layout_engine: Some(TaffyLayoutEngine::new()),
477 root_view: None,
478 element_id_stack: GlobalElementId::default(),
479 rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
480 next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
481 dirty_views: FxHashSet::default(),
482 focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
483 focus_listeners: SubscriberSet::new(),
484 focus_lost_listeners: SubscriberSet::new(),
485 default_prevented: true,
486 mouse_position,
487 modifiers,
488 scale_factor,
489 bounds,
490 bounds_observers: SubscriberSet::new(),
491 active: false,
492 dirty: false,
493 refreshing: false,
494 drawing: false,
495 activation_observers: SubscriberSet::new(),
496 focus: None,
497 focus_enabled: true,
498
499 #[cfg(any(test, feature = "test-support"))]
500 focus_invalidated: false,
501 }
502 }
503}
504
505/// Indicates which region of the window is visible. Content falling outside of this mask will not be
506/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type
507/// to leave room to support more complex shapes in the future.
508#[derive(Clone, Debug, Default, PartialEq, Eq)]
509#[repr(C)]
510pub struct ContentMask<P: Clone + Default + Debug> {
511 /// The bounds
512 pub bounds: Bounds<P>,
513}
514
515impl ContentMask<Pixels> {
516 /// Scale the content mask's pixel units by the given scaling factor.
517 pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
518 ContentMask {
519 bounds: self.bounds.scale(factor),
520 }
521 }
522
523 /// Intersect the content mask with the given content mask.
524 pub fn intersect(&self, other: &Self) -> Self {
525 let bounds = self.bounds.intersect(&other.bounds);
526 ContentMask { bounds }
527 }
528}
529
530/// Provides access to application state in the context of a single window. Derefs
531/// to an [`AppContext`], so you can also pass a [`WindowContext`] to any method that takes
532/// an [`AppContext`] and call any [`AppContext`] methods.
533pub struct WindowContext<'a> {
534 pub(crate) app: &'a mut AppContext,
535 pub(crate) window: &'a mut Window,
536}
537
538impl<'a> WindowContext<'a> {
539 pub(crate) fn new(app: &'a mut AppContext, window: &'a mut Window) -> Self {
540 Self { app, window }
541 }
542
543 /// Obtain a handle to the window that belongs to this context.
544 pub fn window_handle(&self) -> AnyWindowHandle {
545 self.window.handle
546 }
547
548 /// Mark the window as dirty, scheduling it to be redrawn on the next frame.
549 pub fn refresh(&mut self) {
550 if !self.window.drawing {
551 self.window.refreshing = true;
552 self.window.dirty = true;
553 }
554 }
555
556 /// Close this window.
557 pub fn remove_window(&mut self) {
558 self.window.removed = true;
559 }
560
561 /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus
562 /// for elements rendered within this window.
563 pub fn focus_handle(&mut self) -> FocusHandle {
564 FocusHandle::new(&self.window.focus_handles)
565 }
566
567 /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.
568 pub fn focused(&self) -> Option<FocusHandle> {
569 self.window
570 .focus
571 .and_then(|id| FocusHandle::for_id(id, &self.window.focus_handles))
572 }
573
574 /// Move focus to the element associated with the given [`FocusHandle`].
575 pub fn focus(&mut self, handle: &FocusHandle) {
576 if !self.window.focus_enabled || self.window.focus == Some(handle.id) {
577 return;
578 }
579
580 self.window.focus = Some(handle.id);
581 self.window
582 .rendered_frame
583 .dispatch_tree
584 .clear_pending_keystrokes();
585
586 #[cfg(any(test, feature = "test-support"))]
587 {
588 self.window.focus_invalidated = true;
589 }
590
591 self.refresh();
592 }
593
594 /// Remove focus from all elements within this context's window.
595 pub fn blur(&mut self) {
596 if !self.window.focus_enabled {
597 return;
598 }
599
600 self.window.focus = None;
601 self.refresh();
602 }
603
604 /// Blur the window and don't allow anything in it to be focused again.
605 pub fn disable_focus(&mut self) {
606 self.blur();
607 self.window.focus_enabled = false;
608 }
609
610 /// Dispatch the given action on the currently focused element.
611 pub fn dispatch_action(&mut self, action: Box<dyn Action>) {
612 let focus_handle = self.focused();
613
614 self.defer(move |cx| {
615 let node_id = focus_handle
616 .and_then(|handle| {
617 cx.window
618 .rendered_frame
619 .dispatch_tree
620 .focusable_node_id(handle.id)
621 })
622 .unwrap_or_else(|| cx.window.rendered_frame.dispatch_tree.root_node_id());
623
624 cx.propagate_event = true;
625 cx.dispatch_action_on_node(node_id, action);
626 })
627 }
628
629 pub(crate) fn dispatch_keystroke_observers(
630 &mut self,
631 event: &dyn Any,
632 action: Option<Box<dyn Action>>,
633 ) {
634 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
635 return;
636 };
637
638 self.keystroke_observers
639 .clone()
640 .retain(&(), move |callback| {
641 (callback)(
642 &KeystrokeEvent {
643 keystroke: key_down_event.keystroke.clone(),
644 action: action.as_ref().map(|action| action.boxed_clone()),
645 },
646 self,
647 );
648 true
649 });
650 }
651
652 pub(crate) fn clear_pending_keystrokes(&mut self) {
653 self.window
654 .rendered_frame
655 .dispatch_tree
656 .clear_pending_keystrokes();
657 self.window
658 .next_frame
659 .dispatch_tree
660 .clear_pending_keystrokes();
661 }
662
663 /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
664 /// that are currently on the stack to be returned to the app.
665 pub fn defer(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
666 let handle = self.window.handle;
667 self.app.defer(move |cx| {
668 handle.update(cx, |_, cx| f(cx)).ok();
669 });
670 }
671
672 /// Subscribe to events emitted by a model or view.
673 /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
674 /// The callback will be invoked a handle to the emitting entity (either a [`View`] or [`Model`]), the event, and a window context for the current window.
675 pub fn subscribe<Emitter, E, Evt>(
676 &mut self,
677 entity: &E,
678 mut on_event: impl FnMut(E, &Evt, &mut WindowContext<'_>) + 'static,
679 ) -> Subscription
680 where
681 Emitter: EventEmitter<Evt>,
682 E: Entity<Emitter>,
683 Evt: 'static,
684 {
685 let entity_id = entity.entity_id();
686 let entity = entity.downgrade();
687 let window_handle = self.window.handle;
688 let (subscription, activate) = self.app.event_listeners.insert(
689 entity_id,
690 (
691 TypeId::of::<Evt>(),
692 Box::new(move |event, cx| {
693 window_handle
694 .update(cx, |_, cx| {
695 if let Some(handle) = E::upgrade_from(&entity) {
696 let event = event.downcast_ref().expect("invalid event type");
697 on_event(handle, event, cx);
698 true
699 } else {
700 false
701 }
702 })
703 .unwrap_or(false)
704 }),
705 ),
706 );
707 self.app.defer(move |_| activate());
708 subscription
709 }
710
711 /// Create an `AsyncWindowContext`, which has a static lifetime and can be held across
712 /// await points in async code.
713 pub fn to_async(&self) -> AsyncWindowContext {
714 AsyncWindowContext::new(self.app.to_async(), self.window.handle)
715 }
716
717 /// Schedule the given closure to be run directly after the current frame is rendered.
718 pub fn on_next_frame(&mut self, callback: impl FnOnce(&mut WindowContext) + 'static) {
719 let handle = self.window.handle;
720 let display_id = self.window.display_id;
721
722 let mut frame_consumers = std::mem::take(&mut self.app.frame_consumers);
723 if let Entry::Vacant(e) = frame_consumers.entry(display_id) {
724 let (tx, mut rx) = mpsc::unbounded::<()>();
725 self.platform.set_display_link_output_callback(
726 display_id,
727 Box::new(move |_current_time, _output_time| _ = tx.unbounded_send(())),
728 );
729
730 let consumer_task = self.app.spawn(|cx| async move {
731 while rx.next().await.is_some() {
732 cx.update(|cx| {
733 for callback in cx
734 .next_frame_callbacks
735 .get_mut(&display_id)
736 .unwrap()
737 .drain(..)
738 .collect::<SmallVec<[_; 32]>>()
739 {
740 callback(cx);
741 }
742 })
743 .ok();
744
745 // Flush effects, then stop the display link if no new next_frame_callbacks have been added.
746
747 cx.update(|cx| {
748 if cx.next_frame_callbacks.is_empty() {
749 cx.platform.stop_display_link(display_id);
750 }
751 })
752 .ok();
753 }
754 });
755 e.insert(consumer_task);
756 }
757 debug_assert!(self.app.frame_consumers.is_empty());
758 self.app.frame_consumers = frame_consumers;
759
760 if self.next_frame_callbacks.is_empty() {
761 self.platform.start_display_link(display_id);
762 }
763
764 self.next_frame_callbacks
765 .entry(display_id)
766 .or_default()
767 .push(Box::new(move |cx: &mut AppContext| {
768 cx.update_window(handle, |_root_view, cx| callback(cx)).ok();
769 }));
770 }
771
772 /// Spawn the future returned by the given closure on the application thread pool.
773 /// The closure is provided a handle to the current window and an `AsyncWindowContext` for
774 /// use within your future.
775 pub fn spawn<Fut, R>(&mut self, f: impl FnOnce(AsyncWindowContext) -> Fut) -> Task<R>
776 where
777 R: 'static,
778 Fut: Future<Output = R> + 'static,
779 {
780 self.app
781 .spawn(|app| f(AsyncWindowContext::new(app, self.window.handle)))
782 }
783
784 /// Update the global of the given type. The given closure is given simultaneous mutable
785 /// access both to the global and the context.
786 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
787 where
788 G: 'static,
789 {
790 let mut global = self.app.lease_global::<G>();
791 let result = f(&mut global, self);
792 self.app.end_global_lease(global);
793 result
794 }
795
796 #[must_use]
797 /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
798 /// layout is being requested, along with the layout ids of any children. This method is called during
799 /// calls to the `Element::layout` trait method and enables any element to participate in layout.
800 pub fn request_layout(
801 &mut self,
802 style: &Style,
803 children: impl IntoIterator<Item = LayoutId>,
804 ) -> LayoutId {
805 self.app.layout_id_buffer.clear();
806 self.app.layout_id_buffer.extend(children);
807 let rem_size = self.rem_size();
808
809 self.window.layout_engine.as_mut().unwrap().request_layout(
810 style,
811 rem_size,
812 &self.app.layout_id_buffer,
813 )
814 }
815
816 /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
817 /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
818 /// determine the element's size. One place this is used internally is when measuring text.
819 ///
820 /// The given closure is invoked at layout time with the known dimensions and available space and
821 /// returns a `Size`.
822 pub fn request_measured_layout<
823 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
824 + 'static,
825 >(
826 &mut self,
827 style: Style,
828 measure: F,
829 ) -> LayoutId {
830 let rem_size = self.rem_size();
831 self.window
832 .layout_engine
833 .as_mut()
834 .unwrap()
835 .request_measured_layout(style, rem_size, measure)
836 }
837
838 pub(crate) fn layout_style(&self, layout_id: LayoutId) -> Option<&Style> {
839 self.window
840 .layout_engine
841 .as_ref()
842 .unwrap()
843 .requested_style(layout_id)
844 }
845
846 /// Compute the layout for the given id within the given available space.
847 /// This method is called for its side effect, typically by the framework prior to painting.
848 /// After calling it, you can request the bounds of the given layout node id or any descendant.
849 pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
850 let mut layout_engine = self.window.layout_engine.take().unwrap();
851 layout_engine.compute_layout(layout_id, available_space, self);
852 self.window.layout_engine = Some(layout_engine);
853 }
854
855 /// Obtain the bounds computed for the given LayoutId relative to the window. This method should not
856 /// be invoked until the paint phase begins, and will usually be invoked by GPUI itself automatically
857 /// in order to pass your element its `Bounds` automatically.
858 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
859 let mut bounds = self
860 .window
861 .layout_engine
862 .as_mut()
863 .unwrap()
864 .layout_bounds(layout_id)
865 .map(Into::into);
866 bounds.origin += self.element_offset();
867 bounds
868 }
869
870 fn window_bounds_changed(&mut self) {
871 self.window.scale_factor = self.window.platform_window.scale_factor();
872 self.window.viewport_size = self.window.platform_window.content_size();
873 self.window.bounds = self.window.platform_window.bounds();
874 self.window.display_id = self.window.platform_window.display().id();
875 self.refresh();
876
877 self.window
878 .bounds_observers
879 .clone()
880 .retain(&(), |callback| callback(self));
881 }
882
883 /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.
884 pub fn window_bounds(&self) -> WindowBounds {
885 self.window.bounds
886 }
887
888 /// Returns the size of the drawable area within the window.
889 pub fn viewport_size(&self) -> Size<Pixels> {
890 self.window.viewport_size
891 }
892
893 /// Returns whether this window is focused by the operating system (receiving key events).
894 pub fn is_window_active(&self) -> bool {
895 self.window.active
896 }
897
898 /// Toggle zoom on the window.
899 pub fn zoom_window(&self) {
900 self.window.platform_window.zoom();
901 }
902
903 /// Update the window's title at the platform level.
904 pub fn set_window_title(&mut self, title: &str) {
905 self.window.platform_window.set_title(title);
906 }
907
908 /// Mark the window as dirty at the platform level.
909 pub fn set_window_edited(&mut self, edited: bool) {
910 self.window.platform_window.set_edited(edited);
911 }
912
913 /// Determine the display on which the window is visible.
914 pub fn display(&self) -> Option<Rc<dyn PlatformDisplay>> {
915 self.platform
916 .displays()
917 .into_iter()
918 .find(|display| display.id() == self.window.display_id)
919 }
920
921 /// Show the platform character palette.
922 pub fn show_character_palette(&self) {
923 self.window.platform_window.show_character_palette();
924 }
925
926 /// The scale factor of the display associated with the window. For example, it could
927 /// return 2.0 for a "retina" display, indicating that each logical pixel should actually
928 /// be rendered as two pixels on screen.
929 pub fn scale_factor(&self) -> f32 {
930 self.window.scale_factor
931 }
932
933 /// The size of an em for the base font of the application. Adjusting this value allows the
934 /// UI to scale, just like zooming a web page.
935 pub fn rem_size(&self) -> Pixels {
936 self.window.rem_size
937 }
938
939 /// Sets the size of an em for the base font of the application. Adjusting this value allows the
940 /// UI to scale, just like zooming a web page.
941 pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
942 self.window.rem_size = rem_size.into();
943 }
944
945 /// The line height associated with the current text style.
946 pub fn line_height(&self) -> Pixels {
947 let rem_size = self.rem_size();
948 let text_style = self.text_style();
949 text_style
950 .line_height
951 .to_pixels(text_style.font_size, rem_size)
952 }
953
954 /// Call to prevent the default action of an event. Currently only used to prevent
955 /// parent elements from becoming focused on mouse down.
956 pub fn prevent_default(&mut self) {
957 self.window.default_prevented = true;
958 }
959
960 /// Obtain whether default has been prevented for the event currently being dispatched.
961 pub fn default_prevented(&self) -> bool {
962 self.window.default_prevented
963 }
964
965 /// Register a mouse event listener on the window for the next frame. The type of event
966 /// is determined by the first parameter of the given listener. When the next frame is rendered
967 /// the listener will be cleared.
968 pub fn on_mouse_event<Event: MouseEvent>(
969 &mut self,
970 mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static,
971 ) {
972 let view_id = self.parent_view_id();
973 let order = self.window.next_frame.z_index_stack.clone();
974 self.window
975 .next_frame
976 .mouse_listeners
977 .entry(TypeId::of::<Event>())
978 .or_default()
979 .push((
980 order,
981 view_id,
982 Box::new(
983 move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| {
984 handler(event.downcast_ref().unwrap(), phase, cx)
985 },
986 ),
987 ))
988 }
989
990 /// Register a key event listener on the window for the next frame. The type of event
991 /// is determined by the first parameter of the given listener. When the next frame is rendered
992 /// the listener will be cleared.
993 ///
994 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
995 /// a specific need to register a global listener.
996 pub fn on_key_event<Event: KeyEvent>(
997 &mut self,
998 listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static,
999 ) {
1000 self.window.next_frame.dispatch_tree.on_key_event(Rc::new(
1001 move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| {
1002 if let Some(event) = event.downcast_ref::<Event>() {
1003 listener(event, phase, cx)
1004 }
1005 },
1006 ));
1007 }
1008
1009 /// Register an action listener on the window for the next frame. The type of action
1010 /// is determined by the first parameter of the given listener. When the next frame is rendered
1011 /// the listener will be cleared.
1012 ///
1013 /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
1014 /// a specific need to register a global listener.
1015 pub fn on_action(
1016 &mut self,
1017 action_type: TypeId,
1018 listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static,
1019 ) {
1020 self.window
1021 .next_frame
1022 .dispatch_tree
1023 .on_action(action_type, Rc::new(listener));
1024 }
1025
1026 /// Determine whether the given action is available along the dispatch path to the currently focused element.
1027 pub fn is_action_available(&self, action: &dyn Action) -> bool {
1028 let target = self
1029 .focused()
1030 .and_then(|focused_handle| {
1031 self.window
1032 .rendered_frame
1033 .dispatch_tree
1034 .focusable_node_id(focused_handle.id)
1035 })
1036 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
1037 self.window
1038 .rendered_frame
1039 .dispatch_tree
1040 .is_action_available(action, target)
1041 }
1042
1043 /// The position of the mouse relative to the window.
1044 pub fn mouse_position(&self) -> Point<Pixels> {
1045 self.window.mouse_position
1046 }
1047
1048 /// The current state of the keyboard's modifiers
1049 pub fn modifiers(&self) -> Modifiers {
1050 self.window.modifiers
1051 }
1052
1053 /// Update the cursor style at the platform level.
1054 pub fn set_cursor_style(&mut self, style: CursorStyle) {
1055 let view_id = self.parent_view_id();
1056 self.window.next_frame.cursor_styles.insert(view_id, style);
1057 self.window.next_frame.requested_cursor_style = Some(style);
1058 }
1059
1060 /// Set a tooltip to be rendered for the upcoming frame
1061 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) {
1062 let view_id = self.parent_view_id();
1063 self.window.next_frame.tooltip_request = Some(TooltipRequest { view_id, tooltip });
1064 }
1065
1066 /// Called during painting to track which z-index is on top at each pixel position
1067 pub fn add_opaque_layer(&mut self, bounds: Bounds<Pixels>) {
1068 let stacking_order = self.window.next_frame.z_index_stack.clone();
1069 let view_id = self.parent_view_id();
1070 let depth_map = &mut self.window.next_frame.depth_map;
1071 match depth_map.binary_search_by(|(level, _, _)| stacking_order.cmp(level)) {
1072 Ok(i) | Err(i) => depth_map.insert(i, (stacking_order, view_id, bounds)),
1073 }
1074 }
1075
1076 /// Returns true if there is no opaque layer containing the given point
1077 /// on top of the given level. Layers whose level is an extension of the
1078 /// level are not considered to be on top of the level.
1079 pub fn was_top_layer(&self, point: &Point<Pixels>, level: &StackingOrder) -> bool {
1080 for (opaque_level, _, bounds) in self.window.rendered_frame.depth_map.iter() {
1081 if level >= opaque_level {
1082 break;
1083 }
1084
1085 if bounds.contains(point) && !opaque_level.starts_with(level) {
1086 return false;
1087 }
1088 }
1089 true
1090 }
1091
1092 pub(crate) fn was_top_layer_under_active_drag(
1093 &self,
1094 point: &Point<Pixels>,
1095 level: &StackingOrder,
1096 ) -> bool {
1097 for (opaque_level, _, bounds) in self.window.rendered_frame.depth_map.iter() {
1098 if level >= opaque_level {
1099 break;
1100 }
1101 if opaque_level
1102 .first()
1103 .map(|c| c.z_index == ACTIVE_DRAG_Z_INDEX)
1104 .unwrap_or(false)
1105 {
1106 continue;
1107 }
1108
1109 if bounds.contains(point) && !opaque_level.starts_with(level) {
1110 return false;
1111 }
1112 }
1113 true
1114 }
1115
1116 /// Called during painting to get the current stacking order.
1117 pub fn stacking_order(&self) -> &StackingOrder {
1118 &self.window.next_frame.z_index_stack
1119 }
1120
1121 /// Paint one or more drop shadows into the scene for the next frame at the current z-index.
1122 pub fn paint_shadows(
1123 &mut self,
1124 bounds: Bounds<Pixels>,
1125 corner_radii: Corners<Pixels>,
1126 shadows: &[BoxShadow],
1127 ) {
1128 let scale_factor = self.scale_factor();
1129 let content_mask = self.content_mask();
1130 let view_id = self.parent_view_id();
1131 let window = &mut *self.window;
1132 for shadow in shadows {
1133 let mut shadow_bounds = bounds;
1134 shadow_bounds.origin += shadow.offset;
1135 shadow_bounds.dilate(shadow.spread_radius);
1136 window.next_frame.scene.insert(
1137 &window.next_frame.z_index_stack,
1138 Shadow {
1139 view_id: view_id.into(),
1140 layer_id: 0,
1141 order: 0,
1142 bounds: shadow_bounds.scale(scale_factor),
1143 content_mask: content_mask.scale(scale_factor),
1144 corner_radii: corner_radii.scale(scale_factor),
1145 color: shadow.color,
1146 blur_radius: shadow.blur_radius.scale(scale_factor),
1147 },
1148 );
1149 }
1150 }
1151
1152 /// Paint one or more quads into the scene for the next frame at the current stacking context.
1153 /// Quads are colored rectangular regions with an optional background, border, and corner radius.
1154 /// see [`fill`], [`outline`], and [`quad`] to construct this type.
1155 pub fn paint_quad(&mut self, quad: PaintQuad) {
1156 let scale_factor = self.scale_factor();
1157 let content_mask = self.content_mask();
1158 let view_id = self.parent_view_id();
1159
1160 let window = &mut *self.window;
1161 window.next_frame.scene.insert(
1162 &window.next_frame.z_index_stack,
1163 Quad {
1164 view_id: view_id.into(),
1165 layer_id: 0,
1166 order: 0,
1167 bounds: quad.bounds.scale(scale_factor),
1168 content_mask: content_mask.scale(scale_factor),
1169 background: quad.background,
1170 border_color: quad.border_color,
1171 corner_radii: quad.corner_radii.scale(scale_factor),
1172 border_widths: quad.border_widths.scale(scale_factor),
1173 },
1174 );
1175 }
1176
1177 /// Paint the given `Path` into the scene for the next frame at the current z-index.
1178 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Hsla>) {
1179 let scale_factor = self.scale_factor();
1180 let content_mask = self.content_mask();
1181 let view_id = self.parent_view_id();
1182
1183 path.content_mask = content_mask;
1184 path.color = color.into();
1185 path.view_id = view_id.into();
1186 let window = &mut *self.window;
1187 window
1188 .next_frame
1189 .scene
1190 .insert(&window.next_frame.z_index_stack, path.scale(scale_factor));
1191 }
1192
1193 /// Paint an underline into the scene for the next frame at the current z-index.
1194 pub fn paint_underline(
1195 &mut self,
1196 origin: Point<Pixels>,
1197 width: Pixels,
1198 style: &UnderlineStyle,
1199 ) {
1200 let scale_factor = self.scale_factor();
1201 let height = if style.wavy {
1202 style.thickness * 3.
1203 } else {
1204 style.thickness
1205 };
1206 let bounds = Bounds {
1207 origin,
1208 size: size(width, height),
1209 };
1210 let content_mask = self.content_mask();
1211 let view_id = self.parent_view_id();
1212
1213 let window = &mut *self.window;
1214 window.next_frame.scene.insert(
1215 &window.next_frame.z_index_stack,
1216 Underline {
1217 view_id: view_id.into(),
1218 layer_id: 0,
1219 order: 0,
1220 bounds: bounds.scale(scale_factor),
1221 content_mask: content_mask.scale(scale_factor),
1222 thickness: style.thickness.scale(scale_factor),
1223 color: style.color.unwrap_or_default(),
1224 wavy: style.wavy,
1225 },
1226 );
1227 }
1228
1229 /// Paint a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
1230 /// The y component of the origin is the baseline of the glyph.
1231 pub fn paint_glyph(
1232 &mut self,
1233 origin: Point<Pixels>,
1234 font_id: FontId,
1235 glyph_id: GlyphId,
1236 font_size: Pixels,
1237 color: Hsla,
1238 ) -> Result<()> {
1239 let scale_factor = self.scale_factor();
1240 let glyph_origin = origin.scale(scale_factor);
1241 let subpixel_variant = Point {
1242 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
1243 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
1244 };
1245 let params = RenderGlyphParams {
1246 font_id,
1247 glyph_id,
1248 font_size,
1249 subpixel_variant,
1250 scale_factor,
1251 is_emoji: false,
1252 };
1253
1254 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
1255 if !raster_bounds.is_zero() {
1256 let tile =
1257 self.window
1258 .sprite_atlas
1259 .get_or_insert_with(¶ms.clone().into(), &mut || {
1260 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
1261 Ok((size, Cow::Owned(bytes)))
1262 })?;
1263 let bounds = Bounds {
1264 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
1265 size: tile.bounds.size.map(Into::into),
1266 };
1267 let content_mask = self.content_mask().scale(scale_factor);
1268 let view_id = self.parent_view_id();
1269 let window = &mut *self.window;
1270 window.next_frame.scene.insert(
1271 &window.next_frame.z_index_stack,
1272 MonochromeSprite {
1273 view_id: view_id.into(),
1274 layer_id: 0,
1275 order: 0,
1276 bounds,
1277 content_mask,
1278 color,
1279 tile,
1280 },
1281 );
1282 }
1283 Ok(())
1284 }
1285
1286 /// Paint an emoji glyph into the scene for the next frame at the current z-index.
1287 /// The y component of the origin is the baseline of the glyph.
1288 pub fn paint_emoji(
1289 &mut self,
1290 origin: Point<Pixels>,
1291 font_id: FontId,
1292 glyph_id: GlyphId,
1293 font_size: Pixels,
1294 ) -> Result<()> {
1295 let scale_factor = self.scale_factor();
1296 let glyph_origin = origin.scale(scale_factor);
1297 let params = RenderGlyphParams {
1298 font_id,
1299 glyph_id,
1300 font_size,
1301 // We don't render emojis with subpixel variants.
1302 subpixel_variant: Default::default(),
1303 scale_factor,
1304 is_emoji: true,
1305 };
1306
1307 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
1308 if !raster_bounds.is_zero() {
1309 let tile =
1310 self.window
1311 .sprite_atlas
1312 .get_or_insert_with(¶ms.clone().into(), &mut || {
1313 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
1314 Ok((size, Cow::Owned(bytes)))
1315 })?;
1316 let bounds = Bounds {
1317 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
1318 size: tile.bounds.size.map(Into::into),
1319 };
1320 let content_mask = self.content_mask().scale(scale_factor);
1321 let view_id = self.parent_view_id();
1322 let window = &mut *self.window;
1323
1324 window.next_frame.scene.insert(
1325 &window.next_frame.z_index_stack,
1326 PolychromeSprite {
1327 view_id: view_id.into(),
1328 layer_id: 0,
1329 order: 0,
1330 bounds,
1331 corner_radii: Default::default(),
1332 content_mask,
1333 tile,
1334 grayscale: false,
1335 },
1336 );
1337 }
1338 Ok(())
1339 }
1340
1341 /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
1342 pub fn paint_svg(
1343 &mut self,
1344 bounds: Bounds<Pixels>,
1345 path: SharedString,
1346 color: Hsla,
1347 ) -> Result<()> {
1348 let scale_factor = self.scale_factor();
1349 let bounds = bounds.scale(scale_factor);
1350 // Render the SVG at twice the size to get a higher quality result.
1351 let params = RenderSvgParams {
1352 path,
1353 size: bounds
1354 .size
1355 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
1356 };
1357
1358 let tile =
1359 self.window
1360 .sprite_atlas
1361 .get_or_insert_with(¶ms.clone().into(), &mut || {
1362 let bytes = self.svg_renderer.render(¶ms)?;
1363 Ok((params.size, Cow::Owned(bytes)))
1364 })?;
1365 let content_mask = self.content_mask().scale(scale_factor);
1366 let view_id = self.parent_view_id();
1367
1368 let window = &mut *self.window;
1369 window.next_frame.scene.insert(
1370 &window.next_frame.z_index_stack,
1371 MonochromeSprite {
1372 view_id: view_id.into(),
1373 layer_id: 0,
1374 order: 0,
1375 bounds,
1376 content_mask,
1377 color,
1378 tile,
1379 },
1380 );
1381
1382 Ok(())
1383 }
1384
1385 /// Paint an image into the scene for the next frame at the current z-index.
1386 pub fn paint_image(
1387 &mut self,
1388 bounds: Bounds<Pixels>,
1389 corner_radii: Corners<Pixels>,
1390 data: Arc<ImageData>,
1391 grayscale: bool,
1392 ) -> Result<()> {
1393 let scale_factor = self.scale_factor();
1394 let bounds = bounds.scale(scale_factor);
1395 let params = RenderImageParams { image_id: data.id };
1396
1397 let tile = self
1398 .window
1399 .sprite_atlas
1400 .get_or_insert_with(¶ms.clone().into(), &mut || {
1401 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
1402 })?;
1403 let content_mask = self.content_mask().scale(scale_factor);
1404 let corner_radii = corner_radii.scale(scale_factor);
1405 let view_id = self.parent_view_id();
1406
1407 let window = &mut *self.window;
1408 window.next_frame.scene.insert(
1409 &window.next_frame.z_index_stack,
1410 PolychromeSprite {
1411 view_id: view_id.into(),
1412 layer_id: 0,
1413 order: 0,
1414 bounds,
1415 content_mask,
1416 corner_radii,
1417 tile,
1418 grayscale,
1419 },
1420 );
1421 Ok(())
1422 }
1423
1424 /// Paint a surface into the scene for the next frame at the current z-index.
1425 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
1426 let scale_factor = self.scale_factor();
1427 let bounds = bounds.scale(scale_factor);
1428 let content_mask = self.content_mask().scale(scale_factor);
1429 let view_id = self.parent_view_id();
1430 let window = &mut *self.window;
1431 window.next_frame.scene.insert(
1432 &window.next_frame.z_index_stack,
1433 Surface {
1434 view_id: view_id.into(),
1435 layer_id: 0,
1436 order: 0,
1437 bounds,
1438 content_mask,
1439 image_buffer,
1440 },
1441 );
1442 }
1443
1444 pub(crate) fn reuse_view(&mut self) {
1445 let view_id = self.parent_view_id();
1446 let grafted_view_ids = self
1447 .window
1448 .next_frame
1449 .dispatch_tree
1450 .reuse_view(view_id, &mut self.window.rendered_frame.dispatch_tree);
1451 for view_id in grafted_view_ids {
1452 assert!(self.window.next_frame.reused_views.insert(view_id));
1453
1454 // Reuse the previous input handler requested during painting of the reused view.
1455 if self
1456 .window
1457 .rendered_frame
1458 .requested_input_handler
1459 .as_ref()
1460 .map_or(false, |requested| requested.view_id == view_id)
1461 {
1462 self.window.next_frame.requested_input_handler =
1463 self.window.rendered_frame.requested_input_handler.take();
1464 }
1465
1466 // Reuse the tooltip previously requested during painting of the reused view.
1467 if self
1468 .window
1469 .rendered_frame
1470 .tooltip_request
1471 .as_ref()
1472 .map_or(false, |requested| requested.view_id == view_id)
1473 {
1474 self.window.next_frame.tooltip_request =
1475 self.window.rendered_frame.tooltip_request.take();
1476 }
1477
1478 // Reuse the cursor styles previously requested during painting of the reused view.
1479 if let Some(style) = self.window.rendered_frame.cursor_styles.remove(&view_id) {
1480 self.window.next_frame.cursor_styles.insert(view_id, style);
1481 self.window.next_frame.requested_cursor_style = Some(style);
1482 }
1483 }
1484 }
1485
1486 /// Draw pixels to the display for this window based on the contents of its scene.
1487 pub(crate) fn draw(&mut self) {
1488 self.window.dirty = false;
1489 self.window.drawing = true;
1490
1491 #[cfg(any(test, feature = "test-support"))]
1492 {
1493 self.window.focus_invalidated = false;
1494 }
1495
1496 if let Some(requested_handler) = self.window.rendered_frame.requested_input_handler.as_mut()
1497 {
1498 requested_handler.handler = self.window.platform_window.take_input_handler();
1499 }
1500
1501 let root_view = self.window.root_view.take().unwrap();
1502
1503 self.with_z_index(0, |cx| {
1504 cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| {
1505 for (action_type, action_listeners) in &cx.app.global_action_listeners {
1506 for action_listener in action_listeners.iter().cloned() {
1507 cx.window.next_frame.dispatch_tree.on_action(
1508 *action_type,
1509 Rc::new(move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| {
1510 action_listener(action, phase, cx)
1511 }),
1512 )
1513 }
1514 }
1515
1516 let available_space = cx.window.viewport_size.map(Into::into);
1517 root_view.draw(Point::default(), available_space, cx);
1518 })
1519 });
1520
1521 if let Some(active_drag) = self.app.active_drag.take() {
1522 self.with_z_index(ACTIVE_DRAG_Z_INDEX, |cx| {
1523 let offset = cx.mouse_position() - active_drag.cursor_offset;
1524 let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
1525 active_drag.view.draw(offset, available_space, cx);
1526 });
1527 self.active_drag = Some(active_drag);
1528 } else if let Some(tooltip_request) = self.window.next_frame.tooltip_request.take() {
1529 self.with_z_index(1, |cx| {
1530 let available_space = size(AvailableSpace::MinContent, AvailableSpace::MinContent);
1531 tooltip_request.tooltip.view.draw(
1532 tooltip_request.tooltip.cursor_offset,
1533 available_space,
1534 cx,
1535 );
1536 });
1537 self.window.next_frame.tooltip_request = Some(tooltip_request);
1538 }
1539 self.window.dirty_views.clear();
1540
1541 self.window
1542 .next_frame
1543 .dispatch_tree
1544 .preserve_pending_keystrokes(
1545 &mut self.window.rendered_frame.dispatch_tree,
1546 self.window.focus,
1547 );
1548 self.window.next_frame.focus = self.window.focus;
1549 self.window.next_frame.window_active = self.window.active;
1550 self.window.root_view = Some(root_view);
1551
1552 // Set the cursor only if we're the active window.
1553 let cursor_style = self
1554 .window
1555 .next_frame
1556 .requested_cursor_style
1557 .take()
1558 .unwrap_or(CursorStyle::Arrow);
1559 if self.is_window_active() {
1560 self.platform.set_cursor_style(cursor_style);
1561 }
1562
1563 // Register requested input handler with the platform window.
1564 if let Some(requested_input) = self.window.next_frame.requested_input_handler.as_mut() {
1565 if let Some(handler) = requested_input.handler.take() {
1566 self.window.platform_window.set_input_handler(handler);
1567 }
1568 }
1569
1570 self.window.layout_engine.as_mut().unwrap().clear();
1571 self.text_system()
1572 .finish_frame(&self.window.next_frame.reused_views);
1573 self.window
1574 .next_frame
1575 .finish(&mut self.window.rendered_frame);
1576 ELEMENT_ARENA.with_borrow_mut(|element_arena| element_arena.clear());
1577
1578 let previous_focus_path = self.window.rendered_frame.focus_path();
1579 let previous_window_active = self.window.rendered_frame.window_active;
1580 mem::swap(&mut self.window.rendered_frame, &mut self.window.next_frame);
1581 self.window.next_frame.clear();
1582 let current_focus_path = self.window.rendered_frame.focus_path();
1583 let current_window_active = self.window.rendered_frame.window_active;
1584
1585 if previous_focus_path != current_focus_path
1586 || previous_window_active != current_window_active
1587 {
1588 if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
1589 self.window
1590 .focus_lost_listeners
1591 .clone()
1592 .retain(&(), |listener| listener(self));
1593 }
1594
1595 let event = FocusEvent {
1596 previous_focus_path: if previous_window_active {
1597 previous_focus_path
1598 } else {
1599 Default::default()
1600 },
1601 current_focus_path: if current_window_active {
1602 current_focus_path
1603 } else {
1604 Default::default()
1605 },
1606 };
1607 self.window
1608 .focus_listeners
1609 .clone()
1610 .retain(&(), |listener| listener(&event, self));
1611 }
1612
1613 self.window
1614 .platform_window
1615 .draw(&self.window.rendered_frame.scene);
1616 self.window.refreshing = false;
1617 self.window.drawing = false;
1618 }
1619
1620 /// Dispatch a mouse or keyboard event on the window.
1621 pub fn dispatch_event(&mut self, event: PlatformInput) -> bool {
1622 // Handlers may set this to false by calling `stop_propagation`.
1623 self.app.propagate_event = true;
1624 // Handlers may set this to true by calling `prevent_default`.
1625 self.window.default_prevented = false;
1626
1627 let event = match event {
1628 // Track the mouse position with our own state, since accessing the platform
1629 // API for the mouse position can only occur on the main thread.
1630 PlatformInput::MouseMove(mouse_move) => {
1631 self.window.mouse_position = mouse_move.position;
1632 self.window.modifiers = mouse_move.modifiers;
1633 PlatformInput::MouseMove(mouse_move)
1634 }
1635 PlatformInput::MouseDown(mouse_down) => {
1636 self.window.mouse_position = mouse_down.position;
1637 self.window.modifiers = mouse_down.modifiers;
1638 PlatformInput::MouseDown(mouse_down)
1639 }
1640 PlatformInput::MouseUp(mouse_up) => {
1641 self.window.mouse_position = mouse_up.position;
1642 self.window.modifiers = mouse_up.modifiers;
1643 PlatformInput::MouseUp(mouse_up)
1644 }
1645 PlatformInput::MouseExited(mouse_exited) => {
1646 self.window.modifiers = mouse_exited.modifiers;
1647 PlatformInput::MouseExited(mouse_exited)
1648 }
1649 PlatformInput::ModifiersChanged(modifiers_changed) => {
1650 self.window.modifiers = modifiers_changed.modifiers;
1651 PlatformInput::ModifiersChanged(modifiers_changed)
1652 }
1653 PlatformInput::ScrollWheel(scroll_wheel) => {
1654 self.window.mouse_position = scroll_wheel.position;
1655 self.window.modifiers = scroll_wheel.modifiers;
1656 PlatformInput::ScrollWheel(scroll_wheel)
1657 }
1658 // Translate dragging and dropping of external files from the operating system
1659 // to internal drag and drop events.
1660 PlatformInput::FileDrop(file_drop) => match file_drop {
1661 FileDropEvent::Entered { position, paths } => {
1662 self.window.mouse_position = position;
1663 if self.active_drag.is_none() {
1664 self.active_drag = Some(AnyDrag {
1665 value: Box::new(paths.clone()),
1666 view: self.new_view(|_| paths).into(),
1667 cursor_offset: position,
1668 });
1669 }
1670 PlatformInput::MouseMove(MouseMoveEvent {
1671 position,
1672 pressed_button: Some(MouseButton::Left),
1673 modifiers: Modifiers::default(),
1674 })
1675 }
1676 FileDropEvent::Pending { position } => {
1677 self.window.mouse_position = position;
1678 PlatformInput::MouseMove(MouseMoveEvent {
1679 position,
1680 pressed_button: Some(MouseButton::Left),
1681 modifiers: Modifiers::default(),
1682 })
1683 }
1684 FileDropEvent::Submit { position } => {
1685 self.activate(true);
1686 self.window.mouse_position = position;
1687 PlatformInput::MouseUp(MouseUpEvent {
1688 button: MouseButton::Left,
1689 position,
1690 modifiers: Modifiers::default(),
1691 click_count: 1,
1692 })
1693 }
1694 FileDropEvent::Exited => PlatformInput::MouseUp(MouseUpEvent {
1695 button: MouseButton::Left,
1696 position: Point::default(),
1697 modifiers: Modifiers::default(),
1698 click_count: 1,
1699 }),
1700 },
1701 PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
1702 };
1703
1704 if let Some(any_mouse_event) = event.mouse_event() {
1705 self.dispatch_mouse_event(any_mouse_event);
1706 } else if let Some(any_key_event) = event.keyboard_event() {
1707 self.dispatch_key_event(any_key_event);
1708 }
1709
1710 !self.app.propagate_event
1711 }
1712
1713 fn dispatch_mouse_event(&mut self, event: &dyn Any) {
1714 if let Some(mut handlers) = self
1715 .window
1716 .rendered_frame
1717 .mouse_listeners
1718 .remove(&event.type_id())
1719 {
1720 // Because handlers may add other handlers, we sort every time.
1721 handlers.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
1722
1723 // Capture phase, events bubble from back to front. Handlers for this phase are used for
1724 // special purposes, such as detecting events outside of a given Bounds.
1725 for (_, _, handler) in &mut handlers {
1726 handler(event, DispatchPhase::Capture, self);
1727 if !self.app.propagate_event {
1728 break;
1729 }
1730 }
1731
1732 // Bubble phase, where most normal handlers do their work.
1733 if self.app.propagate_event {
1734 for (_, _, handler) in handlers.iter_mut().rev() {
1735 handler(event, DispatchPhase::Bubble, self);
1736 if !self.app.propagate_event {
1737 break;
1738 }
1739 }
1740 }
1741
1742 self.window
1743 .rendered_frame
1744 .mouse_listeners
1745 .insert(event.type_id(), handlers);
1746 }
1747
1748 if self.app.propagate_event && self.has_active_drag() {
1749 if event.is::<MouseMoveEvent>() {
1750 // If this was a mouse move event, redraw the window so that the
1751 // active drag can follow the mouse cursor.
1752 self.refresh();
1753 } else if event.is::<MouseUpEvent>() {
1754 // If this was a mouse up event, cancel the active drag and redraw
1755 // the window.
1756 self.active_drag = None;
1757 self.refresh();
1758 }
1759 }
1760 }
1761
1762 fn dispatch_key_event(&mut self, event: &dyn Any) {
1763 let node_id = self
1764 .window
1765 .focus
1766 .and_then(|focus_id| {
1767 self.window
1768 .rendered_frame
1769 .dispatch_tree
1770 .focusable_node_id(focus_id)
1771 })
1772 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
1773
1774 let dispatch_path = self
1775 .window
1776 .rendered_frame
1777 .dispatch_tree
1778 .dispatch_path(node_id);
1779
1780 let mut actions: Vec<Box<dyn Action>> = Vec::new();
1781
1782 let mut context_stack: SmallVec<[KeyContext; 16]> = SmallVec::new();
1783 for node_id in &dispatch_path {
1784 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1785
1786 if let Some(context) = node.context.clone() {
1787 context_stack.push(context);
1788 }
1789 }
1790
1791 for node_id in dispatch_path.iter().rev() {
1792 // Match keystrokes
1793 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1794 if node.context.is_some() {
1795 if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
1796 let mut new_actions = self
1797 .window
1798 .rendered_frame
1799 .dispatch_tree
1800 .dispatch_key(&key_down_event.keystroke, &context_stack);
1801 actions.append(&mut new_actions);
1802 }
1803
1804 context_stack.pop();
1805 }
1806 }
1807
1808 if !actions.is_empty() {
1809 self.clear_pending_keystrokes();
1810 }
1811
1812 self.propagate_event = true;
1813 for action in actions {
1814 self.dispatch_action_on_node(node_id, action.boxed_clone());
1815 if !self.propagate_event {
1816 self.dispatch_keystroke_observers(event, Some(action));
1817 return;
1818 }
1819 }
1820
1821 // Capture phase
1822 for node_id in &dispatch_path {
1823 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1824
1825 for key_listener in node.key_listeners.clone() {
1826 key_listener(event, DispatchPhase::Capture, self);
1827 if !self.propagate_event {
1828 return;
1829 }
1830 }
1831 }
1832
1833 // Bubble phase
1834 for node_id in dispatch_path.iter().rev() {
1835 // Handle low level key events
1836 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1837 for key_listener in node.key_listeners.clone() {
1838 key_listener(event, DispatchPhase::Bubble, self);
1839 if !self.propagate_event {
1840 return;
1841 }
1842 }
1843 }
1844
1845 self.dispatch_keystroke_observers(event, None);
1846 }
1847
1848 /// Determine whether a potential multi-stroke key binding is in progress on this window.
1849 pub fn has_pending_keystrokes(&self) -> bool {
1850 self.window
1851 .rendered_frame
1852 .dispatch_tree
1853 .has_pending_keystrokes()
1854 }
1855
1856 fn dispatch_action_on_node(&mut self, node_id: DispatchNodeId, action: Box<dyn Action>) {
1857 let dispatch_path = self
1858 .window
1859 .rendered_frame
1860 .dispatch_tree
1861 .dispatch_path(node_id);
1862
1863 // Capture phase
1864 for node_id in &dispatch_path {
1865 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1866 for DispatchActionListener {
1867 action_type,
1868 listener,
1869 } in node.action_listeners.clone()
1870 {
1871 let any_action = action.as_any();
1872 if action_type == any_action.type_id() {
1873 listener(any_action, DispatchPhase::Capture, self);
1874 if !self.propagate_event {
1875 return;
1876 }
1877 }
1878 }
1879 }
1880 // Bubble phase
1881 for node_id in dispatch_path.iter().rev() {
1882 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1883 for DispatchActionListener {
1884 action_type,
1885 listener,
1886 } in node.action_listeners.clone()
1887 {
1888 let any_action = action.as_any();
1889 if action_type == any_action.type_id() {
1890 self.propagate_event = false; // Actions stop propagation by default during the bubble phase
1891 listener(any_action, DispatchPhase::Bubble, self);
1892 if !self.propagate_event {
1893 return;
1894 }
1895 }
1896 }
1897 }
1898 }
1899
1900 /// Register the given handler to be invoked whenever the global of the given type
1901 /// is updated.
1902 pub fn observe_global<G: 'static>(
1903 &mut self,
1904 f: impl Fn(&mut WindowContext<'_>) + 'static,
1905 ) -> Subscription {
1906 let window_handle = self.window.handle;
1907 let (subscription, activate) = self.global_observers.insert(
1908 TypeId::of::<G>(),
1909 Box::new(move |cx| window_handle.update(cx, |_, cx| f(cx)).is_ok()),
1910 );
1911 self.app.defer(move |_| activate());
1912 subscription
1913 }
1914
1915 /// Focus the current window and bring it to the foreground at the platform level.
1916 pub fn activate_window(&self) {
1917 self.window.platform_window.activate();
1918 }
1919
1920 /// Minimize the current window at the platform level.
1921 pub fn minimize_window(&self) {
1922 self.window.platform_window.minimize();
1923 }
1924
1925 /// Toggle full screen status on the current window at the platform level.
1926 pub fn toggle_full_screen(&self) {
1927 self.window.platform_window.toggle_full_screen();
1928 }
1929
1930 /// Present a platform dialog.
1931 /// The provided message will be presented, along with buttons for each answer.
1932 /// When a button is clicked, the returned Receiver will receive the index of the clicked button.
1933 pub fn prompt(
1934 &self,
1935 level: PromptLevel,
1936 message: &str,
1937 answers: &[&str],
1938 ) -> oneshot::Receiver<usize> {
1939 self.window.platform_window.prompt(level, message, answers)
1940 }
1941
1942 /// Returns all available actions for the focused element.
1943 pub fn available_actions(&self) -> Vec<Box<dyn Action>> {
1944 let node_id = self
1945 .window
1946 .focus
1947 .and_then(|focus_id| {
1948 self.window
1949 .rendered_frame
1950 .dispatch_tree
1951 .focusable_node_id(focus_id)
1952 })
1953 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
1954
1955 self.window
1956 .rendered_frame
1957 .dispatch_tree
1958 .available_actions(node_id)
1959 }
1960
1961 /// Returns key bindings that invoke the given action on the currently focused element.
1962 pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
1963 self.window
1964 .rendered_frame
1965 .dispatch_tree
1966 .bindings_for_action(
1967 action,
1968 &self.window.rendered_frame.dispatch_tree.context_stack,
1969 )
1970 }
1971
1972 /// Returns any bindings that would invoke the given action on the given focus handle if it were focused.
1973 pub fn bindings_for_action_in(
1974 &self,
1975 action: &dyn Action,
1976 focus_handle: &FocusHandle,
1977 ) -> Vec<KeyBinding> {
1978 let dispatch_tree = &self.window.rendered_frame.dispatch_tree;
1979
1980 let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {
1981 return vec![];
1982 };
1983 let context_stack = dispatch_tree
1984 .dispatch_path(node_id)
1985 .into_iter()
1986 .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
1987 .collect();
1988 dispatch_tree.bindings_for_action(action, &context_stack)
1989 }
1990
1991 /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.
1992 pub fn listener_for<V: Render, E>(
1993 &self,
1994 view: &View<V>,
1995 f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
1996 ) -> impl Fn(&E, &mut WindowContext) + 'static {
1997 let view = view.downgrade();
1998 move |e: &E, cx: &mut WindowContext| {
1999 view.update(cx, |view, cx| f(view, e, cx)).ok();
2000 }
2001 }
2002
2003 /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.
2004 pub fn handler_for<V: Render>(
2005 &self,
2006 view: &View<V>,
2007 f: impl Fn(&mut V, &mut ViewContext<V>) + 'static,
2008 ) -> impl Fn(&mut WindowContext) {
2009 let view = view.downgrade();
2010 move |cx: &mut WindowContext| {
2011 view.update(cx, |view, cx| f(view, cx)).ok();
2012 }
2013 }
2014
2015 /// Invoke the given function with the given focus handle present on the key dispatch stack.
2016 /// If you want an element to participate in key dispatch, use this method to push its key context and focus handle into the stack during paint.
2017 pub fn with_key_dispatch<R>(
2018 &mut self,
2019 context: Option<KeyContext>,
2020 focus_handle: Option<FocusHandle>,
2021 f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
2022 ) -> R {
2023 let window = &mut self.window;
2024 let focus_id = focus_handle.as_ref().map(|handle| handle.id);
2025 window
2026 .next_frame
2027 .dispatch_tree
2028 .push_node(context.clone(), focus_id, None);
2029
2030 let result = f(focus_handle, self);
2031
2032 self.window.next_frame.dispatch_tree.pop_node();
2033
2034 result
2035 }
2036
2037 /// Invoke the given function with the given view id present on the view stack.
2038 /// This is a fairly low-level method used to layout views.
2039 pub fn with_view_id<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
2040 let text_system = self.text_system().clone();
2041 text_system.with_view(view_id, || {
2042 if self.window.next_frame.view_stack.last() == Some(&view_id) {
2043 return f(self);
2044 } else {
2045 self.window.next_frame.view_stack.push(view_id);
2046 let result = f(self);
2047 self.window.next_frame.view_stack.pop();
2048 result
2049 }
2050 })
2051 }
2052
2053 /// Invoke the given function with the given view id present on the view stack.
2054 /// This is a fairly low-level method used to paint views.
2055 pub fn paint_view<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
2056 let text_system = self.text_system().clone();
2057 text_system.with_view(view_id, || {
2058 if self.window.next_frame.view_stack.last() == Some(&view_id) {
2059 return f(self);
2060 } else {
2061 self.window.next_frame.view_stack.push(view_id);
2062 self.window
2063 .next_frame
2064 .dispatch_tree
2065 .push_node(None, None, Some(view_id));
2066 let result = f(self);
2067 self.window.next_frame.dispatch_tree.pop_node();
2068 self.window.next_frame.view_stack.pop();
2069 result
2070 }
2071 })
2072 }
2073
2074 /// Update or initialize state for an element with the given id that lives across multiple
2075 /// frames. If an element with this id existed in the rendered frame, its state will be passed
2076 /// to the given closure. The state returned by the closure will be stored so it can be referenced
2077 /// when drawing the next frame.
2078 pub(crate) fn with_element_state<S, R>(
2079 &mut self,
2080 id: ElementId,
2081 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
2082 ) -> R
2083 where
2084 S: 'static,
2085 {
2086 self.with_element_id(Some(id), |cx| {
2087 let global_id = cx.window().element_id_stack.clone();
2088
2089 if let Some(any) = cx
2090 .window_mut()
2091 .next_frame
2092 .element_states
2093 .remove(&global_id)
2094 .or_else(|| {
2095 cx.window_mut()
2096 .rendered_frame
2097 .element_states
2098 .remove(&global_id)
2099 })
2100 {
2101 let ElementStateBox {
2102 inner,
2103 parent_view_id,
2104 #[cfg(debug_assertions)]
2105 type_name
2106 } = any;
2107 // Using the extra inner option to avoid needing to reallocate a new box.
2108 let mut state_box = inner
2109 .downcast::<Option<S>>()
2110 .map_err(|_| {
2111 #[cfg(debug_assertions)]
2112 {
2113 anyhow!(
2114 "invalid element state type for id, requested_type {:?}, actual type: {:?}",
2115 std::any::type_name::<S>(),
2116 type_name
2117 )
2118 }
2119
2120 #[cfg(not(debug_assertions))]
2121 {
2122 anyhow!(
2123 "invalid element state type for id, requested_type {:?}",
2124 std::any::type_name::<S>(),
2125 )
2126 }
2127 })
2128 .unwrap();
2129
2130 // Actual: Option<AnyElement> <- View
2131 // Requested: () <- AnyElement
2132 let state = state_box
2133 .take()
2134 .expect("element state is already on the stack");
2135 let (result, state) = f(Some(state), cx);
2136 state_box.replace(state);
2137 cx.window_mut()
2138 .next_frame
2139 .element_states
2140 .insert(global_id, ElementStateBox {
2141 inner: state_box,
2142 parent_view_id,
2143 #[cfg(debug_assertions)]
2144 type_name
2145 });
2146 result
2147 } else {
2148 let (result, state) = f(None, cx);
2149 let parent_view_id = cx.parent_view_id();
2150 cx.window_mut()
2151 .next_frame
2152 .element_states
2153 .insert(global_id,
2154 ElementStateBox {
2155 inner: Box::new(Some(state)),
2156 parent_view_id,
2157 #[cfg(debug_assertions)]
2158 type_name: std::any::type_name::<S>()
2159 }
2160
2161 );
2162 result
2163 }
2164 })
2165 }
2166
2167 fn parent_view_id(&self) -> EntityId {
2168 *self
2169 .window
2170 .next_frame
2171 .view_stack
2172 .last()
2173 .expect("a view should always be on the stack while drawing")
2174 }
2175
2176 /// Set an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
2177 /// platform to receive textual input with proper integration with concerns such
2178 /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
2179 /// rendered.
2180 ///
2181 /// [element_input_handler]: crate::ElementInputHandler
2182 pub fn handle_input(
2183 &mut self,
2184 focus_handle: &FocusHandle,
2185 input_handler: impl PlatformInputHandler,
2186 ) {
2187 if focus_handle.is_focused(self) {
2188 let view_id = self.parent_view_id();
2189 self.window.next_frame.requested_input_handler = Some(RequestedInputHandler {
2190 view_id,
2191 handler: Some(Box::new(input_handler)),
2192 })
2193 }
2194 }
2195
2196 /// Register a callback that can interrupt the closing of the current window based the returned boolean.
2197 /// If the callback returns false, the window won't be closed.
2198 pub fn on_window_should_close(&mut self, f: impl Fn(&mut WindowContext) -> bool + 'static) {
2199 let mut this = self.to_async();
2200 self.window
2201 .platform_window
2202 .on_should_close(Box::new(move || {
2203 this.update(|_, cx| {
2204 // Ensure that the window is removed from the app if it's been closed
2205 // by always pre-empting the system close event.
2206 if f(cx) {
2207 cx.remove_window();
2208 }
2209 false
2210 })
2211 .unwrap_or(true)
2212 }))
2213 }
2214}
2215
2216impl Context for WindowContext<'_> {
2217 type Result<T> = T;
2218
2219 fn new_model<T>(&mut self, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T) -> Model<T>
2220 where
2221 T: 'static,
2222 {
2223 let slot = self.app.entities.reserve();
2224 let model = build_model(&mut ModelContext::new(&mut *self.app, slot.downgrade()));
2225 self.entities.insert(slot, model)
2226 }
2227
2228 fn update_model<T: 'static, R>(
2229 &mut self,
2230 model: &Model<T>,
2231 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
2232 ) -> R {
2233 let mut entity = self.entities.lease(model);
2234 let result = update(
2235 &mut *entity,
2236 &mut ModelContext::new(&mut *self.app, model.downgrade()),
2237 );
2238 self.entities.end_lease(entity);
2239 result
2240 }
2241
2242 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
2243 where
2244 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
2245 {
2246 if window == self.window.handle {
2247 let root_view = self.window.root_view.clone().unwrap();
2248 Ok(update(root_view, self))
2249 } else {
2250 window.update(self.app, update)
2251 }
2252 }
2253
2254 fn read_model<T, R>(
2255 &self,
2256 handle: &Model<T>,
2257 read: impl FnOnce(&T, &AppContext) -> R,
2258 ) -> Self::Result<R>
2259 where
2260 T: 'static,
2261 {
2262 let entity = self.entities.read(handle);
2263 read(entity, &*self.app)
2264 }
2265
2266 fn read_window<T, R>(
2267 &self,
2268 window: &WindowHandle<T>,
2269 read: impl FnOnce(View<T>, &AppContext) -> R,
2270 ) -> Result<R>
2271 where
2272 T: 'static,
2273 {
2274 if window.any_handle == self.window.handle {
2275 let root_view = self
2276 .window
2277 .root_view
2278 .clone()
2279 .unwrap()
2280 .downcast::<T>()
2281 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
2282 Ok(read(root_view, self))
2283 } else {
2284 self.app.read_window(window, read)
2285 }
2286 }
2287}
2288
2289impl VisualContext for WindowContext<'_> {
2290 fn new_view<V>(
2291 &mut self,
2292 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
2293 ) -> Self::Result<View<V>>
2294 where
2295 V: 'static + Render,
2296 {
2297 let slot = self.app.entities.reserve();
2298 let view = View {
2299 model: slot.clone(),
2300 };
2301 let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, &view);
2302 let entity = build_view_state(&mut cx);
2303 cx.entities.insert(slot, entity);
2304
2305 cx.new_view_observers
2306 .clone()
2307 .retain(&TypeId::of::<V>(), |observer| {
2308 let any_view = AnyView::from(view.clone());
2309 (observer)(any_view, self);
2310 true
2311 });
2312
2313 view
2314 }
2315
2316 /// Update the given view. Prefer calling `View::update` instead, which calls this method.
2317 fn update_view<T: 'static, R>(
2318 &mut self,
2319 view: &View<T>,
2320 update: impl FnOnce(&mut T, &mut ViewContext<'_, T>) -> R,
2321 ) -> Self::Result<R> {
2322 let mut lease = self.app.entities.lease(&view.model);
2323 let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, view);
2324 let result = update(&mut *lease, &mut cx);
2325 cx.app.entities.end_lease(lease);
2326 result
2327 }
2328
2329 fn replace_root_view<V>(
2330 &mut self,
2331 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
2332 ) -> Self::Result<View<V>>
2333 where
2334 V: 'static + Render,
2335 {
2336 let view = self.new_view(build_view);
2337 self.window.root_view = Some(view.clone().into());
2338 self.refresh();
2339 view
2340 }
2341
2342 fn focus_view<V: crate::FocusableView>(&mut self, view: &View<V>) -> Self::Result<()> {
2343 self.update_view(view, |view, cx| {
2344 view.focus_handle(cx).clone().focus(cx);
2345 })
2346 }
2347
2348 fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
2349 where
2350 V: ManagedView,
2351 {
2352 self.update_view(view, |_, cx| cx.emit(DismissEvent))
2353 }
2354}
2355
2356impl<'a> std::ops::Deref for WindowContext<'a> {
2357 type Target = AppContext;
2358
2359 fn deref(&self) -> &Self::Target {
2360 self.app
2361 }
2362}
2363
2364impl<'a> std::ops::DerefMut for WindowContext<'a> {
2365 fn deref_mut(&mut self) -> &mut Self::Target {
2366 self.app
2367 }
2368}
2369
2370impl<'a> Borrow<AppContext> for WindowContext<'a> {
2371 fn borrow(&self) -> &AppContext {
2372 self.app
2373 }
2374}
2375
2376impl<'a> BorrowMut<AppContext> for WindowContext<'a> {
2377 fn borrow_mut(&mut self) -> &mut AppContext {
2378 self.app
2379 }
2380}
2381
2382/// This trait contains functionality that is shared across [`ViewContext`] and [`WindowContext`]
2383pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
2384 #[doc(hidden)]
2385 fn app_mut(&mut self) -> &mut AppContext {
2386 self.borrow_mut()
2387 }
2388
2389 #[doc(hidden)]
2390 fn app(&self) -> &AppContext {
2391 self.borrow()
2392 }
2393
2394 #[doc(hidden)]
2395 fn window(&self) -> &Window {
2396 self.borrow()
2397 }
2398
2399 #[doc(hidden)]
2400 fn window_mut(&mut self) -> &mut Window {
2401 self.borrow_mut()
2402 }
2403
2404 /// Pushes the given element id onto the global stack and invokes the given closure
2405 /// with a `GlobalElementId`, which disambiguates the given id in the context of its ancestor
2406 /// ids. Because elements are discarded and recreated on each frame, the `GlobalElementId` is
2407 /// used to associate state with identified elements across separate frames.
2408 fn with_element_id<R>(
2409 &mut self,
2410 id: Option<impl Into<ElementId>>,
2411 f: impl FnOnce(&mut Self) -> R,
2412 ) -> R {
2413 if let Some(id) = id.map(Into::into) {
2414 let window = self.window_mut();
2415 window.element_id_stack.push(id);
2416 let result = f(self);
2417 let window: &mut Window = self.borrow_mut();
2418 window.element_id_stack.pop();
2419 result
2420 } else {
2421 f(self)
2422 }
2423 }
2424
2425 /// Invoke the given function with the given content mask after intersecting it
2426 /// with the current mask.
2427 fn with_content_mask<R>(
2428 &mut self,
2429 mask: Option<ContentMask<Pixels>>,
2430 f: impl FnOnce(&mut Self) -> R,
2431 ) -> R {
2432 if let Some(mask) = mask {
2433 let mask = mask.intersect(&self.content_mask());
2434 self.window_mut().next_frame.content_mask_stack.push(mask);
2435 let result = f(self);
2436 self.window_mut().next_frame.content_mask_stack.pop();
2437 result
2438 } else {
2439 f(self)
2440 }
2441 }
2442
2443 /// Invoke the given function with the content mask reset to that
2444 /// of the window.
2445 fn break_content_mask<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
2446 let mask = ContentMask {
2447 bounds: Bounds {
2448 origin: Point::default(),
2449 size: self.window().viewport_size,
2450 },
2451 };
2452
2453 let new_root_z_index = post_inc(&mut self.window_mut().next_frame.next_root_z_index);
2454 let new_stacking_order_id =
2455 post_inc(&mut self.window_mut().next_frame.next_stacking_order_id);
2456 let new_context = StackingContext {
2457 z_index: new_root_z_index,
2458 id: new_stacking_order_id,
2459 };
2460
2461 let old_stacking_order = mem::take(&mut self.window_mut().next_frame.z_index_stack);
2462
2463 self.window_mut().next_frame.z_index_stack.push(new_context);
2464 self.window_mut().next_frame.content_mask_stack.push(mask);
2465 let result = f(self);
2466 self.window_mut().next_frame.content_mask_stack.pop();
2467 self.window_mut().next_frame.z_index_stack = old_stacking_order;
2468
2469 result
2470 }
2471
2472 /// Called during painting to invoke the given closure in a new stacking context. The given
2473 /// z-index is interpreted relative to the previous call to `stack`.
2474 fn with_z_index<R>(&mut self, z_index: u16, f: impl FnOnce(&mut Self) -> R) -> R {
2475 let new_stacking_order_id =
2476 post_inc(&mut self.window_mut().next_frame.next_stacking_order_id);
2477 let new_context = StackingContext {
2478 z_index,
2479 id: new_stacking_order_id,
2480 };
2481
2482 self.window_mut().next_frame.z_index_stack.push(new_context);
2483 let result = f(self);
2484 self.window_mut().next_frame.z_index_stack.pop();
2485
2486 result
2487 }
2488
2489 /// Update the global element offset relative to the current offset. This is used to implement
2490 /// scrolling.
2491 fn with_element_offset<R>(
2492 &mut self,
2493 offset: Point<Pixels>,
2494 f: impl FnOnce(&mut Self) -> R,
2495 ) -> R {
2496 if offset.is_zero() {
2497 return f(self);
2498 };
2499
2500 let abs_offset = self.element_offset() + offset;
2501 self.with_absolute_element_offset(abs_offset, f)
2502 }
2503
2504 /// Update the global element offset based on the given offset. This is used to implement
2505 /// drag handles and other manual painting of elements.
2506 fn with_absolute_element_offset<R>(
2507 &mut self,
2508 offset: Point<Pixels>,
2509 f: impl FnOnce(&mut Self) -> R,
2510 ) -> R {
2511 self.window_mut()
2512 .next_frame
2513 .element_offset_stack
2514 .push(offset);
2515 let result = f(self);
2516 self.window_mut().next_frame.element_offset_stack.pop();
2517 result
2518 }
2519
2520 /// Obtain the current element offset.
2521 fn element_offset(&self) -> Point<Pixels> {
2522 self.window()
2523 .next_frame
2524 .element_offset_stack
2525 .last()
2526 .copied()
2527 .unwrap_or_default()
2528 }
2529
2530 /// Obtain the current content mask.
2531 fn content_mask(&self) -> ContentMask<Pixels> {
2532 self.window()
2533 .next_frame
2534 .content_mask_stack
2535 .last()
2536 .cloned()
2537 .unwrap_or_else(|| ContentMask {
2538 bounds: Bounds {
2539 origin: Point::default(),
2540 size: self.window().viewport_size,
2541 },
2542 })
2543 }
2544
2545 /// The size of an em for the base font of the application. Adjusting this value allows the
2546 /// UI to scale, just like zooming a web page.
2547 fn rem_size(&self) -> Pixels {
2548 self.window().rem_size
2549 }
2550}
2551
2552impl Borrow<Window> for WindowContext<'_> {
2553 fn borrow(&self) -> &Window {
2554 self.window
2555 }
2556}
2557
2558impl BorrowMut<Window> for WindowContext<'_> {
2559 fn borrow_mut(&mut self) -> &mut Window {
2560 self.window
2561 }
2562}
2563
2564impl<T> BorrowWindow for T where T: BorrowMut<AppContext> + BorrowMut<Window> {}
2565
2566/// Provides access to application state that is specialized for a particular [`View`].
2567/// Allows you to interact with focus, emit events, etc.
2568/// ViewContext also derefs to [`WindowContext`], giving you access to all of its methods as well.
2569/// When you call [`View::update`], you're passed a `&mut V` and an `&mut ViewContext<V>`.
2570pub struct ViewContext<'a, V> {
2571 window_cx: WindowContext<'a>,
2572 view: &'a View<V>,
2573}
2574
2575impl<V> Borrow<AppContext> for ViewContext<'_, V> {
2576 fn borrow(&self) -> &AppContext {
2577 &*self.window_cx.app
2578 }
2579}
2580
2581impl<V> BorrowMut<AppContext> for ViewContext<'_, V> {
2582 fn borrow_mut(&mut self) -> &mut AppContext {
2583 &mut *self.window_cx.app
2584 }
2585}
2586
2587impl<V> Borrow<Window> for ViewContext<'_, V> {
2588 fn borrow(&self) -> &Window {
2589 &*self.window_cx.window
2590 }
2591}
2592
2593impl<V> BorrowMut<Window> for ViewContext<'_, V> {
2594 fn borrow_mut(&mut self) -> &mut Window {
2595 &mut *self.window_cx.window
2596 }
2597}
2598
2599impl<'a, V: 'static> ViewContext<'a, V> {
2600 pub(crate) fn new(app: &'a mut AppContext, window: &'a mut Window, view: &'a View<V>) -> Self {
2601 Self {
2602 window_cx: WindowContext::new(app, window),
2603 view,
2604 }
2605 }
2606
2607 /// Get the entity_id of this view.
2608 pub fn entity_id(&self) -> EntityId {
2609 self.view.entity_id()
2610 }
2611
2612 /// Get the view pointer underlying this context.
2613 pub fn view(&self) -> &View<V> {
2614 self.view
2615 }
2616
2617 /// Get the model underlying this view.
2618 pub fn model(&self) -> &Model<V> {
2619 &self.view.model
2620 }
2621
2622 /// Access the underlying window context.
2623 pub fn window_context(&mut self) -> &mut WindowContext<'a> {
2624 &mut self.window_cx
2625 }
2626
2627 /// Set a given callback to be run on the next frame.
2628 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut V, &mut ViewContext<V>) + 'static)
2629 where
2630 V: 'static,
2631 {
2632 let view = self.view().clone();
2633 self.window_cx.on_next_frame(move |cx| view.update(cx, f));
2634 }
2635
2636 /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
2637 /// that are currently on the stack to be returned to the app.
2638 pub fn defer(&mut self, f: impl FnOnce(&mut V, &mut ViewContext<V>) + 'static) {
2639 let view = self.view().downgrade();
2640 self.window_cx.defer(move |cx| {
2641 view.update(cx, f).ok();
2642 });
2643 }
2644
2645 /// Observe another model or view for changes to its state, as tracked by [`ModelContext::notify`].
2646 pub fn observe<V2, E>(
2647 &mut self,
2648 entity: &E,
2649 mut on_notify: impl FnMut(&mut V, E, &mut ViewContext<'_, V>) + 'static,
2650 ) -> Subscription
2651 where
2652 V2: 'static,
2653 V: 'static,
2654 E: Entity<V2>,
2655 {
2656 let view = self.view().downgrade();
2657 let entity_id = entity.entity_id();
2658 let entity = entity.downgrade();
2659 let window_handle = self.window.handle;
2660 let (subscription, activate) = self.app.observers.insert(
2661 entity_id,
2662 Box::new(move |cx| {
2663 window_handle
2664 .update(cx, |_, cx| {
2665 if let Some(handle) = E::upgrade_from(&entity) {
2666 view.update(cx, |this, cx| on_notify(this, handle, cx))
2667 .is_ok()
2668 } else {
2669 false
2670 }
2671 })
2672 .unwrap_or(false)
2673 }),
2674 );
2675 self.app.defer(move |_| activate());
2676 subscription
2677 }
2678
2679 /// Subscribe to events emitted by another model or view.
2680 /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
2681 /// The callback will be invoked with a reference to the current view, a handle to the emitting entity (either a [`View`] or [`Model`]), the event, and a view context for the current view.
2682 pub fn subscribe<V2, E, Evt>(
2683 &mut self,
2684 entity: &E,
2685 mut on_event: impl FnMut(&mut V, E, &Evt, &mut ViewContext<'_, V>) + 'static,
2686 ) -> Subscription
2687 where
2688 V2: EventEmitter<Evt>,
2689 E: Entity<V2>,
2690 Evt: 'static,
2691 {
2692 let view = self.view().downgrade();
2693 let entity_id = entity.entity_id();
2694 let handle = entity.downgrade();
2695 let window_handle = self.window.handle;
2696 let (subscription, activate) = self.app.event_listeners.insert(
2697 entity_id,
2698 (
2699 TypeId::of::<Evt>(),
2700 Box::new(move |event, cx| {
2701 window_handle
2702 .update(cx, |_, cx| {
2703 if let Some(handle) = E::upgrade_from(&handle) {
2704 let event = event.downcast_ref().expect("invalid event type");
2705 view.update(cx, |this, cx| on_event(this, handle, event, cx))
2706 .is_ok()
2707 } else {
2708 false
2709 }
2710 })
2711 .unwrap_or(false)
2712 }),
2713 ),
2714 );
2715 self.app.defer(move |_| activate());
2716 subscription
2717 }
2718
2719 /// Register a callback to be invoked when the view is released.
2720 ///
2721 /// The callback receives a handle to the view's window. This handle may be
2722 /// invalid, if the window was closed before the view was released.
2723 pub fn on_release(
2724 &mut self,
2725 on_release: impl FnOnce(&mut V, AnyWindowHandle, &mut AppContext) + 'static,
2726 ) -> Subscription {
2727 let window_handle = self.window.handle;
2728 let (subscription, activate) = self.app.release_listeners.insert(
2729 self.view.model.entity_id,
2730 Box::new(move |this, cx| {
2731 let this = this.downcast_mut().expect("invalid entity type");
2732 on_release(this, window_handle, cx)
2733 }),
2734 );
2735 activate();
2736 subscription
2737 }
2738
2739 /// Register a callback to be invoked when the given Model or View is released.
2740 pub fn observe_release<V2, E>(
2741 &mut self,
2742 entity: &E,
2743 mut on_release: impl FnMut(&mut V, &mut V2, &mut ViewContext<'_, V>) + 'static,
2744 ) -> Subscription
2745 where
2746 V: 'static,
2747 V2: 'static,
2748 E: Entity<V2>,
2749 {
2750 let view = self.view().downgrade();
2751 let entity_id = entity.entity_id();
2752 let window_handle = self.window.handle;
2753 let (subscription, activate) = self.app.release_listeners.insert(
2754 entity_id,
2755 Box::new(move |entity, cx| {
2756 let entity = entity.downcast_mut().expect("invalid entity type");
2757 let _ = window_handle.update(cx, |_, cx| {
2758 view.update(cx, |this, cx| on_release(this, entity, cx))
2759 });
2760 }),
2761 );
2762 activate();
2763 subscription
2764 }
2765
2766 /// Indicate that this view has changed, which will invoke any observers and also mark the window as dirty.
2767 /// If this view or any of its ancestors are *cached*, notifying it will cause it or its ancestors to be redrawn.
2768 pub fn notify(&mut self) {
2769 for view_id in self
2770 .window
2771 .rendered_frame
2772 .dispatch_tree
2773 .view_path(self.view.entity_id())
2774 .into_iter()
2775 .rev()
2776 {
2777 if !self.window.dirty_views.insert(view_id) {
2778 break;
2779 }
2780 }
2781
2782 if !self.window.drawing {
2783 self.window_cx.window.dirty = true;
2784 self.window_cx.app.push_effect(Effect::Notify {
2785 emitter: self.view.model.entity_id,
2786 });
2787 }
2788 }
2789
2790 /// Register a callback to be invoked when the window is resized.
2791 pub fn observe_window_bounds(
2792 &mut self,
2793 mut callback: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2794 ) -> Subscription {
2795 let view = self.view.downgrade();
2796 let (subscription, activate) = self.window.bounds_observers.insert(
2797 (),
2798 Box::new(move |cx| view.update(cx, |view, cx| callback(view, cx)).is_ok()),
2799 );
2800 activate();
2801 subscription
2802 }
2803
2804 /// Register a callback to be invoked when the window is activated or deactivated.
2805 pub fn observe_window_activation(
2806 &mut self,
2807 mut callback: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2808 ) -> Subscription {
2809 let view = self.view.downgrade();
2810 let (subscription, activate) = self.window.activation_observers.insert(
2811 (),
2812 Box::new(move |cx| view.update(cx, |view, cx| callback(view, cx)).is_ok()),
2813 );
2814 activate();
2815 subscription
2816 }
2817
2818 /// Register a listener to be called when the given focus handle receives focus.
2819 /// Returns a subscription and persists until the subscription is dropped.
2820 pub fn on_focus(
2821 &mut self,
2822 handle: &FocusHandle,
2823 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2824 ) -> Subscription {
2825 let view = self.view.downgrade();
2826 let focus_id = handle.id;
2827 let (subscription, activate) = self.window.focus_listeners.insert(
2828 (),
2829 Box::new(move |event, cx| {
2830 view.update(cx, |view, cx| {
2831 if event.previous_focus_path.last() != Some(&focus_id)
2832 && event.current_focus_path.last() == Some(&focus_id)
2833 {
2834 listener(view, cx)
2835 }
2836 })
2837 .is_ok()
2838 }),
2839 );
2840 self.app.defer(move |_| activate());
2841 subscription
2842 }
2843
2844 /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
2845 /// Returns a subscription and persists until the subscription is dropped.
2846 pub fn on_focus_in(
2847 &mut self,
2848 handle: &FocusHandle,
2849 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2850 ) -> Subscription {
2851 let view = self.view.downgrade();
2852 let focus_id = handle.id;
2853 let (subscription, activate) = self.window.focus_listeners.insert(
2854 (),
2855 Box::new(move |event, cx| {
2856 view.update(cx, |view, cx| {
2857 if !event.previous_focus_path.contains(&focus_id)
2858 && event.current_focus_path.contains(&focus_id)
2859 {
2860 listener(view, cx)
2861 }
2862 })
2863 .is_ok()
2864 }),
2865 );
2866 self.app.defer(move |_| activate());
2867 subscription
2868 }
2869
2870 /// Register a listener to be called when the given focus handle loses focus.
2871 /// Returns a subscription and persists until the subscription is dropped.
2872 pub fn on_blur(
2873 &mut self,
2874 handle: &FocusHandle,
2875 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2876 ) -> Subscription {
2877 let view = self.view.downgrade();
2878 let focus_id = handle.id;
2879 let (subscription, activate) = self.window.focus_listeners.insert(
2880 (),
2881 Box::new(move |event, cx| {
2882 view.update(cx, |view, cx| {
2883 if event.previous_focus_path.last() == Some(&focus_id)
2884 && event.current_focus_path.last() != Some(&focus_id)
2885 {
2886 listener(view, cx)
2887 }
2888 })
2889 .is_ok()
2890 }),
2891 );
2892 self.app.defer(move |_| activate());
2893 subscription
2894 }
2895
2896 /// Register a listener to be called when nothing in the window has focus.
2897 /// This typically happens when the node that was focused is removed from the tree,
2898 /// and this callback lets you chose a default place to restore the users focus.
2899 /// Returns a subscription and persists until the subscription is dropped.
2900 pub fn on_focus_lost(
2901 &mut self,
2902 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2903 ) -> Subscription {
2904 let view = self.view.downgrade();
2905 let (subscription, activate) = self.window.focus_lost_listeners.insert(
2906 (),
2907 Box::new(move |cx| view.update(cx, |view, cx| listener(view, cx)).is_ok()),
2908 );
2909 activate();
2910 subscription
2911 }
2912
2913 /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
2914 /// Returns a subscription and persists until the subscription is dropped.
2915 pub fn on_focus_out(
2916 &mut self,
2917 handle: &FocusHandle,
2918 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2919 ) -> Subscription {
2920 let view = self.view.downgrade();
2921 let focus_id = handle.id;
2922 let (subscription, activate) = self.window.focus_listeners.insert(
2923 (),
2924 Box::new(move |event, cx| {
2925 view.update(cx, |view, cx| {
2926 if event.previous_focus_path.contains(&focus_id)
2927 && !event.current_focus_path.contains(&focus_id)
2928 {
2929 listener(view, cx)
2930 }
2931 })
2932 .is_ok()
2933 }),
2934 );
2935 self.app.defer(move |_| activate());
2936 subscription
2937 }
2938
2939 /// Schedule a future to be run asynchronously.
2940 /// The given callback is invoked with a [`WeakView<V>`] to avoid leaking the view for a long-running process.
2941 /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the view across await points.
2942 /// The returned future will be polled on the main thread.
2943 pub fn spawn<Fut, R>(
2944 &mut self,
2945 f: impl FnOnce(WeakView<V>, AsyncWindowContext) -> Fut,
2946 ) -> Task<R>
2947 where
2948 R: 'static,
2949 Fut: Future<Output = R> + 'static,
2950 {
2951 let view = self.view().downgrade();
2952 self.window_cx.spawn(|cx| f(view, cx))
2953 }
2954
2955 /// Update the global state of the given type.
2956 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
2957 where
2958 G: 'static,
2959 {
2960 let mut global = self.app.lease_global::<G>();
2961 let result = f(&mut global, self);
2962 self.app.end_global_lease(global);
2963 result
2964 }
2965
2966 /// Register a callback to be invoked when the given global state changes.
2967 pub fn observe_global<G: 'static>(
2968 &mut self,
2969 mut f: impl FnMut(&mut V, &mut ViewContext<'_, V>) + 'static,
2970 ) -> Subscription {
2971 let window_handle = self.window.handle;
2972 let view = self.view().downgrade();
2973 let (subscription, activate) = self.global_observers.insert(
2974 TypeId::of::<G>(),
2975 Box::new(move |cx| {
2976 window_handle
2977 .update(cx, |_, cx| view.update(cx, |view, cx| f(view, cx)).is_ok())
2978 .unwrap_or(false)
2979 }),
2980 );
2981 self.app.defer(move |_| activate());
2982 subscription
2983 }
2984
2985 /// Add a listener for any mouse event that occurs in the window.
2986 /// This is a fairly low level method.
2987 /// Typically, you'll want to use methods on UI elements, which perform bounds checking etc.
2988 pub fn on_mouse_event<Event: MouseEvent>(
2989 &mut self,
2990 handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext<V>) + 'static,
2991 ) {
2992 let handle = self.view().clone();
2993 self.window_cx.on_mouse_event(move |event, phase, cx| {
2994 handle.update(cx, |view, cx| {
2995 handler(view, event, phase, cx);
2996 })
2997 });
2998 }
2999
3000 /// Register a callback to be invoked when the given Key Event is dispatched to the window.
3001 pub fn on_key_event<Event: KeyEvent>(
3002 &mut self,
3003 handler: impl Fn(&mut V, &Event, DispatchPhase, &mut ViewContext<V>) + 'static,
3004 ) {
3005 let handle = self.view().clone();
3006 self.window_cx.on_key_event(move |event, phase, cx| {
3007 handle.update(cx, |view, cx| {
3008 handler(view, event, phase, cx);
3009 })
3010 });
3011 }
3012
3013 /// Register a callback to be invoked when the given Action type is dispatched to the window.
3014 pub fn on_action(
3015 &mut self,
3016 action_type: TypeId,
3017 listener: impl Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext<V>) + 'static,
3018 ) {
3019 let handle = self.view().clone();
3020 self.window_cx
3021 .on_action(action_type, move |action, phase, cx| {
3022 handle.update(cx, |view, cx| {
3023 listener(view, action, phase, cx);
3024 })
3025 });
3026 }
3027
3028 /// Emit an event to be handled any other views that have subscribed via [ViewContext::subscribe].
3029 pub fn emit<Evt>(&mut self, event: Evt)
3030 where
3031 Evt: 'static,
3032 V: EventEmitter<Evt>,
3033 {
3034 let emitter = self.view.model.entity_id;
3035 self.app.push_effect(Effect::Emit {
3036 emitter,
3037 event_type: TypeId::of::<Evt>(),
3038 event: Box::new(event),
3039 });
3040 }
3041
3042 /// Move focus to the current view, assuming it implements [`FocusableView`].
3043 pub fn focus_self(&mut self)
3044 where
3045 V: FocusableView,
3046 {
3047 self.defer(|view, cx| view.focus_handle(cx).focus(cx))
3048 }
3049
3050 /// Convenience method for accessing view state in an event callback.
3051 ///
3052 /// Many GPUI callbacks take the form of `Fn(&E, &mut WindowContext)`,
3053 /// but it's often useful to be able to access view state in these
3054 /// callbacks. This method provides a convenient way to do so.
3055 pub fn listener<E>(
3056 &self,
3057 f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
3058 ) -> impl Fn(&E, &mut WindowContext) + 'static {
3059 let view = self.view().downgrade();
3060 move |e: &E, cx: &mut WindowContext| {
3061 view.update(cx, |view, cx| f(view, e, cx)).ok();
3062 }
3063 }
3064}
3065
3066impl<V> Context for ViewContext<'_, V> {
3067 type Result<U> = U;
3068
3069 fn new_model<T: 'static>(
3070 &mut self,
3071 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
3072 ) -> Model<T> {
3073 self.window_cx.new_model(build_model)
3074 }
3075
3076 fn update_model<T: 'static, R>(
3077 &mut self,
3078 model: &Model<T>,
3079 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
3080 ) -> R {
3081 self.window_cx.update_model(model, update)
3082 }
3083
3084 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
3085 where
3086 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
3087 {
3088 self.window_cx.update_window(window, update)
3089 }
3090
3091 fn read_model<T, R>(
3092 &self,
3093 handle: &Model<T>,
3094 read: impl FnOnce(&T, &AppContext) -> R,
3095 ) -> Self::Result<R>
3096 where
3097 T: 'static,
3098 {
3099 self.window_cx.read_model(handle, read)
3100 }
3101
3102 fn read_window<T, R>(
3103 &self,
3104 window: &WindowHandle<T>,
3105 read: impl FnOnce(View<T>, &AppContext) -> R,
3106 ) -> Result<R>
3107 where
3108 T: 'static,
3109 {
3110 self.window_cx.read_window(window, read)
3111 }
3112}
3113
3114impl<V: 'static> VisualContext for ViewContext<'_, V> {
3115 fn new_view<W: Render + 'static>(
3116 &mut self,
3117 build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W,
3118 ) -> Self::Result<View<W>> {
3119 self.window_cx.new_view(build_view_state)
3120 }
3121
3122 fn update_view<V2: 'static, R>(
3123 &mut self,
3124 view: &View<V2>,
3125 update: impl FnOnce(&mut V2, &mut ViewContext<'_, V2>) -> R,
3126 ) -> Self::Result<R> {
3127 self.window_cx.update_view(view, update)
3128 }
3129
3130 fn replace_root_view<W>(
3131 &mut self,
3132 build_view: impl FnOnce(&mut ViewContext<'_, W>) -> W,
3133 ) -> Self::Result<View<W>>
3134 where
3135 W: 'static + Render,
3136 {
3137 self.window_cx.replace_root_view(build_view)
3138 }
3139
3140 fn focus_view<W: FocusableView>(&mut self, view: &View<W>) -> Self::Result<()> {
3141 self.window_cx.focus_view(view)
3142 }
3143
3144 fn dismiss_view<W: ManagedView>(&mut self, view: &View<W>) -> Self::Result<()> {
3145 self.window_cx.dismiss_view(view)
3146 }
3147}
3148
3149impl<'a, V> std::ops::Deref for ViewContext<'a, V> {
3150 type Target = WindowContext<'a>;
3151
3152 fn deref(&self) -> &Self::Target {
3153 &self.window_cx
3154 }
3155}
3156
3157impl<'a, V> std::ops::DerefMut for ViewContext<'a, V> {
3158 fn deref_mut(&mut self) -> &mut Self::Target {
3159 &mut self.window_cx
3160 }
3161}
3162
3163// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
3164slotmap::new_key_type! {
3165 /// A unique identifier for a window.
3166 pub struct WindowId;
3167}
3168
3169impl WindowId {
3170 /// Converts this window ID to a `u64`.
3171 pub fn as_u64(&self) -> u64 {
3172 self.0.as_ffi()
3173 }
3174}
3175
3176/// A handle to a window with a specific root view type.
3177/// Note that this does not keep the window alive on its own.
3178#[derive(Deref, DerefMut)]
3179pub struct WindowHandle<V> {
3180 #[deref]
3181 #[deref_mut]
3182 pub(crate) any_handle: AnyWindowHandle,
3183 state_type: PhantomData<V>,
3184}
3185
3186impl<V: 'static + Render> WindowHandle<V> {
3187 /// Create a new handle from a window ID.
3188 /// This does not check if the root type of the window is `V`.
3189 pub fn new(id: WindowId) -> Self {
3190 WindowHandle {
3191 any_handle: AnyWindowHandle {
3192 id,
3193 state_type: TypeId::of::<V>(),
3194 },
3195 state_type: PhantomData,
3196 }
3197 }
3198
3199 /// Get the root view out of this window.
3200 ///
3201 /// This will fail if the window is closed or if the root view's type does not match `V`.
3202 pub fn root<C>(&self, cx: &mut C) -> Result<View<V>>
3203 where
3204 C: Context,
3205 {
3206 Flatten::flatten(cx.update_window(self.any_handle, |root_view, _| {
3207 root_view
3208 .downcast::<V>()
3209 .map_err(|_| anyhow!("the type of the window's root view has changed"))
3210 }))
3211 }
3212
3213 /// Update the root view of this window.
3214 ///
3215 /// This will fail if the window has been closed or if the root view's type does not match
3216 pub fn update<C, R>(
3217 &self,
3218 cx: &mut C,
3219 update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
3220 ) -> Result<R>
3221 where
3222 C: Context,
3223 {
3224 cx.update_window(self.any_handle, |root_view, cx| {
3225 let view = root_view
3226 .downcast::<V>()
3227 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
3228 Ok(cx.update_view(&view, update))
3229 })?
3230 }
3231
3232 /// Read the root view out of this window.
3233 ///
3234 /// This will fail if the window is closed or if the root view's type does not match `V`.
3235 pub fn read<'a>(&self, cx: &'a AppContext) -> Result<&'a V> {
3236 let x = cx
3237 .windows
3238 .get(self.id)
3239 .and_then(|window| {
3240 window
3241 .as_ref()
3242 .and_then(|window| window.root_view.clone())
3243 .map(|root_view| root_view.downcast::<V>())
3244 })
3245 .ok_or_else(|| anyhow!("window not found"))?
3246 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
3247
3248 Ok(x.read(cx))
3249 }
3250
3251 /// Read the root view out of this window, with a callback
3252 ///
3253 /// This will fail if the window is closed or if the root view's type does not match `V`.
3254 pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &AppContext) -> R) -> Result<R>
3255 where
3256 C: Context,
3257 {
3258 cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
3259 }
3260
3261 /// Read the root view pointer off of this window.
3262 ///
3263 /// This will fail if the window is closed or if the root view's type does not match `V`.
3264 pub fn root_view<C>(&self, cx: &C) -> Result<View<V>>
3265 where
3266 C: Context,
3267 {
3268 cx.read_window(self, |root_view, _cx| root_view.clone())
3269 }
3270
3271 /// Check if this window is 'active'.
3272 ///
3273 /// Will return `None` if the window is closed.
3274 pub fn is_active(&self, cx: &AppContext) -> Option<bool> {
3275 cx.windows
3276 .get(self.id)
3277 .and_then(|window| window.as_ref().map(|window| window.active))
3278 }
3279}
3280
3281impl<V> Copy for WindowHandle<V> {}
3282
3283impl<V> Clone for WindowHandle<V> {
3284 fn clone(&self) -> Self {
3285 *self
3286 }
3287}
3288
3289impl<V> PartialEq for WindowHandle<V> {
3290 fn eq(&self, other: &Self) -> bool {
3291 self.any_handle == other.any_handle
3292 }
3293}
3294
3295impl<V> Eq for WindowHandle<V> {}
3296
3297impl<V> Hash for WindowHandle<V> {
3298 fn hash<H: Hasher>(&self, state: &mut H) {
3299 self.any_handle.hash(state);
3300 }
3301}
3302
3303impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
3304 fn from(val: WindowHandle<V>) -> Self {
3305 val.any_handle
3306 }
3307}
3308
3309/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.
3310#[derive(Copy, Clone, PartialEq, Eq, Hash)]
3311pub struct AnyWindowHandle {
3312 pub(crate) id: WindowId,
3313 state_type: TypeId,
3314}
3315
3316impl AnyWindowHandle {
3317 /// Get the ID of this window.
3318 pub fn window_id(&self) -> WindowId {
3319 self.id
3320 }
3321
3322 /// Attempt to convert this handle to a window handle with a specific root view type.
3323 /// If the types do not match, this will return `None`.
3324 pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
3325 if TypeId::of::<T>() == self.state_type {
3326 Some(WindowHandle {
3327 any_handle: *self,
3328 state_type: PhantomData,
3329 })
3330 } else {
3331 None
3332 }
3333 }
3334
3335 /// Update the state of the root view of this window.
3336 ///
3337 /// This will fail if the window has been closed.
3338 pub fn update<C, R>(
3339 self,
3340 cx: &mut C,
3341 update: impl FnOnce(AnyView, &mut WindowContext<'_>) -> R,
3342 ) -> Result<R>
3343 where
3344 C: Context,
3345 {
3346 cx.update_window(self, update)
3347 }
3348
3349 /// Read the state of the root view of this window.
3350 ///
3351 /// This will fail if the window has been closed.
3352 pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(View<T>, &AppContext) -> R) -> Result<R>
3353 where
3354 C: Context,
3355 T: 'static,
3356 {
3357 let view = self
3358 .downcast::<T>()
3359 .context("the type of the window's root view has changed")?;
3360
3361 cx.read_window(&view, read)
3362 }
3363}
3364
3365/// An identifier for an [`Element`](crate::Element).
3366///
3367/// Can be constructed with a string, a number, or both, as well
3368/// as other internal representations.
3369#[derive(Clone, Debug, Eq, PartialEq, Hash)]
3370pub enum ElementId {
3371 /// The ID of a View element
3372 View(EntityId),
3373 /// An integer ID.
3374 Integer(usize),
3375 /// A string based ID.
3376 Name(SharedString),
3377 /// An ID that's equated with a focus handle.
3378 FocusHandle(FocusId),
3379 /// A combination of a name and an integer.
3380 NamedInteger(SharedString, usize),
3381}
3382
3383impl ElementId {
3384 pub(crate) fn from_entity_id(entity_id: EntityId) -> Self {
3385 ElementId::View(entity_id)
3386 }
3387}
3388
3389impl TryInto<SharedString> for ElementId {
3390 type Error = anyhow::Error;
3391
3392 fn try_into(self) -> anyhow::Result<SharedString> {
3393 if let ElementId::Name(name) = self {
3394 Ok(name)
3395 } else {
3396 Err(anyhow!("element id is not string"))
3397 }
3398 }
3399}
3400
3401impl From<usize> for ElementId {
3402 fn from(id: usize) -> Self {
3403 ElementId::Integer(id)
3404 }
3405}
3406
3407impl From<i32> for ElementId {
3408 fn from(id: i32) -> Self {
3409 Self::Integer(id as usize)
3410 }
3411}
3412
3413impl From<SharedString> for ElementId {
3414 fn from(name: SharedString) -> Self {
3415 ElementId::Name(name)
3416 }
3417}
3418
3419impl From<&'static str> for ElementId {
3420 fn from(name: &'static str) -> Self {
3421 ElementId::Name(name.into())
3422 }
3423}
3424
3425impl<'a> From<&'a FocusHandle> for ElementId {
3426 fn from(handle: &'a FocusHandle) -> Self {
3427 ElementId::FocusHandle(handle.id)
3428 }
3429}
3430
3431impl From<(&'static str, EntityId)> for ElementId {
3432 fn from((name, id): (&'static str, EntityId)) -> Self {
3433 ElementId::NamedInteger(name.into(), id.as_u64() as usize)
3434 }
3435}
3436
3437impl From<(&'static str, usize)> for ElementId {
3438 fn from((name, id): (&'static str, usize)) -> Self {
3439 ElementId::NamedInteger(name.into(), id)
3440 }
3441}
3442
3443impl From<(&'static str, u64)> for ElementId {
3444 fn from((name, id): (&'static str, u64)) -> Self {
3445 ElementId::NamedInteger(name.into(), id as usize)
3446 }
3447}
3448
3449/// A rectangle to be rendered in the window at the given position and size.
3450/// Passed as an argument [`WindowContext::paint_quad`].
3451#[derive(Clone)]
3452pub struct PaintQuad {
3453 bounds: Bounds<Pixels>,
3454 corner_radii: Corners<Pixels>,
3455 background: Hsla,
3456 border_widths: Edges<Pixels>,
3457 border_color: Hsla,
3458}
3459
3460impl PaintQuad {
3461 /// Set the corner radii of the quad.
3462 pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
3463 PaintQuad {
3464 corner_radii: corner_radii.into(),
3465 ..self
3466 }
3467 }
3468
3469 /// Set the border widths of the quad.
3470 pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
3471 PaintQuad {
3472 border_widths: border_widths.into(),
3473 ..self
3474 }
3475 }
3476
3477 /// Set the border color of the quad.
3478 pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
3479 PaintQuad {
3480 border_color: border_color.into(),
3481 ..self
3482 }
3483 }
3484
3485 /// Set the background color of the quad.
3486 pub fn background(self, background: impl Into<Hsla>) -> Self {
3487 PaintQuad {
3488 background: background.into(),
3489 ..self
3490 }
3491 }
3492}
3493
3494/// Create a quad with the given parameters.
3495pub fn quad(
3496 bounds: Bounds<Pixels>,
3497 corner_radii: impl Into<Corners<Pixels>>,
3498 background: impl Into<Hsla>,
3499 border_widths: impl Into<Edges<Pixels>>,
3500 border_color: impl Into<Hsla>,
3501) -> PaintQuad {
3502 PaintQuad {
3503 bounds,
3504 corner_radii: corner_radii.into(),
3505 background: background.into(),
3506 border_widths: border_widths.into(),
3507 border_color: border_color.into(),
3508 }
3509}
3510
3511/// Create a filled quad with the given bounds and background color.
3512pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Hsla>) -> PaintQuad {
3513 PaintQuad {
3514 bounds: bounds.into(),
3515 corner_radii: (0.).into(),
3516 background: background.into(),
3517 border_widths: (0.).into(),
3518 border_color: transparent_black(),
3519 }
3520}
3521
3522/// Create a rectangle outline with the given bounds, border color, and a 1px border width
3523pub fn outline(bounds: impl Into<Bounds<Pixels>>, border_color: impl Into<Hsla>) -> PaintQuad {
3524 PaintQuad {
3525 bounds: bounds.into(),
3526 corner_radii: (0.).into(),
3527 background: transparent_black(),
3528 border_widths: (1.).into(),
3529 border_color: border_color.into(),
3530 }
3531}