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, StackingOrder, Style,
23 Surface, TextStyleRefinement, Underline, UnderlineStyle, Window, WindowContext,
24 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: u32,
49 pub(crate) next_root_z_index: u8,
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) {
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
338 pub fn with_text_style<F, R>(&mut self, style: Option<TextStyleRefinement>, f: F) -> R
339 where
340 F: FnOnce(&mut Self) -> R,
341 {
342 if let Some(style) = style {
343 self.push_text_style(style);
344 let result = f(self);
345 self.pop_text_style();
346 result
347 } else {
348 f(self)
349 }
350 }
351
352 /// Updates the cursor style at the platform level.
353 pub fn set_cursor_style(&mut self, style: CursorStyle) {
354 let view_id = self.parent_view_id();
355 self.window.next_frame.cursor_styles.insert(view_id, style);
356 self.window.next_frame.requested_cursor_style = Some(style);
357 }
358
359 /// Sets a tooltip to be rendered for the upcoming frame
360 pub fn set_tooltip(&mut self, tooltip: AnyTooltip) {
361 let view_id = self.parent_view_id();
362 self.window.next_frame.tooltip_request = Some(TooltipRequest { view_id, tooltip });
363 }
364
365 /// Pushes the given element id onto the global stack and invokes the given closure
366 /// with a `GlobalElementId`, which disambiguates the given id in the context of its ancestor
367 /// ids. Because elements are discarded and recreated on each frame, the `GlobalElementId` is
368 /// used to associate state with identified elements across separate frames.
369 pub fn with_element_id<R>(
370 &mut self,
371 id: Option<impl Into<ElementId>>,
372 f: impl FnOnce(&mut Self) -> R,
373 ) -> R {
374 if let Some(id) = id.map(Into::into) {
375 let window = self.window_mut();
376 window.element_id_stack.push(id);
377 let result = f(self);
378 let window: &mut Window = self.borrow_mut();
379 window.element_id_stack.pop();
380 result
381 } else {
382 f(self)
383 }
384 }
385
386 /// Invoke the given function with the given content mask after intersecting it
387 /// with the current mask.
388 pub fn with_content_mask<R>(
389 &mut self,
390 mask: Option<ContentMask<Pixels>>,
391 f: impl FnOnce(&mut Self) -> R,
392 ) -> R {
393 if let Some(mask) = mask {
394 let mask = mask.intersect(&self.content_mask());
395 self.window_mut().next_frame.content_mask_stack.push(mask);
396 let result = f(self);
397 self.window_mut().next_frame.content_mask_stack.pop();
398 result
399 } else {
400 f(self)
401 }
402 }
403
404 /// Invoke the given function with the content mask reset to that
405 /// of the window.
406 pub fn break_content_mask<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R {
407 let mask = ContentMask {
408 bounds: Bounds {
409 origin: Point::default(),
410 size: self.window().viewport_size,
411 },
412 };
413 let new_stacking_order_id =
414 post_inc(&mut self.window_mut().next_frame.next_stacking_order_id);
415 let new_root_z_index = post_inc(&mut self.window_mut().next_frame.next_root_z_index);
416 let old_stacking_order = mem::take(&mut self.window_mut().next_frame.z_index_stack);
417 self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id;
418 self.window_mut()
419 .next_frame
420 .z_index_stack
421 .push(new_root_z_index);
422 self.window_mut().next_frame.content_mask_stack.push(mask);
423 let result = f(self);
424 self.window_mut().next_frame.content_mask_stack.pop();
425 self.window_mut().next_frame.z_index_stack = old_stacking_order;
426 result
427 }
428
429 /// Called during painting to invoke the given closure in a new stacking context. The given
430 /// z-index is interpreted relative to the previous call to `stack`.
431 pub fn with_z_index<R>(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R {
432 let new_stacking_order_id =
433 post_inc(&mut self.window_mut().next_frame.next_stacking_order_id);
434 let old_stacking_order_id = mem::replace(
435 &mut self.window_mut().next_frame.z_index_stack.id,
436 new_stacking_order_id,
437 );
438 self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id;
439 self.window_mut().next_frame.z_index_stack.push(z_index);
440 let result = f(self);
441 self.window_mut().next_frame.z_index_stack.id = old_stacking_order_id;
442 self.window_mut().next_frame.z_index_stack.pop();
443 result
444 }
445
446 /// Updates the global element offset relative to the current offset. This is used to implement
447 /// scrolling.
448 pub fn with_element_offset<R>(
449 &mut self,
450 offset: Point<Pixels>,
451 f: impl FnOnce(&mut Self) -> R,
452 ) -> R {
453 if offset.is_zero() {
454 return f(self);
455 };
456
457 let abs_offset = self.element_offset() + offset;
458 self.with_absolute_element_offset(abs_offset, f)
459 }
460
461 /// Updates the global element offset based on the given offset. This is used to implement
462 /// drag handles and other manual painting of elements.
463 pub fn with_absolute_element_offset<R>(
464 &mut self,
465 offset: Point<Pixels>,
466 f: impl FnOnce(&mut Self) -> R,
467 ) -> R {
468 self.window_mut()
469 .next_frame
470 .element_offset_stack
471 .push(offset);
472 let result = f(self);
473 self.window_mut().next_frame.element_offset_stack.pop();
474 result
475 }
476
477 /// Obtain the current element offset.
478 pub fn element_offset(&self) -> Point<Pixels> {
479 self.window()
480 .next_frame
481 .element_offset_stack
482 .last()
483 .copied()
484 .unwrap_or_default()
485 }
486
487 /// Obtain the current content mask.
488 pub fn content_mask(&self) -> ContentMask<Pixels> {
489 self.window()
490 .next_frame
491 .content_mask_stack
492 .last()
493 .cloned()
494 .unwrap_or_else(|| ContentMask {
495 bounds: Bounds {
496 origin: Point::default(),
497 size: self.window().viewport_size,
498 },
499 })
500 }
501
502 /// The size of an em for the base font of the application. Adjusting this value allows the
503 /// UI to scale, just like zooming a web page.
504 pub fn rem_size(&self) -> Pixels {
505 self.window().rem_size
506 }
507
508 /// Updates or initializes state for an element with the given id that lives across multiple
509 /// frames. If an element with this ID existed in the rendered frame, its state will be passed
510 /// to the given closure. The state returned by the closure will be stored so it can be referenced
511 /// when drawing the next frame.
512 pub fn with_element_state<S, R>(
513 &mut self,
514 id: ElementId,
515 f: impl FnOnce(Option<S>, &mut Self) -> (R, S),
516 ) -> R
517 where
518 S: 'static,
519 {
520 self.with_element_id(Some(id), |cx| {
521 let global_id = cx.window().element_id_stack.clone();
522
523 if let Some(any) = cx
524 .window_mut()
525 .next_frame
526 .element_states
527 .remove(&global_id)
528 .or_else(|| {
529 cx.window_mut()
530 .rendered_frame
531 .element_states
532 .remove(&global_id)
533 })
534 {
535 let ElementStateBox {
536 inner,
537 parent_view_id,
538 #[cfg(debug_assertions)]
539 type_name
540 } = any;
541 // Using the extra inner option to avoid needing to reallocate a new box.
542 let mut state_box = inner
543 .downcast::<Option<S>>()
544 .map_err(|_| {
545 #[cfg(debug_assertions)]
546 {
547 anyhow::anyhow!(
548 "invalid element state type for id, requested_type {:?}, actual type: {:?}",
549 std::any::type_name::<S>(),
550 type_name
551 )
552 }
553
554 #[cfg(not(debug_assertions))]
555 {
556 anyhow::anyhow!(
557 "invalid element state type for id, requested_type {:?}",
558 std::any::type_name::<S>(),
559 )
560 }
561 })
562 .unwrap();
563
564 // Actual: Option<AnyElement> <- View
565 // Requested: () <- AnyElement
566 let state = state_box
567 .take()
568 .expect("element state is already on the stack");
569 let (result, state) = f(Some(state), cx);
570 state_box.replace(state);
571 cx.window_mut()
572 .next_frame
573 .element_states
574 .insert(global_id, ElementStateBox {
575 inner: state_box,
576 parent_view_id,
577 #[cfg(debug_assertions)]
578 type_name
579 });
580 result
581 } else {
582 let (result, state) = f(None, cx);
583 let parent_view_id = cx.parent_view_id();
584 cx.window_mut()
585 .next_frame
586 .element_states
587 .insert(global_id,
588 ElementStateBox {
589 inner: Box::new(Some(state)),
590 parent_view_id,
591 #[cfg(debug_assertions)]
592 type_name: std::any::type_name::<S>()
593 }
594
595 );
596 result
597 }
598 })
599 }
600 /// Paint one or more drop shadows into the scene for the next frame at the current z-index.
601 pub fn paint_shadows(
602 &mut self,
603 bounds: Bounds<Pixels>,
604 corner_radii: Corners<Pixels>,
605 shadows: &[BoxShadow],
606 ) {
607 let scale_factor = self.scale_factor();
608 let content_mask = self.content_mask();
609 let view_id = self.parent_view_id();
610 let window = &mut *self.window;
611 for shadow in shadows {
612 let mut shadow_bounds = bounds;
613 shadow_bounds.origin += shadow.offset;
614 shadow_bounds.dilate(shadow.spread_radius);
615 window.next_frame.scene.insert(
616 &window.next_frame.z_index_stack,
617 Shadow {
618 view_id: view_id.into(),
619 layer_id: 0,
620 order: 0,
621 bounds: shadow_bounds.scale(scale_factor),
622 content_mask: content_mask.scale(scale_factor),
623 corner_radii: corner_radii.scale(scale_factor),
624 color: shadow.color,
625 blur_radius: shadow.blur_radius.scale(scale_factor),
626 },
627 );
628 }
629 }
630
631 /// Paint one or more quads into the scene for the next frame at the current stacking context.
632 /// Quads are colored rectangular regions with an optional background, border, and corner radius.
633 /// see [`fill`], [`outline`], and [`quad`] to construct this type.
634 pub fn paint_quad(&mut self, quad: PaintQuad) {
635 let scale_factor = self.scale_factor();
636 let content_mask = self.content_mask();
637 let view_id = self.parent_view_id();
638
639 let window = &mut *self.window;
640 window.next_frame.scene.insert(
641 &window.next_frame.z_index_stack,
642 Quad {
643 view_id: view_id.into(),
644 layer_id: 0,
645 order: 0,
646 bounds: quad.bounds.scale(scale_factor),
647 content_mask: content_mask.scale(scale_factor),
648 background: quad.background,
649 border_color: quad.border_color,
650 corner_radii: quad.corner_radii.scale(scale_factor),
651 border_widths: quad.border_widths.scale(scale_factor),
652 },
653 );
654 }
655
656 /// Paint the given `Path` into the scene for the next frame at the current z-index.
657 pub fn paint_path(&mut self, mut path: Path<Pixels>, color: impl Into<Hsla>) {
658 let scale_factor = self.scale_factor();
659 let content_mask = self.content_mask();
660 let view_id = self.parent_view_id();
661
662 path.content_mask = content_mask;
663 path.color = color.into();
664 path.view_id = view_id.into();
665 let window = &mut *self.window;
666 window
667 .next_frame
668 .scene
669 .insert(&window.next_frame.z_index_stack, path.scale(scale_factor));
670 }
671
672 /// Paint an underline into the scene for the next frame at the current z-index.
673 pub fn paint_underline(
674 &mut self,
675 origin: Point<Pixels>,
676 width: Pixels,
677 style: &UnderlineStyle,
678 ) {
679 let scale_factor = self.scale_factor();
680 let height = if style.wavy {
681 style.thickness * 3.
682 } else {
683 style.thickness
684 };
685 let bounds = Bounds {
686 origin,
687 size: size(width, height),
688 };
689 let content_mask = self.content_mask();
690 let view_id = self.parent_view_id();
691
692 let window = &mut *self.window;
693 window.next_frame.scene.insert(
694 &window.next_frame.z_index_stack,
695 Underline {
696 view_id: view_id.into(),
697 layer_id: 0,
698 order: 0,
699 bounds: bounds.scale(scale_factor),
700 content_mask: content_mask.scale(scale_factor),
701 thickness: style.thickness.scale(scale_factor),
702 color: style.color.unwrap_or_default(),
703 wavy: style.wavy,
704 },
705 );
706 }
707
708 /// Paint a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
709 /// The y component of the origin is the baseline of the glyph.
710 pub fn paint_glyph(
711 &mut self,
712 origin: Point<Pixels>,
713 font_id: FontId,
714 glyph_id: GlyphId,
715 font_size: Pixels,
716 color: Hsla,
717 ) -> Result<()> {
718 let scale_factor = self.scale_factor();
719 let glyph_origin = origin.scale(scale_factor);
720 let subpixel_variant = Point {
721 x: (glyph_origin.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
722 y: (glyph_origin.y.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
723 };
724 let params = RenderGlyphParams {
725 font_id,
726 glyph_id,
727 font_size,
728 subpixel_variant,
729 scale_factor,
730 is_emoji: false,
731 };
732
733 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
734 if !raster_bounds.is_zero() {
735 let tile =
736 self.window
737 .sprite_atlas
738 .get_or_insert_with(¶ms.clone().into(), &mut || {
739 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
740 Ok((size, Cow::Owned(bytes)))
741 })?;
742 let bounds = Bounds {
743 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
744 size: tile.bounds.size.map(Into::into),
745 };
746 let content_mask = self.content_mask().scale(scale_factor);
747 let view_id = self.parent_view_id();
748 let window = &mut *self.window;
749 window.next_frame.scene.insert(
750 &window.next_frame.z_index_stack,
751 MonochromeSprite {
752 view_id: view_id.into(),
753 layer_id: 0,
754 order: 0,
755 bounds,
756 content_mask,
757 color,
758 tile,
759 },
760 );
761 }
762 Ok(())
763 }
764
765 /// Paint an emoji glyph into the scene for the next frame at the current z-index.
766 /// The y component of the origin is the baseline of the glyph.
767 pub fn paint_emoji(
768 &mut self,
769 origin: Point<Pixels>,
770 font_id: FontId,
771 glyph_id: GlyphId,
772 font_size: Pixels,
773 ) -> Result<()> {
774 let scale_factor = self.scale_factor();
775 let glyph_origin = origin.scale(scale_factor);
776 let params = RenderGlyphParams {
777 font_id,
778 glyph_id,
779 font_size,
780 // We don't render emojis with subpixel variants.
781 subpixel_variant: Default::default(),
782 scale_factor,
783 is_emoji: true,
784 };
785
786 let raster_bounds = self.text_system().raster_bounds(¶ms)?;
787 if !raster_bounds.is_zero() {
788 let tile =
789 self.window
790 .sprite_atlas
791 .get_or_insert_with(¶ms.clone().into(), &mut || {
792 let (size, bytes) = self.text_system().rasterize_glyph(¶ms)?;
793 Ok((size, Cow::Owned(bytes)))
794 })?;
795 let bounds = Bounds {
796 origin: glyph_origin.map(|px| px.floor()) + raster_bounds.origin.map(Into::into),
797 size: tile.bounds.size.map(Into::into),
798 };
799 let content_mask = self.content_mask().scale(scale_factor);
800 let view_id = self.parent_view_id();
801 let window = &mut *self.window;
802
803 window.next_frame.scene.insert(
804 &window.next_frame.z_index_stack,
805 PolychromeSprite {
806 view_id: view_id.into(),
807 layer_id: 0,
808 order: 0,
809 bounds,
810 corner_radii: Default::default(),
811 content_mask,
812 tile,
813 grayscale: false,
814 },
815 );
816 }
817 Ok(())
818 }
819
820 /// Paint a monochrome SVG into the scene for the next frame at the current stacking context.
821 pub fn paint_svg(
822 &mut self,
823 bounds: Bounds<Pixels>,
824 path: SharedString,
825 color: Hsla,
826 ) -> Result<()> {
827 let scale_factor = self.scale_factor();
828 let bounds = bounds.scale(scale_factor);
829 // Render the SVG at twice the size to get a higher quality result.
830 let params = RenderSvgParams {
831 path,
832 size: bounds
833 .size
834 .map(|pixels| DevicePixels::from((pixels.0 * 2.).ceil() as i32)),
835 };
836
837 let tile =
838 self.window
839 .sprite_atlas
840 .get_or_insert_with(¶ms.clone().into(), &mut || {
841 let bytes = self.svg_renderer.render(¶ms)?;
842 Ok((params.size, Cow::Owned(bytes)))
843 })?;
844 let content_mask = self.content_mask().scale(scale_factor);
845 let view_id = self.parent_view_id();
846
847 let window = &mut *self.window;
848 window.next_frame.scene.insert(
849 &window.next_frame.z_index_stack,
850 MonochromeSprite {
851 view_id: view_id.into(),
852 layer_id: 0,
853 order: 0,
854 bounds,
855 content_mask,
856 color,
857 tile,
858 },
859 );
860
861 Ok(())
862 }
863
864 /// Paint an image into the scene for the next frame at the current z-index.
865 pub fn paint_image(
866 &mut self,
867 bounds: Bounds<Pixels>,
868 corner_radii: Corners<Pixels>,
869 data: Arc<ImageData>,
870 grayscale: bool,
871 ) -> Result<()> {
872 let scale_factor = self.scale_factor();
873 let bounds = bounds.scale(scale_factor);
874 let params = RenderImageParams { image_id: data.id };
875
876 let tile = self
877 .window
878 .sprite_atlas
879 .get_or_insert_with(¶ms.clone().into(), &mut || {
880 Ok((data.size(), Cow::Borrowed(data.as_bytes())))
881 })?;
882 let content_mask = self.content_mask().scale(scale_factor);
883 let corner_radii = corner_radii.scale(scale_factor);
884 let view_id = self.parent_view_id();
885
886 let window = &mut *self.window;
887 window.next_frame.scene.insert(
888 &window.next_frame.z_index_stack,
889 PolychromeSprite {
890 view_id: view_id.into(),
891 layer_id: 0,
892 order: 0,
893 bounds,
894 content_mask,
895 corner_radii,
896 tile,
897 grayscale,
898 },
899 );
900 Ok(())
901 }
902
903 /// Paint a surface into the scene for the next frame at the current z-index.
904 pub fn paint_surface(&mut self, bounds: Bounds<Pixels>, image_buffer: CVImageBuffer) {
905 let scale_factor = self.scale_factor();
906 let bounds = bounds.scale(scale_factor);
907 let content_mask = self.content_mask().scale(scale_factor);
908 let view_id = self.parent_view_id();
909 let window = &mut *self.window;
910 window.next_frame.scene.insert(
911 &window.next_frame.z_index_stack,
912 Surface {
913 view_id: view_id.into(),
914 layer_id: 0,
915 order: 0,
916 bounds,
917 content_mask,
918 image_buffer,
919 },
920 );
921 }
922
923 #[must_use]
924 /// Add a node to the layout tree for the current frame. Takes the `Style` of the element for which
925 /// layout is being requested, along with the layout ids of any children. This method is called during
926 /// calls to the `Element::layout` trait method and enables any element to participate in layout.
927 pub fn request_layout(
928 &mut self,
929 style: &Style,
930 children: impl IntoIterator<Item = LayoutId>,
931 ) -> LayoutId {
932 self.app.layout_id_buffer.clear();
933 self.app.layout_id_buffer.extend(children);
934 let rem_size = self.rem_size();
935
936 self.cx
937 .window
938 .layout_engine
939 .as_mut()
940 .unwrap()
941 .request_layout(style, rem_size, &self.cx.app.layout_id_buffer)
942 }
943
944 /// Add a node to the layout tree for the current frame. Instead of taking a `Style` and children,
945 /// this variant takes a function that is invoked during layout so you can use arbitrary logic to
946 /// determine the element's size. One place this is used internally is when measuring text.
947 ///
948 /// The given closure is invoked at layout time with the known dimensions and available space and
949 /// returns a `Size`.
950 pub fn request_measured_layout<
951 F: FnMut(Size<Option<Pixels>>, Size<AvailableSpace>, &mut WindowContext) -> Size<Pixels>
952 + 'static,
953 >(
954 &mut self,
955 style: Style,
956 measure: F,
957 ) -> LayoutId {
958 let rem_size = self.rem_size();
959 self.window
960 .layout_engine
961 .as_mut()
962 .unwrap()
963 .request_measured_layout(style, rem_size, measure)
964 }
965
966 /// Compute the layout for the given id within the given available space.
967 /// This method is called for its side effect, typically by the framework prior to painting.
968 /// After calling it, you can request the bounds of the given layout node id or any descendant.
969 pub fn compute_layout(&mut self, layout_id: LayoutId, available_space: Size<AvailableSpace>) {
970 let mut layout_engine = self.window.layout_engine.take().unwrap();
971 layout_engine.compute_layout(layout_id, available_space, self);
972 self.window.layout_engine = Some(layout_engine);
973 }
974
975 /// Obtain the bounds computed for the given LayoutId relative to the window. This method should not
976 /// be invoked until the paint phase begins, and will usually be invoked by GPUI itself automatically
977 /// in order to pass your element its `Bounds` automatically.
978 pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
979 let mut bounds = self
980 .window
981 .layout_engine
982 .as_mut()
983 .unwrap()
984 .layout_bounds(layout_id)
985 .map(Into::into);
986 bounds.origin += self.element_offset();
987 bounds
988 }
989
990 pub(crate) fn layout_style(&self, layout_id: LayoutId) -> Option<&Style> {
991 self.window
992 .layout_engine
993 .as_ref()
994 .unwrap()
995 .requested_style(layout_id)
996 }
997
998 /// Called during painting to track which z-index is on top at each pixel position
999 pub fn add_opaque_layer(&mut self, bounds: Bounds<Pixels>) {
1000 let stacking_order = self.window.next_frame.z_index_stack.clone();
1001 let view_id = self.parent_view_id();
1002 let depth_map = &mut self.window.next_frame.depth_map;
1003 match depth_map.binary_search_by(|(level, _, _)| stacking_order.cmp(level)) {
1004 Ok(i) | Err(i) => depth_map.insert(i, (stacking_order, view_id, bounds)),
1005 }
1006 }
1007
1008 /// Invoke the given function with the given focus handle present on the key dispatch stack.
1009 /// 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.
1010 pub fn with_key_dispatch<R>(
1011 &mut self,
1012 context: Option<KeyContext>,
1013 focus_handle: Option<FocusHandle>,
1014 f: impl FnOnce(Option<FocusHandle>, &mut Self) -> R,
1015 ) -> R {
1016 let window = &mut self.window;
1017 let focus_id = focus_handle.as_ref().map(|handle| handle.id);
1018 window
1019 .next_frame
1020 .dispatch_tree
1021 .push_node(context.clone(), focus_id, None);
1022
1023 let result = f(focus_handle, self);
1024
1025 self.window.next_frame.dispatch_tree.pop_node();
1026
1027 result
1028 }
1029
1030 /// Invoke the given function with the given view id present on the view stack.
1031 /// This is a fairly low-level method used to layout views.
1032 pub fn with_view_id<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
1033 let text_system = self.text_system().clone();
1034 text_system.with_view(view_id, || {
1035 if self.window.next_frame.view_stack.last() == Some(&view_id) {
1036 return f(self);
1037 } else {
1038 self.window.next_frame.view_stack.push(view_id);
1039 let result = f(self);
1040 self.window.next_frame.view_stack.pop();
1041 result
1042 }
1043 })
1044 }
1045
1046 /// Invoke the given function with the given view id present on the view stack.
1047 /// This is a fairly low-level method used to paint views.
1048 pub fn paint_view<R>(&mut self, view_id: EntityId, f: impl FnOnce(&mut Self) -> R) -> R {
1049 let text_system = self.text_system().clone();
1050 text_system.with_view(view_id, || {
1051 if self.window.next_frame.view_stack.last() == Some(&view_id) {
1052 return f(self);
1053 } else {
1054 self.window.next_frame.view_stack.push(view_id);
1055 self.window
1056 .next_frame
1057 .dispatch_tree
1058 .push_node(None, None, Some(view_id));
1059 let result = f(self);
1060 self.window.next_frame.dispatch_tree.pop_node();
1061 self.window.next_frame.view_stack.pop();
1062 result
1063 }
1064 })
1065 }
1066
1067 /// Sets an input handler, such as [`ElementInputHandler`][element_input_handler], which interfaces with the
1068 /// platform to receive textual input with proper integration with concerns such
1069 /// as IME interactions. This handler will be active for the upcoming frame until the following frame is
1070 /// rendered.
1071 ///
1072 /// [element_input_handler]: crate::ElementInputHandler
1073 pub fn handle_input(&mut self, focus_handle: &FocusHandle, input_handler: impl InputHandler) {
1074 if focus_handle.is_focused(self) {
1075 let view_id = self.parent_view_id();
1076 self.window.next_frame.requested_input_handler = Some(RequestedInputHandler {
1077 view_id,
1078 handler: Some(PlatformInputHandler::new(
1079 self.to_async(),
1080 Box::new(input_handler),
1081 )),
1082 })
1083 }
1084 }
1085
1086 /// Register a mouse event listener on the window for the next frame. The type of event
1087 /// is determined by the first parameter of the given listener. When the next frame is rendered
1088 /// the listener will be cleared.
1089 pub fn on_mouse_event<Event: MouseEvent>(
1090 &mut self,
1091 mut handler: impl FnMut(&Event, DispatchPhase, &mut ElementContext) + 'static,
1092 ) {
1093 let view_id = self.parent_view_id();
1094 let order = self.window.next_frame.z_index_stack.clone();
1095 self.window
1096 .next_frame
1097 .mouse_listeners
1098 .entry(TypeId::of::<Event>())
1099 .or_default()
1100 .push((
1101 order,
1102 view_id,
1103 Box::new(
1104 move |event: &dyn Any, phase: DispatchPhase, cx: &mut ElementContext<'_>| {
1105 handler(event.downcast_ref().unwrap(), phase, cx)
1106 },
1107 ),
1108 ))
1109 }
1110
1111 /// Register a key event listener on the window for the next frame. The type of event
1112 /// is determined by the first parameter of the given listener. When the next frame is rendered
1113 /// the listener will be cleared.
1114 ///
1115 /// This is a fairly low-level method, so prefer using event handlers on elements unless you have
1116 /// a specific need to register a global listener.
1117 pub fn on_key_event<Event: KeyEvent>(
1118 &mut self,
1119 listener: impl Fn(&Event, DispatchPhase, &mut ElementContext) + 'static,
1120 ) {
1121 self.window.next_frame.dispatch_tree.on_key_event(Rc::new(
1122 move |event: &dyn Any, phase, cx: &mut ElementContext<'_>| {
1123 if let Some(event) = event.downcast_ref::<Event>() {
1124 listener(event, phase, cx)
1125 }
1126 },
1127 ));
1128 }
1129}