#ifndef UI_VIEWS_TEST_WIDGET_TEST_H_
#define UI_VIEWS_TEST_WIDGET_TEST_H_
#include <memory>
#include <string>
#include <utility>
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/test/bind.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/widget/widget_observer.h"
#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) || \
BUILDFLAG(IS_CHROMEOS_LACROS)
#include "ui/display/screen.h"
#endif
namespace ui {
class EventSink;
class ImeKeyEventDispatcher;
}
namespace views {
class View;
class Widget;
namespace internal {
class RootView;
}
namespace test {
using ViewPredicate = base::RepeatingCallback<bool(const View*)>;
View* AnyViewMatchingPredicate(View* root, const ViewPredicate& predicate);
template <typename Pred>
View* AnyViewMatchingPredicate(View* root, Pred predicate) {
return AnyViewMatchingPredicate(root, base::BindLambdaForTesting(predicate));
}
View* AnyViewMatchingPredicate(Widget* widget, const ViewPredicate& predicate);
template <typename Pred>
View* AnyViewMatchingPredicate(Widget* widget, Pred predicate) {
return AnyViewMatchingPredicate(widget,
base::BindLambdaForTesting(predicate));
}
View* AnyViewWithClassName(Widget* widget, const std::string& classname);
class WidgetTest : public ViewsTestBase {
public:
WidgetTest();
explicit WidgetTest(
std::unique_ptr<base::test::TaskEnvironment> task_environment);
WidgetTest(const WidgetTest&) = delete;
WidgetTest& operator=(const WidgetTest&) = delete;
~WidgetTest() override;
Widget* CreateTopLevelPlatformWidget();
Widget* CreateTopLevelFramelessPlatformWidget();
Widget* CreateChildPlatformWidget(gfx::NativeView parent_native_view);
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
Widget* CreateTopLevelPlatformDesktopWidget();
#endif
Widget* CreateTopLevelNativeWidget();
Widget* CreateChildNativeWidgetWithParent(Widget* parent);
View* GetMousePressedHandler(views::internal::RootView* root_view);
View* GetMouseMoveHandler(views::internal::RootView* root_view);
View* GetGestureHandler(views::internal::RootView* root_view);
static void SimulateNativeActivate(Widget* widget);
static bool IsNativeWindowVisible(gfx::NativeWindow window);
static bool IsWindowStackedAbove(Widget* above, Widget* below);
gfx::Size GetNativeWidgetMinimumContentSize(Widget* widget);
static ui::EventSink* GetEventSink(Widget* widget);
static ui::ImeKeyEventDispatcher* GetImeKeyEventDispatcherForWidget(
Widget* widget);
static bool IsNativeWindowTransparent(gfx::NativeWindow window);
static bool WidgetHasInProcessShadow(Widget* widget);
static Widget::Widgets GetAllWidgets();
static void WaitForSystemAppActivation();
};
class DesktopWidgetTest : public WidgetTest {
public:
DesktopWidgetTest();
DesktopWidgetTest(const DesktopWidgetTest&) = delete;
DesktopWidgetTest& operator=(const DesktopWidgetTest&) = delete;
~DesktopWidgetTest() override;
void SetUp() override;
};
class DesktopWidgetTestInteractive : public DesktopWidgetTest {
public:
DesktopWidgetTestInteractive();
DesktopWidgetTestInteractive(const DesktopWidgetTestInteractive&) = delete;
DesktopWidgetTestInteractive& operator=(const DesktopWidgetTestInteractive&) =
delete;
~DesktopWidgetTestInteractive() override;
void SetUp() override;
#if (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)) || \
BUILDFLAG(IS_CHROMEOS_LACROS)
void TearDown() override;
std::unique_ptr<display::Screen> screen_;
#endif
};
class TestDesktopWidgetDelegate : public WidgetDelegate {
public:
TestDesktopWidgetDelegate();
explicit TestDesktopWidgetDelegate(Widget* widget);
TestDesktopWidgetDelegate(const TestDesktopWidgetDelegate&) = delete;
TestDesktopWidgetDelegate& operator=(const TestDesktopWidgetDelegate&) =
delete;
~TestDesktopWidgetDelegate() override;
void InitWidget(Widget::InitParams init_params);
void set_contents_view(View* contents_view) {
contents_view_ = contents_view;
}
void set_can_close(bool can_close) { can_close_ = can_close; }
int window_closing_count() const { return window_closing_count_; }
const gfx::Rect& initial_bounds() { return initial_bounds_; }
Widget::ClosedReason last_closed_reason() const {
return last_closed_reason_;
}
bool can_close() const { return can_close_; }
void WindowClosing() override;
Widget* GetWidget() override;
const Widget* GetWidget() const override;
View* GetContentsView() override;
bool OnCloseRequested(Widget::ClosedReason close_reason) override;
private:
raw_ptr<Widget> widget_;
raw_ptr<View> contents_view_ = nullptr;
int window_closing_count_ = 0;
gfx::Rect initial_bounds_ = gfx::Rect(100, 100, 200, 200);
bool can_close_ = true;
Widget::ClosedReason last_closed_reason_ = Widget::ClosedReason::kUnspecified;
};
class TestInitialFocusWidgetDelegate : public TestDesktopWidgetDelegate {
public:
explicit TestInitialFocusWidgetDelegate(gfx::NativeWindow context);
TestInitialFocusWidgetDelegate(const TestInitialFocusWidgetDelegate&) =
delete;
TestInitialFocusWidgetDelegate& operator=(
const TestInitialFocusWidgetDelegate&) = delete;
~TestInitialFocusWidgetDelegate() override;
View* view() { return view_; }
View* GetInitiallyFocusedView() override;
private:
raw_ptr<View> view_;
};
class WidgetActivationWaiter : public WidgetObserver {
public:
WidgetActivationWaiter(Widget* widget, bool active);
WidgetActivationWaiter(const WidgetActivationWaiter&) = delete;
WidgetActivationWaiter& operator=(const WidgetActivationWaiter&) = delete;
~WidgetActivationWaiter() override;
void Wait();
private:
void OnWidgetActivationChanged(Widget* widget, bool active) override;
bool observed_ = false;
bool active_;
base::RunLoop run_loop_;
base::ScopedObservation<Widget, WidgetObserver> widget_observation_{this};
};
class WidgetDestroyedWaiter : public WidgetObserver {
public:
explicit WidgetDestroyedWaiter(Widget* widget);
WidgetDestroyedWaiter(const WidgetDestroyedWaiter&) = delete;
WidgetDestroyedWaiter& operator=(const WidgetDestroyedWaiter&) = delete;
~WidgetDestroyedWaiter() override;
void Wait();
private:
void OnWidgetDestroyed(Widget* widget) override;
base::RunLoop run_loop_;
base::ScopedObservation<Widget, WidgetObserver> widget_observation_{this};
};
class WidgetVisibleWaiter : public WidgetObserver {
public:
explicit WidgetVisibleWaiter(Widget* widget);
WidgetVisibleWaiter(const WidgetVisibleWaiter&) = delete;
WidgetVisibleWaiter& operator=(const WidgetVisibleWaiter&) = delete;
~WidgetVisibleWaiter() override;
void Wait();
private:
void OnWidgetVisibilityChanged(Widget* widget, bool visible) override;
void OnWidgetDestroying(Widget* widget) override;
const raw_ptr<Widget, DanglingUntriaged> widget_;
base::RunLoop run_loop_;
base::ScopedObservation<Widget, WidgetObserver> widget_observation_{this};
};
}
}
#endif