Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion masonry/src/doc/implementing_container_widget.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ There are a few things to note here:

### `compose`

The `compose` method is called during the compose pass, after layout.
The `compose` method may be called during the compose pass, after layout.
Masonry guarantees that `compose` is called after that widget's `layout` method runs, or when the widget explicitly requests compose.

The compose pass runs top-down and assigns transforms to children. Transform-only layout changes (e.g. scrolling) should request compose instead of requesting layout.

Expand Down
15 changes: 9 additions & 6 deletions masonry_core/src/core/contexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -440,11 +440,11 @@ impl EventCtx<'_> {
/// capture the pointer during any other event.
///
/// A widget normally only receives pointer events when the pointer is inside the widget's
/// layout box. Pointer capture causes widget layout boxes to be ignored: when the pointer is
/// border-box. Pointer capture causes border-box hit checks to be ignored: when the pointer is
/// captured by a widget, that widget will continue receiving pointer events when the pointer
/// is outside the widget's layout box. Other widgets the pointer is over will not receive
/// is outside the widget's border-box. Other widgets the pointer is over will not receive
/// events. Events that are not marked as handled by the capturing widget, bubble up to the
/// widget's ancestors, ignoring their layout boxes as well.
/// widget's ancestors, ignoring their border-boxes as well.
///
/// The pointer cannot be captured by multiple widgets at the same time. If a widget has
/// captured the pointer and another widget captures it, the first widget loses the pointer
Expand Down Expand Up @@ -1584,11 +1584,12 @@ impl_context_method!(
self.widget_state.set_needs_layout(true);
}

// TODO - Document better
/// Requests a [`compose`] pass.
/// Requests that this widget's [`compose`] method be called.
///
/// The compose pass is often cheaper than the layout pass,
/// because it can only transform individual widgets' position.
/// Use this when widget-owned state read by [`compose`] changes,
/// such as a scroll offset applied to a child during compose.
///
/// [`compose`]: crate::core::Widget::compose
pub fn request_compose(&mut self) {
Expand Down Expand Up @@ -1920,7 +1921,9 @@ impl_context_method!(

/// Removes the IME cursor area.
///
/// See [`LayoutCtx::set_ime_area`](LayoutCtx::set_ime_area) for more details.
/// See [`set_ime_area`] for more details.
///
/// [`set_ime_area`]: Self::set_ime_area
pub fn clear_ime_area(&mut self) {
self.widget_state.ime_area = None;
}
Expand Down
11 changes: 9 additions & 2 deletions masonry_core/src/core/widget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ pub trait Widget: AsDynWidget + Any {
/// 1. (Optionally) Call [`compute_size`] to get the border-box size the child wants to be.
/// If the container has somehow already decided on the child length on one axis, then it
/// should instead call [`compute_length`] with the correct border-box `cross_length`.
/// 2. Decide on a final border-box [`Size`] that the child should be. The parent is in control.
/// 2. Decide what the border-box [`Size`] of the child should be. The parent is in control.
/// Note, however, that the child will still be in control of its own [`paint`] method.
/// If a child is given a size smaller than its [`MinContent`], its painting is likely
/// to overflow its bounds, depending on both the child's and the parent's clip settings.
Expand Down Expand Up @@ -361,7 +361,14 @@ pub trait Widget: AsDynWidget + Any {
/// [`MinContent`]: crate::layout::Dim::MinContent
fn layout(&mut self, ctx: &mut LayoutCtx<'_>, props: &PropertiesRef<'_>, size: Size);

/// Runs after the widget's final transform has been computed.
/// Updates compose-only state like scroll translations.
///
/// Cheaper alternative than doing a full layout.
///
/// This method is guaranteed to be called after this widget's [`layout`] method runs,
/// and after this widget explicitly requests compose. It may also be called in other scenarios.
///
/// [`layout`]: Self::layout
fn compose(&mut self, ctx: &mut ComposeCtx<'_>) {}

/// Paints the widget's background.
Expand Down
4 changes: 2 additions & 2 deletions masonry_core/src/core/widget_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ use crate::layout::MeasurementCache;
/// Some fields follow a naming scheme:
/// - `request_xxx`: this specific widget has requested the xxx pass to run on it.
/// - `needs_xxx`: this widget or a descendant has requested the xxx pass to run on it.
/// - `is_xxx`: this widget has the xxx property.
/// - `has_xxx`: this widget or a descendant has the xxx property.
/// - `is_xxx`: this widget is in the xxx state.
/// - `has_xxx`: this widget or a descendant is in the xxx state.
///
/// # Resetting flags
///
Expand Down
10 changes: 7 additions & 3 deletions masonry_core/src/doc/pass_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ To address these invalidations, Masonry runs a set of **rewrite passes** over th

The layout pass may call [`Widget::measure`] any number of times, including zero.
It may then call [`Widget::layout`].
The compose pass will call [`Widget::compose`].
The compose pass will call [`Widget::compose`] on widgets that requested compose.
Running [`Widget::layout`] also requests [`Widget::compose`] for that widget.
The update_xxx passes call the widgets' update method.

By default, each of these passes completes without doing any work, unless pass-dependent invalidation flags are set.
Expand Down Expand Up @@ -189,7 +190,10 @@ Not doing so is a logical bug, and may trigger debug assertions.
### Compose pass

The **compose** pass runs top-down and assigns transforms to children.
Transform-only layout changes (e.g. scrolling) should request compose instead of requesting layout.
Transform-only presentation changes (e.g. scrolling) should request compose instead of requesting layout.

[`Widget::compose`] is called when the widget explicitly requests compose or after that widget's [`Widget::layout`] method runs.
It may also be called in other scenarios, but widgets should not rely on [`Widget::compose`] as a notification for every change to their window transform.

Compose is meant to be a cheaper way to position widgets than layout.
Because the compose pass is more limited than layout, it's easier to recompute in many situations.
Expand Down Expand Up @@ -229,7 +233,7 @@ External mutation is how Xilem applies any changes to the widget tree produced b
Some notes about pass context types:

- Render passes should be pure and can be skipped occasionally, therefore their context types ([`PaintCtx`] and [`AccessCtx`]) can't set invalidation flags or send signals.
- The `layout` and `compose` passes lay out all widgets, which are transiently invalid during the passes, therefore [`MeasureCtx`], [`LayoutCtx`], and [`ComposeCtx`] cannot access the size and position of the `self` widget.
- The `layout` and `compose` passes lay out all widgets, which are transiently invalid during the passes, therefore [`MeasureCtx`] and [`LayoutCtx`] cannot access the size and position of the `self` widget.
They can access the layout of children if they have already been laid out.
- For the same reason, [`MeasureCtx`], [`LayoutCtx`], and [`ComposeCtx`] cannot create a `WidgetRef` reference to a child.
- [`MutateCtx`], [`EventCtx`] and [`UpdateCtx`] can let you add and remove children.
Expand Down
2 changes: 1 addition & 1 deletion masonry_core/src/passes/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! before any translations applied in [`compose`](crate::passes::compose).
//!
//! The framework helps orchestrate the size computation alongside [`Widget::measure`].
//! The final chosen size is passed to [`Widget::layout`].
//! The layout size is passed to [`Widget::layout`].

use dpi::LogicalSize;
use tracing::{info_span, trace};
Expand Down
3 changes: 1 addition & 2 deletions masonry_testing/src/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ pub struct TestHarnessParams {
/// This is useful:
///
/// 1) For individual widgets, as they will often be designed with content outside their
/// layout box (e.g. drop shadows, focus indicators).
/// border-box (e.g. drop shadows, focus indicators).
/// 2) For full apps, as it allows (manual) validation that none of the app content is cut off by
/// the window border.
///
Expand Down Expand Up @@ -694,7 +694,6 @@ impl<W: Widget> TestHarness<W> {
pub fn mouse_move_to(&mut self, id: WidgetId) {
let widget = self.get_widget_with_id(id);
let local_widget_center = widget.ctx().border_box().center();

let widget_center = widget.ctx().window_transform() * local_widget_center;

// TODO - Add reachable_by_pointer() method.
Expand Down
Loading