1 // Copyright 2014 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_transformer_controller.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ui/aura/window_tree_host.h"
10 #include "ui/events/devices/device_data_manager.h"
11 #include "ui/gfx/display.h"
17 DisplayInfo
CreateDisplayInfo(int64 id
,
18 unsigned int touch_device_id
,
19 const gfx::Rect
& bounds
) {
20 DisplayInfo
info(id
, std::string(), false);
21 info
.SetBounds(bounds
);
22 info
.set_touch_device_id(touch_device_id
);
24 // Create a default mode.
25 std::vector
<DisplayMode
> default_modes(
26 1, DisplayMode(bounds
.size(), 60, false, true));
27 info
.SetDisplayModes(default_modes
);
32 ui::TouchscreenDevice
CreateTouchscreenDevice(unsigned int id
,
33 const gfx::Size
& size
) {
34 return ui::TouchscreenDevice(id
, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL
,
35 std::string(), size
, 0);
40 typedef test::AshTestBase TouchTransformerControllerTest
;
42 TEST_F(TouchTransformerControllerTest
, MirrorModeLetterboxing
) {
43 // The internal display has native resolution of 2560x1700, and in
44 // mirror mode it is configured as 1920x1200. This is in letterboxing
46 DisplayInfo internal_display_info
=
47 CreateDisplayInfo(1, 10u, gfx::Rect(0, 0, 1920, 1200));
48 internal_display_info
.set_is_aspect_preserving_scaling(true);
49 std::vector
<DisplayMode
> internal_modes
;
50 internal_modes
.push_back(
51 DisplayMode(gfx::Size(2560, 1700), 60, false, true));
52 internal_modes
.push_back(
53 DisplayMode(gfx::Size(1920, 1200), 60, false, false));
54 internal_display_info
.SetDisplayModes(internal_modes
);
56 DisplayInfo external_display_info
=
57 CreateDisplayInfo(2, 11u, gfx::Rect(0, 0, 1920, 1200));
59 gfx::Size
fb_size(1920, 1200);
61 // Create the touchscreens with the same size as the framebuffer so we can
62 // share the tests between Ozone & X11.
63 ui::TouchscreenDevice internal_touchscreen
=
64 CreateTouchscreenDevice(10, fb_size
);
65 ui::TouchscreenDevice external_touchscreen
=
66 CreateTouchscreenDevice(11, fb_size
);
68 TouchTransformerController
* tt_controller
=
69 Shell::GetInstance()->touch_transformer_controller();
70 ui::DeviceDataManager
* device_manager
= ui::DeviceDataManager::GetInstance();
72 device_manager
->UpdateTouchInfoForDisplay(
73 internal_display_info
.id(), internal_display_info
.touch_device_id(),
74 tt_controller
->GetTouchTransform(internal_display_info
,
75 internal_display_info
,
76 internal_touchscreen
, fb_size
));
78 device_manager
->UpdateTouchInfoForDisplay(
79 internal_display_info
.id(), external_display_info
.touch_device_id(),
80 tt_controller
->GetTouchTransform(external_display_info
,
81 external_display_info
,
82 external_touchscreen
, fb_size
));
84 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(10));
85 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(11));
87 // External touch display has the default TouchTransformer.
90 device_manager
->ApplyTouchTransformer(11, &x
, &y
);
94 // In letterboxing, there is (1-2560*(1200/1920)/1700)/2 = 2.95% of the
95 // height on both the top & bottom region of the screen is blank.
96 // When touch events coming at Y range [0, 1200), the mapping should be
98 // [~35, ~1165] ---> [0, 1200)
99 // [~1165, 1200] ---> >= 1200
102 device_manager
->ApplyTouchTransformer(10, &x
, &y
);
103 EXPECT_NEAR(100, x
, 0.5);
104 EXPECT_NEAR(0, y
, 0.5);
108 device_manager
->ApplyTouchTransformer(10, &x
, &y
);
109 EXPECT_NEAR(100, x
, 0.5);
110 EXPECT_NEAR(1200, y
, 0.5);
113 TEST_F(TouchTransformerControllerTest
, MirrorModePillarboxing
) {
114 // The internal display has native resolution of 1366x768, and in
115 // mirror mode it is configured as 1024x768. This is in pillarboxing
117 DisplayInfo internal_display_info
=
118 CreateDisplayInfo(1, 10, gfx::Rect(0, 0, 1024, 768));
119 internal_display_info
.set_is_aspect_preserving_scaling(true);
120 std::vector
<DisplayMode
> internal_modes
;
121 internal_modes
.push_back(
122 DisplayMode(gfx::Size(1366, 768), 60, false, true));
123 internal_modes
.push_back(
124 DisplayMode(gfx::Size(1024, 768), 60, false, false));
125 internal_display_info
.SetDisplayModes(internal_modes
);
127 DisplayInfo external_display_info
=
128 CreateDisplayInfo(2, 11, gfx::Rect(0, 0, 1024, 768));
130 gfx::Size
fb_size(1024, 768);
132 // Create the touchscreens with the same size as the framebuffer so we can
133 // share the tests between Ozone & X11.
134 ui::TouchscreenDevice internal_touchscreen
=
135 CreateTouchscreenDevice(10, fb_size
);
136 ui::TouchscreenDevice external_touchscreen
=
137 CreateTouchscreenDevice(11, fb_size
);
139 TouchTransformerController
* tt_controller
=
140 Shell::GetInstance()->touch_transformer_controller();
141 ui::DeviceDataManager
* device_manager
= ui::DeviceDataManager::GetInstance();
143 device_manager
->UpdateTouchInfoForDisplay(
144 internal_display_info
.id(), internal_display_info
.touch_device_id(),
145 tt_controller
->GetTouchTransform(internal_display_info
,
146 internal_display_info
,
147 internal_touchscreen
, fb_size
));
149 device_manager
->UpdateTouchInfoForDisplay(
150 internal_display_info
.id(), external_display_info
.touch_device_id(),
151 tt_controller
->GetTouchTransform(external_display_info
,
152 external_display_info
,
153 external_touchscreen
, fb_size
));
155 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(10));
156 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(11));
158 // External touch display has the default TouchTransformer.
161 device_manager
->ApplyTouchTransformer(11, &x
, &y
);
165 // In pillarboxing, there is (1-768*(1024/768)/1366)/2 = 12.5% of the
166 // width on both the left & rigth region of the screen is blank.
167 // When touch events coming at X range [0, 1024), the mapping should be
168 // [0, ~128] ---> < 0
169 // [~128, ~896] ---> [0, 1024)
170 // [~896, 1024] ---> >= 1024
173 device_manager
->ApplyTouchTransformer(10, &x
, &y
);
174 EXPECT_NEAR(0, x
, 0.5);
175 EXPECT_NEAR(100, y
, 0.5);
179 device_manager
->ApplyTouchTransformer(10, &x
, &y
);
180 EXPECT_NEAR(1024, x
, 0.5);
181 EXPECT_NEAR(100, y
, 0.5);
184 TEST_F(TouchTransformerControllerTest
, SoftwareMirrorMode
) {
185 // External display 1 has size 1280x850. External display 2 has size
186 // 1920x1080. When using software mirroring to mirror display 1 onto
187 // display 2, the displays are in extended mode and we map touches from both
188 // displays to display 1.
189 // The total frame buffer is 1920x1990,
190 // where 1990 = 850 + 60 (hidden gap) + 1080 and the second monitor is
191 // translated to point (0, 950) in the framebuffer.
192 DisplayInfo display1_info
=
193 CreateDisplayInfo(1, 10u, gfx::Rect(0, 0, 1280, 850));
194 std::vector
<DisplayMode
> display1_modes
;
195 display1_modes
.push_back(DisplayMode(gfx::Size(1280, 850), 60, false, true));
196 display1_info
.SetDisplayModes(display1_modes
);
198 DisplayInfo display2_info
=
199 CreateDisplayInfo(2, 11u, gfx::Rect(0, 950, 1920, 1080));
200 std::vector
<DisplayMode
> display2_modes
;
201 display2_modes
.push_back(DisplayMode(gfx::Size(1920, 1080), 60, false, true));
202 display2_info
.SetDisplayModes(display2_modes
);
204 gfx::Size
fb_size(1920, 1990);
206 // Create the touchscreens with the same size as the framebuffer so we can
207 // share the tests between Ozone & X11.
208 ui::TouchscreenDevice display1_touchscreen
=
209 CreateTouchscreenDevice(10, fb_size
);
210 ui::TouchscreenDevice display2_touchscreen
=
211 CreateTouchscreenDevice(11, fb_size
);
213 TouchTransformerController
* tt_controller
=
214 Shell::GetInstance()->touch_transformer_controller();
215 ui::DeviceDataManager
* device_manager
= ui::DeviceDataManager::GetInstance();
217 device_manager
->UpdateTouchInfoForDisplay(
218 display1_info
.id(), display1_info
.touch_device_id(),
219 tt_controller
->GetTouchTransform(display1_info
, display1_info
,
220 display1_touchscreen
, fb_size
));
222 device_manager
->UpdateTouchInfoForDisplay(
223 display1_info
.id(), display2_info
.touch_device_id(),
224 tt_controller
->GetTouchTransform(display1_info
, display2_info
,
225 display2_touchscreen
, fb_size
));
227 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(10));
228 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(11));
230 // Mapping for touch events from display 1's touchscreen:
231 // [0, 1920) x [0, 1990) -> [0, 1280) x [0, 850)
234 device_manager
->ApplyTouchTransformer(10, &x
, &y
);
235 EXPECT_NEAR(0, x
, 0.5);
236 EXPECT_NEAR(0, y
, 0.5);
240 device_manager
->ApplyTouchTransformer(10, &x
, &y
);
241 EXPECT_NEAR(1280, x
, 0.5);
242 EXPECT_NEAR(850, y
, 0.5);
244 // In pillarboxing, there is (1-1280*(1080/850)/1920)/2 = 7.65% of the
245 // width on both the left & right region of the screen is blank.
246 // Events come in the range [0, 1920) x [0, 1990).
249 // [0, ~147] ---> < 0
250 // [~147, ~1773] ---> [0, 1280)
251 // [~1773, 1920] ---> >= 1280
253 // [0, 1990) -> [0, 1080)
256 device_manager
->ApplyTouchTransformer(11, &x
, &y
);
257 EXPECT_NEAR(0, x
, 0.5);
258 EXPECT_NEAR(0, y
, 0.5);
262 device_manager
->ApplyTouchTransformer(11, &x
, &y
);
263 EXPECT_NEAR(1280, x
, 0.5);
264 EXPECT_NEAR(850, y
, 0.5);
267 TEST_F(TouchTransformerControllerTest
, ExtendedMode
) {
268 // The internal display has size 1366 x 768. The external display has
269 // size 2560x1600. The total frame buffer is 2560x2428,
270 // where 2428 = 768 + 60 (hidden gap) + 1600
271 // and the second monitor is translated to Point (0, 828) in the
273 DisplayInfo display1
= CreateDisplayInfo(1, 5u, gfx::Rect(0, 0, 1366, 768));
274 DisplayInfo display2
=
275 CreateDisplayInfo(2, 6u, gfx::Rect(0, 828, 2560, 1600));
276 gfx::Size
fb_size(2560, 2428);
278 // Create the touchscreens with the same size as the framebuffer so we can
279 // share the tests between Ozone & X11.
280 ui::TouchscreenDevice touchscreen1
= CreateTouchscreenDevice(5, fb_size
);
281 ui::TouchscreenDevice touchscreen2
= CreateTouchscreenDevice(6, fb_size
);
283 TouchTransformerController
* tt_controller
=
284 Shell::GetInstance()->touch_transformer_controller();
285 ui::DeviceDataManager
* device_manager
= ui::DeviceDataManager::GetInstance();
287 device_manager
->UpdateTouchInfoForDisplay(
288 display1
.id(), display1
.touch_device_id(),
289 tt_controller
->GetTouchTransform(display1
, display1
, touchscreen1
,
292 device_manager
->UpdateTouchInfoForDisplay(
293 display2
.id(), display2
.touch_device_id(),
294 tt_controller
->GetTouchTransform(display2
, display2
, touchscreen2
,
297 EXPECT_EQ(1, device_manager
->GetTargetDisplayForTouchDevice(5));
298 EXPECT_EQ(2, device_manager
->GetTargetDisplayForTouchDevice(6));
300 // Mapping for touch events from internal touch display:
301 // [0, 2560) x [0, 2428) -> [0, 1366) x [0, 768)
304 device_manager
->ApplyTouchTransformer(5, &x
, &y
);
305 EXPECT_NEAR(0, x
, 0.5);
306 EXPECT_NEAR(0, y
, 0.5);
310 device_manager
->ApplyTouchTransformer(5, &x
, &y
);
311 EXPECT_NEAR(1365, x
, 0.5);
312 EXPECT_NEAR(768, y
, 0.5);
314 // Mapping for touch events from external touch display:
315 // [0, 2560) x [0, 2428) -> [0, 2560) x [0, 1600)
318 device_manager
->ApplyTouchTransformer(6, &x
, &y
);
319 #if defined(USE_OZONE)
320 // On ozone we expect screen coordinates so add display origin.
321 EXPECT_NEAR(0 + 0, x
, 0.5);
322 EXPECT_NEAR(0 + 828, y
, 0.5);
324 EXPECT_NEAR(0, x
, 0.5);
325 EXPECT_NEAR(0, y
, 0.5);
330 device_manager
->ApplyTouchTransformer(6, &x
, &y
);
331 #if defined(USE_OZONE)
332 // On ozone we expect screen coordinates so add display origin.
333 EXPECT_NEAR(2559 + 0, x
, 0.5);
334 EXPECT_NEAR(1599 + 828, y
, 0.5);
336 EXPECT_NEAR(2559, x
, 0.5);
337 EXPECT_NEAR(1599, y
, 0.5);
341 TEST_F(TouchTransformerControllerTest
, TouchRadiusScale
) {
342 DisplayInfo display
= CreateDisplayInfo(1, 5u, gfx::Rect(0, 0, 2560, 1600));
343 ui::TouchscreenDevice touch_device
=
344 CreateTouchscreenDevice(5, gfx::Size(1001, 1001));
346 TouchTransformerController
* tt_controller
=
347 Shell::GetInstance()->touch_transformer_controller();
348 // Default touchscreen position range is 1001x1001;
349 EXPECT_EQ(sqrt((2560.0 * 1600.0) / (1001.0 * 1001.0)),
350 tt_controller
->GetTouchResolutionScale(display
, touch_device
));