Fixed
- Animated cursor consumes 50-60% GPU at idle — the rAF animation loop ran at 60-120fps continuously whenever the editor had focus because
this.active = animating || this.view.hasFocusalways evaluated totrue. The heartbeat timer (500ms setInterval) also re-woke the loop every 500ms if it stopped, defeating any idle-stop optimization. Implemented a 4-phase GPU optimization: (1) fixed theactiveflag to only reflect animation state (active = animating), (2) added a 3-gear frame governor (hot: rAF at ~60fps during animation, warm: setTimeout 600ms for blink toggle, stopped: no scheduling), (3) dirty-rect canvas clearing (only clear the cursor's bounding box instead of full viewport), (4) per-frame overhead reduction (cachedgetComputedStyle,matchMedia, accent color; mutable physics quad to eliminate 20 object allocations per tick). Idle GPU usage drops from 60-120 rAF/sec to ~1.67 rAF/sec (97-99% reduction). (#148)- Plugin:
src/vim/animated-cursor/manager.ts(3-gear frame governor with hot/warm/stopped states, heartbeat stall detection vialastLoopTime, dirty-rect tracking viamarkDirty()/snapshotDirtyRegion(), DPR change listener, MutationObserver for theme detection,sizeCanvas()moved to ResizeObserver) - Plugin:
src/vim/animated-cursor/controller.ts(active = animating, cached block char info per position, accent color refresh on theme change only,needsBlink()for warm gear scheduling) - Plugin:
src/vim/animated-cursor/physics.ts(mutabletargetQuadviaupdateQuadFromRect(), eliminates per-frame allocations) - Plugin:
src/vim/animated-cursor/config.ts(cachedprefers-reduced-motionmedia query with change listener) - Plugin:
src/vim/animated-cursor/types.ts(needsBlink()anddidDraw()added toTickableinterface)
- Plugin:
Tests
- Animated cursor idle rAF rate measurement — empirical e2e test that instruments
requestAnimationFrameto count callbacks over a 5-second idle window with animated cursor enabled. Verifies rAF rate is well below continuous 60fps (before: 825 rAF/5sec = 165/sec; after: 8 rAF/5sec = 1.6/sec — 99% reduction). (#148)- Test:
test/specs/animated-cursor.e2e.ts(rAF counter via patchedwindow.requestAnimationFrame, 5-second idle measurement, threshold assertion < 150)
- Test:
- Table-nav hotkey test uses platform-correct modifier on macOS — the
Ctrl+Pregression test for table-nav hotkey passthrough (#146) hardcodedKey.Control, which does not open the command palette on macOS (where the shortcut isCmd+P). The test now usesobsidianPage.getPlatform()and sendsKey.Commandon macOS,Key.Controlelsewhere.- Test:
test/specs/table-nav-hotkeys.e2e.ts(platform-aware modifier key viaobsidianPage.getPlatform())
- Test:
Documentation
CHANGELOG.mdKNOWN_LIMITATIONS.md: updated animated cursor section — marked rAF loop death as enhanced with gear system, added GPU optimization detailsdocs/features/animated-cursor.md: updated cross-platform resilience section with gear system details
Full Changelog: 0.130.0...0.131.0