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.
5 #include "ui/events/x/device_data_manager.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/x/device_list_cache_x.h"
17 #include "ui/events/x/touch_factory_x11.h"
18 #include "ui/gfx/display.h"
19 #include "ui/gfx/point3_f.h"
20 #include "ui/gfx/x/x11_types.h"
22 // XIScrollClass was introduced in XI 2.1 so we need to define it here
23 // for backward-compatibility with older versions of XInput.
24 #if !defined(XIScrollClass)
25 #define XIScrollClass 3
28 // Multi-touch support was introduced in XI 2.2. Add XI event types here
29 // for backward-compatibility with older versions of XInput.
30 #if !defined(XI_TouchBegin)
31 #define XI_TouchBegin 18
32 #define XI_TouchUpdate 19
33 #define XI_TouchEnd 20
36 // Copied from xserver-properties.h
37 #define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
38 #define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
40 // CMT specific timings
41 #define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp"
42 #define AXIS_LABEL_PROP_ABS_DBL_END_TIME "Abs Dbl End Timestamp"
45 #define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X "Abs Dbl Ordinal X"
46 #define AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y "Abs Dbl Ordinal Y"
49 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VX "Abs Dbl Fling X Velocity"
50 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VY "Abs Dbl Fling Y Velocity"
51 #define AXIS_LABEL_PROP_ABS_FLING_STATE "Abs Fling State"
53 #define AXIS_LABEL_PROP_ABS_FINGER_COUNT "Abs Finger Count"
55 // Cros metrics gesture from touchpad
56 #define AXIS_LABEL_PROP_ABS_METRICS_TYPE "Abs Metrics Type"
57 #define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1 "Abs Dbl Metrics Data 1"
58 #define AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2 "Abs Dbl Metrics Data 2"
60 // Touchscreen multi-touch
61 #define AXIS_LABEL_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major"
62 #define AXIS_LABEL_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor"
63 #define AXIS_LABEL_ABS_MT_ORIENTATION "Abs MT Orientation"
64 #define AXIS_LABEL_ABS_MT_PRESSURE "Abs MT Pressure"
65 #define AXIS_LABEL_ABS_MT_TRACKING_ID "Abs MT Tracking ID"
66 #define AXIS_LABEL_TOUCH_TIMESTAMP "Touch Timestamp"
68 // When you add new data types, please make sure the order here is aligned
69 // with the order in the DataType enum in the header file because we assume
70 // they are in sync when updating the device list (see UpdateDeviceList).
71 const char* kCachedAtoms[] = {
72 AXIS_LABEL_PROP_REL_HWHEEL,
73 AXIS_LABEL_PROP_REL_WHEEL,
74 AXIS_LABEL_PROP_ABS_DBL_ORDINAL_X,
75 AXIS_LABEL_PROP_ABS_DBL_ORDINAL_Y,
76 AXIS_LABEL_PROP_ABS_DBL_START_TIME,
77 AXIS_LABEL_PROP_ABS_DBL_END_TIME,
78 AXIS_LABEL_PROP_ABS_DBL_FLING_VX,
79 AXIS_LABEL_PROP_ABS_DBL_FLING_VY,
80 AXIS_LABEL_PROP_ABS_FLING_STATE,
81 AXIS_LABEL_PROP_ABS_METRICS_TYPE,
82 AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA1,
83 AXIS_LABEL_PROP_ABS_DBL_METRICS_DATA2,
84 AXIS_LABEL_PROP_ABS_FINGER_COUNT,
85 AXIS_LABEL_ABS_MT_TOUCH_MAJOR,
86 AXIS_LABEL_ABS_MT_TOUCH_MINOR,
87 AXIS_LABEL_ABS_MT_ORIENTATION,
88 AXIS_LABEL_ABS_MT_PRESSURE,
89 AXIS_LABEL_ABS_MT_TRACKING_ID,
90 AXIS_LABEL_TOUCH_TIMESTAMP,
95 // Constants for checking if a data type lies in the range of CMT/Touch data
97 const int kCMTDataTypeStart = ui::DeviceDataManager::DT_CMT_SCROLL_X;
98 const int kCMTDataTypeEnd = ui::DeviceDataManager::DT_CMT_FINGER_COUNT;
99 const int kTouchDataTypeStart = ui::DeviceDataManager::DT_TOUCH_MAJOR;
100 const int kTouchDataTypeEnd = ui::DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP;
104 bool DeviceDataManager::IsCMTDataType(const int type) {
105 return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd);
108 bool DeviceDataManager::IsTouchDataType(const int type) {
109 return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd);
112 DeviceDataManager* DeviceDataManager::GetInstance() {
113 return Singleton<DeviceDataManager>::get();
116 DeviceDataManager::DeviceDataManager()
118 atom_cache_(gfx::GetXDisplay(), kCachedAtoms),
119 button_map_count_(0) {
120 CHECK(gfx::GetXDisplay());
121 InitializeXInputInternal();
123 // Make sure the sizes of enum and kCachedAtoms are aligned.
124 CHECK(arraysize(kCachedAtoms) == static_cast<size_t>(DT_LAST_ENTRY) + 1);
125 UpdateDeviceList(gfx::GetXDisplay());
127 for (int i = 0; i < kMaxDeviceNum; i++)
128 touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
131 DeviceDataManager::~DeviceDataManager() {
134 bool DeviceDataManager::InitializeXInputInternal() {
135 // Check if XInput is available on the system.
137 int opcode, event, error;
138 if (!XQueryExtension(
139 gfx::GetXDisplay(), "XInputExtension", &opcode, &event, &error)) {
140 VLOG(1) << "X Input extension not available: error=" << error;
144 // Check the XInput version.
145 #if defined(USE_XI2_MT)
146 int major = 2, minor = USE_XI2_MT;
148 int major = 2, minor = 0;
150 if (XIQueryVersion(gfx::GetXDisplay(), &major, &minor) == BadRequest) {
151 VLOG(1) << "XInput2 not supported in the server.";
154 #if defined(USE_XI2_MT)
155 if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
156 DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
157 << "But 2." << USE_XI2_MT << " is required.";
163 CHECK_NE(-1, xi_opcode_);
165 // Possible XI event types for XIDeviceEvent. See the XI2 protocol
167 xi_device_event_types_[XI_KeyPress] = true;
168 xi_device_event_types_[XI_KeyRelease] = true;
169 xi_device_event_types_[XI_ButtonPress] = true;
170 xi_device_event_types_[XI_ButtonRelease] = true;
171 xi_device_event_types_[XI_Motion] = true;
172 // Multi-touch support was introduced in XI 2.2.
174 xi_device_event_types_[XI_TouchBegin] = true;
175 xi_device_event_types_[XI_TouchUpdate] = true;
176 xi_device_event_types_[XI_TouchEnd] = true;
181 bool DeviceDataManager::IsXInput2Available() const {
182 return xi_opcode_ != -1;
185 void DeviceDataManager::UpdateDeviceList(Display* display) {
186 cmt_devices_.reset();
188 for (int i = 0; i < kMaxDeviceNum; ++i) {
189 valuator_count_[i] = 0;
190 valuator_lookup_[i].clear();
191 data_type_lookup_[i].clear();
192 valuator_min_[i].clear();
193 valuator_max_[i].clear();
194 for (int j = 0; j < kMaxSlotNum; j++)
195 last_seen_valuator_[i][j].clear();
198 // Find all the touchpad devices.
199 XDeviceList dev_list =
200 ui::DeviceListCacheX::GetInstance()->GetXDeviceList(display);
201 Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
202 for (int i = 0; i < dev_list.count; ++i)
203 if (dev_list[i].type == xi_touchpad)
204 touchpads_[dev_list[i].id] = true;
206 if (!IsXInput2Available())
209 // Update the structs with new valuator information
210 XIDeviceList info_list =
211 ui::DeviceListCacheX::GetInstance()->GetXI2DeviceList(display);
212 Atom atoms[DT_LAST_ENTRY];
213 for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type)
214 atoms[data_type] = atom_cache_.GetAtom(kCachedAtoms[data_type]);
216 for (int i = 0; i < info_list.count; ++i) {
217 XIDeviceInfo* info = info_list.devices + i;
219 // We currently handle only slave, non-keyboard devices
220 if (info->use != XISlavePointer && info->use != XIFloatingSlave)
223 bool possible_cmt = false;
224 bool not_cmt = false;
225 const int deviceid = info->deviceid;
227 for (int j = 0; j < info->num_classes; ++j) {
228 if (info->classes[j]->type == XIValuatorClass)
229 ++valuator_count_[deviceid];
230 else if (info->classes[j]->type == XIScrollClass)
234 // Skip devices that don't use any valuator
235 if (!valuator_count_[deviceid])
238 valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
239 data_type_lookup_[deviceid].resize(
240 valuator_count_[deviceid], DT_LAST_ENTRY);
241 valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
242 valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
243 for (int j = 0; j < kMaxSlotNum; j++)
244 last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
245 for (int j = 0; j < info->num_classes; ++j) {
246 if (info->classes[j]->type != XIValuatorClass)
249 XIValuatorClassInfo* v =
250 reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
251 for (int data_type = 0; data_type < DT_LAST_ENTRY; ++data_type) {
252 if (v->label == atoms[data_type]) {
253 valuator_lookup_[deviceid][data_type] = v->number;
254 data_type_lookup_[deviceid][v->number] = data_type;
255 valuator_min_[deviceid][data_type] = v->min;
256 valuator_max_[deviceid][data_type] = v->max;
257 if (IsCMTDataType(data_type))
264 if (possible_cmt && !not_cmt)
265 cmt_devices_[deviceid] = true;
269 bool DeviceDataManager::GetSlotNumber(const XIDeviceEvent* xiev, int* slot) {
270 #if defined(USE_XI2_MT)
271 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
272 if (!factory->IsMultiTouchDevice(xiev->sourceid)) {
276 return factory->QuerySlotForTrackingID(xiev->detail, slot);
283 void DeviceDataManager::GetEventRawData(const XEvent& xev, EventData* data) {
284 if (xev.type != GenericEvent)
287 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
288 if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
291 const int sourceid = xiev->sourceid;
292 double* valuators = xiev->valuators.values;
293 for (int i = 0; i <= valuator_count_[sourceid]; ++i) {
294 if (XIMaskIsSet(xiev->valuators.mask, i)) {
295 int type = data_type_lookup_[sourceid][i];
296 if (type != DT_LAST_ENTRY) {
297 (*data)[type] = *valuators;
298 if (IsTouchDataType(type)) {
300 if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
301 last_seen_valuator_[sourceid][slot][type] = *valuators;
309 bool DeviceDataManager::GetEventData(const XEvent& xev,
310 const DataType type, double* value) {
311 if (xev.type != GenericEvent)
314 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
315 if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum)
317 const int sourceid = xiev->sourceid;
318 if (valuator_lookup_[sourceid].empty())
321 if (type == DT_TOUCH_TRACKING_ID) {
322 // With XInput2 MT, Tracking ID is provided in the detail field for touch
324 if (xiev->evtype == XI_TouchBegin ||
325 xiev->evtype == XI_TouchEnd ||
326 xiev->evtype == XI_TouchUpdate) {
327 *value = xiev->detail;
334 int val_index = valuator_lookup_[sourceid][type];
336 if (val_index >= 0) {
337 if (XIMaskIsSet(xiev->valuators.mask, val_index)) {
338 double* valuators = xiev->valuators.values;
339 while (val_index--) {
340 if (XIMaskIsSet(xiev->valuators.mask, val_index))
344 if (IsTouchDataType(type)) {
345 if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
346 last_seen_valuator_[sourceid][slot][type] = *value;
349 } else if (IsTouchDataType(type)) {
350 if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum)
351 *value = last_seen_valuator_[sourceid][slot][type];
358 bool DeviceDataManager::IsXIDeviceEvent(
359 const base::NativeEvent& native_event) const {
360 if (native_event->type != GenericEvent ||
361 native_event->xcookie.extension != xi_opcode_)
363 return xi_device_event_types_[native_event->xcookie.evtype];
366 bool DeviceDataManager::IsTouchpadXInputEvent(
367 const base::NativeEvent& native_event) const {
368 if (native_event->type != GenericEvent)
371 XIDeviceEvent* xievent =
372 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
373 if (xievent->sourceid >= kMaxDeviceNum)
375 return touchpads_[xievent->sourceid];
378 bool DeviceDataManager::IsCMTDeviceEvent(
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 cmt_devices_[xievent->sourceid];
390 bool DeviceDataManager::IsCMTGestureEvent(
391 const base::NativeEvent& native_event) const {
392 return (IsScrollEvent(native_event) ||
393 IsFlingEvent(native_event) ||
394 IsCMTMetricsEvent(native_event));
397 bool DeviceDataManager::HasEventData(
398 const XIDeviceEvent* xiev, const DataType type) const {
399 const int idx = valuator_lookup_[xiev->sourceid][type];
400 return (idx >= 0) && XIMaskIsSet(xiev->valuators.mask, idx);
403 bool DeviceDataManager::IsScrollEvent(
404 const base::NativeEvent& native_event) const {
405 if (!IsCMTDeviceEvent(native_event))
408 XIDeviceEvent* xiev =
409 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
410 return (HasEventData(xiev, DT_CMT_SCROLL_X) ||
411 HasEventData(xiev, DT_CMT_SCROLL_Y));
414 bool DeviceDataManager::IsFlingEvent(
415 const base::NativeEvent& native_event) const {
416 if (!IsCMTDeviceEvent(native_event))
419 XIDeviceEvent* xiev =
420 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
421 return (HasEventData(xiev, DT_CMT_FLING_X) &&
422 HasEventData(xiev, DT_CMT_FLING_Y) &&
423 HasEventData(xiev, DT_CMT_FLING_STATE));
426 bool DeviceDataManager::IsCMTMetricsEvent(
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_METRICS_TYPE) &&
434 HasEventData(xiev, DT_CMT_METRICS_DATA1) &&
435 HasEventData(xiev, DT_CMT_METRICS_DATA2));
438 bool DeviceDataManager::HasGestureTimes(
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_START_TIME) &&
446 HasEventData(xiev, DT_CMT_END_TIME));
449 void DeviceDataManager::GetScrollOffsets(const base::NativeEvent& native_event,
450 float* x_offset, float* y_offset,
451 float* x_offset_ordinal,
452 float* y_offset_ordinal,
456 *x_offset_ordinal = 0;
457 *y_offset_ordinal = 0;
461 GetEventRawData(*native_event, &data);
463 if (data.find(DT_CMT_SCROLL_X) != data.end())
464 *x_offset = data[DT_CMT_SCROLL_X];
465 if (data.find(DT_CMT_SCROLL_Y) != data.end())
466 *y_offset = data[DT_CMT_SCROLL_Y];
467 if (data.find(DT_CMT_ORDINAL_X) != data.end())
468 *x_offset_ordinal = data[DT_CMT_ORDINAL_X];
469 if (data.find(DT_CMT_ORDINAL_Y) != data.end())
470 *y_offset_ordinal = data[DT_CMT_ORDINAL_Y];
471 if (data.find(DT_CMT_FINGER_COUNT) != data.end())
472 *finger_count = static_cast<int>(data[DT_CMT_FINGER_COUNT]);
475 void DeviceDataManager::GetFlingData(const base::NativeEvent& native_event,
476 float* vx, float* vy,
477 float* vx_ordinal, float* vy_ordinal,
486 GetEventRawData(*native_event, &data);
488 if (data.find(DT_CMT_FLING_X) != data.end())
489 *vx = data[DT_CMT_FLING_X];
490 if (data.find(DT_CMT_FLING_Y) != data.end())
491 *vy = data[DT_CMT_FLING_Y];
492 if (data.find(DT_CMT_FLING_STATE) != data.end())
493 *is_cancel = !!static_cast<unsigned int>(data[DT_CMT_FLING_STATE]);
494 if (data.find(DT_CMT_ORDINAL_X) != data.end())
495 *vx_ordinal = data[DT_CMT_ORDINAL_X];
496 if (data.find(DT_CMT_ORDINAL_Y) != data.end())
497 *vy_ordinal = data[DT_CMT_ORDINAL_Y];
500 void DeviceDataManager::GetMetricsData(const base::NativeEvent& native_event,
501 GestureMetricsType* type,
502 float* data1, float* data2) {
503 *type = kGestureMetricsTypeUnknown;
508 GetEventRawData(*native_event, &data);
510 if (data.find(DT_CMT_METRICS_TYPE) != data.end()) {
511 int val = static_cast<int>(data[DT_CMT_METRICS_TYPE]);
513 *type = kGestureMetricsTypeNoisyGround;
515 *type = kGestureMetricsTypeUnknown;
517 if (data.find(DT_CMT_METRICS_DATA1) != data.end())
518 *data1 = data[DT_CMT_METRICS_DATA1];
519 if (data.find(DT_CMT_METRICS_DATA2) != data.end())
520 *data2 = data[DT_CMT_METRICS_DATA2];
523 int DeviceDataManager::GetMappedButton(int button) {
524 return button > 0 && button <= button_map_count_ ? button_map_[button - 1] :
528 void DeviceDataManager::UpdateButtonMap() {
529 button_map_count_ = XGetPointerMapping(gfx::GetXDisplay(),
531 arraysize(button_map_));
534 void DeviceDataManager::GetGestureTimes(const base::NativeEvent& native_event,
541 GetEventRawData(*native_event, &data);
543 if (data.find(DT_CMT_START_TIME) != data.end())
544 *start_time = data[DT_CMT_START_TIME];
545 if (data.find(DT_CMT_END_TIME) != data.end())
546 *end_time = data[DT_CMT_END_TIME];
549 bool DeviceDataManager::NormalizeData(unsigned int deviceid,
554 if (GetDataRange(deviceid, type, &min_value, &max_value)) {
555 *value = (*value - min_value) / (max_value - min_value);
556 DCHECK(*value >= 0.0 && *value <= 1.0);
562 bool DeviceDataManager::GetDataRange(unsigned int deviceid,
564 double* min, double* max) {
565 if (deviceid >= static_cast<unsigned int>(kMaxDeviceNum))
567 if (valuator_lookup_[deviceid][type] >= 0) {
568 *min = valuator_min_[deviceid][type];
569 *max = valuator_max_[deviceid][type];
575 void DeviceDataManager::SetDeviceListForTest(
576 const std::vector<unsigned int>& touchscreen,
577 const std::vector<unsigned int>& cmt_devices) {
578 for (int i = 0; i < kMaxDeviceNum; ++i) {
579 valuator_count_[i] = 0;
580 valuator_lookup_[i].clear();
581 data_type_lookup_[i].clear();
582 valuator_min_[i].clear();
583 valuator_max_[i].clear();
584 for (int j = 0; j < kMaxSlotNum; j++)
585 last_seen_valuator_[i][j].clear();
588 for (size_t i = 0; i < touchscreen.size(); i++) {
589 unsigned int deviceid = touchscreen[i];
590 InitializeValuatorsForTest(deviceid, kTouchDataTypeStart, kTouchDataTypeEnd,
594 cmt_devices_.reset();
595 for (size_t i = 0; i < cmt_devices.size(); ++i) {
596 unsigned int deviceid = cmt_devices[i];
597 cmt_devices_[deviceid] = true;
598 touchpads_[deviceid] = true;
599 InitializeValuatorsForTest(deviceid, kCMTDataTypeStart, kCMTDataTypeEnd,
604 void DeviceDataManager::SetValuatorDataForTest(XIDeviceEvent* xievent,
607 int index = valuator_lookup_[xievent->deviceid][type];
608 CHECK(!XIMaskIsSet(xievent->valuators.mask, index));
609 CHECK(index >= 0 && index < valuator_count_[xievent->deviceid]);
610 XISetMask(xievent->valuators.mask, index);
612 double* valuators = xievent->valuators.values;
613 for (int i = 0; i < index; ++i) {
614 if (XIMaskIsSet(xievent->valuators.mask, i))
617 for (int i = DT_LAST_ENTRY - 1; i > valuators - xievent->valuators.values;
619 xievent->valuators.values[i] = xievent->valuators.values[i - 1];
623 void DeviceDataManager::InitializeValuatorsForTest(int deviceid,
628 valuator_lookup_[deviceid].resize(DT_LAST_ENTRY, -1);
629 data_type_lookup_[deviceid].resize(DT_LAST_ENTRY, DT_LAST_ENTRY);
630 valuator_min_[deviceid].resize(DT_LAST_ENTRY, 0);
631 valuator_max_[deviceid].resize(DT_LAST_ENTRY, 0);
632 for (int j = 0; j < kMaxSlotNum; j++)
633 last_seen_valuator_[deviceid][j].resize(DT_LAST_ENTRY, 0);
634 for (int j = start_valuator; j <= end_valuator; ++j) {
635 valuator_lookup_[deviceid][j] = valuator_count_[deviceid];
636 data_type_lookup_[deviceid][valuator_count_[deviceid]] = j;
637 valuator_min_[deviceid][j] = min_value;
638 valuator_max_[deviceid][j] = max_value;
639 valuator_count_[deviceid]++;
643 bool DeviceDataManager::TouchEventNeedsCalibrate(int touch_device_id) const {
644 #if defined(OS_CHROMEOS) && defined(USE_XI2_MT)
645 int64 touch_display_id = GetDisplayForTouchDevice(touch_device_id);
646 if (base::SysInfo::IsRunningOnChromeOS() &&
647 touch_display_id == gfx::Display::InternalDisplayId()) {
650 #endif // defined(OS_CHROMEOS) && defined(USE_XI2_MT)
654 void DeviceDataManager::ClearTouchTransformerRecord() {
655 for (int i = 0; i < kMaxDeviceNum; i++) {
656 touch_device_transformer_map_[i] = gfx::Transform();
657 touch_device_to_display_map_[i] = gfx::Display::kInvalidDisplayID;
661 bool DeviceDataManager::IsTouchDeviceIdValid(int touch_device_id) const {
662 return (touch_device_id > 0 && touch_device_id < kMaxDeviceNum);
665 void DeviceDataManager::UpdateTouchInfoForDisplay(
668 const gfx::Transform& touch_transformer) {
669 if (IsTouchDeviceIdValid(touch_device_id)) {
670 touch_device_to_display_map_[touch_device_id] = display_id;
671 touch_device_transformer_map_[touch_device_id] = touch_transformer;
675 void DeviceDataManager::ApplyTouchTransformer(int touch_device_id,
676 float* x, float* y) {
677 if (IsTouchDeviceIdValid(touch_device_id)) {
678 gfx::Point3F point(*x, *y, 0.0);
679 const gfx::Transform& trans =
680 touch_device_transformer_map_[touch_device_id];
681 trans.TransformPoint(&point);
687 int64 DeviceDataManager::GetDisplayForTouchDevice(int touch_device_id) const {
688 if (IsTouchDeviceIdValid(touch_device_id))
689 return touch_device_to_display_map_[touch_device_id];
690 return gfx::Display::kInvalidDisplayID;