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