#include "ash/display/extended_mouse_warp_controller.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/display/screen_position_controller.h"
#include "ash/host/ash_window_tree_host_platform.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ui/aura/env.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
#include "ui/display/display.h"
#include "ui/display/display_layout.h"
#include "ui/display/display_layout_builder.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/screen.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/test/event_generator.h"
#include "ui/wm/core/coordinate_conversion.h"
namespace ash {
class ExtendedMouseWarpControllerTest : public AshTestBase {
public:
ExtendedMouseWarpControllerTest() = default;
ExtendedMouseWarpControllerTest(const ExtendedMouseWarpControllerTest&) =
delete;
ExtendedMouseWarpControllerTest& operator=(
const ExtendedMouseWarpControllerTest&) = delete;
~ExtendedMouseWarpControllerTest() override = default;
protected:
MouseCursorEventFilter* event_filter() {
return Shell::Get()->mouse_cursor_filter();
}
ExtendedMouseWarpController* mouse_warp_controller() {
return static_cast<ExtendedMouseWarpController*>(
event_filter()->mouse_warp_controller_for_test());
}
size_t GetWarpRegionsCount() {
return mouse_warp_controller()->warp_regions_.size();
}
const ExtendedMouseWarpController::WarpRegion* GetWarpRegion(size_t index) {
return mouse_warp_controller()->warp_regions_[index].get();
}
const gfx::Rect& GetIndicatorBounds(int64_t id) {
return GetWarpRegion(0)->GetIndicatorBoundsForTest(id);
}
const gfx::Rect& GetIndicatorNativeBounds(int64_t id) {
return GetWarpRegion(0)->GetIndicatorNativeBoundsForTest(id);
}
void DispatchMouseEventWithNative(AshWindowTreeHostPlatform* host,
const gfx::Point& location_in_host_native,
ui::EventType event_type,
int event_flag1,
int event_flag2) {
ui::MouseEvent native_event(event_type, location_in_host_native,
location_in_host_native, ui::EventTimeForNow(),
event_flag1, event_flag2);
ui::MouseEvent mouseev(&native_event);
host->DispatchEvent(&mouseev);
base::RunLoop().RunUntilIdle();
}
};
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnRight) {
UpdateDisplay("360x350,800x700");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
int64_t display_0_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[0]).id();
int64_t display_1_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[1]).id();
std::unique_ptr<display::DisplayLayout> layout(
display::test::CreateDisplayLayout(display_manager(),
display::DisplayPlacement::RIGHT, 0));
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 32, 1, 318), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 350), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
EXPECT_EQ(gfx::Rect(359, 0, 1, 350), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 32, 1, 318), GetIndicatorBounds(display_1_id));
layout->placement_list[0].offset = 5;
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 32, 1, 318), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 5, 1, 345), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
EXPECT_EQ(gfx::Rect(359, 5, 1, 345), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 37, 1, 313), GetIndicatorBounds(display_1_id));
layout->placement_list[0].offset = 200;
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 200, 1, 150), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 200, 1, 150), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 200, 1, 150), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 200, 1, 150), GetIndicatorBounds(display_1_id));
layout->placement_list[0].offset = -5;
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 32, 1, 318), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 350), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 0, 1, 350), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 27, 1, 323), GetIndicatorBounds(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnLeft) {
UpdateDisplay("360x350,800x700");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
int64_t display_0_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[0]).id();
int64_t display_1_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[1]).id();
std::unique_ptr<display::DisplayLayout> layout(
display::test::CreateDisplayLayout(display_manager(),
display::DisplayPlacement::LEFT, 0));
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 32, 1, 318), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 0, 1, 350), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 0, 1, 350), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 32, 1, 318), GetIndicatorBounds(display_1_id));
layout->placement_list[0].offset = 250;
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 250, 1, 100), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 250, 1, 100), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 250, 1, 100), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 250, 1, 100), GetIndicatorBounds(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnTopBottom) {
UpdateDisplay("360x350,800x700");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
int64_t display_0_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[0]).id();
int64_t display_1_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[1]).id();
std::unique_ptr<display::DisplayLayout> layout(
display::test::CreateDisplayLayout(display_manager(),
display::DisplayPlacement::TOP, 0));
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 0, 360, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(0, -1, 360, 1), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 0, 360, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(0, -1, 360, 1), GetIndicatorBounds(display_1_id));
layout->placement_list[0].offset = 250;
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(250, 0, 110, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(250, -1, 110, 1), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(250, 0, 110, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(250, -1, 110, 1), GetIndicatorBounds(display_1_id));
layout->placement_list[0].position = display::DisplayPlacement::BOTTOM;
layout->placement_list[0].offset = 0;
display_manager()->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 349, 360, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(0, 350, 360, 1), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] );
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 349, 360, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(0, 350, 360, 1), GetIndicatorBounds(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestThreeDisplays) {
UpdateDisplay("360x350,800x700,1000x900");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
display::Screen* screen = display::Screen::Get();
int64_t display_0_id = screen->GetDisplayNearestWindow(root_windows[0]).id();
int64_t display_1_id = screen->GetDisplayNearestWindow(root_windows[1]).id();
int64_t display_2_id = screen->GetDisplayNearestWindow(root_windows[2]).id();
event_filter()->ShowSharedEdgeIndicator(root_windows[0]);
ASSERT_EQ(2U, GetWarpRegionsCount());
const ExtendedMouseWarpController::WarpRegion* region_0 = GetWarpRegion(0);
const ExtendedMouseWarpController::WarpRegion* region_1 = GetWarpRegion(1);
EXPECT_EQ(gfx::Rect(359, 32, 1, 318),
region_1->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 350),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1159, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1160, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_2_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1]);
ASSERT_EQ(2U, mouse_warp_controller()->warp_regions_.size());
region_0 = GetWarpRegion(0);
region_1 = GetWarpRegion(1);
EXPECT_EQ(gfx::Rect(359, 0, 1, 350),
region_1->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(360, 32, 1, 318),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1159, 32, 1, 668),
region_0->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1160, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_2_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[2]);
ASSERT_EQ(2U, mouse_warp_controller()->warp_regions_.size());
region_0 = GetWarpRegion(0);
region_1 = GetWarpRegion(1);
EXPECT_EQ(gfx::Rect(359, 0, 1, 350),
region_1->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 350),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1159, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1160, 32, 1, 668),
region_0->GetIndicatorBoundsForTest(display_2_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest,
IndicatorBoundsTestThreeDisplaysWithLayout) {
UpdateDisplay("700x500,600x500,1000x900");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
display::Screen* screen = display::Screen::Get();
int64_t display_0_id = screen->GetDisplayNearestWindow(root_windows[0]).id();
int64_t display_1_id = screen->GetDisplayNearestWindow(root_windows[1]).id();
int64_t display_2_id = screen->GetDisplayNearestWindow(root_windows[2]).id();
display::DisplayLayoutBuilder builder(display_0_id);
builder.AddDisplayPlacement(display_1_id, display_0_id,
display::DisplayPlacement::RIGHT, 0);
builder.AddDisplayPlacement(display_2_id, display_0_id,
display::DisplayPlacement::BOTTOM, 100);
display_manager()->SetLayoutForCurrentDisplays(builder.Build());
ASSERT_EQ(3U, GetWarpRegionsCount());
event_filter()->ShowSharedEdgeIndicator(root_windows[0]);
ASSERT_EQ(3U, GetWarpRegionsCount());
const ExtendedMouseWarpController::WarpRegion* region_0 = GetWarpRegion(0);
const ExtendedMouseWarpController::WarpRegion* region_1 = GetWarpRegion(1);
const ExtendedMouseWarpController::WarpRegion* region_2 = GetWarpRegion(2);
EXPECT_EQ(gfx::Rect(100, 499, 600, 1),
region_0->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(100, 500, 600, 1),
region_0->GetIndicatorBoundsForTest(display_2_id));
EXPECT_EQ(gfx::Rect(700, 499, 400, 1),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(700, 500, 400, 1),
region_1->GetIndicatorBoundsForTest(display_2_id));
EXPECT_EQ(gfx::Rect(699, 32, 1, 468),
region_2->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(700, 0, 1, 500),
region_2->GetIndicatorBoundsForTest(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest,
IndicatorBoundsTestThreeDisplaysWithLayout2) {
UpdateDisplay("700x500,600x500,1000x900");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
display::Screen* screen = display::Screen::Get();
int64_t display_0_id = screen->GetDisplayNearestWindow(root_windows[0]).id();
int64_t display_1_id = screen->GetDisplayNearestWindow(root_windows[1]).id();
int64_t display_2_id = screen->GetDisplayNearestWindow(root_windows[2]).id();
display::DisplayLayoutBuilder builder(display_0_id);
builder.AddDisplayPlacement(display_2_id, display_0_id,
display::DisplayPlacement::BOTTOM, 100);
builder.AddDisplayPlacement(display_1_id, display_2_id,
display::DisplayPlacement::TOP, 800);
display_manager()->SetLayoutForCurrentDisplays(builder.Build());
ASSERT_EQ(2U, GetWarpRegionsCount());
event_filter()->ShowSharedEdgeIndicator(root_windows[0]);
ASSERT_EQ(2U, GetWarpRegionsCount());
const ExtendedMouseWarpController::WarpRegion* region_0 = GetWarpRegion(0);
const ExtendedMouseWarpController::WarpRegion* region_1 = GetWarpRegion(1);
EXPECT_EQ(gfx::Rect(100, 499, 600, 1),
region_0->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(100, 500, 600, 1),
region_0->GetIndicatorBoundsForTest(display_2_id));
EXPECT_EQ(gfx::Rect(900, 499, 200, 1),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(900, 500, 200, 1),
region_1->GetIndicatorBoundsForTest(display_2_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest,
DISABLED_CheckHostPointToScreenInMouseWarpRegion) {
UpdateDisplay("50+50-300x200@0.8,50+300-300x100/r");
aura::Window::Windows root_windows = Shell::Get()->GetAllRootWindows();
display::Display primary_display =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[0]);
ASSERT_EQ("250x250", primary_display.size().ToString());
ASSERT_EQ(0.8f, primary_display.device_scale_factor());
std::unique_ptr<aura::test::TestWindowDelegate> test_window_delegate =
std::make_unique<aura::test::TestWindowDelegate>();
test_window_delegate->set_window_component(HTCAPTION);
const gfx::Size initial_window_size(100, 100);
std::unique_ptr<aura::Window> test_window(
CreateTestWindowInShell({.delegate = test_window_delegate.get(),
.bounds = gfx::Rect(initial_window_size),
.window_id = 0}));
ASSERT_EQ(root_windows[0], test_window->GetRootWindow());
ASSERT_FALSE(test_window->HasCapture());
AshWindowTreeHostPlatform* window_host =
static_cast<AshWindowTreeHostPlatform*>(root_windows[0]->GetHost());
gfx::Point location_in_host_native(0, 0);
DispatchMouseEventWithNative(window_host, location_in_host_native,
ui::EventType::kMouseMoved, ui::EF_NONE,
ui::EF_NONE);
DispatchMouseEventWithNative(
window_host, location_in_host_native, ui::EventType::kMousePressed,
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
ASSERT_TRUE(test_window->HasCapture());
int64_t display_0_id = primary_display.id();
const gfx::Rect indicator_in_primary_display =
GetIndicatorNativeBounds(display_0_id);
int64_t display_1_id =
display::Screen::Get()->GetDisplayNearestWindow(root_windows[1]).id();
const gfx::Rect indicator_in_secondary_display =
GetIndicatorNativeBounds(display_1_id);
gfx::Point location_in_screen_native, location_in_screen_dip;
location_in_screen_native = indicator_in_primary_display.CenterPoint();
location_in_host_native =
location_in_screen_native -
root_windows[0]->GetHost()->GetBoundsInPixels().OffsetFromOrigin();
DispatchMouseEventWithNative(window_host, location_in_host_native,
ui::EventType::kMouseDragged,
ui::EF_LEFT_MOUSE_BUTTON, 0);
location_in_screen_dip = aura::Env::GetInstance()->last_mouse_location();
EXPECT_TRUE(
root_windows[1]->GetBoundsInScreen().Contains(location_in_screen_dip));
location_in_screen_native = indicator_in_secondary_display.CenterPoint();
location_in_host_native =
location_in_screen_native -
root_windows[0]->GetHost()->GetBoundsInPixels().OffsetFromOrigin();
DispatchMouseEventWithNative(window_host, location_in_host_native,
ui::EventType::kMouseDragged,
ui::EF_LEFT_MOUSE_BUTTON, 0);
location_in_screen_dip = aura::Env::GetInstance()->last_mouse_location();
EXPECT_TRUE(
root_windows[0]->GetBoundsInScreen().Contains(location_in_screen_dip));
EXPECT_EQ(247, aura::Env::GetInstance()->last_mouse_location().x());
gfx::Point location_in_host_dip;
location_in_screen_dip = aura::Env::GetInstance()->last_mouse_location();
location_in_host_dip = location_in_screen_dip;
::wm::ConvertPointFromScreen(root_windows[0], &location_in_host_dip);
location_in_host_native = location_in_host_dip;
root_windows[0]->GetHost()->ConvertDIPToPixels(&location_in_host_native);
DispatchMouseEventWithNative(
window_host, location_in_host_native, ui::EventType::kMouseReleased,
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
}
}