1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ash/wm/ash_native_cursor_manager.h"
6
7#include "ash/display/display_info.h"
8#include "ash/display/display_manager.h"
9#include "ash/shell.h"
10#include "ash/test/ash_test_base.h"
11#include "ash/test/cursor_manager_test_api.h"
12#include "ui/aura/test/aura_test_utils.h"
13#include "ui/aura/test/test_window_delegate.h"
14#include "ui/aura/test/test_windows.h"
15#include "ui/aura/window.h"
16#include "ui/aura/window_event_dispatcher.h"
17#include "ui/base/cursor/image_cursors.h"
18#include "ui/gfx/screen.h"
19
20#if defined(OS_WIN)
21#include "base/win/windows_version.h"
22#include "ui/base/cursor/cursor_loader_win.h"
23#endif
24
25#if defined(USE_X11)
26#include "ui/base/cursor/cursor_loader_x11.h"
27#include "ui/resources/grit/ui_resources.h"
28#endif
29
30namespace ash {
31namespace test {
32
33namespace {
34
35// A delegate for recording a mouse event location.
36class MouseEventLocationDelegate : public aura::test::TestWindowDelegate {
37 public:
38  MouseEventLocationDelegate() {}
39  virtual ~MouseEventLocationDelegate() {}
40
41  gfx::Point GetMouseEventLocationAndReset() {
42    gfx::Point p = mouse_event_location_;
43    mouse_event_location_.SetPoint(-100, -100);
44    return p;
45  }
46
47  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
48    mouse_event_location_ = event->location();
49    event->SetHandled();
50  }
51
52 private:
53  gfx::Point mouse_event_location_;
54
55  DISALLOW_COPY_AND_ASSIGN(MouseEventLocationDelegate);
56};
57
58}  // namespace
59
60typedef test::AshTestBase AshNativeCursorManagerTest;
61
62TEST_F(AshNativeCursorManagerTest, LockCursor) {
63  ::wm::CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager();
64  CursorManagerTestApi test_api(cursor_manager);
65
66#if defined(OS_WIN)
67  ui::CursorLoaderWin::SetCursorResourceModule(L"ash_unittests.exe");
68#endif
69  cursor_manager->SetCursor(ui::kCursorCopy);
70  EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type());
71  UpdateDisplay("800x800*2/r");
72  EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
73  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
74  EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
75  EXPECT_TRUE(test_api.GetCurrentCursor().platform());
76
77  cursor_manager->LockCursor();
78  EXPECT_TRUE(cursor_manager->IsCursorLocked());
79
80  // Cursor type does not change while cursor is locked.
81  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
82  cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL);
83  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
84  cursor_manager->SetCursorSet(ui::CURSOR_SET_LARGE);
85  EXPECT_EQ(ui::CURSOR_SET_LARGE, test_api.GetCurrentCursorSet());
86  cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL);
87  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
88
89  // Cursor type does not change while cursor is locked.
90  cursor_manager->SetCursor(ui::kCursorPointer);
91  EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type());
92
93  // Device scale factor and rotation do change even while cursor is locked.
94  UpdateDisplay("800x800/u");
95  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
96  EXPECT_EQ(gfx::Display::ROTATE_180, test_api.GetCurrentCursorRotation());
97
98  cursor_manager->UnlockCursor();
99  EXPECT_FALSE(cursor_manager->IsCursorLocked());
100
101  // Cursor type changes to the one specified while cursor is locked.
102  EXPECT_EQ(ui::kCursorPointer, test_api.GetCurrentCursor().native_type());
103  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
104  EXPECT_TRUE(test_api.GetCurrentCursor().platform());
105}
106
107TEST_F(AshNativeCursorManagerTest, SetCursor) {
108  ::wm::CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager();
109  CursorManagerTestApi test_api(cursor_manager);
110#if defined(OS_WIN)
111  ui::CursorLoaderWin::SetCursorResourceModule(L"ash_unittests.exe");
112#endif
113  cursor_manager->SetCursor(ui::kCursorCopy);
114  EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type());
115  EXPECT_TRUE(test_api.GetCurrentCursor().platform());
116  cursor_manager->SetCursor(ui::kCursorPointer);
117  EXPECT_EQ(ui::kCursorPointer, test_api.GetCurrentCursor().native_type());
118  EXPECT_TRUE(test_api.GetCurrentCursor().platform());
119}
120
121TEST_F(AshNativeCursorManagerTest, SetCursorSet) {
122  ::wm::CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager();
123  CursorManagerTestApi test_api(cursor_manager);
124
125  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
126
127  cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL);
128  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
129
130  cursor_manager->SetCursorSet(ui::CURSOR_SET_LARGE);
131  EXPECT_EQ(ui::CURSOR_SET_LARGE, test_api.GetCurrentCursorSet());
132
133  cursor_manager->SetCursorSet(ui::CURSOR_SET_NORMAL);
134  EXPECT_EQ(ui::CURSOR_SET_NORMAL, test_api.GetCurrentCursorSet());
135}
136
137TEST_F(AshNativeCursorManagerTest, SetDeviceScaleFactorAndRotation) {
138  ::wm::CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager();
139  CursorManagerTestApi test_api(cursor_manager);
140  UpdateDisplay("800x100*2");
141  EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
142  EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
143
144  UpdateDisplay("800x100/l");
145  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
146  EXPECT_EQ(gfx::Display::ROTATE_270, test_api.GetCurrentCursorRotation());
147}
148
149#if defined(OS_CHROMEOS)
150// TODO(oshima): crbug.com/143619
151TEST_F(AshNativeCursorManagerTest, FractionalScale) {
152  ::wm::CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager();
153  CursorManagerTestApi test_api(cursor_manager);
154  // Cursor should use the resource scale factor.
155  UpdateDisplay("800x100*1.25");
156  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
157}
158#endif
159
160TEST_F(AshNativeCursorManagerTest, UIScaleShouldNotChangeCursor) {
161  int64 display_id = Shell::GetScreen()->GetPrimaryDisplay().id();
162  gfx::Display::SetInternalDisplayId(display_id);
163
164  ::wm::CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager();
165  CursorManagerTestApi test_api(cursor_manager);
166  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
167
168  display_manager->SetDisplayUIScale(display_id, 0.5f);
169  EXPECT_EQ(1.0f,
170            Shell::GetScreen()->GetPrimaryDisplay().device_scale_factor());
171  EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor());
172
173  display_manager->SetDisplayUIScale(display_id, 1.0f);
174
175  // 2x display should keep using 2x cursor regardless of the UI scale.
176  UpdateDisplay("800x800*2");
177  EXPECT_EQ(2.0f,
178            Shell::GetScreen()->GetPrimaryDisplay().device_scale_factor());
179  EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
180  display_manager->SetDisplayUIScale(display_id, 2.0f);
181  EXPECT_EQ(1.0f,
182            Shell::GetScreen()->GetPrimaryDisplay().device_scale_factor());
183  EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor());
184}
185
186#if defined(USE_X11)
187// This test is in ash_unittests becuase ui_unittests does not include
188// 2x assets. crbug.com/372541.
189TEST_F(AshNativeCursorManagerTest, CursorLoaderX11Test) {
190  const int kCursorId = 1;
191  ui::CursorLoaderX11 loader;
192  loader.set_scale(1.0f);
193
194  loader.LoadImageCursor(kCursorId, IDR_AURA_CURSOR_MOVE, gfx::Point());
195  const XcursorImage* image = loader.GetXcursorImageForTest(kCursorId);
196  int height = image->height;
197  int width = image->width;
198  loader.UnloadAll();
199
200  // Load 2x cursor and make sure its size is 2x of the 1x cusor.
201  loader.set_scale(2.0f);
202  loader.LoadImageCursor(kCursorId, IDR_AURA_CURSOR_MOVE, gfx::Point());
203  image = loader.GetXcursorImageForTest(kCursorId);
204  EXPECT_EQ(height * 2, static_cast<int>(image->height));
205  EXPECT_EQ(width * 2, static_cast<int>(image->width));
206}
207#endif
208
209}  // namespace test
210}  // namespace ash
211