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/event_constants.h"
14 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
15 #include "ui/events/x/touch_factory_x11.h"
19 // Converts ui::EventType to state for X*Events.
20 unsigned int XEventState(int flags) {
22 ((flags & ui::EF_SHIFT_DOWN) ? ShiftMask : 0) |
23 ((flags & ui::EF_CONTROL_DOWN) ? ControlMask : 0) |
24 ((flags & ui::EF_ALT_DOWN) ? Mod1Mask : 0) |
25 ((flags & ui::EF_CAPS_LOCK_DOWN) ? LockMask : 0) |
26 ((flags & ui::EF_LEFT_MOUSE_BUTTON) ? Button1Mask: 0) |
27 ((flags & ui::EF_MIDDLE_MOUSE_BUTTON) ? Button2Mask: 0) |
28 ((flags & ui::EF_RIGHT_MOUSE_BUTTON) ? Button3Mask: 0);
31 // Converts EventType to XKeyEvent type.
32 int XKeyEventType(ui::EventType type) {
34 case ui::ET_KEY_PRESSED:
36 case ui::ET_KEY_RELEASED:
43 int XIButtonEventType(ui::EventType type) {
45 case ui::ET_MOUSEWHEEL:
46 case ui::ET_MOUSE_PRESSED:
47 // The button release X events for mouse wheels are dropped by Aura.
48 return XI_ButtonPress;
49 case ui::ET_MOUSE_RELEASED:
50 return XI_ButtonRelease;
57 // Converts EventType to XButtonEvent type.
58 int XButtonEventType(ui::EventType type) {
60 case ui::ET_MOUSEWHEEL:
61 case ui::ET_MOUSE_PRESSED:
62 // The button release X events for mouse wheels are dropped by Aura.
64 case ui::ET_MOUSE_RELEASED:
71 // Converts KeyboardCode to XKeyEvent keycode.
72 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code,
75 const int keysym = XKeysymForWindowsKeyCode(key_code,
76 flags & ui::EF_SHIFT_DOWN);
77 // Tests assume the keycode for XK_less is equal to the one of XK_comma,
78 // but XKeysymToKeycode returns 94 for XK_less while it returns 59 for
79 // XK_comma. Here we convert the value for XK_less to the value for XK_comma.
80 return (keysym == XK_less) ? 59 : XKeysymToKeycode(display, keysym);
83 // Converts Aura event type and flag to X button event.
84 unsigned int XButtonEventButton(ui::EventType type,
86 // Aura events don't keep track of mouse wheel button, so just return
87 // the first mouse wheel button.
88 if (type == ui::ET_MOUSEWHEEL)
91 if (flags & ui::EF_LEFT_MOUSE_BUTTON)
93 if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
95 if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
101 void InitValuatorsForXIDeviceEvent(XIDeviceEvent* xiev) {
102 int valuator_count = ui::DeviceDataManager::DT_LAST_ENTRY;
103 xiev->valuators.mask_len = (valuator_count / 8) + 1;
104 xiev->valuators.mask = new unsigned char[xiev->valuators.mask_len];
105 memset(xiev->valuators.mask, 0, xiev->valuators.mask_len);
106 xiev->valuators.values = new double[valuator_count];
109 XEvent* CreateXInput2Event(int deviceid,
112 const gfx::Point& location) {
113 XEvent* event = new XEvent;
114 memset(event, 0, sizeof(*event));
115 event->type = GenericEvent;
116 event->xcookie.data = new XIDeviceEvent;
117 XIDeviceEvent* xiev =
118 static_cast<XIDeviceEvent*>(event->xcookie.data);
119 memset(xiev, 0, sizeof(XIDeviceEvent));
120 xiev->deviceid = deviceid;
121 xiev->sourceid = deviceid;
122 xiev->evtype = evtype;
123 xiev->detail = tracking_id;
124 xiev->event_x = location.x();
125 xiev->event_y = location.y();
126 if (evtype == XI_ButtonPress || evtype == XI_ButtonRelease) {
127 xiev->buttons.mask_len = 8;
128 xiev->buttons.mask = new unsigned char[xiev->buttons.mask_len];
129 memset(xiev->buttons.mask, 0, xiev->buttons.mask_len);
138 // XInput2 events contain additional data that need to be explicitly freed (see
139 // |CreateXInput2Event()|.
140 void XEventDeleter::operator()(XEvent* event) {
141 if (event->type == GenericEvent) {
142 XIDeviceEvent* xiev =
143 static_cast<XIDeviceEvent*>(event->xcookie.data);
145 delete[] xiev->valuators.mask;
146 delete[] xiev->valuators.values;
147 delete[] xiev->buttons.mask;
154 ScopedXI2Event::ScopedXI2Event() {}
155 ScopedXI2Event::~ScopedXI2Event() {}
157 void ScopedXI2Event::InitKeyEvent(EventType type,
158 KeyboardCode key_code,
160 XDisplay* display = gfx::GetXDisplay();
161 event_.reset(new XEvent);
162 memset(event_.get(), 0, sizeof(XEvent));
163 event_->type = XKeyEventType(type);
164 CHECK_NE(0, event_->type);
165 event_->xkey.serial = 0;
166 event_->xkey.send_event = 0;
167 event_->xkey.display = display;
168 event_->xkey.time = 0;
169 event_->xkey.window = 0;
170 event_->xkey.root = 0;
171 event_->xkey.subwindow = 0;
174 event_->xkey.x_root = 0;
175 event_->xkey.y_root = 0;
176 event_->xkey.state = XEventState(flags);
177 event_->xkey.keycode = XKeyEventKeyCode(key_code, flags, display);
178 event_->xkey.same_screen = 1;
181 void ScopedXI2Event::InitGenericButtonEvent(int deviceid,
184 event_.reset(CreateXInput2Event(deviceid,
185 XIButtonEventType(type), 0, gfx::Point()));
186 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
187 xievent->mods.effective = XEventState(flags);
188 xievent->detail = XButtonEventButton(type, flags);
189 XISetMask(xievent->buttons.mask, xievent->detail);
192 void ScopedXI2Event::InitButtonEvent(EventType type,
194 event_.reset(new XEvent);
195 memset(event_.get(), 0, sizeof(XEvent));
196 event_->type = XButtonEventType(type);
197 CHECK_NE(0, event_->type);
198 event_->xbutton.serial = 0;
199 event_->xbutton.send_event = 0;
200 event_->xbutton.display = gfx::GetXDisplay();
201 event_->xbutton.time = 0;
202 event_->xbutton.window = 0;
203 event_->xbutton.root = 0;
204 event_->xbutton.subwindow = 0;
205 event_->xbutton.x = 0;
206 event_->xbutton.y = 0;
207 event_->xbutton.x_root = 0;
208 event_->xbutton.y_root = 0;
209 event_->xbutton.state = XEventState(flags);
210 event_->xbutton.button = XButtonEventButton(type, flags);
211 event_->xbutton.same_screen = 1;
214 void ScopedXI2Event::InitMouseWheelEvent(int wheel_delta,
216 InitButtonEvent(ui::ET_MOUSEWHEEL, flags);
217 // MouseWheelEvents are not taking horizontal scrolls into account
219 event_->xbutton.button = wheel_delta > 0 ? Button4 : Button5;
222 void ScopedXI2Event::InitScrollEvent(int deviceid,
225 int x_offset_ordinal,
226 int y_offset_ordinal,
228 event_.reset(CreateXInput2Event(deviceid, XI_Motion, 0, gfx::Point()));
230 Valuator valuators[] = {
231 Valuator(DeviceDataManager::DT_CMT_SCROLL_X, x_offset),
232 Valuator(DeviceDataManager::DT_CMT_SCROLL_Y, y_offset),
233 Valuator(DeviceDataManager::DT_CMT_ORDINAL_X, x_offset_ordinal),
234 Valuator(DeviceDataManager::DT_CMT_ORDINAL_Y, y_offset_ordinal),
235 Valuator(DeviceDataManager::DT_CMT_FINGER_COUNT, finger_count)
238 std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
241 void ScopedXI2Event::InitFlingScrollEvent(int deviceid,
244 int x_velocity_ordinal,
245 int y_velocity_ordinal,
247 event_.reset(CreateXInput2Event(deviceid, XI_Motion, deviceid, gfx::Point()));
249 Valuator valuators[] = {
250 Valuator(DeviceDataManager::DT_CMT_FLING_STATE, is_cancel ? 1 : 0),
251 Valuator(DeviceDataManager::DT_CMT_FLING_Y, y_velocity),
252 Valuator(DeviceDataManager::DT_CMT_ORDINAL_Y, y_velocity_ordinal),
253 Valuator(DeviceDataManager::DT_CMT_FLING_X, x_velocity),
254 Valuator(DeviceDataManager::DT_CMT_ORDINAL_X, x_velocity_ordinal)
258 std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
261 void ScopedXI2Event::InitTouchEvent(int deviceid,
264 const gfx::Point& location,
265 const std::vector<Valuator>& valuators) {
266 event_.reset(CreateXInput2Event(deviceid, evtype, tracking_id, location));
267 SetUpValuators(valuators);
270 void ScopedXI2Event::SetUpValuators(const std::vector<Valuator>& valuators) {
272 CHECK_EQ(GenericEvent, event_->type);
273 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(event_->xcookie.data);
274 InitValuatorsForXIDeviceEvent(xiev);
275 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
276 for (size_t i = 0; i < valuators.size(); ++i) {
277 manager->SetValuatorDataForTest(xiev, valuators[i].data_type,
282 void SetUpScrollDeviceForTest(unsigned int deviceid) {
283 std::vector<unsigned int> device_list;
284 device_list.push_back(deviceid);
286 TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
287 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
288 manager->SetDeviceListForTest(std::vector<unsigned int>(), device_list);
291 void SetUpTouchDevicesForTest(const std::vector<unsigned int>& devices) {
292 TouchFactory::GetInstance()->SetTouchDeviceForTest(devices);
293 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
294 manager->SetDeviceListForTest(devices, std::vector<unsigned int>());