[desktopCapture Windows] ignore Chrome notification window on top
Chrome uses Windows native framework to show the notification of the ongoing presenting. This notification window is enumerated as a separated window which is on top most. If this window blocks the target window, Chrome can't do the cropping and has to switch to GDI methods. If GDI methods can't capture the target window, then capturing will fail until the notification is dismissed. It's hard to identify the notification window in EnumWindows() callback. So far it works if we ignore window with no title and class name prefixed with "Chrome_WidgetWin_" and with certain extended styles, as so does in this CL. Bug: chromium:847664 Change-Id: Iafabcb1f685adb91bf092475642151e1475cdf61 Reviewed-on: https://webrtc-review.googlesource.com/79742 Reviewed-by: Jamie Walch <jamiewalch@chromium.org> Commit-Queue: Brave Yao <braveyao@webrtc.org> Cr-Commit-Position: refs/heads/master@{#23474}
This commit is contained in:
@ -44,6 +44,10 @@ struct TopWindowVerifierContext {
|
||||
|
||||
// The function is called during EnumWindow for every window enumerated and is
|
||||
// responsible for verifying if the selected window is on top.
|
||||
// Return TRUE to continue enumerating if the current window belongs to the
|
||||
// selected window or is to be ignored.
|
||||
// Return FALSE to stop enumerating if the selected window is found or decided
|
||||
// if it's on top most.
|
||||
BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
|
||||
TopWindowVerifierContext* context =
|
||||
reinterpret_cast<TopWindowVerifierContext*>(param);
|
||||
@ -63,6 +67,17 @@ BOOL CALLBACK TopWindowVerifier(HWND hwnd, LPARAM param) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Ignore Chrome notification windows, especially the notification for the
|
||||
// ongoing window sharing.
|
||||
// Notes:
|
||||
// - This only works with notifications from Chrome, not other Apps.
|
||||
// - All notifications from Chrome will be ignored.
|
||||
// - This may cause part or whole of notification window being cropped into
|
||||
// the capturing of the target window if there is overlapping.
|
||||
if (context->window_capture_helper->IsWindowChromeNotification(hwnd)) {
|
||||
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.
|
||||
|
@ -17,6 +17,9 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Prefix used to match the window class for Chrome windows.
|
||||
const wchar_t kChromeWindowClassPrefix[] = L"Chrome_WidgetWin_";
|
||||
|
||||
bool GetWindowRect(HWND window, DesktopRect* result) {
|
||||
RECT rect;
|
||||
if (!::GetWindowRect(window, &rect)) {
|
||||
@ -166,6 +169,37 @@ bool WindowCaptureHelperWin::IsAeroEnabled() {
|
||||
return result != FALSE;
|
||||
}
|
||||
|
||||
// This is just a best guess of a notification window. Chrome uses the Windows
|
||||
// native framework for showing notifications. So far what we know about such a
|
||||
// window includes: no title, class name with prefix "Chrome_WidgetWin_" and
|
||||
// with certain extended styles.
|
||||
bool WindowCaptureHelperWin::IsWindowChromeNotification(HWND hwnd) {
|
||||
const size_t kTitleLength = 32;
|
||||
WCHAR window_title[kTitleLength];
|
||||
GetWindowText(hwnd, window_title, kTitleLength);
|
||||
if (wcsnlen_s(window_title, kTitleLength) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t kClassLength = 256;
|
||||
WCHAR class_name[kClassLength];
|
||||
const int class_name_length = GetClassName(hwnd, class_name, kClassLength);
|
||||
RTC_DCHECK(class_name_length)
|
||||
<< "Error retrieving the application's class name";
|
||||
if (wcsncmp(class_name, kChromeWindowClassPrefix,
|
||||
wcsnlen_s(kChromeWindowClassPrefix, kClassLength)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
if ((exstyle & WS_EX_NOACTIVATE) && (exstyle & WS_EX_TOOLWINDOW) &&
|
||||
(exstyle & WS_EX_TOPMOST)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WindowCaptureHelperWin::IsWindowOnCurrentDesktop(HWND hwnd) {
|
||||
// Make sure the window is on the current virtual desktop.
|
||||
if (virtual_desktop_manager_) {
|
||||
|
@ -66,6 +66,7 @@ class WindowCaptureHelperWin {
|
||||
~WindowCaptureHelperWin();
|
||||
|
||||
bool IsAeroEnabled();
|
||||
bool IsWindowChromeNotification(HWND hwnd);
|
||||
bool IsWindowOnCurrentDesktop(HWND hwnd);
|
||||
bool IsWindowVisibleOnCurrentDesktop(HWND hwnd);
|
||||
|
||||
|
Reference in New Issue
Block a user