mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
7 Commits
refactor/p
...
sckp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a80305df81 | ||
|
|
55636eddb4 | ||
|
|
35b9caa4ab | ||
|
|
ce5cce555f | ||
|
|
3ff42dee57 | ||
|
|
83c611977c | ||
|
|
85039665f4 |
@@ -16,6 +16,12 @@ app.whenReady().then(() => {
|
|||||||
const mainWindow = new BrowserWindow()
|
const mainWindow = new BrowserWindow()
|
||||||
|
|
||||||
session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
|
session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
|
||||||
|
// If we should use the system picker
|
||||||
|
// Note: this is currently experimental
|
||||||
|
if (desktopCapturer.isDisplayMediaSystemPickerAvailable()) {
|
||||||
|
callback({ video: desktopCapturer.systemPickerVideoSource })
|
||||||
|
return
|
||||||
|
}
|
||||||
desktopCapturer.getSources({ types: ['screen'] }).then((sources) => {
|
desktopCapturer.getSources({ types: ['screen'] }).then((sources) => {
|
||||||
// Grant access to the first screen found.
|
// Grant access to the first screen found.
|
||||||
callback({ video: sources[0], audio: 'loopback' })
|
callback({ video: sources[0], audio: 'loopback' })
|
||||||
@@ -94,6 +100,23 @@ which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
|||||||
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
|
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
|
||||||
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-windows-macos
|
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-windows-macos
|
||||||
|
|
||||||
|
### `desktopCapturer.isDisplayMediaSystemPickerAvailable()` _Experimental_
|
||||||
|
|
||||||
|
Returns `Boolean`, whether or not requesting desktop content via
|
||||||
|
the system picker is supported on this platform.
|
||||||
|
|
||||||
|
Currently this will only return `true` on macOS 14.4 and higher. When
|
||||||
|
true you should respect this value and use `systemPickerVideoSource` as
|
||||||
|
otherwise the OS may present scary warning dialogs to your users.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
### `desktopCapturer.systemPickerVideoSource` _Experimental_ _Readonly_
|
||||||
|
|
||||||
|
A `DesktopCapturerSource` property that should be used in conjunction with
|
||||||
|
[`session.setDisplayMediaRequestHandler`](./session.md#sessetdisplaymediarequesthandlerhandler) to use the system picker instead
|
||||||
|
of providing a specific video source from `getSources`.
|
||||||
|
|
||||||
## Caveats
|
## Caveats
|
||||||
|
|
||||||
`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.
|
`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ filenames = {
|
|||||||
"shell/browser/api/electron_api_debugger.h",
|
"shell/browser/api/electron_api_debugger.h",
|
||||||
"shell/browser/api/electron_api_desktop_capturer.cc",
|
"shell/browser/api/electron_api_desktop_capturer.cc",
|
||||||
"shell/browser/api/electron_api_desktop_capturer.h",
|
"shell/browser/api/electron_api_desktop_capturer.h",
|
||||||
|
"shell/browser/api/electron_api_desktop_capturer_mac.mm",
|
||||||
"shell/browser/api/electron_api_dialog.cc",
|
"shell/browser/api/electron_api_dialog.cc",
|
||||||
"shell/browser/api/electron_api_download_item.cc",
|
"shell/browser/api/electron_api_download_item.cc",
|
||||||
"shell/browser/api/electron_api_download_item.h",
|
"shell/browser/api/electron_api_download_item.h",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { BrowserWindow } from 'electron/main';
|
import { BrowserWindow } from 'electron/main';
|
||||||
const { createDesktopCapturer } = process._linkedBinding('electron_browser_desktop_capturer');
|
const { createDesktopCapturer, isDisplayMediaSystemPickerAvailable } = process._linkedBinding('electron_browser_desktop_capturer');
|
||||||
|
|
||||||
const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
|
const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b);
|
||||||
|
|
||||||
@@ -13,6 +13,19 @@ function isValid (options: Electron.SourcesOptions) {
|
|||||||
return Array.isArray(options?.types);
|
return Array.isArray(options?.types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Magic video source that activates the native system picker
|
||||||
|
let fakeVideoSourceId = -1;
|
||||||
|
const systemPickerVideoSource = Object.create(null);
|
||||||
|
Object.defineProperty(systemPickerVideoSource, 'id', {
|
||||||
|
get () {
|
||||||
|
return `window:${fakeVideoSourceId--}:0`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
systemPickerVideoSource.name = '';
|
||||||
|
Object.freeze(systemPickerVideoSource);
|
||||||
|
|
||||||
|
export { isDisplayMediaSystemPickerAvailable, systemPickerVideoSource };
|
||||||
|
|
||||||
export async function getSources (args: Electron.SourcesOptions) {
|
export async function getSources (args: Electron.SourcesOptions) {
|
||||||
if (!isValid(args)) throw new Error('Invalid options');
|
if (!isValid(args)) throw new Error('Invalid options');
|
||||||
|
|
||||||
|
|||||||
@@ -131,3 +131,4 @@ feat_enable_passing_exit_code_on_service_process_crash.patch
|
|||||||
chore_remove_reference_to_chrome_browser_themes.patch
|
chore_remove_reference_to_chrome_browser_themes.patch
|
||||||
feat_enable_customizing_symbol_color_in_framecaptionbutton.patch
|
feat_enable_customizing_symbol_color_in_framecaptionbutton.patch
|
||||||
fix_potential_draggable_region_crash_when_no_mainframeimpl.patch
|
fix_potential_draggable_region_crash_when_no_mainframeimpl.patch
|
||||||
|
feat_allow_usage_of_sccontentsharingpicker_on_supported_platforms.patch
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Samuel Attard <marshallofsound@electronjs.org>
|
||||||
|
Date: Thu, 8 Aug 2024 08:39:10 -0700
|
||||||
|
Subject: feat: allow usage of SCContentSharingPicker on supported platforms
|
||||||
|
|
||||||
|
This is implemented as a magic "window id" that instead of pulling an SCStream manually
|
||||||
|
instead farms out to the screen picker.
|
||||||
|
|
||||||
|
diff --git a/content/browser/media/capture/screen_capture_kit_device_mac.mm b/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||||
|
index 5c09b98b0c0ade9197a73186809ae4da28a12506..1bafa222164041b011eb0f70d72e0dc217804e9e 100644
|
||||||
|
--- a/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||||
|
+++ b/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||||
|
@@ -25,6 +25,57 @@
|
||||||
|
std::optional<gfx::Rect>)>;
|
||||||
|
using ErrorCallback = base::RepeatingClosure;
|
||||||
|
|
||||||
|
+API_AVAILABLE(macos(14.0))
|
||||||
|
+@interface ScreenCaptureKitPickerHelper
|
||||||
|
+ : NSObject <SCContentSharingPickerObserver>
|
||||||
|
+
|
||||||
|
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||||
|
+ didCancelForStream:(SCStream *)stream;
|
||||||
|
+
|
||||||
|
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||||
|
+ didUpdateWithFilter:(SCContentFilter *)filter
|
||||||
|
+ forStream:(SCStream *)stream;
|
||||||
|
+
|
||||||
|
+- (void)contentSharingPickerStartDidFailWithError:(NSError *)error;
|
||||||
|
+
|
||||||
|
+@end
|
||||||
|
+
|
||||||
|
+@implementation ScreenCaptureKitPickerHelper {
|
||||||
|
+ base::RepeatingCallback<void(SCContentFilter *)> _pickerCallback;
|
||||||
|
+ ErrorCallback _errorCallback;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||||
|
+ didCancelForStream:(SCStream *)stream {
|
||||||
|
+ // TODO: This doesn't appear to be called, we probably need
|
||||||
|
+ // to wait for apple to fix a thing before we can correctly
|
||||||
|
+ // handle cancel events
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+- (void)contentSharingPicker:(SCContentSharingPicker *)picker
|
||||||
|
+ didUpdateWithFilter:(SCContentFilter *)filter
|
||||||
|
+ forStream:(SCStream *)stream {
|
||||||
|
+ if (stream == nil) {
|
||||||
|
+ _pickerCallback.Run(filter);
|
||||||
|
+ [picker removeObserver:self];
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+- (void)contentSharingPickerStartDidFailWithError:(NSError *)error {
|
||||||
|
+ _errorCallback.Run();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+- (instancetype)initWithStreamPickCallback:(base::RepeatingCallback<void(SCContentFilter *)>)pickerCallback
|
||||||
|
+ errorCallback:(ErrorCallback)errorCallback {
|
||||||
|
+ if (self = [super init]) {
|
||||||
|
+ _pickerCallback = pickerCallback;
|
||||||
|
+ _errorCallback = errorCallback;
|
||||||
|
+ }
|
||||||
|
+ return self;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+@end
|
||||||
|
+
|
||||||
|
API_AVAILABLE(macos(12.3))
|
||||||
|
@interface ScreenCaptureKitDeviceHelper
|
||||||
|
: NSObject <SCStreamDelegate, SCStreamOutput>
|
||||||
|
@@ -141,7 +192,8 @@ + (SCStreamConfiguration*)streamConfigurationWithFrameSize:(gfx::Size)frameSize
|
||||||
|
|
||||||
|
class API_AVAILABLE(macos(12.3)) ScreenCaptureKitDeviceMac
|
||||||
|
: public IOSurfaceCaptureDeviceBase,
|
||||||
|
- public ScreenCaptureKitResetStreamInterface {
|
||||||
|
+ public ScreenCaptureKitResetStreamInterface
|
||||||
|
+ {
|
||||||
|
public:
|
||||||
|
explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source)
|
||||||
|
: source_(source),
|
||||||
|
@@ -157,11 +209,29 @@ explicit ScreenCaptureKitDeviceMac(const DesktopMediaID& source)
|
||||||
|
helper_ = [[ScreenCaptureKitDeviceHelper alloc]
|
||||||
|
initWithSampleCallback:sample_callback
|
||||||
|
errorCallback:error_callback];
|
||||||
|
+
|
||||||
|
+ if (@available(macOS 14.0, *)) {
|
||||||
|
+ auto picker_callback = base::BindPostTask(
|
||||||
|
+ device_task_runner_,
|
||||||
|
+ base::BindRepeating(&ScreenCaptureKitDeviceMac::OnContentFilterReady, weak_factory_.GetWeakPtr())
|
||||||
|
+ );
|
||||||
|
+ auto* picker_observer = [[ScreenCaptureKitPickerHelper alloc] initWithStreamPickCallback:picker_callback errorCallback:error_callback];
|
||||||
|
+ [[SCContentSharingPicker sharedPicker] addObserver:picker_observer];
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
ScreenCaptureKitDeviceMac(const ScreenCaptureKitDeviceMac&) = delete;
|
||||||
|
ScreenCaptureKitDeviceMac& operator=(const ScreenCaptureKitDeviceMac&) =
|
||||||
|
delete;
|
||||||
|
- ~ScreenCaptureKitDeviceMac() override = default;
|
||||||
|
+ ~ScreenCaptureKitDeviceMac() override {
|
||||||
|
+ if (@available(macOS 14.0, *)) {
|
||||||
|
+ auto* picker = [SCContentSharingPicker sharedPicker];
|
||||||
|
+ ScreenCaptureKitDeviceMac::active_streams_--;
|
||||||
|
+ picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
|
||||||
|
+ if (ScreenCaptureKitDeviceMac::active_streams_ == 0 && picker.active) {
|
||||||
|
+ picker.active = false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
void OnShareableContentCreated(SCShareableContent* content) {
|
||||||
|
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
|
||||||
|
@@ -225,6 +295,9 @@ void OnShareableContentCreated(SCShareableContent* content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ OnContentFilterReady(filter);
|
||||||
|
+ }
|
||||||
|
+ void OnContentFilterReady(SCContentFilter* filter) {
|
||||||
|
gfx::RectF dest_rect_in_frame;
|
||||||
|
actual_capture_format_ = capture_params().requested_format;
|
||||||
|
actual_capture_format_.pixel_format = media::PIXEL_FORMAT_NV12;
|
||||||
|
@@ -238,6 +311,7 @@ void OnShareableContentCreated(SCShareableContent* content) {
|
||||||
|
stream_ = [[SCStream alloc] initWithFilter:filter
|
||||||
|
configuration:config
|
||||||
|
delegate:helper_];
|
||||||
|
+
|
||||||
|
{
|
||||||
|
NSError* error = nil;
|
||||||
|
bool add_stream_output_result =
|
||||||
|
@@ -405,6 +479,26 @@ void OnUpdateConfigurationError() {
|
||||||
|
void OnStart() override {
|
||||||
|
DCHECK(device_task_runner_->RunsTasksInCurrentSequence());
|
||||||
|
|
||||||
|
+ if (@available(macOS 14.0, *)) {
|
||||||
|
+ if (source_.id < 0 && source_.window_id == 0) {
|
||||||
|
+ auto* picker = [SCContentSharingPicker sharedPicker];
|
||||||
|
+ ScreenCaptureKitDeviceMac::active_streams_++;
|
||||||
|
+ picker.maximumStreamCount = @(ScreenCaptureKitDeviceMac::active_streams_);
|
||||||
|
+ if (!picker.active) {
|
||||||
|
+ picker.active = true;
|
||||||
|
+ }
|
||||||
|
+ NSMutableArray<NSNumber*>* exclude_ns_windows = [NSMutableArray array];
|
||||||
|
+ [[[[NSApplication sharedApplication] windows] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSWindow* win, NSDictionary *bindings) {
|
||||||
|
+ return [win sharingType] == NSWindowSharingNone;
|
||||||
|
+ }]] enumerateObjectsUsingBlock:^(NSWindow* win, NSUInteger idx, BOOL *stop) {
|
||||||
|
+ [exclude_ns_windows addObject:@([win windowNumber])];
|
||||||
|
+ }];
|
||||||
|
+ picker.defaultConfiguration.excludedWindowIDs = exclude_ns_windows;
|
||||||
|
+ [picker present];
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
auto content_callback = base::BindPostTask(
|
||||||
|
device_task_runner_,
|
||||||
|
base::BindRepeating(
|
||||||
|
@@ -470,6 +564,8 @@ void ResetStreamTo(SCWindow* window) override {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
+ static int active_streams_;
|
||||||
|
+
|
||||||
|
const DesktopMediaID source_;
|
||||||
|
const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
|
||||||
|
|
||||||
|
@@ -498,6 +594,8 @@ void ResetStreamTo(SCWindow* window) override {
|
||||||
|
base::WeakPtrFactory<ScreenCaptureKitDeviceMac> weak_factory_{this};
|
||||||
|
};
|
||||||
|
|
||||||
|
+int ScreenCaptureKitDeviceMac::active_streams_ = 0;
|
||||||
|
+
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<media::VideoCaptureDevice> CreateScreenCaptureKitDeviceMac(
|
||||||
@@ -489,6 +489,13 @@ gin::Handle<DesktopCapturer> DesktopCapturer::Create(v8::Isolate* isolate) {
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
#if !BUILDFLAG(IS_MAC)
|
||||||
|
bool DesktopCapturer::IsDisplayMediaSystemPickerAvailable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
gin::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
|
gin::ObjectTemplateBuilder DesktopCapturer::GetObjectTemplateBuilder(
|
||||||
v8::Isolate* isolate) {
|
v8::Isolate* isolate) {
|
||||||
return gin::Wrappable<DesktopCapturer>::GetObjectTemplateBuilder(isolate)
|
return gin::Wrappable<DesktopCapturer>::GetObjectTemplateBuilder(isolate)
|
||||||
@@ -510,6 +517,9 @@ void Initialize(v8::Local<v8::Object> exports,
|
|||||||
gin_helper::Dictionary dict(context->GetIsolate(), exports);
|
gin_helper::Dictionary dict(context->GetIsolate(), exports);
|
||||||
dict.SetMethod("createDesktopCapturer",
|
dict.SetMethod("createDesktopCapturer",
|
||||||
&electron::api::DesktopCapturer::Create);
|
&electron::api::DesktopCapturer::Create);
|
||||||
|
dict.SetMethod(
|
||||||
|
"isDisplayMediaSystemPickerAvailable",
|
||||||
|
&electron::api::DesktopCapturer::IsDisplayMediaSystemPickerAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class DesktopCapturer : public gin::Wrappable<DesktopCapturer>,
|
|||||||
|
|
||||||
static gin::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
static gin::Handle<DesktopCapturer> Create(v8::Isolate* isolate);
|
||||||
|
|
||||||
|
static bool IsDisplayMediaSystemPickerAvailable();
|
||||||
|
|
||||||
void StartHandling(bool capture_window,
|
void StartHandling(bool capture_window,
|
||||||
bool capture_screen,
|
bool capture_screen,
|
||||||
const gfx::Size& thumbnail_size,
|
const gfx::Size& thumbnail_size,
|
||||||
|
|||||||
17
shell/browser/api/electron_api_desktop_capturer_mac.mm
Normal file
17
shell/browser/api/electron_api_desktop_capturer_mac.mm
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) 2024 Salesforce, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "shell/browser/api/electron_api_desktop_capturer.h"
|
||||||
|
|
||||||
|
namespace electron::api {
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool DesktopCapturer::IsDisplayMediaSystemPickerAvailable() {
|
||||||
|
if (@available(macOS 14.4, *)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace electron::api
|
||||||
@@ -58,6 +58,11 @@ void InitializeFeatureList() {
|
|||||||
if (platform_specific_enable_features.size() > 0) {
|
if (platform_specific_enable_features.size() > 0) {
|
||||||
enable_features += std::string(",") + platform_specific_enable_features;
|
enable_features += std::string(",") + platform_specific_enable_features;
|
||||||
}
|
}
|
||||||
|
std::string platform_specific_disable_features =
|
||||||
|
DisablePlatformSpecificFeatures();
|
||||||
|
if (platform_specific_disable_features.size() > 0) {
|
||||||
|
disable_features += std::string(",") + platform_specific_disable_features;
|
||||||
|
}
|
||||||
base::FeatureList::InitInstance(enable_features, disable_features);
|
base::FeatureList::InitInstance(enable_features, disable_features);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +78,9 @@ void InitializeFieldTrials() {
|
|||||||
std::string EnablePlatformSpecificFeatures() {
|
std::string EnablePlatformSpecificFeatures() {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
std::string DisablePlatformSpecificFeatures() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace electron {
|
|||||||
void InitializeFeatureList();
|
void InitializeFeatureList();
|
||||||
void InitializeFieldTrials();
|
void InitializeFieldTrials();
|
||||||
std::string EnablePlatformSpecificFeatures();
|
std::string EnablePlatformSpecificFeatures();
|
||||||
|
std::string DisablePlatformSpecificFeatures();
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|
||||||
#endif // ELECTRON_SHELL_BROWSER_FEATURE_LIST_H_
|
#endif // ELECTRON_SHELL_BROWSER_FEATURE_LIST_H_
|
||||||
|
|||||||
@@ -31,4 +31,13 @@ std::string EnablePlatformSpecificFeatures() {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DisablePlatformSpecificFeatures() {
|
||||||
|
if (@available(macOS 14.4, *)) {
|
||||||
|
// Required to stop timing out getDisplayMedia while waiting for
|
||||||
|
// the user to select a window with the picker
|
||||||
|
return "TimeoutHangingVideoCaptureStarts";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace electron
|
} // namespace electron
|
||||||
|
|||||||
2
typings/internal-ambient.d.ts
vendored
2
typings/internal-ambient.d.ts
vendored
@@ -213,7 +213,7 @@ declare namespace NodeJS {
|
|||||||
_linkedBinding(name: 'electron_browser_app'): { app: Electron.App, App: Function };
|
_linkedBinding(name: 'electron_browser_app'): { app: Electron.App, App: Function };
|
||||||
_linkedBinding(name: 'electron_browser_auto_updater'): { autoUpdater: Electron.AutoUpdater };
|
_linkedBinding(name: 'electron_browser_auto_updater'): { autoUpdater: Electron.AutoUpdater };
|
||||||
_linkedBinding(name: 'electron_browser_crash_reporter'): CrashReporterBinding;
|
_linkedBinding(name: 'electron_browser_crash_reporter'): CrashReporterBinding;
|
||||||
_linkedBinding(name: 'electron_browser_desktop_capturer'): { createDesktopCapturer(): ElectronInternal.DesktopCapturer; };
|
_linkedBinding(name: 'electron_browser_desktop_capturer'): { createDesktopCapturer(): ElectronInternal.DesktopCapturer; isDisplayMediaSystemPickerAvailable(): boolean; };
|
||||||
_linkedBinding(name: 'electron_browser_event_emitter'): { setEventEmitterPrototype(prototype: Object): void; };
|
_linkedBinding(name: 'electron_browser_event_emitter'): { setEventEmitterPrototype(prototype: Object): void; };
|
||||||
_linkedBinding(name: 'electron_browser_global_shortcut'): { globalShortcut: Electron.GlobalShortcut };
|
_linkedBinding(name: 'electron_browser_global_shortcut'): { globalShortcut: Electron.GlobalShortcut };
|
||||||
_linkedBinding(name: 'electron_browser_image_view'): { ImageView: any };
|
_linkedBinding(name: 'electron_browser_image_view'): { ImageView: any };
|
||||||
|
|||||||
Reference in New Issue
Block a user