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-Original-Commit-Position: refs/heads/master@{#19532}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 2a47e5dfc8ff9ce2f6b54e05149eb39299ecc92a
diff --git a/modules/desktop_capture/cropping_window_capturer_win.cc b/modules/desktop_capture/cropping_window_capturer_win.cc
index 6b046d8..5730e43 100644
--- a/modules/desktop_capture/cropping_window_capturer_win.cc
+++ b/modules/desktop_capture/cropping_window_capturer_win.cc
@@ -90,20 +90,35 @@
     }
   }
 
-  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 @@
 
   // 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) {