1//! The element context is the main interface for interacting with the frame during a paint.
2//!
3//! Elements are hierarchical and with a few exceptions the context accumulates state in a stack
4//! as it processes all of the elements in the frame. The methods that interact with this stack
5//! are generally marked with `with_*`, and take a callback to denote the region of code that
6//! should be executed with that state.
7//!
8//! The other main interface is the `paint_*` family of methods, which push basic drawing commands
9//! to the GPU. Everything in a GPUI app is drawn with these methods.
10//!
11//! There are also several internal methods that GPUI uses, such as [`ElementContext::with_element_state`]
12//! to call the paint and layout methods on elements. These have been included as they're often useful
13//! for taking manual control of the layouting or painting of specialized elements.
14
15use std::{
16 any::{Any, TypeId},
17 borrow::{Borrow, BorrowMut, Cow},
18 mem,
19 ops::Range,
20 rc::Rc,
21 sync::Arc,
22};
23
24use anyhow::Result;
25use collections::FxHashMap;
26use derive_more::{Deref, DerefMut};
27use futures::{future::Shared, FutureExt};
28#[cfg(target_os = "macos")]
29use media::core_video::CVImageBuffer;
30use smallvec::SmallVec;
31
32use crate::{
33 hash, prelude::*, size, AnyElement, AnyTooltip, AppContext, Asset, AvailableSpace, Bounds,
34 BoxShadow, ContentMask, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchPhase,
35 DispatchTree, DrawPhase, ElementId, ElementStateBox, EntityId, FocusHandle, FocusId, FontId,
36 GlobalElementId, GlyphId, Hsla, ImageData, InputHandler, IsZero, KeyContext, KeyEvent,
37 LayoutId, LineLayoutIndex, ModifiersChangedEvent, MonochromeSprite, MouseEvent, PaintQuad,
38 Path, Pixels, PlatformInputHandler, Point, PolychromeSprite, Quad, RenderGlyphParams,
39 RenderImageParams, RenderSvgParams, Scene, Shadow, SharedString, Size, StrikethroughStyle,
40 Style, Task, TextStyleRefinement, TransformationMatrix, Underline, UnderlineStyle, Window,
41 WindowContext, SUBPIXEL_VARIANTS,
42};
43
44pub(crate) type AnyMouseListener =
45 Box<dyn FnMut(&dyn Any, DispatchPhase, &mut ElementContext) + 'static>;
46
47#[derive(Clone)]
48pub(crate) struct CursorStyleRequest {
49 pub(crate) hitbox_id: HitboxId,
50 pub(crate) style: CursorStyle,
51}
52
53/// An identifier for a [Hitbox].
54#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
55pub struct HitboxId(usize);
56
57impl HitboxId {
58 /// Checks if the hitbox with this id is currently hovered.
59 pub fn is_hovered(&self, cx: &WindowContext) -> bool {
60 cx.window.mouse_hit_test.0.contains(self)
61 }
62}
63
64/// A rectangular region that potentially blocks hitboxes inserted prior.
65/// See [ElementContext::insert_hitbox] for more details.
66#[derive(Clone, Debug, Deref)]
67pub struct Hitbox {
68 /// A unique identifier for the hitbox
69 pub id: HitboxId,
70 /// The bounds of the hitbox
71 #[deref]
72 pub bounds: Bounds<Pixels>,
73 /// Whether the hitbox occludes other hitboxes inserted prior.
74 pub opaque: bool,
75}
76
77impl Hitbox {
78 /// Checks if the hitbox is currently hovered.
79 pub fn is_hovered(&self, cx: &WindowContext) -> bool {
80 self.id.is_hovered(cx)
81 }
82}
83
84#[derive(Default, Eq, PartialEq)]
85pub(crate) struct HitTest(SmallVec<[HitboxId; 8]>);
86
87pub(crate) struct DeferredDraw {
88 priority: usize,
89 parent_node: DispatchNodeId,
90 element_id_stack: GlobalElementId,
91 text_style_stack: Vec<TextStyleRefinement>,
92 element: Option<AnyElement>,
93 absolute_offset: Point<Pixels>,
94 layout_range: Range<AfterLayoutIndex>,
95 paint_range: Range<PaintIndex>,
96}
97
98pub(crate) struct Frame {
99 pub(crate) focus: Option<FocusId>,
100 pub(crate) window_active: bool,
101 pub(crate) element_states: FxHashMap<(GlobalElementId, TypeId), ElementStateBox>,
102 accessed_element_states: Vec<(GlobalElementId, TypeId)>,
103 pub(crate) mouse_listeners: Vec<Option<AnyMouseListener>>,
104 pub(crate) dispatch_tree: DispatchTree,
105 pub(crate) scene: Scene,
106 pub(crate) hitboxes: Vec<Hitbox>,
107 pub(crate) deferred_draws: Vec<DeferredDraw>,
108 pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
109 pub(crate) element_offset_stack: Vec<Point<Pixels>>,
110 pub(crate) input_handlers: Vec<Option<PlatformInputHandler>>,
111 pub(crate) tooltip_requests: Vec<Option<AnyTooltip>>,
112 pub(crate) cursor_styles: Vec<CursorStyleRequest>,
113 #[cfg(any(test, feature = "test-support"))]
114 pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
115}
116
117#[derive(Clone, Default)]
118pub(crate) struct AfterLayoutIndex {
119 hitboxes_index: usize,
120 tooltips_index: usize,
121 deferred_draws_index: usize,
122 dispatch_tree_index: usize,
123 accessed_element_states_index: usize,
124 line_layout_index: LineLayoutIndex,
125}
126
127#[derive(Clone, Default)]
128pub(crate) struct PaintIndex {
129 scene_index: usize,
130 mouse_listeners_index: usize,
131 input_handlers_index: usize,
132 cursor_styles_index: usize,
133 accessed_element_states_index: usize,
134 line_layout_index: LineLayoutIndex,
135}
136
137impl Frame {
138 pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
139 Frame {
140 focus: None,
141 window_active: false,
142 element_states: FxHashMap::default(),
143 accessed_element_states: Vec::new(),
144 mouse_listeners: Vec::new(),
145 dispatch_tree,
146 scene: Scene::default(),
147 hitboxes: Vec::new(),
148 deferred_draws: Vec::new(),
149 content_mask_stack: Vec::new(),
150 element_offset_stack: Vec::new(),
151 input_handlers: Vec::new(),
152 tooltip_requests: Vec::new(),
153 cursor_styles: Vec::new(),
154
155 #[cfg(any(test, feature = "test-support"))]
156 debug_bounds: FxHashMap::default(),
157 }
158 }
159
160 pub(crate) fn clear(&mut self) {
161 self.element_states.clear();
162 self.accessed_element_states.clear();
163 self.mouse_listeners.clear();
164 self.dispatch_tree.clear();
165 self.scene.clear();
166 self.input_handlers.clear();
167 self.tooltip_requests.clear();
168 self.cursor_styles.clear();
169 self.hitboxes.clear();
170 self.deferred_draws.clear();
171 }
172
173 pub(crate) fn hit_test(&self, position: Point<Pixels>) -> HitTest {
174 let mut hit_test = HitTest::default();
175 for hitbox in self.hitboxes.iter().rev() {
176 if hitbox.bounds.contains(&position) {
177 hit_test.0.push(hitbox.id);
178 if hitbox.opaque {
179 break;
180 }
181 }
182 }
183 hit_test
184 }
185
186 pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
187 self.focus
188 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
189 .unwrap_or_default()
190 }
191
192 pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
193 for element_state_key in &self.accessed_element_states {
194 if let Some(element_state) = prev_frame.element_states.remove(element_state_key) {
195 self.element_states
196 .insert(element_state_key.clone(), element_state);
197 }
198 }
199
200 self.scene.finish();
201 }
202}
203
204/// This context is used for assisting in the implementation of the element trait
205#[derive(Deref, DerefMut)]
206pub struct ElementContext<'a> {
207 pub(crate) cx: WindowContext<'a>,
208}
209
210impl<'a> WindowContext<'a> {
211 /// Convert this window context into an ElementContext in this callback.
212 /// If you need to use this method, you're probably intermixing the imperative
213 /// and declarative APIs, which is not recommended.
214 pub fn with_element_context<R>(&mut self, f: impl FnOnce(&mut ElementContext) -> R) -> R {
215 f(&mut ElementContext {
216 cx: WindowContext::new(self.app, self.window),
217 })
218 }
219}
220
221impl<'a> Borrow<AppContext> for ElementContext<'a> {
222 fn borrow(&self) -> &AppContext {
223 self.cx.app
224 }
225}
226
227impl<'a> BorrowMut<AppContext> for ElementContext<'a> {
228 fn borrow_mut(&mut self) -> &mut AppContext {
229 self.cx.borrow_mut()
230 }
231}
232
233impl<'a> Borrow<WindowContext<'a>> for ElementContext<'a> {
234 fn borrow(&self) -> &WindowContext<'a> {
235 &self.cx
236 }
237}
238
239impl<'a> BorrowMut<WindowContext<'a>> for ElementContext<'a> {
240 fn borrow_mut(&mut self) -> &mut WindowContext<'a> {
241 &mut self.cx
242 }
243}
244
245impl<'a> Borrow<Window> for ElementContext<'a> {
246 fn borrow(&self) -> &Window {
247 self.cx.window
248 }
249}
250
251impl<'a> BorrowMut<Window> for ElementContext<'a> {
252 fn borrow_mut(&mut self) -> &mut Window {
253 self.cx.borrow_mut()
254 }
255}
256
257impl<'a> Context for ElementContext<'a> {
258 type Result<T> = <WindowContext<'a> as Context>::Result<T>;
259
260 fn new_model<T: 'static>(
261 &mut self,
262 build_model: impl FnOnce(&mut crate::ModelContext<'_, T>) -> T,
263 ) -> Self::Result<crate::Model<T>> {
264 self.cx.new_model(build_model)
265 }
266
267 fn update_model<T, R>(
268 &mut self,
269 handle: &crate::Model<T>,
270 update: impl FnOnce(&mut T, &mut crate::ModelContext<'_, T>) -> R,
271 ) -> Self::Result<R>
272 where
273 T: 'static,
274 {
275 self.cx.update_model(handle, update)
276 }
277
278 fn read_model<T, R>(
279 &self,
280 handle: &crate::Model<T>,
281 read: impl FnOnce(&T, &AppContext) -> R,
282 ) -> Self::Result<R>
283 where
284 T: 'static,
285 {
286 self.cx.read_model(handle, read)
287 }
288
289 fn update_window<T, F>(&mut self, window: crate::AnyWindowHandle, f: F) -> Result<T>
290 where
291 F: FnOnce(crate::AnyView, &mut WindowContext<'_>) -> T,
292 {
293 self.cx.update_window(window, f)
294 }
295
296 fn read_window<T, R>(
297 &self,
298 window: &crate::WindowHandle<T>,
299 read: impl FnOnce(crate::View<T>, &AppContext) -> R,
300 ) -> Result<R>
301 where
302 T: 'static,
303 {
304 self.cx.read_window(window, read)
305 }
306}
307
308impl<'a> VisualContext for ElementContext<'a> {
309 fn new_view<V>(
310 &mut self,
311 build_view: impl FnOnce(&mut crate::ViewContext<'_, V>) -> V,
312 ) -> Self::Result<crate::View<V>>
313 where
314 V: 'static + Render,
315 {
316 self.cx.new_view(build_view)
317 }
318
319 fn update_view<V: 'static, R>(
320 &mut self,
321 view: &crate::View<V>,
322 update: impl FnOnce(&mut V, &mut crate::ViewContext<'_, V>) -> R,
323 ) -> Self::Result<R> {
324 self.cx.update_view(view, update)
325 }
326
327 fn replace_root_view<V>(
328 &mut self,
329 build_view: impl FnOnce(&mut crate::ViewContext<'_, V>) -> V,
330 ) -> Self::Result<crate::View<V>>
331 where
332 V: 'static + Render,
333 {
334 self.cx.replace_root_view(build_view)
335 }
336
337 fn focus_view<V>(&mut self, view: &crate::View<V>) -> Self::Result<()>
338 where
339 V: crate::FocusableView,
340 {
341 self.cx.focus_view(view)
342 }
343
344 fn dismiss_view<V>(&mut self, view: &crate::View<V>) -> Self::Result<()>
345 where
346 V: crate::ManagedView,
347 {
348 self.cx.dismiss_view(view)
349 }
350}
351
352impl<'a> ElementContext<'a> {
353 pub(crate) fn draw_roots(&mut self) {
354 self.window.draw_phase = DrawPhase::Layout;
355
356 // Layout all root elements.
357 let mut root_element = self.window.root_view.as_ref().unwrap().clone().into_any();
358 root_element.layout(Point::default(), self.window.viewport_size.into(), self);
359
360 let mut sorted_deferred_draws =
361 (0..self.window.next_frame.deferred_draws.len()).collect::<SmallVec<[_; 8]>>();
362 sorted_deferred_draws.sort_by_key(|ix| self.window.next_frame.deferred_draws[*ix].priority);
363 self.layout_deferred_draws(&sorted_deferred_draws);
364
365 let mut prompt_element = None;
366 let mut active_drag_element = None;
367 let mut tooltip_element = None;
368 if let Some(prompt) = self.window.prompt.take() {
369 let mut element = prompt.view.any_view().into_any();
370 element.layout(Point::default(), self.window.viewport_size.into(), self);
371 prompt_element = Some(element);
372 self.window.prompt = Some(prompt);
373 } else if let Some(active_drag) = self.app.active_drag.take() {
374 let mut element = active_drag.view.clone().into_any();
375 let offset = self.mouse_position() - active_drag.cursor_offset;
376 element.layout(offset, AvailableSpace::min_size(), self);
377 active_drag_element = Some(element);
378 self.app.active_drag = Some(active_drag);
379 } else if let Some(tooltip_request) =
380 self.window.next_frame.tooltip_requests.last().cloned()
381 {
382 let tooltip_request = tooltip_request.unwrap();
383 let mut element = tooltip_request.view.clone().into_any();
384 let offset = tooltip_request.cursor_offset;
385 element.layout(offset, AvailableSpace::min_size(), self);
386 tooltip_element = Some(element);
387 }
388
389 self.window.mouse_hit_test = self.window.next_frame.hit_test(self.window.mouse_position);
390
391 // Now actually paint the elements.
392 self.window.draw_phase = DrawPhase::Paint;
393 root_element.paint(self);
394
395 self.paint_deferred_draws(&sorted_deferred_draws);
396
397 if let Some(mut prompt_element) = prompt_element {
398 prompt_element.paint(self)
399 } else if let Some(mut drag_element) = active_drag_element {
400 drag_element.paint(self);
401 } else if let Some(mut tooltip_element) = tooltip_element {
402 tooltip_element.paint(self);
403 }
404 }
405
406 fn layout_deferred_draws(&mut self, deferred_draw_indices: &[usize]) {
407 assert_eq!(self.window.element_id_stack.len(), 0);
408
409 let mut deferred_draws = mem::take(&mut self.window.next_frame.deferred_draws);
410 for deferred_draw_ix in deferred_draw_indices {
411 let deferred_draw = &mut deferred_draws[*deferred_draw_ix];
412 self.window.element_id_stack = deferred_draw.element_id_stack.clone();
413 self.window.text_style_stack = deferred_draw.text_style_stack.clone();
414 self.window
415 .next_frame
416 .dispatch_tree
417 .set_active_node(deferred_draw.parent_node);
418
419 let layout_start = self.after_layout_index();
420 if let Some(element) = deferred_draw.element.as_mut() {
421 self.with_absolute_element_offset(deferred_draw.absolute_offset, |cx| {
422 element.after_layout(cx)
423 });
424 } else {
425 self.reuse_after_layout(deferred_draw.layout_range.clone());
426 }
427 let layout_end = self.after_layout_index();
428 deferred_draw.layout_range = layout_start..layout_end;
429 }
430 assert_eq!(
431 self.window.next_frame.deferred_draws.len(),
432 0,
433 "cannot call defer_draw during deferred drawing"
434 );
435 self.window.next_frame.deferred_draws = deferred_draws;
436 self.window.element_id_stack.clear();
437 self.window.text_style_stack.clear();
438 }
439
440 fn paint_deferred_draws(&mut self, deferred_draw_indices: &[usize]) {
441 assert_eq!(self.window.element_id_stack.len(), 0);
442
443 let mut deferred_draws = mem::take(&mut self.window.next_frame.deferred_draws);
444 for deferred_draw_ix in deferred_draw_indices {
445 let mut deferred_draw = &mut deferred_draws[*deferred_draw_ix];
446 self.window.element_id_stack = deferred_draw.element_id_stack.clone();
447 self.window
448 .next_frame
449 .dispatch_tree
450 .set_active_node(deferred_draw.parent_node);
451
452 let paint_start = self.paint_index();
453 if let Some(element) = deferred_draw.element.as_mut() {
454 element.paint(self);
455 } else {
456 self.reuse_paint(deferred_draw.paint_range.clone());
457 }
458 let paint_end = self.paint_index();
459 deferred_draw.paint_range = paint_start..paint_end;
460 }
461 self.window.next_frame.deferred_draws = deferred_draws;
462 self.window.element_id_stack.clear();
463 }
464
465 pub(crate) fn after_layout_index(&self) -> AfterLayoutIndex {
466 AfterLayoutIndex {
467 hitboxes_index: self.window.next_frame.hitboxes.len(),
468 tooltips_index: self.window.next_frame.tooltip_requests.len(),
469 deferred_draws_index: self.window.next_frame.deferred_draws.len(),
470 dispatch_tree_index: self.window.next_frame.dispatch_tree.len(),
471 accessed_element_states_index: self.window.next_frame.accessed_element_states.len(),
472 line_layout_index: self.window.text_system.layout_index(),
473 }
474 }
475
476 pub(crate) fn reuse_after_layout(&mut self, range: Range<AfterLayoutIndex>) {
477 let window = &mut self.window;
478 window.next_frame.hitboxes.extend(
479 window.rendered_frame.hitboxes[range.start.hitboxes_index..range.end.hitboxes_index]
480 .iter()
481 .cloned(),
482 );
483 window.next_frame.tooltip_requests.extend(
484 window.rendered_frame.tooltip_requests
485 [range.start.tooltips_index..range.end.tooltips_index]
486 .iter_mut()
487 .map(|request| request.take()),
488 );
489 window.next_frame.accessed_element_states.extend(
490 window.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
491 ..range.end.accessed_element_states_index]
492 .iter()
493 .cloned(),
494 );
495 window
496 .text_system
497 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
498
499 let reused_subtree = window.next_frame.dispatch_tree.reuse_subtree(
500 range.start.dispatch_tree_index..range.end.dispatch_tree_index,
501 &mut window.rendered_frame.dispatch_tree,
502 );
503 window.next_frame.deferred_draws.extend(
504 window.rendered_frame.deferred_draws
505 [range.start.deferred_draws_index..range.end.deferred_draws_index]
506 .iter()
507 .map(|deferred_draw| DeferredDraw {
508 parent_node: reused_subtree.refresh_node_id(deferred_draw.parent_node),
509 element_id_stack: deferred_draw.element_id_stack.clone(),
510 text_style_stack: deferred_draw.text_style_stack.clone(),
511 priority: deferred_draw.priority,
512 element: None,
513 absolute_offset: deferred_draw.absolute_offset,
514 layout_range: deferred_draw.layout_range.clone(),
515 paint_range: deferred_draw.paint_range.clone(),
516 }),
517 );
518 }
519
520 pub(crate) fn paint_index(&self) -> PaintIndex {
521 PaintIndex {
522 scene_index: self.window.next_frame.scene.len(),
523 mouse_listeners_index: self.window.next_frame.mouse_listeners.len(),
524 input_handlers_index: self.window.next_frame.input_handlers.len(),
525 cursor_styles_index: self.window.next_frame.cursor_styles.len(),
526 accessed_element_states_index: self.window.next_frame.accessed_element_states.len(),
527 line_layout_index: self.window.text_system.layout_index(),
528 }
529 }
530
531 pub(crate) fn reuse_paint(&mut self, range: Range<PaintIndex>) {
532 let window = &mut self.cx.window;
533
534 window.next_frame.cursor_styles.extend(
535 window.rendered_frame.cursor_styles
536 [range.start.cursor_styles_index..range.end.cursor_styles_index]
537 .iter()
538 .cloned(),
539 );
540 window.next_frame.input_handlers.extend(
541 window.rendered_frame.input_handlers
542 [range.start.input_handlers_index..range.end.input_handlers_index]
543 .iter_mut()
544 .map(|handler| handler.take()),
545 );
546 window.next_frame.mouse_listeners.extend(
547 window.rendered_frame.mouse_listeners
548 [range.start.mouse_listeners_index..range.end.mouse_listeners_index]
549 .iter_mut()
550 .map(|listener| listener.take()),
551 );
552 window.next_frame.accessed_element_states.extend(
553 window.rendered_frame.accessed_element_states[range.start.accessed_element_states_index
554 ..range.end.accessed_element_states_index]
555 .iter()
556 .cloned(),
557 );
558 window
559 .text_system
560 .reuse_layouts(range.start.line_layout_index..range.end.line_layout_index);
561 window.next_frame.scene.replay(
562 range.start.scene_index..range.end.scene_index,
563 &window.rendered_frame.scene,
564 );
565 }
566
567 /// Push a text style onto the stack, and call a function with that style active.
568 /// Use [`AppContext::text_style`] to get the current, combined text style.
569 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
570 where
571 F: FnOnce(&mut Self) -> R,
572 {
573 if let Some(style) = style {
574 self.window.text_style_stack.push(style);
575 let result = f(self);
576 self.window.text_style_stack.pop();
577 result
578 } else {
579 f(self)
580 }
581 }
582
583 /// Updates the cursor style at the platform level.
584 pub fn set_cursor_style(&mut self, style: CursorStyle, hitbox: &Hitbox) {
585 self.window
586 .next_frame
587 .cursor_styles
588 .push(CursorStyleRequest {
589 hitbox_id: hitbox.id,
590 style,
591 });
592 }
593
594 /// Sets a tooltip to be rendered for the upcoming frame
595 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) {
596 self.window.next_frame.tooltip_requests.push(Some(tooltip));
597 }
598
599 /// Pushes the given element id onto the global stack and invokes the given closure
600 /// with a `GlobalElementId`, which disambiguates the given id in the context of its ancestor
601 /// ids. Because elements are discarded and recreated on each frame, the `GlobalElementId` is
602 /// used to associate state with identified elements across separate frames.
603 pub fn with_element_id<R>(
604 &mut self,
605 id: Option<impl Into<ElementId>>,
606 f: impl FnOnce(&mut Self) -> R,
607 ) -> R {
608 if let Some(id) = id.map(Into::into) {
609 let window = self.window_mut();
610 window.element_id_stack.push(id);
611 let result = f(self);
612 let window: &mut Window = self.borrow_mut();
613 window.element_id_stack.pop();
614 result
615 } else {
616 f(self)
617 }
618 }
619
620 /// Invoke the given function with the given content mask after intersecting it
621 /// with the current mask.
622 pub fn with_content_mask<R>(
623 &mut self,
624 mask: Option<ContentMask<Pixels>>,
625 f: impl FnOnce(&mut Self) -> R,
626 ) -> R {
627 if let Some(mask) = mask {
628 let mask = mask.intersect(&self.content_mask());
629 self.window_mut().next_frame.content_mask_stack.push(mask);
630 let result = f(self);
631 self.window_mut().next_frame.content_mask_stack.pop();
632 result
633 } else {
634 f(self)
635 }
636 }
637
638 /// Updates the global element offset relative to the current offset. This is used to implement
639 /// scrolling.
640 pub fn with_element_offset<R>(
641 &mut self,
642 offset: Point<Pixels>,
643 f: impl FnOnce(&mut Self) -> R,
644 ) -> R {
645 if offset.is_zero() {
646 return f(self);
647 };
648
649 let abs_offset = self.element_offset() + offset;
650 self.with_absolute_element_offset(abs_offset, f)
651 }
652
653 /// Updates the global element offset based on the given offset. This is used to implement
654 /// drag handles and other manual painting of elements.
655 pub fn with_absolute_element_offset<R>(
656 &mut self,
657 offset: Point<Pixels>,
658 f: impl FnOnce(&mut Self) -> R,
659 ) -> R {
660 self.window_mut()
661 .next_frame
662 .element_offset_stack
663 .push(offset);
664 let result = f(self);
665 self.window_mut().next_frame.element_offset_stack.pop();
666 result
667 }
668
669 /// Remove an asset from GPUI's cache
670 pub fn remove_cached_asset<A: Asset + 'static>(
671 &mut self,
672 source: &A::Source,
673 ) -> Option<A::Output> {
674 self.asset_cache.remove::<A>(source)
675 }
676
677 /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
678 /// Your view will be re-drawn once the asset has finished loading.
679 ///
680 /// Note that the multiple calls to this method will only result in one `Asset::load` call.
681 /// The results of that call will be cached, and returned on subsequent uses of this API.
682 ///
683 /// Use [Self::remove_cached_asset] to reload your asset.
684 pub fn use_cached_asset<A: Asset + 'static>(
685 &mut self,
686 source: &A::Source,
687 ) -> Option<A::Output> {
688 self.asset_cache.get::<A>(source).or_else(|| {
689 if let Some(asset) = self.use_asset::<A>(source) {
690 self.asset_cache
691 .insert::<A>(source.to_owned(), asset.clone());
692 Some(asset)
693 } else {
694 None
695 }
696 })
697 }
698
699 /// Asynchronously load an asset, if the asset hasn't finished loading this will return None.
700 /// Your view will be re-drawn once the asset has finished loading.
701 ///
702 /// Note that the multiple calls to this method will only result in one `Asset::load` call at a
703 /// time.
704 ///
705 /// This asset will not be cached by default, see [Self::use_cached_asset]
706 pub fn use_asset<A: Asset + 'static>(&mut self, source: &A::Source) -> Option<A::Output> {
707 let asset_id = (TypeId::of::<A>(), hash(source));
708 let mut is_first = false;
709 let task = self
710 .loading_assets
711 .remove(&asset_id)
712 .map(|boxed_task| *boxed_task.downcast::<Shared<Task<A::Output>>>().unwrap())
713 .unwrap_or_else(|| {
714 is_first = true;
715 let future = A::load(source.clone(), self);
716 let task = self.background_executor().spawn(future).shared();
717 task
718 });
719
720 task.clone().now_or_never().or_else(|| {
721 if is_first {
722 let parent_id = self.parent_view_id();
723 self.spawn({
724 let task = task.clone();
725 |mut cx| async move {
726 task.await;
727
728 cx.on_next_frame(move |cx| {
729 if let Some(parent_id) = parent_id {
730 cx.notify(parent_id)
731 } else {
732 cx.refresh()
733 }
734 });
735 }
736 })
737 .detach();
738 }
739
740 self.loading_assets.insert(asset_id, Box::new(task));
741
742 None
743 })
744 }
745
746 /// Obtain the current element offset.
747 pub fn element_offset(&self) -> Point<Pixels> {
748 self.window()
749 .next_frame
750 .element_offset_stack
751 .last()
752 .copied()
753 .unwrap_or_default()
754 }
755
756 /// Obtain the current content mask.
757 pub fn content_mask(&self) -> ContentMask<Pixels> {
758 self.window()
759 .next_frame
760 .content_mask_stack
761 .last()
762 .cloned()
763 .unwrap_or_else(|| ContentMask {
764 bounds: Bounds {
765 origin: Point::default(),
766 size: self.window().viewport_size,
767 },
768 })
769 }
770
771 /// The size of an em for the base font of the application. Adjusting this value allows the
772 /// UI to scale, just like zooming a web page.
773 pub fn rem_size(&self) -> Pixels {
774 self.window().rem_size
775 }
776
777 /// Updates or initializes state for an element with the given id that lives across multiple
778 /// frames. If an element with this ID existed in the rendered frame, its state will be passed
779 /// to the given closure. The state returned by the closure will be stored so it can be referenced
780 /// when drawing the next frame.
781 pub fn with_element_state<S, R>(
782 &mut self,
783 element_id: Option<ElementId>,
784 f: impl FnOnce(Option<Option<S>>, &mut Self) -> (R, Option<S>),
785 ) -> R
786 where
787 S: 'static,
788 {
789 let id_is_none = element_id.is_none();
790 self.with_element_id(element_id, |cx| {
791 if id_is_none {
792 let (result, state) = f(None, cx);
793 debug_assert!(state.is_none(), "you must not return an element state when passing None for the element id");
794 result
795 } else {
796 let global_id = cx.window().element_id_stack.clone();
797 let key = (global_id, TypeId::of::<S>());
798 cx.window.next_frame.accessed_element_states.push(key.clone());
799
800 if let Some(any) = cx
801 .window_mut()
802 .next_frame
803 .element_states
804 .remove(&key)
805 .or_else(|| {
806 cx.window_mut()
807 .rendered_frame
808 .element_states
809 .remove(&key)
810 })
811 {
812 let ElementStateBox {
813 inner,
814 #[cfg(debug_assertions)]
815 type_name
816 } = any;
817 // Using the extra inner option to avoid needing to reallocate a new box.
818 let mut state_box = inner
819 .downcast::<Option<S>>()
820 .map_err(|_| {
821 #[cfg(debug_assertions)]
822 {
823 anyhow::anyhow!(
824 "invalid element state type for id, requested_type {:?}, actual type: {:?}",
825 std::any::type_name::<S>(),
826 type_name
827 )
828 }
829
830 #[cfg(not(debug_assertions))]
831 {
832 anyhow::anyhow!(
833 "invalid element state type for id, requested_type {:?}",
834 std::any::type_name::<S>(),
835 )
836 }
837 })
838 .unwrap();
839
840 // Actual: Option<AnyElement> <- View
841 // Requested: () <- AnyElement
842 let state = state_box
843 .take()
844 .expect("reentrant call to with_element_state for the same state type and element id");
845 let (result, state) = f(Some(Some(state)), cx);
846 state_box.replace(state.expect("you must return "));
847 cx.window_mut()
848 .next_frame
849 .element_states
850 .insert(key, ElementStateBox {
851 inner: state_box,
852 #[cfg(debug_assertions)]
853 type_name
854 });
855 result
856 } else {
857 let (result, state) = f(Some(None), cx);
858 cx.window_mut()
859 .next_frame
860 .element_states
861 .insert(key,
862 ElementStateBox {
863 inner: Box::new(Some(state.expect("you must return Some<State> when you pass some element id"))),
864 #[cfg(debug_assertions)]
865 type_name: std::any::type_name::<S>()
866 }
867
868 );
869 result
870 }
871 }
872 })
873 }
874
875 /// Defers the drawing of the given element, scheduling it to be painted on top of the currently-drawn tree
876 /// at a later time. The `priority` parameter determines the drawing order relative to other deferred elements,
877 /// with higher values being drawn on top.
878 pub fn defer_draw(
879 &mut self,
880 element: AnyElement,
881 absolute_offset: Point<Pixels>,
882 priority: usize,
883 ) {
884 let window = &mut self.cx.window;
885 assert_eq!(
886 window.draw_phase,
887 DrawPhase::Layout,
888 "defer_draw can only be called during before_layout or after_layout"
889 );
890 let parent_node = window.next_frame.dispatch_tree.active_node_id().unwrap();
891 window.next_frame.deferred_draws.push(DeferredDraw {
892 parent_node,
893 element_id_stack: window.element_id_stack.clone(),
894 text_style_stack: window.text_style_stack.clone(),
895 priority,
896 element: Some(element),
897 absolute_offset,
898 layout_range: AfterLayoutIndex::default()..AfterLayoutIndex::default(),
899 paint_range: PaintIndex::default()..PaintIndex::default(),
900 });
901 }
902
903 /// Creates a new painting layer for the specified bounds. A "layer" is a batch
904 /// of geometry that are non-overlapping and have the same draw order. This is typically used
905 /// for performance reasons.
906 pub fn paint_layer<R>(&mut self, bounds: Bounds<Pixels>, f: impl FnOnce(&mut Self) -> R) -> R {
907 let scale_factor = self.scale_factor();
908 let content_mask = self.content_mask();
909 let clipped_bounds = bounds.intersect(&content_mask.bounds);
910 if !clipped_bounds.is_empty() {
911 self.window
912 .next_frame
913 .scene
914 .push_layer(clipped_bounds.scale(scale_factor));
915 }
916
917 let result = f(self);
918
919 if !clipped_bounds.is_empty() {
920 self.window.next_frame.scene.pop_layer();
921 }
922
923 result
924 }
925
926 /// Paint one or more drop shadows into the scene for the next frame at the current z-index.
927 pub fn paint_shadows(
928 &mut self,
929 bounds: Bounds<Pixels>,
930 corner_radii: Corners<Pixels>,
931 shadows: &[BoxShadow],
932 ) {
933 let scale_factor = self.scale_factor();
934 let content_mask = self.content_mask();
935 for shadow in shadows {
936 let mut shadow_bounds = bounds;
937 shadow_bounds.origin += shadow.offset;
938 shadow_bounds.dilate(shadow.spread_radius);
939 self.window.next_frame.scene.insert_primitive(Shadow {
940 order: 0,
941 blur_radius: shadow.blur_radius.scale(scale_factor),
942 bounds: shadow_bounds.scale(scale_factor),
943 content_mask: content_mask.scale(scale_factor),
944 corner_radii: corner_radii.scale(scale_factor),
945 color: shadow.color,
946 });
947 }
948 }
949
950 /// Paint one or more quads into the scene for the next frame at the current stacking context.
951 /// Quads are colored rectangular regions with an optional background, border, and corner radius.
952 /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.
953 pub fn paint_quad(&mut self, quad: PaintQuad) {
954 let scale_factor = self.scale_factor();
955 let content_mask = self.content_mask();
956 self.window.next_frame.scene.insert_primitive(Quad {
957 order: 0,
958 pad: 0,
959 bounds: quad.bounds.scale(scale_factor),
960 content_mask: content_mask.scale(scale_factor),
961 background: quad.background,
962 border_color: quad.border_color,
963 corner_radii: quad.corner_radii.scale(scale_factor),
964 border_widths: quad.border_widths.scale(scale_factor),
965 });
966 }
967
968 /// Paint the given `Path` into the scene for the next frame at the current z-index.
969 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Hsla>) {
970 let scale_factor = self.scale_factor();
971 let content_mask = self.content_mask();
972 path.content_mask = content_mask;
973 path.color = color.into();
974 self.window
975 .next_frame
976 .scene
977 .insert_primitive(path.scale(scale_factor));
978 }
979
980 /// Paint an underline into the scene for the next frame at the current z-index.
981 pub fn paint_underline(
982 &mut self,
983 origin: Point<Pixels>,
984 width: Pixels,
985 style: &UnderlineStyle,
986 ) {
987 let scale_factor = self.scale_factor();
988 let height = if style.wavy {
989 style.thickness * 3.
990 } else {
991 style.thickness
992 };
993 let bounds = Bounds {
994 origin,
995 size: size(width, height),
996 };
997 let content_mask = self.content_mask();
998
999 self.window.next_frame.scene.insert_primitive(Underline {
1000 order: 0,
1001 pad: 0,
1002 bounds: bounds.scale(scale_factor),
1003 content_mask: content_mask.scale(scale_factor),
1004 color: style.color.unwrap_or_default(),
1005 thickness: style.thickness.scale(scale_factor),
1006 wavy: style.wavy,
1007 });
1008 }
1009
1010 /// Paint a strikethrough into the scene for the next frame at the current z-index.
1011 pub fn paint_strikethrough(
1012 &mut self,
1013 origin: Point<Pixels>,
1014 width: Pixels,
1015 style: &StrikethroughStyle,
1016 ) {
1017 let scale_factor = self.scale_factor();
1018 let height = style.thickness;
1019 let bounds = Bounds {
1020 origin,
1021 size: size(width, height),
1022 };
1023 let content_mask = self.content_mask();
1024
1025 self.window.next_frame.scene.insert_primitive(Underline {
1026 order: 0,
1027 pad: 0,
1028 bounds: bounds.scale(scale_factor),
1029 content_mask: content_mask.scale(scale_factor),
1030 thickness: style.thickness.scale(scale_factor),
1031 color: style.color.unwrap_or_default(),
1032 wavy: false,
1033 });
1034 }
1035
1036 /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
1037 ///
1038 /// The y component of the origin is the baseline of the glyph.
1039 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
1040 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
1041 /// This method is only useful if you need to paint a single glyph that has already been shaped.
1042 pub fn paint_glyph(
1043 &mut self,
1044 origin: Point<Pixels>,
1045 font_id: FontId,
1046 glyph_id: GlyphId,
1047 font_size: Pixels,
1048 color: Hsla,
1049 ) -> Result<()> {
1050 let scale_factor = self.scale_factor();
1051 let glyph_origin = origin.scale(scale_factor);
1052 let subpixel_variant = Point {
1053 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
1054 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
1055 };
1056 let params = RenderGlyphParams {
1057 font_id,
1058 glyph_id,
1059 font_size,
1060 subpixel_variant,
1061 scale_factor,
1062 is_emoji: false,
1063 };
1064
1065 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
1066 if !raster_bounds.is_zero() {
1067 let tile =
1068 self.window
1069 .sprite_atlas
1070 .get_or_insert_with(¶ms.clone().into(), &mut || {
1071 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
1072 Ok((size, Cow::Owned(bytes)))
1073 })?;
1074 let bounds = Bounds {
1075 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
1076 size: tile.bounds.size.map(Into::into),
1077 };
1078 let content_mask = self.content_mask().scale(scale_factor);
1079 self.window
1080 .next_frame
1081 .scene
1082 .insert_primitive(MonochromeSprite {
1083 order: 0,
1084 pad: 0,
1085 bounds,
1086 content_mask,
1087 color,
1088 tile,
1089 transformation: TransformationMatrix::unit(),
1090 });
1091 }
1092 Ok(())
1093 }
1094
1095 /// Paints an emoji glyph into the scene for the next frame at the current z-index.
1096 ///
1097 /// The y component of the origin is the baseline of the glyph.
1098 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
1099 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
1100 /// This method is only useful if you need to paint a single emoji that has already been shaped.
1101 pub fn paint_emoji(
1102 &mut self,
1103 origin: Point<Pixels>,
1104 font_id: FontId,
1105 glyph_id: GlyphId,
1106 font_size: Pixels,
1107 ) -> Result<()> {
1108 let scale_factor = self.scale_factor();
1109 let glyph_origin = origin.scale(scale_factor);
1110 let params = RenderGlyphParams {
1111 font_id,
1112 glyph_id,
1113 font_size,
1114 // We don't render emojis with subpixel variants.
1115 subpixel_variant: Default::default(),
1116 scale_factor,
1117 is_emoji: true,
1118 };
1119
1120 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
1121 if !raster_bounds.is_zero() {
1122 let tile =
1123 self.window
1124 .sprite_atlas
1125 .get_or_insert_with(¶ms.clone().into(), &mut || {
1126 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
1127 Ok((size, Cow::Owned(bytes)))
1128 })?;
1129 let bounds = Bounds {
1130 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
1131 size: tile.bounds.size.map(Into::into),
1132 };
1133 let content_mask = self.content_mask().scale(scale_factor);
1134
1135 self.window
1136 .next_frame
1137 .scene
1138 .insert_primitive(PolychromeSprite {
1139 order: 0,
1140 grayscale: false,
1141 bounds,
1142 corner_radii: Default::default(),
1143 content_mask,
1144 tile,
1145 });
1146 }
1147 Ok(())
1148 }
1149
1150 /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
1151 pub fn paint_svg(
1152 &mut self,
1153 bounds: Bounds<Pixels>,
1154 path: SharedString,
1155 transformation: TransformationMatrix,
1156 color: Hsla,
1157 ) -> Result<()> {
1158 let scale_factor = self.scale_factor();
1159 let bounds = bounds.scale(scale_factor);
1160 // Render the SVG at twice the size to get a higher quality result.
1161 let params = RenderSvgParams {
1162 path,
1163 size: bounds
1164 .size
1165 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
1166 };
1167
1168 let tile =
1169 self.window
1170 .sprite_atlas
1171 .get_or_insert_with(¶ms.clone().into(), &mut || {
1172 let bytes = self.svg_renderer.render(¶ms)?;
1173 Ok((params.size, Cow::Owned(bytes)))
1174 })?;
1175 let content_mask = self.content_mask().scale(scale_factor);
1176
1177 self.window
1178 .next_frame
1179 .scene
1180 .insert_primitive(MonochromeSprite {
1181 order: 0,
1182 pad: 0,
1183 bounds,
1184 content_mask,
1185 color,
1186 tile,
1187 transformation,
1188 });
1189
1190 Ok(())
1191 }
1192
1193 /// Paint an image into the scene for the next frame at the current z-index.
1194 pub fn paint_image(
1195 &mut self,
1196 bounds: Bounds<Pixels>,
1197 corner_radii: Corners<Pixels>,
1198 data: Arc<ImageData>,
1199 grayscale: bool,
1200 ) -> Result<()> {
1201 let scale_factor = self.scale_factor();
1202 let bounds = bounds.scale(scale_factor);
1203 let params = RenderImageParams { image_id: data.id };
1204
1205 let tile = self
1206 .window
1207 .sprite_atlas
1208 .get_or_insert_with(¶ms.clone().into(), &mut || {
1209 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
1210 })?;
1211 let content_mask = self.content_mask().scale(scale_factor);
1212 let corner_radii = corner_radii.scale(scale_factor);
1213
1214 self.window
1215 .next_frame
1216 .scene
1217 .insert_primitive(PolychromeSprite {
1218 order: 0,
1219 grayscale,
1220 bounds,
1221 content_mask,
1222 corner_radii,
1223 tile,
1224 });
1225 Ok(())
1226 }
1227
1228 /// Paint a surface into the scene for the next frame at the current z-index.
1229 #[cfg(target_os = "macos")]
1230 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
1231 let scale_factor = self.scale_factor();
1232 let bounds = bounds.scale(scale_factor);
1233 let content_mask = self.content_mask().scale(scale_factor);
1234 self.window
1235 .next_frame
1236 .scene
1237 .insert_primitive(crate::Surface {
1238 order: 0,
1239 bounds,
1240 content_mask,
1241 image_buffer,
1242 });
1243 }
1244
1245 #[must_use]
1246 /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
1247 /// layout is being requested, along with the layout ids of any children. This method is called during
1248 /// calls to the `Element::layout` trait method and enables any element to participate in layout.
1249 pub fn request_layout(
1250 &mut self,
1251 style: &Style,
1252 children: impl IntoIterator<Item = LayoutId>,
1253 ) -> LayoutId {
1254 self.app.layout_id_buffer.clear();
1255 self.app.layout_id_buffer.extend(children);
1256 let rem_size = self.rem_size();
1257
1258 self.cx
1259 .window
1260 .layout_engine
1261 .as_mut()
1262 .unwrap()
1263 .before_layout(style, rem_size, &self.cx.app.layout_id_buffer)
1264 }
1265
1266 /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
1267 /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
1268 /// determine the element's size. One place this is used internally is when measuring text.
1269 ///
1270 /// The given closure is invoked at layout time with the known dimensions and available space and
1271 /// returns a `Size`.
1272 pub fn request_measured_layout<
1273 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
1274 + 'static,
1275 >(
1276 &mut self,
1277 style: Style,
1278 measure: F,
1279 ) -> LayoutId {
1280 let rem_size = self.rem_size();
1281 self.window
1282 .layout_engine
1283 .as_mut()
1284 .unwrap()
1285 .request_measured_layout(style, rem_size, measure)
1286 }
1287
1288 /// Compute the layout for the given id within the given available space.
1289 /// This method is called for its side effect, typically by the framework prior to painting.
1290 /// After calling it, you can request the bounds of the given layout node id or any descendant.
1291 pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
1292 let mut layout_engine = self.window.layout_engine.take().unwrap();
1293 layout_engine.compute_layout(layout_id, available_space, self);
1294 self.window.layout_engine = Some(layout_engine);
1295 }
1296
1297 /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by
1298 /// GPUI itself automatically in order to pass your element its `Bounds` automatically.
1299 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
1300 let mut bounds = self
1301 .window
1302 .layout_engine
1303 .as_mut()
1304 .unwrap()
1305 .layout_bounds(layout_id)
1306 .map(Into::into);
1307 bounds.origin += self.element_offset();
1308 bounds
1309 }
1310
1311 /// This method should be called during `after_layout`. You can use
1312 /// the returned [Hitbox] during `paint` or in an event handler
1313 /// to determine whether the inserted hitbox was the topmost.
1314 pub fn insert_hitbox(&mut self, bounds: Bounds<Pixels>, opaque: bool) -> Hitbox {
1315 let content_mask = self.content_mask();
1316 let window = &mut self.window;
1317 let id = window.next_hitbox_id;
1318 window.next_hitbox_id.0 += 1;
1319 let hitbox = Hitbox {
1320 id,
1321 bounds: bounds.intersect(&content_mask.bounds),
1322 opaque,
1323 };
1324 window.next_frame.hitboxes.push(hitbox.clone());
1325 hitbox
1326 }
1327
1328 /// Sets the key context for the current element. This context will be used to translate
1329 /// keybindings into actions.
1330 pub fn set_key_context(&mut self, context: KeyContext) {
1331 self.window
1332 .next_frame
1333 .dispatch_tree
1334 .set_key_context(context);
1335 }
1336
1337 /// Sets the focus handle for the current element. This handle will be used to manage focus state
1338 /// and keyboard event dispatch for the element.
1339 pub fn set_focus_handle(&mut self, focus_handle: &FocusHandle) {
1340 self.window
1341 .next_frame
1342 .dispatch_tree
1343 .set_focus_id(focus_handle.id);
1344 }
1345
1346 /// Sets the view id for the current element, which will be used to manage view caching.
1347 pub fn set_view_id(&mut self, view_id: EntityId) {
1348 self.window.next_frame.dispatch_tree.set_view_id(view_id);
1349 }
1350
1351 /// Get the last view id for the current element
1352 pub fn parent_view_id(&mut self) -> Option<EntityId> {
1353 self.window.next_frame.dispatch_tree.parent_view_id()
1354 }
1355
1356 /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
1357 /// platform to receive textual input with proper integration with concerns such
1358 /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
1359 /// rendered.
1360 ///
1361 /// [element_input_handler]: crate::ElementInputHandler
1362 pub fn handle_input(&mut self, focus_handle: &FocusHandle, input_handler: impl InputHandler) {
1363 if focus_handle.is_focused(self) {
1364 let cx = self.to_async();
1365 self.window
1366 .next_frame
1367 .input_handlers
1368 .push(Some(PlatformInputHandler::new(cx, Box::new(input_handler))));
1369 }
1370 }
1371
1372 /// Register a mouse event listener on the window for the next frame. The type of event
1373 /// is determined by the first parameter of the given listener. When the next frame is rendered
1374 /// the listener will be cleared.
1375 pub fn on_mouse_event<Event: MouseEvent>(
1376 &mut self,
1377 mut handler: impl FnMut(&Event, DispatchPhase, &mut ElementContext) + 'static,
1378 ) {
1379 self.window.next_frame.mouse_listeners.push(Some(Box::new(
1380 move |event: &dyn Any, phase: DispatchPhase, cx: &mut ElementContext<'_>| {
1381 if let Some(event) = event.downcast_ref() {
1382 handler(event, phase, cx)
1383 }
1384 },
1385 )));
1386 }
1387
1388 /// Register a key event listener on the window for the next frame. The type of event
1389 /// is determined by the first parameter of the given listener. When the next frame is rendered
1390 /// the listener will be cleared.
1391 ///
1392 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1393 /// a specific need to register a global listener.
1394 pub fn on_key_event<Event: KeyEvent>(
1395 &mut self,
1396 listener: impl Fn(&Event, DispatchPhase, &mut ElementContext) + 'static,
1397 ) {
1398 self.window.next_frame.dispatch_tree.on_key_event(Rc::new(
1399 move |event: &dyn Any, phase, cx: &mut ElementContext<'_>| {
1400 if let Some(event) = event.downcast_ref::<Event>() {
1401 listener(event, phase, cx)
1402 }
1403 },
1404 ));
1405 }
1406
1407 /// Register a modifiers changed event listener on the window for the next frame.
1408 ///
1409 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1410 /// a specific need to register a global listener.
1411 pub fn on_modifiers_changed(
1412 &mut self,
1413 listener: impl Fn(&ModifiersChangedEvent, &mut ElementContext) + 'static,
1414 ) {
1415 self.window
1416 .next_frame
1417 .dispatch_tree
1418 .on_modifiers_changed(Rc::new(
1419 move |event: &ModifiersChangedEvent, cx: &mut ElementContext<'_>| {
1420 listener(event, cx)
1421 },
1422 ));
1423 }
1424}