#include "include/base/cef_callback.h"
#include "include/views/cef_box_layout.h"
#include "include/views/cef_layout.h"
#include "include/views/cef_panel.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/ceftests/image_util.h"
#include "tests/ceftests/thread_helper.h"
#include "tests/ceftests/views/test_window_delegate.h"
#include "tests/gtest/include/gtest/gtest.h"
#define WINDOW_TEST_ASYNC(name) UI_THREAD_TEST_ASYNC(ViewsWindowTest, name)
#if !defined(OS_WIN)
#define VK_MENU 0x12
#endif
namespace {
const int kStateDelayMS = 200;
const int kWSize = TestWindowDelegate::kWSize;
void ExpectCloseRects(const CefRect& expected,
const CefRect& actual,
int allowed_deviance) {
EXPECT_LE(abs(expected.x - actual.x), allowed_deviance);
EXPECT_LE(abs(expected.y - actual.y), allowed_deviance);
EXPECT_LE(abs(expected.width - actual.width), allowed_deviance);
EXPECT_LE(abs(expected.height - actual.height), allowed_deviance);
}
void WindowCreateImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowCreateFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->frameless = true;
TestWindowDelegate::RunTest(event, std::move(config));
}
void RunWindowShow(CefRefPtr<CefWindow> window) {
EXPECT_FALSE(window->IsVisible());
EXPECT_FALSE(window->IsDrawn());
window->Show();
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
}
void WindowCreateWithOriginImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->window_origin = {100, 200};
config->on_window_created = base::BindOnce(RunWindowShow);
TestWindowDelegate::RunTest(event, std::move(config));
}
void RunWindowShowHide(CefRefPtr<CefWindow> window) {
RunWindowShow(window);
window->Hide();
EXPECT_FALSE(window->IsVisible());
EXPECT_FALSE(window->IsDrawn());
}
void WindowShowHideImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowShowHide);
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowShowHideFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowShowHide);
config->frameless = true;
TestWindowDelegate::RunTest(event, std::move(config));
}
const int kWPanel1ID = 1;
const int kWPanel2ID = 2;
void CreateBoxLayout(CefRefPtr<CefWindow> parent) {
CefRefPtr<CefPanel> panel_child1 = CefPanel::CreatePanel(nullptr);
panel_child1->SetID(kWPanel1ID);
panel_child1->SetBackgroundColor(CefColorSetARGB(255, 0, 0, 255));
EXPECT_TRUE(panel_child1->IsVisible());
EXPECT_FALSE(panel_child1->IsDrawn());
CefRefPtr<CefPanel> panel_child2 = CefPanel::CreatePanel(nullptr);
panel_child2->SetID(kWPanel2ID);
panel_child2->SetBackgroundColor(CefColorSetARGB(255, 0, 255, 0));
EXPECT_TRUE(panel_child2->IsVisible());
EXPECT_FALSE(panel_child2->IsDrawn());
CefBoxLayoutSettings settings;
parent->SetToBoxLayout(settings);
parent->AddChildView(panel_child1);
parent->AddChildView(panel_child2);
EXPECT_TRUE(panel_child1->IsDrawn());
EXPECT_TRUE(panel_child1->IsDrawn());
CefRefPtr<CefBoxLayout> layout = parent->GetLayout()->AsBoxLayout();
layout->SetFlexForView(panel_child1, 1);
layout->SetFlexForView(panel_child2, 1);
parent->Layout();
ExpectCloseRects(CefRect(0, 0, kWSize, kWSize / 2), panel_child1->GetBounds(),
1);
ExpectCloseRects(CefRect(0, kWSize / 2, kWSize, kWSize / 2),
panel_child2->GetBounds(), 1);
}
void RunWindowLayoutAndCoords(CefRefPtr<CefWindow> window) {
CreateBoxLayout(window);
CefRefPtr<CefView> view1 = window->GetViewForID(kWPanel1ID);
EXPECT_TRUE(view1.get());
CefRefPtr<CefView> view2 = window->GetViewForID(kWPanel2ID);
EXPECT_TRUE(view2.get());
window->Show();
CefRect client_bounds_in_screen = window->GetClientAreaBoundsInScreen();
CefPoint point;
point = CefPoint(0, 0);
EXPECT_TRUE(view1->ConvertPointToScreen(point));
EXPECT_EQ(CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y),
point);
point = CefPoint(0, 0);
EXPECT_TRUE(view2->ConvertPointToScreen(point));
EXPECT_EQ(CefPoint(client_bounds_in_screen.x,
client_bounds_in_screen.y + kWSize / 2),
point);
point = CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y);
EXPECT_TRUE(view1->ConvertPointFromScreen(point));
EXPECT_EQ(CefPoint(0, 0), point);
point = CefPoint(client_bounds_in_screen.x,
client_bounds_in_screen.y + kWSize / 2);
EXPECT_TRUE(view2->ConvertPointFromScreen(point));
EXPECT_EQ(CefPoint(0, 0), point);
point = CefPoint(0, 0);
EXPECT_TRUE(view1->ConvertPointToWindow(point));
EXPECT_EQ(CefPoint(0, 0), point);
point = CefPoint(0, 0);
EXPECT_TRUE(view2->ConvertPointToWindow(point));
EXPECT_EQ(CefPoint(0, kWSize / 2), point);
point = CefPoint(0, 0);
EXPECT_TRUE(view1->ConvertPointFromWindow(point));
EXPECT_EQ(CefPoint(0, 0), point);
point = CefPoint(0, kWSize / 2);
EXPECT_TRUE(view2->ConvertPointFromWindow(point));
EXPECT_EQ(CefPoint(0, 0), point);
point = CefPoint(0, 0);
EXPECT_TRUE(view1->ConvertPointToView(view2, point));
EXPECT_EQ(CefPoint(0, -kWSize / 2), point);
point = CefPoint(0, 0);
EXPECT_TRUE(view2->ConvertPointToView(view1, point));
EXPECT_EQ(CefPoint(0, kWSize / 2), point);
point = CefPoint(0, -kWSize / 2);
EXPECT_TRUE(view1->ConvertPointFromView(view2, point));
EXPECT_EQ(CefPoint(0, 0), point);
point = CefPoint(0, kWSize / 2);
EXPECT_TRUE(view2->ConvertPointFromView(view1, point));
EXPECT_EQ(CefPoint(0, 0), point);
CefRefPtr<CefDisplay> display = window->GetDisplay();
EXPECT_TRUE(display.get());
point = CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y);
display->ConvertPointToPixels(point);
display->ConvertPointFromPixels(point);
EXPECT_EQ(CefPoint(client_bounds_in_screen.x, client_bounds_in_screen.y),
point);
}
void WindowLayoutAndCoordsImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowLayoutAndCoords);
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowLayoutAndCoordsFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowLayoutAndCoords);
config->frameless = true;
TestWindowDelegate::RunTest(event, std::move(config));
}
void VerifyRestore(CefRefPtr<CefWindow> window) {
EXPECT_FALSE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->Close();
}
void VerifyMaximize(CefRefPtr<CefWindow> window) {
EXPECT_FALSE(window->IsMinimized());
EXPECT_TRUE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->Restore();
CefPostDelayedTask(TID_UI, base::BindOnce(VerifyRestore, window),
kStateDelayMS);
}
void RunWindowMaximize(CefRefPtr<CefWindow> window) {
CreateBoxLayout(window);
window->Show();
EXPECT_FALSE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->Maximize();
CefPostDelayedTask(TID_UI, base::BindOnce(VerifyMaximize, window),
kStateDelayMS);
}
void WindowMaximizeImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowMaximize);
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowMaximizeFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowMaximize);
config->frameless = true;
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
void VerifyMinimize(CefRefPtr<CefWindow> window) {
EXPECT_TRUE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->Restore();
CefPostDelayedTask(TID_UI, base::BindOnce(VerifyRestore, window),
kStateDelayMS);
}
void RunWindowMinimize(CefRefPtr<CefWindow> window) {
CreateBoxLayout(window);
window->Show();
EXPECT_FALSE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->Minimize();
CefPostDelayedTask(TID_UI, base::BindOnce(VerifyMinimize, window),
kStateDelayMS);
}
void WindowMinimizeImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowMinimize);
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowMinimizeFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowMinimize);
config->frameless = true;
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
void VerifyFullscreenExit(CefRefPtr<CefWindow> window) {
EXPECT_FALSE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->Close();
}
void VerifyFullscreen(CefRefPtr<CefWindow> window) {
EXPECT_FALSE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_TRUE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->SetFullscreen(false);
CefPostDelayedTask(TID_UI, base::BindOnce(VerifyFullscreenExit, window),
kStateDelayMS);
}
void RunWindowFullscreen(CefRefPtr<CefWindow> window) {
CreateBoxLayout(window);
window->Show();
EXPECT_FALSE(window->IsMinimized());
EXPECT_FALSE(window->IsMaximized());
EXPECT_FALSE(window->IsFullscreen());
EXPECT_TRUE(window->IsVisible());
EXPECT_TRUE(window->IsDrawn());
window->SetFullscreen(true);
CefPostDelayedTask(TID_UI, base::BindOnce(VerifyFullscreen, window),
kStateDelayMS);
}
void WindowFullscreenImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowFullscreen);
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowFullscreenFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowFullscreen);
config->frameless = true;
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
void RunWindowIcon(CefRefPtr<CefWindow> window) {
CefRefPtr<CefImage> image = CefImage::CreateImage();
image_util::LoadIconImage(image, 1.0);
image_util::LoadIconImage(image, 2.0);
EXPECT_FALSE(window->GetWindowIcon().get());
window->SetWindowIcon(image);
EXPECT_TRUE(image->IsSame(window->GetWindowIcon()));
EXPECT_FALSE(window->GetWindowAppIcon().get());
window->SetWindowAppIcon(image);
EXPECT_TRUE(image->IsSame(window->GetWindowAppIcon()));
window->Show();
}
void WindowIconImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowIcon);
TestWindowDelegate::RunTest(event, std::move(config));
}
void WindowIconFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowIcon);
config->frameless = true;
TestWindowDelegate::RunTest(event, std::move(config));
}
const int kChar = 'A';
const int kCloseWindowId = 2;
bool got_accelerator;
int got_key_event_alt_count;
bool got_key_event_char;
void TriggerAccelerator(CefRefPtr<CefWindow> window) {
window->SendKeyPress(kChar, EVENTFLAG_ALT_DOWN);
}
bool OnKeyEvent(CefRefPtr<CefWindow> window, const CefKeyEvent& event) {
if (event.type != KEYEVENT_RAWKEYDOWN)
return false;
if (event.windows_key_code == VK_MENU) {
EXPECT_FALSE(got_key_event_char);
if (got_key_event_alt_count == 0)
EXPECT_FALSE(got_accelerator);
else
EXPECT_TRUE(got_accelerator);
EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
got_key_event_alt_count++;
} else if (event.windows_key_code == kChar) {
EXPECT_TRUE(got_accelerator);
EXPECT_EQ(got_key_event_alt_count, 2);
EXPECT_FALSE(got_key_event_char);
EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
got_key_event_char = true;
window->RemoveAllAccelerators();
window->Close();
return true;
}
return false;
}
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
EXPECT_FALSE(got_accelerator);
EXPECT_EQ(got_key_event_alt_count, 1);
EXPECT_FALSE(got_key_event_char);
EXPECT_EQ(kCloseWindowId, command_id);
got_accelerator = true;
window->RemoveAccelerator(kCloseWindowId);
TriggerAccelerator(window);
return true;
}
void RunWindowAccelerator(CefRefPtr<CefWindow> window) {
window->SetAccelerator(kCloseWindowId, kChar, false, false, true);
window->Show();
CefPostDelayedTask(TID_UI, base::BindOnce(TriggerAccelerator, window),
kStateDelayMS);
}
void VerifyWindowAccelerator(CefRefPtr<CefWindow> window) {
EXPECT_TRUE(got_accelerator);
EXPECT_EQ(got_key_event_alt_count, 2);
EXPECT_TRUE(got_key_event_char);
}
void WindowAcceleratorImpl(CefRefPtr<CefWaitableEvent> event) {
got_accelerator = false;
got_key_event_alt_count = 0;
got_key_event_char = false;
auto config = std::make_unique<TestWindowDelegate::Config>();
config->on_window_created = base::BindOnce(RunWindowAccelerator);
config->on_window_destroyed = base::BindOnce(VerifyWindowAccelerator);
config->on_accelerator = base::BindRepeating(OnAccelerator);
config->on_key_event = base::BindRepeating(OnKeyEvent);
config->close_window = false;
TestWindowDelegate::RunTest(event, std::move(config));
}
}
WINDOW_TEST_ASYNC(WindowCreate)
WINDOW_TEST_ASYNC(WindowCreateFrameless)
WINDOW_TEST_ASYNC(WindowCreateWithOrigin)
WINDOW_TEST_ASYNC(WindowShowHide)
WINDOW_TEST_ASYNC(WindowShowHideFrameless)
WINDOW_TEST_ASYNC(WindowLayoutAndCoords)
WINDOW_TEST_ASYNC(WindowLayoutAndCoordsFrameless)
WINDOW_TEST_ASYNC(WindowMaximize)
WINDOW_TEST_ASYNC(WindowMaximizeFrameless)
WINDOW_TEST_ASYNC(WindowMinimize)
WINDOW_TEST_ASYNC(WindowMinimizeFrameless)
WINDOW_TEST_ASYNC(WindowFullscreen)
WINDOW_TEST_ASYNC(WindowFullscreenFrameless)
WINDOW_TEST_ASYNC(WindowIcon)
WINDOW_TEST_ASYNC(WindowIconFrameless)
WINDOW_TEST_ASYNC(WindowAccelerator)