blob: 76368f6b6868955d3249e84b64ceabd8468d35b9 [file]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/test/widget_test.h"
#include "base/functional/callback_helpers.h"
#include "base/rand_util.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/views/test/native_widget_factory.h"
#include "ui/views/widget/root_view.h"
#if BUILDFLAG(IS_MAC)
#include "base/test/scoped_run_loop_timeout.h"
#include "base/test/test_timeouts.h"
#endif
#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
#include "ui/views/test/test_desktop_screen_ozone.h"
#elif BUILDFLAG(IS_WIN)
#include "ui/views/widget/desktop_aura/desktop_screen_win.h"
#endif
namespace views::test {
namespace {
View::Views ShuffledChildren(View* view) {
View::Views children(view->children());
base::RandomShuffle(children.begin(), children.end());
return children;
}
} // namespace
View* AnyViewMatchingPredicate(View* view, const ViewPredicate& predicate) {
if (predicate.Run(view)) {
return view;
}
// Note that we randomize the order of the children, to avoid this function
// always choosing the same View to return out of a set of possible Views.
// If we didn't do this, client code could accidentally depend on a specific
// search order.
for (views::View* child : ShuffledChildren(view)) {
auto* found = AnyViewMatchingPredicate(child, predicate);
if (found) {
return found;
}
}
return nullptr;
}
View* AnyViewMatchingPredicate(Widget* widget, const ViewPredicate& predicate) {
return AnyViewMatchingPredicate(widget->GetRootView(), predicate);
}
View* AnyViewWithClassName(Widget* widget, const std::string& classname) {
return AnyViewMatchingPredicate(widget, [&](const View* view) {
return view->GetClassName() == classname;
});
}
WidgetTest::WidgetTest() = default;
WidgetTest::WidgetTest(
std::unique_ptr<base::test::TaskEnvironment> task_environment)
: ViewsTestBase(std::move(task_environment)) {}
WidgetTest::~WidgetTest() = default;
Widget* WidgetTest::CreateTopLevelPlatformWidget(
Widget::InitParams::Ownership ownership) {
auto widget = std::make_unique<Widget>();
Widget::InitParams params =
CreateParams(ownership, Widget::InitParams::TYPE_WINDOW);
params.native_widget =
CreatePlatformNativeWidgetImpl(widget.get(), kStubCapture, nullptr);
widget->Init(std::move(params));
return widget.release();
}
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
Widget* WidgetTest::CreateTopLevelPlatformDesktopWidget(
Widget::InitParams::Ownership ownership) {
auto widget = std::make_unique<Widget>();
Widget::InitParams params =
CreateParams(ownership, Widget::InitParams::TYPE_WINDOW);
params.native_widget = CreatePlatformDesktopNativeWidgetImpl(
widget.get(), kStubCapture, base::DoNothing());
widget->Init(std::move(params));
return widget.release();
}
#endif
Widget* WidgetTest::CreateTopLevelFramelessPlatformWidget(
Widget::InitParams::Ownership ownership) {
auto widget = std::make_unique<Widget>();
Widget::InitParams params =
CreateParams(ownership, Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.native_widget =
CreatePlatformNativeWidgetImpl(widget.get(), kStubCapture, nullptr);
widget->Init(std::move(params));
return widget.release();
}
Widget* WidgetTest::CreateChildPlatformWidget(
gfx::NativeView parent_native_view,
Widget::InitParams::Ownership ownership) {
Widget::InitParams params =
CreateParams(ownership, Widget::InitParams::TYPE_CONTROL);
params.parent = parent_native_view;
auto child = std::make_unique<Widget>();
params.native_widget =
CreatePlatformNativeWidgetImpl(child.get(), kStubCapture, nullptr);
child->Init(std::move(params));
child->SetContentsView(std::make_unique<View>());
return child.release();
}
Widget* WidgetTest::CreateTopLevelNativeWidget(
Widget::InitParams::Ownership ownership) {
auto toplevel = std::make_unique<Widget>();
Widget::InitParams params =
CreateParams(ownership, Widget::InitParams::TYPE_WINDOW);
toplevel->Init(std::move(params));
return toplevel.release();
}
Widget* WidgetTest::CreateChildNativeWidgetWithParent(
Widget* parent,
Widget::InitParams::Ownership ownership) {
auto child = std::make_unique<Widget>();
Widget::InitParams params =
CreateParams(ownership, Widget::InitParams::TYPE_CONTROL);
params.parent = parent->GetNativeView();
child->Init(std::move(params));
child->SetContentsView(std::make_unique<View>());
return child.release();
}
View* WidgetTest::GetMousePressedHandler(views::internal::RootView* root_view) {
return root_view->mouse_pressed_handler_;
}
View* WidgetTest::GetMouseMoveHandler(views::internal::RootView* root_view) {
return root_view->mouse_move_handler_;
}
View* WidgetTest::GetGestureHandler(views::internal::RootView* root_view) {
return root_view->gesture_handler_;
}
DesktopWidgetTest::DesktopWidgetTest() = default;
DesktopWidgetTest::~DesktopWidgetTest() = default;
void DesktopWidgetTest::SetUp() {
set_native_widget_type(NativeWidgetType::kDesktop);
WidgetTest::SetUp();
}
DesktopWidgetTestInteractive::DesktopWidgetTestInteractive() = default;
DesktopWidgetTestInteractive::~DesktopWidgetTestInteractive() = default;
void DesktopWidgetTestInteractive::SetUp() {
SetUpForInteractiveTests();
#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
screen_ = views::test::TestDesktopScreenOzone::Create();
#elif BUILDFLAG(IS_WIN)
screen_ = std::make_unique<views::DesktopScreenWin>();
#endif
DesktopWidgetTest::SetUp();
}
#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) || BUILDFLAG(IS_WIN)
void DesktopWidgetTestInteractive::TearDown() {
DesktopWidgetTest::TearDown();
screen_.reset();
}
#endif
TestDesktopWidgetDelegate::TestDesktopWidgetDelegate()
: TestDesktopWidgetDelegate(nullptr) {}
TestDesktopWidgetDelegate::TestDesktopWidgetDelegate(Widget* widget)
: widget_(widget) {
SetFocusTraversesOut(true);
if (!widget_) {
owned_widget_ = std::make_unique<Widget>();
widget_ = owned_widget_.get();
}
}
TestDesktopWidgetDelegate::~TestDesktopWidgetDelegate() {
if (widget_) {
widget_->CloseNow();
}
EXPECT_FALSE(widget_);
}
void TestDesktopWidgetDelegate::InitWidget(Widget::InitParams init_params) {
init_params.delegate = this;
init_params.bounds = initial_bounds_;
widget_->Init(std::move(init_params));
}
void TestDesktopWidgetDelegate::WindowClosing() {
window_closing_count_++;
widget_ = nullptr;
contents_view_ = nullptr;
}
Widget* TestDesktopWidgetDelegate::GetWidget() {
return widget_;
}
const Widget* TestDesktopWidgetDelegate::GetWidget() const {
return widget_;
}
View* TestDesktopWidgetDelegate::GetContentsView() {
return contents_view_ ? contents_view_.get()
: WidgetDelegate::GetContentsView();
}
bool TestDesktopWidgetDelegate::OnCloseRequested(
Widget::ClosedReason close_reason) {
last_closed_reason_ = close_reason;
return can_close_;
}
TestInitialFocusWidgetDelegate::TestInitialFocusWidgetDelegate(
gfx::NativeWindow context) {
Widget::InitParams params(Widget::InitParams::CLIENT_OWNS_WIDGET,
Widget::InitParams::TYPE_WINDOW);
params.context = context;
params.delegate = this;
GetWidget()->Init(std::move(params));
view_ =
GetWidget()->GetContentsView()->AddChildView(std::make_unique<View>());
view_->SetFocusBehavior(View::FocusBehavior::ALWAYS);
}
TestInitialFocusWidgetDelegate::~TestInitialFocusWidgetDelegate() = default;
View* TestInitialFocusWidgetDelegate::GetInitiallyFocusedView() {
return view_;
}
WidgetDestroyedWaiter::WidgetDestroyedWaiter(Widget* widget) {
widget_observation_.Observe(widget);
}
WidgetDestroyedWaiter::~WidgetDestroyedWaiter() = default;
void WidgetDestroyedWaiter::Wait() {
run_loop_.Run();
}
void WidgetDestroyedWaiter::OnWidgetDestroyed(Widget* widget) {
widget_observation_.Reset();
run_loop_.Quit();
}
WidgetVisibleWaiter::WidgetVisibleWaiter(Widget* widget) {
widget_observation_.Observe(widget);
}
WidgetVisibleWaiter::~WidgetVisibleWaiter() = default;
void WidgetVisibleWaiter::Wait() {
expecting_visible_ = true;
if (!widget_observation_.GetSource()->IsVisible()) {
run_loop_.Run();
}
}
void WidgetVisibleWaiter::WaitUntilInvisible() {
expecting_visible_ = false;
if (widget_observation_.GetSource()->IsVisible()) {
run_loop_.Run();
}
}
void WidgetVisibleWaiter::OnWidgetVisibilityChanged(Widget* widget,
bool visible) {
if (!run_loop_.running()) {
return;
}
if (visible == expecting_visible_) {
DCHECK(widget_observation_.IsObservingSource(widget));
run_loop_.Quit();
}
}
void WidgetVisibleWaiter::OnWidgetDestroying(Widget* widget) {
if (run_loop_.running()) {
ADD_FAILURE() << "Widget destroying before it became visible!";
}
DCHECK(widget_observation_.IsObservingSource(widget));
widget_observation_.Reset();
}
} // namespace views::test