Symptom
On macOS, CSS resize cursors (ew-resize, ns-resize) never appear when hovering over pane resize handles. The cursor stays as the default arrow. mouseenter/mouseleave events also fail to fire on the handles.
Root Cause — Two Stacked Bugs
Layer 1 — WKWebView hit-tests at pre-transform layout coordinates
WebKit's internal EventHandler::selectCursor() performs hit-testing using each element's layout bounding box, not its composited (visual) position. Our resize handles are positioned with transform: translateX/Y(N). The visual position differs from the layout position, so WebKit's cursor-selection hit-test finds the wrong element and the CSS cursor rule on the handle is never evaluated.
document.elementsFromPoint() uses composited coordinates and correctly finds the handle — but this is a different code path from WebKit's internal cursor selection.
Layer 2 — tao's NSView cursor-rect machinery overrides document.body.style.cursor
Even when we correctly detect the handle via elementsFromPoint and set document.body.style.cursor = 'ew-resize', this is overridden by macOS AppKit's resetCursorRects. Tauri's tao layer registers an addCursorRect covering the full NSView bounds, and the AppKit cursor-rect scan (which runs on every mouse-moved event) resets the cursor back to the tao-level default, overriding whatever WebKit set from web content.
A compounding factor: tauri#8770 confirmed that internal_on_mousemove was actively resetting the cursor to default on every mousemove on macOS (fixed in PR #8790). Verify the app runs a Tauri version that includes this fix.
What Was Tried
- CSS
cursor: ew-resize on the handle — fails due to Layer 1 (pre-transform hit-test)
elementsFromPoint on mousemove → document.body.style.cursor — correctly detects the handle (bypasses Layer 1) but fails due to Layer 2 (tao cursor-rect override resets it immediately)
Relevant Issues
| Source |
Issue |
Status |
| wry |
#175 — Cursor bug on macOS |
Fixed (PR #220) |
| tauri |
#8770 — internal_on_mousemove resets cursor on macOS |
Fixed (PR #8790) |
| tauri |
#2588 — macOS cursor weirdness |
Closed as upstream WebKit |
| WebKit |
Bug 101857 — cursor not updating on style change |
Fixed (changeset 142861, 20 ms deferred update) |
| Safari 26.3 |
ticket 166731882 — ew-resize/ns-resize not displaying |
Fixed in Safari 26.3 only |
| Apple Forums |
WebView Doesn't Respect Cursor Properties |
Workaround: override resetCursorRects |
Candidate Fixes (ranked)
Fix 1 (Recommended): Window.setCursorIcon() via Tauri IPC
Replace document.body.style.cursor with getCurrentWindow().setCursorIcon('ewResize'). This calls tao's set_cursor_icon → AppKit NSCursor path at the window level, bypassing both WebKit's CSS cursor system (Layer 1) and the cursor-rect override (Layer 2). The elementsFromPoint detection is already in place — only the cursor-setting call changes.
import { getCurrentWindow } from '@tauri-apps/api/window';
let currentCursor = 'default';
const updateCursor = throttle(16, (x: number, y: number) => {
if (isResizing()) return;
const handle = document.elementsFromPoint(x, y).find(el => el.classList.contains('resize-handle'));
const desired = handle
? (handle.classList.contains('flex-row') ? 'ewResize' : 'nsResize')
: 'default';
if (desired !== currentCursor) {
currentCursor = desired;
getCurrentWindow().setCursorIcon(desired);
}
});
Requires "window:allow-set-cursor-icon" in the app's capabilities JSON.
Fix 2: Remove CSS transform from resize handles; use left/top positioning
Eliminates Layer 1 entirely. If the layout engine positions handles via left: Npx instead of transform: translateX(Npx), WebKit's hit-test finds the element at its visual position and CSS cursor rules work normally. May require layout engine changes.
Fix 3 (Quick attempt): will-change: transform on resize handles
Speculatively forces WebKit to promote the handle to a compositing layer. Some evidence suggests this may cause WebKit to use composited coordinates for hit-testing. 5-minute CSS-only change worth trying first.
.resize-handle { will-change: transform; }
Platform Notes
| macOS |
Safari |
cursor ew-resize display |
hit-test transform bug |
| Sequoia 15.x |
18.x |
Not present |
Present |
| Tahoe 26.0–26.2 |
26.0–26.2 |
Present |
Present |
| Tahoe 26.3+ |
26.3+ |
Fixed |
Present |
Fix must work on Safari 18.x (Sequoia) — still the majority of users (~52% macOS Tahoe adoption as of early 2026).
Full Analysis
Full investigation with deep-dive, source references, and additional candidate fixes: docs/investigations/wkwebview-cursor-transform-bug.md
Symptom
On macOS, CSS resize cursors (
ew-resize,ns-resize) never appear when hovering over pane resize handles. The cursor stays as the default arrow.mouseenter/mouseleaveevents also fail to fire on the handles.Root Cause — Two Stacked Bugs
Layer 1 — WKWebView hit-tests at pre-transform layout coordinates
WebKit's internal
EventHandler::selectCursor()performs hit-testing using each element's layout bounding box, not its composited (visual) position. Our resize handles are positioned withtransform: translateX/Y(N). The visual position differs from the layout position, so WebKit's cursor-selection hit-test finds the wrong element and the CSScursorrule on the handle is never evaluated.document.elementsFromPoint()uses composited coordinates and correctly finds the handle — but this is a different code path from WebKit's internal cursor selection.Layer 2 —
tao's NSView cursor-rect machinery overridesdocument.body.style.cursorEven when we correctly detect the handle via
elementsFromPointand setdocument.body.style.cursor = 'ew-resize', this is overridden by macOS AppKit'sresetCursorRects. Tauri'staolayer registers anaddCursorRectcovering the full NSView bounds, and the AppKit cursor-rect scan (which runs on every mouse-moved event) resets the cursor back to the tao-level default, overriding whatever WebKit set from web content.A compounding factor:
tauri#8770confirmed thatinternal_on_mousemovewas actively resetting the cursor to default on every mousemove on macOS (fixed in PR #8790). Verify the app runs a Tauri version that includes this fix.What Was Tried
cursor: ew-resizeon the handle — fails due to Layer 1 (pre-transform hit-test)elementsFromPointonmousemove→document.body.style.cursor— correctly detects the handle (bypasses Layer 1) but fails due to Layer 2 (tao cursor-rect override resets it immediately)Relevant Issues
internal_on_mousemoveresets cursor on macOSew-resize/ns-resizenot displayingresetCursorRectsCandidate Fixes (ranked)
Fix 1 (Recommended):
Window.setCursorIcon()via Tauri IPCReplace
document.body.style.cursorwithgetCurrentWindow().setCursorIcon('ewResize'). This calls tao'sset_cursor_icon→ AppKitNSCursorpath at the window level, bypassing both WebKit's CSS cursor system (Layer 1) and the cursor-rect override (Layer 2). TheelementsFromPointdetection is already in place — only the cursor-setting call changes.Requires
"window:allow-set-cursor-icon"in the app's capabilities JSON.Fix 2: Remove CSS transform from resize handles; use
left/toppositioningEliminates Layer 1 entirely. If the layout engine positions handles via
left: Npxinstead oftransform: translateX(Npx), WebKit's hit-test finds the element at its visual position and CSScursorrules work normally. May require layout engine changes.Fix 3 (Quick attempt):
will-change: transformon resize handlesSpeculatively forces WebKit to promote the handle to a compositing layer. Some evidence suggests this may cause WebKit to use composited coordinates for hit-testing. 5-minute CSS-only change worth trying first.
Platform Notes
ew-resizedisplayFix must work on Safari 18.x (Sequoia) — still the majority of users (~52% macOS Tahoe adoption as of early 2026).
Full Analysis
Full investigation with deep-dive, source references, and additional candidate fixes:
docs/investigations/wkwebview-cursor-transform-bug.md