diff --git a/modules/desktop_capture/cropping_window_capturer_win.cc b/modules/desktop_capture/cropping_window_capturer_win.cc index 20c54663cb..dc9ceb8115 100644 --- a/modules/desktop_capture/cropping_window_capturer_win.cc +++ b/modules/desktop_capture/cropping_window_capturer_win.cc @@ -117,36 +117,13 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) { // 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. + if (context->window_capture_helper->IsWindowIntersectWithSelectedWindow( + hwnd, context->selected_window, context->selected_window_rect)) { + // If intersection is not empty, the selected window is not on top. context->is_top_window = false; return FALSE; } - content_rect.IntersectWith(context->selected_window_rect); - - // If intersection is not empty, the selected window is not on top. - if (!content_rect.is_empty()) { - context->is_top_window = false; - return FALSE; - } // Otherwise, keep enumerating. return TRUE; } diff --git a/modules/desktop_capture/win/window_capture_utils.cc b/modules/desktop_capture/win/window_capture_utils.cc index 4c5489fa71..f2e9052482 100644 --- a/modules/desktop_capture/win/window_capture_utils.cc +++ b/modules/desktop_capture/win/window_capture_utils.cc @@ -20,6 +20,9 @@ namespace webrtc { // Prefix used to match the window class for Chrome windows. const wchar_t kChromeWindowClassPrefix[] = L"Chrome_WidgetWin_"; +// The hiddgen taskbar will leave a 2 pixel margin on the screen. +const int kHiddenTaskbarMarginOnScreen = 2; + bool GetWindowRect(HWND window, DesktopRect* result) { RECT rect; if (!::GetWindowRect(window, &rect)) { @@ -199,6 +202,58 @@ bool WindowCaptureHelperWin::IsWindowChromeNotification(HWND hwnd) { return false; } +// |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. +bool WindowCaptureHelperWin::IsWindowIntersectWithSelectedWindow( + HWND hwnd, + HWND selected_hwnd, + const DesktopRect& selected_window_rect) { + DesktopRect content_rect; + if (!GetWindowContentRect(hwnd, &content_rect)) { + // Bail out if failed to get the window area. + return true; + } + content_rect.IntersectWith(selected_window_rect); + + if (content_rect.is_empty()) { + return false; + } + + // When the taskbar is automatically hidden, it will leave a 2 pixel margin on + // the screen which will overlap the maximized selected window that will use + // up the full screen area. Since there is no solid way to identify a hidden + // taskbar window, we have to make an exemption here if the overlapping is + // 2 x screen_width/height to a maximized window. + bool is_maximized = false; + IsWindowMaximized(selected_hwnd, &is_maximized); + bool overlaps_hidden_horizontal_taskbar = + selected_window_rect.width() == content_rect.width() && + content_rect.height() == kHiddenTaskbarMarginOnScreen; + bool overlaps_hidden_vertical_taskbar = + selected_window_rect.height() == content_rect.height() && + content_rect.width() == kHiddenTaskbarMarginOnScreen; + if (is_maximized && (overlaps_hidden_horizontal_taskbar || + overlaps_hidden_vertical_taskbar)) { + return false; + } + + return true; +} + bool WindowCaptureHelperWin::IsWindowOnCurrentDesktop(HWND hwnd) { // Make sure the window is on the current virtual desktop. if (virtual_desktop_manager_) { diff --git a/modules/desktop_capture/win/window_capture_utils.h b/modules/desktop_capture/win/window_capture_utils.h index 529d1b65a6..1dfcf9f7e4 100644 --- a/modules/desktop_capture/win/window_capture_utils.h +++ b/modules/desktop_capture/win/window_capture_utils.h @@ -67,6 +67,10 @@ class WindowCaptureHelperWin { bool IsAeroEnabled(); bool IsWindowChromeNotification(HWND hwnd); + bool IsWindowIntersectWithSelectedWindow( + HWND hwnd, + HWND selected_hwnd, + const DesktopRect& selected_window_rect); bool IsWindowOnCurrentDesktop(HWND hwnd); bool IsWindowVisibleOnCurrentDesktop(HWND hwnd);