From cfdcf48e1b2cccc9cebe64d84d159713b0832e86 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Thu, 25 Jul 2024 11:17:37 +0200 Subject: [PATCH] fix: desktopCapturer breaks BrowserWindow resizable on macOS (#43013) * fix: desktopCapturer breaks BrowserWindow resizable on macOS * test: oops fix showing --- lib/browser/api/desktop-capturer.ts | 19 +++++++++++++++++++ shell/browser/feature_list_mac.mm | 2 +- spec/api-desktop-capturer-spec.ts | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lib/browser/api/desktop-capturer.ts b/lib/browser/api/desktop-capturer.ts index fc27bbb86c63..6b9720510f52 100644 --- a/lib/browser/api/desktop-capturer.ts +++ b/lib/browser/api/desktop-capturer.ts @@ -1,3 +1,4 @@ +import { BrowserWindow } from 'electron/main'; const { createDesktopCapturer } = process._linkedBinding('electron_browser_desktop_capturer'); const deepEqual = (a: ElectronInternal.GetSourcesOptions, b: ElectronInternal.GetSourcesOptions) => JSON.stringify(a) === JSON.stringify(b); @@ -15,6 +16,16 @@ function isValid (options: Electron.SourcesOptions) { export async function getSources (args: Electron.SourcesOptions) { if (!isValid(args)) throw new Error('Invalid options'); + const resizableValues = new Map(); + if (process.platform === 'darwin') { + // Fix for bug in ScreenCaptureKit that modifies a window's styleMask the first time + // it captures a non-resizable window. We record each non-resizable window's styleMask, + // and we restore modified styleMasks later, after the screen capture. + for (const win of BrowserWindow.getAllWindows()) { + resizableValues.set([win.id], win.resizable); + } + } + const captureWindow = args.types.includes('window'); const captureScreen = args.types.includes('screen'); @@ -44,6 +55,14 @@ export async function getSources (args: Electron.SourcesOptions) { delete capturer._onerror; delete capturer._onfinished; capturer = null; + + if (process.platform === 'darwin') { + for (const win of BrowserWindow.getAllWindows()) { + if (resizableValues.has(win.id)) { + win.resizable = resizableValues.get(win.id); + } + }; + } } // Remove from currentlyRunning once we resolve or reject currentlyRunning = currentlyRunning.filter(running => running.options !== options); diff --git a/shell/browser/feature_list_mac.mm b/shell/browser/feature_list_mac.mm index c3a01fc2be6c..cde16007e951 100644 --- a/shell/browser/feature_list_mac.mm +++ b/shell/browser/feature_list_mac.mm @@ -22,7 +22,7 @@ std::string EnablePlatformSpecificFeatures() { // kThumbnailCapturerMac, // chrome/browser/media/webrtc/thumbnail_capturer_mac.mm #if DCHECK_IS_ON() - return ""; + return "ScreenCaptureKitPickerScreen,ScreenCaptureKitStreamPickerSonoma"; #else return "ScreenCaptureKitPickerScreen,ScreenCaptureKitStreamPickerSonoma," "ThumbnailCapturerMac:capture_mode/sc_screenshot_manager"; diff --git a/spec/api-desktop-capturer-spec.ts b/spec/api-desktop-capturer-spec.ts index b7729ac74803..5c6eadf0d1b2 100644 --- a/spec/api-desktop-capturer-spec.ts +++ b/spec/api-desktop-capturer-spec.ts @@ -148,6 +148,20 @@ ifdescribe(!process.arch.includes('arm') && process.platform !== 'win32')('deskt } }); + // Regression test - see https://github.com/electron/electron/issues/43002 + it('does not affect window resizable state', async () => { + w.resizable = false; + + const wShown = once(w, 'show'); + w.show(); + await wShown; + + const sources = await desktopCapturer.getSources({ types: ['window', 'screen'] }); + expect(sources).to.be.an('array').that.is.not.empty(); + + expect(w.resizable).to.be.false(); + }); + it('moveAbove should move the window at the requested place', async () => { // DesktopCapturer.getSources() is guaranteed to return in the correct // z-order from foreground to background.