Skip to content

Commit

Permalink
Implement handling for MS PowerPoint Presentation Mode.
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Reviewed-by: Jamie Walch <[email protected]>
Reviewed-by: Justin Uberti <[email protected]>
Reviewed-by: Wez <[email protected]>
Cr-Commit-Position: refs/heads/master@{#29993}
  • Loading branch information
Roman Gaiu authored and Commit Bot committed Dec 3, 2019
1 parent 831ce5f commit b588353
Show file tree
Hide file tree
Showing 21 changed files with 797 additions and 259 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ NVIDIA Corporation <*@nvidia.com>
Opera Software ASA <*@opera.com>
Optical Tone Ltd <*@opticaltone.com>
Pengutronix e.K. <*@pengutronix.de>
RingCentral, Inc. <*@ringcentral.com>
Sinch AB <*@sinch.com>
struktur AG <*@struktur.de>
Telenor Digital AS <*@telenor.com>
Expand Down
11 changes: 9 additions & 2 deletions modules/desktop_capture/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,10 @@ rtc_library("desktop_capture_generic") {
"fake_desktop_capturer.h",
"fallback_desktop_capturer_wrapper.cc",
"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.h",
"mouse_cursor_monitor.h",
Expand All @@ -319,8 +323,8 @@ rtc_library("desktop_capture_generic") {
"mac/desktop_configuration.h",
"mac/desktop_configuration_monitor.cc",
"mac/desktop_configuration_monitor.h",
"mac/full_screen_chrome_window_detector.cc",
"mac/full_screen_chrome_window_detector.h",
"mac/full_screen_mac_application_handler.cc",
"mac/full_screen_mac_application_handler.h",
"mac/window_list_utils.cc",
"mac/window_list_utils.h",
]
Expand Down Expand Up @@ -431,6 +435,8 @@ rtc_library("desktop_capture_generic") {
"win/dxgi_texture_mapping.h",
"win/dxgi_texture_staging.cc",
"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_thread_desktop.cc",
"win/scoped_thread_desktop.h",
Expand Down Expand Up @@ -470,6 +476,7 @@ rtc_library("desktop_capture_generic") {
"../../system_wrappers:cpu_features_api",
"../../system_wrappers:metrics",
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
]

if (build_with_mozilla) {
Expand Down
1 change: 1 addition & 0 deletions modules/desktop_capture/cropping_window_capturer.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class RTC_EXPORT CroppingWindowCapturer : public DesktopCapturer,

WindowId selected_window() const { return selected_window_; }
WindowId excluded_window() const { return excluded_window_; }
DesktopCapturer* window_capturer() const { return window_capturer_.get(); }

private:
DesktopCaptureOptions options_;
Expand Down
44 changes: 40 additions & 4 deletions modules/desktop_capture/cropping_window_capturer_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,26 +98,53 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {

class CroppingWindowCapturerWin : public CroppingWindowCapturer {
public:
CroppingWindowCapturerWin(const DesktopCaptureOptions& options)
: CroppingWindowCapturer(options) {}
explicit CroppingWindowCapturerWin(const DesktopCaptureOptions& options)
: CroppingWindowCapturer(options),
full_screen_window_detector_(options.full_screen_window_detector()) {}

void CaptureFrame() override;

private:
bool ShouldUseScreenCapturer() 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
// rectangular, or the rect from GetWindowRect if the region is not set.
DesktopRect window_region_rect_;

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() {
if (!rtc::IsWindows8OrLater() && window_capture_helper_.IsAeroEnabled()) {
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.
if (!window_capture_helper_.IsWindowVisibleOnCurrentDesktop(selected)) {
return false;
Expand Down Expand Up @@ -207,7 +234,7 @@ DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() {
TRACE_EVENT0("webrtc",
"CroppingWindowCapturerWin::GetWindowRectInVirtualScreen");
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,
/*original_rect*/ nullptr)) {
RTC_LOG(LS_WARNING) << "Failed to get window info: " << GetLastError();
Expand All @@ -222,6 +249,15 @@ DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() {
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

// static
Expand Down
12 changes: 10 additions & 2 deletions modules/desktop_capture/desktop_capture_options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
*/

#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 {

Expand All @@ -32,8 +37,11 @@ DesktopCaptureOptions DesktopCaptureOptions::CreateDefault() {
#endif
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
result.set_configuration_monitor(new DesktopConfigurationMonitor());
result.set_full_screen_chrome_window_detector(
new FullScreenChromeWindowDetector());
result.set_full_screen_window_detector(
new FullScreenWindowDetector(CreateFullScreenMacApplicationHandler));
#elif defined(WEBRTC_WIN)
result.set_full_screen_window_detector(
new FullScreenWindowDetector(CreateFullScreenWinApplicationHandler));
#endif
return result;
}
Expand Down
24 changes: 11 additions & 13 deletions modules/desktop_capture/desktop_capture_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@

#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
#include "modules/desktop_capture/mac/desktop_configuration_monitor.h"
#include "modules/desktop_capture/mac/full_screen_chrome_window_detector.h"
#endif

#include "modules/desktop_capture/full_screen_window_detector.h"

namespace webrtc {

// An object that stores initialization parameters for screen and window
Expand Down Expand Up @@ -62,21 +63,18 @@ class RTC_EXPORT DesktopCaptureOptions {
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 {
bool allow_iosurface() const { return allow_iosurface_; }
void set_allow_iosurface(bool allow) { allow_iosurface_ = allow; }
#endif

FullScreenWindowDetector* full_screen_window_detector() const {
return full_screen_window_detector_;
}
void set_full_screen_chrome_window_detector(
rtc::scoped_refptr<FullScreenChromeWindowDetector> detector) {
void set_full_screen_window_detector(
rtc::scoped_refptr<FullScreenWindowDetector> detector) {
full_screen_window_detector_ = detector;
}

bool allow_iosurface() const { return allow_iosurface_; }
void set_allow_iosurface(bool allow) { allow_iosurface_ = allow; }
#endif

// Flag indicating that the capturer should use screen change notifications.
// Enables/disables use of XDAMAGE in the X11 capturer.
bool use_update_notifications() const { return use_update_notifications_; }
Expand Down Expand Up @@ -142,11 +140,11 @@ class RTC_EXPORT DesktopCaptureOptions {

#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
rtc::scoped_refptr<FullScreenChromeWindowDetector>
full_screen_window_detector_;
bool allow_iosurface_ = false;
#endif

rtc::scoped_refptr<FullScreenWindowDetector> full_screen_window_detector_;

#if defined(WEBRTC_WIN)
bool allow_use_magnification_api_ = false;
bool allow_directx_capturer_ = false;
Expand Down
30 changes: 30 additions & 0 deletions modules/desktop_capture/full_screen_application_handler.cc
Original file line number Diff line number Diff line change
@@ -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 changes: 48 additions & 0 deletions modules/desktop_capture/full_screen_application_handler.h
Original file line number Diff line number Diff line change
@@ -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 changes: 84 additions & 0 deletions modules/desktop_capture/full_screen_window_detector.cc
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit b588353

Please sign in to comment.