slint icon indicating copy to clipboard operation
slint copied to clipboard

Rectangle is not rendering when using the 'winit' backend - works fine with the Qt backend

Open bennysj opened this issue 1 month ago • 4 comments

Bug Description

The idea is to ping and drag an rectangle / area. This works perfectly fine using the Qt backend. With the 'winit' the Rectangle is not rendered.

Reproducible Code (if applicable)

export component AppWindow inherits Window {
    width: 1280px;
    height: 1000px;

    Rectangle {
        visible: touch.pressed;
        x: touch.mouse-x > touch.pressed-x ? touch.pressed-x : touch.mouse-x;
        y: touch.mouse-y > touch.pressed-y ? touch.pressed-y : touch.mouse-y;
        width: Math.abs(touch.pressed-x - touch.mouse-x);
        height: Math.abs(touch.pressed-y - touch.mouse-y);
        border-color: darkgray;
        border-width: 1px;
        background: darkblue;
        opacity: 0.34;

        changed x => {
            debug("x=", self.x);
        }

        changed y => {
            debug("y=", self.y);
        }

        changed width => {
            debug("width=", self.width);
        }

        changed height => {
            debug("height=", self.height);
        }

    }

    touch := TouchArea {
    }
}

Environment Details

  • Slint Version: 1.14
  • Platform/OS: Fedora Linux 42
  • Programming Language: Slint & Rust
  • Backend/Renderer: winit

Product Impact

No response

bennysj avatar Nov 28 '25 09:11 bennysj

I can reproduce with femtovg. All other renderer works fine.

ogoffart avatar Nov 28 '25 10:11 ogoffart

Simplified test case:

export component AppWindow inherits Window {
    preferred-width: 1280px;
    preferred-height: 1000px;

    background: touch.pressed ?  #888 : #777;

    Rectangle {
        visible: !touch.pressed;
        width: 50%;
        height: 50%;
        background: darkblue;
        opacity: 0.34;

    }

    touch := TouchArea { }
}

Strangly, the blue rectangle is shown before clicking, but doesn't re-appear after the click.

ogoffart avatar Nov 28 '25 10:11 ogoffart

I investigated the issue a bit, here is what happens:

  • The opacity creates a layer (because there is two children item: the Clip (for visible) and the Rectangle). (technically a layer wouldn't be required but we're not smart enough to detect Clip doesn't render)
  • The layer is cached but somehow doesn't register a dependency on the Clip::clip property when it is false. (probably because the size is 0x0)
  • When the visibility goes back to true, the cached layer is rendered without redrawing

ogoffart avatar Nov 28 '25 10:11 ogoffart

The thiing is that we return None here because the texture would be empty. https://github.com/slint-ui/slint/blob/25ec2fb589fc7cf2a76f86780b6f22fbe02f6e6a/internal/renderers/femtovg/itemrenderer.rs#L1086

This causes us to bypass the render_item_children that register any dependencies

ogoffart avatar Nov 28 '25 11:11 ogoffart