From 7308e37fc93fc1882f51f8346e54e8c6d4aefca9 Mon Sep 17 00:00:00 2001 From: sahilcodexx Date: Sat, 8 Aug 2026 17:27:05 +0530 Subject: [PATCH 1/3] fix(linux): resolve HUD overlay restricted width and popover clipping on Hyprland/Wayland --- electron/hudOverlayBounds.test.ts | 95 ++++--------------- electron/hudOverlayBounds.ts | 10 +- electron/windows.ts | 4 +- src/components/launch/LaunchWindow.module.css | 4 +- 4 files changed, 29 insertions(+), 84 deletions(-) diff --git a/electron/hudOverlayBounds.test.ts b/electron/hudOverlayBounds.test.ts index db21e92bd..a08def995 100644 --- a/electron/hudOverlayBounds.test.ts +++ b/electron/hudOverlayBounds.test.ts @@ -18,61 +18,21 @@ describe("getHudOverlayWindowBounds", () => { expect(getHudOverlayWindowBounds(workArea, true)).toEqual(workArea); }); - it("uses a bottom-centered compact fallback when mouse passthrough is unavailable", () => { - expect(getHudOverlayWindowBounds(workArea, false)).toEqual({ - x: 650, - y: 920, - width: 860, - height: 160, - }); + it("uses the full work area when mouse passthrough is supported", () => { + expect(getHudOverlayWindowBounds(workArea, true)).toEqual(workArea); }); - it("expands the non-passthrough fallback for HUD menus and hover interaction", () => { - expect(getHudOverlayWindowBounds(workArea, false, true)).toEqual({ - x: 650, - y: 540, - width: 860, - height: 540, - }); + it("uses full display work area bounds for the overlay window", () => { + expect(getHudOverlayWindowBounds(workArea, false)).toEqual(workArea); }); - it("keeps the compact fallback inside small displays", () => { - expect( - getHudOverlayWindowBounds( - { - x: -100, - y: 20, - width: 640, - height: 420, - }, - false, - ), - ).toEqual({ - x: -100, - y: 280, - width: 640, - height: 160, - }); + it("expands to full work area bounds", () => { + expect(getHudOverlayWindowBounds(workArea, false, true)).toEqual(workArea); }); - it("fits the expanded fallback inside small displays", () => { - expect( - getHudOverlayWindowBounds( - { - x: -100, - y: 20, - width: 640, - height: 420, - }, - false, - true, - ), - ).toEqual({ - x: -100, - y: 20, - width: 640, - height: 420, - }); + it("preserves full work area bounds inside small displays", () => { + const small = { x: -100, y: 20, width: 640, height: 420 }; + expect(getHudOverlayWindowBounds(small, false)).toEqual(small); }); }); @@ -84,64 +44,49 @@ describe("resizeHudOverlayFallbackBounds", () => { height: 1080, }; - it("preserves the dragged bottom edge when expanding", () => { + it("returns full work area when expanding", () => { expect( resizeHudOverlayFallbackBounds( workArea, { x: 420, y: 700, - width: 860, + width: 1200, height: 160, }, true, ), - ).toEqual({ - x: 420, - y: 320, - width: 860, - height: 540, - }); + ).toEqual(workArea); }); - it("preserves the dragged bottom edge when compacting", () => { + it("returns full work area when compacting", () => { expect( resizeHudOverlayFallbackBounds( workArea, { x: 420, - y: 320, - width: 860, - height: 540, + y: 260, + width: 1200, + height: 600, }, false, ), - ).toEqual({ - x: 420, - y: 700, - width: 860, - height: 160, - }); + ).toEqual(workArea); }); - it("keeps resized fallback bounds inside the display work area", () => { + it("returns full work area inside the display work area", () => { expect( resizeHudOverlayFallbackBounds( workArea, { x: 1500, y: 900, - width: 860, + width: 1200, height: 160, }, true, ), - ).toEqual({ - x: 1060, - y: 520, - width: 860, - height: 540, - }); + ).toEqual(workArea); }); }); diff --git a/electron/hudOverlayBounds.ts b/electron/hudOverlayBounds.ts index 8c51b88c7..7aba77f40 100644 --- a/electron/hudOverlayBounds.ts +++ b/electron/hudOverlayBounds.ts @@ -5,9 +5,9 @@ export interface HudOverlayWorkArea { height: number; } -const NON_PASSTHROUGH_HUD_WIDTH_DIP = 860; +const NON_PASSTHROUGH_HUD_WIDTH_DIP = 1200; const NON_PASSTHROUGH_HUD_COMPACT_HEIGHT_DIP = 160; -const NON_PASSTHROUGH_HUD_EXPANDED_HEIGHT_DIP = 540; +const NON_PASSTHROUGH_HUD_EXPANDED_HEIGHT_DIP = 600; function clamp(value: number, min: number, max: number): number { return Math.min(Math.max(value, min), max); @@ -18,7 +18,7 @@ export function getHudOverlayWindowBounds( mousePassthroughSupported: boolean, fallbackExpanded = false, ): HudOverlayWorkArea { - if (mousePassthroughSupported) { + if (mousePassthroughSupported || process.platform === "linux") { return { ...workArea }; } @@ -55,6 +55,10 @@ export function resizeHudOverlayFallbackBounds( currentBounds: HudOverlayWorkArea, fallbackExpanded: boolean, ): HudOverlayWorkArea { + if (process.platform === "linux") { + return { ...workArea }; + } + const nextBounds = getHudOverlayWindowBounds(workArea, false, fallbackExpanded); const maxX = workArea.x + workArea.width - nextBounds.width; const maxY = workArea.y + workArea.height - nextBounds.height; diff --git a/electron/windows.ts b/electron/windows.ts index 55f6314cd..16519d7b6 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -311,9 +311,7 @@ function setHudOverlayMousePassthrough(ignore: boolean) { } if (!isHudOverlayMousePassthroughSupported()) { - if (process.platform !== "linux") { - setHudOverlayFallbackExpanded(!ignore); - } + setHudOverlayFallbackExpanded(!ignore); hudOverlayWindow.setIgnoreMouseEvents(false); return; } diff --git a/src/components/launch/LaunchWindow.module.css b/src/components/launch/LaunchWindow.module.css index 3638e7563..0685782a0 100644 --- a/src/components/launch/LaunchWindow.module.css +++ b/src/components/launch/LaunchWindow.module.css @@ -11,7 +11,7 @@ align-items: center; gap: 10px; width: max-content; - max-width: 1200px; + max-width: 100%; background: var(--launch-bar-bg); border: 1px solid var(--launch-bar-border); border-radius: 20px; @@ -95,8 +95,6 @@ color: #4eeeb0; } - - .menuCard { width: 300px; max-height: 400px; From 594cee17aa7058caa7ca970b205e077831694235 Mon Sep 17 00:00:00 2001 From: sahilcodexx Date: Sat, 8 Aug 2026 20:39:38 +0530 Subject: [PATCH 2/3] test(electron): make HUD overlay bounds expectations platform-specific --- electron/hudOverlayBounds.test.ts | 119 ++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 14 deletions(-) diff --git a/electron/hudOverlayBounds.test.ts b/electron/hudOverlayBounds.test.ts index a08def995..89f6a38ef 100644 --- a/electron/hudOverlayBounds.test.ts +++ b/electron/hudOverlayBounds.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from "vitest"; +import { afterEach, describe, expect, it, vi } from "vitest"; import { getHudOverlayWindowBounds, @@ -14,25 +14,78 @@ describe("getHudOverlayWindowBounds", () => { height: 1040, }; - it("uses the full work area when mouse passthrough is supported", () => { - expect(getHudOverlayWindowBounds(workArea, true)).toEqual(workArea); + afterEach(() => { + vi.restoreAllMocks(); }); it("uses the full work area when mouse passthrough is supported", () => { expect(getHudOverlayWindowBounds(workArea, true)).toEqual(workArea); }); - it("uses full display work area bounds for the overlay window", () => { + it("uses full display work area bounds on Linux when mouse passthrough is false", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("linux"); expect(getHudOverlayWindowBounds(workArea, false)).toEqual(workArea); }); - it("expands to full work area bounds", () => { - expect(getHudOverlayWindowBounds(workArea, false, true)).toEqual(workArea); + it("uses a bottom-centered compact fallback on non-Linux when mouse passthrough is unavailable", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + expect(getHudOverlayWindowBounds(workArea, false)).toEqual({ + x: 480, + y: 920, + width: 1200, + height: 160, + }); }); - it("preserves full work area bounds inside small displays", () => { - const small = { x: -100, y: 20, width: 640, height: 420 }; - expect(getHudOverlayWindowBounds(small, false)).toEqual(small); + it("expands the non-Linux fallback for HUD menus and hover interaction", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + expect(getHudOverlayWindowBounds(workArea, false, true)).toEqual({ + x: 480, + y: 480, + width: 1200, + height: 600, + }); + }); + + it("keeps the non-Linux compact fallback inside small displays", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + expect( + getHudOverlayWindowBounds( + { + x: -100, + y: 20, + width: 640, + height: 420, + }, + false, + ), + ).toEqual({ + x: -100, + y: 280, + width: 640, + height: 160, + }); + }); + + it("fits the non-Linux expanded fallback inside small displays", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + expect( + getHudOverlayWindowBounds( + { + x: -100, + y: 20, + width: 640, + height: 420, + }, + false, + true, + ), + ).toEqual({ + x: -100, + y: 20, + width: 640, + height: 420, + }); }); }); @@ -44,7 +97,12 @@ describe("resizeHudOverlayFallbackBounds", () => { height: 1080, }; - it("returns full work area when expanding", () => { + afterEach(() => { + vi.restoreAllMocks(); + }); + + it("returns full work area on Linux", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("linux"); expect( resizeHudOverlayFallbackBounds( workArea, @@ -59,7 +117,29 @@ describe("resizeHudOverlayFallbackBounds", () => { ).toEqual(workArea); }); - it("returns full work area when compacting", () => { + it("preserves the dragged bottom edge on non-Linux when expanding", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + expect( + resizeHudOverlayFallbackBounds( + workArea, + { + x: 420, + y: 700, + width: 1200, + height: 160, + }, + true, + ), + ).toEqual({ + x: 420, + y: 260, + width: 1200, + height: 600, + }); + }); + + it("preserves the dragged bottom edge on non-Linux when compacting", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); expect( resizeHudOverlayFallbackBounds( workArea, @@ -71,10 +151,16 @@ describe("resizeHudOverlayFallbackBounds", () => { }, false, ), - ).toEqual(workArea); + ).toEqual({ + x: 420, + y: 700, + width: 1200, + height: 160, + }); }); - it("returns full work area inside the display work area", () => { + it("keeps resized fallback bounds inside display work area on non-Linux", () => { + vi.spyOn(process, "platform", "get").mockReturnValue("win32"); expect( resizeHudOverlayFallbackBounds( workArea, @@ -86,7 +172,12 @@ describe("resizeHudOverlayFallbackBounds", () => { }, true, ), - ).toEqual(workArea); + ).toEqual({ + x: 720, + y: 460, + width: 1200, + height: 600, + }); }); }); From 8fdee920045ab5526b1919a558e3c2d87cdd4898 Mon Sep 17 00:00:00 2001 From: sahilcodexx Date: Sat, 8 Aug 2026 20:46:56 +0530 Subject: [PATCH 3/3] test(electron): replace process.platform getter spy with data-property override helper --- electron/hudOverlayBounds.test.ts | 34 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/electron/hudOverlayBounds.test.ts b/electron/hudOverlayBounds.test.ts index 89f6a38ef..b96450d8a 100644 --- a/electron/hudOverlayBounds.test.ts +++ b/electron/hudOverlayBounds.test.ts @@ -1,4 +1,4 @@ -import { afterEach, describe, expect, it, vi } from "vitest"; +import { afterEach, describe, expect, it } from "vitest"; import { getHudOverlayWindowBounds, @@ -6,6 +6,16 @@ import { shouldExpandHudOverlayFallback, } from "./hudOverlayBounds"; +const ORIGINAL_PLATFORM = process.platform; + +function setPlatform(platform: NodeJS.Platform) { + Object.defineProperty(process, "platform", { + value: platform, + configurable: true, + writable: true, + }); +} + describe("getHudOverlayWindowBounds", () => { const workArea = { x: 120, @@ -15,7 +25,7 @@ describe("getHudOverlayWindowBounds", () => { }; afterEach(() => { - vi.restoreAllMocks(); + setPlatform(ORIGINAL_PLATFORM); }); it("uses the full work area when mouse passthrough is supported", () => { @@ -23,12 +33,12 @@ describe("getHudOverlayWindowBounds", () => { }); it("uses full display work area bounds on Linux when mouse passthrough is false", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("linux"); + setPlatform("linux"); expect(getHudOverlayWindowBounds(workArea, false)).toEqual(workArea); }); it("uses a bottom-centered compact fallback on non-Linux when mouse passthrough is unavailable", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect(getHudOverlayWindowBounds(workArea, false)).toEqual({ x: 480, y: 920, @@ -38,7 +48,7 @@ describe("getHudOverlayWindowBounds", () => { }); it("expands the non-Linux fallback for HUD menus and hover interaction", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect(getHudOverlayWindowBounds(workArea, false, true)).toEqual({ x: 480, y: 480, @@ -48,7 +58,7 @@ describe("getHudOverlayWindowBounds", () => { }); it("keeps the non-Linux compact fallback inside small displays", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect( getHudOverlayWindowBounds( { @@ -68,7 +78,7 @@ describe("getHudOverlayWindowBounds", () => { }); it("fits the non-Linux expanded fallback inside small displays", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect( getHudOverlayWindowBounds( { @@ -98,11 +108,11 @@ describe("resizeHudOverlayFallbackBounds", () => { }; afterEach(() => { - vi.restoreAllMocks(); + setPlatform(ORIGINAL_PLATFORM); }); it("returns full work area on Linux", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("linux"); + setPlatform("linux"); expect( resizeHudOverlayFallbackBounds( workArea, @@ -118,7 +128,7 @@ describe("resizeHudOverlayFallbackBounds", () => { }); it("preserves the dragged bottom edge on non-Linux when expanding", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect( resizeHudOverlayFallbackBounds( workArea, @@ -139,7 +149,7 @@ describe("resizeHudOverlayFallbackBounds", () => { }); it("preserves the dragged bottom edge on non-Linux when compacting", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect( resizeHudOverlayFallbackBounds( workArea, @@ -160,7 +170,7 @@ describe("resizeHudOverlayFallbackBounds", () => { }); it("keeps resized fallback bounds inside display work area on non-Linux", () => { - vi.spyOn(process, "platform", "get").mockReturnValue("win32"); + setPlatform("win32"); expect( resizeHudOverlayFallbackBounds( workArea,