diff --git a/modules/desktop_capture/cropping_window_capturer_win.cc b/modules/desktop_capture/cropping_window_capturer_win.cc index a5616714ba..b08f4411a5 100644 --- a/modules/desktop_capture/cropping_window_capturer_win.cc +++ b/modules/desktop_capture/cropping_window_capturer_win.cc @@ -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(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. diff --git a/modules/desktop_capture/win/window_capture_utils.cc b/modules/desktop_capture/win/window_capture_utils.cc index 8929bb7de3..219024813a 100644 --- a/modules/desktop_capture/win/window_capture_utils.cc +++ b/modules/desktop_capture/win/window_capture_utils.cc @@ -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_) { diff --git a/modules/desktop_capture/win/window_capture_utils.h b/modules/desktop_capture/win/window_capture_utils.h index 7cb5097aa3..eb4f945dcd 100644 --- a/modules/desktop_capture/win/window_capture_utils.h +++ b/modules/desktop_capture/win/window_capture_utils.h @@ -66,6 +66,7 @@ class WindowCaptureHelperWin { ~WindowCaptureHelperWin(); bool IsAeroEnabled(); + bool IsWindowChromeNotification(HWND hwnd); bool IsWindowOnCurrentDesktop(HWND hwnd); bool IsWindowVisibleOnCurrentDesktop(HWND hwnd);