mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-30 00:15:27 -07:00
fix(overlay): Linux X11/XWayland stacking, stale pause state, multi-copy selector (#101)
This commit is contained in:
@@ -16,13 +16,19 @@ test('linux mpv fullscreen overlay refresh burst schedules overlay refresh work
|
||||
const calls: string[] = [];
|
||||
|
||||
try {
|
||||
scheduleLinuxVisibleOverlayFullscreenRefreshBurst({
|
||||
scheduleLinuxVisibleOverlayFullscreenRefreshBurst(true, {
|
||||
overlayManager: {
|
||||
getMainWindow: () =>
|
||||
({
|
||||
hide: () => calls.push('hide'),
|
||||
isFullScreen: () => false,
|
||||
isDestroyed: () => false,
|
||||
isVisible: () => true,
|
||||
setFullScreen: (fullscreen: boolean) => calls.push(`fullscreen:${fullscreen}`),
|
||||
setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) =>
|
||||
calls.push(
|
||||
`mouse-ignore:${ignore}:${options?.forward === true ? 'forward' : 'plain'}`,
|
||||
),
|
||||
showInactive: () => calls.push('showInactive'),
|
||||
}) as never,
|
||||
getVisibleOverlayVisible: () => true,
|
||||
@@ -30,6 +36,8 @@ test('linux mpv fullscreen overlay refresh burst schedules overlay refresh work
|
||||
overlayVisibilityRuntime: {
|
||||
updateVisibleOverlayVisibility: () => calls.push('updateVisibleOverlayVisibility'),
|
||||
},
|
||||
syncVisibleOverlayMpvFullscreenMode: (fullscreen: boolean) =>
|
||||
calls.push(`sync-overlay-mode:${fullscreen}`),
|
||||
ensureOverlayWindowLevel: () => calls.push('ensureOverlayWindowLevel'),
|
||||
});
|
||||
|
||||
@@ -39,8 +47,11 @@ test('linux mpv fullscreen overlay refresh burst schedules overlay refresh work
|
||||
}
|
||||
|
||||
assert.ok(calls.includes('updateVisibleOverlayVisibility'));
|
||||
assert.ok(calls.includes('sync-overlay-mode:true'));
|
||||
assert.ok(!calls.includes('fullscreen:true'));
|
||||
assert.ok(calls.includes('hide'));
|
||||
assert.ok(calls.includes('showInactive'));
|
||||
assert.ok(calls.includes('mouse-ignore:true:forward'));
|
||||
assert.ok(calls.includes('ensureOverlayWindowLevel'));
|
||||
} finally {
|
||||
clearLinuxMpvFullscreenOverlayRefreshTimeouts();
|
||||
@@ -50,7 +61,46 @@ test('linux mpv fullscreen overlay refresh burst schedules overlay refresh work
|
||||
}
|
||||
});
|
||||
|
||||
test('linux mpv fullscreen overlay refresh update schedules a fresh burst when fullscreen exits', async () => {
|
||||
test('linux mpv fullscreen overlay refresh remembers mode even when overlay is hidden', async () => {
|
||||
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, 'platform');
|
||||
Object.defineProperty(process, 'platform', {
|
||||
configurable: true,
|
||||
value: 'linux',
|
||||
});
|
||||
|
||||
const calls: string[] = [];
|
||||
|
||||
try {
|
||||
scheduleLinuxVisibleOverlayFullscreenRefreshBurst(true, {
|
||||
overlayManager: {
|
||||
getMainWindow: () => null,
|
||||
getVisibleOverlayVisible: () => false,
|
||||
},
|
||||
overlayVisibilityRuntime: {
|
||||
updateVisibleOverlayVisibility: () => calls.push('updateVisibleOverlayVisibility'),
|
||||
},
|
||||
syncVisibleOverlayMpvFullscreenMode: (fullscreen: boolean) =>
|
||||
calls.push(`sync-overlay-mode:${fullscreen}`),
|
||||
ensureOverlayWindowLevel: () => calls.push('ensureOverlayWindowLevel'),
|
||||
});
|
||||
|
||||
const deadline = Date.now() + 200;
|
||||
while (!calls.includes('sync-overlay-mode:true') && Date.now() < deadline) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 5));
|
||||
}
|
||||
|
||||
assert.ok(calls.includes('sync-overlay-mode:true'));
|
||||
assert.ok(!calls.includes('updateVisibleOverlayVisibility'));
|
||||
assert.ok(!calls.includes('ensureOverlayWindowLevel'));
|
||||
} finally {
|
||||
clearLinuxMpvFullscreenOverlayRefreshTimeouts();
|
||||
if (originalPlatformDescriptor) {
|
||||
Object.defineProperty(process, 'platform', originalPlatformDescriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('linux mpv fullscreen overlay refresh updates mode without hide/show when fullscreen exits', async () => {
|
||||
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, 'platform');
|
||||
Object.defineProperty(process, 'platform', {
|
||||
configurable: true,
|
||||
@@ -65,8 +115,14 @@ test('linux mpv fullscreen overlay refresh update schedules a fresh burst when f
|
||||
getMainWindow: () =>
|
||||
({
|
||||
hide: () => calls.push('hide'),
|
||||
isFullScreen: () => true,
|
||||
isDestroyed: () => false,
|
||||
isVisible: () => true,
|
||||
setFullScreen: (fullscreen: boolean) => calls.push(`fullscreen:${fullscreen}`),
|
||||
setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) =>
|
||||
calls.push(
|
||||
`mouse-ignore:${ignore}:${options?.forward === true ? 'forward' : 'plain'}`,
|
||||
),
|
||||
showInactive: () => calls.push('showInactive'),
|
||||
}) as never,
|
||||
getVisibleOverlayVisible: () => true,
|
||||
@@ -74,6 +130,8 @@ test('linux mpv fullscreen overlay refresh update schedules a fresh burst when f
|
||||
overlayVisibilityRuntime: {
|
||||
updateVisibleOverlayVisibility: () => calls.push('updateVisibleOverlayVisibility'),
|
||||
},
|
||||
syncVisibleOverlayMpvFullscreenMode: (fullscreen: boolean) =>
|
||||
calls.push(`sync-overlay-mode:${fullscreen}`),
|
||||
ensureOverlayWindowLevel: () => calls.push('ensureOverlayWindowLevel'),
|
||||
};
|
||||
|
||||
@@ -84,9 +142,125 @@ test('linux mpv fullscreen overlay refresh update schedules a fresh burst when f
|
||||
|
||||
assert.equal(typeof nextCancel, 'function');
|
||||
assert.ok(calls.includes('updateVisibleOverlayVisibility'));
|
||||
assert.ok(calls.includes('hide'));
|
||||
assert.ok(calls.includes('showInactive'));
|
||||
assert.ok(calls.includes('ensureOverlayWindowLevel'));
|
||||
assert.ok(calls.includes('sync-overlay-mode:false'));
|
||||
assert.ok(!calls.includes('fullscreen:false'));
|
||||
assert.equal(calls.includes('hide'), false);
|
||||
assert.equal(calls.includes('showInactive'), false);
|
||||
assert.equal(calls.includes('mouse-ignore:true:forward'), false);
|
||||
assert.equal(calls.includes('ensureOverlayWindowLevel'), false);
|
||||
} finally {
|
||||
clearLinuxMpvFullscreenOverlayRefreshTimeouts();
|
||||
if (originalPlatformDescriptor) {
|
||||
Object.defineProperty(process, 'platform', originalPlatformDescriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('linux mpv fullscreen overlay refresh restores click-through after restacking', async () => {
|
||||
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, 'platform');
|
||||
Object.defineProperty(process, 'platform', {
|
||||
configurable: true,
|
||||
value: 'linux',
|
||||
});
|
||||
|
||||
const calls: string[] = [];
|
||||
|
||||
try {
|
||||
scheduleLinuxVisibleOverlayFullscreenRefreshBurst(true, {
|
||||
overlayManager: {
|
||||
getMainWindow: () =>
|
||||
({
|
||||
hide: () => calls.push('hide'),
|
||||
isFullScreen: () => false,
|
||||
isDestroyed: () => false,
|
||||
isVisible: () => true,
|
||||
setFullScreen: (fullscreen: boolean) => calls.push(`fullscreen:${fullscreen}`),
|
||||
setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) =>
|
||||
calls.push(
|
||||
`mouse-ignore:${ignore}:${options?.forward === true ? 'forward' : 'plain'}`,
|
||||
),
|
||||
showInactive: () => calls.push('showInactive'),
|
||||
}) as never,
|
||||
getVisibleOverlayVisible: () => true,
|
||||
},
|
||||
overlayVisibilityRuntime: {
|
||||
updateVisibleOverlayVisibility: () => calls.push('updateVisibleOverlayVisibility'),
|
||||
},
|
||||
syncVisibleOverlayMpvFullscreenMode: (fullscreen: boolean) =>
|
||||
calls.push(`sync-overlay-mode:${fullscreen}`),
|
||||
ensureOverlayWindowLevel: () => calls.push('ensureOverlayWindowLevel'),
|
||||
});
|
||||
|
||||
const deadline = Date.now() + 200;
|
||||
while (!calls.includes('mouse-ignore:true:forward') && Date.now() < deadline) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 5));
|
||||
}
|
||||
|
||||
const showIndex = calls.indexOf('showInactive');
|
||||
const passthroughIndex = calls.indexOf('mouse-ignore:true:forward');
|
||||
const levelIndex = calls.indexOf('ensureOverlayWindowLevel');
|
||||
const syncIndex = calls.indexOf('sync-overlay-mode:true');
|
||||
|
||||
assert.ok(syncIndex >= 0);
|
||||
assert.ok(showIndex >= 0);
|
||||
assert.ok(syncIndex < showIndex);
|
||||
assert.ok(passthroughIndex > showIndex);
|
||||
assert.ok(levelIndex > passthroughIndex);
|
||||
} finally {
|
||||
clearLinuxMpvFullscreenOverlayRefreshTimeouts();
|
||||
if (originalPlatformDescriptor) {
|
||||
Object.defineProperty(process, 'platform', originalPlatformDescriptor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('linux mpv fullscreen overlay refresh preserves active subtitle interaction after restacking', async () => {
|
||||
const originalPlatformDescriptor = Object.getOwnPropertyDescriptor(process, 'platform');
|
||||
Object.defineProperty(process, 'platform', {
|
||||
configurable: true,
|
||||
value: 'linux',
|
||||
});
|
||||
|
||||
const calls: string[] = [];
|
||||
|
||||
try {
|
||||
scheduleLinuxVisibleOverlayFullscreenRefreshBurst(true, {
|
||||
overlayManager: {
|
||||
getMainWindow: () =>
|
||||
({
|
||||
hide: () => calls.push('hide'),
|
||||
isFullScreen: () => false,
|
||||
isDestroyed: () => false,
|
||||
isVisible: () => true,
|
||||
setFullScreen: (fullscreen: boolean) => calls.push(`fullscreen:${fullscreen}`),
|
||||
setIgnoreMouseEvents: (ignore: boolean, options?: { forward?: boolean }) =>
|
||||
calls.push(
|
||||
`mouse-ignore:${ignore}:${options?.forward === true ? 'forward' : 'plain'}`,
|
||||
),
|
||||
showInactive: () => calls.push('showInactive'),
|
||||
}) as never,
|
||||
getVisibleOverlayVisible: () => true,
|
||||
},
|
||||
overlayVisibilityRuntime: {
|
||||
updateVisibleOverlayVisibility: () => calls.push('updateVisibleOverlayVisibility'),
|
||||
},
|
||||
syncVisibleOverlayMpvFullscreenMode: (fullscreen: boolean) =>
|
||||
calls.push(`sync-overlay-mode:${fullscreen}`),
|
||||
getOverlayInteractionActive: () => true,
|
||||
ensureOverlayWindowLevel: () => calls.push('ensureOverlayWindowLevel'),
|
||||
});
|
||||
|
||||
const deadline = Date.now() + 200;
|
||||
while (!calls.includes('mouse-ignore:false:plain') && Date.now() < deadline) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 5));
|
||||
}
|
||||
|
||||
const showIndex = calls.indexOf('showInactive');
|
||||
const interactiveIndex = calls.indexOf('mouse-ignore:false:plain');
|
||||
|
||||
assert.ok(showIndex >= 0);
|
||||
assert.ok(interactiveIndex > showIndex);
|
||||
assert.equal(calls.includes('mouse-ignore:true:forward'), false);
|
||||
} finally {
|
||||
clearLinuxMpvFullscreenOverlayRefreshTimeouts();
|
||||
if (originalPlatformDescriptor) {
|
||||
|
||||
Reference in New Issue
Block a user