Avoid capturing extraneous windows in CroppingWindowCapturerWin

This change reduces cases where capturing a window with the cropping
capturer captures unrelated windows from the same process. For instance:
- Capturing an Explorer window could include portions of taskbar UI,
  e.g. when an auto-hide taskbar or window preview thumbnails are shown
  overtop.
- Capturing a window from a process with multiple windows could include
  menus/tooltips from another window.

Instead of capturing any window with an empty/matching title created by
the same process, the cropping capturer will capture any window created
by the same thread. While not foolproof, this heuristic seems to capture
menus/tooltips from the window of interest while excluding those from
other top-level windows in practice (assuming those were created by a
separate thread / independent message pump).

Bug: webrtc:10856
Change-Id: I2072c79da9e0158475b442a43b5b96d6ad307bc2
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/148641
Reviewed-by: Jamie Walch <jamiewalch@chromium.org>
Commit-Queue: Jamie Walch <jamiewalch@chromium.org>
Cr-Commit-Position: refs/heads/master@{#28824}
This commit is contained in:
Bryan Ferguson 2019-08-08 16:41:02 -07:00 committed by Commit Bot
parent e427996c61
commit 1544915bb4

View File

@ -37,7 +37,8 @@ struct TopWindowVerifierContext {
RTC_DCHECK_NE(selected_window, excluded_window);
GetWindowTextW(selected_window, selected_window_title, kTitleLength);
GetWindowThreadProcessId(selected_window, &selected_window_process_id);
selected_window_thread_id =
GetWindowThreadProcessId(selected_window, &selected_window_process_id);
}
const HWND selected_window;
@ -46,6 +47,7 @@ struct TopWindowVerifierContext {
WindowCaptureHelperWin* window_capture_helper;
WCHAR selected_window_title[kTitleLength];
DWORD selected_window_process_id;
DWORD selected_window_thread_id;
bool is_top_window;
};
@ -93,19 +95,15 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
return TRUE;
}
// If |hwnd| has no title or has same title as the selected window (i.e.
// 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.
WCHAR window_title[kTitleLength];
GetWindowTextW(hwnd, window_title, kTitleLength);
if (wcsnlen_s(window_title, kTitleLength) == 0 ||
wcscmp(window_title, context->selected_window_title) == 0) {
DWORD enumerated_window_process_id;
GetWindowThreadProcessId(hwnd, &enumerated_window_process_id);
if (context->selected_window_process_id == enumerated_window_process_id) {
return TRUE;
}
// Ignore windows that belong to the same thread since we want to capture
// them. This check works for tooltips & context menus.
DWORD enumerated_window_process_id = 0;
DWORD enumerated_window_thread_id =
GetWindowThreadProcessId(hwnd, &enumerated_window_process_id);
if (enumerated_window_thread_id != 0 &&
enumerated_window_process_id == context->selected_window_process_id &&
enumerated_window_thread_id == context->selected_window_thread_id) {
return TRUE;
}
// Checks whether current window |hwnd| intersects with