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, KeymatchMode, LayoutId, MonochromeSprite,
36 MouseEvent, PaintQuad, Path, Pixels, PlatformInputHandler, Point, PolychromeSprite, Quad,
37 RenderGlyphParams, RenderImageParams, RenderSvgParams, Scene, Shadow, SharedString, Size,
38 StackingContext, StackingOrder, Style, TextStyleRefinement, Underline, UnderlineStyle, Window,
39 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: collections::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 /// Paints a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
764 ///
765 /// The y component of the origin is the baseline of the glyph.
766 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
767 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
768 /// This method is only useful if you need to paint a single glyph that has already been shaped.
769 pub fn paint_glyph(
770 &mut self,
771 origin: Point<Pixels>,
772 font_id: FontId,
773 glyph_id: GlyphId,
774 font_size: Pixels,
775 color: Hsla,
776 ) -> Result<()> {
777 let scale_factor = self.scale_factor();
778 let glyph_origin = origin.scale(scale_factor);
779 let subpixel_variant = Point {
780 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
781 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
782 };
783 let params = RenderGlyphParams {
784 font_id,
785 glyph_id,
786 font_size,
787 subpixel_variant,
788 scale_factor,
789 is_emoji: false,
790 };
791
792 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
793 if !raster_bounds.is_zero() {
794 let tile =
795 self.window
796 .sprite_atlas
797 .get_or_insert_with(¶ms.clone().into(), &mut || {
798 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
799 Ok((size, Cow::Owned(bytes)))
800 })?;
801 let bounds = Bounds {
802 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
803 size: tile.bounds.size.map(Into::into),
804 };
805 let content_mask = self.content_mask().scale(scale_factor);
806 let view_id = self.parent_view_id();
807 let window = &mut *self.window;
808 window.next_frame.scene.insert(
809 &window.next_frame.z_index_stack,
810 MonochromeSprite {
811 view_id: view_id.into(),
812 layer_id: 0,
813 order: 0,
814 bounds,
815 content_mask,
816 color,
817 tile,
818 },
819 );
820 }
821 Ok(())
822 }
823
824 /// Paints an emoji glyph into the scene for the next frame at the current z-index.
825 ///
826 /// The y component of the origin is the baseline of the glyph.
827 /// You should generally prefer to use the [`ShapedLine::paint`](crate::ShapedLine::paint) or
828 /// [`WrappedLine::paint`](crate::WrappedLine::paint) methods in the [`TextSystem`](crate::TextSystem).
829 /// This method is only useful if you need to paint a single emoji that has already been shaped.
830 pub fn paint_emoji(
831 &mut self,
832 origin: Point<Pixels>,
833 font_id: FontId,
834 glyph_id: GlyphId,
835 font_size: Pixels,
836 ) -> Result<()> {
837 let scale_factor = self.scale_factor();
838 let glyph_origin = origin.scale(scale_factor);
839 let params = RenderGlyphParams {
840 font_id,
841 glyph_id,
842 font_size,
843 // We don't render emojis with subpixel variants.
844 subpixel_variant: Default::default(),
845 scale_factor,
846 is_emoji: true,
847 };
848
849 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
850 if !raster_bounds.is_zero() {
851 let tile =
852 self.window
853 .sprite_atlas
854 .get_or_insert_with(¶ms.clone().into(), &mut || {
855 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
856 Ok((size, Cow::Owned(bytes)))
857 })?;
858 let bounds = Bounds {
859 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
860 size: tile.bounds.size.map(Into::into),
861 };
862 let content_mask = self.content_mask().scale(scale_factor);
863 let view_id = self.parent_view_id();
864 let window = &mut *self.window;
865
866 window.next_frame.scene.insert(
867 &window.next_frame.z_index_stack,
868 PolychromeSprite {
869 view_id: view_id.into(),
870 layer_id: 0,
871 order: 0,
872 bounds,
873 corner_radii: Default::default(),
874 content_mask,
875 tile,
876 grayscale: false,
877 pad: 0,
878 },
879 );
880 }
881 Ok(())
882 }
883
884 /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
885 pub fn paint_svg(
886 &mut self,
887 bounds: Bounds<Pixels>,
888 path: SharedString,
889 color: Hsla,
890 ) -> Result<()> {
891 let scale_factor = self.scale_factor();
892 let bounds = bounds.scale(scale_factor);
893 // Render the SVG at twice the size to get a higher quality result.
894 let params = RenderSvgParams {
895 path,
896 size: bounds
897 .size
898 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
899 };
900
901 let tile =
902 self.window
903 .sprite_atlas
904 .get_or_insert_with(¶ms.clone().into(), &mut || {
905 let bytes = self.svg_renderer.render(¶ms)?;
906 Ok((params.size, Cow::Owned(bytes)))
907 })?;
908 let content_mask = self.content_mask().scale(scale_factor);
909 let view_id = self.parent_view_id();
910
911 let window = &mut *self.window;
912 window.next_frame.scene.insert(
913 &window.next_frame.z_index_stack,
914 MonochromeSprite {
915 view_id: view_id.into(),
916 layer_id: 0,
917 order: 0,
918 bounds,
919 content_mask,
920 color,
921 tile,
922 },
923 );
924
925 Ok(())
926 }
927
928 /// Paint an image into the scene for the next frame at the current z-index.
929 pub fn paint_image(
930 &mut self,
931 bounds: Bounds<Pixels>,
932 corner_radii: Corners<Pixels>,
933 data: Arc<ImageData>,
934 grayscale: bool,
935 ) -> Result<()> {
936 let scale_factor = self.scale_factor();
937 let bounds = bounds.scale(scale_factor);
938 let params = RenderImageParams { image_id: data.id };
939
940 let tile = self
941 .window
942 .sprite_atlas
943 .get_or_insert_with(¶ms.clone().into(), &mut || {
944 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
945 })?;
946 let content_mask = self.content_mask().scale(scale_factor);
947 let corner_radii = corner_radii.scale(scale_factor);
948 let view_id = self.parent_view_id();
949
950 let window = &mut *self.window;
951 window.next_frame.scene.insert(
952 &window.next_frame.z_index_stack,
953 PolychromeSprite {
954 view_id: view_id.into(),
955 layer_id: 0,
956 order: 0,
957 bounds,
958 content_mask,
959 corner_radii,
960 tile,
961 grayscale,
962 pad: 0,
963 },
964 );
965 Ok(())
966 }
967
968 /// Paint a surface into the scene for the next frame at the current z-index.
969 #[cfg(target_os = "macos")]
970 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
971 let scale_factor = self.scale_factor();
972 let bounds = bounds.scale(scale_factor);
973 let content_mask = self.content_mask().scale(scale_factor);
974 let view_id = self.parent_view_id();
975 let window = &mut *self.window;
976 window.next_frame.scene.insert(
977 &window.next_frame.z_index_stack,
978 crate::Surface {
979 view_id: view_id.into(),
980 layer_id: 0,
981 order: 0,
982 bounds,
983 content_mask,
984 image_buffer,
985 },
986 );
987 }
988
989 #[must_use]
990 /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
991 /// layout is being requested, along with the layout ids of any children. This method is called during
992 /// calls to the `Element::layout` trait method and enables any element to participate in layout.
993 pub fn request_layout(
994 &mut self,
995 style: &Style,
996 children: impl IntoIterator<Item = LayoutId>,
997 ) -> LayoutId {
998 self.app.layout_id_buffer.clear();
999 self.app.layout_id_buffer.extend(children);
1000 let rem_size = self.rem_size();
1001
1002 self.cx
1003 .window
1004 .layout_engine
1005 .as_mut()
1006 .unwrap()
1007 .request_layout(style, rem_size, &self.cx.app.layout_id_buffer)
1008 }
1009
1010 /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
1011 /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
1012 /// determine the element's size. One place this is used internally is when measuring text.
1013 ///
1014 /// The given closure is invoked at layout time with the known dimensions and available space and
1015 /// returns a `Size`.
1016 pub fn request_measured_layout<
1017 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
1018 + 'static,
1019 >(
1020 &mut self,
1021 style: Style,
1022 measure: F,
1023 ) -> LayoutId {
1024 let rem_size = self.rem_size();
1025 self.window
1026 .layout_engine
1027 .as_mut()
1028 .unwrap()
1029 .request_measured_layout(style, rem_size, measure)
1030 }
1031
1032 /// Compute the layout for the given id within the given available space.
1033 /// This method is called for its side effect, typically by the framework prior to painting.
1034 /// After calling it, you can request the bounds of the given layout node id or any descendant.
1035 pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
1036 let mut layout_engine = self.window.layout_engine.take().unwrap();
1037 layout_engine.compute_layout(layout_id, available_space, self);
1038 self.window.layout_engine = Some(layout_engine);
1039 }
1040
1041 /// Obtain the bounds computed for the given LayoutId relative to the window. This method will usually be invoked by
1042 /// GPUI itself automatically in order to pass your element its `Bounds` automatically.
1043 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
1044 let mut bounds = self
1045 .window
1046 .layout_engine
1047 .as_mut()
1048 .unwrap()
1049 .layout_bounds(layout_id)
1050 .map(Into::into);
1051 bounds.origin += self.element_offset();
1052 bounds
1053 }
1054
1055 pub(crate) fn layout_style(&self, layout_id: LayoutId) -> Option<&Style> {
1056 self.window
1057 .layout_engine
1058 .as_ref()
1059 .unwrap()
1060 .requested_style(layout_id)
1061 }
1062
1063 /// Called during painting to track which z-index is on top at each pixel position
1064 pub fn add_opaque_layer(&mut self, bounds: Bounds<Pixels>) {
1065 let stacking_order = self.window.next_frame.z_index_stack.clone();
1066 let view_id = self.parent_view_id();
1067 let depth_map = &mut self.window.next_frame.depth_map;
1068 match depth_map.binary_search_by(|(level, _, _)| stacking_order.cmp(level)) {
1069 Ok(i) | Err(i) => depth_map.insert(i, (stacking_order, view_id, bounds)),
1070 }
1071 }
1072
1073 /// Invoke the given function with the given focus handle present on the key dispatch stack.
1074 /// 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.
1075 pub fn with_key_dispatch<R>(
1076 &mut self,
1077 context: Option<KeyContext>,
1078 focus_handle: Option<FocusHandle>,
1079 f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
1080 ) -> R {
1081 let window = &mut self.window;
1082 let focus_id = focus_handle.as_ref().map(|handle| handle.id);
1083 window
1084 .next_frame
1085 .dispatch_tree
1086 .push_node(context.clone(), focus_id, None);
1087
1088 let result = f(focus_handle, self);
1089
1090 self.window.next_frame.dispatch_tree.pop_node();
1091
1092 result
1093 }
1094
1095 /// Invoke the given function with the given view id present on the view stack.
1096 /// This is a fairly low-level method used to layout views.
1097 pub fn with_view_id<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
1098 let text_system = self.text_system().clone();
1099 text_system.with_view(view_id, || {
1100 if self.window.next_frame.view_stack.last() == Some(&view_id) {
1101 f(self)
1102 } else {
1103 self.window.next_frame.view_stack.push(view_id);
1104 let result = f(self);
1105 self.window.next_frame.view_stack.pop();
1106 result
1107 }
1108 })
1109 }
1110
1111 /// Invoke the given function with the given view id present on the view stack.
1112 /// This is a fairly low-level method used to paint views.
1113 pub fn paint_view<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
1114 let text_system = self.text_system().clone();
1115 text_system.with_view(view_id, || {
1116 if self.window.next_frame.view_stack.last() == Some(&view_id) {
1117 f(self)
1118 } else {
1119 self.window.next_frame.view_stack.push(view_id);
1120 self.window
1121 .next_frame
1122 .dispatch_tree
1123 .push_node(None, None, Some(view_id));
1124 let result = f(self);
1125 self.window.next_frame.dispatch_tree.pop_node();
1126 self.window.next_frame.view_stack.pop();
1127 result
1128 }
1129 })
1130 }
1131
1132 /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
1133 /// platform to receive textual input with proper integration with concerns such
1134 /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
1135 /// rendered.
1136 ///
1137 /// [element_input_handler]: crate::ElementInputHandler
1138 pub fn handle_input(&mut self, focus_handle: &FocusHandle, input_handler: impl InputHandler) {
1139 if focus_handle.is_focused(self) {
1140 let view_id = self.parent_view_id();
1141 self.window.next_frame.requested_input_handler = Some(RequestedInputHandler {
1142 view_id,
1143 handler: Some(PlatformInputHandler::new(
1144 self.to_async(),
1145 Box::new(input_handler),
1146 )),
1147 })
1148 }
1149 }
1150
1151 /// keymatch mode immediate instructs GPUI to prefer shorter action bindings.
1152 /// In the case that you have a keybinding of `"cmd-k": "terminal::Clear"` and
1153 /// `"cmd-k left": "workspace::MoveLeft"`, GPUI will by default wait for 1s after
1154 /// you type cmd-k to see if you're going to type left.
1155 /// This is problematic in the terminal
1156 pub fn keymatch_mode_immediate(&mut self) {
1157 self.window.next_frame.dispatch_tree.keymatch_mode = KeymatchMode::Immediate;
1158 }
1159
1160 /// Register a mouse event listener on the window for the next frame. The type of event
1161 /// is determined by the first parameter of the given listener. When the next frame is rendered
1162 /// the listener will be cleared.
1163 pub fn on_mouse_event<Event: MouseEvent>(
1164 &mut self,
1165 mut handler: impl FnMut(&Event, DispatchPhase, &mut ElementContext) + 'static,
1166 ) {
1167 let view_id = self.parent_view_id();
1168 let order = self.window.next_frame.z_index_stack.clone();
1169 self.window
1170 .next_frame
1171 .mouse_listeners
1172 .entry(TypeId::of::<Event>())
1173 .or_default()
1174 .push((
1175 order,
1176 view_id,
1177 Box::new(
1178 move |event: &dyn Any, phase: DispatchPhase, cx: &mut ElementContext<'_>| {
1179 handler(event.downcast_ref().unwrap(), phase, cx)
1180 },
1181 ),
1182 ))
1183 }
1184
1185 /// Register a key event listener on the window for the next frame. The type of event
1186 /// is determined by the first parameter of the given listener. When the next frame is rendered
1187 /// the listener will be cleared.
1188 ///
1189 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1190 /// a specific need to register a global listener.
1191 pub fn on_key_event<Event: KeyEvent>(
1192 &mut self,
1193 listener: impl Fn(&Event, DispatchPhase, &mut ElementContext) + 'static,
1194 ) {
1195 self.window.next_frame.dispatch_tree.on_key_event(Rc::new(
1196 move |event: &dyn Any, phase, cx: &mut ElementContext<'_>| {
1197 if let Some(event) = event.downcast_ref::<Event>() {
1198 listener(event, phase, cx)
1199 }
1200 },
1201 ));
1202 }
1203}