Improve startup dictionary progress and fix overlay/plugin input handlin

- show a dedicated startup OSD "building" phase for character dictionary sync
- forward bare `Tab` from visible overlay to mpv so AniSkip works while focused
- fix Windows plugin env override resolution for `SUBMINER_BINARY_PATH`
This commit is contained in:
2026-03-09 02:35:03 -07:00
parent e0f82d28f0
commit e59192bbe1
28 changed files with 577 additions and 104 deletions

View File

@@ -3,6 +3,10 @@ import * as path from 'path';
import { WindowGeometry } from '../../types';
import { createLogger } from '../../logger';
import { IPC_CHANNELS } from '../../shared/ipc/contracts';
import {
handleOverlayWindowBeforeInputEvent,
type OverlayWindowKind,
} from './overlay-window-input';
const logger = createLogger('main:overlay-window');
const overlayWindowLayerByInstance = new WeakMap<BrowserWindow, OverlayWindowKind>();
@@ -23,26 +27,6 @@ function loadOverlayWindowLayer(window: BrowserWindow, layer: OverlayWindowKind)
});
}
export type OverlayWindowKind = 'visible' | 'modal';
function isLookupWindowToggleInput(input: Electron.Input): boolean {
if (input.type !== 'keyDown') return false;
if (input.alt) return false;
if (!input.control && !input.meta) return false;
if (input.shift) return false;
const normalizedKey = typeof input.key === 'string' ? input.key.toLowerCase() : '';
return input.code === 'KeyY' || normalizedKey === 'y';
}
function isKeyboardModeToggleInput(input: Electron.Input): boolean {
if (input.type !== 'keyDown') return false;
if (input.alt) return false;
if (!input.control && !input.meta) return false;
if (!input.shift) return false;
const normalizedKey = typeof input.key === 'string' ? input.key.toLowerCase() : '';
return input.code === 'KeyY' || normalizedKey === 'y';
}
export function updateOverlayWindowBounds(
geometry: WindowGeometry,
window: BrowserWindow | null,
@@ -92,6 +76,7 @@ export function createOverlayWindow(
setOverlayDebugVisualizationEnabled: (enabled: boolean) => void;
isOverlayVisible: (kind: OverlayWindowKind) => boolean;
tryHandleOverlayShortcutLocalFallback: (input: Electron.Input) => boolean;
forwardTabToMpv: () => void;
onWindowClosed: (kind: OverlayWindowKind) => void;
},
): BrowserWindow {
@@ -142,20 +127,19 @@ export function createOverlayWindow(
}
window.webContents.on('before-input-event', (event, input) => {
if (kind === 'modal') return;
if (!window.isVisible()) return;
if (isKeyboardModeToggleInput(input)) {
event.preventDefault();
window.webContents.send(IPC_CHANNELS.event.keyboardModeToggleRequested);
return;
}
if (isLookupWindowToggleInput(input)) {
event.preventDefault();
window.webContents.send(IPC_CHANNELS.event.lookupWindowToggleRequested);
return;
}
if (!options.tryHandleOverlayShortcutLocalFallback(input)) return;
event.preventDefault();
handleOverlayWindowBeforeInputEvent({
kind,
windowVisible: window.isVisible(),
input,
preventDefault: () => event.preventDefault(),
sendKeyboardModeToggleRequested: () =>
window.webContents.send(IPC_CHANNELS.event.keyboardModeToggleRequested),
sendLookupWindowToggleRequested: () =>
window.webContents.send(IPC_CHANNELS.event.lookupWindowToggleRequested),
tryHandleOverlayShortcutLocalFallback: (nextInput) =>
options.tryHandleOverlayShortcutLocalFallback(nextInput),
forwardTabToMpv: () => options.forwardTabToMpv(),
});
});
window.hide();
@@ -185,3 +169,5 @@ export function syncOverlayWindowLayer(window: BrowserWindow, layer: 'visible'):
if (overlayWindowLayerByInstance.get(window) === layer) return;
loadOverlayWindowLayer(window, layer);
}
export type { OverlayWindowKind } from './overlay-window-input';