We had the raw_window_handle_06 feature and functions in Rust, but there
wasn't an easy way to do the same in C++. This is especially useful for
embedding windows (such as browsers, 3D views, etc.) or just wanting to
access the platform's handles for other reasons.
ChangeLog: It's now possible to access platform native window handles
from C++, like a HWND.
No point in stuffing u16 into f32 just to reuse an existing type.
OTOH ArrayOfU16 can be reused for other things than grid layout
organized data, so give it a more generic name than
GridLayoutOrganizedData (we should do the same for LayoutCache, at
least if we ever reuse the type for an additional purpose)
The goal is to be able to enable feature conditionally with `i-slint-renderer-software/?...`
NOTE: this change the implementation of
`SceneBuilder::platform_text_fill_brush/platform_text_stroke_brush`
It was warning about `non_exhaustive_omitted_patterns`.
And it changed it to always return the brush color so gradient gets
converted to plain color instead of None.
This is the behavior with the non-parley renderer
This seems just be a typo, I think it's supposed check if _WIN32 *or*
_WIN64 is defined. Before compilation for Linux could easily pass
through because it doesn't have _WIN64 defined.
Shouldn't have any adverse affects since this was never going to work on
Linux in the first place.
This allows to store the result into a different cache property
than the one that comes out of solve_grid_layout, which fixes
a binding loop when the text of a widget depends on its row or col
value.
* Add support for CSS conic-gradient 'from <angle>' syntax
Implement rotation support for conic gradients by adding the 'from <angle>'
syntax, which rotates the entire gradient by the specified angle.
- Add `from_angle` field to ConicGradient expression
- Parse 'from <angle>' syntax in compiler (defaults to 0deg when omitted)
- Normalize angles to 0-1 range (0.0 = 0°, 1.0 = 360°)
- Add `ConicGradientBrush::rotated_stops()` method that:
* Applies rotation by adding from_angle to each stop position
* Adds boundary stops at 0.0 and 1.0 with interpolated colors
* Handles stops outside [0, 1] range for boundary interpolation
- Update all renderers (Skia, FemtoVG, Qt, Software) to use rotated_stops()
The rotation is applied at render time by the rotated_stops() method,
which ensures all renderers consistently handle the gradient rotation.
* Add screenshot to rotated conic gradient docs example
Wraps the rotated conic gradient example in CodeSnippetMD to automatically
generate and display a visual screenshot of the gradient rotation effect.
This makes it easier for users to understand how the 'from' parameter rotates
the gradient.
* Make ConicGradientBrush fields private
The from_angle and stops fields don't need to be pub since:
- Rust code in the same module can access them without pub
- C++ FFI access works through cbindgen-generated struct (C++ struct members are public by default)
* Optimize ConicGradientBrush::rotated_stops to avoid allocations
- Changed return type from Vec to SharedVector
- When from_angle is zero, returns a clone of internal SharedVector
(only increments reference count instead of allocating new Vec)
- Removed break from duplicate position separation loop to handle
all duplicate pairs, not just the first one
- Updated documentation to match actual implementation
* Remove automatic sorting in ConicGradientBrush::new() to match CSS spec
- CSS conic-gradient does not automatically sort color stops
- Stops are processed in the order specified by the user
- Changed boundary stop interpolation logic to use max_by/min_by
instead of relying on sorted order
- This allows CSS-style hard transitions when stops are out of order
* Move conic gradient rotation processing to construction time
Major changes:
- ConicGradientBrush::new() now applies rotation and boundary stop
processing immediately, instead of deferring to rotated_stops()
- Removed rotated_stops() method - backends now use stops() directly
- Changed to LinearGradientBrush pattern: store angle in first dummy stop
- Added angle() method to retrieve the stored angle
- Maintained #[repr(transparent)] by removing from_angle field
- All backends updated: rotated_stops() -> stops()
- Qt backend
- Skia renderer
- femtovg renderer
- Software renderer
C++ API changes:
- Added FFI function slint_conic_gradient_new() for C++ to call Rust's new()
- Updated make_conic_gradient() to call FFI function instead of manually
constructing SharedVector
- Ensures C++-created gradients get full rotation processing
Benefits:
- Eliminates per-frame rotation calculations
- Reduces memory usage (no from_angle field)
- Consistent with LinearGradientBrush design
- C++ and Rust APIs now produce identical results
* Change ConicGradientBrush::new() from_angle parameter to use degrees
- Changed from_angle parameter from normalized form (0.0-1.0) to degrees
- Matches LinearGradientBrush API convention (angle in degrees)
- Updated internal conversion: from_angle / 360.0 for normalization
- Stores angle as-is in degrees in the first dummy stop
- FFI function slint_conic_gradient_new() passes degrees directly
Example usage:
ConicGradientBrush::new(90.0, stops) // 90 degrees
LinearGradientBrush::new(90.0, stops) // 90 degrees (consistent)
* Fix ConicGradient color transformation methods to preserve angle
Changed brighter(), darker(), transparentize(), and with_alpha() methods
to clone and modify the gradient in-place instead of calling new().
- Clones the existing gradient (preserves angle and rotation)
- Modifies only color stops (skips first stop which contains angle)
- Avoids re-running expensive rotation processing
- Maintains the original angle information
Before: ConicGradientBrush::new(0.0, ...) // Lost angle information
After: Clone + modify colors in-place // Preserves angle
* Use premultiplied alpha interpolation for conic gradient colors
- Changed interpolate_color() to use premultiplied RGBA interpolation
- Updated signature to match Color::mix convention (&Color, factor)
- Added documentation explaining why we can't use Color::mix() here
(Sass algorithm vs CSS gradient color interpolation)
- Reference: https://www.w3.org/TR/css-images-4/#color-interpolation
This ensures correct visual interpolation of semi-transparent colors
in gradient boundaries, following CSS gradient specification.
* Run rustfmt on conic gradient code
* Fix ConicGradientBrush edge cases and add comprehensive tests
- Handle stops that are all below 0.0 or all above 1.0
- Add default transparent gradient when no valid stops remain
- Add 7 unit tests covering basic functionality and edge cases
* Apply clippy suggestion: use retain() instead of filter().collect()
* Fix radial-gradient parsing to allow empty gradients
Allow @radial-gradient(circle) without color stops, fixing syntax test
regression from commit 820ae2b04.
The previous logic required a comma after 'circle', but it should only
error if there's something that is NOT a comma.
* Fix conic-gradient syntax test error markers
Update error markers to match actual compiler error positions.
The 'from 2' case produces two errors:
- One at the @conic-gradient expression level
- One at the literal '2' position
Auto-updated using SLINT_SYNTAX_TEST_UPDATE=1.
* Refactor ConicGradientBrush epsilon adjustment and update tests
- Move epsilon adjustment for first stop into rotation block
(only needed when rotation is applied)
- Update property_view test to reflect boundary stops added by
ConicGradientBrush::new()
* Update conic-gradient screenshot reference image
Update the reference screenshot to match the current rendering output.
The small pixel differences (1% different pixels, max color diff 3.46)
are due to minor rounding differences in the conic gradient implementation.
* Fix ConicGradientBrush C++ FFI to avoid C-linkage return type error
Refactored ConicGradientBrush construction to match LinearGradientBrush
pattern, fixing macOS Clang error about returning C++ types from extern "C"
functions.
Changes:
- Rust: Split ConicGradientBrush::new into simple construction + separate
normalize_stops() and apply_rotation() methods
- Rust: Added FFI functions slint_conic_gradient_normalize_stops() and
slint_conic_gradient_apply_rotation() that take pointers (no return value)
- C++: Construct SharedVector directly in make_conic_gradient(), then call
Rust functions via pointer (matching LinearGradientBrush pattern)
- Optimized both methods to only copy when changes are needed
This resolves the macOS Clang error:
"'slint_conic_gradient_new' has C-linkage specified, but returns incomplete
type 'ConicGradientBrush' which could be incompatible with C"
The new approach maintains ABI compatibility while keeping complex gradient
processing logic in Rust.
* Fix C++ header generation to avoid GradientStop redefinition error
Resolves the macOS CI compilation error where GradientStop and
ConicGradientBrush were being defined in multiple headers
(slint_color_internal.h, slint_image_internal.h, and slint_brush_internal.h).
Changes:
- cbindgen.rs: Add ConicGradientBrush and FFI functions to slint_brush_internal.h include list
- cbindgen.rs: Add GradientStop, ConicGradientBrush, and FFI functions to exclude list for other headers
- slint_color.h: Add forward declaration for ConicGradientBrush
- slint_color.h: Add friend declaration for ConicGradientBrush to allow access to Color::inner
Root cause: After adding extern "C" functions in graphics/brush.rs,
cbindgen automatically detects and tries to include them in all headers
that use graphics/brush.rs as a source. The exclude list + filter logic
ensures these types only appear in slint_brush_internal.h.
This fixes the C++ compilation errors:
- "redefinition of 'GradientStop'"
- "ConicGradientBrush does not name a type"
- "Color::inner is private within this context"
* Prepare ConicGradientBrush FFI for Rust 2024 edition
Update FFI functions to use the new `#[unsafe(no_mangle)]` attribute
syntax and safe function signatures in preparation for Rust 2024 edition.
- Add `#![allow(unsafe_code)]` to graphics module for `#[unsafe(no_mangle)]`
- Add `#[cfg(feature = "ffi")]` to conditionally compile FFI functions
- Change from raw pointers to safe references (&mut)
- Remove manual null checks and unsafe blocks
For the implementation of BuiltinFunction::GetWindowDefaultFontSize, instead of going to the window adapter's window item rc (which will be the outermost window item), start at the first item of the current component and work the way up from there.
Fixes#4298
After commit e04f028c91, the
default-font-size property on WindowItem isn't set anymore by default,
so BuiltinFunction::GetWindowDefaultFontSize, which reads it, would
return zero.
Instead, delegate to a run-time function where we can fall back to the
default from the renderer.
This patch changes rem.slint to use the newer syntax. The main change to
the test case though is to removal of the explicit default-font-size
property setting, so that we fall back to the value provided by the
renderer. This test relies on being run with the testing backend.
Fixes#8961
The second constructor of `Slice` causes the Slice to be passed
differently (in different register) as a return value.
So remove that constructor and use a helper function to
construct a Slice
Previously there were two kinds of Menu:
1. "Simple" menu that don't have any `if` or `for`
2. "Complex" menu that have `if` and `for`
For the first kind, we were generating in the compiler the `entries` and
`sub-menu` callback. This lead to more efficient and simple code at
runtime.
For the second kind, we generate an item tree so we can dynamically
produce them at runtime.
The issue is that as we added feature, the code became complex to
handle, even in the simple case as we need to create a `VRc<MenuVTable>`
also for the context menu so we can have native context menu.
We still need the "Simple" case for the internal though.
So for that I added a ShowPopupMenuInternal builtin function although it
only differ from ShowPopupMenu by the type of its second argument.
Since the generated code has lots in common, they are still handled
together.
The proof that the two different codepath were harmful is that removing
it showed a bug with contextmenu within repeated element.
the `contextmenu_delete.slint` started failling. It worked before
because it was only a problem with "Complex" menu and the test used a
"Simple" menu.
The change in the interpreter should also solve the issue #9031 which
were using the wrong item tree as the menu.
- Implement @conic-gradient(color angle, ...) syntax
- Center is always at rectangle center (no center_x/center_y parameters)
- 0 degrees starts at north (12 o'clock position)
- Support Slint angle units: deg, rad, turn
- Software renderer: Full native implementation
- Qt backend: Native support with angle offset correction
- Skia backend: Native support with angle offset correction
- FemtoVG backend: Fallback to solid color (first gradient stop)
ChangeLog: Added support for `@conic-gradient`
Fixes#3957
Missing feature:
- conversion between Value and enums
- conversion from value to Model
- Compatibility with the testing framework (get the `VRc<ItemTreeTable>` from an instance)
This exposes FocusReason to .slint, and adds it as an argument to focus-event-changed callback on FocusScope to close#8387. It also adds two new callbacks, focus-gained and focus-lost, which are identical to focus-event-changed but are only invoked on focus gain or loss respectively.
In addition to this, it removes the FocusEventReason::AccessKit variant, replacing it with the mouse variant to hopefully make AccessKit more compatible with any Slint code that will use FocusEventReason.
Finally, I added two tests based on focus_change_event.slint, one for testing the FocusEventReason argument and another for testing the new callbacks.
close#8387
ChangeLog: Added `focus-gained` and `focus-lost` callback to FocusScope. Pass an `FocusReason` enum to the FocusScope callbacks
Closes#5992
Adds the enum FocusEventReason and makes it an argument for FocusEvent. This reason could eventually be exposed in Slint to solve #8387.
Using the focus reason tracking, I also added a select all on keyboard focus for TextInputs (except on macOS), which should close#5992.
ChangeLog: TextInput selects its content when focused with the keyboard on Windows and Linux