Repository navigation
Description
What happened?
When any iframe in the page is navigating, WebView2 shows the system arrow over the whole WebView. This happens even when the iframe is hidden or off-screen. The page's CSS cursor (a custom url() cursor or a keyword such as crosshair) comes back only when that iframe has finished loading.
Our e-book reader preloads the next pages in hidden iframes. Because of this, the cursor flips to the system arrow for 0.1 to 0.5 seconds after every page turn, and back again when the preload finishes.
Importance
Moderate. My app's user experience is affected, but still usable.
Runtime Channel
Stable release (WebView2 Runtime)
Runtime Version
155.0.4283.62
SDK Version
1.0.3650.58
Framework
Win32
Operating System
Windows 11
OS Version
10.0.26300
Repro steps
- Load the page below in WebView2. The page sets
cursor: crosshairon the whole document. - Rest the mouse over the page. Do not move it.
- Click "start". Every second, the page points a hidden iframe at a URL that takes about one second to load.
Expected: the crosshair stays.
Actual: the cursor turns into the system arrow while the hidden iframe loads, then goes back to the crosshair.
<!doctype html>
<html style="cursor: crosshair; height: 100%">
<body style="height: 100%; margin: 0">
<button id="b">start</button>
<iframe id="f" style="position: absolute; left: -10000px; width: 10px; height: 10px"></iframe>
<script>
b.onclick = () => setInterval(() => { f.src = "https://httpbin.org/delay/1?" + Date.now(); }, 2000);
</script>
</body>
</html>The same happens with a custom cursor (cursor: url(cur.png) 0 0, auto). It also happens with a same-origin blob: iframe navigated through contentWindow.location.replace(). That case is shorter, but you still see it.
Where it comes from (Chromium):
FrameTree::NodeLoadingStateChangedcallsroot()->render_manager()->SetIsLoading(...)whenever any frame in the tree starts or stops loading. This includes subframe loads thatGetLoadingStatereports asLOADING_WITHOUT_UI.RenderWidgetHostViewAura::SetIsLoading→UpdateCursorIfOverSelf:As a result, any page cursor except// Do not show loading cursor when the cursor is currently hidden. if (is_loading_ && cursor != ui::mojom::CursorType::kNone) cursor = ui::Cursor(ui::mojom::CursorType::kPointer);
nonebecomes the pointer until every frame finishes loading.
Suggestion: do not override the page's cursor for loads that do not show loading UI. For example, apply the override only for LOADING_UI_REQUESTED (a main-frame navigation), or give hosts a setting to turn it off.
Workaround we use: while our own iframes navigate, we set cursor: none !important and draw the cursor image ourselves at the mouse position. We wait about 40 ms before navigating, so that Blink's 20 ms cursor update reaches the browser first.
Repros in Edge Browser
Yes, issue can be reproduced in the corresponding Edge version
Regression
No, this never worked
Last working version (if regression)
No response
Activity