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