#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/no_destructor.h"
#include "build/build_config.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/test/aura_test_helper.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/layer.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/shadow_controller.h"
#if BUILDFLAG(ENABLE_DESKTOP_AURA)
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
#endif
namespace views::test {
namespace {
base::NoDestructor<WidgetTest::RootWindowProvider> g_root_window_provider;
bool FindLayersInOrder(
const std::vector<raw_ptr<ui::Layer, VectorExperimental>>& children,
const ui::Layer** first,
const ui::Layer** second) {
for (const ui::Layer* child : children) {
if (child == *second) {
*second = nullptr;
return *first == nullptr;
}
if (child == *first) {
*first = nullptr;
}
if (FindLayersInOrder(child->children(), first, second)) {
return true;
}
if (!*second) {
return false;
}
}
return false;
}
#if BUILDFLAG(IS_WIN)
struct FindAllWindowsData {
RAW_PTR_EXCLUSION aura::Window::Windows* windows;
};
BOOL CALLBACK FindAllWindowsCallback(HWND hwnd, LPARAM param) {
FindAllWindowsData* data = reinterpret_cast<FindAllWindowsData*>(param);
if (aura::WindowTreeHost* host =
aura::WindowTreeHost::GetForAcceleratedWidget(hwnd)) {
data->windows->push_back(host->window());
}
return TRUE;
}
#endif
aura::Window::Windows GetAllTopLevelWindows() {
aura::Window::Windows roots;
if (*g_root_window_provider) {
return g_root_window_provider->Run();
}
#if BUILDFLAG(IS_WIN)
{
FindAllWindowsData data = {&roots};
EnumThreadWindows(GetCurrentThreadId(), FindAllWindowsCallback,
reinterpret_cast<LPARAM>(&data));
}
#elif BUILDFLAG(ENABLE_DESKTOP_AURA)
roots = DesktopWindowTreeHostPlatform::GetAllOpenWindows();
#endif
aura::test::AuraTestHelper* aura_test_helper =
aura::test::AuraTestHelper::GetInstance();
if (aura_test_helper) {
roots.push_back(aura_test_helper->GetContext());
}
return roots;
}
}
void WidgetTest::SetRootWindowProvider(RootWindowProvider provider) {
*g_root_window_provider = std::move(provider);
}
void WidgetTest::SimulateNativeActivate(Widget* widget) {
gfx::NativeView native_view = widget->GetNativeView();
aura::client::GetFocusClient(native_view)->FocusWindow(native_view);
}
bool WidgetTest::IsNativeWindowVisible(gfx::NativeWindow window) {
return window->IsVisible();
}
bool WidgetTest::IsWindowStackedAbove(Widget* above, Widget* below) {
EXPECT_TRUE(above->IsVisible());
EXPECT_TRUE(below->IsVisible());
ui::Layer* root_layer = above->GetNativeWindow()->GetRootWindow()->layer();
const ui::Layer* first = below->GetLayer();
const ui::Layer* second = above->GetLayer();
return FindLayersInOrder(root_layer->children(), &first, &second);
}
gfx::Size WidgetTest::GetNativeWidgetMinimumContentSize(Widget* widget) {
#if !BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
return widget->GetNativeWindow()->delegate()->GetMinimumSize();
#else
NOTREACHED();
#endif
}
ui::EventSink* WidgetTest::GetEventSink(Widget* widget) {
return widget->GetNativeWindow()->GetHost()->GetEventSink();
}
ui::ImeKeyEventDispatcher* WidgetTest::GetImeKeyEventDispatcherForWidget(
Widget* widget) {
return widget->GetNativeWindow()->GetRootWindow()->GetHost();
}
bool WidgetTest::IsNativeWindowTransparent(gfx::NativeWindow window) {
return window->GetTransparent();
}
bool WidgetTest::WidgetHasInProcessShadow(Widget* widget) {
aura::Window* window = widget->GetNativeWindow();
if (wm::ShadowController::GetShadowForWindow(window)) {
return true;
}
if (window->parent() == window->GetRootWindow()) {
return wm::ShadowController::GetShadowForWindow(window->GetRootWindow());
}
return false;
}
Widget::Widgets WidgetTest::GetAllWidgets() {
Widget::Widgets all_widgets;
for (aura::Window* window : GetAllTopLevelWindows()) {
all_widgets.merge(Widget::GetAllChildWidgets(window->GetRootWindow()));
}
return all_widgets;
}
void WidgetTest::WaitForSystemAppActivation() {}
}