Skip to content

fix(hud): preserve user-dragged position across recording state changes#224

Merged
webadderall merged 3 commits intowebadderall:mainfrom
afostr:feature/preserve-hud-position
Apr 13, 2026
Merged

fix(hud): preserve user-dragged position across recording state changes#224
webadderall merged 3 commits intowebadderall:mainfrom
afostr:feature/preserve-hud-position

Conversation

@afostr
Copy link
Copy Markdown
Contributor

@afostr afostr commented Apr 11, 2026

Pull Request Template

Description

This preserves the location of the recording hud bar when recording starts.
Without this the recording start state change snaps the bar back to the same spot, and this can be in the way of your recording.

Motivation

This solves a minor UX issue where the hud bar snaps back to a center location as the recording starts. I had tried a work around where I would use the timer delay start and clear the bar out of the way during the countdown, but as soon as the countdown finishes it snaps back on top of the app I need to record.
Of course, I can just drag it a way but that disrupts the flow/concentration of the task at hand.

Type of Change

  • Other (please specify). Minor UX improvement

Related Issue(s)

none found

Screenshots / Video

none

Video (wherever possible):

<video src="path/to/video.mp4" controls width="600"></video>

Testing Guide

I tested this by building and running the app.
I would then start a recording and observe that the location of the hud bar does not snap back to the center location as the video starts.

Checklist

  • I have performed a self-review of my code.
  • NA,IMO I have added any necessary screenshots or videos.
  • I have linked related issue(s) and updated the changelog if applicable.
    (I skimmed issue list after and didn't see them)
    (didn't touch release log)

Thank you for contributing!

Summary by CodeRabbit

  • Improvements
    • HUD window now remembers the last position you dragged it to and preserves that custom position during resizing and bounds adjustments.
    • Window placement is clamped to the current display work area so the HUD remains fully visible.
    • Display changes (removal or metric changes) automatically clear or revalidate the saved HUD position to keep it on-screen.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
Validation error: Invalid regex pattern for base branch. Received: "*" at "reviews.auto_review.base_branches[0]"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

applyHudOverlayBounds() now preserves a user-saved HUD window position (hudUserPosition), clamps resized bounds to the active display work area, and registers screen listeners to clear or revalidate the saved position on display changes; listeners are removed when the HUD window closes.

Changes

Cohort / File(s) Summary
HUD Position & Display Handling
electron/windows.ts
Introduce module-level hudUserPosition; capture final {x,y} on "hud-overlay-drag" "end"; apply clamped user position in applyHudOverlayBounds() when present; add screen listeners (display-removed, display-metrics-changed) to clear/validate position and reapply bounds; remove listeners on HUD "closed".

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant HUD as HUDOverlayWindow
    participant Main as electron/windows.ts
    participant Screen as Screen API
    participant Display as DisplayWorkArea

    User->>HUD: drag HUD (move)
    HUD->>Main: emit "hud-overlay-drag" (end) with bounds
    Main->>Main: set hudUserPosition = {x,y}
    Main->>Main: call applyHudOverlayBounds()
    Main->>Display: query current workArea
    Display-->>Main: workArea
    Main->>Main: clamp hudUserPosition to workArea, set window bounds

    Screen->>Main: "display-metrics-changed" / "display-removed"
    Main->>Main: validate hudUserPosition against displays
    alt position invalid
        Main->>Main: clear hudUserPosition and reapply default bounds
    end
    HUD->>Main: "closed"
    Main->>Screen: remove listeners
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰
I nudged my HUD with gentle paws,
Saved the spot without a pause.
If screens move or pixels roam,
I check the bounds and bring it home. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: preserving the user-dragged HUD position during recording state transitions, directly addressing the core problem solved by this PR.
Description check ✅ Passed The PR description covers all major template sections including purpose, motivation, type of change, testing guide, and checklist items are completed.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
electron/windows.ts (1)

505-526: Consider removing screen event listeners in the HUD window closed handler as a defensive best practice.

The current code registers screen.on("display-removed") and screen.on("display-metrics-changed") listeners in createHudOverlayWindow() but never removes them. While the HUD window is only created once at app startup and never recreated, proper cleanup prevents future regressions if the window creation logic changes. Suggested approach: extract the handlers to named functions and remove them when the window closes.

Suggested fix
 	const screen = getScreen();
-	screen.on("display-removed", () => {
+	const handleDisplayRemoved = () => {
 		hudUserPosition = null;
-	});
-	screen.on("display-metrics-changed", () => {
+	};
+	const handleDisplayMetricsChanged = () => {
 		if (hudUserPosition) {
 			const displays = screen.getAllDisplays();
 			const onScreen = displays.some(
 				(d) =>
 					hudUserPosition!.x >= d.workArea.x &&
 					hudUserPosition!.x < d.workArea.x + d.workArea.width &&
 					hudUserPosition!.y >= d.workArea.y &&
 					hudUserPosition!.y < d.workArea.y + d.workArea.height,
 			);
 			if (!onScreen) {
 				hudUserPosition = null;
 				applyHudOverlayBounds(hudOverlayExpanded);
 			}
 		}
-	});
+	};
+	screen.on("display-removed", handleDisplayRemoved);
+	screen.on("display-metrics-changed", handleDisplayMetricsChanged);
 	win.on("closed", () => {
+		screen.removeListener("display-removed", handleDisplayRemoved);
+		screen.removeListener("display-metrics-changed", handleDisplayMetricsChanged);
 		if (hudOverlayWindow === win) {
 			hudOverlayWindow = null;
 		}
 	});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@electron/windows.ts` around lines 505 - 526, The screen event listeners
registered via getScreen().on("display-removed", ...) and
getScreen().on("display-metrics-changed", ...) leak because they are added
inside createHudOverlayWindow() and never removed; extract the anonymous
callbacks into named functions (e.g., handleDisplayRemoved and
handleDisplayMetricsChanged) that reference hudUserPosition and call
applyHudOverlayBounds(hudOverlayExpanded) as needed, register those named
handlers with screen.on(...) when creating the HUD, and remove them with
screen.removeListener("display-removed", handleDisplayRemoved) and
screen.removeListener("display-metrics-changed", handleDisplayMetricsChanged)
from the HUD window's 'closed' (or 'close') handler to ensure proper cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@electron/windows.ts`:
- Around line 511-524: The handler for screen.on("display-metrics-changed") only
calls applyHudOverlayBounds(hudOverlayExpanded) when hudUserPosition is null
after an on-screen check, which misses cases where the saved point remains
inside but the window now overflows; always invoke
applyHudOverlayBounds(hudOverlayExpanded) at the end of the
display-metrics-changed callback (regardless of hudUserPosition/onScreen) so the
HUD is re-clamped to the current work area, keeping hudUserPosition updates and
the existing onScreen check intact.

---

Nitpick comments:
In `@electron/windows.ts`:
- Around line 505-526: The screen event listeners registered via
getScreen().on("display-removed", ...) and
getScreen().on("display-metrics-changed", ...) leak because they are added
inside createHudOverlayWindow() and never removed; extract the anonymous
callbacks into named functions (e.g., handleDisplayRemoved and
handleDisplayMetricsChanged) that reference hudUserPosition and call
applyHudOverlayBounds(hudOverlayExpanded) as needed, register those named
handlers with screen.on(...) when creating the HUD, and remove them with
screen.removeListener("display-removed", handleDisplayRemoved) and
screen.removeListener("display-metrics-changed", handleDisplayMetricsChanged)
from the HUD window's 'closed' (or 'close') handler to ensure proper cleanup.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1df19e08-f237-4c31-ad6a-dbeb7eee8dac

📥 Commits

Reviewing files that changed from the base of the PR and between d6f1225 and c7be601.

📒 Files selected for processing (1)
  • electron/windows.ts

afostr added 3 commits April 11, 2026 12:10
The HUD overlay snaps back to the centered default position whenever
recording starts because the idle-to-recording UI swap triggers a
resize, and applyHudOverlayBounds() always recomputes a centered
location. This is disruptive when the user has intentionally moved
the bar out of the way before a timed recording.

Remember the position after a drag ends and reuse it for subsequent
bounds updates, clamped to the current work area. The position resets
on app restart or when displays change so the bar cannot get stranded
off-screen.
@afostr afostr force-pushed the feature/preserve-hud-position branch from c7be601 to dc39031 Compare April 11, 2026 17:14
@webadderall webadderall merged commit 8f50cc1 into webadderall:main Apr 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants