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.
7 #include <X11/extensions/XInput2.h>
10 // Generically-named #defines from Xlib that conflict with symbols in GTest.
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/events/event.h"
16 #include "ui/events/event_constants.h"
17 #include "ui/events/event_utils.h"
18 #include "ui/events/x/events_x_utils.h"
19 #include "ui/gfx/point.h"
25 // Initializes the passed-in Xlib event.
26 void InitButtonEvent(XEvent
* event
,
28 const gfx::Point
& location
,
31 memset(event
, 0, sizeof(*event
));
33 // We don't bother setting fields that the event code doesn't use, such as
34 // x_root/y_root and window/root/subwindow.
35 XButtonEvent
* button_event
= &(event
->xbutton
);
36 button_event
->type
= is_press
? ButtonPress
: ButtonRelease
;
37 button_event
->x
= location
.x();
38 button_event
->y
= location
.y();
39 button_event
->button
= button
;
40 button_event
->state
= state
;
45 TEST(EventsXTest
, ButtonEvents
) {
47 gfx::Point
location(5, 10);
50 InitButtonEvent(&event
, true, location
, 1, 0);
51 EXPECT_EQ(ui::ET_MOUSE_PRESSED
, ui::EventTypeFromNative(&event
));
52 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON
, ui::EventFlagsFromNative(&event
));
53 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
54 EXPECT_TRUE(ui::IsMouseEvent(&event
));
56 InitButtonEvent(&event
, true, location
, 2, Button1Mask
| ShiftMask
);
57 EXPECT_EQ(ui::ET_MOUSE_PRESSED
, ui::EventTypeFromNative(&event
));
58 EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON
| ui::EF_MIDDLE_MOUSE_BUTTON
|
60 ui::EventFlagsFromNative(&event
));
61 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
62 EXPECT_TRUE(ui::IsMouseEvent(&event
));
64 InitButtonEvent(&event
, false, location
, 3, 0);
65 EXPECT_EQ(ui::ET_MOUSE_RELEASED
, ui::EventTypeFromNative(&event
));
66 EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON
, ui::EventFlagsFromNative(&event
));
67 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
68 EXPECT_TRUE(ui::IsMouseEvent(&event
));
71 InitButtonEvent(&event
, true, location
, 4, 0);
72 EXPECT_EQ(ui::ET_MOUSEWHEEL
, ui::EventTypeFromNative(&event
));
73 EXPECT_EQ(0, ui::EventFlagsFromNative(&event
));
74 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
75 EXPECT_TRUE(ui::IsMouseEvent(&event
));
76 offset
= ui::GetMouseWheelOffset(&event
);
77 EXPECT_GT(offset
.y(), 0);
78 EXPECT_EQ(0, offset
.x());
81 InitButtonEvent(&event
, true, location
, 5, 0);
82 EXPECT_EQ(ui::ET_MOUSEWHEEL
, ui::EventTypeFromNative(&event
));
83 EXPECT_EQ(0, ui::EventFlagsFromNative(&event
));
84 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
85 EXPECT_TRUE(ui::IsMouseEvent(&event
));
86 offset
= ui::GetMouseWheelOffset(&event
);
87 EXPECT_LT(offset
.y(), 0);
88 EXPECT_EQ(0, offset
.x());
90 // Scroll left, typically.
91 InitButtonEvent(&event
, true, location
, 6, 0);
92 EXPECT_EQ(ui::ET_MOUSEWHEEL
, ui::EventTypeFromNative(&event
));
93 EXPECT_EQ(0, ui::EventFlagsFromNative(&event
));
94 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
95 EXPECT_TRUE(ui::IsMouseEvent(&event
));
96 offset
= ui::GetMouseWheelOffset(&event
);
97 EXPECT_EQ(0, offset
.y());
98 EXPECT_EQ(0, offset
.x());
100 // Scroll right, typically.
101 InitButtonEvent(&event
, true, location
, 7, 0);
102 EXPECT_EQ(ui::ET_MOUSEWHEEL
, ui::EventTypeFromNative(&event
));
103 EXPECT_EQ(0, ui::EventFlagsFromNative(&event
));
104 EXPECT_EQ(location
, ui::EventLocationFromNative(&event
));
105 EXPECT_TRUE(ui::IsMouseEvent(&event
));
106 offset
= ui::GetMouseWheelOffset(&event
);
107 EXPECT_EQ(0, offset
.y());
108 EXPECT_EQ(0, offset
.x());
110 // TODO(derat): Test XInput code.
113 TEST(EventsXTest
, AvoidExtraEventsOnWheelRelease
) {
115 gfx::Point
location(5, 10);
117 InitButtonEvent(&event
, true, location
, 4, 0);
118 EXPECT_EQ(ui::ET_MOUSEWHEEL
, ui::EventTypeFromNative(&event
));
120 // We should return ET_UNKNOWN for the release event instead of returning
121 // ET_MOUSEWHEEL; otherwise we'll scroll twice for each scrollwheel step.
122 InitButtonEvent(&event
, false, location
, 4, 0);
123 EXPECT_EQ(ui::ET_UNKNOWN
, ui::EventTypeFromNative(&event
));
125 // TODO(derat): Test XInput code.
128 TEST(EventsXTest
, EnterLeaveEvent
) {
130 event
.xcrossing
.type
= EnterNotify
;
131 event
.xcrossing
.x
= 10;
132 event
.xcrossing
.y
= 20;
133 event
.xcrossing
.x_root
= 110;
134 event
.xcrossing
.y_root
= 120;
136 // Mouse enter events are converted to mouse move events to be consistent with
137 // the way views handle mouse enter. See comments for EnterNotify case in
138 // ui::EventTypeFromNative for more details.
139 EXPECT_EQ(ui::ET_MOUSE_MOVED
, ui::EventTypeFromNative(&event
));
140 EXPECT_EQ("10,20", ui::EventLocationFromNative(&event
).ToString());
141 EXPECT_EQ("110,120", ui::EventSystemLocationFromNative(&event
).ToString());
143 event
.xcrossing
.type
= LeaveNotify
;
144 event
.xcrossing
.x
= 30;
145 event
.xcrossing
.y
= 40;
146 event
.xcrossing
.x_root
= 230;
147 event
.xcrossing
.y_root
= 240;
148 EXPECT_EQ(ui::ET_MOUSE_EXITED
, ui::EventTypeFromNative(&event
));
149 EXPECT_EQ("30,40", ui::EventLocationFromNative(&event
).ToString());
150 EXPECT_EQ("230,240", ui::EventSystemLocationFromNative(&event
).ToString());
153 TEST(EventsXTest
, ClickCount
) {
155 gfx::Point
location(5, 10);
157 for (int i
= 1; i
<= 3; ++i
) {
158 InitButtonEvent(&event
, true, location
, 1, 0);
160 MouseEvent
mouseev(&event
);
161 EXPECT_EQ(ui::ET_MOUSE_PRESSED
, mouseev
.type());
162 EXPECT_EQ(i
, mouseev
.GetClickCount());
165 InitButtonEvent(&event
, false, location
, 1, 0);
167 MouseEvent
mouseev(&event
);
168 EXPECT_EQ(ui::ET_MOUSE_RELEASED
, mouseev
.type());
169 EXPECT_EQ(i
, mouseev
.GetClickCount());
174 #if defined(USE_XI2_MT)
175 TEST(EventsXTest
, TouchEventBasic
) {
176 std::vector
<unsigned int> devices
;
177 devices
.push_back(0);
178 ui::SetupTouchDevicesForTest(devices
);
179 std::vector
<Valuator
> valuators
;
181 // Init touch begin with tracking id 5, touch id 0.
182 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_MAJOR
, 20));
183 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_ORIENTATION
, 0.3f
));
184 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_PRESSURE
, 100));
185 ui::ScopedXI2Event
event1(CreateTouchEventForTest(
186 0, XI_TouchBegin
, 5, gfx::Point(10, 10), valuators
));
187 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, ui::EventTypeFromNative(event1
));
188 EXPECT_EQ("10,10", ui::EventLocationFromNative(event1
).ToString());
189 EXPECT_EQ(GetTouchId(event1
), 0);
190 EXPECT_EQ(GetTouchRadiusX(event1
), 10);
191 EXPECT_FLOAT_EQ(GetTouchAngle(event1
), 0.15f
);
192 EXPECT_FLOAT_EQ(GetTouchForce(event1
), 0.1f
);
194 // Touch update, with new orientation info.
196 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_ORIENTATION
, 0.5f
));
197 ui::ScopedXI2Event
event2(CreateTouchEventForTest(
198 0, XI_TouchUpdate
, 5, gfx::Point(20, 20), valuators
));
199 EXPECT_EQ(ui::ET_TOUCH_MOVED
, ui::EventTypeFromNative(event2
));
200 EXPECT_EQ("20,20", ui::EventLocationFromNative(event2
).ToString());
201 EXPECT_EQ(GetTouchId(event2
), 0);
202 EXPECT_EQ(GetTouchRadiusX(event2
), 10);
203 EXPECT_FLOAT_EQ(GetTouchAngle(event2
), 0.25f
);
204 EXPECT_FLOAT_EQ(GetTouchForce(event2
), 0.1f
);
206 // Another touch with tracking id 6, touch id 1.
208 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_MAJOR
, 100));
209 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_ORIENTATION
, 0.9f
));
210 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_PRESSURE
, 500));
211 ui::ScopedXI2Event
event3(CreateTouchEventForTest(
212 0, XI_TouchBegin
, 6, gfx::Point(200, 200), valuators
));
213 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, ui::EventTypeFromNative(event3
));
214 EXPECT_EQ("200,200", ui::EventLocationFromNative(event3
).ToString());
215 EXPECT_EQ(GetTouchId(event3
), 1);
216 EXPECT_EQ(GetTouchRadiusX(event3
), 50);
217 EXPECT_FLOAT_EQ(GetTouchAngle(event3
), 0.45f
);
218 EXPECT_FLOAT_EQ(GetTouchForce(event3
), 0.5f
);
220 // Touch with tracking id 5 should have old radius/angle value and new pressue
223 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_PRESSURE
, 50));
224 ui::ScopedXI2Event
event4(CreateTouchEventForTest(
225 0, XI_TouchEnd
, 5, gfx::Point(30, 30), valuators
));
226 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, ui::EventTypeFromNative(event4
));
227 EXPECT_EQ("30,30", ui::EventLocationFromNative(event4
).ToString());
228 EXPECT_EQ(GetTouchId(event4
), 0);
229 EXPECT_EQ(GetTouchRadiusX(event4
), 10);
230 EXPECT_FLOAT_EQ(GetTouchAngle(event4
), 0.25f
);
231 EXPECT_FLOAT_EQ(GetTouchForce(event4
), 0.05f
);
233 // Touch with tracking id 6 should have old angle/pressure value and new
236 valuators
.push_back(Valuator(DeviceDataManager::DT_TOUCH_MAJOR
, 50));
237 ui::ScopedXI2Event
event5(CreateTouchEventForTest(
238 0, XI_TouchEnd
, 6, gfx::Point(200, 200), valuators
));
239 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, ui::EventTypeFromNative(event5
));
240 EXPECT_EQ("200,200", ui::EventLocationFromNative(event5
).ToString());
241 EXPECT_EQ(GetTouchId(event5
), 1);
242 EXPECT_EQ(GetTouchRadiusX(event5
), 25);
243 EXPECT_FLOAT_EQ(GetTouchAngle(event5
), 0.45f
);
244 EXPECT_FLOAT_EQ(GetTouchForce(event5
), 0.5f
);