1 // Copyright (c) 2013 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.
5 #include "ash/touch/touch_observer_hud.h"
7 #include "ash/ash_switches.h"
8 #include "ash/display/display_manager.h"
9 #include "ash/root_window_controller.h"
10 #include "ash/screen_util.h"
11 #include "ash/shell.h"
12 #include "ash/test/ash_test_base.h"
13 #include "ash/test/display_manager_test_api.h"
14 #include "ash/touch/touch_hud_debug.h"
15 #include "ash/touch/touch_hud_projection.h"
16 #include "base/command_line.h"
17 #include "base/format_macros.h"
18 #include "base/strings/stringprintf.h"
19 #include "ui/aura/window.h"
20 #include "ui/views/widget/widget.h"
24 class TouchHudTestBase
: public test::AshTestBase
{
27 ~TouchHudTestBase() override
{}
29 void SetUp() override
{
30 test::AshTestBase::SetUp();
32 // Initialize display infos. They should be initialized after Ash
33 // environment is set up, i.e., after test::AshTestBase::SetUp().
34 internal_display_id_
= test::DisplayManagerTestApi(GetDisplayManager()).
35 SetFirstDisplayAsInternalDisplay();
36 external_display_id_
= 10;
37 mirrored_display_id_
= 11;
39 internal_display_info_
=
40 CreateDisplayInfo(internal_display_id_
, gfx::Rect(0, 0, 500, 500));
41 external_display_info_
=
42 CreateDisplayInfo(external_display_id_
, gfx::Rect(1, 1, 100, 100));
43 mirrored_display_info_
=
44 CreateDisplayInfo(mirrored_display_id_
, gfx::Rect(0, 0, 100, 100));
47 gfx::Display
GetPrimaryDisplay() {
48 return Shell::GetScreen()->GetPrimaryDisplay();
51 const gfx::Display
& GetSecondaryDisplay() {
52 return ScreenUtil::GetSecondaryDisplay();
55 void SetupSingleDisplay() {
56 display_info_list_
.clear();
57 display_info_list_
.push_back(internal_display_info_
);
58 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
61 void SetupDualDisplays() {
62 display_info_list_
.clear();
63 display_info_list_
.push_back(internal_display_info_
);
64 display_info_list_
.push_back(external_display_info_
);
65 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
68 void SetInternalAsPrimary() {
69 const gfx::Display
& internal_display
=
70 GetDisplayManager()->GetDisplayForId(internal_display_id_
);
71 GetDisplayController()->SetPrimaryDisplay(internal_display
);
74 void SetExternalAsPrimary() {
75 const gfx::Display
& external_display
=
76 GetDisplayManager()->GetDisplayForId(external_display_id_
);
77 GetDisplayController()->SetPrimaryDisplay(external_display
);
80 void MirrorDisplays() {
81 DCHECK_EQ(2U, display_info_list_
.size());
82 DCHECK_EQ(internal_display_id_
, display_info_list_
[0].id());
83 DCHECK_EQ(external_display_id_
, display_info_list_
[1].id());
84 display_info_list_
[1] = mirrored_display_info_
;
85 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
88 void UnmirrorDisplays() {
89 DCHECK_EQ(2U, display_info_list_
.size());
90 DCHECK_EQ(internal_display_id_
, display_info_list_
[0].id());
91 DCHECK_EQ(mirrored_display_id_
, display_info_list_
[1].id());
92 display_info_list_
[1] = external_display_info_
;
93 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
96 void RemoveInternalDisplay() {
97 DCHECK_LT(0U, display_info_list_
.size());
98 DCHECK_EQ(internal_display_id_
, display_info_list_
[0].id());
99 display_info_list_
.erase(display_info_list_
.begin());
100 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
103 void RemoveExternalDisplay() {
104 DCHECK_EQ(2U, display_info_list_
.size());
105 display_info_list_
.pop_back();
106 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
109 void AddInternalDisplay() {
110 DCHECK_EQ(0U, display_info_list_
.size());
111 display_info_list_
.push_back(internal_display_info_
);
112 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
115 void AddExternalDisplay() {
116 DCHECK_EQ(1U, display_info_list_
.size());
117 display_info_list_
.push_back(external_display_info_
);
118 GetDisplayManager()->OnNativeDisplaysChanged(display_info_list_
);
121 int64
internal_display_id() const {
122 return internal_display_id_
;
125 int64
external_display_id() const {
126 return external_display_id_
;
130 DisplayManager
* GetDisplayManager() {
131 return Shell::GetInstance()->display_manager();
134 DisplayController
* GetDisplayController() {
135 return Shell::GetInstance()->display_controller();
138 const gfx::Display
& GetInternalDisplay() {
139 return GetDisplayManager()->GetDisplayForId(internal_display_id_
);
142 const gfx::Display
& GetExternalDisplay() {
143 return GetDisplayManager()->GetDisplayForId(external_display_id_
);
146 aura::Window
* GetInternalRootWindow() {
147 return GetDisplayController()->GetRootWindowForDisplayId(
148 internal_display_id_
);
151 aura::Window
* GetExternalRootWindow() {
152 return GetDisplayController()->GetRootWindowForDisplayId(
153 external_display_id_
);
156 aura::Window
* GetPrimaryRootWindow() {
157 const gfx::Display
& display
= GetPrimaryDisplay();
158 return GetDisplayController()->GetRootWindowForDisplayId(display
.id());
161 aura::Window
* GetSecondaryRootWindow() {
162 const gfx::Display
& display
= GetSecondaryDisplay();
163 return GetDisplayController()->GetRootWindowForDisplayId(display
.id());
166 RootWindowController
* GetInternalRootController() {
167 aura::Window
* root
= GetInternalRootWindow();
168 return GetRootWindowController(root
);
171 RootWindowController
* GetExternalRootController() {
172 aura::Window
* root
= GetExternalRootWindow();
173 return GetRootWindowController(root
);
176 RootWindowController
* GetPrimaryRootController() {
177 aura::Window
* root
= GetPrimaryRootWindow();
178 return GetRootWindowController(root
);
181 RootWindowController
* GetSecondaryRootController() {
182 aura::Window
* root
= GetSecondaryRootWindow();
183 return GetRootWindowController(root
);
186 DisplayInfo
CreateDisplayInfo(int64 id
, const gfx::Rect
& bounds
) {
187 DisplayInfo
info(id
, base::StringPrintf("x-%" PRId64
, id
), false);
188 info
.SetBounds(bounds
);
192 aura::Window
* GetRootWindowForTouchHud(TouchObserverHUD
* hud
) {
193 return hud
->root_window_
;
196 views::Widget
* GetWidgetForTouchHud(TouchObserverHUD
* hud
) {
200 int64 internal_display_id_
;
201 int64 external_display_id_
;
202 int64 mirrored_display_id_
;
203 DisplayInfo internal_display_info_
;
204 DisplayInfo external_display_info_
;
205 DisplayInfo mirrored_display_info_
;
207 std::vector
<DisplayInfo
> display_info_list_
;
209 DISALLOW_COPY_AND_ASSIGN(TouchHudTestBase
);
212 class TouchHudDebugTest
: public TouchHudTestBase
{
214 TouchHudDebugTest() {}
215 ~TouchHudDebugTest() override
{}
217 void SetUp() override
{
218 // Add ash-touch-hud flag to enable debug touch HUD. This flag should be set
219 // before Ash environment is set up, i.e., before TouchHudTestBase::SetUp().
220 base::CommandLine::ForCurrentProcess()->AppendSwitch(
221 ash::switches::kAshTouchHud
);
223 TouchHudTestBase::SetUp();
226 void CheckInternalDisplay() {
227 EXPECT_NE(static_cast<TouchObserverHUD
*>(NULL
), GetInternalTouchHudDebug());
228 EXPECT_EQ(internal_display_id(), GetInternalTouchHudDebug()->display_id());
229 EXPECT_EQ(GetInternalRootWindow(),
230 GetRootWindowForTouchHud(GetInternalTouchHudDebug()));
231 EXPECT_EQ(GetInternalRootWindow(),
232 GetWidgetForTouchHud(GetInternalTouchHudDebug())->
233 GetNativeView()->GetRootWindow());
234 EXPECT_EQ(GetInternalDisplay().size(),
235 GetWidgetForTouchHud(GetInternalTouchHudDebug())->
236 GetWindowBoundsInScreen().size());
239 void CheckExternalDisplay() {
240 EXPECT_NE(static_cast<TouchHudDebug
*>(NULL
), GetExternalTouchHudDebug());
241 EXPECT_EQ(external_display_id(), GetExternalTouchHudDebug()->display_id());
242 EXPECT_EQ(GetExternalRootWindow(),
243 GetRootWindowForTouchHud(GetExternalTouchHudDebug()));
244 EXPECT_EQ(GetExternalRootWindow(),
245 GetWidgetForTouchHud(GetExternalTouchHudDebug())->
246 GetNativeView()->GetRootWindow());
247 EXPECT_EQ(GetExternalDisplay().size(),
248 GetWidgetForTouchHud(GetExternalTouchHudDebug())->
249 GetWindowBoundsInScreen().size());
253 TouchHudDebug
* GetInternalTouchHudDebug() {
254 return GetInternalRootController()->touch_hud_debug();
257 TouchHudDebug
* GetExternalTouchHudDebug() {
258 return GetExternalRootController()->touch_hud_debug();
261 TouchHudDebug
* GetPrimaryTouchHudDebug() {
262 return GetPrimaryRootController()->touch_hud_debug();
265 TouchHudDebug
* GetSecondaryTouchHudDebug() {
266 return GetSecondaryRootController()->touch_hud_debug();
269 DISALLOW_COPY_AND_ASSIGN(TouchHudDebugTest
);
272 class TouchHudProjectionTest
: public TouchHudTestBase
{
274 TouchHudProjectionTest() {}
275 ~TouchHudProjectionTest() override
{}
277 void EnableTouchHudProjection() {
278 Shell::GetInstance()->SetTouchHudProjectionEnabled(true);
281 void DisableTouchHudProjection() {
282 Shell::GetInstance()->SetTouchHudProjectionEnabled(false);
285 TouchHudProjection
* GetInternalTouchHudProjection() {
286 return GetInternalRootController()->touch_hud_projection();
289 int GetInternalTouchPointsCount() {
290 return GetInternalTouchHudProjection()->points_
.size();
293 void SendTouchEventToInternalHud(ui::EventType type
,
294 const gfx::Point
& location
,
296 ui::TouchEvent
event(type
, location
, touch_id
, event_time
);
297 GetInternalTouchHudProjection()->OnTouchEvent(&event
);
299 // Advance time for next event.
300 event_time
+= base::TimeDelta::FromMilliseconds(100);
304 base::TimeDelta event_time
;
306 DISALLOW_COPY_AND_ASSIGN(TouchHudProjectionTest
);
309 // Checks if debug touch HUD is correctly initialized for a single display.
310 TEST_F(TouchHudDebugTest
, SingleDisplay
) {
311 // Setup a single display setting.
312 SetupSingleDisplay();
314 // Check if touch HUD is set correctly and associated with appropriate
316 CheckInternalDisplay();
319 // Checks if debug touch HUDs are correctly initialized for two displays.
320 TEST_F(TouchHudDebugTest
, DualDisplays
) {
321 if (!SupportsMultipleDisplays())
324 // Setup a dual display setting.
327 // Check if touch HUDs are set correctly and associated with appropriate
329 CheckInternalDisplay();
330 CheckExternalDisplay();
333 // Checks if debug touch HUDs are correctly handled when primary display is
335 TEST_F(TouchHudDebugTest
, SwapPrimaryDisplay
) {
336 if (!SupportsMultipleDisplays())
339 // Setup a dual display setting.
342 // Set the primary display to the external one.
343 SetExternalAsPrimary();
345 // Check if displays' touch HUDs are not swapped as root windows are.
346 EXPECT_EQ(external_display_id(), GetPrimaryDisplay().id());
347 EXPECT_EQ(internal_display_id(), GetSecondaryDisplay().id());
348 CheckInternalDisplay();
349 CheckExternalDisplay();
351 // Set the primary display back to the internal one.
352 SetInternalAsPrimary();
354 // Check if displays' touch HUDs are not swapped back as root windows are.
355 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
356 EXPECT_EQ(external_display_id(), GetSecondaryDisplay().id());
357 CheckInternalDisplay();
358 CheckExternalDisplay();
361 // Checks if debug touch HUDs are correctly handled when displays are mirrored.
362 TEST_F(TouchHudDebugTest
, MirrorDisplays
) {
363 if (!SupportsMultipleDisplays())
366 // Setup a dual display setting.
372 // Check if the internal display is intact.
373 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
374 CheckInternalDisplay();
376 // Unmirror displays.
379 // Check if external display is added back correctly.
380 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
381 EXPECT_EQ(external_display_id(), GetSecondaryDisplay().id());
382 CheckInternalDisplay();
383 CheckExternalDisplay();
386 // Checks if debug touch HUDs are correctly handled when displays are mirrored
387 // after setting the external display as the primary one.
388 TEST_F(TouchHudDebugTest
, SwapPrimaryThenMirrorDisplays
) {
389 if (!SupportsMultipleDisplays())
392 // Setup a dual display setting.
395 // Set the primary display to the external one.
396 SetExternalAsPrimary();
401 // Check if the internal display is set as the primary one.
402 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
403 CheckInternalDisplay();
405 // Unmirror displays.
408 // Check if the external display is added back as the primary display and
409 // touch HUDs are set correctly.
410 EXPECT_EQ(external_display_id(), GetPrimaryDisplay().id());
411 EXPECT_EQ(internal_display_id(), GetSecondaryDisplay().id());
412 CheckInternalDisplay();
413 CheckExternalDisplay();
416 // Checks if debug touch HUDs are correctly handled when the external display,
417 // which is the secondary one, is removed.
418 TEST_F(TouchHudDebugTest
, RemoveSecondaryDisplay
) {
419 if (!SupportsMultipleDisplays())
422 // Setup a dual display setting.
425 // Remove external display which is the secondary one.
426 RemoveExternalDisplay();
428 // Check if the internal display is intact.
429 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
430 CheckInternalDisplay();
432 // Add external display back.
433 AddExternalDisplay();
435 // Check if displays' touch HUDs are set correctly.
436 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
437 EXPECT_EQ(external_display_id(), GetSecondaryDisplay().id());
438 CheckInternalDisplay();
439 CheckExternalDisplay();
442 // Checks if debug touch HUDs are correctly handled when the external display,
443 // which is set as the primary display, is removed.
444 TEST_F(TouchHudDebugTest
, RemovePrimaryDisplay
) {
445 if (!SupportsMultipleDisplays())
448 // Setup a dual display setting.
451 // Set the primary display to the external one.
452 SetExternalAsPrimary();
454 // Remove the external display which is the primary display.
455 RemoveExternalDisplay();
457 // Check if the internal display is set as the primary one.
458 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
459 CheckInternalDisplay();
461 // Add the external display back.
462 AddExternalDisplay();
464 // Check if the external display is set as primary and touch HUDs are set
466 EXPECT_EQ(external_display_id(), GetPrimaryDisplay().id());
467 EXPECT_EQ(internal_display_id(), GetSecondaryDisplay().id());
468 CheckInternalDisplay();
469 CheckExternalDisplay();
472 // Checks if debug touch HUDs are correctly handled when all displays are
474 TEST_F(TouchHudDebugTest
, Headless
) {
475 if (!SupportsMultipleDisplays())
478 // Setup a single display setting.
479 SetupSingleDisplay();
481 // Remove the only display which is the internal one.
482 RemoveInternalDisplay();
484 // Add the internal display back.
485 AddInternalDisplay();
487 // Check if the display's touch HUD is set correctly.
488 EXPECT_EQ(internal_display_id(), GetPrimaryDisplay().id());
489 CheckInternalDisplay();
492 // Checks projection touch HUD with a sequence of touch-pressed, touch-moved,
493 // and touch-released events.
494 TEST_F(TouchHudProjectionTest
, TouchMoveRelease
) {
495 SetupSingleDisplay();
496 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
498 EnableTouchHudProjection();
499 EXPECT_NE(static_cast<TouchHudProjection
*>(NULL
),
500 GetInternalTouchHudProjection());
501 EXPECT_EQ(0, GetInternalTouchPointsCount());
503 SendTouchEventToInternalHud(ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 1);
504 EXPECT_EQ(1, GetInternalTouchPointsCount());
506 SendTouchEventToInternalHud(ui::ET_TOUCH_MOVED
, gfx::Point(10, 20), 1);
507 EXPECT_EQ(1, GetInternalTouchPointsCount());
509 SendTouchEventToInternalHud(ui::ET_TOUCH_RELEASED
, gfx::Point(10, 20), 1);
510 EXPECT_EQ(0, GetInternalTouchPointsCount());
512 // Disabling projection touch HUD shoud remove it without crashing.
513 DisableTouchHudProjection();
514 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
517 // Checks projection touch HUD with a sequence of touch-pressed, touch-moved,
518 // and touch-cancelled events.
519 TEST_F(TouchHudProjectionTest
, TouchMoveCancel
) {
520 SetupSingleDisplay();
521 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
523 EnableTouchHudProjection();
524 EXPECT_NE(static_cast<TouchHudProjection
*>(NULL
),
525 GetInternalTouchHudProjection());
526 EXPECT_EQ(0, GetInternalTouchPointsCount());
528 SendTouchEventToInternalHud(ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 1);
529 EXPECT_EQ(1, GetInternalTouchPointsCount());
531 SendTouchEventToInternalHud(ui::ET_TOUCH_MOVED
, gfx::Point(10, 20), 1);
532 EXPECT_EQ(1, GetInternalTouchPointsCount());
534 SendTouchEventToInternalHud(ui::ET_TOUCH_CANCELLED
, gfx::Point(10, 20), 1);
535 EXPECT_EQ(0, GetInternalTouchPointsCount());
537 // Disabling projection touch HUD shoud remove it without crashing.
538 DisableTouchHudProjection();
539 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
542 // Checks projection touch HUD with two simultaneous touches.
543 TEST_F(TouchHudProjectionTest
, DoubleTouch
) {
544 SetupSingleDisplay();
545 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
547 EnableTouchHudProjection();
548 EXPECT_NE(static_cast<TouchHudProjection
*>(NULL
),
549 GetInternalTouchHudProjection());
550 EXPECT_EQ(0, GetInternalTouchPointsCount());
552 SendTouchEventToInternalHud(ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 1);
553 EXPECT_EQ(1, GetInternalTouchPointsCount());
555 SendTouchEventToInternalHud(ui::ET_TOUCH_PRESSED
, gfx::Point(20, 10), 2);
556 EXPECT_EQ(2, GetInternalTouchPointsCount());
558 SendTouchEventToInternalHud(ui::ET_TOUCH_MOVED
, gfx::Point(10, 20), 1);
559 EXPECT_EQ(2, GetInternalTouchPointsCount());
561 SendTouchEventToInternalHud(ui::ET_TOUCH_MOVED
, gfx::Point(20, 20), 2);
562 EXPECT_EQ(2, GetInternalTouchPointsCount());
564 SendTouchEventToInternalHud(ui::ET_TOUCH_RELEASED
, gfx::Point(10, 20), 1);
565 EXPECT_EQ(1, GetInternalTouchPointsCount());
567 SendTouchEventToInternalHud(ui::ET_TOUCH_RELEASED
, gfx::Point(20, 20), 2);
568 EXPECT_EQ(0, GetInternalTouchPointsCount());
570 // Disabling projection touch HUD shoud remove it without crashing.
571 DisableTouchHudProjection();
572 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
575 // Checks if turning off touch HUD projection while touching the screen is
576 // handled correctly.
577 TEST_F(TouchHudProjectionTest
, DisableWhileTouching
) {
578 SetupSingleDisplay();
579 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());
581 EnableTouchHudProjection();
582 EXPECT_NE(static_cast<TouchHudProjection
*>(NULL
),
583 GetInternalTouchHudProjection());
584 EXPECT_EQ(0, GetInternalTouchPointsCount());
586 SendTouchEventToInternalHud(ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 1);
587 EXPECT_EQ(1, GetInternalTouchPointsCount());
589 // Disabling projection touch HUD shoud remove it without crashing.
590 DisableTouchHudProjection();
591 EXPECT_EQ(NULL
, GetInternalTouchHudProjection());