fix: restore accelerated scrolling on Linux WebKitGTK - #210
Conversation
Scrolling felt sluggish and inconsistent across the whole app (chat, sidebar, menus) on Linux. Two root causes: 1. The Wayland crash workaround set WEBKIT_DISABLE_DMABUF_RENDERER=1 and WEBKIT_DISABLE_COMPOSITING_MODE=1 process-wide, forcing WebKitGTK into non-accelerated CPU rendering (~56ms per scroll frame vs ~16ms accelerated). Replaced with WEBKIT_DMABUF_RENDERER_FORCE_SHM=1, which keeps GPU compositing and threaded scrolling while routing the final buffer handoff through shared memory - avoiding both the dual-GPU Wayland explicit-sync crash (Error 71, WebKit bug 280210) and the GBM EGL failure. A startup crash sentinel falls back to the legacy compatibility flags after repeated failed accelerated launches. 2. WebKitGTK's enable-smooth-scrolling default animates wheel input with a per-event retargeted 200ms easing (WebKit bug 258926), so high-rate wheel input made content move slower the faster you scrolled. Smooth scrolling is now disabled on every webview window by default, with an opt-in toggle under Settings > Appearance. Renderer env hygiene, so stale flags can never defeat the fix: - tauri:dev scripts no longer hardcode WEBKIT_DISABLE_DMABUF_RENDERER - flags inherited from an older parent app instance are scrubbed (CODEMUX_WEBKIT_COMPAT=1 and =0 values remain explicit escape hatches) - PTY/terminal/daemon children no longer inherit renderer vars Frontend scroll polish: - transcript edge fade re-enabled (free once composited; auto-disables via get_renderer_mode when the app runs in compatibility mode) - cm-sweep animates transform instead of left (no per-frame layout) - preset bar / title bar tabs: shared non-passive wheel handler with deltaMode normalization and preventDefault only when consumed - MessageTrail normalizes wheel deltaMode before scrollTop writes - scroll-lock wheel guard added to the launch reasoning picker - removed six undefined (no-op) scrollbar/fade utility classes - sidebar row transition-all narrowed to the properties it animates Verified: cargo test 2263 lib tests + integration suites, vitest 3070 tests across 212 files, tsc clean.
Deep review — Opus 5 (high effort)I gave this one the extra pass. Root-causing four previous attempts down to a single process-wide env var is genuinely good work, and the fix is the right shape: What I verified as correctRather than list what I read, here is what I actively went looking to break and couldn't:
Findings1. The compat-mode probe is value-blind, and the rest of the module isn'tlet non_composited = std::env::var_os(DISABLE_DMABUF_ENV).is_some()
|| std::env::var_os(DISABLE_COMPOSITING_ENV).is_some();
COMPAT_MODE.store(non_composited, Ordering::Release);
Cosmetic in effect, but it's the one place in a carefully value-aware file that ignores the value. 2.
|
|
Extra-deep review by GPT 5.6 Sol xhigh found two functional issues:
I also checked the implementation against WebKitGTK's current Validation: |
- Make the compat-mode report value-aware: WEBKIT_DISABLE_*=0 is WebKit's own opt-out and no longer flags the process as CPU-rendered - Gate the accelerated FORCE_SHM default on WebKitGTK 2.40+ (the DMA-BUF renderer floor); older runtimes go straight to the legacy compatibility flags instead of crashing until the sentinel trips - Disarm the crash sentinel on a graceful run-loop exit so interrupted startups no longer count toward the CPU-rendering fallback threshold - Skip the renderer-mode probe and smooth-scrolling init on the web remote client and hide the Settings scrolling toggle there: both act on the desktop host's webview, not the browser the user is viewing - Drop the dead userAgent parameter from decideTranscriptFade and the unused scrollbar-none class in the attachment carousel
Problem
Scrolling across the entire app on Linux (chat transcript, sidebar, menus, dialogs) felt sluggish, inconsistent, and got slower the faster you scrolled — despite multiple past attempts (#119, #141, #156, #185) that each fixed real symptoms but never the cause.
Root causes
1. The app forced WebKitGTK into CPU rendering. The April Wayland-crash workaround set
WEBKIT_DISABLE_DMABUF_RENDERER=1+WEBKIT_DISABLE_COMPOSITING_MODE=1process-wide, disabling accelerated compositing and threaded scrolling for every surface. Measured: ~56ms per scroll frame (~18fps) vs ~16ms (~63fps) accelerated. This is why the jank was app-wide and why frontend-level fixes never stuck — PR #185 explicitly deferred this flag as a follow-up.2. WebKitGTK smooth scrolling is broken for high-resolution wheels (WebKit bug 258926): each wheel event retargets the scroll animation and resets its clock against a 200ms eased duration, so faster input produces slower motion by construction.
enable-smooth-scrollingdefaults to TRUE and wry never disables it.Fix
WEBKIT_DMABUF_RENDERER_FORCE_SHM=1: keeps GPU compositing + async scrolling, routes only the final buffer handoff through shared memory — avoiding the dual-GPU Wayland explicit-sync crash (WebKit bug 280210, "Error 71") and the GBM EGL failure. Verified crash-free and stable on the affected hardware (RTX 3090 + AMD iGPU, Wayland and X11).webview_tuning.rs): if accelerated startup fails twice consecutively, fall back (sticky) to the legacy compatibility flags. Cleared on a successful main-window page load; duplicate launches can't fake a crash streak.CODEMUX_WEBKIT_COMPAT=1andWEBKIT_DMABUF_RENDERER_FORCE_SHM=0remain explicit escape hatches.tauri:devscripts no longer hardcode a disable flag; flags inherited from an older running app instance are detected and scrubbed (with a stderr diagnostic); PTY/terminal/daemon children no longer inherit renderer vars at all.Frontend polish
get_renderer_modecommand whenever the app actually runs in compatibility modecm-sweepanimatestransforminstead ofleft(verified pixel-identical travel; no per-frame layout)useHorizontalWheelScroll) withdeltaModenormalization;preventDefaultonly when the strip consumed the scroll, so edge wheels still chaindeltaModebeforescrollTopwritesreact-remove-scrolllock rule; other surfaces correctly need none)transition-allDeliberately deferred
Verification
cargo checkclean;cargo test: 2263 lib tests + all integration suites passing (incl. 8 newwebview_tuningtests)tsc --noEmitclean;vitest: 212 files / 3070 tests passing (new tests for wheel normalization, smooth-scrolling setting/hook, fade gating, tab-strip wheel behavior)