1 // Copyright 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 "ui/events/test/events_test_utils_x11.h"
7 #include <X11/extensions/XI2.h>
8 #include <X11/keysym.h>
12 #include "base/logging.h"
13 #include "ui/events/devices/x11/touch_factory_x11.h"
14 #include "ui/events/event_constants.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
20 // Converts ui::EventType to state for X*Events.
21 unsigned int XEventState(int flags
) {
23 ((flags
& ui::EF_SHIFT_DOWN
) ? ShiftMask
: 0) |
24 ((flags
& ui::EF_CONTROL_DOWN
) ? ControlMask
: 0) |
25 ((flags
& ui::EF_ALT_DOWN
) ? Mod1Mask
: 0) |
26 ((flags
& ui::EF_CAPS_LOCK_DOWN
) ? LockMask
: 0) |
27 ((flags
& ui::EF_ALTGR_DOWN
) ? Mod5Mask
: 0) |
28 ((flags
& ui::EF_COMMAND_DOWN
) ? Mod4Mask
: 0) |
29 ((flags
& ui::EF_MOD3_DOWN
) ? Mod3Mask
: 0) |
30 ((flags
& ui::EF_LEFT_MOUSE_BUTTON
) ? Button1Mask
: 0) |
31 ((flags
& ui::EF_MIDDLE_MOUSE_BUTTON
) ? Button2Mask
: 0) |
32 ((flags
& ui::EF_RIGHT_MOUSE_BUTTON
) ? Button3Mask
: 0);
35 // Converts EventType to XKeyEvent type.
36 int XKeyEventType(ui::EventType type
) {
38 case ui::ET_KEY_PRESSED
:
40 case ui::ET_KEY_RELEASED
:
47 // Converts EventType to XI2 event type.
48 int XIKeyEventType(ui::EventType type
) {
50 case ui::ET_KEY_PRESSED
:
52 case ui::ET_KEY_RELEASED
:
59 int XIButtonEventType(ui::EventType type
) {
61 case ui::ET_MOUSEWHEEL
:
62 case ui::ET_MOUSE_PRESSED
:
63 // The button release X events for mouse wheels are dropped by Aura.
64 return XI_ButtonPress
;
65 case ui::ET_MOUSE_RELEASED
:
66 return XI_ButtonRelease
;
73 // Converts Aura event type and flag to X button event.
74 unsigned int XButtonEventButton(ui::EventType type
,
76 // Aura events don't keep track of mouse wheel button, so just return
77 // the first mouse wheel button.
78 if (type
== ui::ET_MOUSEWHEEL
)
81 if (flags
& ui::EF_LEFT_MOUSE_BUTTON
)
83 if (flags
& ui::EF_MIDDLE_MOUSE_BUTTON
)
85 if (flags
& ui::EF_RIGHT_MOUSE_BUTTON
)
91 void InitValuatorsForXIDeviceEvent(XIDeviceEvent
* xiev
) {
92 int valuator_count
= ui::DeviceDataManagerX11::DT_LAST_ENTRY
;
93 xiev
->valuators
.mask_len
= (valuator_count
/ 8) + 1;
94 xiev
->valuators
.mask
= new unsigned char[xiev
->valuators
.mask_len
];
95 memset(xiev
->valuators
.mask
, 0, xiev
->valuators
.mask_len
);
96 xiev
->valuators
.values
= new double[valuator_count
];
99 XEvent
* CreateXInput2Event(int deviceid
,
102 const gfx::Point
& location
) {
103 XEvent
* event
= new XEvent
;
104 memset(event
, 0, sizeof(*event
));
105 event
->type
= GenericEvent
;
106 event
->xcookie
.data
= new XIDeviceEvent
;
107 XIDeviceEvent
* xiev
=
108 static_cast<XIDeviceEvent
*>(event
->xcookie
.data
);
109 memset(xiev
, 0, sizeof(XIDeviceEvent
));
110 xiev
->deviceid
= deviceid
;
111 xiev
->sourceid
= deviceid
;
112 xiev
->evtype
= evtype
;
113 xiev
->detail
= tracking_id
;
114 xiev
->event_x
= location
.x();
115 xiev
->event_y
= location
.y();
116 xiev
->event
= DefaultRootWindow(gfx::GetXDisplay());
117 if (evtype
== XI_ButtonPress
|| evtype
== XI_ButtonRelease
) {
118 xiev
->buttons
.mask_len
= 8;
119 xiev
->buttons
.mask
= new unsigned char[xiev
->buttons
.mask_len
];
120 memset(xiev
->buttons
.mask
, 0, xiev
->buttons
.mask_len
);
129 // XInput2 events contain additional data that need to be explicitly freed (see
130 // |CreateXInput2Event()|.
131 void XEventDeleter::operator()(XEvent
* event
) {
132 if (event
->type
== GenericEvent
) {
133 XIDeviceEvent
* xiev
=
134 static_cast<XIDeviceEvent
*>(event
->xcookie
.data
);
136 delete[] xiev
->valuators
.mask
;
137 delete[] xiev
->valuators
.values
;
138 delete[] xiev
->buttons
.mask
;
145 ScopedXI2Event::ScopedXI2Event() {}
146 ScopedXI2Event::~ScopedXI2Event() {}
148 void ScopedXI2Event::InitKeyEvent(EventType type
,
149 KeyboardCode key_code
,
151 XDisplay
* display
= gfx::GetXDisplay();
152 event_
.reset(new XEvent
);
153 memset(event_
.get(), 0, sizeof(XEvent
));
154 event_
->type
= XKeyEventType(type
);
155 CHECK_NE(0, event_
->type
);
156 event_
->xkey
.serial
= 0;
157 event_
->xkey
.send_event
= 0;
158 event_
->xkey
.display
= display
;
159 event_
->xkey
.time
= 0;
160 event_
->xkey
.window
= 0;
161 event_
->xkey
.root
= 0;
162 event_
->xkey
.subwindow
= 0;
165 event_
->xkey
.x_root
= 0;
166 event_
->xkey
.y_root
= 0;
167 event_
->xkey
.state
= XEventState(flags
);
168 event_
->xkey
.keycode
= XKeyCodeForWindowsKeyCode(key_code
, flags
, display
);
169 event_
->xkey
.same_screen
= 1;
172 void ScopedXI2Event::InitGenericKeyEvent(int deviceid
,
175 KeyboardCode key_code
,
178 CreateXInput2Event(deviceid
, XIKeyEventType(type
), 0, gfx::Point()));
179 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
180 CHECK_NE(0, xievent
->evtype
);
181 XDisplay
* display
= gfx::GetXDisplay();
182 event_
->xgeneric
.display
= display
;
183 xievent
->display
= display
;
184 xievent
->mods
.effective
= XEventState(flags
);
185 xievent
->detail
= XKeyCodeForWindowsKeyCode(key_code
, flags
, display
);
186 xievent
->sourceid
= sourceid
;
189 void ScopedXI2Event::InitGenericButtonEvent(int deviceid
,
191 const gfx::Point
& location
,
193 event_
.reset(CreateXInput2Event(deviceid
,
194 XIButtonEventType(type
), 0, gfx::Point()));
195 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
196 xievent
->mods
.effective
= XEventState(flags
);
197 xievent
->detail
= XButtonEventButton(type
, flags
);
198 xievent
->event_x
= location
.x();
199 xievent
->event_y
= location
.y();
200 XISetMask(xievent
->buttons
.mask
, xievent
->detail
);
201 // Setup an empty valuator list for generic button events.
202 SetUpValuators(std::vector
<Valuator
>());
205 void ScopedXI2Event::InitGenericMouseWheelEvent(int deviceid
,
208 InitGenericButtonEvent(deviceid
, ui::ET_MOUSEWHEEL
, gfx::Point(), flags
);
209 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
210 xievent
->detail
= wheel_delta
> 0 ? Button4
: Button5
;
213 void ScopedXI2Event::InitScrollEvent(int deviceid
,
216 int x_offset_ordinal
,
217 int y_offset_ordinal
,
219 event_
.reset(CreateXInput2Event(deviceid
, XI_Motion
, 0, gfx::Point()));
221 Valuator valuators
[] = {
222 Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_X
, x_offset
),
223 Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_Y
, y_offset
),
224 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X
, x_offset_ordinal
),
225 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y
, y_offset_ordinal
),
226 Valuator(DeviceDataManagerX11::DT_CMT_FINGER_COUNT
, finger_count
)
229 std::vector
<Valuator
>(valuators
, valuators
+ arraysize(valuators
)));
232 void ScopedXI2Event::InitFlingScrollEvent(int deviceid
,
235 int x_velocity_ordinal
,
236 int y_velocity_ordinal
,
238 event_
.reset(CreateXInput2Event(deviceid
, XI_Motion
, deviceid
, gfx::Point()));
240 Valuator valuators
[] = {
241 Valuator(DeviceDataManagerX11::DT_CMT_FLING_STATE
, is_cancel
? 1 : 0),
242 Valuator(DeviceDataManagerX11::DT_CMT_FLING_Y
, y_velocity
),
243 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y
, y_velocity_ordinal
),
244 Valuator(DeviceDataManagerX11::DT_CMT_FLING_X
, x_velocity
),
245 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X
, x_velocity_ordinal
)
249 std::vector
<Valuator
>(valuators
, valuators
+ arraysize(valuators
)));
252 void ScopedXI2Event::InitTouchEvent(int deviceid
,
255 const gfx::Point
& location
,
256 const std::vector
<Valuator
>& valuators
) {
257 event_
.reset(CreateXInput2Event(deviceid
, evtype
, tracking_id
, location
));
259 // If a timestamp was specified, setup the event.
260 for (size_t i
= 0; i
< valuators
.size(); ++i
) {
261 if (valuators
[i
].data_type
==
262 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
) {
263 SetUpValuators(valuators
);
268 // No timestamp was specified. Use |ui::EventTimeForNow()|.
269 std::vector
<Valuator
> valuators_with_time
= valuators
;
270 valuators_with_time
.push_back(
271 Valuator(DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
,
272 (ui::EventTimeForNow()).InMicroseconds()));
273 SetUpValuators(valuators_with_time
);
276 void ScopedXI2Event::SetUpValuators(const std::vector
<Valuator
>& valuators
) {
278 CHECK_EQ(GenericEvent
, event_
->type
);
279 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
280 InitValuatorsForXIDeviceEvent(xiev
);
281 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
282 for (size_t i
= 0; i
< valuators
.size(); ++i
) {
283 manager
->SetValuatorDataForTest(xiev
, valuators
[i
].data_type
,
288 void SetUpTouchPadForTest(int deviceid
) {
289 std::vector
<int> device_list
;
290 device_list
.push_back(deviceid
);
292 TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list
);
293 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
294 manager
->SetDeviceListForTest(std::vector
<int>(), device_list
,
298 void SetUpTouchDevicesForTest(const std::vector
<int>& devices
) {
299 TouchFactory::GetInstance()->SetTouchDeviceForTest(devices
);
300 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
301 manager
->SetDeviceListForTest(devices
, std::vector
<int>(),
305 void SetUpPointerDevicesForTest(const std::vector
<int>& devices
) {
306 TouchFactory::GetInstance()->SetPointerDeviceForTest(devices
);
307 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
308 manager
->SetDeviceListForTest(std::vector
<int>(), std::vector
<int>(),