Commit Graph

1031 Commits

Author SHA1 Message Date
Olivier FAURE 094e645754
Add pixel snapping to layout pass (#1239)
Remove coordinates rounding code from Align and Flex.

Remove rounding from BoxConstraints: instead, widgets do layout under
the assumption that they're in a full f64 coordinate space, and rounding
only happens at the end of layout.

Document pixel snapping.
Pixel-snap the baseline as well.
Remove `invalid_screenshot_2` test (which relied on placing a child
widget with sub-pixel boundaries to produce a slightly incorrect image,
which we can no longer do).
Update all screenshot tests.

See [#masonry > Aligning layout boxes to pixel
boundaries](https://xi.zulipchat.com/#narrow/channel/317477-masonry/topic/Aligning.20layout.20boxes.20to.20pixel.20boundaries)
for details.
2025-07-30 12:10:04 +00:00
Nixon cc4f92812c
Dynamic child for masonry `Button` (#1253)
Switching from `Button` to `Button<W>` so that it can contain other type
of widgets as well!

Edit: Now switching to `Button` with a `dyn Widget` as the child
instead!
2025-07-30 10:14:43 +00:00
Olivier FAURE 7054bd42a6
Make TestHarness constructors take NewWidget (#1241)
Have WidgetExt methods return NewWidget instead of WrapperWidget.
Rewrite testing tutorial a bit.
Rewrite some tests to avoid relying on WidgetExt.

This overall makes code more consistent: everything which creates a
widget takes `NewWidget`.
2025-07-29 12:54:45 +00:00
Daniel McNab d4d48d80a5
Make the environment and element available in `View::message` (#1220)
See [#xilem > Environment
System](https://xi.zulipchat.com/#narrow/channel/354396-xilem/topic/Environment.20System/with/529496085)
and [#xilem > Giving &#96;message&#96; access to the
Element](https://xi.zulipchat.com/#narrow/channel/354396-xilem/topic/Giving.20.60message.60.20access.20to.20the.20Element/with/529436165)
for motivation.

This is a massive refactor, to significant improve the capabilities of
Xilem.
The main difficulty so far has been sequences, as we need to skip the
right amount of items.
This will either require storing large amounts of item, or restoring the
`count` method on sequences.

Obviously Xilem and Xilem Web are not yet done in this PR.

---------

Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
2025-07-29 11:05:10 +00:00
Olivier FAURE be1c8e87d5
Factor Axis, CrossAxisAlignment and MainAxisAlignment out of `flex.rs` (#1240)
These types are going to be used in other widgets (notably the future
Stack widget) and should not exclusive to Flex.
2025-07-28 18:02:15 +00:00
Olivier FAURE 22f303ecb9
Replace RawWrapper concept with much simpler RawCtx (#1200)
The main differences are:
- get_raw and get_raw_mut now both give a mutable context.
- get_raw_ and get_raw_mut are no longer included in AccessCtx.
- No need for more layers of macro copy-pasting, instead everything is
in RawCtx.

Currently RawCtx is only used in Portal widget.
Places where the code was gated behind an `if false` block have been
removed.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2025-07-28 14:02:18 +00:00
Olivier FAURE f46be4eadf
Better document RenderRootSignal values (#1249)
The previous docs were very uninformative, and missed some crucial info
(e.g. the mechanics of dragging and resizing).

Some of these enum values directly mirror winit methods.
For these, the new docs match how Winit will handle these values.

---------

Co-authored-by: Tom Churchman <thomas@kepow.org>
2025-07-28 13:32:09 +00:00
Olivier FAURE 32503ec1ea
Add rudimentary clipboard support (#1237)
This only supports copy-pasting strings, not rich text. And the way
Ctrl+V is detected is somewhat dubious.

But it does effectively add clipboard support to Masonry apps.

Ideally, on the long term, we may want to be able to programmatically
request clipboard contents; I'm not sure how to implement that cleanly
given RenderRoot's architecture, without making masonry_core depend
directly on a clipboard-handling library.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2025-07-28 13:30:26 +00:00
Olivier FAURE dd45044538
Add WidgetArenaNode type to centralize all data in a single TreeArena (#1248)
This reduces code duplication (a lot of code no longer has to be
copy-pasted three times).
This is especially important for the upcoming widget refactor, which
will add more code for each arena.
2025-07-28 13:13:41 +00:00
Olivier FAURE fb026d580f
Document `MASONRY_BLESS_TEST` and have it handle new screenshots. (#1251)
`MASONRY_BLESS_TEST` is used to treat all screenshots as valid.

This PR documents the flag and makes sure it works even when there's no
reference file.
2025-07-28 13:04:30 +00:00
Olivier FAURE 956274488a
Add `impl From<...> for Properties` with various tuples. (#1242)
This should make code adding widgets with properties easier to write in
the future.

(This PR doesn't rewrite existing code.)
2025-07-28 13:01:43 +00:00
Pufferfish 5e49206c28
Use properties in `ProgressBar` (#1246)
Hi 👋, I'm looking forward for this library, so I decided to start
contributing by solving a simple issue.

Closes #1069
2025-07-26 21:40:37 +00:00
Olivier FAURE 4f8a70358d
Better document flex gap and spacers (#1245) 2025-07-26 21:21:25 +00:00
Olivier FAURE c76b7e5626
Add `TestHarness::root_id()` convenience method (#1252) 2025-07-26 21:21:19 +00:00
Olivier FAURE fe65383d23
Suppress doc in web examples (#1243)
Building that doc was fairly useless given that all items in the
examples are private.
2025-07-25 17:46:10 +00:00
Olivier FAURE 796ff70db3
Cache RenderContext and VelloRenderer in TestHarness (#1233)
Constructing those types take a lot of time.
Caching them between render calls lets us considerably speed up tests
with multiple snapshots. (Still doesn't help with single-snapshot
tests.)

Re-enable a multi-screenshot test that was taking too long.
2025-07-25 17:43:57 +00:00
Olivier FAURE 531a426cbb
Remove a check from on_access_event methods (#1225)
The `ctx.target() == ctx.widget_id()` checks were added back when
Masonry still used the "send event to every widget in the tree, recurse
inside widget code, use bloom filters to skip subtrees" approach.

It doesn't make sense anymore, except maybe as a guard against bubbling,
but button and checkbox don't have to worry about that.
2025-07-25 14:33:52 +00:00
Olivier FAURE 0d374c6c50
Implement tests to check that widgets can handle a size of zero (#1232)
The tests re-use the examples, since they already use a variety of
widgets.

Tweak harness renderer code to not give wgpu a size of zero in those
cases.

Fix some problems that came up.
2025-07-25 12:41:57 +00:00
Olivier FAURE c9b6f416cd
Add type parameter to TestHarness (#1235)
This lets us skip downcast calls around edit_root_widget and root_widget
(though we don't really use the latter).
2025-07-25 12:09:29 +00:00
Olivier FAURE 48599c40c9
Have ZStack use UnitPoint and remove Alignment enum (#1219) 2025-07-24 19:31:43 +00:00
Olivier FAURE 162da2b22a
Add explicit panic to `RenderRoot:edit_root_widget` (#1234)
Add TODO comment.
2025-07-24 19:14:16 +00:00
Olivier FAURE 3def29b2a4
Make a bunch of property functions const (#1236)
For no particular reason.
Some of the property constructors cannot be made const because they use
trait methods.
2025-07-24 18:19:44 +00:00
Olivier FAURE cea7a58ed4
Rewrite calc_masonry example to use properties for styling (#1227)
Use a Grid widget instead of a hierarchy of Flex widgets for layout
Remove the redundant CalcButton widget implementation.

I'm quite happy with how the result looks, but I'm surprised by the gap
between buttons. It should definitely be smaller. EDIT: Oh, it's because
gave them fairly wide transparent borders. Makes sense.

The example code itself became much, much easier to understand at a
glance.
2025-07-24 13:05:52 +00:00
Olivier FAURE 61b8a82fa7
Add layout caching to Masonry and remove `skip_layout()` method. (#1223)
Remove caching code from `Flex`.
Fix how layout handles stashing flags.

`skip_layout()` was used for stashed widgets (no longer necessary) and
layout caching, which we now handle at the Masonry level.
2025-07-24 12:50:16 +00:00
Bruce Mitchener 23259a3ecb
Re-export `CursorIcon` from `masonry_core::core` (#1222)
Instead of re-exporting `cursor_icon` from `masonry_core` and `masonry`,
we can re-export the single type that matters (`CursorIcon`) from
`masonry_core::core` / `masonry::core`.
2025-07-24 03:08:25 +00:00
Olivier FAURE 99204faff8
Add doc aliases so we can renumber doc chapters without changing imports (#1216) 2025-07-23 17:16:09 +00:00
Olivier FAURE bca4038de0
Add color_rectangle.rs file (#1202)
Add color_rectangle mod which mirror the code examples in the tutorial.
Fix bitrot in tutorials surfaced by creating color_rectangle. Add
snapshot files for new tests in color_rectangle.
2025-07-23 13:45:35 +00:00
Olivier FAURE d43b608764
Document update passes (#1210) 2025-07-23 13:19:30 +00:00
Bruce Mitchener 62ebb73dd2
`masonry`: Import from `masonry_core` via `crate::core` (#1221) 2025-07-23 12:37:48 +00:00
Olivier FAURE e14ba3a5f9
Create `NewWidget` type and refactor all methods that add a child widget to use that type (#1215)
This is a fairly large PR, with a few motivations:

- To introduce the concept of a `NewWidget` type which holds all the
options a widget will be created with.
- To standardize how new widgets are added, and remove the code
duplication in `with_child`, `with_child_id`, `with_child_pod`,
`insert_child`, `insert_child_pod`, etc, methods.
- To make the Xilem-side code much simpler by taking care of the widget
creation options on the Masonry side.
- To prepare the way for #1212.
- To prepare the upcoming lifecycle refactor, in which NewWidget will be
the only way to add a widget to the widget tree.

Overall I think it makes the Masonry APIs more elegant, at the cost of
making the builder-style "Create a widget tree with the children already
filled in" widget construction more verbose.
I think that's a worthwhile trade-off because (1) we still expect most
of our users to be Xilem-style frameworks which can tolerate the
verbosity (2) I expect the builder-style constructors to be
significantly altered in the lifecycle refactor (though I think this PR
is still worth adding even if the lifecycle refactor doesn't come).
2025-07-22 13:42:29 +00:00
Olivier FAURE b12f0275c3
Refactor layout code and remove `WidgetState::synthetic` (#1195)
Make `run_layout_on` function more modular:
- Make it not take a LayoutCtx parameter.
- Make it not propagate state to parent state.
Make run_layout_pass no longer create a fake WidgetState parent to the
root.
Remove `WidgetState::synthetic()` constructor since it's no longer
needed.

Otherwise, doesn't change any behavior.
2025-07-21 21:42:42 +00:00
Olivier FAURE 50d83d7904
Add ChildrenIds type alias to avoid spelling out SmallVec size. (#1190)
Use type alias in various places.
Avoid referencing smallvec from widget code.

Fixes #1141.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2025-07-21 19:18:39 +00:00
Olivier FAURE 0e24f873dd
Add new gradient types (#1206)
Add `GradientShape::Radial` variant.
Add `GradientShape::Sweep` variant.

Add new `Gradient` constructors.
Add screenshot tests for new gradients.

This PR adds a lot of TODOs, but implementing gradients in a way that
closely matches the CSS spec is just hard.
It still covers many common use-cases, and as such it's worth merging
this before figuring out the full solution.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2025-07-21 17:49:48 +00:00
Matt Campbell 2abbf876ee
Accessibility for `VirtualScroll` (#1077)
This implements the right AccessKit role, properties, and actions for
`VirtualScroll`.

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2025-07-21 17:38:29 +00:00
Olivier FAURE 9e3195c172
Add `TestHarness::scroll_into_view` method. (#1214)
This may be useful in cases where the user wants the harness to click
something that would otherwise be scrolled away.
2025-07-21 17:18:11 +00:00
Olivier FAURE a5af61f21d
Rename doc files and modules (#1186) 2025-07-21 17:12:05 +00:00
Olivier FAURE 69e5f2b808
Create WidgetArenaMut type and start refactor of pass internals. (#1197)
This is the first step of a refactor where widgets, widget states and
widget properties will be stored in the same object. So we would end up
with a type like this:

```rust
struct WidgetArenaNode {
    pub(crate) widget: Box<dyn Widget>,
    pub(crate) state: WidgetState,
    pub(crate) properties: AnyMap,
}
```

and WidgetArena might look like:

```rust
pub(crate) struct WidgetArena {
    pub(crate) nodes: TreeArena<WidgetArenaNode>,
}
```

Doing so without making an absolutely unreadable diff is tough, so I
split the work into several PRs. This one just moves code around to make
future diffs shorter.
2025-07-21 17:01:29 +00:00
Olivier FAURE 38e3d9a564
Remove `masonry_core::UnitPoint` and move `Handled` to other module (#1191) 2025-07-21 16:26:14 +00:00
Philipp Mildenberger 72ade97ee1
Add a nix flake to support development on NixOS (#1203)
Adds a basic nix flake with `devShells` that uses a rust environment to
run on various targets, using the MSRV `rust-version` specified in the
root `Cargo.toml`.

Fixes #66

---------

Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
2025-07-21 16:14:48 +00:00
Olivier FAURE 751c75e62a
Update code which handles stashing (#1150)
Avoids the panic in #1119.
2025-07-21 16:02:59 +00:00
Olivier FAURE 6046a097bb
Add active status (#1189)
This replaces "has pointer capture" with "active" as the name of the
concept of "this button / checkbox / widget is being interacted with".
Pointer capture is its own thing and in the future we might want them to
mean slightly different things.

(Also, when we add multiple pointers, checking an "active" flag will be
easier than checking "is this widget the pointer capture target of any
of the currently live pointers".)
2025-07-21 15:59:43 +00:00
Olivier FAURE 80e20e0a3d
Remove some re-exports in masonry crate (#1194) 2025-07-21 11:51:06 +00:00
Olivier FAURE b850b8d659
Rewrite documentation of `events` module (#1211) 2025-07-21 11:13:53 +00:00
Olivier FAURE 8782fb3cb1
Document window_node_id (#1208) 2025-07-21 11:12:43 +00:00
Olivier FAURE 10e2a1a057
Standardize capitalization of the words "widget" and "property" in doc. (#1187)
Avoid capitalizing it as "Widget" unless explicitly referring to the
trait.
2025-07-20 19:49:22 +00:00
Kiran Wells 1f0619d2f0
Prevent adding nodes to focus chain when stashed (#1181)
This appears to fix the issue in #1175. I'm not very familiar with the
accessibility system, but from what I understand the issue was that
stashed nodes were being included in the focus chain used by
`update_focus`. However, when they would be focused, that was failing in
some way (likely due to them being marked as hidden in the accessibility
tree, again due to being stashed). This caused the `update_focus` logic
to break in strange ways, including periodically failing to focus on
anything when `tab` or `shift-tab` is pressed.

I checked the branch in #1179 since it looks related, but the tab
selection issue persists on that branch as well.

### Testing

I did not find any regressions in the other examples during my testing,
but I'm not sure how to properly test this change.
2025-07-20 16:06:53 +00:00
Olivier FAURE 9d23ec33c0
Remove multiple top-level `#[expect]` annotations (#1198) 2025-07-20 15:35:31 +00:00
Olivier FAURE 962d6b6f6f
Add TODO comment to stroke function (#1205)
Follow-up to #1204.
2025-07-20 15:20:28 +00:00
S.J.R. van Schaik 7ebde96105
Avoid drawing a stroke for zero stroke width (#1204)
If you create a `text_input` and set the border width to zero using
`.border_width(0.0)`, it simply fills the entire area with the border
color, and if focused, with a white color. Currently, a workaround for
this is to use some epsilon (e.g., 0.00001 as the border width), but
ideally we should just be able to use `0.0`, and in that case we
shouldn't be drawing any strokes anyway.

This PR simply adds a check to see if `stroke_width` is equal to zero,
and turns the `masonry::util::stroke` function into a no-op, but maybe
there is a more logical spot to do this.
2025-07-20 14:47:34 +00:00
Olivier FAURE c0f929f06f
Refactor flex gap (#1176) 2025-07-20 10:42:25 +00:00