From 74544f9d1b2b3ed2ea3d13cda3d01cd00b4a6661 Mon Sep 17 00:00:00 2001 From: Zijie He Date: Mon, 24 Jul 2017 16:52:17 -0700 Subject: [PATCH] Return translated position in MouseCursorMonitor This change returns translated position in the newly added overload MouseCursorMonitor::Callback::OnMouseCursorPosition(DesktopVector) callback. Meanwhile it also reduces the duplicate logic in Windows capturer implementations. So except for the deprecated logic in MouseCursorMonitorWin, all GetSystemMetrics() function calls are merged into GetScreenRect(), GetFullscreenRect() and GetFullscreenTopLeft() functions. Bug: webrtc:7950 Change-Id: Ic2a85a80b6947367bdd20d8f96f11e0f5c269006 Reviewed-on: https://chromium-review.googlesource.com/581951 Reviewed-by: Jamie Walch Reviewed-by: Zijie He Commit-Queue: Zijie He Cr-Commit-Position: refs/heads/master@{#19157} --- webrtc/modules/desktop_capture/BUILD.gn | 2 + .../cropping_window_capturer_win.cc | 2 +- .../desktop_capture/desktop_capture_types.h | 2 + .../mac/desktop_configuration.h | 6 ++- .../mouse_cursor_monitor_mac.mm | 6 +-- .../mouse_cursor_monitor_win.cc | 5 ++- .../mouse_cursor_monitor_x11.cc | 3 ++ .../resolution_change_detector.h | 5 +++ .../win/display_configuration_monitor.cc | 37 ++++++++++++++++++ .../win/display_configuration_monitor.h | 38 +++++++++++++++++++ .../win/dxgi_duplicator_controller.cc | 5 +-- .../win/dxgi_duplicator_controller.h | 4 +- .../win/screen_capture_utils.cc | 12 ++++-- .../win/screen_capture_utils.h | 4 ++ .../win/screen_capturer_win_gdi.cc | 13 +------ .../win/screen_capturer_win_gdi.h | 5 +-- .../win/window_capture_utils.h | 4 +- 17 files changed, 122 insertions(+), 31 deletions(-) create mode 100644 webrtc/modules/desktop_capture/win/display_configuration_monitor.cc create mode 100644 webrtc/modules/desktop_capture/win/display_configuration_monitor.h diff --git a/webrtc/modules/desktop_capture/BUILD.gn b/webrtc/modules/desktop_capture/BUILD.gn index 24140fa254..59c317942d 100644 --- a/webrtc/modules/desktop_capture/BUILD.gn +++ b/webrtc/modules/desktop_capture/BUILD.gn @@ -218,6 +218,8 @@ rtc_static_library("desktop_capture") { "win/d3d_device.h", "win/desktop.cc", "win/desktop.h", + "win/display_configuration_monitor.cc", + "win/display_configuration_monitor.h", "win/dxgi_adapter_duplicator.cc", "win/dxgi_adapter_duplicator.h", "win/dxgi_context.cc", diff --git a/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc b/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc index 2d2dee2ab5..b7c71c835c 100644 --- a/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc +++ b/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc @@ -201,7 +201,7 @@ DesktopRect CroppingWindowCapturerWin::GetWindowRectInVirtualScreen() { window_rect.IntersectWith(window_region_rect_); // Convert |window_rect| to be relative to the top-left of the virtual screen. - DesktopRect screen_rect(GetScreenRect(kFullDesktopScreenId, L"")); + DesktopRect screen_rect(GetFullscreenRect()); window_rect.IntersectWith(screen_rect); window_rect.Translate(-screen_rect.left(), -screen_rect.top()); return window_rect; diff --git a/webrtc/modules/desktop_capture/desktop_capture_types.h b/webrtc/modules/desktop_capture/desktop_capture_types.h index f816773bb7..46346b0077 100644 --- a/webrtc/modules/desktop_capture/desktop_capture_types.h +++ b/webrtc/modules/desktop_capture/desktop_capture_types.h @@ -29,6 +29,8 @@ const WindowId kNullWindowId = 0; // - On Windows: integer display device index. // - On OSX: CGDirectDisplayID cast to intptr_t. // - On Linux (with X11): TBD. +// On Windows, ScreenId is implementation dependent: sending a ScreenId from one +// implementation to another usually won't work correctly. typedef intptr_t ScreenId; // The screen id corresponds to all screen combined together. diff --git a/webrtc/modules/desktop_capture/mac/desktop_configuration.h b/webrtc/modules/desktop_capture/mac/desktop_configuration.h index d54d0fb745..73550ac37d 100644 --- a/webrtc/modules/desktop_capture/mac/desktop_configuration.h +++ b/webrtc/modules/desktop_capture/mac/desktop_configuration.h @@ -57,9 +57,11 @@ struct MacDesktopConfiguration { MacDesktopConfiguration& operator=(const MacDesktopConfiguration& other); MacDesktopConfiguration& operator=(MacDesktopConfiguration&& other); - // Returns the desktop & display configurations in Cocoa-style "bottom-up" + // Returns the desktop & display configurations. + // If BottomLeftOrigin is used, the output is in Cocoa-style "bottom-up" // (the origin is the bottom-left of the primary monitor, and coordinates - // increase as you move up the screen). + // increase as you move up the screen). Otherwise, the configuration will be + // converted to follow top-left coordinate system as Windows and X11. static MacDesktopConfiguration GetCurrent(Origin origin); // Returns true if the given desktop configuration equals this one. diff --git a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm index 7bb6b2ccf5..2bb06b7b4b 100644 --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_mac.mm @@ -241,15 +241,15 @@ void MouseCursorMonitorMac::Capture() { state = OUTSIDE; position.set(-1, -1); } - } else { - position.subtract(configuration.bounds.top_left()); } } // Convert Density Independent Pixel to physical pixel. position = DesktopVector(round(position.x() * scale), round(position.y() * scale)); + // TODO(zijiehe): Remove this overload. callback_->OnMouseCursorPosition(state, position); - callback_->OnMouseCursorPosition(position); + callback_->OnMouseCursorPosition( + position.subtract(configuration.bounds.top_left())); } void MouseCursorMonitorMac::CaptureImage(float scale) { diff --git a/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc b/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc index ebf00ac6df..43174cb08b 100644 --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_win.cc @@ -20,6 +20,7 @@ #include "webrtc/modules/desktop_capture/desktop_geometry.h" #include "webrtc/modules/desktop_capture/mouse_cursor.h" #include "webrtc/modules/desktop_capture/win/cursor.h" +#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" #include "webrtc/modules/desktop_capture/win/window_capture_utils.h" #include "webrtc/rtc_base/logging.h" @@ -162,8 +163,10 @@ void MouseCursorMonitorWin::Capture() { position = position.subtract(rect.top_left()); } + // TODO(zijiehe): Remove this overload. callback_->OnMouseCursorPosition(inside ? INSIDE : OUTSIDE, position); - callback_->OnMouseCursorPosition(position); + callback_->OnMouseCursorPosition( + position.subtract(GetFullscreenRect().top_left())); } DesktopRect MouseCursorMonitorWin::GetScreenRect() { diff --git a/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc b/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc index 9b30c49831..edde01c7ba 100644 --- a/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc +++ b/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc @@ -202,7 +202,10 @@ void MouseCursorMonitorX11::Capture() { } const DesktopVector position(win_x, win_y); + // TODO(zijiehe): Remove this overload. callback_->OnMouseCursorPosition(state, position); + // X11 always starts the coordinate from (0, 0), so we do not need to + // translate here. callback_->OnMouseCursorPosition(position); } } diff --git a/webrtc/modules/desktop_capture/resolution_change_detector.h b/webrtc/modules/desktop_capture/resolution_change_detector.h index 6ccf8a7a17..f82c3900a1 100644 --- a/webrtc/modules/desktop_capture/resolution_change_detector.h +++ b/webrtc/modules/desktop_capture/resolution_change_detector.h @@ -17,7 +17,12 @@ namespace webrtc { class ResolutionChangeDetector { public: + // Checks whether the |size| has been changed comparing to the |size| passed + // in during last IsChanged() call. This function won't return false for the + // first time after construction or Reset() call. bool IsChanged(DesktopSize size); + + // Resets to the initial state. void Reset(); private: diff --git a/webrtc/modules/desktop_capture/win/display_configuration_monitor.cc b/webrtc/modules/desktop_capture/win/display_configuration_monitor.cc new file mode 100644 index 0000000000..5685d9574d --- /dev/null +++ b/webrtc/modules/desktop_capture/win/display_configuration_monitor.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 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 "webrtc/modules/desktop_capture/win/display_configuration_monitor.h" + +#include "webrtc/modules/desktop_capture/win/screen_capture_utils.h" + +namespace webrtc { + +bool DisplayConfigurationMonitor::IsChanged() { + DesktopRect rect = GetFullscreenRect(); + if (!initialized_) { + initialized_ = true; + rect_ = rect; + return false; + } + + if (rect.equals(rect_)) { + return false; + } + + rect_ = rect; + return true; +} + +void DisplayConfigurationMonitor::Reset() { + initialized_ = false; +} + +} // namespace webrtc diff --git a/webrtc/modules/desktop_capture/win/display_configuration_monitor.h b/webrtc/modules/desktop_capture/win/display_configuration_monitor.h new file mode 100644 index 0000000000..d13b45ed35 --- /dev/null +++ b/webrtc/modules/desktop_capture/win/display_configuration_monitor.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 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 WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DISPLAY_CONFIGURATION_MONITOR_H_ +#define WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DISPLAY_CONFIGURATION_MONITOR_H_ + +#include "webrtc/modules/desktop_capture/desktop_geometry.h" + +namespace webrtc { + +// A passive monitor to detect the change of display configuration on a Windows +// system. +// TODO(zijiehe): Also check for pixel format changes. +class DisplayConfigurationMonitor { + public: + // Checks whether the change of display configuration has happened after last + // IsChanged() call. This function won't return false for the first time after + // constructor or Reset() call. + bool IsChanged(); + + // Resets to the initial state. + void Reset(); + + private: + DesktopRect rect_; + bool initialized_ = false; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_DESKTOP_CAPTURE_WIN_DISPLAY_CONFIGURATION_MONITOR_H_ diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc index 0cefb86cdc..4a6ab8e829 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.cc @@ -137,8 +137,7 @@ DxgiDuplicatorController::DoDuplicate(DxgiFrame* frame, int monitor_id) { // TODO(zijiehe): Confirm whether IDXGIOutput::GetDesc() and // IDXGIOutputDuplication::GetDesc() can detect the resolution change without // reinitialization. - if (resolution_change_detector_.IsChanged( - GetScreenRect(kFullDesktopScreenId, std::wstring()).size())) { + if (display_configuration_monitor_.IsChanged()) { Deinitialize(); } @@ -266,7 +265,7 @@ bool DxgiDuplicatorController::DoInitialize() { void DxgiDuplicatorController::Deinitialize() { desktop_rect_ = DesktopRect(); duplicators_.clear(); - resolution_change_detector_.Reset(); + display_configuration_monitor_.Reset(); } bool DxgiDuplicatorController::ContextExpired( diff --git a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h index 8ea7f183c2..ddf02a89d1 100644 --- a/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h +++ b/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h @@ -18,9 +18,9 @@ #include #include "webrtc/modules/desktop_capture/desktop_geometry.h" -#include "webrtc/modules/desktop_capture/resolution_change_detector.h" #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" #include "webrtc/modules/desktop_capture/win/d3d_device.h" +#include "webrtc/modules/desktop_capture/win/display_configuration_monitor.h" #include "webrtc/modules/desktop_capture/win/dxgi_adapter_duplicator.h" #include "webrtc/modules/desktop_capture/win/dxgi_context.h" #include "webrtc/modules/desktop_capture/win/dxgi_frame.h" @@ -224,7 +224,7 @@ class DxgiDuplicatorController { DesktopVector dpi_; std::vector duplicators_; D3dInfo d3d_info_; - ResolutionChangeDetector resolution_change_detector_; + DisplayConfigurationMonitor display_configuration_monitor_; // A number to indicate how many succeeded duplications have been performed. uint32_t succeeded_duplications_ = 0; }; diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils.cc b/webrtc/modules/desktop_capture/win/screen_capture_utils.cc index e640bde277..a8718459b2 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils.cc +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils.cc @@ -65,13 +65,17 @@ bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key) { return !!enum_result; } +DesktopRect GetFullscreenRect() { + return DesktopRect::MakeXYWH(GetSystemMetrics(SM_XVIRTUALSCREEN), + GetSystemMetrics(SM_YVIRTUALSCREEN), + GetSystemMetrics(SM_CXVIRTUALSCREEN), + GetSystemMetrics(SM_CYVIRTUALSCREEN)); +} + DesktopRect GetScreenRect(DesktopCapturer::SourceId screen, const std::wstring& device_key) { if (screen == kFullDesktopScreenId) { - return DesktopRect::MakeXYWH(GetSystemMetrics(SM_XVIRTUALSCREEN), - GetSystemMetrics(SM_YVIRTUALSCREEN), - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN)); + return GetFullscreenRect(); } DISPLAY_DEVICE device; diff --git a/webrtc/modules/desktop_capture/win/screen_capture_utils.h b/webrtc/modules/desktop_capture/win/screen_capture_utils.h index 73754b2eea..fdbf633084 100644 --- a/webrtc/modules/desktop_capture/win/screen_capture_utils.h +++ b/webrtc/modules/desktop_capture/win/screen_capture_utils.h @@ -32,6 +32,10 @@ bool GetScreenList(DesktopCapturer::SourceList* screens, // id. bool IsScreenValid(DesktopCapturer::SourceId screen, std::wstring* device_key); +// Get the rect of the entire system in system coordinate system. I.e. the +// primary monitor always starts from (0, 0). +DesktopRect GetFullscreenRect(); + // Get the rect of the screen identified by |screen|, relative to the primary // display's top-left. If the screen device key does not match |device_key|, or // the screen does not exist, or any error happens, an empty rect is returned. diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc index 44c81ff12c..427cb93eae 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.cc @@ -148,14 +148,8 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() { } } - // If the display bounds have changed then recreate GDI resources. - // TODO(wez): Also check for pixel format changes. - DesktopRect screen_rect(DesktopRect::MakeXYWH( - GetSystemMetrics(SM_XVIRTUALSCREEN), - GetSystemMetrics(SM_YVIRTUALSCREEN), - GetSystemMetrics(SM_CXVIRTUALSCREEN), - GetSystemMetrics(SM_CYVIRTUALSCREEN))); - if (!screen_rect.equals(desktop_dc_rect_)) { + // If the display configurations have changed then recreate GDI resources. + if (display_configuration_monitor_.IsChanged()) { if (desktop_dc_) { ReleaseDC(NULL, desktop_dc_); desktop_dc_ = nullptr; @@ -164,7 +158,6 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() { DeleteDC(memory_dc_); memory_dc_ = nullptr; } - desktop_dc_rect_ = DesktopRect(); } if (!desktop_dc_) { @@ -176,8 +169,6 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() { memory_dc_ = CreateCompatibleDC(desktop_dc_); RTC_CHECK(memory_dc_); - desktop_dc_rect_ = screen_rect; - // Make sure the frame buffers will be reallocated. queue_.Reset(); } diff --git a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h index 70a939d760..6822895c6d 100644 --- a/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h +++ b/webrtc/modules/desktop_capture/win/screen_capturer_win_gdi.h @@ -18,6 +18,7 @@ #include "webrtc/modules/desktop_capture/desktop_capturer.h" #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" +#include "webrtc/modules/desktop_capture/win/display_configuration_monitor.h" #include "webrtc/modules/desktop_capture/win/scoped_thread_desktop.h" #include "webrtc/rtc_base/constructormagic.h" @@ -69,9 +70,7 @@ class ScreenCapturerWinGdi : public DesktopCapturer { // Queue of the frames buffers. ScreenCaptureFrameQueue queue_; - // Rectangle describing the bounds of the desktop device context, relative to - // the primary display's top-left. - DesktopRect desktop_dc_rect_; + DisplayConfigurationMonitor display_configuration_monitor_; HMODULE dwmapi_library_ = NULL; DwmEnableCompositionFunc composition_func_ = nullptr; diff --git a/webrtc/modules/desktop_capture/win/window_capture_utils.h b/webrtc/modules/desktop_capture/win/window_capture_utils.h index c13cad7bda..8f59c12d1b 100644 --- a/webrtc/modules/desktop_capture/win/window_capture_utils.h +++ b/webrtc/modules/desktop_capture/win/window_capture_utils.h @@ -18,7 +18,9 @@ namespace webrtc { // Output the window rect, with the left/right/bottom frame border cropped if // the window is maximized. |cropped_rect| is the cropped rect relative to the // desktop. |original_rect| is the original rect returned from GetWindowRect. -// Returns true if all API calls succeeded. +// Returns true if all API calls succeeded. The returned DesktopRect is in +// system coordinates, i.e. the primary monitor on the system always starts from +// (0, 0). bool GetCroppedWindowRect(HWND window, DesktopRect* cropped_rect, DesktopRect* original_rect);