Detect whether a window is out of screen when using cropping window capturer

We are still using cropping window capturer even the window is out of the screen.
See the bug for details.

Bug: webrtc:8134
Change-Id: I5161b1a17a3a1f8244697eea5eb78975be6908f9
Reviewed-on: https://chromium-review.googlesource.com/627338
Commit-Queue: Zijie He <zijiehe@chromium.org>
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#19474}
This commit is contained in:
Zijie He 2017-08-23 11:21:09 -07:00 committed by Commit Bot
parent aa0d2e694a
commit dab31ce1fa
3 changed files with 50 additions and 18 deletions

View File

@ -10,7 +10,6 @@
#include "webrtc/modules/desktop_capture/cropping_window_capturer.h"
#include "webrtc/modules/desktop_capture/win/scoped_gdi_object.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"
@ -134,14 +133,14 @@ bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
return false;
}
HWND selected = reinterpret_cast<HWND>(selected_window());
const HWND selected = reinterpret_cast<HWND>(selected_window());
// Check if the window is hidden or minimized.
if (IsIconic(selected) || !IsWindowVisible(selected)) {
return false;
}
// Check if the window is a translucent layered window.
LONG window_ex_style = GetWindowLong(selected, GWL_EXSTYLE);
const LONG window_ex_style = GetWindowLong(selected, GWL_EXSTYLE);
if (window_ex_style & WS_EX_LAYERED) {
COLORREF color_ref_key = 0;
BYTE alpha = 0;
@ -165,10 +164,15 @@ bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
return false;
}
DesktopRect content_rect;
if (!GetWindowContentRect(selected, &content_rect)) {
return false;
}
DesktopRect region_rect;
// Get the window region and check if it is rectangular.
win::ScopedGDIObject<HRGN, win::DeleteObjectTraits<HRGN> >
scoped_hrgn(CreateRectRgn(0, 0, 0, 0));
int region_type = GetWindowRgn(selected, scoped_hrgn.Get());
const int region_type =
GetWindowRegionTypeWithBoundary(selected, &region_rect);
// Do not use the screen capturer if the region is empty or not rectangular.
if (region_type == COMPLEXREGION || region_type == NULLREGION) {
@ -176,20 +180,29 @@ bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
}
if (region_type == SIMPLEREGION) {
RECT region_rect;
GetRgnBox(scoped_hrgn.Get(), &region_rect);
DesktopRect rgn_rect =
DesktopRect::MakeLTRB(region_rect.left,
region_rect.top,
region_rect.right,
region_rect.bottom);
DesktopRect translated_rect = rgn_rect;
translated_rect.Translate(window_region_rect_.left(),
window_region_rect_.top());
window_region_rect_.IntersectWith(translated_rect);
// The |region_rect| returned from GetRgnBox() is always in window
// coordinate.
region_rect.Translate(
window_region_rect_.left(), window_region_rect_.top());
// MSDN: The window region determines the area *within* the window where the
// system permits drawing.
// https://msdn.microsoft.com/en-us/library/windows/desktop/dd144950(v=vs.85).aspx.
//
// |region_rect| should always be inside of |window_region_rect_|. So after
// the intersection, |window_region_rect_| == |region_rect|. If so, what's
// the point of the intersecting operations? Why cannot we directly retrieve
// |window_region_rect_| from GetWindowRegionTypeWithBoundary() function?
// TODO(zijiehe): Figure out the purpose of these intersections.
window_region_rect_.IntersectWith(region_rect);
content_rect.IntersectWith(region_rect);
}
// TODO(zijiehe): Check whether the client area is out of the screen area.
// Check if the client area is out of the screen area. When the window is
// maximized, only its client area is visible in the screen, the border will
// be hidden. So we are using |content_rect| here.
if (!GetFullscreenRect().ContainsRect(content_rect)) {
return false;
}
// Check if the window is occluded by any other window, excluding the child
// windows, context menus, and |excluded_window_|.

View File

@ -10,6 +10,7 @@
#include "webrtc/modules/desktop_capture/win/window_capture_utils.h"
#include "webrtc/modules/desktop_capture/win/scoped_gdi_object.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/win32.h"
@ -98,6 +99,20 @@ bool GetWindowContentRect(HWND window, DesktopRect* result) {
return true;
}
int GetWindowRegionTypeWithBoundary(HWND window, DesktopRect* result) {
win::ScopedGDIObject<HRGN, win::DeleteObjectTraits<HRGN>>
scoped_hrgn(CreateRectRgn(0, 0, 0, 0));
const int region_type = GetWindowRgn(window, scoped_hrgn.Get());
if (region_type == SIMPLEREGION) {
RECT rect;
GetRgnBox(scoped_hrgn.Get(), &rect);
*result = DesktopRect::MakeLTRB(
rect.left, rect.top, rect.right, rect.bottom);
}
return region_type;
}
AeroChecker::AeroChecker() : dwmapi_library_(nullptr), func_(nullptr) {
// Try to load dwmapi.dll dynamically since it is not available on XP.
dwmapi_library_ = LoadLibrary(L"dwmapi.dll");

View File

@ -37,6 +37,10 @@ bool GetCroppedWindowRect(HWND window,
// APIs fail.
bool GetWindowContentRect(HWND window, DesktopRect* result);
// Returns the region type of the |window| and fill |rect| with the region of
// |window| if region type is SIMPLEREGION.
int GetWindowRegionTypeWithBoundary(HWND window, DesktopRect* result);
typedef HRESULT (WINAPI *DwmIsCompositionEnabledFunc)(BOOL* enabled);
class AeroChecker {
public: