Add a method which brute-force resets the paint and accessibility flags
for all widgets.
This is useful for rescale, and for testing purposes where you want a
quick and dirty way to repaint everything.
Each widget implementation was doing its own bespoke tracing in layout.
This removes the bespoke tracing and adds a trace inside the layout pass
logging the same information in a more centralized way.
The main reason to do this is I'd like to stick to a pattern where all
the recursive pass functions call widget methods directly. I believe
this makes the code much easier to read and understand, even if you
don't consciously notice this pattern.
There was no good reason for selection to be optional, except to not
display it when focus was lost. This is now handled with a boolean flag.
A side-effect of this is that TextWithSelection now remembers its
selection when focus is gained back.
Selection was used with a default value of `(0, 0)` in cases where it
was `None`, so its default value in similar cases is still `(0, 0)`.
This adds public getters for clip path to non-`LayoutCtx` contexts, and
also to `WidgetState` as it seems relevant for painting.
The motivation is to remove private field accesses from
`Widget::get_child_at_pos` as mentioned in
https://github.com/linebender/xilem/pull/565#issuecomment-2374162416.
This leaves one private field access, namely `WidgetState::is_stashed`.
As per the docs of `WidgetState` ("widgets will generally not interact
with it directly"), that field perhaps should not be publicly accessible
from `WidgetState`, but then it should be accessible from `WidgetRef`.
This is very useful for debugging performance issues. I've already used
it to debug [#masonry>`to_do_list`: Horrendous
performance](https://xi.zulipchat.com/#narrow/stream/317477-masonry/topic/to_do_list.3A.20Horrendous.20performance).
Setting a feature works on a workspace-wide basis. I.e `cargo run
--example mason --features tracy` works.
Some weirdness:
- Tracy seems to assume we know when a frame will "start", but we only
know if we'll repaint once processing for an event has finished.
- Something seems to be starting a default "Frame", which isn't really
right. We don't have any continuous frames. Maybe we should always
request a redraw if tracy is enabled.
Either way, I think this feature is useful to land *now*, so am not
planning on resolving these in this PR unless someone provides a
solution.
Reimplement calculation of image size in `Image` widget `layout`
function.
Makes it match against `self.fill` before setting size.
Tests still missing.
Fixes#574
When the scrollbars are not being set, the calculations get NaNs. This
breaks rendering, causing extreme slowdowns and artifacts.
This is discussed in [#masonry>`to_do_list`: Horrendous
performance](https://xi.zulipchat.com/#narrow/stream/317477-masonry/topic/to_do_list.3A.20Horrendous.20performance)
I've made this work now using `is_explicitly_stashed` in layout. It does
not currently cause issues there.
The underlying issue of `NaN`s being created (and not detected) have not
been resolved.
It makes more sense to pass the `NodeBuilder` reference separately to
the `accessibility` method. In particular, this avoids the need to keep
calling a method on `AccessCtx` to get that mutable reference.
The `Widget::get_child_at_pos` has a default linear search
implementation, upholding some conditions (e.g., picking the last child
in "z-order" in case of overlap). Widgets can override this with a
custom implementation (e.g., a widget with many children that maintains
a quadtree to search through). Custom implementations should uphold the
same conditions, we can add some debug assertions to check this in a
later PR.
This introduces a `QueryCtx`, allowing widget methods access to the
global state, widget state, and widget subtree. `QueryCtx` is similar to
the other (mutable) context types, but can be shared.
This also changes `WidgetRef` to consist of a `Widget` and a `QueryCtx`,
similar to `WidgetMut` consisting of a `Widget` and `MutateCtx`. This
required changing where `WidgetRef` can be constructed.
This resolves code comment
ac95f2524a/masonry/src/widget/widget_ref.rs (L192-L199)
Should fix the way repaints were requested every paint on some
platforms.
This PR unfortunately comes with a lack of tests. TestHarness currently
doesn't have good support for testing signals, but even if it did, this
is an inherently visual feature that we don't really have a way to test
visually.
I don't know how to trigger IME on my machine. (I'm using PopOS, a
Debian variant.) If someone wants to either test this or help me get to
speed, I'd appreciate it.
Requesting and resigning focus can happen when handling pointer and
accessibility events, not just keyboard events.
---------
Co-authored-by: Olivier FAURE <couteaubleu@gmail.com>
I believe this is necessary to activate and deactivate input focus with
TalkBack on Android. Assistive technologies on other platforms can also
request the focus action, though none of the AccessKit backends support
the blur action yet.
---------
Co-authored-by: Olivier FAURE <couteaubleu@gmail.com>
Add update_focus_chain pass.
Add update_new_widgets pass.
Remove RenderRoot::root_lifecycle.
Move call_widget_method_with_checks out of Widgetpod.
These new passes aren't intended to stay long-term, but are meant to
make future refactors easier and more concise.
The other goal is to remove almost all the remaining code in the
lifecycle method.
This is part of the Pass Specification RFC:
https://github.com/linebender/rfcs/pull/7
---------
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
This PR adds a basic grid layout to Masonry and Xilem.
The way this layout works is it has a fixed grid based on the initial
size passed in, and grid items are placed based on the position
requested. Grid items are allowed to span more than one cell, if
requested.
There are potential improvements that could be done, like the use of
intrinsic sizing for varied column width based on content size. Though
that could be done in the future taffy layout if we want to keep this
one simple.
~~This PR is still a draft because of one remaining concern. I was not
able to successfully optimize with conditional calls to child widgets
for layout. It led to crashes about the paint rects not being within the
widget's paint rect. `Error in 'Grid' #16: paint_rect Rect { x0: 0.0,
y0: 0.0, x1: 800.0, y1: 610.0 } doesn't contain paint_rect Rect { x0:
400.5, y0: 0.0, x1: 800.5, y1: 150.0 } of child widget 'Button' #5`. My
failed attempt at fixing it is commented out.~~
Since I am rusty on View Sequences, a lot of that code is based on the
Flex implementation. Let me know if I did anything incorrectly or if any
of it is unnecessary, or if anything is missing.
---------
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
Also improve documentation of pointer capture.
Continuation of 59ee615651
(https://github.com/linebender/xilem/pull/488).
Makes `has_pointer_capture` available on all context types except
`LayoutCtx`, like `is_active` used to be.
This is part of the Pass Specification RFC:
https://github.com/linebender/rfcs/pull/7
Note: This PRs comes with a lot of new TODO items. Addressing most of
these items is difficult without major refactors, because Portal code
deals with accessing values across multiple widgets, which is still hard
to do elegantly.
Fixes#576
Can someone who's more familiar with Masonry please confirm that I'm
doing this the right way? I assume that one is supposed to call
request_accessibility update along with request_paint whenever the
change to the widget state could affect accessibility.
This example is inspired by:
https://troz.net/post/2024/swiftui-mac-2024/
Current status:
- Lists status code
- Can select status code
- Downloads image from status code
- Shows image from status code
This adds two new features to Xilem:
- The worker view, which is the obvious extension to `task` for multiple
operations
- The `image` view, which just uses Masonry `Image`.
It also fixes a the Masonry Image view's layout to use the already
extant but unused method.
@PoignardAzur I wanted to have a play with masonry, so I had a go at
building a progress bar. I've made a PR in case you want it, but I won't
be offended if you close the PR. I'm happy to make changes if you see
anything you'd like to change.
---------
Co-authored-by: Olivier FAURE <couteaubleu@gmail.com>
Co-authored-by: jaredoconnell <jared.oc321@gmail.com>
This is also added to `variable_clocks` as needed.
This could also be added to `mason`, but I see a worrying amount of lag
if I do...
I could do with some help tracking this down.
Fixes https://github.com/linebender/xilem/issues/559
See comment on the fix for an explanation. Essentially, the `major`
value was used for multiple purposes, and this corrects into the
expected "direction".
Recursing is done inside the paint and accessibility passes since
ff7635e4c2. I believe this is the correct
continuation of #522, with the removal of these methods "left for later"
as mentioned in
https://github.com/linebender/xilem/pull/522#issuecomment-2298610203.
One note is that Flex now debug-paints its baseline under its children,
rather than over them.
The `SizedBox` widget in Masonry had the option to set a background
brush that was not exposed in its corresponding view in Xilem. The
`SizedBox` view now exposes the option.
Incidentally, `BackgroundBrush::PainterFn` variant had the wrong type,
as such it was not usable. A `scene` parameter is added and the closure
now requires to be `Send + Sync`.
---------
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
Unfortunately this lint is very conservative in its detection, it hasn't
detected the other fix in this PR...
I manually checked, if we had any other bitwise or/and for booleans, and
indeed this was the only case.
---------
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
- Adds tracing_android_trace
- Correct the span for VariableLabel
- Make the created apps "debuggable"
- Enable spans for `wgpu`'s `profiling` results
- Add a span around the Vello rendering to show when that is
One of the problems we ran into with the `to_do_list` example was that
we had a `Flex` inside a `Portal`: the `Portal` widget is designed to
display scrollbars and provide scrolling if the child is larger than its
constraints... but then Flex's `layout` method always clipped the
returned size so it wasn't ever larger than its constraints. Hence, no
scrolling. Removing the `bc.constrain(my_size)` part makes the example
have scrolling behavior again.
This PR also tweaks scrolling code and adds `#[track_caller]` attributes
to help with debugging.
---------
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
I opened https://github.com/linebender/xilem/issues/473 earlier today,
but I realized after looking at the code that it would be super simple
to implement!
Copying over some context from that issue:
- I'm working on a graph renderer using Vello.
- I'm porting it over to a Masonry widget, so that I can build a UI
around it.
- In doing so I noticed there wasn't support for winit's `PinchGesture`,
which I had been using before when messing around with this on my macOS
device.
Please let me know if y'all feel like this is appropriate to include
inside of `PointerEvent`!
This adds a new `VariableLabel` widget, which animates its weight to a
target value in a linear fashion (over a fixed time period). Also adds
support for this in Xilem, and a new `variable_clock` example. This
example also runs on Android.
[Screencast_20240812_171138.webm](https://github.com/user-attachments/assets/5df623f9-f4ca-4b55-b6a9-2047d2581b56)
Current status: The code in Xilem and Masonry library crates is final.
I'm planning on significantly updating the actual example.
Outstanding issues:
- [X] Hacks in support for "Roboto Flex", by always loading it from the
local file - resolved
- [X] It's not clear what subset of Roboto Flex we should use - still
open to bikeshedding
- [ ] The variable font animation support is not really as generic as it
should be. This starts to drift quite close to a styling question,
however.
- [ ] The only supported variable axis is `wgth`
Rather than have to keep a dependency on `kurbo` at the correct version,
always use it via `vello`.
This makes this match how `peniko` is already used within `masonry`.
This is part of the "Pass Specification" RFC:
https://github.com/linebender/rfcs/pull/7
Rename WidgetCtx to MutateCtx.
Add a mutate pass.
Add a `mutate_later` context method to trigger that pass.
Refactor `edit_root_widget` to use a version of that pass.
Add a separate constructor for the synthetic WidgetState created in
RenderRoot.
---------
Co-authored-by: Philipp Mildenberger <philipp@mildenberger.me>
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
This is a first step in implementing the "Pass Specification" RFC:
https://github.com/linebender/rfcs/pull/7
Create a `passes` module.
Create event passes.
Create the update_pointer pass.
Remove `WidgetPod::update_hot_state` method.
Move mouse-cursor-handling code to update_pointer pass.
Implement pointer capture.
Refactor the TreeArena code.
---------
Co-authored-by: Daniel McNab <36049421+DJMcNab@users.noreply.github.com>
These either aren't used, aren't implemented, or are just stubs. A new
implementation may or may not take the same approach given changes
within the ecosystem, and if we want these back, they're in the history.