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