Skip to content

Keep HUD interactive on Linux so the drag handle can receive pointer events#17

Merged
EtienneLescot merged 1 commit into
mainfrom
codex/fix-linux-hud-drag
Jun 22, 2026
Merged

Keep HUD interactive on Linux so the drag handle can receive pointer events#17
EtienneLescot merged 1 commit into
mainfrom
codex/fix-linux-hud-drag

Conversation

@EtienneLescot

@EtienneLescot EtienneLescot commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Fixes #12

Problem

On Linux (Manjaro KDE Wayland), the HUD launch widget shows a drag handle but cannot be moved: clicks on the handle have no effect and the window stays stuck in place. macOS and Windows are unaffected.

Root cause

LaunchWindow toggles the HUD overlay into setIgnoreMouseEvents(true) whenever the pointer leaves interactive regions. On macOS/Windows this is fine because setIgnoreMouseEvents only affects regions marked as "transparent" — but on Linux/Wayland the whole window stops receiving pointer events, so the drag handle never sees the pointerdown that starts a drag.

Fix

In src/components/launch/LaunchWindow.tsx, treat the HUD as always interactive on Linux:

  • Track the platform via getPlatform() and keep an isLinuxHud flag.
  • When computing the value sent to Electron, force shouldIgnoreMouseEvents = false on Linux.
  • Adjust the IPC cache so the cache key reflects the value actually sent, not just the React "enabled" flag — otherwise a platform switch could fail to push an update to Electron.

Test

Added a unit test in src/components/launch/LaunchWindow.test.tsx:

  • Mocks getPlatform to return linux.
  • Renders LaunchWindow and asserts setHudOverlayIgnoreMouseEvents is called with false, so the HUD stays clickable.

Validation

  • npx vitest --run src/components/launch/LaunchWindow.test.tsx passes.
  • npm run build-vite passes.
  • Pre-commit Biome hook passes.

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved HUD overlay behavior on Linux systems—the overlay now remains interactive instead of becoming unresponsive when certain toggles are adjusted, enhancing user experience on Linux platforms.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b3ed7af1-53cb-4bf6-9ddb-ce729830469f

📥 Commits

Reviewing files that changed from the base of the PR and between cb97db6 and a6cd0af.

📒 Files selected for processing (2)
  • src/components/launch/LaunchWindow.test.tsx
  • src/components/launch/LaunchWindow.tsx

📝 Walkthrough

Walkthrough

LaunchWindow adds an isLinuxHud state populated during platform detection. The HUD mouse-event callback now computes shouldIgnoreMouseEvents = !enabled && !isLinuxHud, preventing the overlay from blocking mouse input on Linux. Tests introduce a mutable platformState variable and add a Linux-specific assertion.

Changes

Linux HUD Mouse Event Handling

Layer / File(s) Summary
isLinuxHud state and mouse-event callback
src/components/launch/LaunchWindow.tsx
Adds isLinuxHud React state; the platform-detection effect sets it to true when platform === "linux" and resets it on error. The mouse-event callback is replaced: it now computes shouldIgnoreMouseEvents = !enabled && !isLinuxHud, deduplicates via a ref, and forwards the value to electronAPI.setHudOverlayIgnoreMouseEvents.
Platform-aware test setup and Linux HUD test
src/components/launch/LaunchWindow.test.tsx
Hoists a platformState variable so getPlatform() returns a runtime-controlled value; beforeEach resets it to "darwin". Adds a new test that sets platformState.value to "linux" and asserts setHudOverlayIgnoreMouseEvents(false) is called, verifying the overlay stays interactive on Linux.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 On Linux I hopped, but couldn't drag my bar,
The mouse events ignored me — how bizarre!
A flag called isLinuxHud was born today,
shouldIgnoreMouseEvents now keeps the clicks at bay.
The recorder bar moves freely, hip hooray! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the primary change: keeping the HUD interactive on Linux so the drag handle receives pointer events.
Description check ✅ Passed The description is comprehensive, covering Problem, Root cause, Fix, Test, and Validation sections; all required template sections are either completed or appropriately filled.
Linked Issues check ✅ Passed The PR fully addresses issue #12 by enabling drag functionality on Linux via platform detection and conditional mouse event handling.
Out of Scope Changes check ✅ Passed All changes in LaunchWindow.tsx and LaunchWindow.test.tsx are directly scoped to fixing the Linux HUD drag handle issue; no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-linux-hud-drag

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@EtienneLescot EtienneLescot marked this pull request as ready for review June 22, 2026 09:18
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@EtienneLescot EtienneLescot merged commit 8246d07 into main Jun 22, 2026
11 checks passed
@EtienneLescot EtienneLescot deleted the codex/fix-linux-hud-drag branch June 22, 2026 09:26
@github-actions github-actions Bot mentioned this pull request Jun 22, 2026
1 task
EtienneLescot added a commit that referenced this pull request Jul 1, 2026
Bugs from the spine test pass:

#4 - clips display as 60s instead of the real video length. Root
cause: insertClipAt falls back to PLACEHOLDER_DURATION_SEC (60s) when
asset.durationSec is undefined, and the loadedmetadata auto-correct
(handleLoadedMetadata) didn't fire reliably (in the browser-shim the
preview path is unreliable; in the real Electron window the preview
<video> remounts only when the activeSource swaps, so a freshly-added
asset's metadata never reaches the auto-correct). Fix: probe the file
directly via a throwaway <video> (src/lib/ai-edition/timeline/duration.ts,
5 unit tests) and insert the clip at the real duration synchronously.
Persist the probed duration back onto the asset so subsequent inserts
don't re-probe. Falls back to PLACEHOLDER on probe failure.

#17 - dragging a skip's left/right chevron appeared to move the whole
skip instead of just one edge. Root cause: clipSegments() was called
once with the source skipRanges, then the cut segment was patched with
dragPreview.startSec/endSec - but the surrounding keep segments
weren't regenerated, so their flex widths didn't shrink to make room
and the cut's visual position drifted. Fix: build a virtual skipRanges
with the dragPreview'd bounds and re-run clipSegments() end-to-end so
keep+cut stay consistent.

#18 - clicking the trash button on a skip didn't remove it. Root cause:
startClipReorder calls setPointerCapture on the clip block, so the
subsequent pointerup is captured on the block (not the trash button)
and the click event fires on the block (not the button). Fix: stop
pointerdown propagation on the trash button so the clip block never
captures the pointer.

#5/#19 - clips were overlapping by 1px (the join-border overlap from
T09). User: this is NOT wanted for clips - only for skip strips
inside a clip. Fix: remove the JS left/width shift on hasJoinedPrev.
CSS .joinedPrev/.joinedNext still zero the adjacent border-radius +
border-width so corners blend.

#6 - the reorder marker wasn't visible. Root cause: z-index 11, but
the moving clip has z-index 20, and the marker's soft box-shadow was
only 8px so it disappeared against dark backgrounds. Fix: bump width
to 4px, z-index to 30 (above the moving clip), and stronger box-shadow.

Verified: tsc clean, biome clean, 412 tests pass.
EtienneLescot added a commit that referenced this pull request Jul 2, 2026
Bugs from the spine test pass:

#4 - clips display as 60s instead of the real video length. Root
cause: insertClipAt falls back to PLACEHOLDER_DURATION_SEC (60s) when
asset.durationSec is undefined, and the loadedmetadata auto-correct
(handleLoadedMetadata) didn't fire reliably (in the browser-shim the
preview path is unreliable; in the real Electron window the preview
<video> remounts only when the activeSource swaps, so a freshly-added
asset's metadata never reaches the auto-correct). Fix: probe the file
directly via a throwaway <video> (src/lib/ai-edition/timeline/duration.ts,
5 unit tests) and insert the clip at the real duration synchronously.
Persist the probed duration back onto the asset so subsequent inserts
don't re-probe. Falls back to PLACEHOLDER on probe failure.

#17 - dragging a skip's left/right chevron appeared to move the whole
skip instead of just one edge. Root cause: clipSegments() was called
once with the source skipRanges, then the cut segment was patched with
dragPreview.startSec/endSec - but the surrounding keep segments
weren't regenerated, so their flex widths didn't shrink to make room
and the cut's visual position drifted. Fix: build a virtual skipRanges
with the dragPreview'd bounds and re-run clipSegments() end-to-end so
keep+cut stay consistent.

#18 - clicking the trash button on a skip didn't remove it. Root cause:
startClipReorder calls setPointerCapture on the clip block, so the
subsequent pointerup is captured on the block (not the trash button)
and the click event fires on the block (not the button). Fix: stop
pointerdown propagation on the trash button so the clip block never
captures the pointer.

#5/#19 - clips were overlapping by 1px (the join-border overlap from
T09). User: this is NOT wanted for clips - only for skip strips
inside a clip. Fix: remove the JS left/width shift on hasJoinedPrev.
CSS .joinedPrev/.joinedNext still zero the adjacent border-radius +
border-width so corners blend.

#6 - the reorder marker wasn't visible. Root cause: z-index 11, but
the moving clip has z-index 20, and the marker's soft box-shadow was
only 8px so it disappeared against dark backgrounds. Fix: bump width
to 4px, z-index to 30 (above the moving clip), and stronger box-shadow.

Verified: tsc clean, biome clean, 412 tests pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Can't move the recorder bar

1 participant