Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / events / test / events_test_utils_x11.cc
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.
4
5 #include "ui/events/test/events_test_utils_x11.h"
6
7 #include <X11/extensions/XI2.h>
8 #include <X11/keysym.h>
9 #include <X11/X.h>
10 #include <X11/Xlib.h>
11
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"
16
17 namespace {
18
19 // Converts ui::EventType to state for X*Events.
20 unsigned int XEventState(int flags) {
21   return
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);
29 }
30
31 // Converts EventType to XKeyEvent type.
32 int XKeyEventType(ui::EventType type) {
33   switch (type) {
34     case ui::ET_KEY_PRESSED:
35       return KeyPress;
36     case ui::ET_KEY_RELEASED:
37       return KeyRelease;
38     default:
39       return 0;
40   }
41 }
42
43 int XIButtonEventType(ui::EventType type) {
44   switch (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;
51     default:
52       NOTREACHED();
53       return 0;
54   }
55 }
56
57 // Converts EventType to XButtonEvent type.
58 int XButtonEventType(ui::EventType type) {
59   switch (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.
63       return ButtonPress;
64     case ui::ET_MOUSE_RELEASED:
65       return ButtonRelease;
66     default:
67       return 0;
68   }
69 }
70
71 // Converts KeyboardCode to XKeyEvent keycode.
72 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code,
73                               int flags,
74                               XDisplay* display) {
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);
81 }
82
83 // Converts Aura event type and flag to X button event.
84 unsigned int XButtonEventButton(ui::EventType type,
85                                 int flags) {
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)
89     return Button4;
90
91   if (flags & ui::EF_LEFT_MOUSE_BUTTON)
92     return Button1;
93   if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
94     return Button2;
95   if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
96     return Button3;
97
98   return 0;
99 }
100
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];
107 }
108
109 XEvent* CreateXInput2Event(int deviceid,
110                            int evtype,
111                            int tracking_id,
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);
130   }
131   return event;
132 }
133
134 }  // namespace
135
136 namespace ui {
137
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);
144     if (xiev) {
145       delete[] xiev->valuators.mask;
146       delete[] xiev->valuators.values;
147       delete[] xiev->buttons.mask;
148       delete xiev;
149     }
150   }
151   delete event;
152 }
153
154 ScopedXI2Event::ScopedXI2Event() {}
155 ScopedXI2Event::~ScopedXI2Event() {}
156
157 void ScopedXI2Event::InitKeyEvent(EventType type,
158                                   KeyboardCode key_code,
159                                   int flags) {
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;
172   event_->xkey.x = 0;
173   event_->xkey.y = 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;
179 }
180
181 void ScopedXI2Event::InitGenericButtonEvent(int deviceid,
182                                             EventType type,
183                                             int flags) {
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);
190 }
191
192 void ScopedXI2Event::InitButtonEvent(EventType type,
193                                      int flags) {
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;
212 }
213
214 void ScopedXI2Event::InitMouseWheelEvent(int wheel_delta,
215                                          int flags) {
216   InitButtonEvent(ui::ET_MOUSEWHEEL, flags);
217   // MouseWheelEvents are not taking horizontal scrolls into account
218   // at the moment.
219   event_->xbutton.button = wheel_delta > 0 ? Button4 : Button5;
220 }
221
222 void ScopedXI2Event::InitScrollEvent(int deviceid,
223                                      int x_offset,
224                                      int y_offset,
225                                      int x_offset_ordinal,
226                                      int y_offset_ordinal,
227                                      int finger_count) {
228   event_.reset(CreateXInput2Event(deviceid, XI_Motion, 0, gfx::Point()));
229
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)
236   };
237   SetUpValuators(
238       std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
239 }
240
241 void ScopedXI2Event::InitFlingScrollEvent(int deviceid,
242                                           int x_velocity,
243                                           int y_velocity,
244                                           int x_velocity_ordinal,
245                                           int y_velocity_ordinal,
246                                           bool is_cancel) {
247   event_.reset(CreateXInput2Event(deviceid, XI_Motion, deviceid, gfx::Point()));
248
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)
255   };
256
257   SetUpValuators(
258       std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
259 }
260
261 void ScopedXI2Event::InitTouchEvent(int deviceid,
262                                     int evtype,
263                                     int tracking_id,
264                                     const gfx::Point& location,
265                                     const std::vector<Valuator>& valuators) {
266   event_.reset(CreateXInput2Event(deviceid, evtype, tracking_id, location));
267   SetUpValuators(valuators);
268 }
269
270 void ScopedXI2Event::SetUpValuators(const std::vector<Valuator>& valuators) {
271   CHECK(event_.get());
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,
278                                     valuators[i].value);
279   }
280 }
281
282 void SetUpScrollDeviceForTest(unsigned int deviceid) {
283   std::vector<unsigned int> device_list;
284   device_list.push_back(deviceid);
285
286   TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
287   ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
288   manager->SetDeviceListForTest(std::vector<unsigned int>(), device_list);
289 }
290
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>());
295 }
296
297 }  // namespace ui