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_NUMPAD_KEY
) ? Mod2Mask
: 0) |
31 ((flags
& ui::EF_LEFT_MOUSE_BUTTON
) ? Button1Mask
: 0) |
32 ((flags
& ui::EF_MIDDLE_MOUSE_BUTTON
) ? Button2Mask
: 0) |
33 ((flags
& ui::EF_RIGHT_MOUSE_BUTTON
) ? Button3Mask
: 0);
36 // Converts EventType to XKeyEvent type.
37 int XKeyEventType(ui::EventType type
) {
39 case ui::ET_KEY_PRESSED
:
41 case ui::ET_KEY_RELEASED
:
48 // Converts EventType to XI2 event type.
49 int XIKeyEventType(ui::EventType type
) {
51 case ui::ET_KEY_PRESSED
:
53 case ui::ET_KEY_RELEASED
:
60 int XIButtonEventType(ui::EventType type
) {
62 case ui::ET_MOUSEWHEEL
:
63 case ui::ET_MOUSE_PRESSED
:
64 // The button release X events for mouse wheels are dropped by Aura.
65 return XI_ButtonPress
;
66 case ui::ET_MOUSE_RELEASED
:
67 return XI_ButtonRelease
;
74 // Converts Aura event type and flag to X button event.
75 unsigned int XButtonEventButton(ui::EventType type
,
77 // Aura events don't keep track of mouse wheel button, so just return
78 // the first mouse wheel button.
79 if (type
== ui::ET_MOUSEWHEEL
)
82 if (flags
& ui::EF_LEFT_MOUSE_BUTTON
)
84 if (flags
& ui::EF_MIDDLE_MOUSE_BUTTON
)
86 if (flags
& ui::EF_RIGHT_MOUSE_BUTTON
)
92 void InitValuatorsForXIDeviceEvent(XIDeviceEvent
* xiev
) {
93 int valuator_count
= ui::DeviceDataManagerX11::DT_LAST_ENTRY
;
94 xiev
->valuators
.mask_len
= (valuator_count
/ 8) + 1;
95 xiev
->valuators
.mask
= new unsigned char[xiev
->valuators
.mask_len
];
96 memset(xiev
->valuators
.mask
, 0, xiev
->valuators
.mask_len
);
97 xiev
->valuators
.values
= new double[valuator_count
];
100 XEvent
* CreateXInput2Event(int deviceid
,
103 const gfx::Point
& location
) {
104 XEvent
* event
= new XEvent
;
105 memset(event
, 0, sizeof(*event
));
106 event
->type
= GenericEvent
;
107 event
->xcookie
.data
= new XIDeviceEvent
;
108 XIDeviceEvent
* xiev
=
109 static_cast<XIDeviceEvent
*>(event
->xcookie
.data
);
110 memset(xiev
, 0, sizeof(XIDeviceEvent
));
111 xiev
->deviceid
= deviceid
;
112 xiev
->sourceid
= deviceid
;
113 xiev
->evtype
= evtype
;
114 xiev
->detail
= tracking_id
;
115 xiev
->event_x
= location
.x();
116 xiev
->event_y
= location
.y();
117 xiev
->event
= DefaultRootWindow(gfx::GetXDisplay());
118 if (evtype
== XI_ButtonPress
|| evtype
== XI_ButtonRelease
) {
119 xiev
->buttons
.mask_len
= 8;
120 xiev
->buttons
.mask
= new unsigned char[xiev
->buttons
.mask_len
];
121 memset(xiev
->buttons
.mask
, 0, xiev
->buttons
.mask_len
);
130 // XInput2 events contain additional data that need to be explicitly freed (see
131 // |CreateXInput2Event()|.
132 void XEventDeleter::operator()(XEvent
* event
) {
133 if (event
->type
== GenericEvent
) {
134 XIDeviceEvent
* xiev
=
135 static_cast<XIDeviceEvent
*>(event
->xcookie
.data
);
137 delete[] xiev
->valuators
.mask
;
138 delete[] xiev
->valuators
.values
;
139 delete[] xiev
->buttons
.mask
;
146 ScopedXI2Event::ScopedXI2Event() {}
147 ScopedXI2Event::~ScopedXI2Event() {}
149 void ScopedXI2Event::InitKeyEvent(EventType type
,
150 KeyboardCode key_code
,
152 XDisplay
* display
= gfx::GetXDisplay();
153 event_
.reset(new XEvent
);
154 memset(event_
.get(), 0, sizeof(XEvent
));
155 event_
->type
= XKeyEventType(type
);
156 CHECK_NE(0, event_
->type
);
157 event_
->xkey
.serial
= 0;
158 event_
->xkey
.send_event
= 0;
159 event_
->xkey
.display
= display
;
160 event_
->xkey
.time
= 0;
161 event_
->xkey
.window
= 0;
162 event_
->xkey
.root
= 0;
163 event_
->xkey
.subwindow
= 0;
166 event_
->xkey
.x_root
= 0;
167 event_
->xkey
.y_root
= 0;
168 event_
->xkey
.state
= XEventState(flags
);
169 event_
->xkey
.keycode
= XKeyCodeForWindowsKeyCode(key_code
, flags
, display
);
170 event_
->xkey
.same_screen
= 1;
173 void ScopedXI2Event::InitGenericKeyEvent(int deviceid
,
176 KeyboardCode key_code
,
179 CreateXInput2Event(deviceid
, XIKeyEventType(type
), 0, gfx::Point()));
180 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
181 CHECK_NE(0, xievent
->evtype
);
182 XDisplay
* display
= gfx::GetXDisplay();
183 event_
->xgeneric
.display
= display
;
184 xievent
->display
= display
;
185 xievent
->mods
.effective
= XEventState(flags
);
186 xievent
->detail
= XKeyCodeForWindowsKeyCode(key_code
, flags
, display
);
187 xievent
->sourceid
= sourceid
;
190 void ScopedXI2Event::InitGenericButtonEvent(int deviceid
,
192 const gfx::Point
& location
,
194 event_
.reset(CreateXInput2Event(deviceid
,
195 XIButtonEventType(type
), 0, gfx::Point()));
196 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
197 xievent
->mods
.effective
= XEventState(flags
);
198 xievent
->detail
= XButtonEventButton(type
, flags
);
199 xievent
->event_x
= location
.x();
200 xievent
->event_y
= location
.y();
201 XISetMask(xievent
->buttons
.mask
, xievent
->detail
);
202 // Setup an empty valuator list for generic button events.
203 SetUpValuators(std::vector
<Valuator
>());
206 void ScopedXI2Event::InitGenericMouseWheelEvent(int deviceid
,
209 InitGenericButtonEvent(deviceid
, ui::ET_MOUSEWHEEL
, gfx::Point(), flags
);
210 XIDeviceEvent
* xievent
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
211 xievent
->detail
= wheel_delta
> 0 ? Button4
: Button5
;
214 void ScopedXI2Event::InitScrollEvent(int deviceid
,
217 int x_offset_ordinal
,
218 int y_offset_ordinal
,
220 event_
.reset(CreateXInput2Event(deviceid
, XI_Motion
, 0, gfx::Point()));
222 Valuator valuators
[] = {
223 Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_X
, x_offset
),
224 Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_Y
, y_offset
),
225 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X
, x_offset_ordinal
),
226 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y
, y_offset_ordinal
),
227 Valuator(DeviceDataManagerX11::DT_CMT_FINGER_COUNT
, finger_count
)
230 std::vector
<Valuator
>(valuators
, valuators
+ arraysize(valuators
)));
233 void ScopedXI2Event::InitFlingScrollEvent(int deviceid
,
236 int x_velocity_ordinal
,
237 int y_velocity_ordinal
,
239 event_
.reset(CreateXInput2Event(deviceid
, XI_Motion
, deviceid
, gfx::Point()));
241 Valuator valuators
[] = {
242 Valuator(DeviceDataManagerX11::DT_CMT_FLING_STATE
, is_cancel
? 1 : 0),
243 Valuator(DeviceDataManagerX11::DT_CMT_FLING_Y
, y_velocity
),
244 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y
, y_velocity_ordinal
),
245 Valuator(DeviceDataManagerX11::DT_CMT_FLING_X
, x_velocity
),
246 Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X
, x_velocity_ordinal
)
250 std::vector
<Valuator
>(valuators
, valuators
+ arraysize(valuators
)));
253 void ScopedXI2Event::InitTouchEvent(int deviceid
,
256 const gfx::Point
& location
,
257 const std::vector
<Valuator
>& valuators
) {
258 event_
.reset(CreateXInput2Event(deviceid
, evtype
, tracking_id
, location
));
260 // If a timestamp was specified, setup the event.
261 for (size_t i
= 0; i
< valuators
.size(); ++i
) {
262 if (valuators
[i
].data_type
==
263 DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
) {
264 SetUpValuators(valuators
);
269 // No timestamp was specified. Use |ui::EventTimeForNow()|.
270 std::vector
<Valuator
> valuators_with_time
= valuators
;
271 valuators_with_time
.push_back(
272 Valuator(DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
,
273 (ui::EventTimeForNow()).InMicroseconds()));
274 SetUpValuators(valuators_with_time
);
277 void ScopedXI2Event::SetUpValuators(const std::vector
<Valuator
>& valuators
) {
279 CHECK_EQ(GenericEvent
, event_
->type
);
280 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(event_
->xcookie
.data
);
281 InitValuatorsForXIDeviceEvent(xiev
);
282 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
283 for (size_t i
= 0; i
< valuators
.size(); ++i
) {
284 manager
->SetValuatorDataForTest(xiev
, valuators
[i
].data_type
,
289 void SetUpTouchPadForTest(unsigned int deviceid
) {
290 std::vector
<unsigned int> device_list
;
291 device_list
.push_back(deviceid
);
293 TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list
);
294 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
295 manager
->SetDeviceListForTest(std::vector
<unsigned int>(), device_list
);
298 void SetUpTouchDevicesForTest(const std::vector
<unsigned int>& devices
) {
299 TouchFactory::GetInstance()->SetTouchDeviceForTest(devices
);
300 ui::DeviceDataManagerX11
* manager
= ui::DeviceDataManagerX11::GetInstance();
301 manager
->SetDeviceListForTest(devices
, std::vector
<unsigned int>());