Ultralight icon indicating copy to clipboard operation
Ultralight copied to clipboard

Display artifacts when scrolling page using window.scrollTo()

Open JohnKlenk opened this issue 10 months ago • 3 comments

This is new in 1.4, and only happens in CPU render mode.

1.) Build the sample browser in CPU render mode, via the following line after declaring the "Settings settings;" line in Browser.cpp: settings.force_cpu_renderer = true; 2.) Open the attached "scrollTo_artifact_bug.htm" in the sample browser. 3.) Click in the page body. 4.) Use the up/down arrow keys to move "focus" to different cells.

Bug: When the page scrolls, the "focus" outline can get left behind (also happens with box-shadow).

The problem does not happen when .scrollIntoView() is used, but that function has limitations so scrollTo() is needed for my use case.

scrollTo_artifact_bug.zip

JohnKlenk avatar Apr 29 '25 05:04 JohnKlenk

Screenshot:

Image

JohnKlenk avatar Apr 29 '25 05:04 JohnKlenk

For anyone else who needs a workaround until the fix is in place, here's a function you can call after using window.scrollTo():

function ForceRepaint()
{
    document.body.style.transform = 'scale(1)';
    document.body.offsetHeight;
    document.body.style.transform = '';
}

JohnKlenk avatar Apr 29 '25 19:04 JohnKlenk

Also seeing the apparent same issue sometimes when scrolling with the mouse wheel. Fixed content at the top of the page can leave artifacts in the content below when the lower content is scrolled. My workaround for that is a combination of the following:

    window.addEventListener('scroll', () =>
    {
        ForceRepaint();
    });
function ForceRepaint()
{
    let elem1= document.getElementById('elemcontainer1');
    elem1.style.transform = 'scale(1)';
    elem1.offsetHeight;
    elem1.style.transform = '';

    let elem2= document.getElementById('elemcontainer2');
    elem2.style.transform = 'scale(1)';
    elem2.offsetHeight;
    elem2.style.transform = '';
}

The ForceRepaint() function was changed to only apply to the affected element containers, because applying it to body requires a 10+ timeout to scroll down more than a little bit with the mousewheel or scrollbar, and it results in the page immediately scrolling back to the top unless you use window.scrollTo() to subsequently put it back where it should be. The solution of only affecting the desired elements seems better, and I don't think I can tell a difference whether or not a timeout is used.

JohnKlenk avatar Apr 29 '25 23:04 JohnKlenk

A fix for this will be in 1.4.1-dev (with ViewConfig::enable_compositor = true).

Scrolling was completely rewritten in 1.4.1 to utilize the new tiled compositor backend (works on both CPU and GPU).

P.S., Long story short, upstream WebKit deprecated the old "dirty rectangling" pathway we were using for accelerated scroll on CPU (which has been around since almost the KHTML days) in favor of a new compositing architecture that was designed primarily for out-of-process GPU compositing (which was at odds with our immediate-mode CPU renderer and platform-agnostic GPU renderer).

It took about 9 months of work but we were able to figure out a way to compromise between their new architecture and our unique pipeline so that we can finally get to rendering parity with Chrome/Safari.

adamjs avatar Jul 01 '25 00:07 adamjs

Fixed in 1.4.1-f6c121e1 dev build; closing.

JohnKlenk avatar Jul 08 '25 03:07 JohnKlenk