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