We used to called borrow_mut twice in a row, that can never work.
I suspect we never reached this code path before, but the preview does
because the ComponentContainer probably instentiate its contents in
places that can cause the geometry cache to be empty while doing the
rendering (while it is most likely being filled when computing the dirty
regions
and their related name.
Also move the component module in the item_Tree module
register_component -> register_item_tree
ComponentItemTree -> ItemTreeNodeArray
For #3323
Rationale from that issue:
Right now, we use the term `component` in the Slint language and in the compiler to be a a tree of elements that can be used as an element in a .slint file.
The term is also currently used in the runtime as a tree of runtime Items that are allocated together. (declared in ComponentVTable)
But there are no 1 to 1 mapping between a `component` in the slint language, and a runtime Component.
(for example, the items behind a `if` or `for` or `PopupMenu` are in a different runtime component. And `component` declared in Slint are often inlined)
So we should rename the internal runtime `Component` to `ItemTree`
The currently public `slint::ComponentHandle` wraps the "root" of the ItemTree, but that's ok because it is generated from a .slint `component`, so it doesn't change name
Previously, all the closures passed to `get_or_update_cache_entry` would
have to make sure that the scale factor is an included dependency. This
is error prone, as the parent commits show.
Instead, this change adds a property tracker to each ItemCache and lets
the renderer clear the cache if the scale factor changes.
Strictly speaking this may delete too many entries from the cache (not
all depend on the scale factor), but on the other hand this doesn't
happen very often so we trade robustness over efficiency.
The cursor is loaded by the window adapter from the cache. When it's
loaded the first time, its format will be Svg, so we convert it to a
pixel buffer. That way the skia backend can convert it on first draw
into a skia_safe::Image and replace the cache entry with the backend
storage variant.
So that we don't need to query the geometry multiple time, and this pave
the way to not have the geometry in the items
Part of #1932
As a drive by, fix the clipping of the Path element which incorrectly
offseted the clip by (x,y).
Similar fixes happen in the Clip element in some renderer, but that
didn't have effect because x and y are always 0 for the Clip element
... as well as opacity
When an item change its geometry or clipping, one really must also
refresh all the children, even the ones outside of the item.
And if the position of the parent changes, the old offset must still be
used to compute the geometry
This change also add the clip to the dirty region so we don't need to
draw so much for clipped items
This removes the special code for the generated property getters and
ensures type safety in the run-time library for property value setting.
In the Rust generated code we continue to do arithmetic on the scalar
values, that means we immediately extract the scalar, do arithmetic and
rely on the compiler to only allow compatible units.
Danger zone alert: In the interpreter Value::Number can now be converted
to LogicalLength as-is.
During the rendering, if an area is clipped, it will not be rendered and
therefore will not be rendered as a dependency.
Consider this example:
```
HorizontalBox {
Rectangle {
TouchArea{
Rectangle { background: parent.pressed ? red : blue; }
}
}
Rectangle {
clip: true;
TouchArea{
Rectangle { background: parent.pressed ? red: blue; }
}
}
}
}
```
Clicking on the first rectangle will make that area dirty and it will be
redrawn, but since the second one is clipped away, the renderer will not
visit the child items. And clicking on the second rectangle will not
make it re-drawn.
This patch makes sure we rejuster ad dependency of the window tracker
the non-dirty areas
This fix the printerdemo_mcu stopping to render in some cases
And add a test in the CI that checks for warnings in the internal
crates
(Also changed --exlcude in the test to be matching the one from build,
since c++ test are tested separately)
Previously: Window is an Rc<WindowInner>, which has an Rc<dyn
PLatformWindow> - and weak references the other way around.
Now: Rc<dyn PlatformWindow> is the root of window ownership. The impl
PlatformWindow has a slint::api::Window, which just holds a WindowInner.
This change is incomplete on a few levels, mainly that neither of the
code generators nor the interpreter is ported.
When the renderer does not re-implement visit_clip, we call combine_clip.
Then we're missing out on an optimization the GL renderer does: When the resulting clip region
is empty, we do not need to recurse into children for rendering.
That itself reduces the property dependency chain and avoids unnecessary
updates when invisible (clipped) children change properties.
The as_any() method returning a `&mut dyn Any` meant that the type has to be
'static. The class solution of returning &()
doesn't work because it has to be a mutable ref. Therefore just return an Option.
Now that we store the layer textures as Rc<Texture>, before rendering a
layer we can take a clone of a possibly existing layer texture and if if
the layer's tracker is dirty, we can re-use the existing layer texture
if it's the same size.
This avoids unnecessary texture allocations.
I want a more generic name as I want to do to track component structure
changes in addition to resource freeing and I do not want to add another
call into the generated code.
The borrow logic in ItemCache<T>::get_or_update_cache_entry requires us
to take the per-item cache dirty tracker out of the cache entry, so that
we can drop the ref and allow the update_fn to access the cache for
other items during evaluation.
However in order for the cache to work by not re-evaluating the
update_fn next time if nothing rendering related change, we must put the
tracker back after the check/evaluation, otherwise take() will always
return none.
This is a regression from commit
6cbf2c0609 that changed the call from
get_or_update() - which puts the tracker back - to
get_or_update_cache_entry(), which doesn't. Since the former is now
unused, this commit also removes it.
When computing the dirty regions, the call to geometry() might end up
querying a value that's computed by the layout. For the layout
computation we might end up calling ensure_updated() on a repeater,
which then might destroy components. The destruction involves freeing
cached dirty rectangles (via free_graphics_resources), and that also
requires a write access to the cache. So after retrieving the property
tracker for the dirty geometry, drop access to the cache before calling
geometry().
When using repeaters - like in the slide puzzle - and during renderer a component
gets deleted, we call free_graphics_resources and try to free
the dirty rectangle list in the partial renderer cache. At that point the cache is
already mutably borrowed, which causes a panic.
As remedy, apply the mutable borrow more fine grained and not right when calling
render().