https://bugs.kde.org/show_bug.cgi?id=527273

Grief <[email protected]> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |[email protected]

--- Comment #1 from Grief <[email protected]> ---
I hit the same regression on 6.8.0 (NVIDIA RTX 5080, Wayland, scale 2.25,
cursor size 83, cursor theme "hand-of-evil") and traced it in the source.

Root cause: commit 0e4fd91b "compositor: make cursor repaints smoother" (fix
for bug 509669). Before it, the lambda connected to
OutputLayer::repaintScheduled in Compositor::setupLayers bailed out when
cursorView->needsRepaint() was true and left re-rendering of the cursor image
to composite(). Now it renders the cursor layer synchronously, directly from
the signal (prepareRendering + renderLayer + presentAsync).

The problem is that CursorItem::setImage() updates the item in three separate
steps:

    m_imageItem->setImage(image);                             // 1
    m_imageItem->setPosition(-hotspot);                       // 2
    m_imageItem->setSize(image.size() / image.devicePixelRatio()); // 3

Step 1 calls discardQuads() + scheduleRepaint(), which emits repaintScheduled
synchronously, so the layer is rendered right there: new texture, but the item
still has the OLD size (and old hotspot). Quads are rebuilt from the old
boundingRect. Step 3 (Item::setSize) calls scheduleRepaint(rect()) twice and
only then discardQuads(); the second scheduleRepaint again renders
synchronously, still with the cached quads from step 1, i.e. the old geometry.
After that nothing triggers another render: cursor movement only moves the
plane (canSkipMoveRepaint). Result: the new image is stretched to the
dimensions of the previous image until the image changes again. For animated
shapes every frame is drawn with the previous frame's size.

That is why it only shows with themes whose shapes have different image sizes.
KDE Classic: left_ptr is 10x16, fleur/size_* are 16x16, so after a drag the
arrow is stretched to 16x16 ("very wide"). hand-of-evil: arrow 166x78, pointing
hand 166x90 with animation frames 166..176 wide, so the hand is visibly
squeezed horizontally while hovering links and the arrow is stretched
vertically after leaving them. Breeze is unaffected because all images are
32x32. It is invisible in screenshots/videos because it only affects the
hardware cursor plane buffer.

Workarounds: KWIN_FORCE_SW_CURSOR=1 (software cursor is rendered in
composite(), after all three setters ran), or a theme where all images have
identical dimensions (padding all images of my theme to a common canvas fixed
it for me).

Possible fixes: apply size and position before setImage() in
CursorItem::setImage() (then the last synchronous render sees the final
geometry), or better, don't render from inside the repaintScheduled handler
while the item is mid-update, e.g. defer the render to the event loop /
compositing cycle.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to