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