diff --git a/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc b/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc index 27be392651..6b046d8149 100644 --- a/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc +++ b/webrtc/modules/desktop_capture/cropping_window_capturer_win.cc @@ -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(selected_window()); + const HWND selected = reinterpret_cast(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 > - scoped_hrgn(CreateRectRgn(0, 0, 0, 0)); - int region_type = GetWindowRgn(selected, scoped_hrgn.Get()); + const int region_type = + GetWindowRegionTypeWithBoundary(selected, ®ion_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(), ®ion_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_|. diff --git a/webrtc/modules/desktop_capture/win/window_capture_utils.cc b/webrtc/modules/desktop_capture/win/window_capture_utils.cc index abcb6a641a..07da6ee6af 100644 --- a/webrtc/modules/desktop_capture/win/window_capture_utils.cc +++ b/webrtc/modules/desktop_capture/win/window_capture_utils.cc @@ -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> + 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"); diff --git a/webrtc/modules/desktop_capture/win/window_capture_utils.h b/webrtc/modules/desktop_capture/win/window_capture_utils.h index 255963e054..c889c16aed 100644 --- a/webrtc/modules/desktop_capture/win/window_capture_utils.h +++ b/webrtc/modules/desktop_capture/win/window_capture_utils.h @@ -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: