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. 4 5 #include "ui/events/x/device_data_manager_x11.h" 6 7 #include <X11/extensions/XInput.h> 8 #include <X11/extensions/XInput2.h> 9 #include <X11/Xlib.h> 10 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" 22 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 27 #endif 28 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 35 #endif 36 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" 40 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" 44 45 // Ordinal values 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" 48 49 // Fling properties 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" 53 54 #define AXIS_LABEL_PROP_ABS_FINGER_COUNT "Abs Finger Count" 55 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" 60 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" 70 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, 96 97 NULL 98 }; 99 100 // Constants for checking if a data type lies in the range of CMT/Touch data 101 // types. 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; 106 107 namespace ui { 108 109 bool DeviceDataManagerX11::IsCMTDataType(const int type) { 110 return (type >= kCMTDataTypeStart) && (type <= kCMTDataTypeEnd); 111 } 112 113 bool DeviceDataManagerX11::IsTouchDataType(const int type) { 114 return (type >= kTouchDataTypeStart) && (type <= kTouchDataTypeEnd); 115 } 116 117 // static 118 void DeviceDataManagerX11::CreateInstance() { 119 if (instance()) 120 return; 121 122 new DeviceDataManagerX11(); 123 } 124 125 // static 126 DeviceDataManagerX11* DeviceDataManagerX11::GetInstance() { 127 return static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance()); 128 } 129 130 DeviceDataManagerX11::DeviceDataManagerX11() 131 : xi_opcode_(-1), 132 atom_cache_(gfx::GetXDisplay(), kCachedAtoms), 133 button_map_count_(0) { 134 CHECK(gfx::GetXDisplay()); 135 InitializeXInputInternal(); 136 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()); 140 UpdateButtonMap(); 141 } 142 143 DeviceDataManagerX11::~DeviceDataManagerX11() { 144 } 145 146 bool DeviceDataManagerX11::InitializeXInputInternal() { 147 // Check if XInput is available on the system. 148 xi_opcode_ = -1; 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; 153 return false; 154 } 155 156 // Check the XInput version. 157 #if defined(USE_XI2_MT) 158 int major = 2, minor = USE_XI2_MT; 159 #else 160 int major = 2, minor = 0; 161 #endif 162 if (XIQueryVersion(gfx::GetXDisplay(), &major, &minor) == BadRequest) { 163 VLOG(1) << "XInput2 not supported in the server."; 164 return false; 165 } 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."; 170 return false; 171 } 172 #endif 173 174 xi_opcode_ = opcode; 175 CHECK_NE(-1, xi_opcode_); 176 177 // Possible XI event types for XIDeviceEvent. See the XI2 protocol 178 // specification. 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. 185 if (minor >= 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; 189 } 190 return true; 191 } 192 193 bool DeviceDataManagerX11::IsXInput2Available() const { 194 return xi_opcode_ != -1; 195 } 196 197 void DeviceDataManagerX11::UpdateDeviceList(Display* display) { 198 cmt_devices_.reset(); 199 touchpads_.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(); 208 } 209 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; 217 218 if (!IsXInput2Available()) 219 return; 220 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]); 227 228 for (int i = 0; i < info_list.count; ++i) { 229 XIDeviceInfo* info = info_list.devices + i; 230 231 // We currently handle only slave, non-keyboard devices 232 if (info->use != XISlavePointer && info->use != XIFloatingSlave) 233 continue; 234 235 bool possible_cmt = false; 236 bool not_cmt = false; 237 const int deviceid = info->deviceid; 238 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) 243 not_cmt = true; 244 } 245 246 // Skip devices that don't use any valuator 247 if (!valuator_count_[deviceid]) 248 continue; 249 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) 259 continue; 260 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)) 270 possible_cmt = true; 271 break; 272 } 273 } 274 } 275 276 if (possible_cmt && !not_cmt) 277 cmt_devices_[deviceid] = true; 278 } 279 } 280 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)) { 285 *slot = 0; 286 return true; 287 } 288 return factory->QuerySlotForTrackingID(xiev->detail, slot); 289 #else 290 *slot = 0; 291 return true; 292 #endif 293 } 294 295 void DeviceDataManagerX11::GetEventRawData(const XEvent& xev, EventData* data) { 296 if (xev.type != GenericEvent) 297 return; 298 299 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); 300 if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum) 301 return; 302 data->clear(); 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)) { 311 int slot = -1; 312 if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum) 313 last_seen_valuator_[sourceid][slot][type] = *valuators; 314 } 315 } 316 valuators++; 317 } 318 } 319 } 320 321 bool DeviceDataManagerX11::GetEventData(const XEvent& xev, 322 const DataType type, double* value) { 323 if (xev.type != GenericEvent) 324 return false; 325 326 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); 327 if (xiev->sourceid >= kMaxDeviceNum || xiev->deviceid >= kMaxDeviceNum) 328 return false; 329 const int sourceid = xiev->sourceid; 330 if (valuator_lookup_[sourceid].empty()) 331 return false; 332 333 if (type == DT_TOUCH_TRACKING_ID) { 334 // With XInput2 MT, Tracking ID is provided in the detail field for touch 335 // events. 336 if (xiev->evtype == XI_TouchBegin || 337 xiev->evtype == XI_TouchEnd || 338 xiev->evtype == XI_TouchUpdate) { 339 *value = xiev->detail; 340 } else { 341 *value = 0; 342 } 343 return true; 344 } 345 346 int val_index = valuator_lookup_[sourceid][type]; 347 int slot = 0; 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)) 353 ++valuators; 354 } 355 *value = *valuators; 356 if (IsTouchDataType(type)) { 357 if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum) 358 last_seen_valuator_[sourceid][slot][type] = *value; 359 } 360 return true; 361 } else if (IsTouchDataType(type)) { 362 if (GetSlotNumber(xiev, &slot) && slot >= 0 && slot < kMaxSlotNum) 363 *value = last_seen_valuator_[sourceid][slot][type]; 364 } 365 } 366 367 return false; 368 } 369 370 bool DeviceDataManagerX11::IsXIDeviceEvent( 371 const base::NativeEvent& native_event) const { 372 if (native_event->type != GenericEvent || 373 native_event->xcookie.extension != xi_opcode_) 374 return false; 375 return xi_device_event_types_[native_event->xcookie.evtype]; 376 } 377 378 bool DeviceDataManagerX11::IsTouchpadXInputEvent( 379 const base::NativeEvent& native_event) const { 380 if (native_event->type != GenericEvent) 381 return false; 382 383 XIDeviceEvent* xievent = 384 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 385 if (xievent->sourceid >= kMaxDeviceNum) 386 return false; 387 return touchpads_[xievent->sourceid]; 388 } 389 390 bool DeviceDataManagerX11::IsCMTDeviceEvent( 391 const base::NativeEvent& native_event) const { 392 if (native_event->type != GenericEvent) 393 return false; 394 395 XIDeviceEvent* xievent = 396 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 397 if (xievent->sourceid >= kMaxDeviceNum) 398 return false; 399 return cmt_devices_[xievent->sourceid]; 400 } 401 402 bool DeviceDataManagerX11::IsCMTGestureEvent( 403 const base::NativeEvent& native_event) const { 404 return (IsScrollEvent(native_event) || 405 IsFlingEvent(native_event) || 406 IsCMTMetricsEvent(native_event)); 407 } 408 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); 413 } 414 415 bool DeviceDataManagerX11::IsScrollEvent( 416 const base::NativeEvent& native_event) const { 417 if (!IsCMTDeviceEvent(native_event)) 418 return false; 419 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)); 424 } 425 426 bool DeviceDataManagerX11::IsFlingEvent( 427 const base::NativeEvent& native_event) const { 428 if (!IsCMTDeviceEvent(native_event)) 429 return false; 430 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)); 436 } 437 438 bool DeviceDataManagerX11::IsCMTMetricsEvent( 439 const base::NativeEvent& native_event) const { 440 if (!IsCMTDeviceEvent(native_event)) 441 return false; 442 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)); 448 } 449 450 bool DeviceDataManagerX11::HasGestureTimes( 451 const base::NativeEvent& native_event) const { 452 if (!IsCMTDeviceEvent(native_event)) 453 return false; 454 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)); 459 } 460 461 void DeviceDataManagerX11::GetScrollOffsets( 462 const base::NativeEvent& native_event, 463 float* x_offset, 464 float* y_offset, 465 float* x_offset_ordinal, 466 float* y_offset_ordinal, 467 int* finger_count) { 468 *x_offset = 0; 469 *y_offset = 0; 470 *x_offset_ordinal = 0; 471 *y_offset_ordinal = 0; 472 *finger_count = 2; 473 474 EventData data; 475 GetEventRawData(*native_event, &data); 476 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]); 487 } 488 489 void DeviceDataManagerX11::GetFlingData( 490 const base::NativeEvent& native_event, 491 float* vx, 492 float* vy, 493 float* vx_ordinal, 494 float* vy_ordinal, 495 bool* is_cancel) { 496 *vx = 0; 497 *vy = 0; 498 *vx_ordinal = 0; 499 *vy_ordinal = 0; 500 *is_cancel = false; 501 502 EventData data; 503 GetEventRawData(*native_event, &data); 504 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]; 515 } 516 517 void DeviceDataManagerX11::GetMetricsData( 518 const base::NativeEvent& native_event, 519 GestureMetricsType* type, 520 float* data1, 521 float* data2) { 522 *type = kGestureMetricsTypeUnknown; 523 *data1 = 0; 524 *data2 = 0; 525 526 EventData data; 527 GetEventRawData(*native_event, &data); 528 529 if (data.find(DT_CMT_METRICS_TYPE) != data.end()) { 530 int val = static_cast<int>(data[DT_CMT_METRICS_TYPE]); 531 if (val == 0) 532 *type = kGestureMetricsTypeNoisyGround; 533 else 534 *type = kGestureMetricsTypeUnknown; 535 } 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]; 540 } 541 542 int DeviceDataManagerX11::GetMappedButton(int button) { 543 return button > 0 && button <= button_map_count_ ? button_map_[button - 1] : 544 button; 545 } 546 547 void DeviceDataManagerX11::UpdateButtonMap() { 548 button_map_count_ = XGetPointerMapping(gfx::GetXDisplay(), 549 button_map_, 550 arraysize(button_map_)); 551 } 552 553 void DeviceDataManagerX11::GetGestureTimes( 554 const base::NativeEvent& native_event, 555 double* start_time, 556 double* end_time) { 557 *start_time = 0; 558 *end_time = 0; 559 560 EventData data; 561 GetEventRawData(*native_event, &data); 562 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]; 567 } 568 569 bool DeviceDataManagerX11::NormalizeData(unsigned int deviceid, 570 const DataType type, 571 double* value) { 572 double max_value; 573 double min_value; 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); 577 return true; 578 } 579 return false; 580 } 581 582 bool DeviceDataManagerX11::GetDataRange(unsigned int deviceid, 583 const DataType type, 584 double* min, 585 double* max) { 586 if (deviceid >= static_cast<unsigned int>(kMaxDeviceNum)) 587 return false; 588 if (valuator_lookup_[deviceid][type] >= 0) { 589 *min = valuator_min_[deviceid][type]; 590 *max = valuator_max_[deviceid][type]; 591 return true; 592 } 593 return false; 594 } 595 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(); 607 } 608 609 for (size_t i = 0; i < touchscreen.size(); i++) { 610 unsigned int deviceid = touchscreen[i]; 611 InitializeValuatorsForTest(deviceid, kTouchDataTypeStart, kTouchDataTypeEnd, 612 0, 1000); 613 } 614 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, 621 -1000, 1000); 622 } 623 } 624 625 void DeviceDataManagerX11::SetValuatorDataForTest(XIDeviceEvent* xievent, 626 DataType type, 627 double value) { 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); 632 633 double* valuators = xievent->valuators.values; 634 for (int i = 0; i < index; ++i) { 635 if (XIMaskIsSet(xievent->valuators.mask, i)) 636 valuators++; 637 } 638 for (int i = DT_LAST_ENTRY - 1; i > valuators - xievent->valuators.values; 639 --i) 640 xievent->valuators.values[i] = xievent->valuators.values[i - 1]; 641 *valuators = value; 642 } 643 644 void DeviceDataManagerX11::InitializeValuatorsForTest(int deviceid, 645 int start_valuator, 646 int end_valuator, 647 double min_value, 648 double max_value) { 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]++; 661 } 662 } 663 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()) { 669 return true; 670 } 671 #endif // defined(OS_CHROMEOS) && defined(USE_XI2_MT) 672 return false; 673 } 674 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(); 680 } 681 682 void DeviceDataManagerX11::DisableDevice(unsigned int deviceid) { 683 blocked_devices_.set(deviceid, true); 684 } 685 686 void DeviceDataManagerX11::EnableDevice(unsigned int deviceid) { 687 blocked_devices_.set(deviceid, false); 688 } 689 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) 694 return false; 695 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()) { 704 return false; 705 } 706 707 return blocked_devices_.test(xievent->sourceid); 708 } 709 710 } // namespace ui 711