fix(launch): use live HUD bounds after drag

This commit is contained in:
wiiiii123
2026-04-21 02:54:00 +07:00
parent 316c11035c
commit fcccd1def6
3 changed files with 65 additions and 35 deletions
+20 -13
View File
@@ -41,7 +41,10 @@ import { ContentClamp } from "../ui/content-clamp";
import ProjectBrowserDialog, {
type ProjectLibraryEntry,
} from "../video-editor/ProjectBrowserDialog";
import { shouldRestoreHudMousePassthroughAfterDrag } from "./hudMousePassthrough";
import {
mergeHudInteractiveBounds,
shouldRestoreHudMousePassthroughAfterDrag,
} from "./hudMousePassthrough";
import styles from "./LaunchWindow.module.css";
interface DesktopSource {
@@ -466,21 +469,25 @@ export function LaunchWindow() {
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
event.currentTarget.releasePointerCapture(event.pointerId);
}
const hudBounds = hudContentRef.current?.getBoundingClientRect();
if (
wasDragging &&
shouldRestoreHudMousePassthroughAfterDrag(
hudBounds
const hudBounds = mergeHudInteractiveBounds(
[
dropdownRef.current?.getBoundingClientRect(),
hudBarRef.current?.getBoundingClientRect(),
recordingWebcamPreviewContainerRef.current?.getBoundingClientRect(),
].map((bounds) =>
bounds
? {
left: hudBounds.left,
top: hudBounds.top,
right: hudBounds.right,
bottom: hudBounds.bottom,
left: bounds.left,
top: bounds.top,
right: bounds.right,
bottom: bounds.bottom,
}
: null,
event.clientX,
event.clientY,
)
),
);
if (
wasDragging &&
shouldRestoreHudMousePassthroughAfterDrag(hudBounds, event.clientX, event.clientY)
) {
window.electronAPI?.hudOverlaySetIgnoreMouse?.(true);
}
@@ -1,36 +1,43 @@
import { describe, expect, it } from "vitest";
import { shouldRestoreHudMousePassthroughAfterDrag } from "./hudMousePassthrough";
import {
mergeHudInteractiveBounds,
shouldRestoreHudMousePassthroughAfterDrag,
} from "./hudMousePassthrough";
const hudBounds = { left: 100, top: 200, right: 300, bottom: 260 };
describe("mergeHudInteractiveBounds", () => {
it("returns null when there are no interactive bounds", () => {
expect(mergeHudInteractiveBounds([null, undefined])).toBeNull();
});
it("merges the dropdown, bar, and webcam preview bounds", () => {
expect(
mergeHudInteractiveBounds([
{ left: 120, top: 220, right: 260, bottom: 320 },
{ left: 100, top: 200, right: 300, bottom: 260 },
{ left: 140, top: 280, right: 340, bottom: 430 },
]),
).toEqual({ left: 100, top: 200, right: 340, bottom: 430 });
});
});
describe("shouldRestoreHudMousePassthroughAfterDrag", () => {
it("keeps the HUD interactive when the pointer is still inside the HUD", () => {
expect(
shouldRestoreHudMousePassthroughAfterDrag(
{ left: 100, top: 200, right: 300, bottom: 260 },
180,
230,
),
).toBe(false);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 180, 230)).toBe(false);
});
it("keeps the HUD interactive when the pointer ends on the HUD edge", () => {
expect(
shouldRestoreHudMousePassthroughAfterDrag(
{ left: 100, top: 200, right: 300, bottom: 260 },
300,
260,
),
).toBe(false);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 100, 200)).toBe(false);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 300, 260)).toBe(false);
});
it("restores passthrough when the pointer ends outside the HUD", () => {
expect(
shouldRestoreHudMousePassthroughAfterDrag(
{ left: 100, top: 200, right: 300, bottom: 260 },
301,
261,
),
).toBe(true);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 99, 230)).toBe(true);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 180, 199)).toBe(true);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 301, 230)).toBe(true);
expect(shouldRestoreHudMousePassthroughAfterDrag(hudBounds, 180, 261)).toBe(true);
});
it("restores passthrough when no HUD bounds are available", () => {
@@ -5,6 +5,22 @@ export interface HudInteractiveBounds {
bottom: number;
}
export function mergeHudInteractiveBounds(
bounds: Array<HudInteractiveBounds | null | undefined>,
): HudInteractiveBounds | null {
const presentBounds = bounds.filter((value): value is HudInteractiveBounds => Boolean(value));
if (presentBounds.length === 0) {
return null;
}
return presentBounds.reduce((merged, current) => ({
left: Math.min(merged.left, current.left),
top: Math.min(merged.top, current.top),
right: Math.max(merged.right, current.right),
bottom: Math.max(merged.bottom, current.bottom),
}));
}
export function shouldRestoreHudMousePassthroughAfterDrag(
bounds: HudInteractiveBounds | null,
clientX: number,