Implement handling for MS PowerPoint Presentation Mode.
* Introduce a FullScreenWindowDetector to manage routines for updating the list of sources being application agnostic, inspired by FullScreenChromeWindowDetector. * Introduce a FullScreenApplicationHandler to make a decision about changing window to share in application specific way, inspired by FullScreenChromeWindowDetector. * Remove FullScreenChromeWindowDetector as redundant. * Add FullScreenApplicationHandler for MS PowerPoint and Apple Keynote on MacOS. * Add FullScreenApplicationHandler for MS PowerPoint on Windows. Bug: webrtc:3852 Change-Id: I06507d929308e85b882b2f8210a025afef7f26a9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/156020 Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Jamie Walch <jamiewalch@chromium.org> Reviewed-by: Justin Uberti <juberti@webrtc.org> Reviewed-by: Wez <wez@google.com> Cr-Commit-Position: refs/heads/master@{#29993}
This commit is contained in:
parent
831ce5f171
commit
b588353543
1
AUTHORS
1
AUTHORS
@ -101,6 +101,7 @@ NVIDIA Corporation <*@nvidia.com>
|
|||||||
Opera Software ASA <*@opera.com>
|
Opera Software ASA <*@opera.com>
|
||||||
Optical Tone Ltd <*@opticaltone.com>
|
Optical Tone Ltd <*@opticaltone.com>
|
||||||
Pengutronix e.K. <*@pengutronix.de>
|
Pengutronix e.K. <*@pengutronix.de>
|
||||||
|
RingCentral, Inc. <*@ringcentral.com>
|
||||||
Sinch AB <*@sinch.com>
|
Sinch AB <*@sinch.com>
|
||||||
struktur AG <*@struktur.de>
|
struktur AG <*@struktur.de>
|
||||||
Telenor Digital AS <*@telenor.com>
|
Telenor Digital AS <*@telenor.com>
|
||||||
|
|||||||
@ -300,6 +300,10 @@ rtc_library("desktop_capture_generic") {
|
|||||||
"fake_desktop_capturer.h",
|
"fake_desktop_capturer.h",
|
||||||
"fallback_desktop_capturer_wrapper.cc",
|
"fallback_desktop_capturer_wrapper.cc",
|
||||||
"fallback_desktop_capturer_wrapper.h",
|
"fallback_desktop_capturer_wrapper.h",
|
||||||
|
"full_screen_application_handler.cc",
|
||||||
|
"full_screen_application_handler.h",
|
||||||
|
"full_screen_window_detector.cc",
|
||||||
|
"full_screen_window_detector.h",
|
||||||
"mouse_cursor.cc",
|
"mouse_cursor.cc",
|
||||||
"mouse_cursor.h",
|
"mouse_cursor.h",
|
||||||
"mouse_cursor_monitor.h",
|
"mouse_cursor_monitor.h",
|
||||||
@ -319,8 +323,8 @@ rtc_library("desktop_capture_generic") {
|
|||||||
"mac/desktop_configuration.h",
|
"mac/desktop_configuration.h",
|
||||||
"mac/desktop_configuration_monitor.cc",
|
"mac/desktop_configuration_monitor.cc",
|
||||||
"mac/desktop_configuration_monitor.h",
|
"mac/desktop_configuration_monitor.h",
|
||||||
"mac/full_screen_chrome_window_detector.cc",
|
"mac/full_screen_mac_application_handler.cc",
|
||||||
"mac/full_screen_chrome_window_detector.h",
|
"mac/full_screen_mac_application_handler.h",
|
||||||
"mac/window_list_utils.cc",
|
"mac/window_list_utils.cc",
|
||||||
"mac/window_list_utils.h",
|
"mac/window_list_utils.h",
|
||||||
]
|
]
|
||||||
@ -431,6 +435,8 @@ rtc_library("desktop_capture_generic") {
|
|||||||
"win/dxgi_texture_mapping.h",
|
"win/dxgi_texture_mapping.h",
|
||||||
"win/dxgi_texture_staging.cc",
|
"win/dxgi_texture_staging.cc",
|
||||||
"win/dxgi_texture_staging.h",
|
"win/dxgi_texture_staging.h",
|
||||||
|
"win/full_screen_win_application_handler.cc",
|
||||||
|
"win/full_screen_win_application_handler.h",
|
||||||
"win/scoped_gdi_object.h",
|
"win/scoped_gdi_object.h",
|
||||||
"win/scoped_thread_desktop.cc",
|
"win/scoped_thread_desktop.cc",
|
||||||
"win/scoped_thread_desktop.h",
|
"win/scoped_thread_desktop.h",
|
||||||
@ -470,6 +476,7 @@ rtc_library("desktop_capture_generic") {
|
|||||||
"../../system_wrappers:cpu_features_api",
|
"../../system_wrappers:cpu_features_api",
|
||||||
"../../system_wrappers:metrics",
|
"../../system_wrappers:metrics",
|
||||||
"//third_party/abseil-cpp/absl/memory",
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (build_with_mozilla) {
|
if (build_with_mozilla) {
|
||||||
|
|||||||
@ -68,6 +68,7 @@ class RTC_EXPORT CroppingWindowCapturer : public DesktopCapturer,
|
|||||||
|
|
||||||
WindowId selected_window() const { return selected_window_; }
|
WindowId selected_window() const { return selected_window_; }
|
||||||
WindowId excluded_window() const { return excluded_window_; }
|
WindowId excluded_window() const { return excluded_window_; }
|
||||||
|
DesktopCapturer* window_capturer() const { return window_capturer_.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DesktopCaptureOptions options_;
|
DesktopCaptureOptions options_;
|
||||||
|
|||||||
@ -98,26 +98,53 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
|
|||||||
|
|
||||||
class CroppingWindowCapturerWin : public CroppingWindowCapturer {
|
class CroppingWindowCapturerWin : public CroppingWindowCapturer {
|
||||||
public:
|
public:
|
||||||
CroppingWindowCapturerWin(const DesktopCaptureOptions& options)
|
explicit CroppingWindowCapturerWin(const DesktopCaptureOptions& options)
|
||||||
: CroppingWindowCapturer(options) {}
|
: CroppingWindowCapturer(options),
|
||||||
|
full_screen_window_detector_(options.full_screen_window_detector()) {}
|
||||||
|
|
||||||
|
void CaptureFrame() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ShouldUseScreenCapturer() override;
|
bool ShouldUseScreenCapturer() override;
|
||||||
DesktopRect GetWindowRectInVirtualScreen() override;
|
DesktopRect GetWindowRectInVirtualScreen() override;
|
||||||
|
|
||||||
|
// Returns either selected by user sourceId or sourceId provided by
|
||||||
|
// FullScreenWindowDetector
|
||||||
|
WindowId GetWindowToCapture() const;
|
||||||
|
|
||||||
// The region from GetWindowRgn in the desktop coordinate if the region is
|
// The region from GetWindowRgn in the desktop coordinate if the region is
|
||||||
// rectangular, or the rect from GetWindowRect if the region is not set.
|
// rectangular, or the rect from GetWindowRect if the region is not set.
|
||||||
DesktopRect window_region_rect_;
|
DesktopRect window_region_rect_;
|
||||||
|
|
||||||
WindowCaptureHelperWin window_capture_helper_;
|
WindowCaptureHelperWin window_capture_helper_;
|
||||||
|
|
||||||
|
rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void CroppingWindowCapturerWin::CaptureFrame() {
|
||||||
|
DesktopCapturer* win_capturer = window_capturer();
|
||||||
|
if (win_capturer) {
|
||||||
|
// Update the list of available sources and override source to capture if
|
||||||
|
// FullScreenWindowDetector returns not zero
|
||||||
|
if (full_screen_window_detector_) {
|
||||||
|
full_screen_window_detector_->UpdateWindowListIfNeeded(
|
||||||
|
selected_window(),
|
||||||
|
[win_capturer](DesktopCapturer::SourceList* sources) {
|
||||||
|
return win_capturer->GetSourceList(sources);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
win_capturer->SelectSource(GetWindowToCapture());
|
||||||
|
}
|
||||||
|
|
||||||
|
CroppingWindowCapturer::CaptureFrame();
|
||||||
|
}
|
||||||
|
|
||||||
bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
|
bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
|
||||||
if (!rtc::IsWindows8OrLater() && window_capture_helper_.IsAeroEnabled()) {
|
if (!rtc::IsWindows8OrLater() && window_capture_helper_.IsAeroEnabled()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HWND selected = reinterpret_cast<HWND>(selected_window());
|
const HWND selected = reinterpret_cast<HWND>(GetWindowToCapture());
|
||||||
// Check if the window is visible on current desktop.
|
// Check if the window is visible on current desktop.
|
||||||
if (!window_capture_helper_.IsWindowVisibleOnCurrentDesktop(selected)) {
|
if (!window_capture_helper_.IsWindowVisibleOnCurrentDesktop(selected)) {
|
||||||
return false;
|
return false;
|
||||||
@ -207,7 +234,7 @@ DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() {
|
|||||||
TRACE_EVENT0("webrtc",
|
TRACE_EVENT0("webrtc",
|
||||||
"CroppingWindowCapturerWin::GetWindowRectInVirtualScreen");
|
"CroppingWindowCapturerWin::GetWindowRectInVirtualScreen");
|
||||||
DesktopRect window_rect;
|
DesktopRect window_rect;
|
||||||
HWND hwnd = reinterpret_cast<HWND>(selected_window());
|
HWND hwnd = reinterpret_cast<HWND>(GetWindowToCapture());
|
||||||
if (!GetCroppedWindowRect(hwnd, /*avoid_cropping_border*/ false, &window_rect,
|
if (!GetCroppedWindowRect(hwnd, /*avoid_cropping_border*/ false, &window_rect,
|
||||||
/*original_rect*/ nullptr)) {
|
/*original_rect*/ nullptr)) {
|
||||||
RTC_LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
|
RTC_LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
|
||||||
@ -222,6 +249,15 @@ DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() {
|
|||||||
return window_rect;
|
return window_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowId CroppingWindowCapturerWin::GetWindowToCapture() const {
|
||||||
|
const auto selected_source = selected_window();
|
||||||
|
const auto full_screen_source =
|
||||||
|
full_screen_window_detector_
|
||||||
|
? full_screen_window_detector_->FindFullScreenWindow(selected_source)
|
||||||
|
: 0;
|
||||||
|
return full_screen_source ? full_screen_source : selected_source;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|||||||
@ -9,6 +9,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "modules/desktop_capture/desktop_capture_options.h"
|
#include "modules/desktop_capture/desktop_capture_options.h"
|
||||||
|
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||||
|
#include "modules/desktop_capture/mac/full_screen_mac_application_handler.h"
|
||||||
|
#elif defined(WEBRTC_WIN)
|
||||||
|
#include "modules/desktop_capture/win/full_screen_win_application_handler.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -32,8 +37,11 @@ DesktopCaptureOptions DesktopCaptureOptions::CreateDefault() {
|
|||||||
#endif
|
#endif
|
||||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||||
result.set_configuration_monitor(new DesktopConfigurationMonitor());
|
result.set_configuration_monitor(new DesktopConfigurationMonitor());
|
||||||
result.set_full_screen_chrome_window_detector(
|
result.set_full_screen_window_detector(
|
||||||
new FullScreenChromeWindowDetector());
|
new FullScreenWindowDetector(CreateFullScreenMacApplicationHandler));
|
||||||
|
#elif defined(WEBRTC_WIN)
|
||||||
|
result.set_full_screen_window_detector(
|
||||||
|
new FullScreenWindowDetector(CreateFullScreenWinApplicationHandler));
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,9 +19,10 @@
|
|||||||
|
|
||||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||||
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
||||||
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "modules/desktop_capture/full_screen_window_detector.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
// An object that stores initialization parameters for screen and window
|
// An object that stores initialization parameters for screen and window
|
||||||
@ -62,21 +63,18 @@ class RTC_EXPORT DesktopCaptureOptions {
|
|||||||
configuration_monitor_ = m;
|
configuration_monitor_ = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(zijiehe): Instead of FullScreenChromeWindowDetector, provide a
|
|
||||||
// FullScreenWindowDetector for external consumers to detect the target
|
|
||||||
// fullscreen window.
|
|
||||||
FullScreenChromeWindowDetector* full_screen_chrome_window_detector() const {
|
|
||||||
return full_screen_window_detector_;
|
|
||||||
}
|
|
||||||
void set_full_screen_chrome_window_detector(
|
|
||||||
rtc::scoped_refptr<FullScreenChromeWindowDetector> detector) {
|
|
||||||
full_screen_window_detector_ = detector;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool allow_iosurface() const { return allow_iosurface_; }
|
bool allow_iosurface() const { return allow_iosurface_; }
|
||||||
void set_allow_iosurface(bool allow) { allow_iosurface_ = allow; }
|
void set_allow_iosurface(bool allow) { allow_iosurface_ = allow; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FullScreenWindowDetector* full_screen_window_detector() const {
|
||||||
|
return full_screen_window_detector_;
|
||||||
|
}
|
||||||
|
void set_full_screen_window_detector(
|
||||||
|
rtc::scoped_refptr<FullScreenWindowDetector> detector) {
|
||||||
|
full_screen_window_detector_ = detector;
|
||||||
|
}
|
||||||
|
|
||||||
// Flag indicating that the capturer should use screen change notifications.
|
// Flag indicating that the capturer should use screen change notifications.
|
||||||
// Enables/disables use of XDAMAGE in the X11 capturer.
|
// Enables/disables use of XDAMAGE in the X11 capturer.
|
||||||
bool use_update_notifications() const { return use_update_notifications_; }
|
bool use_update_notifications() const { return use_update_notifications_; }
|
||||||
@ -142,11 +140,11 @@ class RTC_EXPORT DesktopCaptureOptions {
|
|||||||
|
|
||||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||||
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
|
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
|
||||||
rtc::scoped_refptr<FullScreenChromeWindowDetector>
|
|
||||||
full_screen_window_detector_;
|
|
||||||
bool allow_iosurface_ = false;
|
bool allow_iosurface_ = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector_;
|
||||||
|
|
||||||
#if defined(WEBRTC_WIN)
|
#if defined(WEBRTC_WIN)
|
||||||
bool allow_use_magnification_api_ = false;
|
bool allow_use_magnification_api_ = false;
|
||||||
bool allow_directx_capturer_ = false;
|
bool allow_directx_capturer_ = false;
|
||||||
|
|||||||
30
modules/desktop_capture/full_screen_application_handler.cc
Normal file
30
modules/desktop_capture/full_screen_application_handler.cc
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/desktop_capture/full_screen_application_handler.h"
|
||||||
|
#include "rtc_base/logging.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
FullScreenApplicationHandler::FullScreenApplicationHandler(
|
||||||
|
DesktopCapturer::SourceId sourceId)
|
||||||
|
: source_id_(sourceId) {}
|
||||||
|
|
||||||
|
DesktopCapturer::SourceId FullScreenApplicationHandler::FindFullScreenWindow(
|
||||||
|
const DesktopCapturer::SourceList&,
|
||||||
|
int64_t) const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesktopCapturer::SourceId FullScreenApplicationHandler::GetSourceId() const {
|
||||||
|
return source_id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
48
modules/desktop_capture/full_screen_application_handler.h
Normal file
48
modules/desktop_capture/full_screen_application_handler.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODULES_DESKTOP_CAPTURE_FULL_SCREEN_APPLICATION_HANDLER_H_
|
||||||
|
#define MODULES_DESKTOP_CAPTURE_FULL_SCREEN_APPLICATION_HANDLER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "modules/desktop_capture/desktop_capturer.h"
|
||||||
|
#include "rtc_base/constructor_magic.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// Base class for application specific handler to check criteria for switch to
|
||||||
|
// full-screen mode and find if possible the full-screen window to share.
|
||||||
|
// Supposed to be created and owned by platform specific
|
||||||
|
// FullScreenWindowDetector.
|
||||||
|
class FullScreenApplicationHandler {
|
||||||
|
public:
|
||||||
|
virtual ~FullScreenApplicationHandler() {}
|
||||||
|
|
||||||
|
explicit FullScreenApplicationHandler(DesktopCapturer::SourceId sourceId);
|
||||||
|
|
||||||
|
// Returns the full-screen window in place of the original window if all the
|
||||||
|
// criteria are met, or 0 if no such window found.
|
||||||
|
virtual DesktopCapturer::SourceId FindFullScreenWindow(
|
||||||
|
const DesktopCapturer::SourceList& window_list,
|
||||||
|
int64_t timestamp) const;
|
||||||
|
|
||||||
|
// Returns source id of original window associated with
|
||||||
|
// FullScreenApplicationHandler
|
||||||
|
DesktopCapturer::SourceId GetSourceId() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const DesktopCapturer::SourceId source_id_;
|
||||||
|
|
||||||
|
RTC_DISALLOW_COPY_AND_ASSIGN(FullScreenApplicationHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_DESKTOP_CAPTURE_FULL_SCREEN_APPLICATION_HANDLER_H_
|
||||||
84
modules/desktop_capture/full_screen_window_detector.cc
Normal file
84
modules/desktop_capture/full_screen_window_detector.cc
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/desktop_capture/full_screen_window_detector.h"
|
||||||
|
#include "modules/desktop_capture/full_screen_application_handler.h"
|
||||||
|
#include "rtc_base/time_utils.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
FullScreenWindowDetector::FullScreenWindowDetector(
|
||||||
|
ApplicationHandlerFactory application_handler_factory)
|
||||||
|
: application_handler_factory_(application_handler_factory),
|
||||||
|
last_update_time_ms_(0),
|
||||||
|
previous_source_id_(0),
|
||||||
|
no_handler_source_id_(0) {}
|
||||||
|
|
||||||
|
DesktopCapturer::SourceId FullScreenWindowDetector::FindFullScreenWindow(
|
||||||
|
DesktopCapturer::SourceId original_source_id) {
|
||||||
|
if (app_handler_ == nullptr ||
|
||||||
|
app_handler_->GetSourceId() != original_source_id) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return app_handler_->FindFullScreenWindow(window_list_, last_update_time_ms_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullScreenWindowDetector::UpdateWindowListIfNeeded(
|
||||||
|
DesktopCapturer::SourceId original_source_id,
|
||||||
|
rtc::FunctionView<bool(DesktopCapturer::SourceList*)> get_sources) {
|
||||||
|
const bool skip_update = previous_source_id_ != original_source_id;
|
||||||
|
previous_source_id_ = original_source_id;
|
||||||
|
|
||||||
|
// Here is an attempt to avoid redundant creating application handler in case
|
||||||
|
// when an instance of WindowCapturer is used to generate a thumbnail to show
|
||||||
|
// in picker by calling SelectSource and CaptureFrame for every available
|
||||||
|
// source.
|
||||||
|
if (skip_update) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateApplicationHandlerIfNeeded(original_source_id);
|
||||||
|
if (app_handler_ == nullptr) {
|
||||||
|
// There is no FullScreenApplicationHandler specific for
|
||||||
|
// current application
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int64_t kUpdateIntervalMs = 500;
|
||||||
|
|
||||||
|
if ((rtc::TimeMillis() - last_update_time_ms_) <= kUpdateIntervalMs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesktopCapturer::SourceList window_list;
|
||||||
|
if (get_sources(&window_list)) {
|
||||||
|
last_update_time_ms_ = rtc::TimeMillis();
|
||||||
|
window_list_.swap(window_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullScreenWindowDetector::CreateApplicationHandlerIfNeeded(
|
||||||
|
DesktopCapturer::SourceId source_id) {
|
||||||
|
if (no_handler_source_id_ == source_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app_handler_ == nullptr || app_handler_->GetSourceId() != source_id) {
|
||||||
|
app_handler_ = application_handler_factory_
|
||||||
|
? application_handler_factory_(source_id)
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app_handler_ == nullptr) {
|
||||||
|
no_handler_source_id_ = source_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
80
modules/desktop_capture/full_screen_window_detector.h
Normal file
80
modules/desktop_capture/full_screen_window_detector.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODULES_DESKTOP_CAPTURE_FULL_SCREEN_WINDOW_DETECTOR_H_
|
||||||
|
#define MODULES_DESKTOP_CAPTURE_FULL_SCREEN_WINDOW_DETECTOR_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "api/function_view.h"
|
||||||
|
#include "api/ref_counted_base.h"
|
||||||
|
#include "api/scoped_refptr.h"
|
||||||
|
#include "modules/desktop_capture/desktop_capturer.h"
|
||||||
|
#include "modules/desktop_capture/full_screen_application_handler.h"
|
||||||
|
#include "rtc_base/constructor_magic.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// This is a way to handle switch to full-screen mode for application in some
|
||||||
|
// specific cases:
|
||||||
|
// - Chrome on MacOS creates a new window in full-screen mode to
|
||||||
|
// show a tab full-screen and minimizes the old window.
|
||||||
|
// - PowerPoint creates new windows in full-screen mode when user goes to
|
||||||
|
// presentation mode (Slide Show Window, Presentation Window).
|
||||||
|
//
|
||||||
|
// To continue capturing in these cases, we try to find the new full-screen
|
||||||
|
// window using criteria provided by application specific
|
||||||
|
// FullScreenApplicationHandler.
|
||||||
|
|
||||||
|
class FullScreenWindowDetector : public rtc::RefCountedBase {
|
||||||
|
public:
|
||||||
|
using ApplicationHandlerFactory =
|
||||||
|
std::function<std::unique_ptr<FullScreenApplicationHandler>(
|
||||||
|
DesktopCapturer::SourceId sourceId)>;
|
||||||
|
|
||||||
|
FullScreenWindowDetector(
|
||||||
|
ApplicationHandlerFactory application_handler_factory);
|
||||||
|
|
||||||
|
// Returns the full-screen window in place of the original window if all the
|
||||||
|
// criteria provided by FullScreenApplicationHandler are met, or 0 if no such
|
||||||
|
// window found.
|
||||||
|
DesktopCapturer::SourceId FindFullScreenWindow(
|
||||||
|
DesktopCapturer::SourceId original_source_id);
|
||||||
|
|
||||||
|
// The caller should call this function periodically, implementation will
|
||||||
|
// update internal state no often than twice per second
|
||||||
|
void UpdateWindowListIfNeeded(
|
||||||
|
DesktopCapturer::SourceId original_source_id,
|
||||||
|
rtc::FunctionView<bool(DesktopCapturer::SourceList*)> get_sources);
|
||||||
|
|
||||||
|
static rtc::scoped_refptr<FullScreenWindowDetector>
|
||||||
|
CreateFullScreenWindowDetector();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler> app_handler_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateApplicationHandlerIfNeeded(DesktopCapturer::SourceId source_id);
|
||||||
|
|
||||||
|
ApplicationHandlerFactory application_handler_factory_;
|
||||||
|
|
||||||
|
int64_t last_update_time_ms_;
|
||||||
|
DesktopCapturer::SourceId previous_source_id_;
|
||||||
|
|
||||||
|
// Save the source id when we fail to create an instance of
|
||||||
|
// CreateApplicationHandlerIfNeeded to avoid redundant attempt to do it again.
|
||||||
|
DesktopCapturer::SourceId no_handler_source_id_;
|
||||||
|
|
||||||
|
DesktopCapturer::SourceList window_list_;
|
||||||
|
RTC_DISALLOW_COPY_AND_ASSIGN(FullScreenWindowDetector);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_DESKTOP_CAPTURE_FULL_SCREEN_WINDOW_DETECTOR_H_
|
||||||
@ -1,135 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
|
||||||
|
|
||||||
#include <libproc.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "modules/desktop_capture/mac/window_list_utils.h"
|
|
||||||
#include "rtc_base/logging.h"
|
|
||||||
#include "rtc_base/time_utils.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const int64_t kUpdateIntervalMs = 500;
|
|
||||||
|
|
||||||
// Returns the window that is full-screen and has the same title and owner pid
|
|
||||||
// as the input window.
|
|
||||||
CGWindowID FindFullScreenWindowWithSamePidAndTitle(CGWindowID id) {
|
|
||||||
const int pid = GetWindowOwnerPid(id);
|
|
||||||
std::string title = GetWindowTitle(id);
|
|
||||||
if (title.empty())
|
|
||||||
return kCGNullWindowID;
|
|
||||||
|
|
||||||
// Only get on screen, non-desktop windows.
|
|
||||||
CFArrayRef window_array = CGWindowListCopyWindowInfo(
|
|
||||||
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
|
|
||||||
kCGNullWindowID);
|
|
||||||
if (!window_array)
|
|
||||||
return kCGNullWindowID;
|
|
||||||
|
|
||||||
CGWindowID full_screen_window = kCGNullWindowID;
|
|
||||||
|
|
||||||
MacDesktopConfiguration desktop_config = MacDesktopConfiguration::GetCurrent(
|
|
||||||
MacDesktopConfiguration::TopLeftOrigin);
|
|
||||||
|
|
||||||
// Check windows to make sure they have an id, title, and use window layer
|
|
||||||
// other than 0.
|
|
||||||
CFIndex count = CFArrayGetCount(window_array);
|
|
||||||
for (CFIndex i = 0; i < count; ++i) {
|
|
||||||
CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
|
|
||||||
CFArrayGetValueAtIndex(window_array, i));
|
|
||||||
|
|
||||||
CGWindowID window_id = GetWindowId(window);
|
|
||||||
if (window_id == kNullWindowId)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (GetWindowOwnerPid(window) != pid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string window_title = GetWindowTitle(window);
|
|
||||||
if (window_title != title)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (IsWindowFullScreen(desktop_config, window)) {
|
|
||||||
full_screen_window = window_id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CFRelease(window_array);
|
|
||||||
return full_screen_window;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsChromeWindow(CGWindowID id) {
|
|
||||||
int pid = GetWindowOwnerPid(id);
|
|
||||||
char buffer[PROC_PIDPATHINFO_MAXSIZE];
|
|
||||||
int path_length = proc_pidpath(pid, buffer, sizeof(buffer));
|
|
||||||
if (path_length <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char* last_slash = strrchr(buffer, '/');
|
|
||||||
std::string name(last_slash ? last_slash + 1 : buffer);
|
|
||||||
return name.find("Google Chrome") == 0 || name == "Chromium";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
FullScreenChromeWindowDetector::FullScreenChromeWindowDetector()
|
|
||||||
: last_update_time_ns_(0) {}
|
|
||||||
|
|
||||||
FullScreenChromeWindowDetector::~FullScreenChromeWindowDetector() {}
|
|
||||||
|
|
||||||
CGWindowID FullScreenChromeWindowDetector::FindFullScreenWindow(
|
|
||||||
CGWindowID original_window) {
|
|
||||||
if (!IsChromeWindow(original_window) || IsWindowOnScreen(original_window))
|
|
||||||
return kCGNullWindowID;
|
|
||||||
|
|
||||||
CGWindowID full_screen_window_id =
|
|
||||||
FindFullScreenWindowWithSamePidAndTitle(original_window);
|
|
||||||
|
|
||||||
if (full_screen_window_id == kCGNullWindowID)
|
|
||||||
return kCGNullWindowID;
|
|
||||||
|
|
||||||
for (const auto& window : previous_window_list_) {
|
|
||||||
if (static_cast<CGWindowID>(window.id) != full_screen_window_id)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
RTC_LOG(LS_WARNING) << "The full-screen window exists in the list.";
|
|
||||||
return kCGNullWindowID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return full_screen_window_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FullScreenChromeWindowDetector::UpdateWindowListIfNeeded(
|
|
||||||
CGWindowID original_window) {
|
|
||||||
if (IsChromeWindow(original_window) &&
|
|
||||||
(rtc::TimeNanos() - last_update_time_ns_) / rtc::kNumNanosecsPerMillisec >
|
|
||||||
kUpdateIntervalMs) {
|
|
||||||
previous_window_list_.clear();
|
|
||||||
previous_window_list_.swap(current_window_list_);
|
|
||||||
|
|
||||||
// No need to update the window list when the window is minimized.
|
|
||||||
if (!IsWindowOnScreen(original_window)) {
|
|
||||||
previous_window_list_.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetWindowList(¤t_window_list_, false);
|
|
||||||
last_update_time_ns_ = rtc::TimeNanos();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_CHROME_WINDOW_DETECTOR_H_
|
|
||||||
#define MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_CHROME_WINDOW_DETECTOR_H_
|
|
||||||
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
|
||||||
|
|
||||||
#include "api/ref_counted_base.h"
|
|
||||||
#include "modules/desktop_capture/desktop_capturer.h"
|
|
||||||
#include "rtc_base/constructor_magic.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
// This is a work around for the Chrome tab full-screen behavior: Chrome
|
|
||||||
// creates a new window in full-screen mode to show a tab full-screen and
|
|
||||||
// minimizes the old window. To continue capturing in this case, we try to
|
|
||||||
// find the new full-screen window using these criteria:
|
|
||||||
// 0. The original shared window is minimized.
|
|
||||||
// 1. The original shared window's owner application name is "Google Chrome".
|
|
||||||
// 2. The original window and the new window have the same title and owner
|
|
||||||
// pid.
|
|
||||||
// 3. The new window is full-screen.
|
|
||||||
// 4. The new window didn't exist at least 500 millisecond ago.
|
|
||||||
|
|
||||||
class FullScreenChromeWindowDetector : public rtc::RefCountedBase {
|
|
||||||
public:
|
|
||||||
FullScreenChromeWindowDetector();
|
|
||||||
|
|
||||||
// Returns the full-screen window in place of the original window if all the
|
|
||||||
// criteria are met, or kCGNullWindowID if no such window found.
|
|
||||||
CGWindowID FindFullScreenWindow(CGWindowID original_window);
|
|
||||||
|
|
||||||
// The caller should call this function periodically, no less than twice per
|
|
||||||
// second.
|
|
||||||
void UpdateWindowListIfNeeded(CGWindowID original_window);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
~FullScreenChromeWindowDetector() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// We cache the last two results of the window list, so
|
|
||||||
// |previous_window_list_| is taken at least 500ms before the next Capture()
|
|
||||||
// call. If we only save the last result, we may get false positive (i.e.
|
|
||||||
// full-screen window exists in the list) if Capture() is called too soon.
|
|
||||||
DesktopCapturer::SourceList current_window_list_;
|
|
||||||
DesktopCapturer::SourceList previous_window_list_;
|
|
||||||
int64_t last_update_time_ns_;
|
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(FullScreenChromeWindowDetector);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_CHROME_WINDOW_DETECTOR_H_
|
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/desktop_capture/mac/full_screen_mac_application_handler.h"
|
||||||
|
#include <libproc.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
#include "absl/strings/match.h"
|
||||||
|
#include "modules/desktop_capture/mac/window_list_utils.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static constexpr const char* kPowerPointSlideShowTitles[] = {
|
||||||
|
u8"PowerPoint-Bildschirmpräsentation",
|
||||||
|
u8"Προβολή παρουσίασης PowerPoint",
|
||||||
|
u8"PowerPoint スライド ショー",
|
||||||
|
u8"PowerPoint Slide Show",
|
||||||
|
u8"PowerPoint 幻灯片放映",
|
||||||
|
u8"Presentación de PowerPoint",
|
||||||
|
u8"PowerPoint-slideshow",
|
||||||
|
u8"Presentazione di PowerPoint",
|
||||||
|
u8"Prezentácia programu PowerPoint",
|
||||||
|
u8"Apresentação do PowerPoint",
|
||||||
|
u8"PowerPoint-bildspel",
|
||||||
|
u8"Prezentace v aplikaci PowerPoint",
|
||||||
|
u8"PowerPoint 슬라이드 쇼",
|
||||||
|
u8"PowerPoint-lysbildefremvisning",
|
||||||
|
u8"PowerPoint-vetítés",
|
||||||
|
u8"PowerPoint Slayt Gösterisi",
|
||||||
|
u8"Pokaz slajdów programu PowerPoint",
|
||||||
|
u8"PowerPoint 投影片放映",
|
||||||
|
u8"Демонстрация PowerPoint",
|
||||||
|
u8"Diaporama PowerPoint",
|
||||||
|
u8"PowerPoint-diaesitys",
|
||||||
|
u8"Peragaan Slide PowerPoint",
|
||||||
|
u8"PowerPoint-diavoorstelling",
|
||||||
|
u8"การนำเสนอสไลด์ PowerPoint",
|
||||||
|
u8"Apresentação de slides do PowerPoint",
|
||||||
|
u8"הצגת שקופיות של PowerPoint",
|
||||||
|
u8"عرض شرائح في PowerPoint"};
|
||||||
|
|
||||||
|
class FullScreenMacApplicationHandler : public FullScreenApplicationHandler {
|
||||||
|
public:
|
||||||
|
using TitlePredicate =
|
||||||
|
std::function<bool(const std::string&, const std::string&)>;
|
||||||
|
|
||||||
|
FullScreenMacApplicationHandler(DesktopCapturer::SourceId sourceId,
|
||||||
|
TitlePredicate title_predicate)
|
||||||
|
: FullScreenApplicationHandler(sourceId),
|
||||||
|
title_predicate_(title_predicate),
|
||||||
|
owner_pid_(GetWindowOwnerPid(sourceId)) {}
|
||||||
|
|
||||||
|
void InvalidateCacheIfNeeded(const DesktopCapturer::SourceList& source_list,
|
||||||
|
int64_t timestamp) const {
|
||||||
|
// Copy only sources with the same pid
|
||||||
|
if (timestamp != cache_timestamp_) {
|
||||||
|
cache_sources_.clear();
|
||||||
|
std::copy_if(source_list.begin(), source_list.end(),
|
||||||
|
std::back_inserter(cache_sources_),
|
||||||
|
[&](const DesktopCapturer::Source& src) {
|
||||||
|
return src.id != GetSourceId() &&
|
||||||
|
GetWindowOwnerPid(src.id) == owner_pid_;
|
||||||
|
});
|
||||||
|
cache_timestamp_ = timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowId FindFullScreenWindowWithSamePid(
|
||||||
|
const DesktopCapturer::SourceList& source_list,
|
||||||
|
int64_t timestamp) const {
|
||||||
|
InvalidateCacheIfNeeded(source_list, timestamp);
|
||||||
|
if (cache_sources_.empty())
|
||||||
|
return kCGNullWindowID;
|
||||||
|
|
||||||
|
const auto original_window = GetSourceId();
|
||||||
|
const std::string title = GetWindowTitle(original_window);
|
||||||
|
|
||||||
|
// We can ignore any windows with empty titles cause regardless type of
|
||||||
|
// application it's impossible to verify that full screen window and
|
||||||
|
// original window are related to the same document.
|
||||||
|
if (title.empty())
|
||||||
|
return kCGNullWindowID;
|
||||||
|
|
||||||
|
MacDesktopConfiguration desktop_config =
|
||||||
|
MacDesktopConfiguration::GetCurrent(
|
||||||
|
MacDesktopConfiguration::TopLeftOrigin);
|
||||||
|
|
||||||
|
const auto it = std::find_if(
|
||||||
|
cache_sources_.begin(), cache_sources_.end(),
|
||||||
|
[&](const DesktopCapturer::Source& src) {
|
||||||
|
const std::string window_title = GetWindowTitle(src.id);
|
||||||
|
|
||||||
|
if (window_title.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (title_predicate_ && !title_predicate_(title, window_title))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return IsWindowFullScreen(desktop_config, src.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
return it != cache_sources_.end() ? it->id : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DesktopCapturer::SourceId FindFullScreenWindow(
|
||||||
|
const DesktopCapturer::SourceList& source_list,
|
||||||
|
int64_t timestamp) const override {
|
||||||
|
return IsWindowOnScreen(GetSourceId())
|
||||||
|
? 0
|
||||||
|
: FindFullScreenWindowWithSamePid(source_list, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const TitlePredicate title_predicate_;
|
||||||
|
const int owner_pid_;
|
||||||
|
mutable int64_t cache_timestamp_ = 0;
|
||||||
|
mutable DesktopCapturer::SourceList cache_sources_;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool equal_title_predicate(const std::string& original_title,
|
||||||
|
const std::string& title) {
|
||||||
|
return original_title == title;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool slide_show_title_predicate(const std::string& original_title,
|
||||||
|
const std::string& title) {
|
||||||
|
if (title.find(original_title) == std::string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const char* pp_slide_title : kPowerPointSlideShowTitles) {
|
||||||
|
if (absl::StartsWith(title, pp_slide_title))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler>
|
||||||
|
CreateFullScreenMacApplicationHandler(DesktopCapturer::SourceId sourceId) {
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler> result;
|
||||||
|
int pid = GetWindowOwnerPid(sourceId);
|
||||||
|
char buffer[PROC_PIDPATHINFO_MAXSIZE];
|
||||||
|
int path_length = proc_pidpath(pid, buffer, sizeof(buffer));
|
||||||
|
if (path_length > 0) {
|
||||||
|
const char* last_slash = strrchr(buffer, '/');
|
||||||
|
const std::string name{last_slash ? last_slash + 1 : buffer};
|
||||||
|
FullScreenMacApplicationHandler::TitlePredicate predicate = nullptr;
|
||||||
|
if (name.find("Google Chrome") == 0 || name == "Chromium") {
|
||||||
|
predicate = equal_title_predicate;
|
||||||
|
} else if (name == "Microsoft PowerPoint") {
|
||||||
|
predicate = slide_show_title_predicate;
|
||||||
|
} else if (name == "Keynote") {
|
||||||
|
predicate = equal_title_predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (predicate) {
|
||||||
|
result.reset(new FullScreenMacApplicationHandler(sourceId, predicate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_MAC_APPLICATION_HANDLER_H_
|
||||||
|
#define MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_MAC_APPLICATION_HANDLER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "modules/desktop_capture/full_screen_application_handler.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler>
|
||||||
|
CreateFullScreenMacApplicationHandler(DesktopCapturer::SourceId sourceId);
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_DESKTOP_CAPTURE_MAC_FULL_SCREEN_MAC_APPLICATION_HANDLER_H_
|
||||||
@ -15,8 +15,11 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
|
|
||||||
@ -78,7 +81,8 @@ bool GetWindowRef(CGWindowID id,
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
||||||
bool ignore_minimized) {
|
bool ignore_minimized,
|
||||||
|
bool only_zero_layer) {
|
||||||
RTC_DCHECK(on_window);
|
RTC_DCHECK(on_window);
|
||||||
|
|
||||||
// Only get on screen, non-desktop windows.
|
// Only get on screen, non-desktop windows.
|
||||||
@ -122,7 +126,7 @@ bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
|||||||
if (!CFNumberGetValue(window_layer, kCFNumberIntType, &layer)) {
|
if (!CFNumberGetValue(window_layer, kCFNumberIntType, &layer)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (layer != 0) {
|
if (only_zero_layer && layer != 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +155,8 @@ bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GetWindowList(DesktopCapturer::SourceList* windows,
|
bool GetWindowList(DesktopCapturer::SourceList* windows,
|
||||||
bool ignore_minimized) {
|
bool ignore_minimized,
|
||||||
|
bool only_zero_layer) {
|
||||||
// Use a std::list so that iterators are preversed upon insertion and
|
// Use a std::list so that iterators are preversed upon insertion and
|
||||||
// deletion.
|
// deletion.
|
||||||
std::list<DesktopCapturer::Source> sources;
|
std::list<DesktopCapturer::Source> sources;
|
||||||
@ -201,7 +206,7 @@ bool GetWindowList(DesktopCapturer::SourceList* windows,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
ignore_minimized);
|
ignore_minimized, only_zero_layer);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return false;
|
return false;
|
||||||
@ -239,6 +244,15 @@ bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
|
|||||||
return fullscreen;
|
return fullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
|
||||||
|
CGWindowID id) {
|
||||||
|
bool fullscreen = false;
|
||||||
|
GetWindowRef(id, [&](CFDictionaryRef window) {
|
||||||
|
fullscreen = IsWindowFullScreen(desktop_config, window);
|
||||||
|
});
|
||||||
|
return fullscreen;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsWindowOnScreen(CFDictionaryRef window) {
|
bool IsWindowOnScreen(CFDictionaryRef window) {
|
||||||
CFBooleanRef on_screen = reinterpret_cast<CFBooleanRef>(
|
CFBooleanRef on_screen = reinterpret_cast<CFBooleanRef>(
|
||||||
CFDictionaryGetValue(window, kCGWindowIsOnscreen));
|
CFDictionaryGetValue(window, kCGWindowIsOnscreen));
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <ApplicationServices/ApplicationServices.h>
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include "api/function_view.h"
|
#include "api/function_view.h"
|
||||||
#include "modules/desktop_capture/desktop_capture_types.h"
|
#include "modules/desktop_capture/desktop_capture_types.h"
|
||||||
#include "modules/desktop_capture/desktop_capturer.h"
|
#include "modules/desktop_capture/desktop_capturer.h"
|
||||||
@ -24,18 +25,26 @@ namespace webrtc {
|
|||||||
// Iterates all on-screen windows in decreasing z-order and sends them
|
// Iterates all on-screen windows in decreasing z-order and sends them
|
||||||
// one-by-one to |on_window| function. If |on_window| returns false, this
|
// one-by-one to |on_window| function. If |on_window| returns false, this
|
||||||
// function returns immediately. GetWindowList() returns false if native APIs
|
// function returns immediately. GetWindowList() returns false if native APIs
|
||||||
// failed. Menus, dock, minimized windows (if |ignore_minimized| is true) and
|
// failed. Menus, dock (if |only_zero_layer|), minimized windows (if
|
||||||
// any windows which do not have a valid window id or title will be ignored.
|
// |ignore_minimized| is true) and any windows which do not have a valid window
|
||||||
|
// id or title will be ignored.
|
||||||
bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
||||||
bool ignore_minimized);
|
bool ignore_minimized,
|
||||||
|
bool only_zero_layer);
|
||||||
|
|
||||||
// Another helper function to get the on-screen windows.
|
// Another helper function to get the on-screen windows.
|
||||||
bool GetWindowList(DesktopCapturer::SourceList* windows, bool ignore_minimized);
|
bool GetWindowList(DesktopCapturer::SourceList* windows,
|
||||||
|
bool ignore_minimized,
|
||||||
|
bool only_zero_layer);
|
||||||
|
|
||||||
// Returns true if the window is occupying a full screen.
|
// Returns true if the window is occupying a full screen.
|
||||||
bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
|
bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
|
||||||
CFDictionaryRef window);
|
CFDictionaryRef window);
|
||||||
|
|
||||||
|
// Returns true if the window is occupying a full screen.
|
||||||
|
bool IsWindowFullScreen(const MacDesktopConfiguration& desktop_config,
|
||||||
|
CGWindowID id);
|
||||||
|
|
||||||
// Returns true if the |window| is on screen. This function returns false if
|
// Returns true if the |window| is on screen. This function returns false if
|
||||||
// native APIs fail.
|
// native APIs fail.
|
||||||
bool IsWindowOnScreen(CFDictionaryRef window);
|
bool IsWindowOnScreen(CFDictionaryRef window);
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
#include "modules/desktop_capture/desktop_frame.h"
|
#include "modules/desktop_capture/desktop_frame.h"
|
||||||
#include "modules/desktop_capture/mac/desktop_configuration.h"
|
#include "modules/desktop_capture/mac/desktop_configuration.h"
|
||||||
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
||||||
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
|
||||||
#include "modules/desktop_capture/mac/window_list_utils.h"
|
#include "modules/desktop_capture/mac/window_list_utils.h"
|
||||||
#include "modules/desktop_capture/mouse_cursor.h"
|
#include "modules/desktop_capture/mouse_cursor.h"
|
||||||
|
|
||||||
@ -79,21 +78,16 @@ class MouseCursorMonitorMac : public MouseCursorMonitor {
|
|||||||
Callback* callback_;
|
Callback* callback_;
|
||||||
Mode mode_;
|
Mode mode_;
|
||||||
__strong NSImage* last_cursor_;
|
__strong NSImage* last_cursor_;
|
||||||
rtc::scoped_refptr<FullScreenChromeWindowDetector>
|
|
||||||
full_screen_chrome_window_detector_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MouseCursorMonitorMac::MouseCursorMonitorMac(
|
MouseCursorMonitorMac::MouseCursorMonitorMac(const DesktopCaptureOptions& options,
|
||||||
const DesktopCaptureOptions& options,
|
CGWindowID window_id,
|
||||||
CGWindowID window_id,
|
ScreenId screen_id)
|
||||||
ScreenId screen_id)
|
|
||||||
: configuration_monitor_(options.configuration_monitor()),
|
: configuration_monitor_(options.configuration_monitor()),
|
||||||
window_id_(window_id),
|
window_id_(window_id),
|
||||||
screen_id_(screen_id),
|
screen_id_(screen_id),
|
||||||
callback_(NULL),
|
callback_(NULL),
|
||||||
mode_(SHAPE_AND_POSITION),
|
mode_(SHAPE_AND_POSITION) {
|
||||||
full_screen_chrome_window_detector_(
|
|
||||||
options.full_screen_chrome_window_detector()) {
|
|
||||||
assert(window_id == kCGNullWindowID || screen_id == kInvalidScreenId);
|
assert(window_id == kCGNullWindowID || screen_id == kInvalidScreenId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/desktop_capture/win/full_screen_win_application_handler.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cwctype>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "rtc_base/arraysize.h"
|
||||||
|
#include "rtc_base/logging.h" // For RTC_LOG_GLE
|
||||||
|
#include "rtc_base/string_utils.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::string WindowText(HWND window) {
|
||||||
|
size_t len = ::GetWindowTextLength(window);
|
||||||
|
if (len == 0)
|
||||||
|
return std::string();
|
||||||
|
|
||||||
|
std::vector<wchar_t> buffer(len + 1, 0);
|
||||||
|
size_t copied = ::GetWindowTextW(window, buffer.data(), buffer.size());
|
||||||
|
if (copied == 0)
|
||||||
|
return std::string();
|
||||||
|
return rtc::ToUtf8(buffer.data(), copied);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WindowProcessId(HWND window) {
|
||||||
|
DWORD dwProcessId = 0;
|
||||||
|
::GetWindowThreadProcessId(window, &dwProcessId);
|
||||||
|
return dwProcessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring FileNameFromPath(const std::wstring& path) {
|
||||||
|
auto found = path.rfind(L"\\");
|
||||||
|
if (found == std::string::npos)
|
||||||
|
return path;
|
||||||
|
return path.substr(found + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns windows which belong to given process id
|
||||||
|
// |sources| is a full list of available windows
|
||||||
|
// |processId| is a process identifier (window owner)
|
||||||
|
// |window_to_exclude| is a window to be exluded from result
|
||||||
|
DesktopCapturer::SourceList GetProcessWindows(
|
||||||
|
const DesktopCapturer::SourceList& sources,
|
||||||
|
DWORD processId,
|
||||||
|
HWND window_to_exclude) {
|
||||||
|
DesktopCapturer::SourceList result;
|
||||||
|
std::copy_if(sources.begin(), sources.end(), std::back_inserter(result),
|
||||||
|
[&](DesktopCapturer::Source source) {
|
||||||
|
const HWND source_hwnd = reinterpret_cast<HWND>(source.id);
|
||||||
|
return window_to_exclude != source_hwnd &&
|
||||||
|
WindowProcessId(source_hwnd) == processId;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FullScreenPowerPointHandler : public FullScreenApplicationHandler {
|
||||||
|
public:
|
||||||
|
explicit FullScreenPowerPointHandler(DesktopCapturer::SourceId sourceId)
|
||||||
|
: FullScreenApplicationHandler(sourceId) {}
|
||||||
|
|
||||||
|
~FullScreenPowerPointHandler() override {}
|
||||||
|
|
||||||
|
DesktopCapturer::SourceId FindFullScreenWindow(
|
||||||
|
const DesktopCapturer::SourceList& window_list,
|
||||||
|
int64_t timestamp) const override {
|
||||||
|
if (window_list.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
HWND original_window = reinterpret_cast<HWND>(GetSourceId());
|
||||||
|
DWORD process_id = WindowProcessId(original_window);
|
||||||
|
|
||||||
|
DesktopCapturer::SourceList powerpoint_windows =
|
||||||
|
GetProcessWindows(window_list, process_id, original_window);
|
||||||
|
|
||||||
|
if (powerpoint_windows.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (GetWindowType(original_window) != WindowType::kEditor)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const auto original_document = GetDocumentFromEditorTitle(original_window);
|
||||||
|
|
||||||
|
for (const auto& source : powerpoint_windows) {
|
||||||
|
HWND window = reinterpret_cast<HWND>(source.id);
|
||||||
|
|
||||||
|
// Looking for slide show window for the same document
|
||||||
|
if (GetWindowType(window) != WindowType::kSlideShow ||
|
||||||
|
GetDocumentFromSlideShowTitle(window) != original_document) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return source.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class WindowType { kEditor, kSlideShow, kOther };
|
||||||
|
|
||||||
|
WindowType GetWindowType(HWND window) const {
|
||||||
|
if (IsEditorWindow(window))
|
||||||
|
return WindowType::kEditor;
|
||||||
|
else if (IsSlideShowWindow(window))
|
||||||
|
return WindowType::kSlideShow;
|
||||||
|
else
|
||||||
|
return WindowType::kOther;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr static char kDocumentTitleSeparator[] = " - ";
|
||||||
|
|
||||||
|
std::string GetDocumentFromEditorTitle(HWND window) const {
|
||||||
|
std::string title = WindowText(window);
|
||||||
|
auto position = title.find(kDocumentTitleSeparator);
|
||||||
|
return rtc::string_trim(title.substr(0, position));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetDocumentFromSlideShowTitle(HWND window) const {
|
||||||
|
std::string title = WindowText(window);
|
||||||
|
auto left_pos = title.find(kDocumentTitleSeparator);
|
||||||
|
auto right_pos = title.rfind(kDocumentTitleSeparator);
|
||||||
|
constexpr size_t kSeparatorLength = arraysize(kDocumentTitleSeparator) - 1;
|
||||||
|
if (left_pos == std::string::npos || right_pos == std::string::npos)
|
||||||
|
return title;
|
||||||
|
|
||||||
|
if (right_pos > left_pos + kSeparatorLength) {
|
||||||
|
auto result_len = right_pos - left_pos - kSeparatorLength;
|
||||||
|
auto document = title.substr(left_pos + kSeparatorLength, result_len);
|
||||||
|
return rtc::string_trim(document);
|
||||||
|
} else {
|
||||||
|
auto document =
|
||||||
|
title.substr(left_pos + kSeparatorLength, std::wstring::npos);
|
||||||
|
return rtc::string_trim(document);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEditorWindow(HWND window) const {
|
||||||
|
constexpr WCHAR kScreenClassName[] = L"PPTFrameClass";
|
||||||
|
constexpr size_t kScreenClassNameLength = arraysize(kScreenClassName) - 1;
|
||||||
|
|
||||||
|
// We need to verify that window class is equal to |kScreenClassName|.
|
||||||
|
// To do that we need a buffer large enough to include a null terminated
|
||||||
|
// string one code point bigger than |kScreenClassName|. It will help us to
|
||||||
|
// check that size of class name string returned by GetClassNameW is equal
|
||||||
|
// to |kScreenClassNameLength| not being limited by size of buffer (case
|
||||||
|
// when |kScreenClassName| is a prefix for class name string).
|
||||||
|
WCHAR buffer[arraysize(kScreenClassName) + 3];
|
||||||
|
const int length = ::GetClassNameW(window, buffer, arraysize(buffer));
|
||||||
|
if (length != kScreenClassNameLength)
|
||||||
|
return false;
|
||||||
|
return wcsncmp(buffer, kScreenClassName, kScreenClassNameLength) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSlideShowWindow(HWND window) const {
|
||||||
|
const LONG style = ::GetWindowLong(window, GWL_STYLE);
|
||||||
|
const bool min_box = WS_MINIMIZEBOX & style;
|
||||||
|
const bool max_box = WS_MAXIMIZEBOX & style;
|
||||||
|
return !min_box && !max_box;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::wstring GetPathByWindowId(HWND window_id) {
|
||||||
|
DWORD process_id = WindowProcessId(window_id);
|
||||||
|
HANDLE process =
|
||||||
|
::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id);
|
||||||
|
if (process == NULL)
|
||||||
|
return L"";
|
||||||
|
DWORD path_len = MAX_PATH;
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
std::wstring result;
|
||||||
|
if (::QueryFullProcessImageNameW(process, 0, path, &path_len))
|
||||||
|
result = std::wstring(path, path_len);
|
||||||
|
else
|
||||||
|
RTC_LOG_GLE(LS_ERROR) << "QueryFullProcessImageName failed.";
|
||||||
|
|
||||||
|
::CloseHandle(process);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler>
|
||||||
|
CreateFullScreenWinApplicationHandler(DesktopCapturer::SourceId source_id) {
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler> result;
|
||||||
|
std::wstring exe_path = GetPathByWindowId(reinterpret_cast<HWND>(source_id));
|
||||||
|
std::wstring file_name = FileNameFromPath(exe_path);
|
||||||
|
std::transform(file_name.begin(), file_name.end(), file_name.begin(),
|
||||||
|
std::towupper);
|
||||||
|
|
||||||
|
if (file_name == L"POWERPNT.EXE") {
|
||||||
|
result = std::make_unique<FullScreenPowerPointHandler>(source_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODULES_DESKTOP_CAPTURE_WIN_FULL_SCREEN_WIN_APPLICATION_HANDLER_H_
|
||||||
|
#define MODULES_DESKTOP_CAPTURE_WIN_FULL_SCREEN_WIN_APPLICATION_HANDLER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include "modules/desktop_capture/full_screen_application_handler.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
std::unique_ptr<FullScreenApplicationHandler>
|
||||||
|
CreateFullScreenWinApplicationHandler(DesktopCapturer::SourceId sourceId);
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_DESKTOP_CAPTURE_WIN_FULL_SCREEN_WIN_APPLICATION_HANDLER_H_
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include "modules/desktop_capture/mac/desktop_configuration.h"
|
#include "modules/desktop_capture/mac/desktop_configuration.h"
|
||||||
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
|
||||||
#include "modules/desktop_capture/mac/desktop_frame_cgimage.h"
|
#include "modules/desktop_capture/mac/desktop_frame_cgimage.h"
|
||||||
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
|
|
||||||
#include "modules/desktop_capture/mac/window_list_utils.h"
|
#include "modules/desktop_capture/mac/window_list_utils.h"
|
||||||
#include "modules/desktop_capture/window_finder_mac.h"
|
#include "modules/desktop_capture/window_finder_mac.h"
|
||||||
#include "rtc_base/constructor_magic.h"
|
#include "rtc_base/constructor_magic.h"
|
||||||
@ -48,10 +47,9 @@ bool IsWindowValid(CGWindowID id) {
|
|||||||
|
|
||||||
class WindowCapturerMac : public DesktopCapturer {
|
class WindowCapturerMac : public DesktopCapturer {
|
||||||
public:
|
public:
|
||||||
explicit WindowCapturerMac(rtc::scoped_refptr<FullScreenChromeWindowDetector>
|
explicit WindowCapturerMac(
|
||||||
full_screen_chrome_window_detector,
|
rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector,
|
||||||
rtc::scoped_refptr<DesktopConfigurationMonitor>
|
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor);
|
||||||
configuration_monitor);
|
|
||||||
~WindowCapturerMac() override;
|
~WindowCapturerMac() override;
|
||||||
|
|
||||||
// DesktopCapturer interface.
|
// DesktopCapturer interface.
|
||||||
@ -68,8 +66,7 @@ class WindowCapturerMac : public DesktopCapturer {
|
|||||||
// The window being captured.
|
// The window being captured.
|
||||||
CGWindowID window_id_ = 0;
|
CGWindowID window_id_ = 0;
|
||||||
|
|
||||||
const rtc::scoped_refptr<FullScreenChromeWindowDetector>
|
rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector_;
|
||||||
full_screen_chrome_window_detector_;
|
|
||||||
|
|
||||||
const rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
|
const rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
|
||||||
|
|
||||||
@ -79,18 +76,16 @@ class WindowCapturerMac : public DesktopCapturer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
WindowCapturerMac::WindowCapturerMac(
|
WindowCapturerMac::WindowCapturerMac(
|
||||||
rtc::scoped_refptr<FullScreenChromeWindowDetector>
|
rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector,
|
||||||
full_screen_chrome_window_detector,
|
|
||||||
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor)
|
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor)
|
||||||
: full_screen_chrome_window_detector_(
|
: full_screen_window_detector_(std::move(full_screen_window_detector)),
|
||||||
std::move(full_screen_chrome_window_detector)),
|
|
||||||
configuration_monitor_(std::move(configuration_monitor)),
|
configuration_monitor_(std::move(configuration_monitor)),
|
||||||
window_finder_(configuration_monitor_) {}
|
window_finder_(configuration_monitor_) {}
|
||||||
|
|
||||||
WindowCapturerMac::~WindowCapturerMac() {}
|
WindowCapturerMac::~WindowCapturerMac() {}
|
||||||
|
|
||||||
bool WindowCapturerMac::GetSourceList(SourceList* sources) {
|
bool WindowCapturerMac::GetSourceList(SourceList* sources) {
|
||||||
return webrtc::GetWindowList(sources, true);
|
return webrtc::GetWindowList(sources, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowCapturerMac::SelectSource(SourceId id) {
|
bool WindowCapturerMac::SelectSource(SourceId id) {
|
||||||
@ -163,12 +158,15 @@ void WindowCapturerMac::CaptureFrame() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CGWindowID on_screen_window = window_id_;
|
CGWindowID on_screen_window = window_id_;
|
||||||
if (full_screen_chrome_window_detector_) {
|
if (full_screen_window_detector_) {
|
||||||
CGWindowID full_screen_window =
|
full_screen_window_detector_->UpdateWindowListIfNeeded(
|
||||||
full_screen_chrome_window_detector_->FindFullScreenWindow(window_id_);
|
window_id_, [](DesktopCapturer::SourceList* sources) {
|
||||||
|
return webrtc::GetWindowList(sources, true, false);
|
||||||
|
});
|
||||||
|
|
||||||
if (full_screen_window != kCGNullWindowID)
|
CGWindowID full_screen_window = full_screen_window_detector_->FindFullScreenWindow(window_id_);
|
||||||
on_screen_window = full_screen_window;
|
|
||||||
|
if (full_screen_window != kCGNullWindowID) on_screen_window = full_screen_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DesktopFrame> frame = DesktopFrameCGImage::CreateForWindow(on_screen_window);
|
std::unique_ptr<DesktopFrame> frame = DesktopFrameCGImage::CreateForWindow(on_screen_window);
|
||||||
@ -186,9 +184,6 @@ void WindowCapturerMac::CaptureFrame() {
|
|||||||
frame->set_dpi(DesktopVector(kStandardDPI * scale_factor, kStandardDPI * scale_factor));
|
frame->set_dpi(DesktopVector(kStandardDPI * scale_factor, kStandardDPI * scale_factor));
|
||||||
|
|
||||||
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
|
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
|
||||||
|
|
||||||
if (full_screen_chrome_window_detector_)
|
|
||||||
full_screen_chrome_window_detector_->UpdateWindowListIfNeeded(window_id_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -196,9 +191,8 @@ void WindowCapturerMac::CaptureFrame() {
|
|||||||
// static
|
// static
|
||||||
std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
|
std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
|
||||||
const DesktopCaptureOptions& options) {
|
const DesktopCaptureOptions& options) {
|
||||||
return std::unique_ptr<DesktopCapturer>(
|
return std::unique_ptr<DesktopCapturer>(new WindowCapturerMac(
|
||||||
new WindowCapturerMac(options.full_screen_chrome_window_detector(),
|
options.full_screen_window_detector(), options.configuration_monitor()));
|
||||||
options.configuration_monitor()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -38,6 +38,7 @@ WindowId WindowFinderMac::GetWindowUnderPoint(DesktopVector point) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
true,
|
||||||
true);
|
true);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user