Use windows' content rectangles rather than their borders to determine overlapping

If the content area of a window is not covered by the content area of another
window, we do not treat them as overlapping. This can fix the issue that two
fullscreen windows cover each other, or a fullscreen window is covered by the
shadow effect of task bar.

Bug: chromium:741770
Change-Id: I92dc636bc8445d50b00390cf3332695f69daf9c6
Reviewed-on: https://chromium-review.googlesource.com/628244
Commit-Queue: Zijie He <zijiehe@chromium.org>
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#19532}
This commit is contained in:
Zijie He 2017-08-25 17:42:38 -07:00 committed by Commit Bot
parent af5686a229
commit 2a47e5dfc8

View File

@ -90,20 +90,35 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
}
}
DesktopRect window_rect;
// TODO(zijiehe): Window content rectangle should be preferred to avoid
// falling back to window capturer when the border or shadow of another window
// covering the target window.
if (!GetWindowRect(hwnd, &window_rect)) {
// Checks whether current window |hwnd| intersects with
// |context|->selected_window.
// |content_rect| is preferred because,
// 1. WindowCapturerWin is using GDI capturer, which cannot capture DX output.
// So ScreenCapturer should be used as much as possible to avoid
// uncapturable cases. Note: lots of new applications are using DX output
// (hardware acceleration) to improve the performance which cannot be
// captured by WindowCapturerWin. See bug http://crbug.com/741770.
// 2. WindowCapturerWin is still useful because we do not want to expose the
// content on other windows if the target window is covered by them.
// 3. Shadow and borders should not be considered as "content" on other
// windows because they do not expose any useful information.
//
// So we can bear the false-negative cases (target window is covered by the
// borders or shadow of other windows, but we have not detected it) in favor
// of using ScreenCapturer, rather than let the false-positive cases (target
// windows is only covered by borders or shadow of other windows, but we treat
// it as overlapping) impact the user experience.
DesktopRect content_rect;
if (!GetWindowContentRect(hwnd, &content_rect)) {
// Bail out if failed to get the window area.
context->is_top_window = false;
return FALSE;
}
window_rect.IntersectWith(context->selected_window_rect);
content_rect.IntersectWith(context->selected_window_rect);
// If intersection is not empty, the selected window is not on top.
if (!window_rect.is_empty()) {
if (!content_rect.is_empty()) {
context->is_top_window = false;
return FALSE;
}
@ -206,11 +221,10 @@ bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
// Check if the window is occluded by any other window, excluding the child
// windows, context menus, and |excluded_window_|.
// TODO(zijiehe): Content rectangle should be preferred to avoid falling back
// to window capturer when border or shadow of another window covering the
// target window.
// |content_rect| is preferred, see the comments in TopWindowVerifier()
// function.
TopWindowVerifierContext context(
selected, reinterpret_cast<HWND>(excluded_window()), window_region_rect_);
selected, reinterpret_cast<HWND>(excluded_window()), content_rect);
const LPARAM enum_param = reinterpret_cast<LPARAM>(&context);
EnumWindows(&TopWindowVerifier, enum_param);
if (!context.is_top_window) {