From 12d048e1e5645a4eb9e57c2ccef0b5bb9071bc65 Mon Sep 17 00:00:00 2001 From: BeetMan Date: Fri, 30 Oct 2026 11:44:39 -0700 Subject: [PATCH 1/2] fix: Escape in the main window closes the output window After opening the second screen, keyboard focus is handed back to the main window, and on macOS which window ends up focused is not deterministic. Esc only closed the output when the output window itself was focused; in the main window it just paused playback, so exiting felt unreliable. While the output is open, Esc in the main window (including the script editor) now closes it without changing playback. With no output open, Esc still pauses. Co-Authored-By: Claude Opus 5.5 --- README.md | 2 +- tauri/web/index.html | 20 +++++++++ ...37\350\203\275\344\273\213\347\273\215.md" | 4 +- tests/teleprompter.spec.js | 42 +++++++++++++++++++ windows-electron/index.html | 20 +++++++++ ...37\350\203\275\344\273\213\347\273\215.md" | 4 +- ...77\347\224\250\346\214\207\345\215\227.md" | 4 +- 7 files changed, 89 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8ffff2d..7c3790b 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ npm run dist:win -- --config.win.signAndEditExecutable=false | `R` | 回到顶部 | | `↑` / `↓` | 快速滚动页面 | | `←` / `→` | 调节滚动速度 | -| `Esc` | 关闭第二屏输出窗口(仅桌面版) | +| `Esc` | 关闭第二屏输出(仅桌面版,主窗口或第二屏中均可);未开第二屏时停止播放 | ## 开发检查 diff --git a/tauri/web/index.html b/tauri/web/index.html index 15d3cc8..293268e 100644 --- a/tauri/web/index.html +++ b/tauri/web/index.html @@ -2168,6 +2168,19 @@

准备一段稿件

} } + async function closeOutputWindowFromMain() { + if (!window.teleprompterBridge?.closeOutputWindow || outputTogglePending) { + return; + } + outputTogglePending = true; + try { + applyOutputStatus(await window.teleprompterBridge.closeOutputWindow()); + elements.stage.focus({ preventScroll: true }); + } finally { + outputTogglePending = false; + } + } + function startResize(event) { event.preventDefault(); resizing = true; @@ -2551,6 +2564,13 @@

准备一段稿件

} return; } + // 打开第二屏后键盘焦点通常留在主窗口(macOS 上焦点落在哪个窗口还不确定), + // 所以主窗口里按 Esc 也要能关闭第二屏;编辑稿件时同样生效 + if (event.key === "Escape" && outputActive) { + event.preventDefault(); + closeOutputWindowFromMain(); + return; + } // 只有正在输入文字的控件(文本框、下拉框)才把按键留给控件本身; // 按钮和滑块获得焦点时不拦截,让空格/R/F/方向键等全局快捷键始终可用 const shortcutTarget = event.target; diff --git "a/tauri/\345\212\237\350\203\275\344\273\213\347\273\215.md" "b/tauri/\345\212\237\350\203\275\344\273\213\347\273\215.md" index 612fdf3..c5ce22b 100644 --- "a/tauri/\345\212\237\350\203\275\344\273\213\347\273\215.md" +++ "b/tauri/\345\212\237\350\203\275\344\273\213\347\273\215.md" @@ -21,7 +21,7 @@ - `R`:回到顶部 - `↑ / ↓`:快速滚动页面 - `← / →`:调节滚动速度 - - `Esc`:在第二屏窗口中退出第二屏输出 + - `Esc`:关闭第二屏输出(主窗口或第二屏窗口中均可);未开第二屏时停止播放 ## 显示调节 @@ -46,7 +46,7 @@ - 第二屏只显示提词内容,不显示底部控制栏。 - 第二屏顶部显示更醒目的剩余字数。 - 中间指示线包含进度点,便于判断当前阅读位置。 -- 按钮再次点击可以关闭第二屏输出,第二屏窗口按 `Esc` 也可以退出。 +- 按钮再次点击可以关闭第二屏输出,在主窗口或第二屏窗口按 `Esc` 也可以退出。 - 关闭程序时会同步结束相关窗口和进程。 ## 主屏预览 diff --git a/tests/teleprompter.spec.js b/tests/teleprompter.spec.js index 16812bc..0462d79 100644 --- a/tests/teleprompter.spec.js +++ b/tests/teleprompter.spec.js @@ -537,3 +537,45 @@ test("output mode ignores playback keys and only handles Escape", async ({ page await page.keyboard.press("Escape"); await expect.poll(() => page.evaluate(() => window.__closeCalls)).toBe(1); }); + +test("Escape in the main window closes an open output window", async ({ page }) => { + await page.addInitScript(() => { + window.__closeCalls = 0; + window.teleprompterBridge = { + toggleOutputWindow: async () => ({ opened: true, displayCount: 2, outputWidth: 1280, outputHeight: 720 }), + closeOutputWindow: async () => { + window.__closeCalls += 1; + return { opened: false, displayCount: 2 }; + }, + sendState: () => {}, + onState: () => {}, + onOutputStatus: () => {}, + }; + }); + + await page.goto(appUrl); + await page.locator("#outputButton").click(); + await expect(page.locator("#outputButton")).toHaveAttribute("aria-pressed", "true"); + + // 播放中按 Esc 只关第二屏,不改变播放状态 + await page.keyboard.press("Space"); + await expect(page.locator("#playButton")).not.toHaveClass(/primary/); + await page.keyboard.press("Escape"); + await expect(page.locator("#outputButton")).toHaveAttribute("aria-pressed", "false"); + await expect.poll(() => page.evaluate(() => window.__closeCalls)).toBe(1); + await expect(page.locator("#playButton")).not.toHaveClass(/primary/); + + // 第二屏关闭后,Esc 恢复为暂停播放,不再调用关闭 + await page.keyboard.press("Escape"); + await expect(page.locator("#playButton")).toHaveClass(/primary/); + expect(await page.evaluate(() => window.__closeCalls)).toBe(1); + + // 编辑稿件时按 Esc 也能关闭第二屏 + await page.locator("#outputButton").click(); + await expect(page.locator("#outputButton")).toHaveAttribute("aria-pressed", "true"); + await page.locator("#toggleEditorButton").click(); + await page.locator("#scriptInput").focus(); + await page.keyboard.press("Escape"); + await expect(page.locator("#outputButton")).toHaveAttribute("aria-pressed", "false"); + await expect.poll(() => page.evaluate(() => window.__closeCalls)).toBe(2); +}); diff --git a/windows-electron/index.html b/windows-electron/index.html index 15d3cc8..293268e 100644 --- a/windows-electron/index.html +++ b/windows-electron/index.html @@ -2168,6 +2168,19 @@

准备一段稿件

} } + async function closeOutputWindowFromMain() { + if (!window.teleprompterBridge?.closeOutputWindow || outputTogglePending) { + return; + } + outputTogglePending = true; + try { + applyOutputStatus(await window.teleprompterBridge.closeOutputWindow()); + elements.stage.focus({ preventScroll: true }); + } finally { + outputTogglePending = false; + } + } + function startResize(event) { event.preventDefault(); resizing = true; @@ -2551,6 +2564,13 @@

准备一段稿件

} return; } + // 打开第二屏后键盘焦点通常留在主窗口(macOS 上焦点落在哪个窗口还不确定), + // 所以主窗口里按 Esc 也要能关闭第二屏;编辑稿件时同样生效 + if (event.key === "Escape" && outputActive) { + event.preventDefault(); + closeOutputWindowFromMain(); + return; + } // 只有正在输入文字的控件(文本框、下拉框)才把按键留给控件本身; // 按钮和滑块获得焦点时不拦截,让空格/R/F/方向键等全局快捷键始终可用 const shortcutTarget = event.target; diff --git "a/windows-electron/\345\212\237\350\203\275\344\273\213\347\273\215.md" "b/windows-electron/\345\212\237\350\203\275\344\273\213\347\273\215.md" index 99af31d..9aba707 100644 --- "a/windows-electron/\345\212\237\350\203\275\344\273\213\347\273\215.md" +++ "b/windows-electron/\345\212\237\350\203\275\344\273\213\347\273\215.md" @@ -23,7 +23,7 @@ - `R`:回到顶部 - `↑ / ↓`:快速滚动页面 - `← / →`:调节滚动速度 - - `Esc`:在第二屏窗口中退出第二屏输出 + - `Esc`:关闭第二屏输出(主窗口或第二屏窗口中均可);未开第二屏时停止播放 ## 显示调节 @@ -48,7 +48,7 @@ - 第二屏只显示提词内容,不显示底部控制栏。 - 第二屏顶部显示更醒目的剩余字数。 - 中间指示线包含进度点,便于判断当前阅读位置。 -- 按钮再次点击可以关闭第二屏输出,第二屏窗口按 `Esc` 也可以退出。 +- 按钮再次点击可以关闭第二屏输出,在主窗口或第二屏窗口按 `Esc` 也可以退出。 - 关闭程序时会同步结束相关窗口和进程。 ## 主屏预览 diff --git "a/\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/\344\275\277\347\224\250\346\214\207\345\215\227.md" index a3ffa7d..c81a795 100644 --- "a/\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -45,7 +45,7 @@ - 支持水平镜像和垂直镜像 - 顶部显示剩余字数 - 指示线上显示进度圆点 -- 按 `Esc` 可以退出第二屏 +- 在主窗口或第二屏中按 `Esc` 都可以退出第二屏 6.1 版本中,主窗口采用固定比例预览画布,主屏看到的换行、字号、指示线位置会尽量和第二屏一致。 @@ -106,7 +106,7 @@ - `←`:降低滚动速度 - `→`:提高滚动速度 - `Shift + ← / →`:更大幅度调节速度 -- `Esc`:第二屏窗口中退出第二屏;播放时停止播放 +- `Esc`:开启第二屏时关闭第二屏(在主窗口或第二屏中按都可以,不影响播放状态);未开第二屏时停止播放 编辑稿件时,方向键会优先用于文本编辑,不会触发提词器快捷操作。 From 8170bf0626c5449a8a656eadec17f6142b8d9916 Mon Sep 17 00:00:00 2001 From: BeetMan Date: Fri, 30 Oct 2026 11:45:53 -0700 Subject: [PATCH 2/2] docs: add 6.6.1 changelog Co-Authored-By: Claude Opus 5.5 --- .../\346\233\264\346\226\260\346\227\245\345\277\227-6.6.md" | 4 ++++ 1 file changed, 4 insertions(+) diff --git "a/docs/\346\233\264\346\226\260\346\227\245\345\277\227-6.6.md" "b/docs/\346\233\264\346\226\260\346\227\245\345\277\227-6.6.md" index 36d8a8f..17e3951 100644 --- "a/docs/\346\233\264\346\226\260\346\227\245\345\277\227-6.6.md" +++ "b/docs/\346\233\264\346\226\260\346\227\245\345\277\227-6.6.md" @@ -2,6 +2,10 @@ 6.6 版本起 Tauri 版成为主力维护的全平台版本,支持 Windows、macOS 和 Linux;Electron 版保留为 Windows 备用版本。 +## 6.6.1 + +- 修复开启第二屏后按 `Esc` 退出不稳定的问题。之前只有键盘焦点在第二屏窗口时 `Esc` 才会关闭第二屏,而打开第二屏后焦点通常交回主窗口(macOS 上落在哪个窗口不确定)。现在开启第二屏时,在主窗口或第二屏中按 `Esc` 都能关闭第二屏,编辑稿件时同样生效,且不改变播放状态;未开第二屏时 `Esc` 仍为暂停播放。 + ## 6.6.0 ### 全平台支持