Merge pull request #561 from auberginewly/fix/electron-screen-capture-permissions

fix(macOS): fix three screen capture permission issues in Electron layer
This commit is contained in:
Sid
2026-05-09 15:10:47 -07:00
committed by GitHub
3 changed files with 57 additions and 6 deletions
+1 -2
View File
@@ -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": {
+26
View File
@@ -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).
+30 -4
View File
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
import {
app,
BrowserWindow,
desktopCapturer,
ipcMain,
Menu,
nativeImage,
@@ -449,23 +450,48 @@ 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));
});
// 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)