1 // Copyright 2014 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/device_data_manager_x11.h"
7 #include <X11/extensions/XInput.h>
8 #include <X11/extensions/XInput2.h>
11 #include "base/logging.h"
12 #include "base/memory/singleton.h"
13 #include "base/sys_info.h"
14 #include "ui/events/event_constants.h"
15 #include "ui/events/event_switches.h"
16 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
17 #include "ui/events/x/device_list_cache_x.h"
18 #include "ui/events/x/touch_factory_x11.h"
19 #include "ui/gfx/display.h"
20 #include "ui/gfx/point3_f.h"
21 #include "ui/gfx/x/x11_types.h"
23 // XIScrollClass was introduced in XI 2.1 so we need to define it here
24 // for backward-compatibility with older versions of XInput.
25 #if !defined(XIScrollClass)
26 #define XIScrollClass 3
29 // Multi-touch support was introduced in XI 2.2. Add XI event types here
30 // for backward-compatibility with older versions of XInput.
31 #if !defined(XI_TouchBegin)
32 #define XI_TouchBegin 18
33 #define XI_TouchUpdate 19
34 #define XI_TouchEnd 20
37 // Copied from xserver-properties.h
38 #define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
39 #define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
41 // CMT specific timings
42 #define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp"
43 #define AXIS_LABEL_PROP_ABS_DBL_END_TIME "Abs Dbl End Timestamp"
46 #define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X "Abs Dbl Ordinal X"
47 #define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y "Abs Dbl Ordinal Y"
50 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VX "Abs Dbl Fling X Velocity"
51 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VY "Abs Dbl Fling Y Velocity"
52 #define AXIS_LABEL_PROP_ABS_FLING_STATE "Abs Fling State"
54 #define AXIS_LABEL_PROP_ABS_FINGER_COUNT "Abs Finger Count"
56 // Cros metrics gesture from touchpad
57 #define AXIS_LABEL_PROP_ABS_METRICS_TYPE "Abs Metrics Type"
58 #define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1 "Abs Dbl Metrics Data 1"
59 #define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2 "Abs Dbl Metrics Data 2"
61 // Touchscreen multi-touch
62 #define AXIS_LABEL_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major"
63 #define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor"
64 #define AXIS_LABEL_ABS_MT_ORIENTATION "Abs MT Orientation"
65 #define AXIS_LABEL_ABS_MT_PRESSURE "Abs MT Pressure"
66 #define AXIS_LABEL_ABS_MT_POSITION_X "Abs MT Position X"
67 #define AXIS_LABEL_ABS_MT_POSITION_Y "Abs MT Position Y"
68 #define AXIS_LABEL_ABS_MT_TRACKING_ID "Abs MT Tracking ID"
69 #define AXIS_LABEL_TOUCH_TIMESTAMP "Touch Timestamp"
71 // When you add new data types, please make sure the order here is aligned
72 // with the order in the DataType enum in the header file because we assume
73 // they are in sync when updating the device list (see UpdateDeviceList).
74 const char* kCachedAtoms
[] = {
75 AXIS_LABEL_PROP_REL_HWHEEL
,
76 AXIS_LABEL_PROP_REL_WHEEL
,
77 AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X
,
78 AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y
,
79 AXIS_LABEL_PROP_ABS_DBL_START_TIME
,
80 AXIS_LABEL_PROP_ABS_DBL_END_TIME
,
81 AXIS_LABEL_PROP_ABS_DBL_FLING_VX
,
82 AXIS_LABEL_PROP_ABS_DBL_FLING_VY
,
83 AXIS_LABEL_PROP_ABS_FLING_STATE
,
84 AXIS_LABEL_PROP_ABS_METRICS_TYPE
,
85 AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1
,
86 AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2
,
87 AXIS_LABEL_PROP_ABS_FINGER_COUNT
,
88 AXIS_LABEL_ABS_MT_TOUCH_MAJOR
,
89 AXIS_LABEL_ABS_MT_TOUCH_MINOR
,
90 AXIS_LABEL_ABS_MT_ORIENTATION
,
91 AXIS_LABEL_ABS_MT_PRESSURE
,
92 AXIS_LABEL_ABS_MT_POSITION_X
,
93 AXIS_LABEL_ABS_MT_POSITION_Y
,
94 AXIS_LABEL_ABS_MT_TRACKING_ID
,
95 AXIS_LABEL_TOUCH_TIMESTAMP
,
100 // Constants for checking if a data type lies in the range of CMT/Touch data
102 const int kCMTDataTypeStart
= ui::DeviceDataManagerX11::DT_CMT_SCROLL_X
;
103 const int kCMTDataTypeEnd
= ui::DeviceDataManagerX11::DT_CMT_FINGER_COUNT
;
104 const int kTouchDataTypeStart
= ui::DeviceDataManagerX11::DT_TOUCH_MAJOR
;
105 const int kTouchDataTypeEnd
= ui::DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP
;
109 bool DeviceDataManagerX11::IsCMTDataType(const int type
) {
110 return (type
>= kCMTDataTypeStart
) && (type
<= kCMTDataTypeEnd
);
113 bool DeviceDataManagerX11::IsTouchDataType(const int type
) {
114 return (type
>= kTouchDataTypeStart
) && (type
<= kTouchDataTypeEnd
);
118 void DeviceDataManagerX11::CreateInstance() {
122 new DeviceDataManagerX11();
126 DeviceDataManagerX11
* DeviceDataManagerX11::GetInstance() {
127 return static_cast<DeviceDataManagerX11
*>(DeviceDataManager::GetInstance());
130 DeviceDataManagerX11::DeviceDataManagerX11()
132 atom_cache_(gfx::GetXDisplay(), kCachedAtoms
),
133 button_map_count_(0) {
134 CHECK(gfx::GetXDisplay());
135 InitializeXInputInternal();
137 // Make sure the sizes of enum and kCachedAtoms are aligned.
138 CHECK(arraysize(kCachedAtoms
) == static_cast<size_t>(DT_LAST_ENTRY
) + 1);
139 UpdateDeviceList(gfx::GetXDisplay());
143 DeviceDataManagerX11::~DeviceDataManagerX11() {
146 bool DeviceDataManagerX11::InitializeXInputInternal() {
147 // Check if XInput is available on the system.
149 int opcode
, event
, error
;
150 if (!XQueryExtension(
151 gfx::GetXDisplay(), "XInputExtension", &opcode
, &event
, &error
)) {
152 VLOG(1) << "X Input extension not available: error=" << error
;
156 // Check the XInput version.
157 #if defined(USE_XI2_MT)
158 int major
= 2, minor
= USE_XI2_MT
;
160 int major
= 2, minor
= 0;
162 if (XIQueryVersion(gfx::GetXDisplay(), &major
, &minor
) == BadRequest
) {
163 VLOG(1) << "XInput2 not supported in the server.";
166 #if defined(USE_XI2_MT)
167 if (major
< 2 || (major
== 2 && minor
< USE_XI2_MT
)) {
168 DVLOG(1) << "XI version on server is " << major
<< "." << minor
<< ". "
169 << "But 2." << USE_XI2_MT
<< " is required.";
175 CHECK_NE(-1, xi_opcode_
);
177 // Possible XI event types for XIDeviceEvent. See the XI2 protocol
179 xi_device_event_types_
[XI_KeyPress
] = true;
180 xi_device_event_types_
[XI_KeyRelease
] = true;
181 xi_device_event_types_
[XI_ButtonPress
] = true;
182 xi_device_event_types_
[XI_ButtonRelease
] = true;
183 xi_device_event_types_
[XI_Motion
] = true;
184 // Multi-touch support was introduced in XI 2.2.
186 xi_device_event_types_
[XI_TouchBegin
] = true;
187 xi_device_event_types_
[XI_TouchUpdate
] = true;
188 xi_device_event_types_
[XI_TouchEnd
] = true;
193 bool DeviceDataManagerX11::IsXInput2Available() const {
194 return xi_opcode_
!= -1;
197 void DeviceDataManagerX11::UpdateDeviceList(Display
* display
) {
198 cmt_devices_
.reset();
200 for (int i
= 0; i
< kMaxDeviceNum
; ++i
) {
201 valuator_count_
[i
] = 0;
202 valuator_lookup_
[i
].clear();
203 data_type_lookup_
[i
].clear();
204 valuator_min_
[i
].clear();
205 valuator_max_
[i
].clear();
206 for (int j
= 0; j
< kMaxSlotNum
; j
++)
207 last_seen_valuator_
[i
][j
].clear();
210 // Find all the touchpad devices.
211 XDeviceList dev_list
=
212 ui::DeviceListCacheX::GetInstance()->GetXDeviceList(display
);
213 Atom xi_touchpad
= XInternAtom(display
, XI_TOUCHPAD
, false);
214 for (int i
= 0; i
< dev_list
.count
; ++i
)
215 if (dev_list
[i
].type
== xi_touchpad
)
216 touchpads_
[dev_list
[i
].id
] = true;
218 if (!IsXInput2Available())
221 // Update the structs with new valuator information
222 XIDeviceList info_list
=
223 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(display
);
224 Atom atoms
[DT_LAST_ENTRY
];
225 for (int data_type
= 0; data_type
< DT_LAST_ENTRY
; ++data_type
)
226 atoms
[data_type
] = atom_cache_
.GetAtom(kCachedAtoms
[data_type
]);
228 for (int i
= 0; i
< info_list
.count
; ++i
) {
229 XIDeviceInfo
* info
= info_list
.devices
+ i
;
231 // We currently handle only slave, non-keyboard devices
232 if (info
->use
!= XISlavePointer
&& info
->use
!= XIFloatingSlave
)
235 bool possible_cmt
= false;
236 bool not_cmt
= false;
237 const int deviceid
= info
->deviceid
;
239 for (int j
= 0; j
< info
->num_classes
; ++j
) {
240 if (info
->classes
[j
]->type
== XIValuatorClass
)
241 ++valuator_count_
[deviceid
];
242 else if (info
->classes
[j
]->type
== XIScrollClass
)
246 // Skip devices that don't use any valuator
247 if (!valuator_count_
[deviceid
])
250 valuator_lookup_
[deviceid
].resize(DT_LAST_ENTRY
, -1);
251 data_type_lookup_
[deviceid
].resize(
252 valuator_count_
[deviceid
], DT_LAST_ENTRY
);
253 valuator_min_
[deviceid
].resize(DT_LAST_ENTRY
, 0);
254 valuator_max_
[deviceid
].resize(DT_LAST_ENTRY
, 0);
255 for (int j
= 0; j
< kMaxSlotNum
; j
++)
256 last_seen_valuator_
[deviceid
][j
].resize(DT_LAST_ENTRY
, 0);
257 for (int j
= 0; j
< info
->num_classes
; ++j
) {
258 if (info
->classes
[j
]->type
!= XIValuatorClass
)
261 XIValuatorClassInfo
* v
=
262 reinterpret_cast<XIValuatorClassInfo
*>(info
->classes
[j
]);
263 for (int data_type
= 0; data_type
< DT_LAST_ENTRY
; ++data_type
) {
264 if (v
->label
== atoms
[data_type
]) {
265 valuator_lookup_
[deviceid
][data_type
] = v
->number
;
266 data_type_lookup_
[deviceid
][v
->number
] = data_type
;
267 valuator_min_
[deviceid
][data_type
] = v
->min
;
268 valuator_max_
[deviceid
][data_type
] = v
->max
;
269 if (IsCMTDataType(data_type
))
276 if (possible_cmt
&& !not_cmt
)
277 cmt_devices_
[deviceid
] = true;
281 bool DeviceDataManagerX11::GetSlotNumber(const XIDeviceEvent
* xiev
, int* slot
) {
282 #if defined(USE_XI2_MT)
283 ui::TouchFactory
* factory
= ui::TouchFactory::GetInstance();
284 if (!factory
->IsMultiTouchDevice(xiev
->sourceid
)) {
288 return factory
->QuerySlotForTrackingID(xiev
->detail
, slot
);
295 void DeviceDataManagerX11::GetEventRawData(const XEvent
& xev
, EventData
* data
) {
296 if (xev
.type
!= GenericEvent
)
299 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(xev
.xcookie
.data
);
300 if (xiev
->sourceid
>= kMaxDeviceNum
|| xiev
->deviceid
>= kMaxDeviceNum
)
303 const int sourceid
= xiev
->sourceid
;
304 double* valuators
= xiev
->valuators
.values
;
305 for (int i
= 0; i
<= valuator_count_
[sourceid
]; ++i
) {
306 if (XIMaskIsSet(xiev
->valuators
.mask
, i
)) {
307 int type
= data_type_lookup_
[sourceid
][i
];
308 if (type
!= DT_LAST_ENTRY
) {
309 (*data
)[type
] = *valuators
;
310 if (IsTouchDataType(type
)) {
312 if (GetSlotNumber(xiev
, &slot
) && slot
>= 0 && slot
< kMaxSlotNum
)
313 last_seen_valuator_
[sourceid
][slot
][type
] = *valuators
;
321 bool DeviceDataManagerX11::GetEventData(const XEvent
& xev
,
322 const DataType type
, double* value
) {
323 if (xev
.type
!= GenericEvent
)
326 XIDeviceEvent
* xiev
= static_cast<XIDeviceEvent
*>(xev
.xcookie
.data
);
327 if (xiev
->sourceid
>= kMaxDeviceNum
|| xiev
->deviceid
>= kMaxDeviceNum
)
329 const int sourceid
= xiev
->sourceid
;
330 if (valuator_lookup_
[sourceid
].empty())
333 if (type
== DT_TOUCH_TRACKING_ID
) {
334 // With XInput2 MT, Tracking ID is provided in the detail field for touch
336 if (xiev
->evtype
== XI_TouchBegin
||
337 xiev
->evtype
== XI_TouchEnd
||
338 xiev
->evtype
== XI_TouchUpdate
) {
339 *value
= xiev
->detail
;
346 int val_index
= valuator_lookup_
[sourceid
][type
];
348 if (val_index
>= 0) {
349 if (XIMaskIsSet(xiev
->valuators
.mask
, val_index
)) {
350 double* valuators
= xiev
->valuators
.values
;
351 while (val_index
--) {
352 if (XIMaskIsSet(xiev
->valuators
.mask
, val_index
))
356 if (IsTouchDataType(type
)) {
357 if (GetSlotNumber(xiev
, &slot
) && slot
>= 0 && slot
< kMaxSlotNum
)
358 last_seen_valuator_
[sourceid
][slot
][type
] = *value
;
361 } else if (IsTouchDataType(type
)) {
362 if (GetSlotNumber(xiev
, &slot
) && slot
>= 0 && slot
< kMaxSlotNum
)
363 *value
= last_seen_valuator_
[sourceid
][slot
][type
];
370 bool DeviceDataManagerX11::IsXIDeviceEvent(
371 const base::NativeEvent
& native_event
) const {
372 if (native_event
->type
!= GenericEvent
||
373 native_event
->xcookie
.extension
!= xi_opcode_
)
375 return xi_device_event_types_
[native_event
->xcookie
.evtype
];
378 bool DeviceDataManagerX11::IsTouchpadXInputEvent(
379 const base::NativeEvent
& native_event
) const {
380 if (native_event
->type
!= GenericEvent
)
383 XIDeviceEvent
* xievent
=
384 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
385 if (xievent
->sourceid
>= kMaxDeviceNum
)
387 return touchpads_
[xievent
->sourceid
];
390 bool DeviceDataManagerX11::IsCMTDeviceEvent(
391 const base::NativeEvent
& native_event
) const {
392 if (native_event
->type
!= GenericEvent
)
395 XIDeviceEvent
* xievent
=
396 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
397 if (xievent
->sourceid
>= kMaxDeviceNum
)
399 return cmt_devices_
[xievent
->sourceid
];
402 bool DeviceDataManagerX11::IsCMTGestureEvent(
403 const base::NativeEvent
& native_event
) const {
404 return (IsScrollEvent(native_event
) ||
405 IsFlingEvent(native_event
) ||
406 IsCMTMetricsEvent(native_event
));
409 bool DeviceDataManagerX11::HasEventData(
410 const XIDeviceEvent
* xiev
, const DataType type
) const {
411 const int idx
= valuator_lookup_
[xiev
->sourceid
][type
];
412 return (idx
>= 0) && XIMaskIsSet(xiev
->valuators
.mask
, idx
);
415 bool DeviceDataManagerX11::IsScrollEvent(
416 const base::NativeEvent
& native_event
) const {
417 if (!IsCMTDeviceEvent(native_event
))
420 XIDeviceEvent
* xiev
=
421 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
422 return (HasEventData(xiev
, DT_CMT_SCROLL_X
) ||
423 HasEventData(xiev
, DT_CMT_SCROLL_Y
));
426 bool DeviceDataManagerX11::IsFlingEvent(
427 const base::NativeEvent
& native_event
) const {
428 if (!IsCMTDeviceEvent(native_event
))
431 XIDeviceEvent
* xiev
=
432 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
433 return (HasEventData(xiev
, DT_CMT_FLING_X
) &&
434 HasEventData(xiev
, DT_CMT_FLING_Y
) &&
435 HasEventData(xiev
, DT_CMT_FLING_STATE
));
438 bool DeviceDataManagerX11::IsCMTMetricsEvent(
439 const base::NativeEvent
& native_event
) const {
440 if (!IsCMTDeviceEvent(native_event
))
443 XIDeviceEvent
* xiev
=
444 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
445 return (HasEventData(xiev
, DT_CMT_METRICS_TYPE
) &&
446 HasEventData(xiev
, DT_CMT_METRICS_DATA1
) &&
447 HasEventData(xiev
, DT_CMT_METRICS_DATA2
));
450 bool DeviceDataManagerX11::HasGestureTimes(
451 const base::NativeEvent
& native_event
) const {
452 if (!IsCMTDeviceEvent(native_event
))
455 XIDeviceEvent
* xiev
=
456 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
457 return (HasEventData(xiev
, DT_CMT_START_TIME
) &&
458 HasEventData(xiev
, DT_CMT_END_TIME
));
461 void DeviceDataManagerX11::GetScrollOffsets(
462 const base::NativeEvent
& native_event
,
465 float* x_offset_ordinal
,
466 float* y_offset_ordinal
,
470 *x_offset_ordinal
= 0;
471 *y_offset_ordinal
= 0;
475 GetEventRawData(*native_event
, &data
);
477 if (data
.find(DT_CMT_SCROLL_X
) != data
.end())
478 *x_offset
= data
[DT_CMT_SCROLL_X
];
479 if (data
.find(DT_CMT_SCROLL_Y
) != data
.end())
480 *y_offset
= data
[DT_CMT_SCROLL_Y
];
481 if (data
.find(DT_CMT_ORDINAL_X
) != data
.end())
482 *x_offset_ordinal
= data
[DT_CMT_ORDINAL_X
];
483 if (data
.find(DT_CMT_ORDINAL_Y
) != data
.end())
484 *y_offset_ordinal
= data
[DT_CMT_ORDINAL_Y
];
485 if (data
.find(DT_CMT_FINGER_COUNT
) != data
.end())
486 *finger_count
= static_cast<int>(data
[DT_CMT_FINGER_COUNT
]);
489 void DeviceDataManagerX11::GetFlingData(
490 const base::NativeEvent
& native_event
,
503 GetEventRawData(*native_event
, &data
);
505 if (data
.find(DT_CMT_FLING_X
) != data
.end())
506 *vx
= data
[DT_CMT_FLING_X
];
507 if (data
.find(DT_CMT_FLING_Y
) != data
.end())
508 *vy
= data
[DT_CMT_FLING_Y
];
509 if (data
.find(DT_CMT_FLING_STATE
) != data
.end())
510 *is_cancel
= !!static_cast<unsigned int>(data
[DT_CMT_FLING_STATE
]);
511 if (data
.find(DT_CMT_ORDINAL_X
) != data
.end())
512 *vx_ordinal
= data
[DT_CMT_ORDINAL_X
];
513 if (data
.find(DT_CMT_ORDINAL_Y
) != data
.end())
514 *vy_ordinal
= data
[DT_CMT_ORDINAL_Y
];
517 void DeviceDataManagerX11::GetMetricsData(
518 const base::NativeEvent
& native_event
,
519 GestureMetricsType
* type
,
522 *type
= kGestureMetricsTypeUnknown
;
527 GetEventRawData(*native_event
, &data
);
529 if (data
.find(DT_CMT_METRICS_TYPE
) != data
.end()) {
530 int val
= static_cast<int>(data
[DT_CMT_METRICS_TYPE
]);
532 *type
= kGestureMetricsTypeNoisyGround
;
534 *type
= kGestureMetricsTypeUnknown
;
536 if (data
.find(DT_CMT_METRICS_DATA1
) != data
.end())
537 *data1
= data
[DT_CMT_METRICS_DATA1
];
538 if (data
.find(DT_CMT_METRICS_DATA2
) != data
.end())
539 *data2
= data
[DT_CMT_METRICS_DATA2
];
542 int DeviceDataManagerX11::GetMappedButton(int button
) {
543 return button
> 0 && button
<= button_map_count_
? button_map_
[button
- 1] :
547 void DeviceDataManagerX11::UpdateButtonMap() {
548 button_map_count_
= XGetPointerMapping(gfx::GetXDisplay(),
550 arraysize(button_map_
));
553 void DeviceDataManagerX11::GetGestureTimes(
554 const base::NativeEvent
& native_event
,
561 GetEventRawData(*native_event
, &data
);
563 if (data
.find(DT_CMT_START_TIME
) != data
.end())
564 *start_time
= data
[DT_CMT_START_TIME
];
565 if (data
.find(DT_CMT_END_TIME
) != data
.end())
566 *end_time
= data
[DT_CMT_END_TIME
];
569 bool DeviceDataManagerX11::NormalizeData(unsigned int deviceid
,
574 if (GetDataRange(deviceid
, type
, &min_value
, &max_value
)) {
575 *value
= (*value
- min_value
) / (max_value
- min_value
);
576 DCHECK(*value
>= 0.0 && *value
<= 1.0);
582 bool DeviceDataManagerX11::GetDataRange(unsigned int deviceid
,
586 if (deviceid
>= static_cast<unsigned int>(kMaxDeviceNum
))
588 if (valuator_lookup_
[deviceid
][type
] >= 0) {
589 *min
= valuator_min_
[deviceid
][type
];
590 *max
= valuator_max_
[deviceid
][type
];
596 void DeviceDataManagerX11::SetDeviceListForTest(
597 const std::vector
<unsigned int>& touchscreen
,
598 const std::vector
<unsigned int>& cmt_devices
) {
599 for (int i
= 0; i
< kMaxDeviceNum
; ++i
) {
600 valuator_count_
[i
] = 0;
601 valuator_lookup_
[i
].clear();
602 data_type_lookup_
[i
].clear();
603 valuator_min_
[i
].clear();
604 valuator_max_
[i
].clear();
605 for (int j
= 0; j
< kMaxSlotNum
; j
++)
606 last_seen_valuator_
[i
][j
].clear();
609 for (size_t i
= 0; i
< touchscreen
.size(); i
++) {
610 unsigned int deviceid
= touchscreen
[i
];
611 InitializeValuatorsForTest(deviceid
, kTouchDataTypeStart
, kTouchDataTypeEnd
,
615 cmt_devices_
.reset();
616 for (size_t i
= 0; i
< cmt_devices
.size(); ++i
) {
617 unsigned int deviceid
= cmt_devices
[i
];
618 cmt_devices_
[deviceid
] = true;
619 touchpads_
[deviceid
] = true;
620 InitializeValuatorsForTest(deviceid
, kCMTDataTypeStart
, kCMTDataTypeEnd
,
625 void DeviceDataManagerX11::SetValuatorDataForTest(XIDeviceEvent
* xievent
,
628 int index
= valuator_lookup_
[xievent
->deviceid
][type
];
629 CHECK(!XIMaskIsSet(xievent
->valuators
.mask
, index
));
630 CHECK(index
>= 0 && index
< valuator_count_
[xievent
->deviceid
]);
631 XISetMask(xievent
->valuators
.mask
, index
);
633 double* valuators
= xievent
->valuators
.values
;
634 for (int i
= 0; i
< index
; ++i
) {
635 if (XIMaskIsSet(xievent
->valuators
.mask
, i
))
638 for (int i
= DT_LAST_ENTRY
- 1; i
> valuators
- xievent
->valuators
.values
;
640 xievent
->valuators
.values
[i
] = xievent
->valuators
.values
[i
- 1];
644 void DeviceDataManagerX11::InitializeValuatorsForTest(int deviceid
,
649 valuator_lookup_
[deviceid
].resize(DT_LAST_ENTRY
, -1);
650 data_type_lookup_
[deviceid
].resize(DT_LAST_ENTRY
, DT_LAST_ENTRY
);
651 valuator_min_
[deviceid
].resize(DT_LAST_ENTRY
, 0);
652 valuator_max_
[deviceid
].resize(DT_LAST_ENTRY
, 0);
653 for (int j
= 0; j
< kMaxSlotNum
; j
++)
654 last_seen_valuator_
[deviceid
][j
].resize(DT_LAST_ENTRY
, 0);
655 for (int j
= start_valuator
; j
<= end_valuator
; ++j
) {
656 valuator_lookup_
[deviceid
][j
] = valuator_count_
[deviceid
];
657 data_type_lookup_
[deviceid
][valuator_count_
[deviceid
]] = j
;
658 valuator_min_
[deviceid
][j
] = min_value
;
659 valuator_max_
[deviceid
][j
] = max_value
;
660 valuator_count_
[deviceid
]++;
664 bool DeviceDataManagerX11::TouchEventNeedsCalibrate(int touch_device_id
) const {
665 #if defined(OS_CHROMEOS) && defined(USE_XI2_MT)
666 int64 touch_display_id
= GetDisplayForTouchDevice(touch_device_id
);
667 if (base::SysInfo::IsRunningOnChromeOS() &&
668 touch_display_id
== gfx::Display::InternalDisplayId()) {
671 #endif // defined(OS_CHROMEOS) && defined(USE_XI2_MT)
675 void DeviceDataManagerX11::SetDisabledKeyboardAllowedKeys(
676 scoped_ptr
<std::set
<KeyboardCode
> > excepted_keys
) {
677 DCHECK(!excepted_keys
.get() ||
678 !blocked_keyboard_allowed_keys_
.get());
679 blocked_keyboard_allowed_keys_
= excepted_keys
.Pass();
682 void DeviceDataManagerX11::DisableDevice(unsigned int deviceid
) {
683 blocked_devices_
.set(deviceid
, true);
686 void DeviceDataManagerX11::EnableDevice(unsigned int deviceid
) {
687 blocked_devices_
.set(deviceid
, false);
690 bool DeviceDataManagerX11::IsEventBlocked(
691 const base::NativeEvent
& native_event
) {
692 // Only check XI2 events which have a source device id.
693 if (native_event
->type
!= GenericEvent
)
696 XIDeviceEvent
* xievent
=
697 static_cast<XIDeviceEvent
*>(native_event
->xcookie
.data
);
698 // Allow any key events from blocked_keyboard_allowed_keys_.
699 if (blocked_keyboard_allowed_keys_
&&
700 (xievent
->evtype
== XI_KeyPress
|| xievent
->evtype
== XI_KeyRelease
) &&
701 blocked_keyboard_allowed_keys_
->find(
702 KeyboardCodeFromXKeyEvent(native_event
)) !=
703 blocked_keyboard_allowed_keys_
->end()) {
707 return blocked_devices_
.test(xievent
->sourceid
);