CroppingWindowCapturerWin: filter out cloaked window.

A cloaked window is composited but not visible to the user.
When Win10 feature 'Cortana' is enabled it creates a window
that is always invisible and its z-order is top most. Because
of that the cropping capturer detects occlusion everywhere
preventing it from capturing anything.

The solution is to ignore all cloaked windows like if
::IsWindowVisible would return false.

Bug: chromium:978885
Change-Id: Id5aa8dc81dcf4979ffb30dd808fa2a553934c6e6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143980
Commit-Queue: Julien Isorce <julien.isorce@chromium.org>
Reviewed-by: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: Guido Urdaneta <guidou@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28510}
This commit is contained in:
Julien Isorce
2019-07-08 11:35:18 -07:00
committed by Commit Bot
parent a0eefc17f7
commit 5e25facefd
2 changed files with 36 additions and 8 deletions

View File

@ -10,6 +10,9 @@
#include "modules/desktop_capture/win/window_capture_utils.h"
// Just for the DWMWINDOWATTRIBUTE enums (DWMWA_CLOAKED).
#include <dwmapi.h>
#include "modules/desktop_capture/win/scoped_gdi_object.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
@ -137,15 +140,15 @@ bool IsWindowMaximized(HWND window, bool* result) {
}
// WindowCaptureHelperWin implementation.
WindowCaptureHelperWin::WindowCaptureHelperWin()
: dwmapi_library_(nullptr),
func_(nullptr),
virtual_desktop_manager_(nullptr) {
WindowCaptureHelperWin::WindowCaptureHelperWin() {
// Try to load dwmapi.dll dynamically since it is not available on XP.
dwmapi_library_ = LoadLibraryW(L"dwmapi.dll");
if (dwmapi_library_) {
func_ = reinterpret_cast<DwmIsCompositionEnabledFunc>(
GetProcAddress(dwmapi_library_, "DwmIsCompositionEnabled"));
dwm_get_window_attribute_func_ =
reinterpret_cast<DwmGetWindowAttributeFunc>(
GetProcAddress(dwmapi_library_, "DwmGetWindowAttribute"));
}
if (rtc::IsWindows10OrLater()) {
@ -268,7 +271,25 @@ bool WindowCaptureHelperWin::IsWindowOnCurrentDesktop(HWND hwnd) {
bool WindowCaptureHelperWin::IsWindowVisibleOnCurrentDesktop(HWND hwnd) {
return !::IsIconic(hwnd) && ::IsWindowVisible(hwnd) &&
IsWindowOnCurrentDesktop(hwnd);
IsWindowOnCurrentDesktop(hwnd) && !IsWindowCloaked(hwnd);
}
// A cloaked window is composited but not visible to the user.
// Example: Cortana or the Action Center when collapsed.
bool WindowCaptureHelperWin::IsWindowCloaked(HWND hwnd) {
if (!dwm_get_window_attribute_func_) {
// Does not apply.
return false;
}
int res = 0;
if (dwm_get_window_attribute_func_(hwnd, DWMWA_CLOAKED, &res, sizeof(res)) !=
S_OK) {
// Cannot tell so assume not cloacked for backward compatibility.
return false;
}
return res != 0;
}
} // namespace webrtc

View File

@ -60,6 +60,10 @@ bool GetDcSize(HDC hdc, DesktopSize* size);
bool IsWindowMaximized(HWND window, bool* result);
typedef HRESULT(WINAPI* DwmIsCompositionEnabledFunc)(BOOL* enabled);
typedef HRESULT(WINAPI* DwmGetWindowAttributeFunc)(HWND hwnd,
DWORD dwAttribute,
PVOID pvAttribute,
DWORD cbAttribute);
class WindowCaptureHelperWin {
public:
WindowCaptureHelperWin();
@ -73,13 +77,16 @@ class WindowCaptureHelperWin {
const DesktopRect& selected_window_rect);
bool IsWindowOnCurrentDesktop(HWND hwnd);
bool IsWindowVisibleOnCurrentDesktop(HWND hwnd);
bool IsWindowCloaked(HWND hwnd);
private:
HMODULE dwmapi_library_;
DwmIsCompositionEnabledFunc func_;
HMODULE dwmapi_library_ = nullptr;
DwmIsCompositionEnabledFunc func_ = nullptr;
DwmGetWindowAttributeFunc dwm_get_window_attribute_func_ = nullptr;
// Only used on Win10+.
Microsoft::WRL::ComPtr<IVirtualDesktopManager> virtual_desktop_manager_;
Microsoft::WRL::ComPtr<IVirtualDesktopManager> virtual_desktop_manager_ =
nullptr;
RTC_DISALLOW_COPY_AND_ASSIGN(WindowCaptureHelperWin);
};