Fix Windows overlay tracking, z-order, and startup visibility

- switch Windows overlay tracking to native win32 polling with native owner and z-order helpers
- keep the visible overlay and stats overlay aligned across focus handoff, transient tracker misses, and minimize/restore cycles
- start the visible overlay click-through and hide the initial opaque startup frame until the tracked transparent state settles
- add a backlog task for the inconsistent mpv y-t overlay toggle after menu toggles
This commit is contained in:
2026-04-10 01:00:53 -07:00
parent ac25213255
commit 7698258f61
35 changed files with 2658 additions and 230 deletions

View File

@@ -13,6 +13,17 @@ import { normalizeOverlayWindowBoundsForPlatform } from './overlay-window-bounds
const logger = createLogger('main:overlay-window');
const overlayWindowLayerByInstance = new WeakMap<BrowserWindow, OverlayWindowKind>();
const overlayWindowContentReady = new WeakSet<BrowserWindow>();
const OVERLAY_WINDOW_CONTENT_READY_FLAG = '__subminerOverlayContentReady';
export function isOverlayWindowContentReady(window: BrowserWindow): boolean {
return (
overlayWindowContentReady.has(window) ||
(window as BrowserWindow & { [OVERLAY_WINDOW_CONTENT_READY_FLAG]?: boolean })[
OVERLAY_WINDOW_CONTENT_READY_FLAG
] === true
);
}
function getOverlayWindowHtmlPath(): string {
return path.join(__dirname, '..', '..', 'renderer', 'index.html');
@@ -76,13 +87,17 @@ export function createOverlayWindow(
isOverlayVisible: (kind: OverlayWindowKind) => boolean;
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void;
onVisibleWindowBlurred?: () => void;
onWindowContentReady?: () => void;
onWindowClosed: (kind: OverlayWindowKind) => void;
yomitanSession?: Session | null;
},
): BrowserWindow {
const window = new BrowserWindow(buildOverlayWindowOptions(kind, options));
options.ensureOverlayWindowLevel(window);
if (!(process.platform === 'win32' && kind === 'visible')) {
options.ensureOverlayWindowLevel(window);
}
loadOverlayWindowLayer(window, kind);
window.webContents.on('did-fail-load', (_event, errorCode, errorDescription, validatedURL) => {
@@ -93,6 +108,14 @@ export function createOverlayWindow(
options.onRuntimeOptionsChanged();
});
window.once('ready-to-show', () => {
overlayWindowContentReady.add(window);
(window as BrowserWindow & { [OVERLAY_WINDOW_CONTENT_READY_FLAG]?: boolean })[
OVERLAY_WINDOW_CONTENT_READY_FLAG
] = true;
options.onWindowContentReady?.();
});
if (kind === 'visible') {
window.webContents.on('devtools-opened', () => {
options.setOverlayDebugVisualizationEnabled(true);
@@ -136,6 +159,8 @@ export function createOverlayWindow(
moveWindowTop: () => {
window.moveTop();
},
onWindowsVisibleOverlayBlur:
kind === 'visible' ? () => options.onVisibleWindowBlurred?.() : undefined,
});
});