You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
5.7 KiB
179 lines
5.7 KiB
7 months ago
|
/*
|
||
|
* Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by a BSD-style license
|
||
|
* that can be found in the LICENSE file in the root of the source
|
||
|
* tree. An additional intellectual property rights grant can be found
|
||
|
* in the file PATENTS. All contributing project authors may
|
||
|
* be found in the AUTHORS file in the root of the source tree.
|
||
|
*/
|
||
|
|
||
|
#include "modules/desktop_capture/window_finder.h"
|
||
|
|
||
|
#include <stdint.h>
|
||
|
|
||
|
#include <memory>
|
||
|
|
||
|
#include "api/scoped_refptr.h"
|
||
|
#include "modules/desktop_capture/desktop_geometry.h"
|
||
|
#include "modules/desktop_capture/screen_drawer.h"
|
||
|
#include "rtc_base/logging.h"
|
||
|
#include "test/gtest.h"
|
||
|
|
||
|
#if defined(WEBRTC_USE_X11)
|
||
|
#include "modules/desktop_capture/linux/shared_x_display.h"
|
||
|
#include "modules/desktop_capture/linux/x_atom_cache.h"
|
||
|
#endif
|
||
|
|
||
|
#if defined(WEBRTC_WIN)
|
||
|
#include <windows.h>
|
||
|
|
||
|
#include "modules/desktop_capture/win/window_capture_utils.h"
|
||
|
#include "modules/desktop_capture/window_finder_win.h"
|
||
|
#endif
|
||
|
|
||
|
namespace webrtc {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
#if defined(WEBRTC_WIN)
|
||
|
// ScreenDrawerWin does not have a message loop, so it's unresponsive to user
|
||
|
// inputs. WindowFinderWin cannot detect this kind of unresponsive windows.
|
||
|
// Instead, console window is used to test WindowFinderWin.
|
||
|
TEST(WindowFinderTest, FindConsoleWindow) {
|
||
|
// Creates a ScreenDrawer to avoid this test from conflicting with
|
||
|
// ScreenCapturerIntegrationTest: both tests require its window to be in
|
||
|
// foreground.
|
||
|
//
|
||
|
// In ScreenCapturer related tests, this is controlled by
|
||
|
// ScreenDrawer, which has a global lock to ensure only one ScreenDrawer
|
||
|
// window is active. So even we do not use ScreenDrawer for Windows test,
|
||
|
// creating an instance can block ScreenCapturer related tests until this test
|
||
|
// finishes.
|
||
|
//
|
||
|
// Usually the test framework should take care of this "isolated test"
|
||
|
// requirement, but unfortunately WebRTC trybots do not support this.
|
||
|
std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
|
||
|
const int kMaxSize = 10000;
|
||
|
// Enlarges current console window.
|
||
|
system("mode 1000,1000");
|
||
|
const HWND console_window = GetConsoleWindow();
|
||
|
// Ensures that current console window is visible.
|
||
|
ShowWindow(console_window, SW_MAXIMIZE);
|
||
|
// Moves the window to the top-left of the display.
|
||
|
MoveWindow(console_window, 0, 0, kMaxSize, kMaxSize, true);
|
||
|
|
||
|
bool should_restore_notopmost =
|
||
|
(GetWindowLong(console_window, GWL_EXSTYLE) & WS_EX_TOPMOST) == 0;
|
||
|
|
||
|
// Brings console window to top.
|
||
|
SetWindowPos(console_window, HWND_TOPMOST, 0, 0, 0, 0,
|
||
|
SWP_NOMOVE | SWP_NOSIZE);
|
||
|
BringWindowToTop(console_window);
|
||
|
|
||
|
bool success = false;
|
||
|
WindowFinderWin finder;
|
||
|
for (int i = 0; i < kMaxSize; i++) {
|
||
|
const DesktopVector spot(i, i);
|
||
|
const HWND id = reinterpret_cast<HWND>(finder.GetWindowUnderPoint(spot));
|
||
|
if (id == console_window) {
|
||
|
success = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (should_restore_notopmost)
|
||
|
SetWindowPos(console_window, HWND_NOTOPMOST, 0, 0, 0, 0,
|
||
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||
|
|
||
|
if (!success)
|
||
|
FAIL();
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
TEST(WindowFinderTest, FindDrawerWindow) {
|
||
|
WindowFinder::Options options;
|
||
|
#if defined(WEBRTC_USE_X11)
|
||
|
std::unique_ptr<XAtomCache> cache;
|
||
|
const auto shared_x_display = SharedXDisplay::CreateDefault();
|
||
|
if (shared_x_display) {
|
||
|
cache = std::make_unique<XAtomCache>(shared_x_display->display());
|
||
|
options.cache = cache.get();
|
||
|
}
|
||
|
#endif
|
||
|
std::unique_ptr<WindowFinder> finder = WindowFinder::Create(options);
|
||
|
if (!finder) {
|
||
|
RTC_LOG(LS_WARNING)
|
||
|
<< "No WindowFinder implementation for current platform.";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
|
||
|
if (!drawer) {
|
||
|
RTC_LOG(LS_WARNING)
|
||
|
<< "No ScreenDrawer implementation for current platform.";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (drawer->window_id() == kNullWindowId) {
|
||
|
// TODO(zijiehe): WindowFinderTest can use a dedicated window without
|
||
|
// relying on ScreenDrawer.
|
||
|
RTC_LOG(LS_WARNING)
|
||
|
<< "ScreenDrawer implementation for current platform does "
|
||
|
"create a window.";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// ScreenDrawer may not be able to bring the window to the top. So we test
|
||
|
// several spots, at least one of them should succeed.
|
||
|
const DesktopRect region = drawer->DrawableRegion();
|
||
|
if (region.is_empty()) {
|
||
|
RTC_LOG(LS_WARNING)
|
||
|
<< "ScreenDrawer::DrawableRegion() is too small for the "
|
||
|
"WindowFinderTest.";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < region.width(); i++) {
|
||
|
const DesktopVector spot(
|
||
|
region.left() + i, region.top() + i * region.height() / region.width());
|
||
|
const WindowId id = finder->GetWindowUnderPoint(spot);
|
||
|
if (id == drawer->window_id()) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FAIL();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
TEST(WindowFinderTest, ShouldReturnNullWindowIfSpotIsOutOfScreen) {
|
||
|
WindowFinder::Options options;
|
||
|
#if defined(WEBRTC_USE_X11)
|
||
|
std::unique_ptr<XAtomCache> cache;
|
||
|
const auto shared_x_display = SharedXDisplay::CreateDefault();
|
||
|
if (shared_x_display) {
|
||
|
cache = std::make_unique<XAtomCache>(shared_x_display->display());
|
||
|
options.cache = cache.get();
|
||
|
}
|
||
|
#endif
|
||
|
std::unique_ptr<WindowFinder> finder = WindowFinder::Create(options);
|
||
|
if (!finder) {
|
||
|
RTC_LOG(LS_WARNING)
|
||
|
<< "No WindowFinder implementation for current platform.";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ASSERT_EQ(kNullWindowId,
|
||
|
finder->GetWindowUnderPoint(DesktopVector(INT16_MAX, INT16_MAX)));
|
||
|
ASSERT_EQ(kNullWindowId,
|
||
|
finder->GetWindowUnderPoint(DesktopVector(INT16_MAX, INT16_MIN)));
|
||
|
ASSERT_EQ(kNullWindowId,
|
||
|
finder->GetWindowUnderPoint(DesktopVector(INT16_MIN, INT16_MAX)));
|
||
|
ASSERT_EQ(kNullWindowId,
|
||
|
finder->GetWindowUnderPoint(DesktopVector(INT16_MIN, INT16_MIN)));
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
} // namespace webrtc
|