masonry/
contexts.rs

1// Copyright 2020 the Xilem Authors and the Druid Authors
2// SPDX-License-Identifier: Apache-2.0
3
4//! The context types that are passed into various widget methods.
5
6use std::any::Any;
7use std::time::Duration;
8
9use accesskit::{NodeBuilder, TreeUpdate};
10use parley::FontContext;
11use tracing::{trace, warn};
12use winit::dpi::LogicalPosition;
13use winit::window::CursorIcon;
14
15use crate::action::Action;
16use crate::promise::PromiseToken;
17use crate::render_root::{RenderRootSignal, RenderRootState};
18use crate::text_helpers::{ImeChangeSignal, TextFieldRegistration};
19use crate::widget::{CursorChange, WidgetMut, WidgetState};
20use crate::{Insets, Point, Rect, Size, Widget, WidgetId, WidgetPod};
21
22/// A macro for implementing methods on multiple contexts.
23///
24/// There are a lot of methods defined on multiple contexts; this lets us only
25/// have to write them out once.
26macro_rules! impl_context_method {
27    ($ty:ty,  { $($method:item)+ } ) => {
28        impl $ty { $($method)+ }
29    };
30    ( $ty:ty, $($more:ty),+, { $($method:item)+ } ) => {
31        impl_context_method!($ty, { $($method)+ });
32        impl_context_method!($($more),+, { $($method)+ });
33    };
34}
35
36/// A context provided inside of [`WidgetMut`].
37///
38/// When you declare a mutable reference type for your widget, methods of this type
39/// will have access to a `WidgetCtx`. If that method mutates the widget in a way that
40/// requires a later pass (for instance, if your widget has a `set_color` method),
41/// you will need to signal that change in the pass (eg `request_paint`).
42///
43// TODO add tutorial - See issue #5
44pub struct WidgetCtx<'a> {
45    pub(crate) global_state: &'a mut RenderRootState,
46    pub(crate) parent_widget_state: &'a mut WidgetState,
47    pub(crate) widget_state: &'a mut WidgetState,
48}
49
50/// A context provided to event handling methods of widgets.
51///
52/// Widgets should call [`request_paint`](Self::request_paint) whenever an event causes a change
53/// in the widget's appearance, to schedule a repaint.
54pub struct EventCtx<'a> {
55    pub(crate) global_state: &'a mut RenderRootState,
56    pub(crate) widget_state: &'a mut WidgetState,
57    pub(crate) is_handled: bool,
58    pub(crate) request_pan_to_child: Option<Rect>,
59}
60
61/// A context provided to the [`lifecycle`] method on widgets.
62///
63/// [`lifecycle`]: trait.Widget.html#tymethod.lifecycle
64pub struct LifeCycleCtx<'a> {
65    pub(crate) global_state: &'a mut RenderRootState,
66    pub(crate) widget_state: &'a mut WidgetState,
67}
68
69/// A context provided to layout handling methods of widgets.
70///
71/// As of now, the main service provided is access to a factory for
72/// creating text layout objects, which are likely to be useful
73/// during widget layout.
74pub struct LayoutCtx<'a> {
75    pub(crate) global_state: &'a mut RenderRootState,
76    pub(crate) widget_state: &'a mut WidgetState,
77    pub(crate) mouse_pos: Option<Point>,
78}
79
80/// A context passed to paint methods of widgets.
81pub struct PaintCtx<'a> {
82    pub(crate) global_state: &'a mut RenderRootState,
83    pub(crate) widget_state: &'a WidgetState,
84    /// The approximate depth in the tree at the time of painting.
85    pub(crate) depth: u32,
86    pub(crate) debug_paint: bool,
87    pub(crate) debug_widget: bool,
88}
89
90pub struct AccessCtx<'a> {
91    pub(crate) global_state: &'a mut RenderRootState,
92    pub(crate) widget_state: &'a WidgetState,
93    pub(crate) tree_update: &'a mut TreeUpdate,
94    pub(crate) current_node: NodeBuilder,
95    pub(crate) rebuild_all: bool,
96    pub(crate) scale_factor: f64,
97}
98
99pub struct WorkerCtx<'a> {
100    // TODO
101    #[allow(dead_code)]
102    pub(crate) global_state: &'a mut RenderRootState,
103}
104
105pub struct WorkerFn(pub Box<dyn FnOnce(WorkerCtx) + Send + 'static>);
106
107impl_context_method!(
108    WidgetCtx<'_>,
109    EventCtx<'_>,
110    LifeCycleCtx<'_>,
111    PaintCtx<'_>,
112    LayoutCtx<'_>,
113    AccessCtx<'_>,
114    {
115        /// get the `WidgetId` of the current widget.
116        pub fn widget_id(&self) -> WidgetId {
117            self.widget_state.id
118        }
119
120        /// Skip iterating over the given child.
121        ///
122        /// Normally, container widgets are supposed to iterate over each of their
123        /// child widgets in their methods. By default, the framework treats not
124        /// doing so as a mistake, and panics if debug assertions are on.
125        ///
126        /// This tells the framework that a child was deliberately skipped.
127        // TODO - see event flow tutorial - See issue #5
128        pub fn skip_child(&self, child: &mut WidgetPod<impl Widget>) {
129            child.mark_as_visited();
130        }
131    }
132);
133
134// methods on everyone but layoutctx
135impl_context_method!(
136    WidgetCtx<'_>,
137    EventCtx<'_>,
138    LifeCycleCtx<'_>,
139    PaintCtx<'_>,
140    {
141        /// The layout size.
142        ///
143        /// This is the layout size as ultimately determined by the parent
144        /// container, on the previous layout pass.
145        ///
146        /// Generally it will be the same as the size returned by the child widget's
147        /// [`layout`] method.
148        ///
149        /// [`layout`]: trait.Widget.html#tymethod.layout
150        pub fn size(&self) -> Size {
151            self.widget_state.size()
152        }
153
154        /// The origin of the widget in window coordinates, relative to the top left corner of the
155        /// content area.
156        pub fn window_origin(&self) -> Point {
157            self.widget_state.window_origin()
158        }
159
160        /// Convert a point from the widget's coordinate space to the window's.
161        ///
162        /// The returned point is relative to the content area; it excludes window chrome.
163        pub fn to_window(&self, widget_point: Point) -> Point {
164            self.window_origin() + widget_point.to_vec2()
165        }
166
167        /// The "hot" (aka hover) status of a widget.
168        ///
169        /// A widget is "hot" when the mouse is hovered over it. Widgets will
170        /// often change their appearance as a visual indication that they
171        /// will respond to mouse interaction.
172        ///
173        /// The hot status is computed from the widget's layout rect. In a
174        /// container hierarchy, all widgets with layout rects containing the
175        /// mouse position have hot status.
176        ///
177        /// Discussion: there is currently some confusion about whether a
178        /// widget can be considered hot when some other widget is active (for
179        /// example, when clicking to one widget and dragging to the next).
180        /// The documentation should clearly state the resolution.
181        pub fn is_hot(&self) -> bool {
182            self.widget_state.is_hot
183        }
184
185        /// The active status of a widget.
186        ///
187        /// Active status generally corresponds to a mouse button down. Widgets
188        /// with behavior similar to a button will call [`set_active`](EventCtx::set_active) on mouse
189        /// down and then up.
190        ///
191        /// When a widget is active, it gets mouse events even when the mouse
192        /// is dragged away.
193        pub fn is_active(&self) -> bool {
194            self.widget_state.is_active
195        }
196
197        /// The focus status of a widget.
198        ///
199        /// Returns `true` if this specific widget is focused.
200        /// To check if any descendants are focused use [`has_focus`].
201        ///
202        /// Focus means that the widget receives keyboard events.
203        ///
204        /// A widget can request focus using the [`request_focus`] method.
205        /// It's also possible to register for automatic focus via [`register_for_focus`].
206        ///
207        /// If a widget gains or loses focus it will get a [`LifeCycle::FocusChanged`] event.
208        ///
209        /// Only one widget at a time is focused. However due to the way events are routed,
210        /// all ancestors of that widget will also receive keyboard events.
211        ///
212        /// [`request_focus`]: struct.EventCtx.html#method.request_focus
213        /// [`register_for_focus`]: struct.LifeCycleCtx.html#method.register_for_focus
214        /// [`LifeCycle::FocusChanged`]: enum.LifeCycle.html#variant.FocusChanged
215        /// [`has_focus`]: #method.has_focus
216        pub fn is_focused(&self) -> bool {
217            self.global_state.focused_widget == Some(self.widget_id())
218        }
219
220        /// The (tree) focus status of a widget.
221        ///
222        /// Returns `true` if either this specific widget or any one of its descendants is focused.
223        /// To check if only this specific widget is focused use [`is_focused`](Self::is_focused).
224        pub fn has_focus(&self) -> bool {
225            self.widget_state.has_focus
226        }
227
228        /// The disabled state of a widget.
229        ///
230        /// Returns `true` if this widget or any of its ancestors is explicitly disabled.
231        /// To make this widget explicitly disabled use [`set_disabled`].
232        ///
233        /// Disabled means that this widget should not change the state of the application. What
234        /// that means is not entirely clear but in any it should not change its data. Therefore
235        /// others can use this as a safety mechanism to prevent the application from entering an
236        /// illegal state.
237        /// For an example the decrease button of a counter of type `usize` should be disabled if the
238        /// value is `0`.
239        ///
240        /// [`set_disabled`]: EventCtx::set_disabled
241        pub fn is_disabled(&self) -> bool {
242            self.widget_state.is_disabled()
243        }
244
245        /// Check is widget is stashed.
246        ///
247        /// **Note:** Stashed widgets are a WIP feature
248        // FIXME - take stashed parents into account
249        pub fn is_stashed(&self) -> bool {
250            self.widget_state.is_stashed
251        }
252    }
253);
254
255impl_context_method!(EventCtx<'_>, {
256    /// Set the cursor icon.
257    ///
258    /// This setting will be retained until [`clear_cursor`] is called, but it will only take
259    /// effect when this widget is either [`hot`] or [`active`]. If a child widget also sets a
260    /// cursor, the child widget's cursor will take precedence. (If that isn't what you want, use
261    /// [`override_cursor`] instead.)
262    ///
263    /// [`clear_cursor`]: EventCtx::clear_cursor
264    /// [`override_cursor`]: EventCtx::override_cursor
265    /// [`hot`]: EventCtx::is_hot
266    /// [`active`]: EventCtx::is_active
267    pub fn set_cursor(&mut self, cursor: &CursorIcon) {
268        trace!("set_cursor {:?}", cursor);
269        self.widget_state.cursor_change = CursorChange::Set(*cursor);
270    }
271
272    /// Override the cursor icon.
273    ///
274    /// This setting will be retained until [`clear_cursor`] is called, but it will only take
275    /// effect when this widget is either [`hot`] or [`active`]. This will override the cursor
276    /// preferences of a child widget. (If that isn't what you want, use [`set_cursor`] instead.)
277    ///
278    /// [`clear_cursor`]: EventCtx::clear_cursor
279    /// [`set_cursor`]: EventCtx::override_cursor
280    /// [`hot`]: EventCtx::is_hot
281    /// [`active`]: EventCtx::is_active
282    pub fn override_cursor(&mut self, cursor: &CursorIcon) {
283        trace!("override_cursor {:?}", cursor);
284        self.widget_state.cursor_change = CursorChange::Override(*cursor);
285    }
286
287    /// Clear the cursor icon.
288    ///
289    /// This undoes the effect of [`set_cursor`] and [`override_cursor`].
290    ///
291    /// [`override_cursor`]: EventCtx::override_cursor
292    /// [`set_cursor`]: EventCtx::set_cursor
293    pub fn clear_cursor(&mut self) {
294        trace!("clear_cursor");
295        self.widget_state.cursor_change = CursorChange::Default;
296    }
297});
298
299impl<'a> WidgetCtx<'a> {
300    // FIXME - Assert that child's parent is self
301    /// Return a [`WidgetMut`] to a child widget.
302    pub fn get_mut<'c, Child: Widget>(
303        &'c mut self,
304        child: &'c mut WidgetPod<Child>,
305    ) -> WidgetMut<'c, Child> {
306        let child_ctx = WidgetCtx {
307            global_state: self.global_state,
308            parent_widget_state: self.widget_state,
309            widget_state: &mut child.state,
310        };
311        WidgetMut {
312            ctx: child_ctx,
313            widget: &mut child.inner,
314        }
315    }
316}
317
318impl<'a> EventCtx<'a> {
319    /// Return a [`WidgetMut`] to a child widget.
320    // FIXME - Assert that child's parent is self
321    pub fn get_mut<'c, Child: Widget>(
322        &'c mut self,
323        child: &'c mut WidgetPod<Child>,
324    ) -> WidgetMut<'c, Child> {
325        let child_ctx = WidgetCtx {
326            global_state: self.global_state,
327            parent_widget_state: self.widget_state,
328            widget_state: &mut child.state,
329        };
330        WidgetMut {
331            ctx: child_ctx,
332            widget: &mut child.inner,
333        }
334    }
335}
336
337impl<'a> LifeCycleCtx<'a> {
338    /// Return a [`WidgetMut`] to a child widget.
339    // FIXME - Assert that child's parent is self
340    pub fn get_mut<'c, Child: Widget>(
341        &'c mut self,
342        child: &'c mut WidgetPod<Child>,
343    ) -> WidgetMut<'c, Child> {
344        let child_ctx = WidgetCtx {
345            global_state: self.global_state,
346            parent_widget_state: self.widget_state,
347            widget_state: &mut child.state,
348        };
349        WidgetMut {
350            ctx: child_ctx,
351            widget: &mut child.inner,
352        }
353    }
354}
355
356// methods on event and lifecycle
357impl_context_method!(WidgetCtx<'_>, EventCtx<'_>, LifeCycleCtx<'_>, {
358    /// Request a [`paint`](crate::Widget::paint) pass.
359    pub fn request_paint(&mut self) {
360        trace!("request_paint");
361        self.widget_state.needs_paint = true;
362    }
363
364    /// Request a layout pass.
365    ///
366    /// A Widget's [`layout`] method is always called when the widget tree
367    /// changes, or the window is resized.
368    ///
369    /// If your widget would like to have layout called at any other time,
370    /// (such as if it would like to change the layout of children in
371    /// response to some event) it must call this method.
372    ///
373    /// [`layout`]: crate::Widget::layout
374    pub fn request_layout(&mut self) {
375        trace!("request_layout");
376        self.widget_state.needs_layout = true;
377    }
378
379    pub fn request_accessibility_update(&mut self) {
380        trace!("request_accessibility_update");
381        self.widget_state.needs_accessibility_update = true;
382        self.widget_state.request_accessibility_update = true;
383    }
384
385    /// Request an animation frame.
386    pub fn request_anim_frame(&mut self) {
387        trace!("request_anim_frame");
388        self.widget_state.request_anim = true;
389    }
390
391    /// Indicate that your children have changed.
392    ///
393    /// Widgets must call this method after adding a new child or removing a child.
394    pub fn children_changed(&mut self) {
395        trace!("children_changed");
396        self.widget_state.children_changed = true;
397        self.widget_state.update_focus_chain = true;
398        self.request_layout();
399    }
400
401    /// Set the disabled state for this widget.
402    ///
403    /// Setting this to `false` does not mean a widget is not still disabled; for instance it may
404    /// still be disabled by an ancestor. See [`is_disabled`] for more information.
405    ///
406    /// Calling this method during [`LifeCycle::DisabledChanged`] has no effect.
407    ///
408    /// [`LifeCycle::DisabledChanged`]: struct.LifeCycle.html#variant.DisabledChanged
409    /// [`is_disabled`]: EventCtx::is_disabled
410    pub fn set_disabled(&mut self, disabled: bool) {
411        // widget_state.children_disabled_changed is not set because we want to be able to delete
412        // changes that happened during DisabledChanged.
413        self.widget_state.is_explicitly_disabled_new = disabled;
414    }
415
416    /// Mark child widget as stashed.
417    ///
418    /// **Note:** Stashed widgets are a WIP feature
419    pub fn set_stashed(&mut self, child: &mut WidgetPod<impl Widget>, stashed: bool) {
420        child.state.is_stashed = stashed;
421        self.children_changed();
422    }
423
424    #[allow(unused)]
425    /// Indicate that text input state has changed.
426    ///
427    /// A widget that accepts text input should call this anytime input state
428    /// (such as the text or the selection) changes as a result of a non text-input
429    /// event.
430    pub fn invalidate_text_input(&mut self, event: ImeChangeSignal) {
431        todo!("invalidate_text_input");
432    }
433});
434
435// methods on everyone but paintctx
436impl_context_method!(
437    WidgetCtx<'_>,
438    EventCtx<'_>,
439    LifeCycleCtx<'_>,
440    LayoutCtx<'_>,
441    {
442        /// Submit an [`Action`].
443        ///
444        /// Note: Actions are still a WIP feature.
445        pub fn submit_action(&mut self, action: Action) {
446            trace!("submit_action");
447            self.global_state
448                .signal_queue
449                .push_back(RenderRootSignal::Action(action, self.widget_state.id));
450        }
451
452        /// Run the provided function in the background.
453        ///
454        /// The function takes a [`WorkerCtx`] which it can use to
455        /// communicate with the main thread.
456        pub fn run_in_background(
457            &mut self,
458            _background_task: impl FnOnce(WorkerCtx) + Send + 'static,
459        ) {
460            // TODO - Use RenderRootSignal::SpawnWorker
461            todo!("run_in_background");
462        }
463
464        /// Run the provided function in the background, and send its result once it's done.
465        ///
466        /// The function takes a [`WorkerCtx`] which it can use to
467        /// communicate with the main thread.
468        ///
469        /// Once the function returns, an [`Event::PromiseResult`](crate::Event::PromiseResult)
470        /// is emitted with the return value.
471        pub fn compute_in_background<T: Any + Send>(
472            &mut self,
473            _background_task: impl FnOnce(WorkerCtx) -> T + Send + 'static,
474        ) -> PromiseToken<T> {
475            // TODO - Use RenderRootSignal::SpawnWorker
476            todo!("compute_in_background");
477        }
478
479        /// Request a timer event.
480        ///
481        /// The return value is a token, which can be used to associate the
482        /// request with the event.
483        pub fn request_timer(&mut self, _deadline: Duration) -> TimerToken {
484            todo!("request_timer");
485        }
486    }
487);
488
489// FIXME - Remove
490pub struct TimerToken;
491
492impl EventCtx<'_> {
493    /// Send a signal to parent widgets to scroll this widget into view.
494    pub fn request_pan_to_this(&mut self) {
495        self.request_pan_to_child = Some(self.widget_state.layout_rect());
496    }
497
498    /// Set the "active" state of the widget.
499    ///
500    /// See [`EventCtx::is_active`](Self::is_active).
501    pub fn set_active(&mut self, active: bool) {
502        trace!("set_active({})", active);
503        self.widget_state.is_active = active;
504        // TODO: plumb mouse grab through to platform (through druid-shell)
505    }
506
507    /// Set the event as "handled", which stops its propagation to other
508    /// widgets.
509    pub fn set_handled(&mut self) {
510        trace!("set_handled");
511        self.is_handled = true;
512    }
513
514    /// Determine whether the event has been handled by some other widget.
515    pub fn is_handled(&self) -> bool {
516        self.is_handled
517    }
518
519    /// Request keyboard focus.
520    ///
521    /// Because only one widget can be focused at a time, multiple focus requests
522    /// from different widgets during a single event cycle means that the last
523    /// widget that requests focus will override the previous requests.
524    ///
525    /// See [`is_focused`](Self::is_focused) for more information about focus.
526    pub fn request_focus(&mut self) {
527        trace!("request_focus");
528        // We need to send the request even if we're currently focused,
529        // because we may have a sibling widget that already requested focus
530        // and we have no way of knowing that yet. We need to override that
531        // to deliver on the "last focus request wins" promise.
532        let id = self.widget_id();
533        self.global_state.next_focused_widget = Some(id);
534    }
535
536    /// Transfer focus to the widget with the given `WidgetId`.
537    ///
538    /// See [`is_focused`](Self::is_focused) for more information about focus.
539    pub fn set_focus(&mut self, target: WidgetId) {
540        trace!("set_focus target={:?}", target);
541        self.global_state.next_focused_widget = Some(target);
542    }
543
544    /// Give up focus.
545    ///
546    /// This should only be called by a widget that currently has focus.
547    ///
548    /// See [`is_focused`](Self::is_focused) for more information about focus.
549    pub fn resign_focus(&mut self) {
550        trace!("resign_focus");
551        if self.has_focus() {
552            self.global_state.next_focused_widget = None;
553        } else {
554            warn!(
555                "resign_focus can only be called by the currently focused widget \
556                 or one of its ancestors. ({:?})",
557                self.widget_id()
558            );
559        }
560    }
561}
562
563impl LifeCycleCtx<'_> {
564    /// Registers a child widget.
565    ///
566    /// This should only be called in response to a `LifeCycle::WidgetAdded` event.
567    ///
568    /// In general, you should not need to call this method; it is handled by
569    /// the `WidgetPod`.
570    // TODO - See issue #9
571    pub(crate) fn register_child(&mut self, child_id: WidgetId) {
572        trace!("register_child id={:?}", child_id);
573        self.widget_state.children.add(&child_id);
574    }
575
576    /// Register this widget to be eligile to accept focus automatically.
577    ///
578    /// This should only be called in response to a [`LifeCycle::BuildFocusChain`] event.
579    ///
580    /// See [`EventCtx::is_focused`](Self::is_focused) for more information about focus.
581    ///
582    /// [`LifeCycle::BuildFocusChain`]: enum.Lifecycle.html#variant.BuildFocusChain
583    pub fn register_for_focus(&mut self) {
584        trace!("register_for_focus");
585        self.widget_state.focus_chain.push(self.widget_id());
586    }
587
588    /// Register this widget as accepting text input.
589    pub fn register_as_text_input(&mut self) {
590        let registration = TextFieldRegistration {
591            widget_id: self.widget_id(),
592        };
593        self.widget_state.text_registrations.push(registration);
594    }
595
596    // TODO - remove - See issue #15
597    /// Register this widget as a portal.
598    ///
599    /// This should only be used by scroll areas.
600    pub fn register_as_portal(&mut self) {
601        self.widget_state.is_portal = true;
602    }
603}
604
605impl LayoutCtx<'_> {
606    /// Set explicit paint [`Insets`] for this widget.
607    ///
608    /// You are not required to set explicit paint bounds unless you need
609    /// to paint outside of your layout bounds. In this case, the argument
610    /// should be an [`Insets`] struct that indicates where your widget
611    /// needs to overpaint, relative to its bounds.
612    ///
613    /// For more information, see [`WidgetPod::paint_insets`].
614    ///
615    /// [`Insets`]: struct.Insets.html
616    /// [`WidgetPod::paint_insets`]: struct.WidgetPod.html#method.paint_insets
617    pub fn set_paint_insets(&mut self, insets: impl Into<Insets>) {
618        let insets = insets.into();
619        trace!("set_paint_insets {:?}", insets);
620        self.widget_state.paint_insets = insets.nonnegative();
621    }
622
623    /// Set an explicit baseline position for this widget.
624    ///
625    /// The baseline position is used to align widgets that contain text,
626    /// such as buttons, labels, and other controls. It may also be used
627    /// by other widgets that are opinionated about how they are aligned
628    /// relative to neighbouring text, such as switches or checkboxes.
629    ///
630    /// The provided value should be the distance from the *bottom* of the
631    /// widget to the baseline.
632    pub fn set_baseline_offset(&mut self, baseline: f64) {
633        trace!("set_baseline_offset {}", baseline);
634        self.widget_state.baseline_offset = baseline;
635    }
636
637    /// Set the position of a child widget, in the paren't coordinate space. This
638    /// will also implicitly change "hot" status and affect the parent's display rect.
639    ///
640    /// Container widgets must call this method with each non-stashed child in their
641    /// layout method, after calling `child.layout(...)`.
642    pub fn place_child(&mut self, child: &mut WidgetPod<impl Widget>, origin: Point) {
643        if origin != child.state.origin {
644            child.state.origin = origin;
645            child.state.needs_window_origin = true;
646        }
647        child.state.is_expecting_place_child_call = false;
648
649        self.widget_state.local_paint_rect =
650            self.widget_state.local_paint_rect.union(child.paint_rect());
651
652        let mouse_pos = self.mouse_pos.map(|pos| LogicalPosition::new(pos.x, pos.y));
653        // if the widget has moved, it may have moved under the mouse, in which
654        // case we need to handle that.
655        if WidgetPod::update_hot_state(
656            &mut child.inner,
657            &mut child.state,
658            self.global_state,
659            mouse_pos,
660        ) {
661            self.widget_state.merge_up(&mut child.state);
662        }
663    }
664}
665
666impl_context_method!(LayoutCtx<'_>, PaintCtx<'_>, {
667    pub fn font_ctx(&mut self) -> &mut FontContext {
668        &mut self.global_state.font_context
669    }
670});
671
672impl PaintCtx<'_> {
673    /// The depth in the tree of the currently painting widget.
674    ///
675    /// This may be used in combination with [`paint_with_z_index`](Self::paint_with_z_index) in order
676    /// to correctly order painting operations.
677    ///
678    /// The `depth` here may not be exact; it is only guaranteed that a child will
679    /// have a greater depth than its parent.
680    #[inline]
681    pub fn depth(&self) -> u32 {
682        self.depth
683    }
684}
685
686impl AccessCtx<'_> {
687    pub fn current_node(&mut self) -> &mut NodeBuilder {
688        &mut self.current_node
689    }
690
691    /// Report whether accessibility was requested on this widget.
692    ///
693    /// This method is primarily intended for containers. The `accessibility`
694    /// method will be called on a widget when it or any of its descendants
695    /// have seen a request. However, in many cases a container need not push
696    /// a node for itself.
697    pub fn is_requested(&self) -> bool {
698        self.widget_state.needs_accessibility_update
699    }
700}