fix(cursor): native cursor overlay fixes for multi-display, crop, zoom and export consistency#2
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
712bd02 to
1d2a421
Compare
64a755a to
055e04a
Compare
|
现在我是已经把光标 overflow 给删掉了 修了多余运动轨迹采集的 bug 我来加一个可选 overflow or not 的开关 After more testing I've reconsidered the cursor-overflow approach: Removed the overflow clipping. The hard clip-path/canvas clipping that confined the cursor to the video bounds is gone — clipping the native cursor at the edge looked worse than letting it sit slightly outside in some cases. |
|
This part is done 👇 Multi-display ghost cursor / motion-trail fix Flow: please @EtienneLescot review and merge this PR into feat/macos-native-capture-pipeline first; it then flows upstream into main via siddharthvaddem#573. Ready for review — thanks! 🙏 |
|
@auberginewly Thanks for the contribution, the feature looks relevant and useful to me overall. I’d like to keep this PR focused and easy to review before merging it into the macOS native capture branch. Could you please squash/reorganize the current commits into 1 or 2 clean commits? There are currently quite a few intermediate commits for the size of the change, and a cleaner history would make the contribution easier to understand. One technical point to double-check before merge: in Apart from that, the functional scope looks good to me: cursor canvas clipping, editor/export consistency, and the related cursor settings i18n all seem relevant. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
src/i18n/locales/zh-TW/settings.json (1)
12-12: Pre-existing structural issue: emptyspeedobject.Line 12 contains an empty
"speed": {}object nested within thezoomsection. This is not part of the current changes but may cause confusion or linting issues.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/i18n/locales/zh-TW/settings.json` at line 12, The JSON contains an extraneous empty "speed" object inside the "zoom" section; remove the empty "speed": {} entry (or replace it with the proper localized keys/values if intended) so the "zoom" object only contains meaningful translation entries—look for the "zoom" object and the "speed" key in settings.json and delete or populate that empty "speed" entry.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/video-editor/SettingsPanel.tsx`:
- Around line 1399-1407: The new Switch (checked={cursorClipToBounds},
onCheckedChange={onCursorClipToBoundsChange}) lacks an accessible name; update
the Switch to include either an aria-label (e.g.,
aria-label={t("cursor.clipToBounds")}) or wire it to the existing text using
aria-labelledby by giving the text element an id and passing that id to
aria-labelledby on the Switch so screen readers announce what the control
toggles within SettingsPanel.
In `@src/components/video-editor/VideoPlayback.tsx`:
- Around line 2036-2055: The native cursor clip DIV (nativeCursorClipRef) is
placed outside composite3DRef so it doesn't receive the same
contain-scale/rotateX/Y/Z 3D transforms and thus the preview cursor stays
unrotated; fix by ensuring the cursor clip and image share the same 3D transform
as the video—either move the nativeCursorClipRef (and its nativeCursorImageRef)
inside the composite3DRef container or apply the identical transform
styles/classes (preserve-3d + the computed
contain-scale/rotateX/rotateY/rotateZ) to nativeCursorClipRef at the same point
where composite3DRef is updated so preview and export remain consistent.
In `@src/i18n/locales/vi/settings.json`:
- Around line 194-201: The translation for cursor.motionBlur ("Mờ chuyển động")
is inconsistent with effects.motionBlur ("Làm mờ chuyển động"); update the value
for "cursor.motionBlur" in the settings.json locale so it matches the existing
phrasing used by "effects.motionBlur" to ensure consistent terminology across
the UI (look for the "cursor.motionBlur" and "effects.motionBlur" keys and
replace the cursor entry with the same string as effects.motionBlur).
In `@src/i18n/locales/zh-TW/settings.json`:
- Around line 195-202: The translation for cursor.motionBlur should match the
existing term used elsewhere: replace the value for "cursor.motionBlur"
(currently "運動模糊") with the same string used by "effects.motionBlur" ("動態模糊") so
both keys use consistent terminology; update the "cursor" object entry for
motionBlur accordingly.
In `@src/lib/exporter/frameRenderer.ts`:
- Around line 529-546: The cameraAwareMaskRect function currently clamps mask
edges to the stage using Math.max/Math.min which forces export clipping inside
the canvas; remove those clamps so the computed rect can extend outside the
stage: compute left/top as camX + camS * maskX and right/bottom as camX + camS *
(maskX + maskW) (using layoutCache.maskRect, layoutCache.stageSize, and
animationState.appliedScale/x/y to locate the code), then return x=left, y=top,
width=right-left, height=bottom-top and br=layoutCache.maskBorderRadius * camS
without applying Math.max/Math.min clamping.
---
Nitpick comments:
In `@src/i18n/locales/zh-TW/settings.json`:
- Line 12: The JSON contains an extraneous empty "speed" object inside the
"zoom" section; remove the empty "speed": {} entry (or replace it with the
proper localized keys/values if intended) so the "zoom" object only contains
meaningful translation entries—look for the "zoom" object and the "speed" key in
settings.json and delete or populate that empty "speed" entry.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 16b1f9bc-6281-4dfe-826e-bc1f3999b154
📒 Files selected for processing (20)
electron/native-bridge/cursor/recording/macNativeCursorRecordingSession.tssrc/components/video-editor/SettingsPanel.tsxsrc/components/video-editor/VideoEditor.tsxsrc/components/video-editor/VideoPlayback.tsxsrc/components/video-editor/types.tssrc/components/video-editor/videoPlayback/layoutUtils.tssrc/i18n/locales/ar/settings.jsonsrc/i18n/locales/en/settings.jsonsrc/i18n/locales/es/settings.jsonsrc/i18n/locales/fr/settings.jsonsrc/i18n/locales/ja-JP/settings.jsonsrc/i18n/locales/ko-KR/settings.jsonsrc/i18n/locales/ru/settings.jsonsrc/i18n/locales/tr/settings.jsonsrc/i18n/locales/vi/settings.jsonsrc/i18n/locales/zh-CN/settings.jsonsrc/i18n/locales/zh-TW/settings.jsonsrc/lib/exporter/frameRenderer.tssrc/lib/exporter/gifExporter.tssrc/lib/exporter/videoExporter.ts
…iew and export - Add nativeCursorClipRef div (outside preserve-3d) with CSS inset() clip-path that tracks the camera-transformed video boundary, including border-radius - Add cameraAwareMaskRect() in FrameRenderer that computes the same boundary for Canvas 2D clip in the export path; remove stage-clamping so rounded corners match the preview's inset() behavior when zoom/pan pushes the mask off-stage - Cache maskBorderRadius in LayoutCache so both shadow and direct composite paths can apply camera-aware rounded clipping - Fix double mask.x offset introduced by nativeCursorMaskRef; replace mask div with clip-path on the outer wrapper - Normalize cursor size relative to maskRect.width so preview and export scale match - Clip cursor to canvas boundary and hide on non-recorded display - Wire cursorClipToBounds flag through FrameRenderConfig and VideoExporter
Add a cursor.clipToBounds toggle to the Settings panel (default on) that controls whether the native cursor is clipped to the video canvas boundary in both preview and export. Wire up 11 locale files (ar, en, es, fr, ja-JP, ko-KR, ru, tr, vi, zh-CN, zh-TW) with the new cursor settings section.
8e65240 to
cfd0042
Compare
|
Done — two things addressed: Commits squashed
The specific mismatch with rounded corners: when zoom/pan pushes the mask rect partially off-stage (e.g. left edge is at // before
const left = Math.max(0, camX + camS * maskX);
const right = Math.min(stageW, camX + camS * (maskX + maskW));
// after — canvas clips out-of-bounds naturally, same as CSS inset()
x: camX + camS * maskX,
width: camS * maskW,The fix applies to all three call-sites (cursor clip, shadow composite, direct composite). |
|
@auberginewly thanks for your swift reply ;-) |
I see!Thanks!this is my first time to write a new feature,and I’ll try my best |
… i18n - Add aria-label to cursorClipToBounds Switch so screen readers announce the control - Mirror composite3D 3D transform onto nativeCursorClipRef so the cursor clip layer rotates with the video during 3D zoom regions (cursor stays outside preserve-3d so clip-path continues to work; only the transform string is mirrored) - Fix vi cursor.motionBlur: "Mờ chuyển động" → "Làm mờ chuyển động" to match effects.motionBlur phrasing - Fix zh-TW cursor.motionBlur: "運動模糊" → "動態模糊" to match effects.motionBlur
|
is that all right?👀 |
|
@auberginewly yes, this looks good to me now. I checked the latest commit |
90a0447
into
EtienneLescot:feat/macos-native-capture-pipeline
Summary
A series of fixes for the macOS native cursor overlay across the
multi-display recording, video crop, zoom, rounded-corner and export
scenarios — keeping the preview path (VideoPlayback.tsx) and the
export path (frameRenderer.ts) consistent — plus a user-facing
toggle to allow the cursor to overflow the canvas.
Problems & fixes
Multi-display ghost cursor & motion trail
Recording display A, moving the mouse to non-recorded display B clamped
the cursor to the canvas edge and kept it visible, producing a long
trail flying back from the edge on return.
macNativeCursorRecordingSession, markvisible: falsewhen out ofbounds — this triggers
hideNativeCursorPreview()and resets smoothing /motion blur, so the cursor snaps cleanly on return.
≈100ms); fast swipes out-and-back are handled by clip-path at the edge
instead of flickering invisible.
Cursor overflowing the video canvas
The enlarged cursor overlay bled into the editor background. The
ancestor's
overflow:hiddenwas broken bytransform-style: preserve-3don
composite3DRef.clip-path: inset()(unaffected by preserve-3d),clipping precisely via
baseMaskRef(incl. crop) + border radius.nativeCursorClipRefout of thepreserve-3dcontainer soclip-path stays correct under 3D-rotation zoom regions.
scale/translation.
Preview / export cursor size mismatch
renderAsset.widthis absolute px; preview canvas ~600px vs export1920px gave a ~3x size discrepancy.
maskRect.width / croppedVideoWidth, sothe cursor occupies the same fraction of the video in both.
Lost rounded corners & zoom over-crop on export
corners → explicit
roundRectclip enforces rounded corners (shadowpath erases square corners via destination-out + evenodd, then
redraws).
is inside cameraContainer and scales with zoom so the video fills the
magnified bounds, but the static maskRect rounded clip on export still
used the small non-zoom size. Extracted
cameraAwareMaskRect()toshare one camera transform across shadow / direct / cursor paths;
degrades to the original static behavior at zoom=1 (no regression).
Consistency cleanup
maskBorderRadiusinLayoutCacheso preview and export sharethe same rounded-corner value.
borderRadiusRefsync effect: a standaloneeffect overwrote the screenCover→0 (full-bleed) corrected value with
the raw prop, making vertical-stack/split presets disagree between
preview and export.
New feature: "Clip to Canvas" toggle
Clipping the cursor to the video bounds is now optional. Added a
cursorClipToBoundssetting (default on, fully backward compatible)in the Show Cursor settings section:
the preview and the exported MP4/GIF.
clip-path,export
drawNativeCursor); the video rounded-corner clips incompositeWithShadowsare fully decoupled and unaffected.settings).
The entire cursor settings section (Show Cursor / Size / Smoothing /
Motion Blur / Click Bounce / Clip to Canvas) is now i18n-backed across
all 11 locales (previously hardcoded English).
Key files
electron/native-bridge/cursor/recording/macNativeCursorRecordingSession.tsvisible:false+ hysteresissrc/components/video-editor/VideoPlayback.tsxsrc/components/video-editor/videoPlayback/layoutUtils.tssrc/lib/exporter/frameRenderer.tssrc/components/video-editor/{VideoEditor,SettingsPanel}.tsx,types.tssrc/lib/exporter/{videoExporter,gifExporter}.tssrc/i18n/locales/*/settings.json(11 locales)cursorsectionTest plan
npm run i18n:check,tsc --noEmit,npm run build-viteall pass🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements