Skip to content

bug(macOS): resize handle cursor (ew-resize/ns-resize) never appears — WKWebView pre-transform hit-test + tao cursor-rect override #247

@a5af

Description

@a5af

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

  1. CSS cursor: ew-resize on the handle — fails due to Layer 1 (pre-transform hit-test)
  2. elementsFromPoint on mousemovedocument.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 #8770internal_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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions