mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-05-04 00:41:33 -07:00
Windows update (#49)
This commit is contained in:
@@ -1,32 +1,80 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { OVERLAY_WINDOW_CONTENT_READY_FLAG } from './overlay-window-flags';
|
||||
import { setVisibleOverlayVisible, updateVisibleOverlayVisibility } from './overlay-visibility';
|
||||
|
||||
type WindowTrackerStub = {
|
||||
isTracking: () => boolean;
|
||||
getGeometry: () => { x: number; y: number; width: number; height: number } | null;
|
||||
isTargetWindowFocused?: () => boolean;
|
||||
isTargetWindowMinimized?: () => boolean;
|
||||
};
|
||||
|
||||
function createMainWindowRecorder() {
|
||||
const calls: string[] = [];
|
||||
let visible = false;
|
||||
let focused = false;
|
||||
let opacity = 1;
|
||||
let contentReady = true;
|
||||
const window = {
|
||||
webContents: {},
|
||||
isDestroyed: () => false,
|
||||
isVisible: () => visible,
|
||||
isFocused: () => focused,
|
||||
hide: () => {
|
||||
visible = false;
|
||||
focused = false;
|
||||
calls.push('hide');
|
||||
},
|
||||
show: () => {
|
||||
visible = true;
|
||||
calls.push('show');
|
||||
},
|
||||
showInactive: () => {
|
||||
visible = true;
|
||||
calls.push('show-inactive');
|
||||
},
|
||||
focus: () => {
|
||||
focused = true;
|
||||
calls.push('focus');
|
||||
},
|
||||
setAlwaysOnTop: (flag: boolean) => {
|
||||
calls.push(`always-on-top:${flag}`);
|
||||
},
|
||||
setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) => {
|
||||
calls.push(`mouse-ignore:${ignore}:${options?.forward === true ? 'forward' : 'plain'}`);
|
||||
},
|
||||
setOpacity: (nextOpacity: number) => {
|
||||
opacity = nextOpacity;
|
||||
calls.push(`opacity:${nextOpacity}`);
|
||||
},
|
||||
moveTop: () => {
|
||||
calls.push('move-top');
|
||||
},
|
||||
};
|
||||
(
|
||||
window as {
|
||||
[OVERLAY_WINDOW_CONTENT_READY_FLAG]?: boolean;
|
||||
}
|
||||
)[OVERLAY_WINDOW_CONTENT_READY_FLAG] = contentReady;
|
||||
|
||||
return { window, calls };
|
||||
return {
|
||||
window,
|
||||
calls,
|
||||
getOpacity: () => opacity,
|
||||
setContentReady: (nextContentReady: boolean) => {
|
||||
contentReady = nextContentReady;
|
||||
(
|
||||
window as {
|
||||
[OVERLAY_WINDOW_CONTENT_READY_FLAG]?: boolean;
|
||||
}
|
||||
)[OVERLAY_WINDOW_CONTENT_READY_FLAG] = contentReady;
|
||||
},
|
||||
setFocused: (nextFocused: boolean) => {
|
||||
focused = nextFocused;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test('macOS keeps visible overlay hidden while tracker is not ready and emits one loading OSD', () => {
|
||||
@@ -163,7 +211,334 @@ test('untracked non-macOS overlay keeps fallback visible behavior when no tracke
|
||||
assert.ok(!calls.includes('osd'));
|
||||
});
|
||||
|
||||
test('Windows visible overlay stays click-through and does not steal focus while tracked', () => {
|
||||
test('Windows visible overlay stays click-through and binds to mpv while tracked', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('opacity:0'));
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('show-inactive'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(!calls.includes('enforce-order'));
|
||||
assert.ok(!calls.includes('focus'));
|
||||
});
|
||||
|
||||
test('Windows visible overlay restores opacity after the deferred reveal delay', async () => {
|
||||
const { window, calls, getOpacity } = createMainWindowRecorder();
|
||||
let syncWindowsZOrderCalls = 0;
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
syncWindowsZOrderCalls += 1;
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.equal(getOpacity(), 0);
|
||||
assert.equal(syncWindowsZOrderCalls, 1);
|
||||
await new Promise<void>((resolve) => setTimeout(resolve, 60));
|
||||
assert.equal(getOpacity(), 1);
|
||||
assert.equal(syncWindowsZOrderCalls, 2);
|
||||
assert.ok(calls.includes('opacity:1'));
|
||||
});
|
||||
|
||||
test('Windows visible overlay waits for content-ready before first reveal', () => {
|
||||
const { window, calls, setContentReady } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
};
|
||||
setContentReady(false);
|
||||
|
||||
const run = () =>
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
run();
|
||||
|
||||
assert.ok(!calls.includes('show-inactive'));
|
||||
assert.ok(!calls.includes('show'));
|
||||
|
||||
setContentReady(true);
|
||||
run();
|
||||
|
||||
assert.ok(calls.includes('show-inactive'));
|
||||
});
|
||||
|
||||
test('tracked Windows overlay refresh rebinds while already visible', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(!calls.includes('show'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(calls.includes('sync-shortcuts'));
|
||||
});
|
||||
|
||||
test('forced passthrough still reapplies while visible on Windows', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
forceMousePassthrough: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(!calls.includes('always-on-top:false'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(!calls.includes('enforce-order'));
|
||||
});
|
||||
|
||||
test('forced passthrough still shows tracked overlay while bound to mpv on Windows', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
forceMousePassthrough: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('show-inactive'));
|
||||
assert.ok(!calls.includes('always-on-top:false'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
});
|
||||
|
||||
test('forced mouse passthrough drops macOS tracked overlay below higher-priority windows', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
@@ -191,13 +566,283 @@ test('Windows visible overlay stays click-through and does not steal focus while
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: true,
|
||||
isWindowsPlatform: false,
|
||||
forceMousePassthrough: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('always-on-top:false'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(!calls.includes('enforce-order'));
|
||||
});
|
||||
|
||||
test('tracked Windows overlay rebinds without hiding when tracker focus changes', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
let focused = true;
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
isTargetWindowFocused: () => focused,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
focused = false;
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(!calls.includes('always-on-top:false'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(!calls.includes('enforce-order'));
|
||||
assert.ok(!calls.includes('show'));
|
||||
});
|
||||
|
||||
test('tracked Windows overlay stays interactive while the overlay window itself is focused', () => {
|
||||
const { window, calls, setFocused } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
isTargetWindowFocused: () => false,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
setFocused(true);
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('mouse-ignore:false:plain'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(!calls.includes('enforce-order'));
|
||||
});
|
||||
|
||||
test('tracked Windows overlay reshows click-through even if focus state is stale after a modal closes', () => {
|
||||
const { window, calls, setFocused } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
isTargetWindowFocused: () => false,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
window.hide();
|
||||
calls.length = 0;
|
||||
setFocused(true);
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('show'));
|
||||
assert.ok(!calls.includes('focus'));
|
||||
assert.ok(calls.includes('show-inactive'));
|
||||
assert.ok(!calls.includes('show'));
|
||||
});
|
||||
|
||||
test('tracked Windows overlay binds above mpv even when tracker focus lags', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => true,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
isTargetWindowFocused: () => false,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(!calls.includes('always-on-top:false'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
});
|
||||
|
||||
test('visible overlay stays hidden while a modal window is active', () => {
|
||||
@@ -355,6 +1000,157 @@ test('Windows keeps visible overlay hidden while tracker is not ready', () => {
|
||||
assert.ok(!calls.includes('update-bounds'));
|
||||
});
|
||||
|
||||
test('Windows preserves visible overlay and rebinds to mpv while tracker transiently loses a non-minimized window', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
let tracking = true;
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => tracking,
|
||||
getGeometry: () => ({ x: 0, y: 0, width: 1280, height: 720 }),
|
||||
isTargetWindowFocused: () => false,
|
||||
isTargetWindowMinimized: () => false,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
tracking = false;
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(!calls.includes('hide'));
|
||||
assert.ok(!calls.includes('show'));
|
||||
assert.ok(!calls.includes('always-on-top:false'));
|
||||
assert.ok(!calls.includes('move-top'));
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('sync-windows-z-order'));
|
||||
assert.ok(!calls.includes('ensure-level'));
|
||||
assert.ok(calls.includes('sync-shortcuts'));
|
||||
});
|
||||
|
||||
test('Windows hides the visible overlay when the tracked window is minimized', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
let tracking = true;
|
||||
const tracker: WindowTrackerStub = {
|
||||
isTracking: () => tracking,
|
||||
getGeometry: () => (tracking ? { x: 0, y: 0, width: 1280, height: 720 } : null),
|
||||
isTargetWindowMinimized: () => !tracking,
|
||||
};
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
calls.length = 0;
|
||||
tracking = false;
|
||||
|
||||
updateVisibleOverlayVisibility({
|
||||
visibleOverlayVisible: true,
|
||||
mainWindow: window as never,
|
||||
windowTracker: tracker as never,
|
||||
trackerNotReadyWarningShown: false,
|
||||
setTrackerNotReadyWarningShown: () => {},
|
||||
updateVisibleOverlayBounds: () => {
|
||||
calls.push('update-bounds');
|
||||
},
|
||||
ensureOverlayWindowLevel: () => {
|
||||
calls.push('ensure-level');
|
||||
},
|
||||
syncWindowsOverlayToMpvZOrder: () => {
|
||||
calls.push('sync-windows-z-order');
|
||||
},
|
||||
syncPrimaryOverlayWindowLayer: () => {
|
||||
calls.push('sync-layer');
|
||||
},
|
||||
enforceOverlayLayerOrder: () => {
|
||||
calls.push('enforce-order');
|
||||
},
|
||||
syncOverlayShortcuts: () => {
|
||||
calls.push('sync-shortcuts');
|
||||
},
|
||||
isMacOSPlatform: false,
|
||||
isWindowsPlatform: true,
|
||||
} as never);
|
||||
|
||||
assert.ok(calls.includes('hide'));
|
||||
assert.ok(!calls.includes('sync-windows-z-order'));
|
||||
});
|
||||
|
||||
test('macOS keeps visible overlay hidden while tracker is not initialized yet', () => {
|
||||
const { window, calls } = createMainWindowRecorder();
|
||||
let trackerWarning = false;
|
||||
|
||||
Reference in New Issue
Block a user