Get foreground tab on Android
[chromium-blink-merge.git] / ui / events / x / events_x_utils.cc
blobea481039880255f70700b199b12505b472b5c060
1 // Copyright (c) 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/x/events_x_utils.h"
7 #include <X11/extensions/XI2.h>
8 #include <X11/keysym.h>
9 #include <X11/X.h>
10 #include <X11/Xlib.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"
17 namespace {
19 const int kScrollValuatorNum = 5;
20 const int kScrollValuatorMap[kScrollValuatorNum][4] = {
21 // { valuator_index, valuator_type, min_val, max_val }
22 { 0, ui::DeviceDataManager::DT_CMT_SCROLL_X, -100, 100 },
23 { 1, ui::DeviceDataManager::DT_CMT_SCROLL_Y, -100, 100 },
24 { 2, ui::DeviceDataManager::DT_CMT_ORDINAL_X, -100, 100 },
25 { 3, ui::DeviceDataManager::DT_CMT_ORDINAL_Y, -100, 100 },
26 { 4, ui::DeviceDataManager::DT_CMT_FINGER_COUNT, 0, 3},
29 #if defined(USE_XI2_MT)
30 const int kTouchValuatorNum = 3;
31 const int kTouchValuatorMap[kTouchValuatorNum][4] = {
32 // { valuator_index, valuator_type, min_val, max_val }
33 { 0, ui::DeviceDataManager::DT_TOUCH_MAJOR, 0, 1000},
34 { 1, ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0, 1},
35 { 2, ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0, 1000},
37 #endif
39 // Converts ui::EventType to state for X*Events.
40 unsigned int XEventState(int flags) {
41 return
42 ((flags & ui::EF_SHIFT_DOWN) ? ShiftMask : 0) |
43 ((flags & ui::EF_CONTROL_DOWN) ? ControlMask : 0) |
44 ((flags & ui::EF_ALT_DOWN) ? Mod1Mask : 0) |
45 ((flags & ui::EF_CAPS_LOCK_DOWN) ? LockMask : 0) |
46 ((flags & ui::EF_LEFT_MOUSE_BUTTON) ? Button1Mask: 0) |
47 ((flags & ui::EF_MIDDLE_MOUSE_BUTTON) ? Button2Mask: 0) |
48 ((flags & ui::EF_RIGHT_MOUSE_BUTTON) ? Button3Mask: 0);
51 // Converts EventType to XKeyEvent type.
52 int XKeyEventType(ui::EventType type) {
53 switch (type) {
54 case ui::ET_KEY_PRESSED:
55 return KeyPress;
56 case ui::ET_KEY_RELEASED:
57 return KeyRelease;
58 default:
59 return 0;
63 // Converts EventType to XButtonEvent type.
64 int XButtonEventType(ui::EventType type) {
65 switch (type) {
66 case ui::ET_MOUSEWHEEL:
67 case ui::ET_MOUSE_PRESSED:
68 // The button release X events for mouse wheels are dropped by Aura.
69 return ButtonPress;
70 case ui::ET_MOUSE_RELEASED:
71 return ButtonRelease;
72 default:
73 return 0;
77 // Converts KeyboardCode to XKeyEvent keycode.
78 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code,
79 int flags,
80 XDisplay* display) {
81 const int keysym = XKeysymForWindowsKeyCode(key_code,
82 flags & ui::EF_SHIFT_DOWN);
83 // Tests assume the keycode for XK_less is equal to the one of XK_comma,
84 // but XKeysymToKeycode returns 94 for XK_less while it returns 59 for
85 // XK_comma. Here we convert the value for XK_less to the value for XK_comma.
86 return (keysym == XK_less) ? 59 : XKeysymToKeycode(display, keysym);
89 // Converts Aura event type and flag to X button event.
90 unsigned int XButtonEventButton(ui::EventType type,
91 int flags) {
92 // Aura events don't keep track of mouse wheel button, so just return
93 // the first mouse wheel button.
94 if (type == ui::ET_MOUSEWHEEL)
95 return Button4;
97 switch (flags) {
98 case ui::EF_LEFT_MOUSE_BUTTON:
99 return Button1;
100 case ui::EF_MIDDLE_MOUSE_BUTTON:
101 return Button2;
102 case ui::EF_RIGHT_MOUSE_BUTTON:
103 return Button3;
106 return 0;
109 void InitValuatorsForXIDeviceEvent(XIDeviceEvent* xiev, int valuator_count) {
110 xiev->valuators.mask_len = (valuator_count / 8) + 1;
111 xiev->valuators.mask = new unsigned char[xiev->valuators.mask_len];
112 memset(xiev->valuators.mask, 0, xiev->valuators.mask_len);
113 xiev->valuators.values = new double[valuator_count];
116 XEvent* CreateXInput2Event(int deviceid,
117 int evtype,
118 int tracking_id,
119 const gfx::Point& location) {
120 XEvent* event = new XEvent;
121 memset(event, 0, sizeof(*event));
122 event->type = GenericEvent;
123 event->xcookie.data = new XIDeviceEvent;
124 XIDeviceEvent* xiev =
125 static_cast<XIDeviceEvent*>(event->xcookie.data);
126 memset(xiev, 0, sizeof(XIDeviceEvent));
127 xiev->deviceid = deviceid;
128 xiev->sourceid = deviceid;
129 xiev->evtype = evtype;
130 xiev->detail = tracking_id;
131 xiev->event_x = location.x();
132 xiev->event_y = location.y();
134 return event;
137 } // namespace
139 namespace ui {
141 void InitXKeyEventForTesting(EventType type,
142 KeyboardCode key_code,
143 int flags,
144 XEvent* event) {
145 CHECK(event);
146 XDisplay* display = gfx::GetXDisplay();
147 XKeyEvent key_event;
148 key_event.type = XKeyEventType(type);
149 CHECK_NE(0, key_event.type);
150 key_event.serial = 0;
151 key_event.send_event = 0;
152 key_event.display = display;
153 key_event.time = 0;
154 key_event.window = 0;
155 key_event.root = 0;
156 key_event.subwindow = 0;
157 key_event.x = 0;
158 key_event.y = 0;
159 key_event.x_root = 0;
160 key_event.y_root = 0;
161 key_event.state = XEventState(flags);
162 key_event.keycode = XKeyEventKeyCode(key_code, flags, display);
163 key_event.same_screen = 1;
164 event->type = key_event.type;
165 event->xkey = key_event;
168 void InitXButtonEventForTesting(EventType type,
169 int flags,
170 XEvent* event) {
171 CHECK(event);
172 XDisplay* display = gfx::GetXDisplay();
173 XButtonEvent button_event;
174 button_event.type = XButtonEventType(type);
175 CHECK_NE(0, button_event.type);
176 button_event.serial = 0;
177 button_event.send_event = 0;
178 button_event.display = display;
179 button_event.time = 0;
180 button_event.window = 0;
181 button_event.root = 0;
182 button_event.subwindow = 0;
183 button_event.x = 0;
184 button_event.y = 0;
185 button_event.x_root = 0;
186 button_event.y_root = 0;
187 button_event.state = XEventState(flags);
188 button_event.button = XButtonEventButton(type, flags);
189 button_event.same_screen = 1;
190 event->type = button_event.type;
191 event->xbutton = button_event;
194 EVENTS_EXPORT void InitXMouseWheelEventForTesting(int wheel_delta,
195 int flags,
196 XEvent* event) {
197 InitXButtonEventForTesting(ui::ET_MOUSEWHEEL, flags, event);
198 // MouseWheelEvents are not taking horizontal scrolls into account
199 // at the moment.
200 event->xbutton.button = wheel_delta > 0 ? Button4 : Button5;
203 ScopedXI2Event::ScopedXI2Event(XEvent* event) : event_(event) {
206 ScopedXI2Event::~ScopedXI2Event() {
207 XIDeviceEvent* xiev =
208 static_cast<XIDeviceEvent*>(event_->xcookie.data);
209 if (xiev) {
210 delete[] xiev->valuators.mask;
211 delete[] xiev->valuators.values;
212 delete xiev;
216 EVENTS_EXPORT XEvent* CreateScrollEventForTest(
217 int deviceid,
218 int x_offset,
219 int y_offset,
220 int x_offset_ordinal,
221 int y_offset_ordinal,
222 int finger_count) {
223 XEvent* event = CreateXInput2Event(
224 deviceid, XI_Motion, deviceid, gfx::Point(0, 0));
226 int valuator_data[kScrollValuatorNum] =
227 { x_offset, y_offset, x_offset_ordinal, y_offset_ordinal, finger_count };
228 XIDeviceEvent* xiev =
229 static_cast<XIDeviceEvent*>(event->xcookie.data);
230 InitValuatorsForXIDeviceEvent(xiev, kScrollValuatorNum);
231 for(int i = 0; i < kScrollValuatorNum; i++) {
232 XISetMask(xiev->valuators.mask, i);
233 xiev->valuators.values[i] = valuator_data[i];
236 return event;
239 EVENTS_EXPORT void SetUpScrollDeviceForTest(unsigned int deviceid) {
240 std::vector<unsigned int> device_list;
241 device_list.push_back(deviceid);
243 TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
244 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
245 manager->SetDeviceListForTest(device_list, device_list, device_list);
247 for (int i = 0; i < kScrollValuatorNum; i++) {
248 manager->SetDeviceValuatorForTest(
249 deviceid,
250 kScrollValuatorMap[i][0],
251 static_cast<DeviceDataManager::DataType>(kScrollValuatorMap[i][1]),
252 kScrollValuatorMap[i][2],
253 kScrollValuatorMap[i][3]);
257 #if defined(USE_XI2_MT)
259 XEvent* CreateTouchEventForTest(int deviceid,
260 int evtype,
261 int tracking_id,
262 const gfx::Point& location,
263 const std::vector<Valuator>& valuators) {
264 XEvent* event = CreateXInput2Event(
265 deviceid, evtype, tracking_id, location);
267 XIDeviceEvent* xiev =
268 static_cast<XIDeviceEvent*>(event->xcookie.data);
269 InitValuatorsForXIDeviceEvent(xiev, valuators.size());
270 int val_count = 0;
271 for (int i = 0; i < kTouchValuatorNum; i++) {
272 for(size_t j = 0; j < valuators.size(); j++) {
273 if (valuators[j].data_type == kTouchValuatorMap[i][1]) {
274 XISetMask(xiev->valuators.mask, kTouchValuatorMap[i][0]);
275 xiev->valuators.values[val_count++] = valuators[j].value;
280 return event;
283 void SetupTouchDevicesForTest(const std::vector<unsigned int>& devices) {
284 std::vector<unsigned int> empty_list;
285 TouchFactory::GetInstance()->SetTouchDeviceForTest(devices);
286 ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
287 manager->SetDeviceListForTest(devices, empty_list, empty_list);
288 for (size_t i = 0; i < devices.size(); i++) {
289 for (int j = 0; j < kTouchValuatorNum; j++) {
290 manager->SetDeviceValuatorForTest(
291 devices[i],
292 kTouchValuatorMap[j][0],
293 static_cast<DeviceDataManager::DataType>(kTouchValuatorMap[j][1]),
294 kTouchValuatorMap[j][2],
295 kTouchValuatorMap[j][3]);
300 #endif // defined(USE_XI2_MT)
302 } // namespace ui