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