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