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 rc::Rc,
20 sync::Arc,
21};
22
23use anyhow::Result;
24use collections::{FxHashMap, FxHashSet};
25use derive_more::{Deref, DerefMut};
26#[cfg(target_os = "macos")]
27use media::core_video::CVImageBuffer;
28use smallvec::SmallVec;
29use util::post_inc;
30
31use crate::{
32 prelude::*, size, AnyTooltip, AppContext, AvailableSpace, Bounds, BoxShadow, ContentMask,
33 Corners, CursorStyle, DevicePixels, DispatchPhase, DispatchTree, ElementId, ElementStateBox,
34 EntityId, FocusHandle, FocusId, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
35 InputHandler, IsZero, KeyContext, KeyEvent, LayoutId, MonochromeSprite, MouseEvent, PaintQuad,
36 Path, Pixels, PlatformInputHandler, Point, PolychromeSprite, Quad, RenderGlyphParams,
37 RenderImageParams, RenderSvgParams, Scene, Shadow, SharedString, Size, StackingContext,
38 StackingOrder, StrikethroughStyle, Style, TextStyleRefinement, Underline, UnderlineStyle,
39 Window, WindowContext, SUBPIXEL_VARIANTS,
40};
41
42type AnyMouseListener = Box<dyn FnMut(&dyn Any, DispatchPhase, &mut ElementContext) + 'static>;
43
44pub(crate) struct RequestedInputHandler {
45 pub(crate) view_id: EntityId,
46 pub(crate) handler: Option<PlatformInputHandler>,
47}
48
49pub(crate) struct TooltipRequest {
50 pub(crate) view_id: EntityId,
51 pub(crate) tooltip: AnyTooltip,
52}
53
54pub(crate) struct Frame {
55 pub(crate) focus: Option<FocusId>,
56 pub(crate) window_active: bool,
57 pub(crate) element_states: FxHashMap<GlobalElementId, ElementStateBox>,
58 pub(crate) mouse_listeners: FxHashMap<TypeId, Vec<(StackingOrder, EntityId, AnyMouseListener)>>,
59 pub(crate) dispatch_tree: DispatchTree,
60 pub(crate) scene: Scene,
61 pub(crate) depth_map: Vec<(StackingOrder, EntityId, Bounds<Pixels>)>,
62 pub(crate) z_index_stack: StackingOrder,
63 pub(crate) next_stacking_order_ids: Vec<u16>,
64 pub(crate) next_root_z_index: u16,
65 pub(crate) content_mask_stack: Vec<ContentMask<Pixels>>,
66 pub(crate) element_offset_stack: Vec<Point<Pixels>>,
67 pub(crate) requested_input_handler: Option<RequestedInputHandler>,
68 pub(crate) tooltip_request: Option<TooltipRequest>,
69 pub(crate) cursor_styles: FxHashMap<EntityId, CursorStyle>,
70 pub(crate) requested_cursor_style: Option<CursorStyle>,
71 pub(crate) view_stack: Vec<EntityId>,
72 pub(crate) reused_views: FxHashSet<EntityId>,
73
74 #[cfg(any(test, feature = "test-support"))]
75 pub(crate) debug_bounds: FxHashMap<String, Bounds<Pixels>>,
76}
77
78impl Frame {
79 pub(crate) fn new(dispatch_tree: DispatchTree) -> Self {
80 Frame {
81 focus: None,
82 window_active: false,
83 element_states: FxHashMap::default(),
84 mouse_listeners: FxHashMap::default(),
85 dispatch_tree,
86 scene: Scene::default(),
87 depth_map: Vec::new(),
88 z_index_stack: StackingOrder::default(),
89 next_stacking_order_ids: vec![0],
90 next_root_z_index: 0,
91 content_mask_stack: Vec::new(),
92 element_offset_stack: Vec::new(),
93 requested_input_handler: None,
94 tooltip_request: None,
95 cursor_styles: FxHashMap::default(),
96 requested_cursor_style: None,
97 view_stack: Vec::new(),
98 reused_views: FxHashSet::default(),
99
100 #[cfg(any(test, feature = "test-support"))]
101 debug_bounds: FxHashMap::default(),
102 }
103 }
104
105 pub(crate) fn clear(&mut self) {
106 self.element_states.clear();
107 self.mouse_listeners.values_mut().for_each(Vec::clear);
108 self.dispatch_tree.clear();
109 self.depth_map.clear();
110 self.next_stacking_order_ids = vec![0];
111 self.next_root_z_index = 0;
112 self.reused_views.clear();
113 self.scene.clear();
114 self.requested_input_handler.take();
115 self.tooltip_request.take();
116 self.cursor_styles.clear();
117 self.requested_cursor_style.take();
118 debug_assert_eq!(self.view_stack.len(), 0);
119 }
120
121 pub(crate) fn focus_path(&self) -> SmallVec<[FocusId; 8]> {
122 self.focus
123 .map(|focus_id| self.dispatch_tree.focus_path(focus_id))
124 .unwrap_or_default()
125 }
126
127 pub(crate) fn finish(&mut self, prev_frame: &mut Self) {
128 // Reuse mouse listeners that didn't change since the last frame.
129 for (type_id, listeners) in &mut prev_frame.mouse_listeners {
130 let next_listeners = self.mouse_listeners.entry(*type_id).or_default();
131 for (order, view_id, listener) in listeners.drain(..) {
132 if self.reused_views.contains(&view_id) {
133 next_listeners.push((order, view_id, listener));
134 }
135 }
136 }
137
138 // Reuse entries in the depth map that didn't change since the last frame.
139 for (order, view_id, bounds) in prev_frame.depth_map.drain(..) {
140 if self.reused_views.contains(&view_id) {
141 match self
142 .depth_map
143 .binary_search_by(|(level, _, _)| order.cmp(level))
144 {
145 Ok(i) | Err(i) => self.depth_map.insert(i, (order, view_id, bounds)),
146 }
147 }
148 }
149
150 // Retain element states for views that didn't change since the last frame.
151 for (element_id, state) in prev_frame.element_states.drain() {
152 if self.reused_views.contains(&state.parent_view_id) {
153 self.element_states.entry(element_id).or_insert(state);
154 }
155 }
156
157 // Reuse geometry that didn't change since the last frame.
158 self.scene
159 .reuse_views(&self.reused_views, &mut prev_frame.scene);
160 self.scene.finish();
161 }
162}
163
164/// This context is used for assisting in the implementation of the element trait
165#[derive(Deref, DerefMut)]
166pub struct ElementContext<'a> {
167 pub(crate) cx: WindowContext<'a>,
168}
169
170impl<'a> WindowContext<'a> {
171 /// Convert this window context into an ElementContext in this callback.
172 /// If you need to use this method, you're probably intermixing the imperative
173 /// and declarative APIs, which is not recommended.
174 pub fn with_element_context<R>(&mut self, f: impl FnOnce(&mut ElementContext) -> R) -> R {
175 f(&mut ElementContext {
176 cx: WindowContext::new(self.app, self.window),
177 })
178 }
179}
180
181impl<'a> Borrow<AppContext> for ElementContext<'a> {
182 fn borrow(&self) -> &AppContext {
183 self.cx.app
184 }
185}
186
187impl<'a> BorrowMut<AppContext> for ElementContext<'a> {
188 fn borrow_mut(&mut self) -> &mut AppContext {
189 self.cx.borrow_mut()
190 }
191}
192
193impl<'a> Borrow<WindowContext<'a>> for ElementContext<'a> {
194 fn borrow(&self) -> &WindowContext<'a> {
195 &self.cx
196 }
197}
198
199impl<'a> BorrowMut<WindowContext<'a>> for ElementContext<'a> {
200 fn borrow_mut(&mut self) -> &mut WindowContext<'a> {
201 &mut self.cx
202 }
203}
204
205impl<'a> Borrow<Window> for ElementContext<'a> {
206 fn borrow(&self) -> &Window {
207 self.cx.window
208 }
209}
210
211impl<'a> BorrowMut<Window> for ElementContext<'a> {
212 fn borrow_mut(&mut self) -> &mut Window {
213 self.cx.borrow_mut()
214 }
215}
216
217impl<'a> Context for ElementContext<'a> {
218 type Result<T> = <WindowContext<'a> as Context>::Result<T>;
219
220 fn new_model<T: 'static>(
221 &mut self,
222 build_model: impl FnOnce(&mut crate::ModelContext<'_, T>) -> T,
223 ) -> Self::Result<crate::Model<T>> {
224 self.cx.new_model(build_model)
225 }
226
227 fn update_model<T, R>(
228 &mut self,
229 handle: &crate::Model<T>,
230 update: impl FnOnce(&mut T, &mut crate::ModelContext<'_, T>) -> R,
231 ) -> Self::Result<R>
232 where
233 T: 'static,
234 {
235 self.cx.update_model(handle, update)
236 }
237
238 fn read_model<T, R>(
239 &self,
240 handle: &crate::Model<T>,
241 read: impl FnOnce(&T, &AppContext) -> R,
242 ) -> Self::Result<R>
243 where
244 T: 'static,
245 {
246 self.cx.read_model(handle, read)
247 }
248
249 fn update_window<T, F>(&mut self, window: crate::AnyWindowHandle, f: F) -> Result<T>
250 where
251 F: FnOnce(crate::AnyView, &mut WindowContext<'_>) -> T,
252 {
253 self.cx.update_window(window, f)
254 }
255
256 fn read_window<T, R>(
257 &self,
258 window: &crate::WindowHandle<T>,
259 read: impl FnOnce(crate::View<T>, &AppContext) -> R,
260 ) -> Result<R>
261 where
262 T: 'static,
263 {
264 self.cx.read_window(window, read)
265 }
266}
267
268impl<'a> VisualContext for ElementContext<'a> {
269 fn new_view<V>(
270 &mut self,
271 build_view: impl FnOnce(&mut crate::ViewContext<'_, V>) -> V,
272 ) -> Self::Result<crate::View<V>>
273 where
274 V: 'static + Render,
275 {
276 self.cx.new_view(build_view)
277 }
278
279 fn update_view<V: 'static, R>(
280 &mut self,
281 view: &crate::View<V>,
282 update: impl FnOnce(&mut V, &mut crate::ViewContext<'_, V>) -> R,
283 ) -> Self::Result<R> {
284 self.cx.update_view(view, update)
285 }
286
287 fn replace_root_view<V>(
288 &mut self,
289 build_view: impl FnOnce(&mut crate::ViewContext<'_, V>) -> V,
290 ) -> Self::Result<crate::View<V>>
291 where
292 V: 'static + Render,
293 {
294 self.cx.replace_root_view(build_view)
295 }
296
297 fn focus_view<V>(&mut self, view: &crate::View<V>) -> Self::Result<()>
298 where
299 V: crate::FocusableView,
300 {
301 self.cx.focus_view(view)
302 }
303
304 fn dismiss_view<V>(&mut self, view: &crate::View<V>) -> Self::Result<()>
305 where
306 V: crate::ManagedView,
307 {
308 self.cx.dismiss_view(view)
309 }
310}
311
312impl<'a> ElementContext<'a> {
313 pub(crate) fn reuse_view(&mut self, next_stacking_order_id: u16) {
314 let view_id = self.parent_view_id();
315 let grafted_view_ids = self
316 .cx
317 .window
318 .next_frame
319 .dispatch_tree
320 .reuse_view(view_id, &mut self.cx.window.rendered_frame.dispatch_tree);
321 for view_id in grafted_view_ids {
322 assert!(self.window.next_frame.reused_views.insert(view_id));
323
324 // Reuse the previous input handler requested during painting of the reused view.
325 if self
326 .window
327 .rendered_frame
328 .requested_input_handler
329 .as_ref()
330 .map_or(false, |requested| requested.view_id == view_id)
331 {
332 self.window.next_frame.requested_input_handler =
333 self.window.rendered_frame.requested_input_handler.take();
334 }
335
336 // Reuse the tooltip previously requested during painting of the reused view.
337 if self
338 .window
339 .rendered_frame
340 .tooltip_request
341 .as_ref()
342 .map_or(false, |requested| requested.view_id == view_id)
343 {
344 self.window.next_frame.tooltip_request =
345 self.window.rendered_frame.tooltip_request.take();
346 }
347
348 // Reuse the cursor styles previously requested during painting of the reused view.
349 if let Some(style) = self.window.rendered_frame.cursor_styles.remove(&view_id) {
350 self.window.next_frame.cursor_styles.insert(view_id, style);
351 self.window.next_frame.requested_cursor_style = Some(style);
352 }
353 }
354
355 debug_assert!(
356 next_stacking_order_id
357 >= self
358 .window
359 .next_frame
360 .next_stacking_order_ids
361 .last()
362 .copied()
363 .unwrap()
364 );
365 *self
366 .window
367 .next_frame
368 .next_stacking_order_ids
369 .last_mut()
370 .unwrap() = next_stacking_order_id;
371 }
372
373 /// Push a text style onto the stack, and call a function with that style active.
374 /// Use [`AppContext::text_style`] to get the current, combined text style.
375 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
376 where
377 F: FnOnce(&mut Self) -> R,
378 {
379 if let Some(style) = style {
380 self.push_text_style(style);
381 let result = f(self);
382 self.pop_text_style();
383 result
384 } else {
385 f(self)
386 }
387 }
388
389 /// Updates the cursor style at the platform level.
390 pub fn set_cursor_style(&mut self, style: CursorStyle) {
391 let view_id = self.parent_view_id();
392 self.window.next_frame.cursor_styles.insert(view_id, style);
393 self.window.next_frame.requested_cursor_style = Some(style);
394 }
395
396 /// Sets a tooltip to be rendered for the upcoming frame
397 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) {
398 let view_id = self.parent_view_id();
399 self.window.next_frame.tooltip_request = Some(TooltipRequest { view_id, tooltip });
400 }
401
402 /// Pushes the given element id onto the global stack and invokes the given closure
403 /// with a `GlobalElementId`, which disambiguates the given id in the context of its ancestor
404 /// ids. Because elements are discarded and recreated on each frame, the `GlobalElementId` is
405 /// used to associate state with identified elements across separate frames.
406 pub fn with_element_id<R>(
407 &mut self,
408 id: Option<impl Into<ElementId>>,
409 f: impl FnOnce(&mut Self) -> R,
410 ) -> R {
411 if let Some(id) = id.map(Into::into) {
412 let window = self.window_mut();
413 window.element_id_stack.push(id);
414 let result = f(self);
415 let window: &mut Window = self.borrow_mut();
416 window.element_id_stack.pop();
417 result
418 } else {
419 f(self)
420 }
421 }
422
423 /// Invoke the given function with the given content mask after intersecting it
424 /// with the current mask.
425 pub fn with_content_mask<R>(
426 &mut self,
427 mask: Option<ContentMask<Pixels>>,
428 f: impl FnOnce(&mut Self) -> R,
429 ) -> R {
430 if let Some(mask) = mask {
431 let mask = mask.intersect(&self.content_mask());
432 self.window_mut().next_frame.content_mask_stack.push(mask);
433 let result = f(self);
434 self.window_mut().next_frame.content_mask_stack.pop();
435 result
436 } else {
437 f(self)
438 }
439 }
440
441 /// Invoke the given function with the content mask reset to that
442 /// of the window.
443 pub fn break_content_mask<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
444 let mask = ContentMask {
445 bounds: Bounds {
446 origin: Point::default(),
447 size: self.window().viewport_size,
448 },
449 };
450
451 let new_root_z_index = post_inc(&mut self.window_mut().next_frame.next_root_z_index);
452 let new_stacking_order_id = post_inc(
453 self.window_mut()
454 .next_frame
455 .next_stacking_order_ids
456 .last_mut()
457 .unwrap(),
458 );
459 let new_context = StackingContext {
460 z_index: new_root_z_index,
461 id: new_stacking_order_id,
462 };
463
464 let old_stacking_order = mem::take(&mut self.window_mut().next_frame.z_index_stack);
465
466 self.window_mut().next_frame.z_index_stack.push(new_context);
467 self.window_mut().next_frame.content_mask_stack.push(mask);
468 let result = f(self);
469 self.window_mut().next_frame.content_mask_stack.pop();
470 self.window_mut().next_frame.z_index_stack = old_stacking_order;
471
472 result
473 }
474
475 /// Called during painting to invoke the given closure in a new stacking context. The given
476 /// z-index is interpreted relative to the previous call to `stack`.
477 pub fn with_z_index<R>(&mut self, z_index: u16, f: impl FnOnce(&mut Self) -> R) -> R {
478 let new_stacking_order_id = post_inc(
479 self.window_mut()
480 .next_frame
481 .next_stacking_order_ids
482 .last_mut()
483 .unwrap(),
484 );
485 self.window_mut().next_frame.next_stacking_order_ids.push(0);
486 let new_context = StackingContext {
487 z_index,
488 id: new_stacking_order_id,
489 };
490
491 self.window_mut().next_frame.z_index_stack.push(new_context);
492 let result = f(self);
493 self.window_mut().next_frame.z_index_stack.pop();
494
495 self.window_mut().next_frame.next_stacking_order_ids.pop();
496
497 result
498 }
499
500 /// Updates the global element offset relative to the current offset. This is used to implement
501 /// scrolling.
502 pub fn with_element_offset<R>(
503 &mut self,
504 offset: Point<Pixels>,
505 f: impl FnOnce(&mut Self) -> R,
506 ) -> R {
507 if offset.is_zero() {
508 return f(self);
509 };
510
511 let abs_offset = self.element_offset() + offset;
512 self.with_absolute_element_offset(abs_offset, f)
513 }
514
515 /// Updates the global element offset based on the given offset. This is used to implement
516 /// drag handles and other manual painting of elements.
517 pub fn with_absolute_element_offset<R>(
518 &mut self,
519 offset: Point<Pixels>,
520 f: impl FnOnce(&mut Self) -> R,
521 ) -> R {
522 self.window_mut()
523 .next_frame
524 .element_offset_stack
525 .push(offset);
526 let result = f(self);
527 self.window_mut().next_frame.element_offset_stack.pop();
528 result
529 }
530
531 /// Obtain the current element offset.
532 pub fn element_offset(&self) -> Point<Pixels> {
533 self.window()
534 .next_frame
535 .element_offset_stack
536 .last()
537 .copied()
538 .unwrap_or_default()
539 }
540
541 /// Obtain the current content mask.
542 pub fn content_mask(&self) -> ContentMask<Pixels> {
543 self.window()
544 .next_frame
545 .content_mask_stack
546 .last()
547 .cloned()
548 .unwrap_or_else(|| ContentMask {
549 bounds: Bounds {
550 origin: Point::default(),
551 size: self.window().viewport_size,
552 },
553 })
554 }
555
556 /// The size of an em for the base font of the application. Adjusting this value allows the
557 /// UI to scale, just like zooming a web page.
558 pub fn rem_size(&self) -> Pixels {
559 self.window().rem_size
560 }
561
562 /// Updates or initializes state for an element with the given id that lives across multiple
563 /// frames. If an element with this ID existed in the rendered frame, its state will be passed
564 /// to the given closure. The state returned by the closure will be stored so it can be referenced
565 /// when drawing the next frame.
566 pub fn with_element_state<S, R>(
567 &mut self,
568 id: ElementId,
569 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
570 ) -> R
571 where
572 S: 'static,
573 {
574 self.with_element_id(Some(id), |cx| {
575 let global_id = cx.window().element_id_stack.clone();
576
577 if let Some(any) = cx
578 .window_mut()
579 .next_frame
580 .element_states
581 .remove(&global_id)
582 .or_else(|| {
583 cx.window_mut()
584 .rendered_frame
585 .element_states
586 .remove(&global_id)
587 })
588 {
589 let ElementStateBox {
590 inner,
591 parent_view_id,
592 #[cfg(debug_assertions)]
593 type_name
594 } = any;
595 // Using the extra inner option to avoid needing to reallocate a new box.
596 let mut state_box = inner
597 .downcast::<Option<S>>()
598 .map_err(|_| {
599 #[cfg(debug_assertions)]
600 {
601 anyhow::anyhow!(
602 "invalid element state type for id, requested_type {:?}, actual type: {:?}",
603 std::any::type_name::<S>(),
604 type_name
605 )
606 }
607
608 #[cfg(not(debug_assertions))]
609 {
610 anyhow::anyhow!(
611 "invalid element state type for id, requested_type {:?}",
612 std::any::type_name::<S>(),
613 )
614 }
615 })
616 .unwrap();
617
618 // Actual: Option<AnyElement> <- View
619 // Requested: () <- AnyElement
620 let state = state_box
621 .take()
622 .expect("element state is already on the stack");
623 let (result, state) = f(Some(state), cx);
624 state_box.replace(state);
625 cx.window_mut()
626 .next_frame
627 .element_states
628 .insert(global_id, ElementStateBox {
629 inner: state_box,
630 parent_view_id,
631 #[cfg(debug_assertions)]
632 type_name
633 });
634 result
635 } else {
636 let (result, state) = f(None, cx);
637 let parent_view_id = cx.parent_view_id();
638 cx.window_mut()
639 .next_frame
640 .element_states
641 .insert(global_id,
642 ElementStateBox {
643 inner: Box::new(Some(state)),
644 parent_view_id,
645 #[cfg(debug_assertions)]
646 type_name: std::any::type_name::<S>()
647 }
648
649 );
650 result
651 }
652 })
653 }
654 /// Paint one or more drop shadows into the scene for the next frame at the current z-index.
655 pub fn paint_shadows(
656 &mut self,
657 bounds: Bounds<Pixels>,
658 corner_radii: Corners<Pixels>,
659 shadows: &[BoxShadow],
660 ) {
661 let scale_factor = self.scale_factor();
662 let content_mask = self.content_mask();
663 let view_id = self.parent_view_id();
664 let window = &mut *self.window;
665 for shadow in shadows {
666 let mut shadow_bounds = bounds;
667 shadow_bounds.origin += shadow.offset;
668 shadow_bounds.dilate(shadow.spread_radius);
669 window.next_frame.scene.insert(
670 &window.next_frame.z_index_stack,
671 Shadow {
672 view_id: view_id.into(),
673 layer_id: 0,
674 order: 0,
675 bounds: shadow_bounds.scale(scale_factor),
676 content_mask: content_mask.scale(scale_factor),
677 corner_radii: corner_radii.scale(scale_factor),
678 color: shadow.color,
679 blur_radius: shadow.blur_radius.scale(scale_factor),
680 pad: 0,
681 },
682 );
683 }
684 }
685
686 /// Paint one or more quads into the scene for the next frame at the current stacking context.
687 /// Quads are colored rectangular regions with an optional background, border, and corner radius.
688 /// see [`fill`](crate::fill), [`outline`](crate::outline), and [`quad`](crate::quad) to construct this type.
689 pub fn paint_quad(&mut self, quad: PaintQuad) {
690 let scale_factor = self.scale_factor();
691 let content_mask = self.content_mask();
692 let view_id = self.parent_view_id();
693
694 let window = &mut *self.window;
695 window.next_frame.scene.insert(
696 &window.next_frame.z_index_stack,
697 Quad {
698 view_id: view_id.into(),
699 layer_id: 0,
700 order: 0,
701 bounds: quad.bounds.scale(scale_factor),
702 content_mask: content_mask.scale(scale_factor),
703 background: quad.background,
704 border_color: quad.border_color,
705 corner_radii: quad.corner_radii.scale(scale_factor),
706 border_widths: quad.border_widths.scale(scale_factor),
707 },
708 );
709 }
710
711 /// Paint the given `Path` into the scene for the next frame at the current z-index.
712 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Hsla>) {
713 let scale_factor = self.scale_factor();
714 let content_mask = self.content_mask();
715 let view_id = self.parent_view_id();
716
717 path.content_mask = content_mask;
718 path.color = color.into();
719 path.view_id = view_id.into();
720 let window = &mut *self.window;
721 window
722 .next_frame
723 .scene
724 .insert(&window.next_frame.z_index_stack, path.scale(scale_factor));
725 }
726
727 /// Paint an underline into the scene for the next frame at the current z-index.
728 pub fn paint_underline(
729 &mut self,
730 origin: Point<Pixels>,
731 width: Pixels,
732 style: &UnderlineStyle,
733 ) {
734 let scale_factor = self.scale_factor();
735 let height = if style.wavy {
736 style.thickness * 3.
737 } else {
738 style.thickness
739 };
740 let bounds = Bounds {
741 origin,
742 size: size(width, height),
743 };
744 let content_mask = self.content_mask();
745 let view_id = self.parent_view_id();
746
747 let window = &mut *self.window;
748 window.next_frame.scene.insert(
749 &window.next_frame.z_index_stack,
750 Underline {
751 view_id: view_id.into(),
752 layer_id: 0,
753 order: 0,
754 bounds: bounds.scale(scale_factor),
755 content_mask: content_mask.scale(scale_factor),
756 color: style.color.unwrap_or_default(),
757 thickness: style.thickness.scale(scale_factor),
758 wavy: style.wavy,
759 },
760 );
761 }
762
763 /// Paint a strikethrough into the scene for the next frame at the current z-index.
764 pub fn paint_strikethrough(
765 &mut self,
766 origin: Point<Pixels>,
767 width: Pixels,
768 style: &StrikethroughStyle,
769 ) {
770 let scale_factor = self.scale_factor();
771 let height = style.thickness;
772 let bounds = Bounds {
773 origin,
774 size: size(width, height),
775 };
776 let content_mask = self.content_mask();
777 let view_id = self.parent_view_id();
778
779 let window = &mut *self.window;
780 window.next_frame.scene.insert(
781 &window.next_frame.z_index_stack,
782 Underline {
783 view_id: view_id.into(),
784 layer_id: 0,
785 order: 0,
786 bounds: bounds.scale(scale_factor),
787 content_mask: content_mask.scale(scale_factor),
788 thickness: style.thickness.scale(scale_factor),
789 color: style.color.unwrap_or_default(),
790 wavy: false,
791 },
792 );
793 }
794
795 /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
796 ///
797 /// The y component of the origin is the baseline of the glyph.
798 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
799 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
800 /// This method is only useful if you need to paint a single glyph that has already been shaped.
801 pub fn paint_glyph(
802 &mut self,
803 origin: Point<Pixels>,
804 font_id: FontId,
805 glyph_id: GlyphId,
806 font_size: Pixels,
807 color: Hsla,
808 ) -> Result<()> {
809 let scale_factor = self.scale_factor();
810 let glyph_origin = origin.scale(scale_factor);
811 let subpixel_variant = Point {
812 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
813 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
814 };
815 let params = RenderGlyphParams {
816 font_id,
817 glyph_id,
818 font_size,
819 subpixel_variant,
820 scale_factor,
821 is_emoji: false,
822 };
823
824 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
825 if !raster_bounds.is_zero() {
826 let tile =
827 self.window
828 .sprite_atlas
829 .get_or_insert_with(¶ms.clone().into(), &mut || {
830 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
831 Ok((size, Cow::Owned(bytes)))
832 })?;
833 let bounds = Bounds {
834 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
835 size: tile.bounds.size.map(Into::into),
836 };
837 let content_mask = self.content_mask().scale(scale_factor);
838 let view_id = self.parent_view_id();
839 let window = &mut *self.window;
840 window.next_frame.scene.insert(
841 &window.next_frame.z_index_stack,
842 MonochromeSprite {
843 view_id: view_id.into(),
844 layer_id: 0,
845 order: 0,
846 bounds,
847 content_mask,
848 color,
849 tile,
850 },
851 );
852 }
853 Ok(())
854 }
855
856 /// Paints an emoji glyph into the scene for the next frame at the current z-index.
857 ///
858 /// The y component of the origin is the baseline of the glyph.
859 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
860 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
861 /// This method is only useful if you need to paint a single emoji that has already been shaped.
862 pub fn paint_emoji(
863 &mut self,
864 origin: Point<Pixels>,
865 font_id: FontId,
866 glyph_id: GlyphId,
867 font_size: Pixels,
868 ) -> Result<()> {
869 let scale_factor = self.scale_factor();
870 let glyph_origin = origin.scale(scale_factor);
871 let params = RenderGlyphParams {
872 font_id,
873 glyph_id,
874 font_size,
875 // We don't render emojis with subpixel variants.
876 subpixel_variant: Default::default(),
877 scale_factor,
878 is_emoji: true,
879 };
880
881 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
882 if !raster_bounds.is_zero() {
883 let tile =
884 self.window
885 .sprite_atlas
886 .get_or_insert_with(¶ms.clone().into(), &mut || {
887 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
888 Ok((size, Cow::Owned(bytes)))
889 })?;
890 let bounds = Bounds {
891 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
892 size: tile.bounds.size.map(Into::into),
893 };
894 let content_mask = self.content_mask().scale(scale_factor);
895 let view_id = self.parent_view_id();
896 let window = &mut *self.window;
897
898 window.next_frame.scene.insert(
899 &window.next_frame.z_index_stack,
900 PolychromeSprite {
901 view_id: view_id.into(),
902 layer_id: 0,
903 order: 0,
904 bounds,
905 corner_radii: Default::default(),
906 content_mask,
907 tile,
908 grayscale: false,
909 pad: 0,
910 },
911 );
912 }
913 Ok(())
914 }
915
916 /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
917 pub fn paint_svg(
918 &mut self,
919 bounds: Bounds<Pixels>,
920 path: SharedString,
921 color: Hsla,
922 ) -> Result<()> {
923 let scale_factor = self.scale_factor();
924 let bounds = bounds.scale(scale_factor);
925 // Render the SVG at twice the size to get a higher quality result.
926 let params = RenderSvgParams {
927 path,
928 size: bounds
929 .size
930 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
931 };
932
933 let tile =
934 self.window
935 .sprite_atlas
936 .get_or_insert_with(¶ms.clone().into(), &mut || {
937 let bytes = self.svg_renderer.render(¶ms)?;
938 Ok((params.size, Cow::Owned(bytes)))
939 })?;
940 let content_mask = self.content_mask().scale(scale_factor);
941 let view_id = self.parent_view_id();
942
943 let window = &mut *self.window;
944 window.next_frame.scene.insert(
945 &window.next_frame.z_index_stack,
946 MonochromeSprite {
947 view_id: view_id.into(),
948 layer_id: 0,
949 order: 0,
950 bounds,
951 content_mask,
952 color,
953 tile,
954 },
955 );
956
957 Ok(())
958 }
959
960 /// Paint an image into the scene for the next frame at the current z-index.
961 pub fn paint_image(
962 &mut self,
963 bounds: Bounds<Pixels>,
964 corner_radii: Corners<Pixels>,
965 data: Arc<ImageData>,
966 grayscale: bool,
967 ) -> Result<()> {
968 let scale_factor = self.scale_factor();
969 let bounds = bounds.scale(scale_factor);
970 let params = RenderImageParams { image_id: data.id };
971
972 let tile = self
973 .window
974 .sprite_atlas
975 .get_or_insert_with(¶ms.clone().into(), &mut || {
976 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
977 })?;
978 let content_mask = self.content_mask().scale(scale_factor);
979 let corner_radii = corner_radii.scale(scale_factor);
980 let view_id = self.parent_view_id();
981
982 let window = &mut *self.window;
983 window.next_frame.scene.insert(
984 &window.next_frame.z_index_stack,
985 PolychromeSprite {
986 view_id: view_id.into(),
987 layer_id: 0,
988 order: 0,
989 bounds,
990 content_mask,
991 corner_radii,
992 tile,
993 grayscale,
994 pad: 0,
995 },
996 );
997 Ok(())
998 }
999
1000 /// Paint a surface into the scene for the next frame at the current z-index.
1001 #[cfg(target_os = "macos")]
1002 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
1003 let scale_factor = self.scale_factor();
1004 let bounds = bounds.scale(scale_factor);
1005 let content_mask = self.content_mask().scale(scale_factor);
1006 let view_id = self.parent_view_id();
1007 let window = &mut *self.window;
1008 window.next_frame.scene.insert(
1009 &window.next_frame.z_index_stack,
1010 crate::Surface {
1011 view_id: view_id.into(),
1012 layer_id: 0,
1013 order: 0,
1014 bounds,
1015 content_mask,
1016 image_buffer,
1017 },
1018 );
1019 }
1020
1021 #[must_use]
1022 /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
1023 /// layout is being requested, along with the layout ids of any children. This method is called during
1024 /// calls to the `Element::layout` trait method and enables any element to participate in layout.
1025 pub fn request_layout(
1026 &mut self,
1027 style: &Style,
1028 children: impl IntoIterator<Item = LayoutId>,
1029 ) -> LayoutId {
1030 self.app.layout_id_buffer.clear();
1031 self.app.layout_id_buffer.extend(children);
1032 let rem_size = self.rem_size();
1033
1034 self.cx
1035 .window
1036 .layout_engine
1037 .as_mut()
1038 .unwrap()
1039 .request_layout(style, rem_size, &self.cx.app.layout_id_buffer)
1040 }
1041
1042 /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
1043 /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
1044 /// determine the element's size. One place this is used internally is when measuring text.
1045 ///
1046 /// The given closure is invoked at layout time with the known dimensions and available space and
1047 /// returns a `Size`.
1048 pub fn request_measured_layout<
1049 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
1050 + 'static,
1051 >(
1052 &mut self,
1053 style: Style,
1054 measure: F,
1055 ) -> LayoutId {
1056 let rem_size = self.rem_size();
1057 self.window
1058 .layout_engine
1059 .as_mut()
1060 .unwrap()
1061 .request_measured_layout(style, rem_size, measure)
1062 }
1063
1064 /// Compute the layout for the given id within the given available space.
1065 /// This method is called for its side effect, typically by the framework prior to painting.
1066 /// After calling it, you can request the bounds of the given layout node id or any descendant.
1067 pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
1068 let mut layout_engine = self.window.layout_engine.take().unwrap();
1069 layout_engine.compute_layout(layout_id, available_space, self);
1070 self.window.layout_engine = Some(layout_engine);
1071 }
1072
1073 /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by
1074 /// GPUI itself automatically in order to pass your element its `Bounds` automatically.
1075 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
1076 let mut bounds = self
1077 .window
1078 .layout_engine
1079 .as_mut()
1080 .unwrap()
1081 .layout_bounds(layout_id)
1082 .map(Into::into);
1083 bounds.origin += self.element_offset();
1084 bounds
1085 }
1086
1087 pub(crate) fn layout_style(&self, layout_id: LayoutId) -> Option<&Style> {
1088 self.window
1089 .layout_engine
1090 .as_ref()
1091 .unwrap()
1092 .requested_style(layout_id)
1093 }
1094
1095 /// Called during painting to track which z-index is on top at each pixel position
1096 pub fn add_opaque_layer(&mut self, bounds: Bounds<Pixels>) {
1097 let stacking_order = self.window.next_frame.z_index_stack.clone();
1098 let view_id = self.parent_view_id();
1099 let depth_map = &mut self.window.next_frame.depth_map;
1100 match depth_map.binary_search_by(|(level, _, _)| stacking_order.cmp(level)) {
1101 Ok(i) | Err(i) => depth_map.insert(i, (stacking_order, view_id, bounds)),
1102 }
1103 }
1104
1105 /// Invoke the given function with the given focus handle present on the key dispatch stack.
1106 /// If you want an element to participate in key dispatch, use this method to push its key context and focus handle into the stack during paint.
1107 pub fn with_key_dispatch<R>(
1108 &mut self,
1109 context: Option<KeyContext>,
1110 focus_handle: Option<FocusHandle>,
1111 f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
1112 ) -> R {
1113 let window = &mut self.window;
1114 let focus_id = focus_handle.as_ref().map(|handle| handle.id);
1115 window
1116 .next_frame
1117 .dispatch_tree
1118 .push_node(context.clone(), focus_id, None);
1119
1120 let result = f(focus_handle, self);
1121
1122 self.window.next_frame.dispatch_tree.pop_node();
1123
1124 result
1125 }
1126
1127 /// Invoke the given function with the given view id present on the view stack.
1128 /// This is a fairly low-level method used to layout views.
1129 pub fn with_view_id<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
1130 let text_system = self.text_system().clone();
1131 text_system.with_view(view_id, || {
1132 if self.window.next_frame.view_stack.last() == Some(&view_id) {
1133 f(self)
1134 } else {
1135 self.window.next_frame.view_stack.push(view_id);
1136 let result = f(self);
1137 self.window.next_frame.view_stack.pop();
1138 result
1139 }
1140 })
1141 }
1142
1143 /// Invoke the given function with the given view id present on the view stack.
1144 /// This is a fairly low-level method used to paint views.
1145 pub fn paint_view<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
1146 let text_system = self.text_system().clone();
1147 text_system.with_view(view_id, || {
1148 if self.window.next_frame.view_stack.last() == Some(&view_id) {
1149 f(self)
1150 } else {
1151 self.window.next_frame.view_stack.push(view_id);
1152 self.window
1153 .next_frame
1154 .dispatch_tree
1155 .push_node(None, None, Some(view_id));
1156 let result = f(self);
1157 self.window.next_frame.dispatch_tree.pop_node();
1158 self.window.next_frame.view_stack.pop();
1159 result
1160 }
1161 })
1162 }
1163
1164 /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
1165 /// platform to receive textual input with proper integration with concerns such
1166 /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
1167 /// rendered.
1168 ///
1169 /// [element_input_handler]: crate::ElementInputHandler
1170 pub fn handle_input(&mut self, focus_handle: &FocusHandle, input_handler: impl InputHandler) {
1171 if focus_handle.is_focused(self) {
1172 let view_id = self.parent_view_id();
1173 self.window.next_frame.requested_input_handler = Some(RequestedInputHandler {
1174 view_id,
1175 handler: Some(PlatformInputHandler::new(
1176 self.to_async(),
1177 Box::new(input_handler),
1178 )),
1179 })
1180 }
1181 }
1182
1183 /// Register a mouse event listener on the window for the next frame. The type of event
1184 /// is determined by the first parameter of the given listener. When the next frame is rendered
1185 /// the listener will be cleared.
1186 pub fn on_mouse_event<Event: MouseEvent>(
1187 &mut self,
1188 mut handler: impl FnMut(&Event, DispatchPhase, &mut ElementContext) + 'static,
1189 ) {
1190 let view_id = self.parent_view_id();
1191 let order = self.window.next_frame.z_index_stack.clone();
1192 self.window
1193 .next_frame
1194 .mouse_listeners
1195 .entry(TypeId::of::<Event>())
1196 .or_default()
1197 .push((
1198 order,
1199 view_id,
1200 Box::new(
1201 move |event: &dyn Any, phase: DispatchPhase, cx: &mut ElementContext<'_>| {
1202 handler(event.downcast_ref().unwrap(), phase, cx)
1203 },
1204 ),
1205 ))
1206 }
1207
1208 /// Register a key event listener on the window for the next frame. The type of event
1209 /// is determined by the first parameter of the given listener. When the next frame is rendered
1210 /// the listener will be cleared.
1211 ///
1212 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1213 /// a specific need to register a global listener.
1214 pub fn on_key_event<Event: KeyEvent>(
1215 &mut self,
1216 listener: impl Fn(&Event, DispatchPhase, &mut ElementContext) + 'static,
1217 ) {
1218 self.window.next_frame.dispatch_tree.on_key_event(Rc::new(
1219 move |event: &dyn Any, phase, cx: &mut ElementContext<'_>| {
1220 if let Some(event) = event.downcast_ref::<Event>() {
1221 listener(event, phase, cx)
1222 }
1223 },
1224 ));
1225 }
1226}