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>
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 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},
39 // Converts ui::EventType to state for X*Events.
40 unsigned int XEventState(int flags
) {
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
) {
54 case ui::ET_KEY_PRESSED
:
56 case ui::ET_KEY_RELEASED
:
63 // Converts EventType to XButtonEvent type.
64 int XButtonEventType(ui::EventType 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.
70 case ui::ET_MOUSE_RELEASED
:
77 // Converts KeyboardCode to XKeyEvent keycode.
78 unsigned int XKeyEventKeyCode(ui::KeyboardCode key_code
,
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
,
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
)
98 case ui::EF_LEFT_MOUSE_BUTTON
:
100 case ui::EF_MIDDLE_MOUSE_BUTTON
:
102 case ui::EF_RIGHT_MOUSE_BUTTON
:
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
,
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();
141 void InitXKeyEventForTesting(EventType type
,
142 KeyboardCode key_code
,
146 XDisplay
* display
= gfx::GetXDisplay();
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
;
154 key_event
.window
= 0;
156 key_event
.subwindow
= 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
,
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;
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
,
197 InitXButtonEventForTesting(ui::ET_MOUSEWHEEL
, flags
, event
);
198 // MouseWheelEvents are not taking horizontal scrolls into account
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
);
210 delete[] xiev
->valuators
.mask
;
211 delete[] xiev
->valuators
.values
;
216 EVENTS_EXPORT XEvent
* CreateScrollEventForTest(
220 int x_offset_ordinal
,
221 int y_offset_ordinal
,
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
];
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(
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
,
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());
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
;
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(
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)