blob: 355dd0f8ad219358d9bcdf410c74f83861ccacf2 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/display/extended_mouse_warp_controller.h"
#include "ash/display/display_layout_store.h"
#include "ash/display/display_manager.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/display_manager_test_api.h"
#include "ui/display/display.h"
#include "ui/display/manager/display_layout.h"
#include "ui/display/manager/display_layout_builder.h"
#include "ui/display/screen.h"
#include "ui/events/test/event_generator.h"
namespace ash {
class ExtendedMouseWarpControllerTest : public test::AshTestBase {
public:
ExtendedMouseWarpControllerTest() {}
~ExtendedMouseWarpControllerTest() override {}
protected:
MouseCursorEventFilter* event_filter() {
return Shell::GetInstance()->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);
}
private:
DISALLOW_COPY_AND_ASSIGN(ExtendedMouseWarpControllerTest);
};
// Verifies if MouseCursorEventFilter's bounds calculation works correctly.
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnRight) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("360x360,700x700");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
int64_t display_0_id = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_windows[0])
.id();
int64_t display_1_id = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_windows[1])
.id();
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
std::unique_ptr<display::DisplayLayout> layout(
test::CreateDisplayLayout(display::DisplayPlacement::RIGHT, 0));
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 16, 1, 344), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 360), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
EXPECT_EQ(gfx::Rect(359, 0, 1, 360), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 16, 1, 344), GetIndicatorBounds(display_1_id));
// Move 2nd display downwards a bit.
layout->placement_list[0].offset = 5;
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
// This is same as before because the 2nd display's y is above
// the indicator's x.
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 16, 1, 344), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 5, 1, 355), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
EXPECT_EQ(gfx::Rect(359, 5, 1, 355), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 21, 1, 339), GetIndicatorBounds(display_1_id));
// Move it down further so that the shared edge is shorter than
// minimum hole size (160).
layout->placement_list[0].offset = 200;
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 200, 1, 160), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 200, 1, 160), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 200, 1, 160), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 200, 1, 160), GetIndicatorBounds(display_1_id));
// Now move 2nd display upwards
layout->placement_list[0].offset = -5;
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 16, 1, 344), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 360), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
// 16 px are reserved on 2nd display from top, so y must be
// (16 - 5) = 11
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(359, 0, 1, 360), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(360, 11, 1, 349), GetIndicatorBounds(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnLeft) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("360x360,700x700");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
int64_t display_0_id = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_windows[0])
.id();
int64_t display_1_id = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_windows[1])
.id();
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
std::unique_ptr<display::DisplayLayout> layout(
test::CreateDisplayLayout(display::DisplayPlacement::LEFT, 0));
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 16, 1, 344), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 0, 1, 360), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 0, 1, 360), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 16, 1, 344), GetIndicatorBounds(display_1_id));
layout->placement_list[0].offset = 250;
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 250, 1, 110), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 250, 1, 110), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 250, 1, 110), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(-1, 250, 1, 110), GetIndicatorBounds(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnTopBottom) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("360x360,700x700");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
int64_t display_0_id = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_windows[0])
.id();
int64_t display_1_id = display::Screen::GetScreen()
->GetDisplayNearestWindow(root_windows[1])
.id();
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
std::unique_ptr<display::DisplayLayout> layout(
test::CreateDisplayLayout(display::DisplayPlacement::TOP, 0));
display_manager->SetLayoutForCurrentDisplays(layout->Copy());
event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */);
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] /* secondary */);
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] /* primary */);
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] /* secondary */);
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] /* primary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 359, 360, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(0, 360, 360, 1), GetIndicatorBounds(display_1_id));
event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */);
ASSERT_EQ(1U, GetWarpRegionsCount());
EXPECT_EQ(gfx::Rect(0, 359, 360, 1), GetIndicatorBounds(display_0_id));
EXPECT_EQ(gfx::Rect(0, 360, 360, 1), GetIndicatorBounds(display_1_id));
event_filter()->HideSharedEdgeIndicator();
}
// Verify indicators show up as expected with 3+ displays.
TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestThreeDisplays) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("360x360,700x700,1000x1000");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
display::Screen* screen = display::Screen::GetScreen();
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();
// Drag from left most display
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, 16, 1, 344),
region_1->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 360),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1059, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1060, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_2_id));
// Drag from middle display
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, 360),
region_1->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(360, 16, 1, 344),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1059, 16, 1, 684),
region_0->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1060, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_2_id));
// Right most display
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, 360),
region_1->GetIndicatorBoundsForTest(display_0_id));
EXPECT_EQ(gfx::Rect(360, 0, 1, 360),
region_1->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1059, 0, 1, 700),
region_0->GetIndicatorBoundsForTest(display_1_id));
EXPECT_EQ(gfx::Rect(1060, 16, 1, 684),
region_0->GetIndicatorBoundsForTest(display_2_id));
event_filter()->HideSharedEdgeIndicator();
// TODO(oshima): Add test cases primary swap.
}
TEST_F(ExtendedMouseWarpControllerTest,
IndicatorBoundsTestThreeDisplaysWithLayout) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("700x500,500x500,1000x1000");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
display::Screen* screen = display::Screen::GetScreen();
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();
// Layout so that all displays touches togter like this:
// +-----+---+
// | 0 | 1 |
// +-+---+--++
// | 2 |
// +------+
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);
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
display_manager->SetLayoutForCurrentDisplays(builder.Build());
ASSERT_EQ(3U, GetWarpRegionsCount());
// Drag from 0.
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);
// between 2 and 0
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));
// between 2 and 1
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));
// between 1 and 0
EXPECT_EQ(gfx::Rect(699, 16, 1, 484),
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) {
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("700x500,500x500,1000x1000");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
display::Screen* screen = display::Screen::GetScreen();
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();
// Layout so that 0 and 1 displays are disconnected.
// +-----+ +---+
// | 0 | |1 |
// +-+---+-+++
// | 2 |
// +------+
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);
DisplayManager* display_manager = Shell::GetInstance()->display_manager();
display_manager->SetLayoutForCurrentDisplays(builder.Build());
ASSERT_EQ(2U, GetWarpRegionsCount());
// Drag from 0.
event_filter()->ShowSharedEdgeIndicator(root_windows[0]);
ASSERT_EQ(2U, GetWarpRegionsCount());
const ExtendedMouseWarpController::WarpRegion* region_0 = GetWarpRegion(0);
const ExtendedMouseWarpController::WarpRegion* region_1 = GetWarpRegion(1);
// between 2 and 0
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));
// between 2 and 1
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();
}
} // namespace ash