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