From b7d25ef389794cef31d9107574322f9a2c2f363c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 03:34:56 +0000 Subject: [PATCH 1/5] Initial plan From db5a1f29e7f0a1d29b335ffbc28690caa03a7438 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 03:44:39 +0000 Subject: [PATCH 2/5] Fix macOS microphone permission registration Instantiate AVCaptureSession when requesting audio permissions to ensure the app properly registers in System Settings > Privacy & Security > Microphone. This fix addresses the issue where RustDesk was not appearing in the microphone permissions list on macOS. Co-authored-by: rustdesk <71636191+rustdesk@users.noreply.github.com> --- flutter/macos/Runner/MainFlutterWindow.swift | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 1cc72419b..a0b292a51 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -210,6 +210,29 @@ class MainFlutterWindow: NSWindow { } case "requestRecordAudio": AVCaptureDevice.requestAccess(for: .audio, completionHandler: { granted in + if granted { + // Actually instantiate an audio device to ensure macOS registers the app + // in System Settings > Privacy & Security > Microphone + if let audioDevice = AVCaptureDevice.default(for: .audio) { + do { + let audioInput = try AVCaptureDeviceInput(device: audioDevice) + let captureSession = AVCaptureSession() + captureSession.beginConfiguration() + if captureSession.canAddInput(audioInput) { + captureSession.addInput(audioInput) + } + captureSession.commitConfiguration() + // Start and immediately stop the session to trigger registration + captureSession.startRunning() + // Stop after a brief moment to ensure registration is complete + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + captureSession.stopRunning() + } + } catch { + NSLog("[RustDesk] Error creating audio capture session for permission registration: %@", error.localizedDescription) + } + } + } DispatchQueue.main.async { result(granted) } From 780c3965419d88dbefc77c0bd04ebf7e64021fab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 03:45:08 +0000 Subject: [PATCH 3/5] Add detailed comments explaining microphone permission fix Co-authored-by: rustdesk <71636191+rustdesk@users.noreply.github.com> --- flutter/macos/Runner/MainFlutterWindow.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index a0b292a51..7bac14d2c 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -209,10 +209,13 @@ class MainFlutterWindow: NSWindow { break } case "requestRecordAudio": + // Request microphone access and trigger system registration + // On macOS 13+, apps only appear in System Settings > Privacy & Security > Microphone + // after they actually attempt to use the microphone, not just request permission. + // We create a brief capture session to ensure proper registration. AVCaptureDevice.requestAccess(for: .audio, completionHandler: { granted in if granted { - // Actually instantiate an audio device to ensure macOS registers the app - // in System Settings > Privacy & Security > Microphone + // Instantiate an audio capture session to trigger macOS registration if let audioDevice = AVCaptureDevice.default(for: .audio) { do { let audioInput = try AVCaptureDeviceInput(device: audioDevice) From 370b467b71d2fca4a1dd4da6532bb128f3df487e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 03:45:47 +0000 Subject: [PATCH 4/5] Address code review feedback: fix memory lifecycle and improve error message - Move capture session lifecycle to main thread - Add strong capture of captureSession in asyncAfter block to prevent premature deallocation - Improve error message to inform user about potential impact and suggested action Co-authored-by: rustdesk <71636191+rustdesk@users.noreply.github.com> --- flutter/macos/Runner/MainFlutterWindow.swift | 35 +++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 7bac14d2c..53dec2742 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -216,23 +216,26 @@ class MainFlutterWindow: NSWindow { AVCaptureDevice.requestAccess(for: .audio, completionHandler: { granted in if granted { // Instantiate an audio capture session to trigger macOS registration - if let audioDevice = AVCaptureDevice.default(for: .audio) { - do { - let audioInput = try AVCaptureDeviceInput(device: audioDevice) - let captureSession = AVCaptureSession() - captureSession.beginConfiguration() - if captureSession.canAddInput(audioInput) { - captureSession.addInput(audioInput) + // This needs to run on main thread to ensure proper lifecycle + DispatchQueue.main.async { + if let audioDevice = AVCaptureDevice.default(for: .audio) { + do { + let audioInput = try AVCaptureDeviceInput(device: audioDevice) + let captureSession = AVCaptureSession() + captureSession.beginConfiguration() + if captureSession.canAddInput(audioInput) { + captureSession.addInput(audioInput) + } + captureSession.commitConfiguration() + // Start and immediately stop the session to trigger registration + captureSession.startRunning() + // Keep a strong reference and stop after a brief moment + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [captureSession] in + captureSession.stopRunning() + } + } catch { + NSLog("[RustDesk] Error creating audio capture session for permission registration: %@. The app may not appear in System Settings > Privacy & Security > Microphone. Please verify permissions manually.", error.localizedDescription) } - captureSession.commitConfiguration() - // Start and immediately stop the session to trigger registration - captureSession.startRunning() - // Stop after a brief moment to ensure registration is complete - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { - captureSession.stopRunning() - } - } catch { - NSLog("[RustDesk] Error creating audio capture session for permission registration: %@", error.localizedDescription) } } } From 36b4f765fd7ee5ea1644827497866ebaf5e771dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Feb 2026 03:46:24 +0000 Subject: [PATCH 5/5] Improve code quality: use named constant and clearer error logs - Extract 0.1 second delay to named constant 'registrationDelay' with explanatory comment - Split error message into separate log lines for better readability Co-authored-by: rustdesk <71636191+rustdesk@users.noreply.github.com> --- flutter/macos/Runner/MainFlutterWindow.swift | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/flutter/macos/Runner/MainFlutterWindow.swift b/flutter/macos/Runner/MainFlutterWindow.swift index 53dec2742..8572d5a82 100644 --- a/flutter/macos/Runner/MainFlutterWindow.swift +++ b/flutter/macos/Runner/MainFlutterWindow.swift @@ -229,12 +229,15 @@ class MainFlutterWindow: NSWindow { captureSession.commitConfiguration() // Start and immediately stop the session to trigger registration captureSession.startRunning() - // Keep a strong reference and stop after a brief moment - DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [captureSession] in + // Minimum delay required for macOS to register the app in System Settings + let registrationDelay: TimeInterval = 0.1 + // Keep a strong reference and stop after the registration delay + DispatchQueue.main.asyncAfter(deadline: .now() + registrationDelay) { [captureSession] in captureSession.stopRunning() } } catch { - NSLog("[RustDesk] Error creating audio capture session for permission registration: %@. The app may not appear in System Settings > Privacy & Security > Microphone. Please verify permissions manually.", error.localizedDescription) + NSLog("[RustDesk] Failed to create audio capture session: %@", error.localizedDescription) + NSLog("[RustDesk] The app may not appear in System Settings > Privacy & Security > Microphone") } } }