Include overlapping dialogs when capturing a window via screen cropping

This change includes windows owned by the primary captured window in the
captured frames if these conditions are met:
1) The owned window (e.g. dialog) overlaps the primary window (in whole
or part)
2) The primary window is otherwise eligible for the crop-from-screen
path (CroppingWindowCapturer is being used, and other conditions in
ShouldUseScreenCapturer are met)

In practice, this means that dialog windows / message boxes are captured
in many cases where they aren't today. This seems beneficial to some
scenarios (e.g. demonstrating / recording how to do something, or
requesting help with something, that involves dialogs).

This is a logical revert of a change for https://crbug.com/webrtc/8062 .
There's some commentary in the newer bug that attempts to make a case
for revisiting that change. (In summary: cases where a dialog would be
substantialy clipped / partial seem relatively uncommon and have
workarounds. Clipping may already occur for menus & tooltips. Clipping
seems less surprising than complete absence.)

Changing the GA_ROOT flag back to GA_ROOTOWNER is sufficient to restore
the older behavior. The removal of the EnumChildWindows call is just a
minor optimization (it was unnecessary/superfluous, since every child
window would match the GA_ROOT check; dialogs are owned root windows,
not child windows).

Removing condition (2) above (capturing dialogs & other related
overlapping windows when not using the crop-from-screen path) is tracked
by https://crbug.com/980864 .

Bug: webrtc:10767
Change-Id: If7b418365685a7b96dc93901ef9367844f9ee99e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/147421
Commit-Queue: Jamie Walch <jamiewalch@chromium.org>
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#28711}
This commit is contained in:
Bryan Ferguson 2019-07-30 15:37:17 -07:00 committed by Commit Bot
parent 5ae853a163
commit e08ca23ec9

View file

@ -85,15 +85,11 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
return TRUE;
}
// Ignore descendant windows since we want to capture them.
// This check does not work for tooltips and context menus. Drop down menus
// and popup windows are fine.
//
// GA_ROOT returns the root window instead of the owner. I.e. for a dialog
// window, GA_ROOT returns the dialog window itself. GA_ROOTOWNER returns the
// application main window which opens the dialog window. Since we are sharing
// the application main window, GA_ROOT should be used here.
if (GetAncestor(hwnd, GA_ROOT) == context->selected_window) {
// Ignore descendant/owned windows since we want to capture them. This check
// works for drop-down menus, pop-up (dialog) windows, and child (confined)
// windows. It doesn't work for tooltips or context menus, which are handled
// differently below.
if (GetAncestor(hwnd, GA_ROOTOWNER) == context->selected_window) {
return TRUE;
}
@ -101,9 +97,6 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
// Window Media Player consisting of several sibling windows) and belongs to
// the same process, assume it's a tooltip or context menu or sibling window
// from the selected window and ignore it.
// TODO(zijiehe): This check cannot cover the case where tooltip or context
// menu of the child-window is covering the main window. See
// https://bugs.chromium.org/p/webrtc/issues/detail?id=8062 for details.
WCHAR window_title[kTitleLength];
GetWindowTextW(hwnd, window_title, kTitleLength);
if (wcsnlen_s(window_title, kTitleLength) == 0 ||
@ -227,17 +220,7 @@ bool CroppingWindowCapturerWin::ShouldUseScreenCapturer() {
TopWindowVerifierContext context(selected,
reinterpret_cast<HWND>(excluded_window()),
content_rect, &window_capture_helper_);
const LPARAM enum_param = reinterpret_cast<LPARAM>(&context);
EnumWindows(&TopWindowVerifier, enum_param);
if (!context.is_top_window) {
return false;
}
// If |selected| is not covered by other windows, check whether it is
// covered by its own child windows. Note: EnumChildWindows() enumerates child
// windows in all generations, but does not include any controls like buttons
// or textboxes.
EnumChildWindows(selected, &TopWindowVerifier, enum_param);
EnumWindows(&TopWindowVerifier, reinterpret_cast<LPARAM>(&context));
return context.is_top_window;
}