On Windows a window may be covered by its own child window. So this change also detects child windows by using EnumChildWindow(). The tooltip or context menu of the child window still cannot be detected after this change. See bug for details. Bug: webrtc:8062 Change-Id: I8455a9206d6a1d9da61013ac9debba4d3edae7d8 Reviewed-on: https://chromium-review.googlesource.com/619728 Commit-Queue: Zijie He <zijiehe@chromium.org> Reviewed-by: Jamie Walch <jamiewalch@chromium.org> Cr-Commit-Position: refs/heads/master@{#19457}
125 lines
4.0 KiB
C++
125 lines
4.0 KiB
C++
/*
|
|
* Copyright (c) 2014 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/window_capture_utils.h"
|
|
|
|
#include "webrtc/rtc_base/checks.h"
|
|
#include "webrtc/rtc_base/win32.h"
|
|
|
|
namespace webrtc {
|
|
|
|
bool GetWindowRect(HWND window, DesktopRect* result) {
|
|
RECT rect;
|
|
if (!::GetWindowRect(window, &rect)) {
|
|
return false;
|
|
}
|
|
*result = DesktopRect::MakeLTRB(
|
|
rect.left, rect.top, rect.right, rect.bottom);
|
|
return true;
|
|
}
|
|
|
|
bool GetCroppedWindowRect(HWND window,
|
|
DesktopRect* cropped_rect,
|
|
DesktopRect* original_rect) {
|
|
DesktopRect window_rect;
|
|
if (!GetWindowRect(window, &window_rect)) {
|
|
return false;
|
|
}
|
|
|
|
if (original_rect) {
|
|
*original_rect = window_rect;
|
|
}
|
|
*cropped_rect = window_rect;
|
|
|
|
WINDOWPLACEMENT window_placement;
|
|
window_placement.length = sizeof(window_placement);
|
|
if (!::GetWindowPlacement(window, &window_placement)) {
|
|
return false;
|
|
}
|
|
|
|
// After Windows8, transparent borders will be added by OS at
|
|
// left/bottom/right sides of a window. If the cropped window
|
|
// doesn't remove these borders, the background will be exposed a bit.
|
|
//
|
|
// On Windows 8.1. or upper, rtc::IsWindows8OrLater(), which uses
|
|
// GetVersionEx() may not correctly return the windows version. See
|
|
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx
|
|
// So we always prefer to check |window_placement|.showCmd.
|
|
if (rtc::IsWindows8OrLater() ||
|
|
window_placement.showCmd == SW_SHOWMAXIMIZED) {
|
|
const int width = GetSystemMetrics(SM_CXSIZEFRAME);
|
|
const int height = GetSystemMetrics(SM_CYSIZEFRAME);
|
|
cropped_rect->Extend(-width, 0, -width, -height);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GetWindowContentRect(HWND window, DesktopRect* result) {
|
|
if (!GetWindowRect(window, result)) {
|
|
return false;
|
|
}
|
|
|
|
RECT rect;
|
|
if (!::GetClientRect(window, &rect)) {
|
|
return false;
|
|
}
|
|
|
|
const int width = rect.right - rect.left;
|
|
// The GetClientRect() is not expected to return a larger area than
|
|
// GetWindowRect().
|
|
if (width > 0 && width < result->width()) {
|
|
// - GetClientRect() always set the left / top of RECT to 0. So we need to
|
|
// estimate the border width from GetClientRect() and GetWindowRect().
|
|
// - Border width of a window varies according to the window type.
|
|
// - GetClientRect() excludes the title bar, which should be considered as
|
|
// part of the content and included in the captured frame. So we always
|
|
// estimate the border width according to the window width.
|
|
// - We assume a window has same border width in each side.
|
|
// So we shrink half of the width difference from all four sides.
|
|
const int shrink = ((width - result->width()) / 2);
|
|
// When |shrink| is negative, DesktopRect::Extend() shrinks itself.
|
|
result->Extend(shrink, 0, shrink, 0);
|
|
// Usually this should not happen, just in case we have received a strange
|
|
// window, which has only left and right borders.
|
|
if (result->height() > shrink * 2) {
|
|
result->Extend(0, shrink, 0, shrink);
|
|
}
|
|
RTC_DCHECK(!result->is_empty());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
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");
|
|
if (dwmapi_library_) {
|
|
func_ = reinterpret_cast<DwmIsCompositionEnabledFunc>(
|
|
GetProcAddress(dwmapi_library_, "DwmIsCompositionEnabled"));
|
|
}
|
|
}
|
|
|
|
AeroChecker::~AeroChecker() {
|
|
if (dwmapi_library_) {
|
|
FreeLibrary(dwmapi_library_);
|
|
}
|
|
}
|
|
|
|
bool AeroChecker::IsAeroEnabled() {
|
|
BOOL result = FALSE;
|
|
if (func_) {
|
|
func_(&result);
|
|
}
|
|
return result != FALSE;
|
|
}
|
|
|
|
} // namespace webrtc
|