1use crate::{
2 px, size, transparent_black, Action, AnyDrag, AnyView, AppContext, Arena, AsyncWindowContext,
3 AvailableSpace, Bounds, Context, Corners, CursorStyle, DispatchActionListener, DispatchNodeId,
4 DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten,
5 Global, GlobalElementId, Hsla, KeyBinding, KeyContext, KeyDownEvent, KeyMatch, KeymatchResult,
6 Keystroke, KeystrokeEvent, Model, ModelContext, Modifiers, MouseButton, MouseMoveEvent,
7 MouseUpEvent, Pixels, PlatformAtlas, PlatformDisplay, PlatformInput, PlatformWindow, Point,
8 PromptLevel, Render, ScaledPixels, SharedString, Size, SubscriberSet, Subscription,
9 TaffyLayoutEngine, Task, View, VisualContext, WeakView, WindowAppearance, WindowBounds,
10 WindowOptions, WindowTextSystem,
11};
12use anyhow::{anyhow, Context as _, Result};
13use collections::FxHashSet;
14use derive_more::{Deref, DerefMut};
15use futures::channel::oneshot;
16use parking_lot::RwLock;
17use slotmap::SlotMap;
18use smallvec::SmallVec;
19use std::{
20 any::{Any, TypeId},
21 borrow::{Borrow, BorrowMut},
22 cell::{Cell, RefCell},
23 fmt::{Debug, Display},
24 future::Future,
25 hash::{Hash, Hasher},
26 marker::PhantomData,
27 mem,
28 rc::Rc,
29 sync::{
30 atomic::{AtomicUsize, Ordering::SeqCst},
31 Arc,
32 },
33 time::{Duration, Instant},
34};
35use util::{measure, ResultExt};
36
37mod element_cx;
38pub use element_cx::*;
39
40const ACTIVE_DRAG_Z_INDEX: u16 = 1;
41
42/// A global stacking order, which is created by stacking successive z-index values.
43/// Each z-index will always be interpreted in the context of its parent z-index.
44#[derive(Debug, Deref, DerefMut, Clone, Ord, PartialOrd, PartialEq, Eq, Default)]
45pub struct StackingOrder(SmallVec<[StackingContext; 64]>);
46
47/// A single entry in a primitive's z-index stacking order
48#[derive(Clone, Ord, PartialOrd, PartialEq, Eq, Default)]
49pub struct StackingContext {
50 pub(crate) z_index: u16,
51 pub(crate) id: u16,
52}
53
54impl std::fmt::Debug for StackingContext {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56 write!(f, "{{{}.{}}} ", self.z_index, self.id)
57 }
58}
59
60/// Represents the two different phases when dispatching events.
61#[derive(Default, Copy, Clone, Debug, Eq, PartialEq)]
62pub enum DispatchPhase {
63 /// After the capture phase comes the bubble phase, in which mouse event listeners are
64 /// invoked front to back and keyboard event listeners are invoked from the focused element
65 /// to the root of the element tree. This is the phase you'll most commonly want to use when
66 /// registering event listeners.
67 #[default]
68 Bubble,
69 /// During the initial capture phase, mouse event listeners are invoked back to front, and keyboard
70 /// listeners are invoked from the root of the tree downward toward the focused element. This phase
71 /// is used for special purposes such as clearing the "pressed" state for click events. If
72 /// you stop event propagation during this phase, you need to know what you're doing. Handlers
73 /// outside of the immediate region may rely on detecting non-local events during this phase.
74 Capture,
75}
76
77impl DispatchPhase {
78 /// Returns true if this represents the "bubble" phase.
79 pub fn bubble(self) -> bool {
80 self == DispatchPhase::Bubble
81 }
82
83 /// Returns true if this represents the "capture" phase.
84 pub fn capture(self) -> bool {
85 self == DispatchPhase::Capture
86 }
87}
88
89type AnyObserver = Box<dyn FnMut(&mut WindowContext) -> bool + 'static>;
90
91type AnyWindowFocusListener = Box<dyn FnMut(&FocusEvent, &mut WindowContext) -> bool + 'static>;
92
93struct FocusEvent {
94 previous_focus_path: SmallVec<[FocusId; 8]>,
95 current_focus_path: SmallVec<[FocusId; 8]>,
96}
97
98slotmap::new_key_type! {
99 /// A globally unique identifier for a focusable element.
100 pub struct FocusId;
101}
102
103thread_local! {
104 pub(crate) static ELEMENT_ARENA: RefCell<Arena> = RefCell::new(Arena::new(8 * 1024 * 1024));
105}
106
107impl FocusId {
108 /// Obtains whether the element associated with this handle is currently focused.
109 pub fn is_focused(&self, cx: &WindowContext) -> bool {
110 cx.window.focus == Some(*self)
111 }
112
113 /// Obtains whether the element associated with this handle contains the focused
114 /// element or is itself focused.
115 pub fn contains_focused(&self, cx: &WindowContext) -> bool {
116 cx.focused()
117 .map_or(false, |focused| self.contains(focused.id, cx))
118 }
119
120 /// Obtains whether the element associated with this handle is contained within the
121 /// focused element or is itself focused.
122 pub fn within_focused(&self, cx: &WindowContext) -> bool {
123 let focused = cx.focused();
124 focused.map_or(false, |focused| focused.id.contains(*self, cx))
125 }
126
127 /// Obtains whether this handle contains the given handle in the most recently rendered frame.
128 pub(crate) fn contains(&self, other: Self, cx: &WindowContext) -> bool {
129 cx.window
130 .rendered_frame
131 .dispatch_tree
132 .focus_contains(*self, other)
133 }
134}
135
136/// A handle which can be used to track and manipulate the focused element in a window.
137pub struct FocusHandle {
138 pub(crate) id: FocusId,
139 handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
140}
141
142impl std::fmt::Debug for FocusHandle {
143 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144 f.write_fmt(format_args!("FocusHandle({:?})", self.id))
145 }
146}
147
148impl FocusHandle {
149 pub(crate) fn new(handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>) -> Self {
150 let id = handles.write().insert(AtomicUsize::new(1));
151 Self {
152 id,
153 handles: handles.clone(),
154 }
155 }
156
157 pub(crate) fn for_id(
158 id: FocusId,
159 handles: &Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
160 ) -> Option<Self> {
161 let lock = handles.read();
162 let ref_count = lock.get(id)?;
163 if ref_count.load(SeqCst) == 0 {
164 None
165 } else {
166 ref_count.fetch_add(1, SeqCst);
167 Some(Self {
168 id,
169 handles: handles.clone(),
170 })
171 }
172 }
173
174 /// Moves the focus to the element associated with this handle.
175 pub fn focus(&self, cx: &mut WindowContext) {
176 cx.focus(self)
177 }
178
179 /// Obtains whether the element associated with this handle is currently focused.
180 pub fn is_focused(&self, cx: &WindowContext) -> bool {
181 self.id.is_focused(cx)
182 }
183
184 /// Obtains whether the element associated with this handle contains the focused
185 /// element or is itself focused.
186 pub fn contains_focused(&self, cx: &WindowContext) -> bool {
187 self.id.contains_focused(cx)
188 }
189
190 /// Obtains whether the element associated with this handle is contained within the
191 /// focused element or is itself focused.
192 pub fn within_focused(&self, cx: &WindowContext) -> bool {
193 self.id.within_focused(cx)
194 }
195
196 /// Obtains whether this handle contains the given handle in the most recently rendered frame.
197 pub fn contains(&self, other: &Self, cx: &WindowContext) -> bool {
198 self.id.contains(other.id, cx)
199 }
200}
201
202impl Clone for FocusHandle {
203 fn clone(&self) -> Self {
204 Self::for_id(self.id, &self.handles).unwrap()
205 }
206}
207
208impl PartialEq for FocusHandle {
209 fn eq(&self, other: &Self) -> bool {
210 self.id == other.id
211 }
212}
213
214impl Eq for FocusHandle {}
215
216impl Drop for FocusHandle {
217 fn drop(&mut self) {
218 self.handles
219 .read()
220 .get(self.id)
221 .unwrap()
222 .fetch_sub(1, SeqCst);
223 }
224}
225
226/// FocusableView allows users of your view to easily
227/// focus it (using cx.focus_view(view))
228pub trait FocusableView: 'static + Render {
229 /// Returns the focus handle associated with this view.
230 fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
231}
232
233/// ManagedView is a view (like a Modal, Popover, Menu, etc.)
234/// where the lifecycle of the view is handled by another view.
235pub trait ManagedView: FocusableView + EventEmitter<DismissEvent> {}
236
237impl<M: FocusableView + EventEmitter<DismissEvent>> ManagedView for M {}
238
239/// Emitted by implementers of [`ManagedView`] to indicate the view should be dismissed, such as when a view is presented as a modal.
240pub struct DismissEvent;
241
242type FrameCallback = Box<dyn FnOnce(&mut WindowContext)>;
243
244// Holds the state for a specific window.
245#[doc(hidden)]
246pub struct Window {
247 pub(crate) handle: AnyWindowHandle,
248 pub(crate) removed: bool,
249 pub(crate) platform_window: Box<dyn PlatformWindow>,
250 display_id: DisplayId,
251 sprite_atlas: Arc<dyn PlatformAtlas>,
252 text_system: Arc<WindowTextSystem>,
253 pub(crate) rem_size: Pixels,
254 pub(crate) viewport_size: Size<Pixels>,
255 layout_engine: Option<TaffyLayoutEngine>,
256 pub(crate) root_view: Option<AnyView>,
257 pub(crate) element_id_stack: GlobalElementId,
258 pub(crate) rendered_frame: Frame,
259 pub(crate) next_frame: Frame,
260 next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>>,
261 pub(crate) dirty_views: FxHashSet<EntityId>,
262 pub(crate) focus_handles: Arc<RwLock<SlotMap<FocusId, AtomicUsize>>>,
263 focus_listeners: SubscriberSet<(), AnyWindowFocusListener>,
264 focus_lost_listeners: SubscriberSet<(), AnyObserver>,
265 default_prevented: bool,
266 mouse_position: Point<Pixels>,
267 modifiers: Modifiers,
268 scale_factor: f32,
269 bounds: WindowBounds,
270 bounds_observers: SubscriberSet<(), AnyObserver>,
271 appearance: WindowAppearance,
272 appearance_observers: SubscriberSet<(), AnyObserver>,
273 active: Rc<Cell<bool>>,
274 pub(crate) dirty: Rc<Cell<bool>>,
275 pub(crate) last_input_timestamp: Rc<Cell<Instant>>,
276 pub(crate) refreshing: bool,
277 pub(crate) drawing: bool,
278 activation_observers: SubscriberSet<(), AnyObserver>,
279 pub(crate) focus: Option<FocusId>,
280 focus_enabled: bool,
281 pending_input: Option<PendingInput>,
282 graphics_profiler_enabled: bool,
283}
284
285#[derive(Default, Debug)]
286struct PendingInput {
287 keystrokes: SmallVec<[Keystroke; 1]>,
288 bindings: SmallVec<[KeyBinding; 1]>,
289 focus: Option<FocusId>,
290 timer: Option<Task<()>>,
291}
292
293impl PendingInput {
294 fn input(&self) -> String {
295 self.keystrokes
296 .iter()
297 .flat_map(|k| k.ime_key.clone())
298 .collect::<Vec<String>>()
299 .join("")
300 }
301
302 fn used_by_binding(&self, binding: &KeyBinding) -> bool {
303 if self.keystrokes.is_empty() {
304 return true;
305 }
306 let keystroke = &self.keystrokes[0];
307 for candidate in keystroke.match_candidates() {
308 if binding.match_keystrokes(&[candidate]) == KeyMatch::Pending {
309 return true;
310 }
311 }
312 false
313 }
314}
315
316pub(crate) struct ElementStateBox {
317 pub(crate) inner: Box<dyn Any>,
318 pub(crate) parent_view_id: EntityId,
319 #[cfg(debug_assertions)]
320 pub(crate) type_name: &'static str,
321}
322
323impl Window {
324 pub(crate) fn new(
325 handle: AnyWindowHandle,
326 options: WindowOptions,
327 cx: &mut AppContext,
328 ) -> Self {
329 let platform_window = cx.platform.open_window(handle, options);
330 let display_id = platform_window.display().id();
331 let sprite_atlas = platform_window.sprite_atlas();
332 let mouse_position = platform_window.mouse_position();
333 let modifiers = platform_window.modifiers();
334 let content_size = platform_window.content_size();
335 let scale_factor = platform_window.scale_factor();
336 let bounds = platform_window.bounds();
337 let appearance = platform_window.appearance();
338 let text_system = Arc::new(WindowTextSystem::new(cx.text_system().clone()));
339 let dirty = Rc::new(Cell::new(true));
340 let active = Rc::new(Cell::new(false));
341 let next_frame_callbacks: Rc<RefCell<Vec<FrameCallback>>> = Default::default();
342 let last_input_timestamp = Rc::new(Cell::new(Instant::now()));
343
344 platform_window.on_close(Box::new({
345 let mut cx = cx.to_async();
346 move || {
347 let _ = handle.update(&mut cx, |_, cx| cx.remove_window());
348 }
349 }));
350 platform_window.on_request_frame(Box::new({
351 let mut cx = cx.to_async();
352 let dirty = dirty.clone();
353 let active = active.clone();
354 let next_frame_callbacks = next_frame_callbacks.clone();
355 let last_input_timestamp = last_input_timestamp.clone();
356 move || {
357 let next_frame_callbacks = next_frame_callbacks.take();
358 if !next_frame_callbacks.is_empty() {
359 handle
360 .update(&mut cx, |_, cx| {
361 for callback in next_frame_callbacks {
362 callback(cx);
363 }
364 })
365 .log_err();
366 }
367
368 if dirty.get() {
369 measure("frame duration", || {
370 handle
371 .update(&mut cx, |_, cx| {
372 cx.draw();
373 cx.present();
374 })
375 .log_err();
376 })
377 }
378 // Keep presenting the current scene for 1 extra second since the
379 // last input to prevent the display from underclocking the refresh rate.
380 else if active.get()
381 && last_input_timestamp.get().elapsed() < Duration::from_secs(1)
382 {
383 handle.update(&mut cx, |_, cx| cx.present()).log_err();
384 }
385 }
386 }));
387 platform_window.on_resize(Box::new({
388 let mut cx = cx.to_async();
389 move |_, _| {
390 handle
391 .update(&mut cx, |_, cx| cx.window_bounds_changed())
392 .log_err();
393 }
394 }));
395 platform_window.on_moved(Box::new({
396 let mut cx = cx.to_async();
397 move || {
398 handle
399 .update(&mut cx, |_, cx| cx.window_bounds_changed())
400 .log_err();
401 }
402 }));
403 platform_window.on_appearance_changed(Box::new({
404 let mut cx = cx.to_async();
405 move || {
406 handle
407 .update(&mut cx, |_, cx| cx.appearance_changed())
408 .log_err();
409 }
410 }));
411 platform_window.on_active_status_change(Box::new({
412 let mut cx = cx.to_async();
413 move |active| {
414 handle
415 .update(&mut cx, |_, cx| {
416 cx.window.active.set(active);
417 cx.window
418 .activation_observers
419 .clone()
420 .retain(&(), |callback| callback(cx));
421 })
422 .log_err();
423 }
424 }));
425
426 platform_window.on_input({
427 let mut cx = cx.to_async();
428 Box::new(move |event| {
429 handle
430 .update(&mut cx, |_, cx| cx.dispatch_event(event))
431 .log_err()
432 .unwrap_or(false)
433 })
434 });
435
436 Window {
437 handle,
438 removed: false,
439 platform_window,
440 display_id,
441 sprite_atlas,
442 text_system,
443 rem_size: px(16.),
444 viewport_size: content_size,
445 layout_engine: Some(TaffyLayoutEngine::new()),
446 root_view: None,
447 element_id_stack: GlobalElementId::default(),
448 rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
449 next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())),
450 next_frame_callbacks,
451 dirty_views: FxHashSet::default(),
452 focus_handles: Arc::new(RwLock::new(SlotMap::with_key())),
453 focus_listeners: SubscriberSet::new(),
454 focus_lost_listeners: SubscriberSet::new(),
455 default_prevented: true,
456 mouse_position,
457 modifiers,
458 scale_factor,
459 bounds,
460 bounds_observers: SubscriberSet::new(),
461 appearance,
462 appearance_observers: SubscriberSet::new(),
463 active,
464 dirty,
465 last_input_timestamp,
466 refreshing: false,
467 drawing: false,
468 activation_observers: SubscriberSet::new(),
469 focus: None,
470 focus_enabled: true,
471 pending_input: None,
472 graphics_profiler_enabled: false,
473 }
474 }
475 fn new_focus_listener(
476 &mut self,
477 value: AnyWindowFocusListener,
478 ) -> (Subscription, impl FnOnce()) {
479 self.focus_listeners.insert((), value)
480 }
481}
482
483/// Indicates which region of the window is visible. Content falling outside of this mask will not be
484/// rendered. Currently, only rectangular content masks are supported, but we give the mask its own type
485/// to leave room to support more complex shapes in the future.
486#[derive(Clone, Debug, Default, PartialEq, Eq)]
487#[repr(C)]
488pub struct ContentMask<P: Clone + Default + Debug> {
489 /// The bounds
490 pub bounds: Bounds<P>,
491}
492
493impl ContentMask<Pixels> {
494 /// Scale the content mask's pixel units by the given scaling factor.
495 pub fn scale(&self, factor: f32) -> ContentMask<ScaledPixels> {
496 ContentMask {
497 bounds: self.bounds.scale(factor),
498 }
499 }
500
501 /// Intersect the content mask with the given content mask.
502 pub fn intersect(&self, other: &Self) -> Self {
503 let bounds = self.bounds.intersect(&other.bounds);
504 ContentMask { bounds }
505 }
506}
507
508/// Provides access to application state in the context of a single window. Derefs
509/// to an [`AppContext`], so you can also pass a [`WindowContext`] to any method that takes
510/// an [`AppContext`] and call any [`AppContext`] methods.
511pub struct WindowContext<'a> {
512 pub(crate) app: &'a mut AppContext,
513 pub(crate) window: &'a mut Window,
514}
515
516impl<'a> WindowContext<'a> {
517 pub(crate) fn new(app: &'a mut AppContext, window: &'a mut Window) -> Self {
518 Self { app, window }
519 }
520
521 /// Obtain a handle to the window that belongs to this context.
522 pub fn window_handle(&self) -> AnyWindowHandle {
523 self.window.handle
524 }
525
526 /// Mark the window as dirty, scheduling it to be redrawn on the next frame.
527 pub fn refresh(&mut self) {
528 if !self.window.drawing {
529 self.window.refreshing = true;
530 self.window.dirty.set(true);
531 }
532 }
533
534 /// Close this window.
535 pub fn remove_window(&mut self) {
536 self.window.removed = true;
537 }
538
539 /// Obtain a new [`FocusHandle`], which allows you to track and manipulate the keyboard focus
540 /// for elements rendered within this window.
541 pub fn focus_handle(&mut self) -> FocusHandle {
542 FocusHandle::new(&self.window.focus_handles)
543 }
544
545 /// Obtain the currently focused [`FocusHandle`]. If no elements are focused, returns `None`.
546 pub fn focused(&self) -> Option<FocusHandle> {
547 self.window
548 .focus
549 .and_then(|id| FocusHandle::for_id(id, &self.window.focus_handles))
550 }
551
552 /// Move focus to the element associated with the given [`FocusHandle`].
553 pub fn focus(&mut self, handle: &FocusHandle) {
554 if !self.window.focus_enabled || self.window.focus == Some(handle.id) {
555 return;
556 }
557
558 self.window.focus = Some(handle.id);
559 self.window
560 .rendered_frame
561 .dispatch_tree
562 .clear_pending_keystrokes();
563 self.refresh();
564 }
565
566 /// Remove focus from all elements within this context's window.
567 pub fn blur(&mut self) {
568 if !self.window.focus_enabled {
569 return;
570 }
571
572 self.window.focus = None;
573 self.refresh();
574 }
575
576 /// Blur the window and don't allow anything in it to be focused again.
577 pub fn disable_focus(&mut self) {
578 self.blur();
579 self.window.focus_enabled = false;
580 }
581
582 /// Accessor for the text system.
583 pub fn text_system(&self) -> &Arc<WindowTextSystem> {
584 &self.window.text_system
585 }
586
587 /// Dispatch the given action on the currently focused element.
588 pub fn dispatch_action(&mut self, action: Box<dyn Action>) {
589 let focus_handle = self.focused();
590
591 self.defer(move |cx| {
592 let node_id = focus_handle
593 .and_then(|handle| {
594 cx.window
595 .rendered_frame
596 .dispatch_tree
597 .focusable_node_id(handle.id)
598 })
599 .unwrap_or_else(|| cx.window.rendered_frame.dispatch_tree.root_node_id());
600
601 cx.propagate_event = true;
602 cx.dispatch_action_on_node(node_id, action);
603 })
604 }
605
606 pub(crate) fn dispatch_keystroke_observers(
607 &mut self,
608 event: &dyn Any,
609 action: Option<Box<dyn Action>>,
610 ) {
611 let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() else {
612 return;
613 };
614
615 self.keystroke_observers
616 .clone()
617 .retain(&(), move |callback| {
618 (callback)(
619 &KeystrokeEvent {
620 keystroke: key_down_event.keystroke.clone(),
621 action: action.as_ref().map(|action| action.boxed_clone()),
622 },
623 self,
624 );
625 true
626 });
627 }
628
629 pub(crate) fn clear_pending_keystrokes(&mut self) {
630 self.window
631 .rendered_frame
632 .dispatch_tree
633 .clear_pending_keystrokes();
634 self.window
635 .next_frame
636 .dispatch_tree
637 .clear_pending_keystrokes();
638 }
639
640 /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
641 /// that are currently on the stack to be returned to the app.
642 pub fn defer(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) {
643 let handle = self.window.handle;
644 self.app.defer(move |cx| {
645 handle.update(cx, |_, cx| f(cx)).ok();
646 });
647 }
648
649 /// Subscribe to events emitted by a model or view.
650 /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
651 /// 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.
652 pub fn subscribe<Emitter, E, Evt>(
653 &mut self,
654 entity: &E,
655 mut on_event: impl FnMut(E, &Evt, &mut WindowContext<'_>) + 'static,
656 ) -> Subscription
657 where
658 Emitter: EventEmitter<Evt>,
659 E: Entity<Emitter>,
660 Evt: 'static,
661 {
662 let entity_id = entity.entity_id();
663 let entity = entity.downgrade();
664 let window_handle = self.window.handle;
665 self.app.new_subscription(
666 entity_id,
667 (
668 TypeId::of::<Evt>(),
669 Box::new(move |event, cx| {
670 window_handle
671 .update(cx, |_, cx| {
672 if let Some(handle) = E::upgrade_from(&entity) {
673 let event = event.downcast_ref().expect("invalid event type");
674 on_event(handle, event, cx);
675 true
676 } else {
677 false
678 }
679 })
680 .unwrap_or(false)
681 }),
682 ),
683 )
684 }
685
686 /// Creates an [`AsyncWindowContext`], which has a static lifetime and can be held across
687 /// await points in async code.
688 pub fn to_async(&self) -> AsyncWindowContext {
689 AsyncWindowContext::new(self.app.to_async(), self.window.handle)
690 }
691
692 /// Schedule the given closure to be run directly after the current frame is rendered.
693 pub fn on_next_frame(&mut self, callback: impl FnOnce(&mut WindowContext) + 'static) {
694 RefCell::borrow_mut(&self.window.next_frame_callbacks).push(Box::new(callback));
695 }
696
697 /// Spawn the future returned by the given closure on the application thread pool.
698 /// The closure is provided a handle to the current window and an `AsyncWindowContext` for
699 /// use within your future.
700 pub fn spawn<Fut, R>(&mut self, f: impl FnOnce(AsyncWindowContext) -> Fut) -> Task<R>
701 where
702 R: 'static,
703 Fut: Future<Output = R> + 'static,
704 {
705 self.app
706 .spawn(|app| f(AsyncWindowContext::new(app, self.window.handle)))
707 }
708
709 /// Updates the global of the given type. The given closure is given simultaneous mutable
710 /// access both to the global and the context.
711 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
712 where
713 G: Global,
714 {
715 let mut global = self.app.lease_global::<G>();
716 let result = f(&mut global, self);
717 self.app.end_global_lease(global);
718 result
719 }
720
721 fn window_bounds_changed(&mut self) {
722 self.window.scale_factor = self.window.platform_window.scale_factor();
723 self.window.viewport_size = self.window.platform_window.content_size();
724 self.window.bounds = self.window.platform_window.bounds();
725 self.window.display_id = self.window.platform_window.display().id();
726 self.refresh();
727
728 self.window
729 .bounds_observers
730 .clone()
731 .retain(&(), |callback| callback(self));
732 }
733
734 /// Returns the bounds of the current window in the global coordinate space, which could span across multiple displays.
735 pub fn window_bounds(&self) -> WindowBounds {
736 self.window.bounds
737 }
738
739 fn appearance_changed(&mut self) {
740 self.window.appearance = self.window.platform_window.appearance();
741
742 self.window
743 .appearance_observers
744 .clone()
745 .retain(&(), |callback| callback(self));
746 }
747
748 /// Returns the appearance of the current window.
749 pub fn appearance(&self) -> WindowAppearance {
750 self.window.appearance
751 }
752
753 /// Returns the size of the drawable area within the window.
754 pub fn viewport_size(&self) -> Size<Pixels> {
755 self.window.viewport_size
756 }
757
758 /// Returns whether this window is focused by the operating system (receiving key events).
759 pub fn is_window_active(&self) -> bool {
760 self.window.active.get()
761 }
762
763 /// Toggle zoom on the window.
764 pub fn zoom_window(&self) {
765 self.window.platform_window.zoom();
766 }
767
768 /// Updates the window's title at the platform level.
769 pub fn set_window_title(&mut self, title: &str) {
770 self.window.platform_window.set_title(title);
771 }
772
773 /// Mark the window as dirty at the platform level.
774 pub fn set_window_edited(&mut self, edited: bool) {
775 self.window.platform_window.set_edited(edited);
776 }
777
778 /// Determine the display on which the window is visible.
779 pub fn display(&self) -> Option<Rc<dyn PlatformDisplay>> {
780 self.platform
781 .displays()
782 .into_iter()
783 .find(|display| display.id() == self.window.display_id)
784 }
785
786 /// Show the platform character palette.
787 pub fn show_character_palette(&self) {
788 self.window.platform_window.show_character_palette();
789 }
790
791 /// The scale factor of the display associated with the window. For example, it could
792 /// return 2.0 for a "retina" display, indicating that each logical pixel should actually
793 /// be rendered as two pixels on screen.
794 pub fn scale_factor(&self) -> f32 {
795 self.window.scale_factor
796 }
797
798 /// The size of an em for the base font of the application. Adjusting this value allows the
799 /// UI to scale, just like zooming a web page.
800 pub fn rem_size(&self) -> Pixels {
801 self.window.rem_size
802 }
803
804 /// Sets the size of an em for the base font of the application. Adjusting this value allows the
805 /// UI to scale, just like zooming a web page.
806 pub fn set_rem_size(&mut self, rem_size: impl Into<Pixels>) {
807 self.window.rem_size = rem_size.into();
808 }
809
810 /// The line height associated with the current text style.
811 pub fn line_height(&self) -> Pixels {
812 let rem_size = self.rem_size();
813 let text_style = self.text_style();
814 text_style
815 .line_height
816 .to_pixels(text_style.font_size, rem_size)
817 }
818
819 /// Call to prevent the default action of an event. Currently only used to prevent
820 /// parent elements from becoming focused on mouse down.
821 pub fn prevent_default(&mut self) {
822 self.window.default_prevented = true;
823 }
824
825 /// Obtain whether default has been prevented for the event currently being dispatched.
826 pub fn default_prevented(&self) -> bool {
827 self.window.default_prevented
828 }
829
830 /// Determine whether the given action is available along the dispatch path to the currently focused element.
831 pub fn is_action_available(&self, action: &dyn Action) -> bool {
832 let target = self
833 .focused()
834 .and_then(|focused_handle| {
835 self.window
836 .rendered_frame
837 .dispatch_tree
838 .focusable_node_id(focused_handle.id)
839 })
840 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
841 self.window
842 .rendered_frame
843 .dispatch_tree
844 .is_action_available(action, target)
845 }
846
847 /// The position of the mouse relative to the window.
848 pub fn mouse_position(&self) -> Point<Pixels> {
849 self.window.mouse_position
850 }
851
852 /// The current state of the keyboard's modifiers
853 pub fn modifiers(&self) -> Modifiers {
854 self.window.modifiers
855 }
856
857 /// Returns true if there is no opaque layer containing the given point
858 /// on top of the given level. Layers who are extensions of the queried layer
859 /// are not considered to be on top of queried layer.
860 pub fn was_top_layer(&self, point: &Point<Pixels>, layer: &StackingOrder) -> bool {
861 // Precondition: the depth map is ordered from topmost to bottomost.
862
863 for (opaque_layer, _, bounds) in self.window.rendered_frame.depth_map.iter() {
864 if layer >= opaque_layer {
865 // The queried layer is either above or is the same as the this opaque layer.
866 // Anything after this point is guaranteed to be below the queried layer.
867 return true;
868 }
869
870 if !bounds.contains(point) {
871 // This opaque layer is above the queried layer but it doesn't contain
872 // the given position, so we can ignore it even if it's above.
873 continue;
874 }
875
876 // At this point, we've established that this opaque layer is on top of the queried layer
877 // and contains the position:
878 // If neither the opaque layer or the queried layer is an extension of the other then
879 // we know they are on different stacking orders, and return false.
880 let is_on_same_layer = opaque_layer
881 .iter()
882 .zip(layer.iter())
883 .all(|(a, b)| a.z_index == b.z_index);
884
885 if !is_on_same_layer {
886 return false;
887 }
888 }
889
890 true
891 }
892
893 pub(crate) fn was_top_layer_under_active_drag(
894 &self,
895 point: &Point<Pixels>,
896 layer: &StackingOrder,
897 ) -> bool {
898 // Precondition: the depth map is ordered from topmost to bottomost.
899
900 for (opaque_layer, _, bounds) in self.window.rendered_frame.depth_map.iter() {
901 if layer >= opaque_layer {
902 // The queried layer is either above or is the same as the this opaque layer.
903 // Anything after this point is guaranteed to be below the queried layer.
904 return true;
905 }
906
907 if !bounds.contains(point) {
908 // This opaque layer is above the queried layer but it doesn't contain
909 // the given position, so we can ignore it even if it's above.
910 continue;
911 }
912
913 // All normal content is rendered with a base z-index of 0, we know that if the root of this opaque layer
914 // equals `ACTIVE_DRAG_Z_INDEX` then it must be the drag layer and we can ignore it as we are
915 // looking to see if the queried layer was the topmost underneath the drag layer.
916 if opaque_layer
917 .first()
918 .map(|c| c.z_index == ACTIVE_DRAG_Z_INDEX)
919 .unwrap_or(false)
920 {
921 continue;
922 }
923
924 // At this point, we've established that this opaque layer is on top of the queried layer
925 // and contains the position:
926 // If neither the opaque layer or the queried layer is an extension of the other then
927 // we know they are on different stacking orders, and return false.
928 let is_on_same_layer = opaque_layer
929 .iter()
930 .zip(layer.iter())
931 .all(|(a, b)| a.z_index == b.z_index);
932
933 if !is_on_same_layer {
934 return false;
935 }
936 }
937
938 true
939 }
940
941 /// Called during painting to get the current stacking order.
942 pub fn stacking_order(&self) -> &StackingOrder {
943 &self.window.next_frame.z_index_stack
944 }
945
946 /// Produces a new frame and assigns it to `rendered_frame`. To actually show
947 /// the contents of the new [Scene], use [present].
948 pub(crate) fn draw(&mut self) {
949 self.window.dirty.set(false);
950 self.window.drawing = true;
951
952 if let Some(requested_handler) = self.window.rendered_frame.requested_input_handler.as_mut()
953 {
954 let input_handler = self.window.platform_window.take_input_handler();
955 requested_handler.handler = input_handler;
956 }
957
958 let root_view = self.window.root_view.take().unwrap();
959 self.with_element_context(|cx| {
960 cx.with_z_index(0, |cx| {
961 cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| {
962 // We need to use cx.cx here so we can utilize borrow splitting
963 for (action_type, action_listeners) in &cx.cx.app.global_action_listeners {
964 for action_listener in action_listeners.iter().cloned() {
965 cx.cx.window.next_frame.dispatch_tree.on_action(
966 *action_type,
967 Rc::new(
968 move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| {
969 action_listener(action, phase, cx)
970 },
971 ),
972 )
973 }
974 }
975
976 let available_space = cx.window.viewport_size.map(Into::into);
977 root_view.draw(Point::default(), available_space, cx);
978 })
979 })
980 });
981
982 if let Some(active_drag) = self.app.active_drag.take() {
983 self.with_element_context(|cx| {
984 cx.with_z_index(ACTIVE_DRAG_Z_INDEX, |cx| {
985 let offset = cx.mouse_position() - active_drag.cursor_offset;
986 let available_space =
987 size(AvailableSpace::MinContent, AvailableSpace::MinContent);
988 active_drag.view.draw(offset, available_space, cx);
989 })
990 });
991 self.active_drag = Some(active_drag);
992 } else if let Some(tooltip_request) = self.window.next_frame.tooltip_request.take() {
993 self.with_element_context(|cx| {
994 cx.with_z_index(1, |cx| {
995 let available_space =
996 size(AvailableSpace::MinContent, AvailableSpace::MinContent);
997 tooltip_request.tooltip.view.draw(
998 tooltip_request.tooltip.cursor_offset,
999 available_space,
1000 cx,
1001 );
1002 })
1003 });
1004 self.window.next_frame.tooltip_request = Some(tooltip_request);
1005 }
1006 self.window.dirty_views.clear();
1007
1008 self.window
1009 .next_frame
1010 .dispatch_tree
1011 .preserve_pending_keystrokes(
1012 &mut self.window.rendered_frame.dispatch_tree,
1013 self.window.focus,
1014 );
1015 self.window.next_frame.focus = self.window.focus;
1016 self.window.next_frame.window_active = self.window.active.get();
1017 self.window.root_view = Some(root_view);
1018
1019 // Set the cursor only if we're the active window.
1020 let cursor_style = self
1021 .window
1022 .next_frame
1023 .requested_cursor_style
1024 .take()
1025 .unwrap_or(CursorStyle::Arrow);
1026 if self.is_window_active() {
1027 self.platform.set_cursor_style(cursor_style);
1028 }
1029
1030 // Register requested input handler with the platform window.
1031 if let Some(requested_input) = self.window.next_frame.requested_input_handler.as_mut() {
1032 if let Some(handler) = requested_input.handler.take() {
1033 self.window.platform_window.set_input_handler(handler);
1034 }
1035 }
1036
1037 self.window.layout_engine.as_mut().unwrap().clear();
1038 self.text_system()
1039 .finish_frame(&self.window.next_frame.reused_views);
1040 self.window
1041 .next_frame
1042 .finish(&mut self.window.rendered_frame);
1043 ELEMENT_ARENA.with_borrow_mut(|element_arena| {
1044 let percentage = (element_arena.len() as f32 / element_arena.capacity() as f32) * 100.;
1045 if percentage >= 80. {
1046 log::warn!("elevated element arena occupation: {}.", percentage);
1047 }
1048 element_arena.clear();
1049 });
1050
1051 let previous_focus_path = self.window.rendered_frame.focus_path();
1052 let previous_window_active = self.window.rendered_frame.window_active;
1053 mem::swap(&mut self.window.rendered_frame, &mut self.window.next_frame);
1054 self.window.next_frame.clear();
1055 let current_focus_path = self.window.rendered_frame.focus_path();
1056 let current_window_active = self.window.rendered_frame.window_active;
1057
1058 if previous_focus_path != current_focus_path
1059 || previous_window_active != current_window_active
1060 {
1061 if !previous_focus_path.is_empty() && current_focus_path.is_empty() {
1062 self.window
1063 .focus_lost_listeners
1064 .clone()
1065 .retain(&(), |listener| listener(self));
1066 }
1067
1068 let event = FocusEvent {
1069 previous_focus_path: if previous_window_active {
1070 previous_focus_path
1071 } else {
1072 Default::default()
1073 },
1074 current_focus_path: if current_window_active {
1075 current_focus_path
1076 } else {
1077 Default::default()
1078 },
1079 };
1080 self.window
1081 .focus_listeners
1082 .clone()
1083 .retain(&(), |listener| listener(&event, self));
1084 }
1085 self.window.refreshing = false;
1086 self.window.drawing = false;
1087 }
1088
1089 fn present(&self) {
1090 self.window
1091 .platform_window
1092 .draw(&self.window.rendered_frame.scene);
1093 }
1094
1095 /// Dispatch a mouse or keyboard event on the window.
1096 pub fn dispatch_event(&mut self, event: PlatformInput) -> bool {
1097 self.window.last_input_timestamp.set(Instant::now());
1098 // Handlers may set this to false by calling `stop_propagation`.
1099 self.app.propagate_event = true;
1100 // Handlers may set this to true by calling `prevent_default`.
1101 self.window.default_prevented = false;
1102
1103 let event = match event {
1104 // Track the mouse position with our own state, since accessing the platform
1105 // API for the mouse position can only occur on the main thread.
1106 PlatformInput::MouseMove(mouse_move) => {
1107 self.window.mouse_position = mouse_move.position;
1108 self.window.modifiers = mouse_move.modifiers;
1109 PlatformInput::MouseMove(mouse_move)
1110 }
1111 PlatformInput::MouseDown(mouse_down) => {
1112 self.window.mouse_position = mouse_down.position;
1113 self.window.modifiers = mouse_down.modifiers;
1114 PlatformInput::MouseDown(mouse_down)
1115 }
1116 PlatformInput::MouseUp(mouse_up) => {
1117 self.window.mouse_position = mouse_up.position;
1118 self.window.modifiers = mouse_up.modifiers;
1119 PlatformInput::MouseUp(mouse_up)
1120 }
1121 PlatformInput::MouseExited(mouse_exited) => {
1122 self.window.modifiers = mouse_exited.modifiers;
1123 PlatformInput::MouseExited(mouse_exited)
1124 }
1125 PlatformInput::ModifiersChanged(modifiers_changed) => {
1126 self.window.modifiers = modifiers_changed.modifiers;
1127 PlatformInput::ModifiersChanged(modifiers_changed)
1128 }
1129 PlatformInput::ScrollWheel(scroll_wheel) => {
1130 self.window.mouse_position = scroll_wheel.position;
1131 self.window.modifiers = scroll_wheel.modifiers;
1132 PlatformInput::ScrollWheel(scroll_wheel)
1133 }
1134 // Translate dragging and dropping of external files from the operating system
1135 // to internal drag and drop events.
1136 PlatformInput::FileDrop(file_drop) => match file_drop {
1137 FileDropEvent::Entered { position, paths } => {
1138 self.window.mouse_position = position;
1139 if self.active_drag.is_none() {
1140 self.active_drag = Some(AnyDrag {
1141 value: Box::new(paths.clone()),
1142 view: self.new_view(|_| paths).into(),
1143 cursor_offset: position,
1144 });
1145 }
1146 PlatformInput::MouseMove(MouseMoveEvent {
1147 position,
1148 pressed_button: Some(MouseButton::Left),
1149 modifiers: Modifiers::default(),
1150 })
1151 }
1152 FileDropEvent::Pending { position } => {
1153 self.window.mouse_position = position;
1154 PlatformInput::MouseMove(MouseMoveEvent {
1155 position,
1156 pressed_button: Some(MouseButton::Left),
1157 modifiers: Modifiers::default(),
1158 })
1159 }
1160 FileDropEvent::Submit { position } => {
1161 self.activate(true);
1162 self.window.mouse_position = position;
1163 PlatformInput::MouseUp(MouseUpEvent {
1164 button: MouseButton::Left,
1165 position,
1166 modifiers: Modifiers::default(),
1167 click_count: 1,
1168 })
1169 }
1170 FileDropEvent::Exited => PlatformInput::MouseUp(MouseUpEvent {
1171 button: MouseButton::Left,
1172 position: Point::default(),
1173 modifiers: Modifiers::default(),
1174 click_count: 1,
1175 }),
1176 },
1177 PlatformInput::KeyDown(_) | PlatformInput::KeyUp(_) => event,
1178 };
1179
1180 if let Some(any_mouse_event) = event.mouse_event() {
1181 self.dispatch_mouse_event(any_mouse_event);
1182 } else if let Some(any_key_event) = event.keyboard_event() {
1183 self.dispatch_key_event(any_key_event);
1184 }
1185
1186 !self.app.propagate_event
1187 }
1188
1189 fn dispatch_mouse_event(&mut self, event: &dyn Any) {
1190 if let Some(mut handlers) = self
1191 .window
1192 .rendered_frame
1193 .mouse_listeners
1194 .remove(&event.type_id())
1195 {
1196 // Because handlers may add other handlers, we sort every time.
1197 handlers.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
1198
1199 // Capture phase, events bubble from back to front. Handlers for this phase are used for
1200 // special purposes, such as detecting events outside of a given Bounds.
1201 for (_, _, handler) in &mut handlers {
1202 self.with_element_context(|cx| {
1203 handler(event, DispatchPhase::Capture, cx);
1204 });
1205 if !self.app.propagate_event {
1206 break;
1207 }
1208 }
1209
1210 // Bubble phase, where most normal handlers do their work.
1211 if self.app.propagate_event {
1212 for (_, _, handler) in handlers.iter_mut().rev() {
1213 self.with_element_context(|cx| {
1214 handler(event, DispatchPhase::Bubble, cx);
1215 });
1216 if !self.app.propagate_event {
1217 break;
1218 }
1219 }
1220 }
1221
1222 self.window
1223 .rendered_frame
1224 .mouse_listeners
1225 .insert(event.type_id(), handlers);
1226 }
1227
1228 if self.app.propagate_event && self.has_active_drag() {
1229 if event.is::<MouseMoveEvent>() {
1230 // If this was a mouse move event, redraw the window so that the
1231 // active drag can follow the mouse cursor.
1232 self.refresh();
1233 } else if event.is::<MouseUpEvent>() {
1234 // If this was a mouse up event, cancel the active drag and redraw
1235 // the window.
1236 self.active_drag = None;
1237 self.refresh();
1238 }
1239 }
1240 }
1241
1242 fn dispatch_key_event(&mut self, event: &dyn Any) {
1243 let node_id = self
1244 .window
1245 .focus
1246 .and_then(|focus_id| {
1247 self.window
1248 .rendered_frame
1249 .dispatch_tree
1250 .focusable_node_id(focus_id)
1251 })
1252 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
1253
1254 let dispatch_path = self
1255 .window
1256 .rendered_frame
1257 .dispatch_tree
1258 .dispatch_path(node_id);
1259
1260 if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
1261 let KeymatchResult { bindings, pending } = self
1262 .window
1263 .rendered_frame
1264 .dispatch_tree
1265 .dispatch_key(&key_down_event.keystroke, &dispatch_path);
1266
1267 if pending {
1268 let mut currently_pending = self.window.pending_input.take().unwrap_or_default();
1269 if currently_pending.focus.is_some() && currently_pending.focus != self.window.focus
1270 {
1271 currently_pending = PendingInput::default();
1272 }
1273 currently_pending.focus = self.window.focus;
1274 currently_pending
1275 .keystrokes
1276 .push(key_down_event.keystroke.clone());
1277 for binding in bindings {
1278 currently_pending.bindings.push(binding);
1279 }
1280
1281 currently_pending.timer = Some(self.spawn(|mut cx| async move {
1282 cx.background_executor.timer(Duration::from_secs(1)).await;
1283 cx.update(move |cx| {
1284 cx.clear_pending_keystrokes();
1285 let Some(currently_pending) = cx.window.pending_input.take() else {
1286 return;
1287 };
1288 cx.replay_pending_input(currently_pending)
1289 })
1290 .log_err();
1291 }));
1292 self.window.pending_input = Some(currently_pending);
1293
1294 self.propagate_event = false;
1295 return;
1296 } else if let Some(currently_pending) = self.window.pending_input.take() {
1297 if bindings
1298 .iter()
1299 .all(|binding| !currently_pending.used_by_binding(binding))
1300 {
1301 self.replay_pending_input(currently_pending)
1302 }
1303 }
1304
1305 if !bindings.is_empty() {
1306 self.clear_pending_keystrokes();
1307 }
1308
1309 self.propagate_event = true;
1310 for binding in bindings {
1311 self.dispatch_action_on_node(node_id, binding.action.boxed_clone());
1312 if !self.propagate_event {
1313 self.dispatch_keystroke_observers(event, Some(binding.action));
1314 return;
1315 }
1316 }
1317 }
1318
1319 self.dispatch_key_down_up_event(event, &dispatch_path);
1320 if !self.propagate_event {
1321 return;
1322 }
1323
1324 self.dispatch_keystroke_observers(event, None);
1325 }
1326
1327 fn dispatch_key_down_up_event(
1328 &mut self,
1329 event: &dyn Any,
1330 dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
1331 ) {
1332 // Capture phase
1333 for node_id in dispatch_path {
1334 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1335
1336 for key_listener in node.key_listeners.clone() {
1337 self.with_element_context(|cx| {
1338 key_listener(event, DispatchPhase::Capture, cx);
1339 });
1340 if !self.propagate_event {
1341 return;
1342 }
1343 }
1344 }
1345
1346 // Bubble phase
1347 for node_id in dispatch_path.iter().rev() {
1348 // Handle low level key events
1349 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1350 for key_listener in node.key_listeners.clone() {
1351 self.with_element_context(|cx| {
1352 key_listener(event, DispatchPhase::Bubble, cx);
1353 });
1354 if !self.propagate_event {
1355 return;
1356 }
1357 }
1358 }
1359 }
1360
1361 /// Determine whether a potential multi-stroke key binding is in progress on this window.
1362 pub fn has_pending_keystrokes(&self) -> bool {
1363 self.window
1364 .rendered_frame
1365 .dispatch_tree
1366 .has_pending_keystrokes()
1367 }
1368
1369 fn replay_pending_input(&mut self, currently_pending: PendingInput) {
1370 let node_id = self
1371 .window
1372 .focus
1373 .and_then(|focus_id| {
1374 self.window
1375 .rendered_frame
1376 .dispatch_tree
1377 .focusable_node_id(focus_id)
1378 })
1379 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
1380
1381 if self.window.focus != currently_pending.focus {
1382 return;
1383 }
1384
1385 let input = currently_pending.input();
1386
1387 self.propagate_event = true;
1388 for binding in currently_pending.bindings {
1389 self.dispatch_action_on_node(node_id, binding.action.boxed_clone());
1390 if !self.propagate_event {
1391 return;
1392 }
1393 }
1394
1395 let dispatch_path = self
1396 .window
1397 .rendered_frame
1398 .dispatch_tree
1399 .dispatch_path(node_id);
1400
1401 for keystroke in currently_pending.keystrokes {
1402 let event = KeyDownEvent {
1403 keystroke,
1404 is_held: false,
1405 };
1406
1407 self.dispatch_key_down_up_event(&event, &dispatch_path);
1408 if !self.propagate_event {
1409 return;
1410 }
1411 }
1412
1413 if !input.is_empty() {
1414 if let Some(mut input_handler) = self.window.platform_window.take_input_handler() {
1415 input_handler.flush_pending_input(&input, self);
1416 self.window.platform_window.set_input_handler(input_handler)
1417 }
1418 }
1419 }
1420
1421 fn dispatch_action_on_node(&mut self, node_id: DispatchNodeId, action: Box<dyn Action>) {
1422 let dispatch_path = self
1423 .window
1424 .rendered_frame
1425 .dispatch_tree
1426 .dispatch_path(node_id);
1427
1428 // Capture phase
1429 for node_id in &dispatch_path {
1430 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1431 for DispatchActionListener {
1432 action_type,
1433 listener,
1434 } in node.action_listeners.clone()
1435 {
1436 let any_action = action.as_any();
1437 if action_type == any_action.type_id() {
1438 self.with_element_context(|cx| {
1439 listener(any_action, DispatchPhase::Capture, cx);
1440 });
1441
1442 if !self.propagate_event {
1443 return;
1444 }
1445 }
1446 }
1447 }
1448 // Bubble phase
1449 for node_id in dispatch_path.iter().rev() {
1450 let node = self.window.rendered_frame.dispatch_tree.node(*node_id);
1451 for DispatchActionListener {
1452 action_type,
1453 listener,
1454 } in node.action_listeners.clone()
1455 {
1456 let any_action = action.as_any();
1457 if action_type == any_action.type_id() {
1458 self.propagate_event = false; // Actions stop propagation by default during the bubble phase
1459
1460 self.with_element_context(|cx| {
1461 listener(any_action, DispatchPhase::Bubble, cx);
1462 });
1463
1464 if !self.propagate_event {
1465 return;
1466 }
1467 }
1468 }
1469 }
1470 }
1471
1472 /// Toggle the graphics profiler to debug your application's rendering performance.
1473 pub fn toggle_graphics_profiler(&mut self) {
1474 self.window.graphics_profiler_enabled = !self.window.graphics_profiler_enabled;
1475 self.window
1476 .platform_window
1477 .set_graphics_profiler_enabled(self.window.graphics_profiler_enabled);
1478 }
1479
1480 /// Register the given handler to be invoked whenever the global of the given type
1481 /// is updated.
1482 pub fn observe_global<G: Global>(
1483 &mut self,
1484 f: impl Fn(&mut WindowContext<'_>) + 'static,
1485 ) -> Subscription {
1486 let window_handle = self.window.handle;
1487 let (subscription, activate) = self.global_observers.insert(
1488 TypeId::of::<G>(),
1489 Box::new(move |cx| window_handle.update(cx, |_, cx| f(cx)).is_ok()),
1490 );
1491 self.app.defer(move |_| activate());
1492 subscription
1493 }
1494
1495 /// Focus the current window and bring it to the foreground at the platform level.
1496 pub fn activate_window(&self) {
1497 self.window.platform_window.activate();
1498 }
1499
1500 /// Minimize the current window at the platform level.
1501 pub fn minimize_window(&self) {
1502 self.window.platform_window.minimize();
1503 }
1504
1505 /// Toggle full screen status on the current window at the platform level.
1506 pub fn toggle_full_screen(&self) {
1507 self.window.platform_window.toggle_full_screen();
1508 }
1509
1510 /// Present a platform dialog.
1511 /// The provided message will be presented, along with buttons for each answer.
1512 /// When a button is clicked, the returned Receiver will receive the index of the clicked button.
1513 pub fn prompt(
1514 &self,
1515 level: PromptLevel,
1516 message: &str,
1517 detail: Option<&str>,
1518 answers: &[&str],
1519 ) -> oneshot::Receiver<usize> {
1520 self.window
1521 .platform_window
1522 .prompt(level, message, detail, answers)
1523 }
1524
1525 /// Returns all available actions for the focused element.
1526 pub fn available_actions(&self) -> Vec<Box<dyn Action>> {
1527 let node_id = self
1528 .window
1529 .focus
1530 .and_then(|focus_id| {
1531 self.window
1532 .rendered_frame
1533 .dispatch_tree
1534 .focusable_node_id(focus_id)
1535 })
1536 .unwrap_or_else(|| self.window.rendered_frame.dispatch_tree.root_node_id());
1537
1538 self.window
1539 .rendered_frame
1540 .dispatch_tree
1541 .available_actions(node_id)
1542 }
1543
1544 /// Returns key bindings that invoke the given action on the currently focused element.
1545 pub fn bindings_for_action(&self, action: &dyn Action) -> Vec<KeyBinding> {
1546 self.window
1547 .rendered_frame
1548 .dispatch_tree
1549 .bindings_for_action(
1550 action,
1551 &self.window.rendered_frame.dispatch_tree.context_stack,
1552 )
1553 }
1554
1555 /// Returns any bindings that would invoke the given action on the given focus handle if it were focused.
1556 pub fn bindings_for_action_in(
1557 &self,
1558 action: &dyn Action,
1559 focus_handle: &FocusHandle,
1560 ) -> Vec<KeyBinding> {
1561 let dispatch_tree = &self.window.rendered_frame.dispatch_tree;
1562
1563 let Some(node_id) = dispatch_tree.focusable_node_id(focus_handle.id) else {
1564 return vec![];
1565 };
1566 let context_stack: Vec<_> = dispatch_tree
1567 .dispatch_path(node_id)
1568 .into_iter()
1569 .filter_map(|node_id| dispatch_tree.node(node_id).context.clone())
1570 .collect();
1571 dispatch_tree.bindings_for_action(action, &context_stack)
1572 }
1573
1574 /// Returns a generic event listener that invokes the given listener with the view and context associated with the given view handle.
1575 pub fn listener_for<V: Render, E>(
1576 &self,
1577 view: &View<V>,
1578 f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
1579 ) -> impl Fn(&E, &mut WindowContext) + 'static {
1580 let view = view.downgrade();
1581 move |e: &E, cx: &mut WindowContext| {
1582 view.update(cx, |view, cx| f(view, e, cx)).ok();
1583 }
1584 }
1585
1586 /// Returns a generic handler that invokes the given handler with the view and context associated with the given view handle.
1587 pub fn handler_for<V: Render>(
1588 &self,
1589 view: &View<V>,
1590 f: impl Fn(&mut V, &mut ViewContext<V>) + 'static,
1591 ) -> impl Fn(&mut WindowContext) {
1592 let view = view.downgrade();
1593 move |cx: &mut WindowContext| {
1594 view.update(cx, |view, cx| f(view, cx)).ok();
1595 }
1596 }
1597
1598 /// Register a callback that can interrupt the closing of the current window based the returned boolean.
1599 /// If the callback returns false, the window won't be closed.
1600 pub fn on_window_should_close(&mut self, f: impl Fn(&mut WindowContext) -> bool + 'static) {
1601 let mut this = self.to_async();
1602 self.window
1603 .platform_window
1604 .on_should_close(Box::new(move || this.update(|cx| f(cx)).unwrap_or(true)))
1605 }
1606
1607 pub(crate) fn parent_view_id(&self) -> EntityId {
1608 *self
1609 .window
1610 .next_frame
1611 .view_stack
1612 .last()
1613 .expect("a view should always be on the stack while drawing")
1614 }
1615
1616 /// Register an action listener on the window for the next frame. The type of action
1617 /// is determined by the first parameter of the given listener. When the next frame is rendered
1618 /// the listener will be cleared.
1619 ///
1620 /// This is a fairly low-level method, so prefer using action handlers on elements unless you have
1621 /// a specific need to register a global listener.
1622 pub fn on_action(
1623 &mut self,
1624 action_type: TypeId,
1625 listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static,
1626 ) {
1627 self.window
1628 .next_frame
1629 .dispatch_tree
1630 .on_action(action_type, Rc::new(listener));
1631 }
1632}
1633
1634impl Context for WindowContext<'_> {
1635 type Result<T> = T;
1636
1637 fn new_model<T>(&mut self, build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T) -> Model<T>
1638 where
1639 T: 'static,
1640 {
1641 let slot = self.app.entities.reserve();
1642 let model = build_model(&mut ModelContext::new(&mut *self.app, slot.downgrade()));
1643 self.entities.insert(slot, model)
1644 }
1645
1646 fn update_model<T: 'static, R>(
1647 &mut self,
1648 model: &Model<T>,
1649 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
1650 ) -> R {
1651 let mut entity = self.entities.lease(model);
1652 let result = update(
1653 &mut *entity,
1654 &mut ModelContext::new(&mut *self.app, model.downgrade()),
1655 );
1656 self.entities.end_lease(entity);
1657 result
1658 }
1659
1660 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
1661 where
1662 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
1663 {
1664 if window == self.window.handle {
1665 let root_view = self.window.root_view.clone().unwrap();
1666 Ok(update(root_view, self))
1667 } else {
1668 window.update(self.app, update)
1669 }
1670 }
1671
1672 fn read_model<T, R>(
1673 &self,
1674 handle: &Model<T>,
1675 read: impl FnOnce(&T, &AppContext) -> R,
1676 ) -> Self::Result<R>
1677 where
1678 T: 'static,
1679 {
1680 let entity = self.entities.read(handle);
1681 read(entity, &*self.app)
1682 }
1683
1684 fn read_window<T, R>(
1685 &self,
1686 window: &WindowHandle<T>,
1687 read: impl FnOnce(View<T>, &AppContext) -> R,
1688 ) -> Result<R>
1689 where
1690 T: 'static,
1691 {
1692 if window.any_handle == self.window.handle {
1693 let root_view = self
1694 .window
1695 .root_view
1696 .clone()
1697 .unwrap()
1698 .downcast::<T>()
1699 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
1700 Ok(read(root_view, self))
1701 } else {
1702 self.app.read_window(window, read)
1703 }
1704 }
1705}
1706
1707impl VisualContext for WindowContext<'_> {
1708 fn new_view<V>(
1709 &mut self,
1710 build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
1711 ) -> Self::Result<View<V>>
1712 where
1713 V: 'static + Render,
1714 {
1715 let slot = self.app.entities.reserve();
1716 let view = View {
1717 model: slot.clone(),
1718 };
1719 let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, &view);
1720 let entity = build_view_state(&mut cx);
1721 cx.entities.insert(slot, entity);
1722
1723 // Non-generic part to avoid leaking SubscriberSet to invokers of `new_view`.
1724 fn notify_observers(cx: &mut WindowContext, tid: TypeId, view: AnyView) {
1725 cx.new_view_observers.clone().retain(&tid, |observer| {
1726 let any_view = view.clone();
1727 (observer)(any_view, cx);
1728 true
1729 });
1730 }
1731 notify_observers(self, TypeId::of::<V>(), AnyView::from(view.clone()));
1732
1733 view
1734 }
1735
1736 /// Updates the given view. Prefer calling [`View::update`] instead, which calls this method.
1737 fn update_view<T: 'static, R>(
1738 &mut self,
1739 view: &View<T>,
1740 update: impl FnOnce(&mut T, &mut ViewContext<'_, T>) -> R,
1741 ) -> Self::Result<R> {
1742 let mut lease = self.app.entities.lease(&view.model);
1743 let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, view);
1744 let result = update(&mut *lease, &mut cx);
1745 cx.app.entities.end_lease(lease);
1746 result
1747 }
1748
1749 fn replace_root_view<V>(
1750 &mut self,
1751 build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
1752 ) -> Self::Result<View<V>>
1753 where
1754 V: 'static + Render,
1755 {
1756 let view = self.new_view(build_view);
1757 self.window.root_view = Some(view.clone().into());
1758 self.refresh();
1759 view
1760 }
1761
1762 fn focus_view<V: crate::FocusableView>(&mut self, view: &View<V>) -> Self::Result<()> {
1763 self.update_view(view, |view, cx| {
1764 view.focus_handle(cx).clone().focus(cx);
1765 })
1766 }
1767
1768 fn dismiss_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
1769 where
1770 V: ManagedView,
1771 {
1772 self.update_view(view, |_, cx| cx.emit(DismissEvent))
1773 }
1774}
1775
1776impl<'a> std::ops::Deref for WindowContext<'a> {
1777 type Target = AppContext;
1778
1779 fn deref(&self) -> &Self::Target {
1780 self.app
1781 }
1782}
1783
1784impl<'a> std::ops::DerefMut for WindowContext<'a> {
1785 fn deref_mut(&mut self) -> &mut Self::Target {
1786 self.app
1787 }
1788}
1789
1790impl<'a> Borrow<AppContext> for WindowContext<'a> {
1791 fn borrow(&self) -> &AppContext {
1792 self.app
1793 }
1794}
1795
1796impl<'a> BorrowMut<AppContext> for WindowContext<'a> {
1797 fn borrow_mut(&mut self) -> &mut AppContext {
1798 self.app
1799 }
1800}
1801
1802/// This trait contains functionality that is shared across [`ViewContext`] and [`WindowContext`]
1803pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
1804 #[doc(hidden)]
1805 fn app_mut(&mut self) -> &mut AppContext {
1806 self.borrow_mut()
1807 }
1808
1809 #[doc(hidden)]
1810 fn app(&self) -> &AppContext {
1811 self.borrow()
1812 }
1813
1814 #[doc(hidden)]
1815 fn window(&self) -> &Window {
1816 self.borrow()
1817 }
1818
1819 #[doc(hidden)]
1820 fn window_mut(&mut self) -> &mut Window {
1821 self.borrow_mut()
1822 }
1823}
1824
1825impl Borrow<Window> for WindowContext<'_> {
1826 fn borrow(&self) -> &Window {
1827 self.window
1828 }
1829}
1830
1831impl BorrowMut<Window> for WindowContext<'_> {
1832 fn borrow_mut(&mut self) -> &mut Window {
1833 self.window
1834 }
1835}
1836
1837impl<T> BorrowWindow for T where T: BorrowMut<AppContext> + BorrowMut<Window> {}
1838
1839/// Provides access to application state that is specialized for a particular [`View`].
1840/// Allows you to interact with focus, emit events, etc.
1841/// ViewContext also derefs to [`WindowContext`], giving you access to all of its methods as well.
1842/// When you call [`View::update`], you're passed a `&mut V` and an `&mut ViewContext<V>`.
1843pub struct ViewContext<'a, V> {
1844 window_cx: WindowContext<'a>,
1845 view: &'a View<V>,
1846}
1847
1848impl<V> Borrow<AppContext> for ViewContext<'_, V> {
1849 fn borrow(&self) -> &AppContext {
1850 &*self.window_cx.app
1851 }
1852}
1853
1854impl<V> BorrowMut<AppContext> for ViewContext<'_, V> {
1855 fn borrow_mut(&mut self) -> &mut AppContext {
1856 &mut *self.window_cx.app
1857 }
1858}
1859
1860impl<V> Borrow<Window> for ViewContext<'_, V> {
1861 fn borrow(&self) -> &Window {
1862 &*self.window_cx.window
1863 }
1864}
1865
1866impl<V> BorrowMut<Window> for ViewContext<'_, V> {
1867 fn borrow_mut(&mut self) -> &mut Window {
1868 &mut *self.window_cx.window
1869 }
1870}
1871
1872impl<'a, V: 'static> ViewContext<'a, V> {
1873 pub(crate) fn new(app: &'a mut AppContext, window: &'a mut Window, view: &'a View<V>) -> Self {
1874 Self {
1875 window_cx: WindowContext::new(app, window),
1876 view,
1877 }
1878 }
1879
1880 /// Get the entity_id of this view.
1881 pub fn entity_id(&self) -> EntityId {
1882 self.view.entity_id()
1883 }
1884
1885 /// Get the view pointer underlying this context.
1886 pub fn view(&self) -> &View<V> {
1887 self.view
1888 }
1889
1890 /// Get the model underlying this view.
1891 pub fn model(&self) -> &Model<V> {
1892 &self.view.model
1893 }
1894
1895 /// Access the underlying window context.
1896 pub fn window_context(&mut self) -> &mut WindowContext<'a> {
1897 &mut self.window_cx
1898 }
1899
1900 /// Sets a given callback to be run on the next frame.
1901 pub fn on_next_frame(&mut self, f: impl FnOnce(&mut V, &mut ViewContext<V>) + 'static)
1902 where
1903 V: 'static,
1904 {
1905 let view = self.view().clone();
1906 self.window_cx.on_next_frame(move |cx| view.update(cx, f));
1907 }
1908
1909 /// Schedules the given function to be run at the end of the current effect cycle, allowing entities
1910 /// that are currently on the stack to be returned to the app.
1911 pub fn defer(&mut self, f: impl FnOnce(&mut V, &mut ViewContext<V>) + 'static) {
1912 let view = self.view().downgrade();
1913 self.window_cx.defer(move |cx| {
1914 view.update(cx, f).ok();
1915 });
1916 }
1917
1918 /// Observe another model or view for changes to its state, as tracked by [`ModelContext::notify`].
1919 pub fn observe<V2, E>(
1920 &mut self,
1921 entity: &E,
1922 mut on_notify: impl FnMut(&mut V, E, &mut ViewContext<'_, V>) + 'static,
1923 ) -> Subscription
1924 where
1925 V2: 'static,
1926 V: 'static,
1927 E: Entity<V2>,
1928 {
1929 let view = self.view().downgrade();
1930 let entity_id = entity.entity_id();
1931 let entity = entity.downgrade();
1932 let window_handle = self.window.handle;
1933 self.app.new_observer(
1934 entity_id,
1935 Box::new(move |cx| {
1936 window_handle
1937 .update(cx, |_, cx| {
1938 if let Some(handle) = E::upgrade_from(&entity) {
1939 view.update(cx, |this, cx| on_notify(this, handle, cx))
1940 .is_ok()
1941 } else {
1942 false
1943 }
1944 })
1945 .unwrap_or(false)
1946 }),
1947 )
1948 }
1949
1950 /// Subscribe to events emitted by another model or view.
1951 /// The entity to which you're subscribing must implement the [`EventEmitter`] trait.
1952 /// 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.
1953 pub fn subscribe<V2, E, Evt>(
1954 &mut self,
1955 entity: &E,
1956 mut on_event: impl FnMut(&mut V, E, &Evt, &mut ViewContext<'_, V>) + 'static,
1957 ) -> Subscription
1958 where
1959 V2: EventEmitter<Evt>,
1960 E: Entity<V2>,
1961 Evt: 'static,
1962 {
1963 let view = self.view().downgrade();
1964 let entity_id = entity.entity_id();
1965 let handle = entity.downgrade();
1966 let window_handle = self.window.handle;
1967 self.app.new_subscription(
1968 entity_id,
1969 (
1970 TypeId::of::<Evt>(),
1971 Box::new(move |event, cx| {
1972 window_handle
1973 .update(cx, |_, cx| {
1974 if let Some(handle) = E::upgrade_from(&handle) {
1975 let event = event.downcast_ref().expect("invalid event type");
1976 view.update(cx, |this, cx| on_event(this, handle, event, cx))
1977 .is_ok()
1978 } else {
1979 false
1980 }
1981 })
1982 .unwrap_or(false)
1983 }),
1984 ),
1985 )
1986 }
1987
1988 /// Register a callback to be invoked when the view is released.
1989 ///
1990 /// The callback receives a handle to the view's window. This handle may be
1991 /// invalid, if the window was closed before the view was released.
1992 pub fn on_release(
1993 &mut self,
1994 on_release: impl FnOnce(&mut V, AnyWindowHandle, &mut AppContext) + 'static,
1995 ) -> Subscription {
1996 let window_handle = self.window.handle;
1997 let (subscription, activate) = self.app.release_listeners.insert(
1998 self.view.model.entity_id,
1999 Box::new(move |this, cx| {
2000 let this = this.downcast_mut().expect("invalid entity type");
2001 on_release(this, window_handle, cx)
2002 }),
2003 );
2004 activate();
2005 subscription
2006 }
2007
2008 /// Register a callback to be invoked when the given Model or View is released.
2009 pub fn observe_release<V2, E>(
2010 &mut self,
2011 entity: &E,
2012 mut on_release: impl FnMut(&mut V, &mut V2, &mut ViewContext<'_, V>) + 'static,
2013 ) -> Subscription
2014 where
2015 V: 'static,
2016 V2: 'static,
2017 E: Entity<V2>,
2018 {
2019 let view = self.view().downgrade();
2020 let entity_id = entity.entity_id();
2021 let window_handle = self.window.handle;
2022 let (subscription, activate) = self.app.release_listeners.insert(
2023 entity_id,
2024 Box::new(move |entity, cx| {
2025 let entity = entity.downcast_mut().expect("invalid entity type");
2026 let _ = window_handle.update(cx, |_, cx| {
2027 view.update(cx, |this, cx| on_release(this, entity, cx))
2028 });
2029 }),
2030 );
2031 activate();
2032 subscription
2033 }
2034
2035 /// Indicate that this view has changed, which will invoke any observers and also mark the window as dirty.
2036 /// If this view or any of its ancestors are *cached*, notifying it will cause it or its ancestors to be redrawn.
2037 pub fn notify(&mut self) {
2038 for view_id in self
2039 .window
2040 .rendered_frame
2041 .dispatch_tree
2042 .view_path(self.view.entity_id())
2043 .into_iter()
2044 .rev()
2045 {
2046 if !self.window.dirty_views.insert(view_id) {
2047 break;
2048 }
2049 }
2050
2051 if !self.window.drawing {
2052 self.window_cx.window.dirty.set(true);
2053 self.window_cx.app.push_effect(Effect::Notify {
2054 emitter: self.view.model.entity_id,
2055 });
2056 }
2057 }
2058
2059 /// Register a callback to be invoked when the window is resized.
2060 pub fn observe_window_bounds(
2061 &mut self,
2062 mut callback: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2063 ) -> Subscription {
2064 let view = self.view.downgrade();
2065 let (subscription, activate) = self.window.bounds_observers.insert(
2066 (),
2067 Box::new(move |cx| view.update(cx, |view, cx| callback(view, cx)).is_ok()),
2068 );
2069 activate();
2070 subscription
2071 }
2072
2073 /// Register a callback to be invoked when the window is activated or deactivated.
2074 pub fn observe_window_activation(
2075 &mut self,
2076 mut callback: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2077 ) -> Subscription {
2078 let view = self.view.downgrade();
2079 let (subscription, activate) = self.window.activation_observers.insert(
2080 (),
2081 Box::new(move |cx| view.update(cx, |view, cx| callback(view, cx)).is_ok()),
2082 );
2083 activate();
2084 subscription
2085 }
2086
2087 /// Registers a callback to be invoked when the window appearance changes.
2088 pub fn observe_window_appearance(
2089 &mut self,
2090 mut callback: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2091 ) -> Subscription {
2092 let view = self.view.downgrade();
2093 let (subscription, activate) = self.window.appearance_observers.insert(
2094 (),
2095 Box::new(move |cx| view.update(cx, |view, cx| callback(view, cx)).is_ok()),
2096 );
2097 activate();
2098 subscription
2099 }
2100
2101 /// Register a listener to be called when the given focus handle receives focus.
2102 /// Returns a subscription and persists until the subscription is dropped.
2103 pub fn on_focus(
2104 &mut self,
2105 handle: &FocusHandle,
2106 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2107 ) -> Subscription {
2108 let view = self.view.downgrade();
2109 let focus_id = handle.id;
2110 let (subscription, activate) =
2111 self.window.new_focus_listener(Box::new(move |event, cx| {
2112 view.update(cx, |view, cx| {
2113 if event.previous_focus_path.last() != Some(&focus_id)
2114 && event.current_focus_path.last() == Some(&focus_id)
2115 {
2116 listener(view, cx)
2117 }
2118 })
2119 .is_ok()
2120 }));
2121 self.app.defer(|_| activate());
2122 subscription
2123 }
2124
2125 /// Register a listener to be called when the given focus handle or one of its descendants receives focus.
2126 /// Returns a subscription and persists until the subscription is dropped.
2127 pub fn on_focus_in(
2128 &mut self,
2129 handle: &FocusHandle,
2130 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2131 ) -> Subscription {
2132 let view = self.view.downgrade();
2133 let focus_id = handle.id;
2134 let (subscription, activate) =
2135 self.window.new_focus_listener(Box::new(move |event, cx| {
2136 view.update(cx, |view, cx| {
2137 if !event.previous_focus_path.contains(&focus_id)
2138 && event.current_focus_path.contains(&focus_id)
2139 {
2140 listener(view, cx)
2141 }
2142 })
2143 .is_ok()
2144 }));
2145 self.app.defer(move |_| activate());
2146 subscription
2147 }
2148
2149 /// Register a listener to be called when the given focus handle loses focus.
2150 /// Returns a subscription and persists until the subscription is dropped.
2151 pub fn on_blur(
2152 &mut self,
2153 handle: &FocusHandle,
2154 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2155 ) -> Subscription {
2156 let view = self.view.downgrade();
2157 let focus_id = handle.id;
2158 let (subscription, activate) =
2159 self.window.new_focus_listener(Box::new(move |event, cx| {
2160 view.update(cx, |view, cx| {
2161 if event.previous_focus_path.last() == Some(&focus_id)
2162 && event.current_focus_path.last() != Some(&focus_id)
2163 {
2164 listener(view, cx)
2165 }
2166 })
2167 .is_ok()
2168 }));
2169 self.app.defer(move |_| activate());
2170 subscription
2171 }
2172
2173 /// Register a listener to be called when nothing in the window has focus.
2174 /// This typically happens when the node that was focused is removed from the tree,
2175 /// and this callback lets you chose a default place to restore the users focus.
2176 /// Returns a subscription and persists until the subscription is dropped.
2177 pub fn on_focus_lost(
2178 &mut self,
2179 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2180 ) -> Subscription {
2181 let view = self.view.downgrade();
2182 let (subscription, activate) = self.window.focus_lost_listeners.insert(
2183 (),
2184 Box::new(move |cx| view.update(cx, |view, cx| listener(view, cx)).is_ok()),
2185 );
2186 activate();
2187 subscription
2188 }
2189
2190 /// Register a listener to be called when the given focus handle or one of its descendants loses focus.
2191 /// Returns a subscription and persists until the subscription is dropped.
2192 pub fn on_focus_out(
2193 &mut self,
2194 handle: &FocusHandle,
2195 mut listener: impl FnMut(&mut V, &mut ViewContext<V>) + 'static,
2196 ) -> Subscription {
2197 let view = self.view.downgrade();
2198 let focus_id = handle.id;
2199 let (subscription, activate) =
2200 self.window.new_focus_listener(Box::new(move |event, cx| {
2201 view.update(cx, |view, cx| {
2202 if event.previous_focus_path.contains(&focus_id)
2203 && !event.current_focus_path.contains(&focus_id)
2204 {
2205 listener(view, cx)
2206 }
2207 })
2208 .is_ok()
2209 }));
2210 self.app.defer(move |_| activate());
2211 subscription
2212 }
2213
2214 /// Schedule a future to be run asynchronously.
2215 /// The given callback is invoked with a [`WeakView<V>`] to avoid leaking the view for a long-running process.
2216 /// It's also given an [`AsyncWindowContext`], which can be used to access the state of the view across await points.
2217 /// The returned future will be polled on the main thread.
2218 pub fn spawn<Fut, R>(
2219 &mut self,
2220 f: impl FnOnce(WeakView<V>, AsyncWindowContext) -> Fut,
2221 ) -> Task<R>
2222 where
2223 R: 'static,
2224 Fut: Future<Output = R> + 'static,
2225 {
2226 let view = self.view().downgrade();
2227 self.window_cx.spawn(|cx| f(view, cx))
2228 }
2229
2230 /// Updates the global state of the given type.
2231 pub fn update_global<G, R>(&mut self, f: impl FnOnce(&mut G, &mut Self) -> R) -> R
2232 where
2233 G: Global,
2234 {
2235 let mut global = self.app.lease_global::<G>();
2236 let result = f(&mut global, self);
2237 self.app.end_global_lease(global);
2238 result
2239 }
2240
2241 /// Register a callback to be invoked when the given global state changes.
2242 pub fn observe_global<G: Global>(
2243 &mut self,
2244 mut f: impl FnMut(&mut V, &mut ViewContext<'_, V>) + 'static,
2245 ) -> Subscription {
2246 let window_handle = self.window.handle;
2247 let view = self.view().downgrade();
2248 let (subscription, activate) = self.global_observers.insert(
2249 TypeId::of::<G>(),
2250 Box::new(move |cx| {
2251 window_handle
2252 .update(cx, |_, cx| view.update(cx, |view, cx| f(view, cx)).is_ok())
2253 .unwrap_or(false)
2254 }),
2255 );
2256 self.app.defer(move |_| activate());
2257 subscription
2258 }
2259
2260 /// Register a callback to be invoked when the given Action type is dispatched to the window.
2261 pub fn on_action(
2262 &mut self,
2263 action_type: TypeId,
2264 listener: impl Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext<V>) + 'static,
2265 ) {
2266 let handle = self.view().clone();
2267 self.window_cx
2268 .on_action(action_type, move |action, phase, cx| {
2269 handle.update(cx, |view, cx| {
2270 listener(view, action, phase, cx);
2271 })
2272 });
2273 }
2274
2275 /// Emit an event to be handled any other views that have subscribed via [ViewContext::subscribe].
2276 pub fn emit<Evt>(&mut self, event: Evt)
2277 where
2278 Evt: 'static,
2279 V: EventEmitter<Evt>,
2280 {
2281 let emitter = self.view.model.entity_id;
2282 self.app.push_effect(Effect::Emit {
2283 emitter,
2284 event_type: TypeId::of::<Evt>(),
2285 event: Box::new(event),
2286 });
2287 }
2288
2289 /// Move focus to the current view, assuming it implements [`FocusableView`].
2290 pub fn focus_self(&mut self)
2291 where
2292 V: FocusableView,
2293 {
2294 self.defer(|view, cx| view.focus_handle(cx).focus(cx))
2295 }
2296
2297 /// Convenience method for accessing view state in an event callback.
2298 ///
2299 /// Many GPUI callbacks take the form of `Fn(&E, &mut WindowContext)`,
2300 /// but it's often useful to be able to access view state in these
2301 /// callbacks. This method provides a convenient way to do so.
2302 pub fn listener<E>(
2303 &self,
2304 f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
2305 ) -> impl Fn(&E, &mut WindowContext) + 'static {
2306 let view = self.view().downgrade();
2307 move |e: &E, cx: &mut WindowContext| {
2308 view.update(cx, |view, cx| f(view, e, cx)).ok();
2309 }
2310 }
2311}
2312
2313impl<V> Context for ViewContext<'_, V> {
2314 type Result<U> = U;
2315
2316 fn new_model<T: 'static>(
2317 &mut self,
2318 build_model: impl FnOnce(&mut ModelContext<'_, T>) -> T,
2319 ) -> Model<T> {
2320 self.window_cx.new_model(build_model)
2321 }
2322
2323 fn update_model<T: 'static, R>(
2324 &mut self,
2325 model: &Model<T>,
2326 update: impl FnOnce(&mut T, &mut ModelContext<'_, T>) -> R,
2327 ) -> R {
2328 self.window_cx.update_model(model, update)
2329 }
2330
2331 fn update_window<T, F>(&mut self, window: AnyWindowHandle, update: F) -> Result<T>
2332 where
2333 F: FnOnce(AnyView, &mut WindowContext<'_>) -> T,
2334 {
2335 self.window_cx.update_window(window, update)
2336 }
2337
2338 fn read_model<T, R>(
2339 &self,
2340 handle: &Model<T>,
2341 read: impl FnOnce(&T, &AppContext) -> R,
2342 ) -> Self::Result<R>
2343 where
2344 T: 'static,
2345 {
2346 self.window_cx.read_model(handle, read)
2347 }
2348
2349 fn read_window<T, R>(
2350 &self,
2351 window: &WindowHandle<T>,
2352 read: impl FnOnce(View<T>, &AppContext) -> R,
2353 ) -> Result<R>
2354 where
2355 T: 'static,
2356 {
2357 self.window_cx.read_window(window, read)
2358 }
2359}
2360
2361impl<V: 'static> VisualContext for ViewContext<'_, V> {
2362 fn new_view<W: Render + 'static>(
2363 &mut self,
2364 build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W,
2365 ) -> Self::Result<View<W>> {
2366 self.window_cx.new_view(build_view_state)
2367 }
2368
2369 fn update_view<V2: 'static, R>(
2370 &mut self,
2371 view: &View<V2>,
2372 update: impl FnOnce(&mut V2, &mut ViewContext<'_, V2>) -> R,
2373 ) -> Self::Result<R> {
2374 self.window_cx.update_view(view, update)
2375 }
2376
2377 fn replace_root_view<W>(
2378 &mut self,
2379 build_view: impl FnOnce(&mut ViewContext<'_, W>) -> W,
2380 ) -> Self::Result<View<W>>
2381 where
2382 W: 'static + Render,
2383 {
2384 self.window_cx.replace_root_view(build_view)
2385 }
2386
2387 fn focus_view<W: FocusableView>(&mut self, view: &View<W>) -> Self::Result<()> {
2388 self.window_cx.focus_view(view)
2389 }
2390
2391 fn dismiss_view<W: ManagedView>(&mut self, view: &View<W>) -> Self::Result<()> {
2392 self.window_cx.dismiss_view(view)
2393 }
2394}
2395
2396impl<'a, V> std::ops::Deref for ViewContext<'a, V> {
2397 type Target = WindowContext<'a>;
2398
2399 fn deref(&self) -> &Self::Target {
2400 &self.window_cx
2401 }
2402}
2403
2404impl<'a, V> std::ops::DerefMut for ViewContext<'a, V> {
2405 fn deref_mut(&mut self) -> &mut Self::Target {
2406 &mut self.window_cx
2407 }
2408}
2409
2410// #[derive(Clone, Copy, Eq, PartialEq, Hash)]
2411slotmap::new_key_type! {
2412 /// A unique identifier for a window.
2413 pub struct WindowId;
2414}
2415
2416impl WindowId {
2417 /// Converts this window ID to a `u64`.
2418 pub fn as_u64(&self) -> u64 {
2419 self.0.as_ffi()
2420 }
2421}
2422
2423/// A handle to a window with a specific root view type.
2424/// Note that this does not keep the window alive on its own.
2425#[derive(Deref, DerefMut)]
2426pub struct WindowHandle<V> {
2427 #[deref]
2428 #[deref_mut]
2429 pub(crate) any_handle: AnyWindowHandle,
2430 state_type: PhantomData<V>,
2431}
2432
2433impl<V: 'static + Render> WindowHandle<V> {
2434 /// Creates a new handle from a window ID.
2435 /// This does not check if the root type of the window is `V`.
2436 pub fn new(id: WindowId) -> Self {
2437 WindowHandle {
2438 any_handle: AnyWindowHandle {
2439 id,
2440 state_type: TypeId::of::<V>(),
2441 },
2442 state_type: PhantomData,
2443 }
2444 }
2445
2446 /// Get the root view out of this window.
2447 ///
2448 /// This will fail if the window is closed or if the root view's type does not match `V`.
2449 pub fn root<C>(&self, cx: &mut C) -> Result<View<V>>
2450 where
2451 C: Context,
2452 {
2453 Flatten::flatten(cx.update_window(self.any_handle, |root_view, _| {
2454 root_view
2455 .downcast::<V>()
2456 .map_err(|_| anyhow!("the type of the window's root view has changed"))
2457 }))
2458 }
2459
2460 /// Updates the root view of this window.
2461 ///
2462 /// This will fail if the window has been closed or if the root view's type does not match
2463 pub fn update<C, R>(
2464 &self,
2465 cx: &mut C,
2466 update: impl FnOnce(&mut V, &mut ViewContext<'_, V>) -> R,
2467 ) -> Result<R>
2468 where
2469 C: Context,
2470 {
2471 cx.update_window(self.any_handle, |root_view, cx| {
2472 let view = root_view
2473 .downcast::<V>()
2474 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
2475 Ok(cx.update_view(&view, update))
2476 })?
2477 }
2478
2479 /// Read the root view out of this window.
2480 ///
2481 /// This will fail if the window is closed or if the root view's type does not match `V`.
2482 pub fn read<'a>(&self, cx: &'a AppContext) -> Result<&'a V> {
2483 let x = cx
2484 .windows
2485 .get(self.id)
2486 .and_then(|window| {
2487 window
2488 .as_ref()
2489 .and_then(|window| window.root_view.clone())
2490 .map(|root_view| root_view.downcast::<V>())
2491 })
2492 .ok_or_else(|| anyhow!("window not found"))?
2493 .map_err(|_| anyhow!("the type of the window's root view has changed"))?;
2494
2495 Ok(x.read(cx))
2496 }
2497
2498 /// Read the root view out of this window, with a callback
2499 ///
2500 /// This will fail if the window is closed or if the root view's type does not match `V`.
2501 pub fn read_with<C, R>(&self, cx: &C, read_with: impl FnOnce(&V, &AppContext) -> R) -> Result<R>
2502 where
2503 C: Context,
2504 {
2505 cx.read_window(self, |root_view, cx| read_with(root_view.read(cx), cx))
2506 }
2507
2508 /// Read the root view pointer off of this window.
2509 ///
2510 /// This will fail if the window is closed or if the root view's type does not match `V`.
2511 pub fn root_view<C>(&self, cx: &C) -> Result<View<V>>
2512 where
2513 C: Context,
2514 {
2515 cx.read_window(self, |root_view, _cx| root_view.clone())
2516 }
2517
2518 /// Check if this window is 'active'.
2519 ///
2520 /// Will return `None` if the window is closed.
2521 pub fn is_active(&self, cx: &AppContext) -> Option<bool> {
2522 cx.windows
2523 .get(self.id)
2524 .and_then(|window| window.as_ref().map(|window| window.active.get()))
2525 }
2526}
2527
2528impl<V> Copy for WindowHandle<V> {}
2529
2530impl<V> Clone for WindowHandle<V> {
2531 fn clone(&self) -> Self {
2532 *self
2533 }
2534}
2535
2536impl<V> PartialEq for WindowHandle<V> {
2537 fn eq(&self, other: &Self) -> bool {
2538 self.any_handle == other.any_handle
2539 }
2540}
2541
2542impl<V> Eq for WindowHandle<V> {}
2543
2544impl<V> Hash for WindowHandle<V> {
2545 fn hash<H: Hasher>(&self, state: &mut H) {
2546 self.any_handle.hash(state);
2547 }
2548}
2549
2550impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
2551 fn from(val: WindowHandle<V>) -> Self {
2552 val.any_handle
2553 }
2554}
2555
2556/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.
2557#[derive(Copy, Clone, PartialEq, Eq, Hash)]
2558pub struct AnyWindowHandle {
2559 pub(crate) id: WindowId,
2560 state_type: TypeId,
2561}
2562
2563impl AnyWindowHandle {
2564 /// Get the ID of this window.
2565 pub fn window_id(&self) -> WindowId {
2566 self.id
2567 }
2568
2569 /// Attempt to convert this handle to a window handle with a specific root view type.
2570 /// If the types do not match, this will return `None`.
2571 pub fn downcast<T: 'static>(&self) -> Option<WindowHandle<T>> {
2572 if TypeId::of::<T>() == self.state_type {
2573 Some(WindowHandle {
2574 any_handle: *self,
2575 state_type: PhantomData,
2576 })
2577 } else {
2578 None
2579 }
2580 }
2581
2582 /// Updates the state of the root view of this window.
2583 ///
2584 /// This will fail if the window has been closed.
2585 pub fn update<C, R>(
2586 self,
2587 cx: &mut C,
2588 update: impl FnOnce(AnyView, &mut WindowContext<'_>) -> R,
2589 ) -> Result<R>
2590 where
2591 C: Context,
2592 {
2593 cx.update_window(self, update)
2594 }
2595
2596 /// Read the state of the root view of this window.
2597 ///
2598 /// This will fail if the window has been closed.
2599 pub fn read<T, C, R>(self, cx: &C, read: impl FnOnce(View<T>, &AppContext) -> R) -> Result<R>
2600 where
2601 C: Context,
2602 T: 'static,
2603 {
2604 let view = self
2605 .downcast::<T>()
2606 .context("the type of the window's root view has changed")?;
2607
2608 cx.read_window(&view, read)
2609 }
2610}
2611
2612/// An identifier for an [`Element`](crate::Element).
2613///
2614/// Can be constructed with a string, a number, or both, as well
2615/// as other internal representations.
2616#[derive(Clone, Debug, Eq, PartialEq, Hash)]
2617pub enum ElementId {
2618 /// The ID of a View element
2619 View(EntityId),
2620 /// An integer ID.
2621 Integer(usize),
2622 /// A string based ID.
2623 Name(SharedString),
2624 /// An ID that's equated with a focus handle.
2625 FocusHandle(FocusId),
2626 /// A combination of a name and an integer.
2627 NamedInteger(SharedString, usize),
2628}
2629
2630impl Display for ElementId {
2631 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2632 match self {
2633 ElementId::View(entity_id) => write!(f, "view-{}", entity_id)?,
2634 ElementId::Integer(ix) => write!(f, "{}", ix)?,
2635 ElementId::Name(name) => write!(f, "{}", name)?,
2636 ElementId::FocusHandle(_) => write!(f, "FocusHandle")?,
2637 ElementId::NamedInteger(s, i) => write!(f, "{}-{}", s, i)?,
2638 }
2639
2640 Ok(())
2641 }
2642}
2643
2644impl ElementId {
2645 pub(crate) fn from_entity_id(entity_id: EntityId) -> Self {
2646 ElementId::View(entity_id)
2647 }
2648}
2649
2650impl TryInto<SharedString> for ElementId {
2651 type Error = anyhow::Error;
2652
2653 fn try_into(self) -> anyhow::Result<SharedString> {
2654 if let ElementId::Name(name) = self {
2655 Ok(name)
2656 } else {
2657 Err(anyhow!("element id is not string"))
2658 }
2659 }
2660}
2661
2662impl From<usize> for ElementId {
2663 fn from(id: usize) -> Self {
2664 ElementId::Integer(id)
2665 }
2666}
2667
2668impl From<i32> for ElementId {
2669 fn from(id: i32) -> Self {
2670 Self::Integer(id as usize)
2671 }
2672}
2673
2674impl From<SharedString> for ElementId {
2675 fn from(name: SharedString) -> Self {
2676 ElementId::Name(name)
2677 }
2678}
2679
2680impl From<&'static str> for ElementId {
2681 fn from(name: &'static str) -> Self {
2682 ElementId::Name(name.into())
2683 }
2684}
2685
2686impl<'a> From<&'a FocusHandle> for ElementId {
2687 fn from(handle: &'a FocusHandle) -> Self {
2688 ElementId::FocusHandle(handle.id)
2689 }
2690}
2691
2692impl From<(&'static str, EntityId)> for ElementId {
2693 fn from((name, id): (&'static str, EntityId)) -> Self {
2694 ElementId::NamedInteger(name.into(), id.as_u64() as usize)
2695 }
2696}
2697
2698impl From<(&'static str, usize)> for ElementId {
2699 fn from((name, id): (&'static str, usize)) -> Self {
2700 ElementId::NamedInteger(name.into(), id)
2701 }
2702}
2703
2704impl From<(&'static str, u64)> for ElementId {
2705 fn from((name, id): (&'static str, u64)) -> Self {
2706 ElementId::NamedInteger(name.into(), id as usize)
2707 }
2708}
2709
2710/// A rectangle to be rendered in the window at the given position and size.
2711/// Passed as an argument [`ElementContext::paint_quad`].
2712#[derive(Clone)]
2713pub struct PaintQuad {
2714 bounds: Bounds<Pixels>,
2715 corner_radii: Corners<Pixels>,
2716 background: Hsla,
2717 border_widths: Edges<Pixels>,
2718 border_color: Hsla,
2719}
2720
2721impl PaintQuad {
2722 /// Sets the corner radii of the quad.
2723 pub fn corner_radii(self, corner_radii: impl Into<Corners<Pixels>>) -> Self {
2724 PaintQuad {
2725 corner_radii: corner_radii.into(),
2726 ..self
2727 }
2728 }
2729
2730 /// Sets the border widths of the quad.
2731 pub fn border_widths(self, border_widths: impl Into<Edges<Pixels>>) -> Self {
2732 PaintQuad {
2733 border_widths: border_widths.into(),
2734 ..self
2735 }
2736 }
2737
2738 /// Sets the border color of the quad.
2739 pub fn border_color(self, border_color: impl Into<Hsla>) -> Self {
2740 PaintQuad {
2741 border_color: border_color.into(),
2742 ..self
2743 }
2744 }
2745
2746 /// Sets the background color of the quad.
2747 pub fn background(self, background: impl Into<Hsla>) -> Self {
2748 PaintQuad {
2749 background: background.into(),
2750 ..self
2751 }
2752 }
2753}
2754
2755/// Creates a quad with the given parameters.
2756pub fn quad(
2757 bounds: Bounds<Pixels>,
2758 corner_radii: impl Into<Corners<Pixels>>,
2759 background: impl Into<Hsla>,
2760 border_widths: impl Into<Edges<Pixels>>,
2761 border_color: impl Into<Hsla>,
2762) -> PaintQuad {
2763 PaintQuad {
2764 bounds,
2765 corner_radii: corner_radii.into(),
2766 background: background.into(),
2767 border_widths: border_widths.into(),
2768 border_color: border_color.into(),
2769 }
2770}
2771
2772/// Creates a filled quad with the given bounds and background color.
2773pub fn fill(bounds: impl Into<Bounds<Pixels>>, background: impl Into<Hsla>) -> PaintQuad {
2774 PaintQuad {
2775 bounds: bounds.into(),
2776 corner_radii: (0.).into(),
2777 background: background.into(),
2778 border_widths: (0.).into(),
2779 border_color: transparent_black(),
2780 }
2781}
2782
2783/// Creates a rectangle outline with the given bounds, border color, and a 1px border width
2784pub fn outline(bounds: impl Into<Bounds<Pixels>>, border_color: impl Into<Hsla>) -> PaintQuad {
2785 PaintQuad {
2786 bounds: bounds.into(),
2787 corner_radii: (0.).into(),
2788 background: transparent_black(),
2789 border_widths: (1.).into(),
2790 border_color: border_color.into(),
2791 }
2792}