From c9b60746268c47670cb47061a1db5efb0d43a679 Mon Sep 17 00:00:00 2001 From: auberginewly <3127221787@qq.com> Date: Sun, 10 May 2026 05:24:19 +0800 Subject: [PATCH 1/3] fix(electron): add screen and display-capture to Electron permission allowlists setPermissionCheckHandler and setPermissionRequestHandler only allowed ["media", "audioCapture", "microphone", "videoCapture", "camera"], causing any renderer-side getUserMedia/desktopCapturer request using a screen source to be silently denied by Electron before macOS TCC is ever consulted. Fix: add "screen" and "display-capture" to both handler allowlists. --- electron/main.ts | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/electron/main.ts b/electron/main.ts index 007df33..cf20b5a 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -449,14 +449,30 @@ app.whenReady().then(async () => { app.dock?.show(); } - // Allow microphone/media permission checks + // Allow microphone/media/screen permission checks session.defaultSession.setPermissionCheckHandler((_webContents, permission) => { - const allowed = ["media", "audioCapture", "microphone", "videoCapture", "camera"]; + const allowed = [ + "media", + "audioCapture", + "microphone", + "videoCapture", + "camera", + "screen", + "display-capture", + ]; return allowed.includes(permission); }); session.defaultSession.setPermissionRequestHandler((_webContents, permission, callback) => { - const allowed = ["media", "audioCapture", "microphone", "videoCapture", "camera"]; + const allowed = [ + "media", + "audioCapture", + "microphone", + "videoCapture", + "camera", + "screen", + "display-capture", + ]; callback(allowed.includes(permission)); }); From be4e2d0c94db9fef4af2b6bbfe20cdde19e45232 Mon Sep 17 00:00:00 2001 From: auberginewly <3127221787@qq.com> Date: Sun, 10 May 2026 05:30:42 +0800 Subject: [PATCH 2/3] fix(electron/macOS): proactively check screen recording permission on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Microphone permission is checked at startup via getMediaAccessStatus, and camera has a dedicated request-camera-access IPC handler, but screen recording relied entirely on desktopCapturer.getSources() to implicitly trigger the TCC prompt — causing the permission dialog to reappear on every launch (issue #558). Note: askForMediaAccess() only accepts "microphone" | "camera"; screen recording TCC is triggered via desktopCapturer.getSources() instead. Fix: - Import desktopCapturer in main.ts - Call getMediaAccessStatus("screen") in app.whenReady(); trigger the TCC prompt via getSources when status is "not-determined" - Add request-screen-access IPC handler symmetric to request-camera-access --- electron/ipc/handlers.ts | 26 ++++++++++++++++++++++++++ electron/main.ts | 12 +++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/electron/ipc/handlers.ts b/electron/ipc/handlers.ts index bf0bc97..b13dd75 100644 --- a/electron/ipc/handlers.ts +++ b/electron/ipc/handlers.ts @@ -718,6 +718,32 @@ export function registerIpcHandlers( } }); + ipcMain.handle("request-screen-access", async () => { + if (process.platform !== "darwin") { + return { success: true, granted: true, status: "granted" }; + } + + try { + const status = systemPreferences.getMediaAccessStatus("screen"); + if (status === "granted") { + return { success: true, granted: true, status }; + } + + // Screen recording has no askForMediaAccess equivalent — the TCC prompt + // is triggered by desktopCapturer.getSources(). Fire it and return so + // the renderer can re-check status after the user responds. + if (status === "not-determined") { + desktopCapturer.getSources({ types: ["screen"] }).catch(() => {}); + return { success: true, granted: false, status: "not-determined" }; + } + + return { success: true, granted: false, status }; + } catch (error) { + console.error("Failed to request screen access:", error); + return { success: false, granted: false, status: "unknown", error: String(error) }; + } + }); + // macOS Accessibility prompt for global click capture. First call shows the // system dialog; the user has to toggle the app in System Settings (no // programmatic grant exists for Accessibility). diff --git a/electron/main.ts b/electron/main.ts index cf20b5a..4e443a9 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url"; import { app, BrowserWindow, + desktopCapturer, ipcMain, Menu, nativeImage, @@ -476,12 +477,21 @@ app.whenReady().then(async () => { callback(allowed.includes(permission)); }); - // Request microphone permission from macOS + // Request microphone and screen recording permissions from macOS if (process.platform === "darwin") { const micStatus = systemPreferences.getMediaAccessStatus("microphone"); if (micStatus !== "granted") { await systemPreferences.askForMediaAccess("microphone"); } + + // Screen recording has no askForMediaAccess equivalent — the TCC prompt is + // triggered by the first desktopCapturer.getSources() call. Firing it here + // at startup settles the permission state early and prevents repeated prompts + // driven by later getSources() calls (fixes repeated permission dialog). + const screenStatus = systemPreferences.getMediaAccessStatus("screen"); + if (screenStatus === "not-determined") { + desktopCapturer.getSources({ types: ["screen"] }).catch(() => {}); + } } // Listen for HUD overlay quit event (macOS only) From 3dd7b85ebb1d16f4d231f8c027b67bd037f63ba4 Mon Sep 17 00:00:00 2001 From: auberginewly <3127221787@qq.com> Date: Sun, 10 May 2026 05:30:48 +0800 Subject: [PATCH 3/3] fix(build): remove misplaced entitlement key from mac.extendInfo com.apple.security.device.audio-input is an entitlement key and should only appear in macos.entitlements. Placing it in extendInfo writes it into Info.plist where it has no effect and is misleading. The correct entry already exists in macos.entitlements; this removes the redundant, incorrectly-placed duplicate. --- electron-builder.json5 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/electron-builder.json5 b/electron-builder.json5 index d9fee6b..372cdf7 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -52,8 +52,7 @@ "NSMicrophoneUsageDescription": "OpenScreen needs microphone access to record voice audio.", "NSCameraUsageDescription": "OpenScreen needs camera access to record webcam video.", "NSScreenCaptureUsageDescription": "OpenScreen needs screen recording permission to detect and capture windows.", - "NSCameraUseContinuityCameraDeviceType": true, - "com.apple.security.device.audio-input": true + "NSCameraUseContinuityCameraDeviceType": true } }, "linux": {