From 32920af4b78213b4479f20796e989d4cc56ce9db Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 13 Feb 2024 20:46:51 -0800 Subject: [PATCH] fix: add capability to use ScreenCaptureKit for thumbnail generation (#41328) This aligns us with Chromiums flags / capabilities in regards to using SCK for everything. Currently on 14.4 Electron apps will pop warnings for usage of deprecated APIs. With this change and a few "enable-features" toggles. `--enable-features="ScreenCaptureKitMac,ScreenCaptureKitStreamPickerSonoma,ThumbnailCapturerMac:capture_mode/sc_screenshot_manager"` As Chromium enables these by default Electron will inherit those changes, apps wishing to skip ahead can apply these flags early. --- chromium_src/BUILD.gn | 2 + patches/chromium/.patches | 1 + ...ing_first_no-op_refresh_in_thumb_cap.patch | 38 +++++++++++++ .../api/electron_api_desktop_capturer.cc | 55 +++++++++++++++---- 4 files changed, 84 insertions(+), 12 deletions(-) create mode 100644 patches/chromium/fix_add_support_for_skipping_first_no-op_refresh_in_thumb_cap.patch diff --git a/chromium_src/BUILD.gn b/chromium_src/BUILD.gn index f10ffd22ef69..3ce8735e562f 100644 --- a/chromium_src/BUILD.gn +++ b/chromium_src/BUILD.gn @@ -242,6 +242,8 @@ static_library("chrome") { "//chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm", "//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.h", "//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm", + "//chrome/browser/media/webrtc/thumbnail_capturer_mac.h", + "//chrome/browser/media/webrtc/thumbnail_capturer_mac.mm", "//chrome/browser/media/webrtc/window_icon_util_mac.mm", "//chrome/browser/platform_util_mac.mm", "//chrome/browser/process_singleton_mac.mm", diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 7b76ce5b0374..0310c5a16204 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -128,3 +128,4 @@ feat_allow_code_cache_in_custom_schemes.patch build_run_reclient_cfg_generator_after_chrome.patch fix_suppress_clang_-wimplicit-const-int-float-conversion_in.patch fix_getcursorscreenpoint_wrongly_returns_0_0.patch +fix_add_support_for_skipping_first_no-op_refresh_in_thumb_cap.patch diff --git a/patches/chromium/fix_add_support_for_skipping_first_no-op_refresh_in_thumb_cap.patch b/patches/chromium/fix_add_support_for_skipping_first_no-op_refresh_in_thumb_cap.patch new file mode 100644 index 000000000000..93736650a495 --- /dev/null +++ b/patches/chromium/fix_add_support_for_skipping_first_no-op_refresh_in_thumb_cap.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samuel Attard +Date: Tue, 13 Feb 2024 17:40:15 -0800 +Subject: fix: add support for skipping first no-op refresh in thumb cap + +Fixes a bug in the SCK thumbnail capturer, will be reported upstream for a hopefully +less hacky fix. + +diff --git a/chrome/browser/media/webrtc/desktop_media_list.h b/chrome/browser/media/webrtc/desktop_media_list.h +index 0c6fccf16a11bbaff10115308e4b489490e5d3e6..3b541e6830ca902cf45483a3193376c0e559185e 100644 +--- a/chrome/browser/media/webrtc/desktop_media_list.h ++++ b/chrome/browser/media/webrtc/desktop_media_list.h +@@ -143,6 +143,8 @@ class DesktopMediaList { + // important when IsSourceDelegated() returns true, as it helps to notify the + // delegated source list when it should be hidden. + virtual void HideList() = 0; ++ ++ bool skip_next_refresh_ = false; + }; + + #endif // CHROME_BROWSER_MEDIA_WEBRTC_DESKTOP_MEDIA_LIST_H_ +diff --git a/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chrome/browser/media/webrtc/desktop_media_list_base.cc +index 780927301744ea7312f230cec76a24a33d71f767..321d3ff46cbb67e880d5414d83a199fb16457038 100644 +--- a/chrome/browser/media/webrtc/desktop_media_list_base.cc ++++ b/chrome/browser/media/webrtc/desktop_media_list_base.cc +@@ -230,7 +230,11 @@ uint32_t DesktopMediaListBase::GetImageHash(const gfx::Image& image) { + void DesktopMediaListBase::OnRefreshComplete() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(refresh_callback_); +- std::move(refresh_callback_).Run(); ++ if (skip_next_refresh_) { ++ skip_next_refresh_ = false; ++ } else { ++ std::move(refresh_callback_).Run(); ++ } + } + + void DesktopMediaListBase::ScheduleNextRefresh() { diff --git a/shell/browser/api/electron_api_desktop_capturer.cc b/shell/browser/api/electron_api_desktop_capturer.cc index 87049e8544fc..a99ec520c0ae 100644 --- a/shell/browser/api/electron_api_desktop_capturer.cc +++ b/shell/browser/api/electron_api_desktop_capturer.cc @@ -14,6 +14,7 @@ #include "base/threading/thread_restrictions.h" #include "chrome/browser/media/webrtc/desktop_capturer_wrapper.h" #include "chrome/browser/media/webrtc/desktop_media_list.h" +#include "chrome/browser/media/webrtc/thumbnail_capturer_mac.h" #include "chrome/browser/media/webrtc/window_icon_util.h" #include "content/public/browser/desktop_capture.h" #include "gin/object_template_builder.h" @@ -136,6 +137,38 @@ base::flat_map MonitorAtomIdToDisplayId() { } #endif +namespace { + +std::unique_ptr MakeWindowCapturer() { +#if BUILDFLAG(IS_MAC) + if (ShouldUseThumbnailCapturerMac(DesktopMediaList::Type::kWindow)) { + return CreateThumbnailCapturerMac(DesktopMediaList::Type::kWindow); + } +#endif // BUILDFLAG(IS_MAC) + + std::unique_ptr window_capturer = + content::desktop_capture::CreateWindowCapturer(); + return window_capturer ? std::make_unique( + std::move(window_capturer)) + : nullptr; +} + +std::unique_ptr MakeScreenCapturer() { +#if BUILDFLAG(IS_MAC) + if (ShouldUseThumbnailCapturerMac(DesktopMediaList::Type::kScreen)) { + return CreateThumbnailCapturerMac(DesktopMediaList::Type::kScreen); + } +#endif // BUILDFLAG(IS_MAC) + + std::unique_ptr screen_capturer = + content::desktop_capture::CreateScreenCapturer(); + return screen_capturer ? std::make_unique( + std::move(screen_capturer)) + : nullptr; +} + +} // namespace + namespace gin { template <> @@ -265,16 +298,15 @@ void DesktopCapturer::StartHandling(bool capture_window, // Initialize the source list. // Apply the new thumbnail size and restart capture. if (capture_window) { - std::unique_ptr window_capturer = - content::desktop_capture::CreateWindowCapturer(); - auto capturer = window_capturer - ? std::make_unique( - std::move(window_capturer)) - : nullptr; + auto capturer = MakeWindowCapturer(); if (capturer) { window_capturer_ = std::make_unique( DesktopMediaList::Type::kWindow, std::move(capturer)); window_capturer_->SetThumbnailSize(thumbnail_size); +#if BUILDFLAG(IS_MAC) + window_capturer_->skip_next_refresh_ = + ShouldUseThumbnailCapturerMac(DesktopMediaList::Type::kWindow); +#endif OnceCallback update_callback = base::BindOnce( &DesktopCapturer::UpdateSourcesList, weak_ptr_factory_.GetWeakPtr(), @@ -295,16 +327,15 @@ void DesktopCapturer::StartHandling(bool capture_window, } if (capture_screen) { - std::unique_ptr screen_capturer = - content::desktop_capture::CreateScreenCapturer(); - auto capturer = screen_capturer - ? std::make_unique( - std::move(screen_capturer)) - : nullptr; + auto capturer = MakeScreenCapturer(); if (capturer) { screen_capturer_ = std::make_unique( DesktopMediaList::Type::kScreen, std::move(capturer)); screen_capturer_->SetThumbnailSize(thumbnail_size); +#if BUILDFLAG(IS_MAC) + screen_capturer_->skip_next_refresh_ = + ShouldUseThumbnailCapturerMac(DesktopMediaList::Type::kScreen); +#endif OnceCallback update_callback = base::BindOnce( &DesktopCapturer::UpdateSourcesList, weak_ptr_factory_.GetWeakPtr(),