Upstream version 9.38.198.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/event_utils.h"
15 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
16 #include "ui/events/x/touch_factory_x11.h"
17
18 namespace {
19
20 // Converts ui::EventType to state for X*Events.
21 unsigned int XEventState(int flags) {
22   return
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);
34 }
35
36 // Converts EventType to XKeyEvent type.
37 int XKeyEventType(ui::EventType type) {
38   switch (type) {
39     case ui::ET_KEY_PRESSED:
40       return KeyPress;
41     case ui::ET_KEY_RELEASED:
42       return KeyRelease;
43     default:
44       return 0;
45   }
46 }
47
48 // Converts EventType to XI2 event type.
49 int XIKeyEventType(ui::EventType type) {
50   switch (type) {
51     case ui::ET_KEY_PRESSED:
52       return XI_KeyPress;
53     case ui::ET_KEY_RELEASED:
54       return XI_KeyRelease;
55     default:
56       return 0;
57   }
58 }
59
60 int XIButtonEventType(ui::EventType type) {
61   switch (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;
68     default:
69       NOTREACHED();
70       return 0;
71   }
72 }
73
74 // Converts Aura event type and flag to X button event.
75 unsigned int XButtonEventButton(ui::EventType type,
76                                 int flags) {
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)
80     return Button4;
81
82   if (flags & ui::EF_LEFT_MOUSE_BUTTON)
83     return Button1;
84   if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
85     return Button2;
86   if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
87     return Button3;
88
89   return 0;
90 }
91
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];
98 }
99
100 XEvent* CreateXInput2Event(int deviceid,
101                            int evtype,
102                            int tracking_id,
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);
122   }
123   return event;
124 }
125
126 }  // namespace
127
128 namespace ui {
129
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);
136     if (xiev) {
137       delete[] xiev->valuators.mask;
138       delete[] xiev->valuators.values;
139       delete[] xiev->buttons.mask;
140       delete xiev;
141     }
142   }
143   delete event;
144 }
145
146 ScopedXI2Event::ScopedXI2Event() {}
147 ScopedXI2Event::~ScopedXI2Event() {}
148
149 void ScopedXI2Event::InitKeyEvent(EventType type,
150                                   KeyboardCode key_code,
151                                   int flags) {
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;
164   event_->xkey.x = 0;
165   event_->xkey.y = 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;
171 }
172
173 void ScopedXI2Event::InitGenericKeyEvent(int deviceid,
174                                          EventType type,
175                                          KeyboardCode key_code,
176                                          int flags) {
177   event_.reset(
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 }
187
188 void ScopedXI2Event::InitGenericButtonEvent(int deviceid,
189                                             EventType type,
190                                             const gfx::Point& location,
191                                             int flags) {
192   event_.reset(CreateXInput2Event(deviceid,
193                                   XIButtonEventType(type), 0, gfx::Point()));
194   XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
195   xievent->mods.effective = XEventState(flags);
196   xievent->detail = XButtonEventButton(type, flags);
197   xievent->event_x = location.x();
198   xievent->event_y = location.y();
199   XISetMask(xievent->buttons.mask, xievent->detail);
200   // Setup an empty valuator list for generic button events.
201   SetUpValuators(std::vector<Valuator>());
202 }
203
204 void ScopedXI2Event::InitGenericMouseWheelEvent(int deviceid,
205                                                 int wheel_delta,
206                                                 int flags) {
207   InitGenericButtonEvent(deviceid, ui::ET_MOUSEWHEEL, gfx::Point(), flags);
208   XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
209   xievent->detail = wheel_delta > 0 ? Button4 : Button5;
210 }
211
212 void ScopedXI2Event::InitScrollEvent(int deviceid,
213                                      int x_offset,
214                                      int y_offset,
215                                      int x_offset_ordinal,
216                                      int y_offset_ordinal,
217                                      int finger_count) {
218   event_.reset(CreateXInput2Event(deviceid, XI_Motion, 0, gfx::Point()));
219
220   Valuator valuators[] = {
221     Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_X, x_offset),
222     Valuator(DeviceDataManagerX11::DT_CMT_SCROLL_Y, y_offset),
223     Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X, x_offset_ordinal),
224     Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y, y_offset_ordinal),
225     Valuator(DeviceDataManagerX11::DT_CMT_FINGER_COUNT, finger_count)
226   };
227   SetUpValuators(
228       std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
229 }
230
231 void ScopedXI2Event::InitFlingScrollEvent(int deviceid,
232                                           int x_velocity,
233                                           int y_velocity,
234                                           int x_velocity_ordinal,
235                                           int y_velocity_ordinal,
236                                           bool is_cancel) {
237   event_.reset(CreateXInput2Event(deviceid, XI_Motion, deviceid, gfx::Point()));
238
239   Valuator valuators[] = {
240     Valuator(DeviceDataManagerX11::DT_CMT_FLING_STATE, is_cancel ? 1 : 0),
241     Valuator(DeviceDataManagerX11::DT_CMT_FLING_Y, y_velocity),
242     Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_Y, y_velocity_ordinal),
243     Valuator(DeviceDataManagerX11::DT_CMT_FLING_X, x_velocity),
244     Valuator(DeviceDataManagerX11::DT_CMT_ORDINAL_X, x_velocity_ordinal)
245   };
246
247   SetUpValuators(
248       std::vector<Valuator>(valuators, valuators + arraysize(valuators)));
249 }
250
251 void ScopedXI2Event::InitTouchEvent(int deviceid,
252                                     int evtype,
253                                     int tracking_id,
254                                     const gfx::Point& location,
255                                     const std::vector<Valuator>& valuators) {
256   event_.reset(CreateXInput2Event(deviceid, evtype, tracking_id, location));
257
258   // If a timestamp was specified, setup the event.
259   for (size_t i = 0; i < valuators.size(); ++i) {
260     if (valuators[i].data_type ==
261         DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP) {
262       SetUpValuators(valuators);
263       return;
264     }
265   }
266
267   // No timestamp was specified. Use |ui::EventTimeForNow()|.
268   std::vector<Valuator> valuators_with_time = valuators;
269   valuators_with_time.push_back(
270       Valuator(DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP,
271                (ui::EventTimeForNow()).InMicroseconds()));
272   SetUpValuators(valuators_with_time);
273 }
274
275 void ScopedXI2Event::SetUpValuators(const std::vector<Valuator>& valuators) {
276   CHECK(event_.get());
277   CHECK_EQ(GenericEvent, event_->type);
278   XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(event_->xcookie.data);
279   InitValuatorsForXIDeviceEvent(xiev);
280   ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
281   for (size_t i = 0; i < valuators.size(); ++i) {
282     manager->SetValuatorDataForTest(xiev, valuators[i].data_type,
283                                     valuators[i].value);
284   }
285 }
286
287 void SetUpTouchPadForTest(unsigned int deviceid) {
288   std::vector<unsigned int> device_list;
289   device_list.push_back(deviceid);
290
291   TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
292   ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
293   manager->SetDeviceListForTest(std::vector<unsigned int>(), device_list);
294 }
295
296 void SetUpTouchDevicesForTest(const std::vector<unsigned int>& devices) {
297   TouchFactory::GetInstance()->SetTouchDeviceForTest(devices);
298   ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
299   manager->SetDeviceListForTest(devices, std::vector<unsigned int>());
300 }
301
302 }  // namespace ui