Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for box shadows and out-of-geometry text items with the partial renderer #7450

Merged
merged 8 commits into from
Jan 30, 2025
126 changes: 126 additions & 0 deletions api/rs/slint/tests/partial_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,129 @@ fn window_background() {
ui.set_c(slint::Color::from_rgb_u8(45, 12, 13));
assert!(!window.draw_if_needed(|_| { unreachable!() }));
}

#[test]
fn touch_area_doesnt_cause_redraw() {
slint::slint! {
export component Ui inherits Window {
in property <color> c: yellow;
in property <length> touch-area-1-x <=> ta1.x;
in property <length> touch-area-2-x <=> ta2.x;
in property <color> sole-pixel-color: red;
background: black;
ta1 := TouchArea {
x: 10px;
y: 0px;
width: 20px;
height: 40px;
Rectangle {
x: 1phx;
y: 20phx;
width: 15phx;
height: 17phx;
background: c;
}
}
ta2 := TouchArea {
x: 10px;
y: 0px;
width: 20px;
height: 40px;
}
sole-pixel := Rectangle {
x: 60px;
y: 0px;
width: 1px;
height: 1px;
background: sole-pixel-color;
}
}
}

slint::platform::set_platform(Box::new(TestPlatform)).ok();
let ui = Ui::new().unwrap();
let window = WINDOW.with(|x| x.clone());
window.set_size(slint::PhysicalSize::new(180, 260));
ui.show().unwrap();
assert!(window.draw_if_needed(|renderer| {
do_test_render_region(renderer, 0, 0, 180, 260);
}));
assert!(!window.draw_if_needed(|_| { unreachable!() }));
ui.set_c(slint::Color::from_rgb_u8(45, 12, 13));
assert!(window.draw_if_needed(|renderer| {
do_test_render_region(renderer, 10 + 1, 20, 10 + 1 + 15, 20 + 17);
}));
assert!(!window.draw_if_needed(|_| { unreachable!() }));
ui.set_touch_area_1_x(20.);
assert!(window.draw_if_needed(|renderer| {
do_test_render_region(renderer, 10 + 1, 20, 10 + 1 + 15 + 10, 20 + 17);
}));
assert!(!window.draw_if_needed(|_| { unreachable!() }));
ui.set_touch_area_2_x(20.);
ui.set_sole_pixel_color(slint::Color::from_rgb_u8(45, 12, 13));
// Moving the touch area should not cause it to be redrawn.
assert!(window.draw_if_needed(|renderer| {
do_test_render_region(renderer, 60, 0, 61, 1);
}));
}

#[test]
fn shadow_redraw_beyond_geometry() {
slint::slint! {
export component Ui inherits Window {
in property <length> x-pos: 10px;
Rectangle {
x: root.x-pos;
y: 10px;
width: 20px;
height: 20px;
drop-shadow-blur: 5px;
drop-shadow-offset-x: 15px;
drop-shadow-offset-y: 5px;
drop-shadow-color: red;
}
}
}

slint::platform::set_platform(Box::new(TestPlatform)).ok();

let window = SKIA_WINDOW.with(|w| w.clone());
NEXT_WINDOW_CHOICE.with(|choice| {
*choice.borrow_mut() = Some(window.clone());
});
let ui = Ui::new().unwrap();
window.set_size(slint::PhysicalSize::new(250, 250).into());
ui.show().unwrap();

assert!(window.draw_if_needed());
assert_eq!(
window.last_dirty_region_bounding_box_size(),
Some(slint::LogicalSize { width: 250., height: 250. })
);
assert_eq!(
window.last_dirty_region_bounding_box_origin(),
Some(slint::LogicalPosition { x: 0., y: 0. })
);

assert!(!window.draw_if_needed());

ui.set_x_pos(20.);

assert!(window.draw_if_needed());

let shadow_width = /* rect width */ 20. + 2. * /* blur */ 5.;
let move_delta = 10.;
let shadow_height = /* rect height */ 20. + 2. * /*blur */ 5.;

let old_shadow_x = /* rect x */ 10. + /* shadow offset */ 15. - /* blur */ 5.;
let old_shadow_y = /* rect y */ 10. + /* shadow offset */ 5. - /* blur */ 5.;

assert_eq!(
window.last_dirty_region_bounding_box_size(),
Some(slint::LogicalSize { width: shadow_width + move_delta, height: shadow_height })
);
assert_eq!(
window.last_dirty_region_bounding_box_origin(),
Some(slint::LogicalPosition { x: old_shadow_x, y: old_shadow_y })
);
}
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,15 @@ impl Item for NativeButton {
qApp->style()->drawControl(QStyle::CE_PushButton, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeButton {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/checkbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,15 @@ impl Item for NativeCheckBox {
qApp->style()->drawControl(QStyle::CE_CheckBox, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeCheckBox {
Expand Down
18 changes: 18 additions & 0 deletions internal/backends/qt/qt_widgets/combobox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ impl Item for NativeComboBox {
qApp->style()->drawControl(QStyle::CE_ComboBoxLabel, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeComboBox {
Expand Down Expand Up @@ -250,6 +259,15 @@ impl Item for NativeComboBoxPopup {
style->drawControl(QStyle::CE_ShapedFrame, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeComboBoxPopup {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/groupbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ impl Item for NativeGroupBox {
qApp->style()->drawComplexControl(QStyle::CC_GroupBox, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeGroupBox {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/lineedit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,15 @@ impl Item for NativeLineEdit {
qApp->style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeLineEdit {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/listviewitem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ impl Item for NativeStandardListViewItem {
}
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeStandardListViewItem {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/progress_indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ impl Item for NativeProgressIndicator {
qApp->style()->drawControl(QStyle::CE_ProgressBar, &option, painter_, widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeProgressIndicator {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/scrollview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,15 @@ impl Item for NativeScrollView {
);
}
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeScrollView {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/slider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,15 @@ impl Item for NativeSlider {
style->drawComplexControl(QStyle::CC_Slider, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl NativeSlider {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/spinbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,15 @@ impl Item for NativeSpinBox {
(*painter)->drawText(text_rect, QString::number(value), QTextOption(static_cast<Qt::AlignmentFlag>(horizontal_alignment)));
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeSpinBox {
Expand Down
9 changes: 9 additions & 0 deletions internal/backends/qt/qt_widgets/tableheadersection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,15 @@ impl Item for NativeTableHeaderSection {
#endif
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeTableHeaderSection {
Expand Down
18 changes: 18 additions & 0 deletions internal/backends/qt/qt_widgets/tabwidget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,15 @@ impl Item for NativeTabWidget {
style->drawPrimitive(QStyle::PE_FrameTabBarBase, &optTabBase, painter->get(), widget);*/
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeTabWidget {
Expand Down Expand Up @@ -528,6 +537,15 @@ impl Item for NativeTab {
qApp->style()->drawControl(QStyle::CE_TabBarTab, &option, painter->get(), widget);
});
}

fn bounding_rect(
self: core::pin::Pin<&Self>,
_window_adapter: &Rc<dyn WindowAdapter>,
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
geometry
}
}

impl ItemConsts for NativeTab {
Expand Down
6 changes: 5 additions & 1 deletion internal/backends/qt/qt_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1591,10 +1591,12 @@ impl QtItemRenderer<'_> {

std::mem::swap(&mut self.painter, &mut layer_painter);

let window_adapter = self.window().window_adapter();

i_slint_core::item_rendering::render_item_children(
self,
&item_rc.item_tree(),
item_rc.index() as isize,
item_rc.index() as isize, &window_adapter
);

std::mem::swap(&mut self.painter, &mut layer_painter);
Expand Down Expand Up @@ -1713,6 +1715,7 @@ impl QtWindow {

fn paint_event(&self, painter: QPainterPtr) {
let runtime_window = WindowInner::from_pub(&self.window);
let window_adapter = runtime_window.window_adapter();
runtime_window.draw_contents(|components| {
i_slint_core::animations::update_animations();
let mut renderer = QtItemRenderer {
Expand All @@ -1727,6 +1730,7 @@ impl QtWindow {
component,
&mut renderer,
*origin,
&window_adapter,
);
}

Expand Down
Loading
Loading