mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-06-10 15:13:32 -07:00
fix(overlay): correct Hyprland fullscreen overlay alignment on Linux (#107)
This commit is contained in:
@@ -230,6 +230,7 @@ test('sendToActiveOverlayWindow targets modal window with full geometry and trac
|
||||
runtime.notifyOverlayModalOpened('runtime-options');
|
||||
assert.equal(window.getShowCount(), 1);
|
||||
assert.equal(window.isFocused(), true);
|
||||
assert.deepEqual(calls, ['bounds:10,20,300,200', 'bounds:10,20,300,200']);
|
||||
assert.deepEqual(window.alwaysOnTopCalls, ['top:true:screen-saver:3']);
|
||||
assert.deepEqual(window.sent, [['runtime-options:open']]);
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { WindowGeometry } from '../types';
|
||||
import { OVERLAY_WINDOW_CONTENT_READY_FLAG } from '../core/services/overlay-window-flags';
|
||||
|
||||
const MODAL_REVEAL_FALLBACK_DELAY_MS = 250;
|
||||
const MODAL_POST_SHOW_BOUNDS_RECONCILE_DELAY_MS = 50;
|
||||
|
||||
function requestOverlayApplicationFocus(): void {
|
||||
try {
|
||||
@@ -144,6 +145,24 @@ export function createOverlayModalRuntimeService(
|
||||
window.moveTop();
|
||||
};
|
||||
|
||||
const reconcileModalWindowBounds = (window: BrowserWindow): void => {
|
||||
const modalWindow = deps.getModalWindow();
|
||||
if (!modalWindow || modalWindow !== window || window.isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
deps.setModalWindowBounds(deps.getModalGeometry());
|
||||
};
|
||||
|
||||
const scheduleModalWindowBoundsReconcile = (window: BrowserWindow): void => {
|
||||
const timeout = setTimeout(() => {
|
||||
if (window.isDestroyed() || !window.isVisible()) {
|
||||
return;
|
||||
}
|
||||
reconcileModalWindowBounds(window);
|
||||
}, MODAL_POST_SHOW_BOUNDS_RECONCILE_DELAY_MS);
|
||||
timeout.unref?.();
|
||||
};
|
||||
|
||||
const sendOrQueueForWindow = (
|
||||
window: BrowserWindow,
|
||||
sendNow: (window: BrowserWindow) => void,
|
||||
@@ -187,6 +206,8 @@ export function createOverlayModalRuntimeService(
|
||||
if (!window.webContents.isFocused()) {
|
||||
window.webContents.focus();
|
||||
}
|
||||
reconcileModalWindowBounds(window);
|
||||
scheduleModalWindowBoundsReconcile(window);
|
||||
};
|
||||
|
||||
const ensureModalWindowInteractive = (window: BrowserWindow): void => {
|
||||
@@ -198,6 +219,8 @@ export function createOverlayModalRuntimeService(
|
||||
if (window.isVisible()) {
|
||||
window.focus();
|
||||
window.webContents.focus();
|
||||
reconcileModalWindowBounds(window);
|
||||
scheduleModalWindowBoundsReconcile(window);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,37 @@ test('live overlay bounds mismatch forces refresh after window manager restore d
|
||||
);
|
||||
});
|
||||
|
||||
test('live overlay bounds mismatch compares content bounds when compositor adds insets', () => {
|
||||
const geometry = { x: 0, y: 0, width: 3440, height: 1440 };
|
||||
|
||||
assert.equal(
|
||||
hasLiveOverlayWindowBoundsMismatch(
|
||||
[
|
||||
{
|
||||
isDestroyed: () => false,
|
||||
getBounds: () => ({ ...geometry }),
|
||||
getContentBounds: () => ({ x: 0, y: 14, width: 3440, height: 1426 }),
|
||||
},
|
||||
],
|
||||
geometry,
|
||||
),
|
||||
true,
|
||||
);
|
||||
assert.equal(
|
||||
hasLiveOverlayWindowBoundsMismatch(
|
||||
[
|
||||
{
|
||||
isDestroyed: () => false,
|
||||
getBounds: () => ({ x: 0, y: -14, width: 3440, height: 1454 }),
|
||||
getContentBounds: () => ({ ...geometry }),
|
||||
},
|
||||
],
|
||||
geometry,
|
||||
),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test('ensure overlay window level handler delegates to core', () => {
|
||||
const calls: string[] = [];
|
||||
const ensureLevel = createEnsureOverlayWindowLevelHandler({
|
||||
|
||||
@@ -3,12 +3,25 @@ import type { WindowGeometry } from '../../types';
|
||||
type OverlayBoundsWindow = {
|
||||
isDestroyed: () => boolean;
|
||||
getBounds: () => WindowGeometry;
|
||||
getContentBounds?: () => WindowGeometry;
|
||||
};
|
||||
|
||||
function sameGeometry(a: WindowGeometry | null | undefined, b: WindowGeometry): boolean {
|
||||
return a?.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
||||
}
|
||||
|
||||
function getWindowAlignmentBounds(window: OverlayBoundsWindow): WindowGeometry | null {
|
||||
try {
|
||||
return window.getContentBounds?.() ?? window.getBounds();
|
||||
} catch {
|
||||
try {
|
||||
return window.getBounds();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function hasLiveOverlayWindowBoundsMismatch(
|
||||
windows: Array<OverlayBoundsWindow | null | undefined>,
|
||||
geometry: WindowGeometry,
|
||||
@@ -17,7 +30,7 @@ export function hasLiveOverlayWindowBoundsMismatch(
|
||||
if (!window || window.isDestroyed()) {
|
||||
return false;
|
||||
}
|
||||
return !sameGeometry(window.getBounds(), geometry);
|
||||
return !sameGeometry(getWindowAlignmentBounds(window), geometry);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user