| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/events/ozone/evdev/event_factory_evdev.h" | 5 #include "ui/events/ozone/evdev/event_factory_evdev.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | |
| 8 #include <linux/input.h> | |
| 9 | |
| 10 #include "base/bind.h" | 7 #include "base/bind.h" |
| 11 #include "base/stl_util.h" | 8 #include "base/debug/trace_event.h" |
| 12 #include "base/task_runner.h" | 9 #include "base/task_runner.h" |
| 13 #include "base/thread_task_runner_handle.h" | 10 #include "base/thread_task_runner_handle.h" |
| 14 #include "base/threading/worker_pool.h" | 11 #include "base/threading/worker_pool.h" |
| 15 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 16 #include "base/trace_event/trace_event.h" | |
| 17 #include "ui/events/devices/device_data_manager.h" | 13 #include "ui/events/devices/device_data_manager.h" |
| 18 #include "ui/events/devices/device_util_linux.h" | |
| 19 #include "ui/events/devices/input_device.h" | 14 #include "ui/events/devices/input_device.h" |
| 20 #include "ui/events/ozone/device/device_event.h" | 15 #include "ui/events/ozone/device/device_event.h" |
| 21 #include "ui/events/ozone/device/device_manager.h" | 16 #include "ui/events/ozone/device/device_manager.h" |
| 22 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h" | 17 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h" |
| 23 #include "ui/events/ozone/evdev/event_converter_evdev_impl.h" | 18 #include "ui/events/ozone/evdev/input_controller_evdev.h" |
| 19 #include "ui/events/ozone/evdev/input_device_factory_evdev.h" |
| 24 #include "ui/events/ozone/evdev/input_injector_evdev.h" | 20 #include "ui/events/ozone/evdev/input_injector_evdev.h" |
| 25 #include "ui/events/ozone/evdev/tablet_event_converter_evdev.h" | |
| 26 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" | |
| 27 | 21 |
| 28 #if defined(USE_EVDEV_GESTURES) | 22 #if defined(USE_EVDEV_GESTURES) |
| 29 #include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h" | |
| 30 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cr
os.h" | |
| 31 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h" | 23 #include "ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.h" |
| 32 #endif | 24 #endif |
| 33 | 25 |
| 34 #ifndef EVIOCSCLOCKID | |
| 35 #define EVIOCSCLOCKID _IOW('E', 0xa0, int) | |
| 36 #endif | |
| 37 | |
| 38 namespace ui { | 26 namespace ui { |
| 39 | 27 |
| 40 namespace { | |
| 41 | |
| 42 typedef base::Callback<void(scoped_ptr<EventConverterEvdev>)> | |
| 43 OpenInputDeviceReplyCallback; | |
| 44 | |
| 45 struct OpenInputDeviceParams { | |
| 46 // Unique identifier for the new device. | |
| 47 int id; | |
| 48 | |
| 49 // Device path to open. | |
| 50 base::FilePath path; | |
| 51 | |
| 52 // Dispatcher for events. Call on UI thread only. | |
| 53 DeviceEventDispatcherEvdev* dispatcher; | |
| 54 | |
| 55 // State shared between devices. Must not be dereferenced on worker thread. | |
| 56 CursorDelegateEvdev* cursor; | |
| 57 #if defined(USE_EVDEV_GESTURES) | |
| 58 GesturePropertyProvider* gesture_property_provider; | |
| 59 #endif | |
| 60 }; | |
| 61 | |
| 62 #if defined(USE_EVDEV_GESTURES) | |
| 63 bool UseGesturesLibraryForDevice(const EventDeviceInfo& devinfo) { | |
| 64 if (devinfo.HasTouchpad()) | |
| 65 return true; | |
| 66 | |
| 67 if (devinfo.HasRelXY()) | |
| 68 return true; // mouse | |
| 69 | |
| 70 return false; | |
| 71 } | |
| 72 #endif | |
| 73 | |
| 74 scoped_ptr<EventConverterEvdev> CreateConverter( | |
| 75 const OpenInputDeviceParams& params, | |
| 76 int fd, | |
| 77 InputDeviceType type, | |
| 78 const EventDeviceInfo& devinfo) { | |
| 79 #if defined(USE_EVDEV_GESTURES) | |
| 80 // Touchpad or mouse: use gestures library. | |
| 81 // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent | |
| 82 if (UseGesturesLibraryForDevice(devinfo)) { | |
| 83 scoped_ptr<GestureInterpreterLibevdevCros> gesture_interp = | |
| 84 make_scoped_ptr(new GestureInterpreterLibevdevCros( | |
| 85 params.id, params.cursor, params.gesture_property_provider, | |
| 86 params.dispatcher)); | |
| 87 return make_scoped_ptr(new EventReaderLibevdevCros( | |
| 88 fd, params.path, params.id, type, devinfo, gesture_interp.Pass())); | |
| 89 } | |
| 90 #endif | |
| 91 | |
| 92 // Touchscreen: use TouchEventConverterEvdev. | |
| 93 if (devinfo.HasMTAbsXY()) { | |
| 94 scoped_ptr<TouchEventConverterEvdev> converter(new TouchEventConverterEvdev( | |
| 95 fd, params.path, params.id, type, params.dispatcher)); | |
| 96 converter->Initialize(devinfo); | |
| 97 return converter.Pass(); | |
| 98 } | |
| 99 | |
| 100 // Graphics tablet | |
| 101 if (devinfo.HasAbsXY()) | |
| 102 return make_scoped_ptr<EventConverterEvdev>(new TabletEventConverterEvdev( | |
| 103 fd, params.path, params.id, type, params.cursor, devinfo, | |
| 104 params.dispatcher)); | |
| 105 | |
| 106 // Everything else: use EventConverterEvdevImpl. | |
| 107 return make_scoped_ptr<EventConverterEvdevImpl>( | |
| 108 new EventConverterEvdevImpl(fd, params.path, params.id, type, devinfo, | |
| 109 params.cursor, params.dispatcher)); | |
| 110 } | |
| 111 | |
| 112 // Open an input device. Opening may put the calling thread to sleep, and | |
| 113 // therefore should be run on a thread where latency is not critical. We | |
| 114 // run it on a thread from the worker pool. | |
| 115 // | |
| 116 // This takes a TaskRunner and runs the reply on that thread, so that we | |
| 117 // can hop threads if necessary (back to the UI thread). | |
| 118 void OpenInputDevice(scoped_ptr<OpenInputDeviceParams> params, | |
| 119 scoped_refptr<base::TaskRunner> reply_runner, | |
| 120 const OpenInputDeviceReplyCallback& reply_callback) { | |
| 121 const base::FilePath& path = params->path; | |
| 122 | |
| 123 TRACE_EVENT1("ozone", "OpenInputDevice", "path", path.value()); | |
| 124 | |
| 125 int fd = open(path.value().c_str(), O_RDONLY | O_NONBLOCK); | |
| 126 if (fd < 0) { | |
| 127 PLOG(ERROR) << "Cannot open '" << path.value(); | |
| 128 return; | |
| 129 } | |
| 130 | |
| 131 // Use monotonic timestamps for events. The touch code in particular | |
| 132 // expects event timestamps to correlate to the monotonic clock | |
| 133 // (base::TimeTicks). | |
| 134 unsigned int clk = CLOCK_MONOTONIC; | |
| 135 if (ioctl(fd, EVIOCSCLOCKID, &clk)) | |
| 136 PLOG(ERROR) << "failed to set CLOCK_MONOTONIC"; | |
| 137 | |
| 138 EventDeviceInfo devinfo; | |
| 139 if (!devinfo.Initialize(fd)) { | |
| 140 LOG(ERROR) << "failed to get device information for " << path.value(); | |
| 141 close(fd); | |
| 142 return; | |
| 143 } | |
| 144 | |
| 145 InputDeviceType type = GetInputDeviceTypeFromPath(path); | |
| 146 | |
| 147 scoped_ptr<EventConverterEvdev> converter = | |
| 148 CreateConverter(*params, fd, type, devinfo); | |
| 149 | |
| 150 // Reply with the constructed converter. | |
| 151 reply_runner->PostTask(FROM_HERE, | |
| 152 base::Bind(reply_callback, base::Passed(&converter))); | |
| 153 } | |
| 154 | |
| 155 // Close an input device. Closing may put the calling thread to sleep, and | |
| 156 // therefore should be run on a thread where latency is not critical. We | |
| 157 // run it on the FILE thread. | |
| 158 void CloseInputDevice(const base::FilePath& path, | |
| 159 scoped_ptr<EventConverterEvdev> converter) { | |
| 160 TRACE_EVENT1("ozone", "CloseInputDevice", "path", path.value()); | |
| 161 converter.reset(); | |
| 162 } | |
| 163 | |
| 164 } // namespace | |
| 165 | |
| 166 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor, | 28 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor, |
| 167 DeviceManager* device_manager, | 29 DeviceManager* device_manager, |
| 168 KeyboardLayoutEngine* keyboard_layout) | 30 KeyboardLayoutEngine* keyboard_layout) |
| 169 : last_device_id_(0), | 31 : last_device_id_(0), |
| 170 device_manager_(device_manager), | 32 device_manager_(device_manager), |
| 171 dispatch_callback_( | 33 dispatch_callback_( |
| 172 base::Bind(&EventFactoryEvdev::PostUiEvent, base::Unretained(this))), | 34 base::Bind(&EventFactoryEvdev::PostUiEvent, base::Unretained(this))), |
| 173 keyboard_(&modifiers_, keyboard_layout, dispatch_callback_), | 35 keyboard_(&modifiers_, keyboard_layout, dispatch_callback_), |
| 174 cursor_(cursor), | 36 cursor_(cursor), |
| 175 #if defined(USE_EVDEV_GESTURES) | 37 #if defined(USE_EVDEV_GESTURES) |
| 176 gesture_property_provider_(new GesturePropertyProvider), | 38 gesture_property_provider_(new GesturePropertyProvider), |
| 177 #endif | 39 #endif |
| 178 input_controller_(this, | 40 input_controller_(&keyboard_, |
| 179 &keyboard_, | |
| 180 &button_map_ | 41 &button_map_ |
| 181 #if defined(USE_EVDEV_GESTURES) | 42 #if defined(USE_EVDEV_GESTURES) |
| 182 , | 43 , |
| 183 gesture_property_provider_.get() | 44 gesture_property_provider_.get() |
| 184 #endif | 45 #endif |
| 185 ), | 46 ), |
| 186 initialized_(false), | 47 initialized_(false), |
| 187 weak_ptr_factory_(this) { | 48 weak_ptr_factory_(this) { |
| 188 DCHECK(device_manager_); | 49 DCHECK(device_manager_); |
| 189 } | 50 } |
| 190 | 51 |
| 191 EventFactoryEvdev::~EventFactoryEvdev() { STLDeleteValues(&converters_); } | 52 EventFactoryEvdev::~EventFactoryEvdev() { |
| 53 } |
| 192 | 54 |
| 193 void EventFactoryEvdev::Init() { | 55 void EventFactoryEvdev::Init() { |
| 194 DCHECK(!initialized_); | 56 DCHECK(!initialized_); |
| 195 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 57 |
| 58 // Set up device factory. |
| 59 input_device_factory_.reset( |
| 60 new InputDeviceFactoryEvdev(this, base::ThreadTaskRunnerHandle::Get(), |
| 61 #if defined(USE_EVDEV_GESTURES) |
| 62 gesture_property_provider_.get(), |
| 63 #endif |
| 64 cursor_)); |
| 65 // TODO(spang): This settings interface is really broken. crbug.com/450899 |
| 66 input_controller_.SetInputDeviceFactory(input_device_factory_.get()); |
| 196 | 67 |
| 197 // Scan & monitor devices. | 68 // Scan & monitor devices. |
| 198 device_manager_->AddObserver(this); | 69 device_manager_->AddObserver(this); |
| 199 device_manager_->ScanDevices(this); | 70 device_manager_->ScanDevices(this); |
| 200 | 71 |
| 201 initialized_ = true; | 72 initialized_ = true; |
| 202 } | 73 } |
| 203 | 74 |
| 204 scoped_ptr<SystemInputInjector> EventFactoryEvdev::CreateSystemInputInjector() { | 75 scoped_ptr<SystemInputInjector> EventFactoryEvdev::CreateSystemInputInjector() { |
| 205 return make_scoped_ptr(new InputInjectorEvdev( | 76 return make_scoped_ptr(new InputInjectorEvdev( |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 FROM_HERE, | 169 FROM_HERE, |
| 299 base::Bind(&EventFactoryEvdev::DispatchUiEventTask, | 170 base::Bind(&EventFactoryEvdev::DispatchUiEventTask, |
| 300 weak_ptr_factory_.GetWeakPtr(), | 171 weak_ptr_factory_.GetWeakPtr(), |
| 301 base::Passed(&event))); | 172 base::Passed(&event))); |
| 302 } | 173 } |
| 303 | 174 |
| 304 void EventFactoryEvdev::DispatchUiEventTask(scoped_ptr<Event> event) { | 175 void EventFactoryEvdev::DispatchUiEventTask(scoped_ptr<Event> event) { |
| 305 DispatchEvent(event.get()); | 176 DispatchEvent(event.get()); |
| 306 } | 177 } |
| 307 | 178 |
| 308 void EventFactoryEvdev::AttachInputDevice( | |
| 309 scoped_ptr<EventConverterEvdev> converter) { | |
| 310 const base::FilePath& path = converter->path(); | |
| 311 | |
| 312 TRACE_EVENT1("ozone", "AttachInputDevice", "path", path.value()); | |
| 313 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 314 | |
| 315 // If we have an existing device, detach it. We don't want two | |
| 316 // devices with the same name open at the same time. | |
| 317 if (converters_[path]) | |
| 318 DetachInputDevice(path); | |
| 319 | |
| 320 // Add initialized device to map. | |
| 321 converters_[path] = converter.release(); | |
| 322 converters_[path]->Start(); | |
| 323 | |
| 324 NotifyDeviceChange(*converters_[path]); | |
| 325 } | |
| 326 | |
| 327 void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent& event) { | 179 void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent& event) { |
| 328 if (event.device_type() != DeviceEvent::INPUT) | 180 if (event.device_type() != DeviceEvent::INPUT) |
| 329 return; | 181 return; |
| 330 | 182 |
| 331 switch (event.action_type()) { | 183 switch (event.action_type()) { |
| 332 case DeviceEvent::ADD: | 184 case DeviceEvent::ADD: |
| 333 case DeviceEvent::CHANGE: { | 185 case DeviceEvent::CHANGE: { |
| 334 TRACE_EVENT1("ozone", "OnDeviceAdded", "path", event.path().value()); | 186 TRACE_EVENT1("ozone", "OnDeviceAdded", "path", event.path().value()); |
| 335 | 187 input_device_factory_->AddInputDevice(NextDeviceId(), event.path()); |
| 336 scoped_ptr<OpenInputDeviceParams> params(new OpenInputDeviceParams); | 188 break; |
| 337 params->id = NextDeviceId(); | |
| 338 params->path = event.path(); | |
| 339 params->cursor = cursor_; | |
| 340 params->dispatcher = this; | |
| 341 | |
| 342 #if defined(USE_EVDEV_GESTURES) | |
| 343 params->gesture_property_provider = gesture_property_provider_.get(); | |
| 344 #endif | |
| 345 | |
| 346 OpenInputDeviceReplyCallback reply_callback = | |
| 347 base::Bind(&EventFactoryEvdev::AttachInputDevice, | |
| 348 weak_ptr_factory_.GetWeakPtr()); | |
| 349 | |
| 350 // Dispatch task to open from the worker pool, since open may block. | |
| 351 base::WorkerPool::PostTask(FROM_HERE, | |
| 352 base::Bind(&OpenInputDevice, | |
| 353 base::Passed(¶ms), | |
| 354 ui_task_runner_, | |
| 355 reply_callback), | |
| 356 true /* task_is_slow */); | |
| 357 } | 189 } |
| 358 break; | |
| 359 case DeviceEvent::REMOVE: { | 190 case DeviceEvent::REMOVE: { |
| 360 TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event.path().value()); | 191 TRACE_EVENT1("ozone", "OnDeviceRemoved", "path", event.path().value()); |
| 361 DetachInputDevice(event.path()); | 192 input_device_factory_->RemoveInputDevice(event.path()); |
| 193 break; |
| 362 } | 194 } |
| 363 break; | |
| 364 } | 195 } |
| 365 } | 196 } |
| 366 | 197 |
| 367 void EventFactoryEvdev::OnDispatcherListChanged() { | 198 void EventFactoryEvdev::OnDispatcherListChanged() { |
| 368 if (!initialized_) | 199 if (!initialized_) |
| 369 Init(); | 200 Init(); |
| 370 } | 201 } |
| 371 | 202 |
| 372 void EventFactoryEvdev::DetachInputDevice(const base::FilePath& path) { | |
| 373 TRACE_EVENT1("ozone", "DetachInputDevice", "path", path.value()); | |
| 374 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | |
| 375 | |
| 376 // Remove device from map. | |
| 377 scoped_ptr<EventConverterEvdev> converter(converters_[path]); | |
| 378 converters_.erase(path); | |
| 379 | |
| 380 if (converter) { | |
| 381 // Cancel libevent notifications from this converter. This part must be | |
| 382 // on UI since the polling happens on UI. | |
| 383 converter->Stop(); | |
| 384 | |
| 385 NotifyDeviceChange(*converter); | |
| 386 | |
| 387 // Dispatch task to close from the worker pool, since close may block. | |
| 388 base::WorkerPool::PostTask( | |
| 389 FROM_HERE, | |
| 390 base::Bind(&CloseInputDevice, path, base::Passed(&converter)), | |
| 391 true); | |
| 392 } | |
| 393 } | |
| 394 | |
| 395 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget, | 203 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget, |
| 396 const gfx::PointF& location) { | 204 const gfx::PointF& location) { |
| 397 if (cursor_) { | 205 if (cursor_) { |
| 398 cursor_->MoveCursorTo(widget, location); | 206 cursor_->MoveCursorTo(widget, location); |
| 399 PostUiEvent(make_scoped_ptr(new MouseEvent(ET_MOUSE_MOVED, | 207 PostUiEvent(make_scoped_ptr(new MouseEvent(ET_MOUSE_MOVED, |
| 400 cursor_->GetLocation(), | 208 cursor_->GetLocation(), |
| 401 cursor_->GetLocation(), | 209 cursor_->GetLocation(), |
| 402 modifiers_.GetModifierFlags(), | 210 modifiers_.GetModifierFlags(), |
| 403 /* changed_button_flags */ 0))); | 211 /* changed_button_flags */ 0))); |
| 404 } | 212 } |
| 405 } | 213 } |
| 406 | 214 |
| 407 void EventFactoryEvdev::DisableInternalTouchpad() { | |
| 408 for (const auto& it : converters_) { | |
| 409 EventConverterEvdev* converter = it.second; | |
| 410 if (converter->type() == InputDeviceType::INPUT_DEVICE_INTERNAL && | |
| 411 converter->HasTouchpad()) { | |
| 412 DCHECK(!converter->HasKeyboard()); | |
| 413 converter->set_ignore_events(true); | |
| 414 } | |
| 415 } | |
| 416 } | |
| 417 | |
| 418 void EventFactoryEvdev::EnableInternalTouchpad() { | |
| 419 for (const auto& it : converters_) { | |
| 420 EventConverterEvdev* converter = it.second; | |
| 421 if (converter->type() == InputDeviceType::INPUT_DEVICE_INTERNAL && | |
| 422 converter->HasTouchpad()) { | |
| 423 DCHECK(!converter->HasKeyboard()); | |
| 424 converter->set_ignore_events(false); | |
| 425 } | |
| 426 } | |
| 427 } | |
| 428 | |
| 429 void EventFactoryEvdev::DisableInternalKeyboardExceptKeys( | |
| 430 scoped_ptr<std::set<DomCode>> excepted_keys) { | |
| 431 for (const auto& it : converters_) { | |
| 432 EventConverterEvdev* converter = it.second; | |
| 433 if (converter->type() == InputDeviceType::INPUT_DEVICE_INTERNAL && | |
| 434 converter->HasKeyboard()) { | |
| 435 converter->SetAllowedKeys(excepted_keys.Pass()); | |
| 436 } | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 void EventFactoryEvdev::EnableInternalKeyboard() { | |
| 441 for (const auto& it : converters_) { | |
| 442 EventConverterEvdev* converter = it.second; | |
| 443 if (converter->type() == InputDeviceType::INPUT_DEVICE_INTERNAL && | |
| 444 converter->HasKeyboard()) { | |
| 445 converter->AllowAllKeys(); | |
| 446 } | |
| 447 } | |
| 448 } | |
| 449 | |
| 450 void EventFactoryEvdev::NotifyDeviceChange( | |
| 451 const EventConverterEvdev& converter) { | |
| 452 if (converter.HasTouchscreen()) | |
| 453 NotifyTouchscreensUpdated(); | |
| 454 | |
| 455 if (converter.HasKeyboard()) | |
| 456 NotifyKeyboardsUpdated(); | |
| 457 } | |
| 458 | |
| 459 void EventFactoryEvdev::NotifyTouchscreensUpdated() { | |
| 460 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); | |
| 461 std::vector<TouchscreenDevice> touchscreens; | |
| 462 for (auto it = converters_.begin(); it != converters_.end(); ++it) { | |
| 463 if (it->second->HasTouchscreen()) { | |
| 464 // TODO(spang): Extract the number of touch-points supported by the | |
| 465 // device. | |
| 466 const int touch_points = 11; | |
| 467 touchscreens.push_back(TouchscreenDevice( | |
| 468 it->second->id(), it->second->type(), std::string() /* Device name */, | |
| 469 it->second->GetTouchscreenSize(), touch_points)); | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 observer->OnTouchscreenDevicesUpdated(touchscreens); | |
| 474 } | |
| 475 | |
| 476 void EventFactoryEvdev::NotifyKeyboardsUpdated() { | |
| 477 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); | |
| 478 std::vector<KeyboardDevice> keyboards; | |
| 479 for (auto it = converters_.begin(); it != converters_.end(); ++it) { | |
| 480 if (it->second->HasKeyboard()) { | |
| 481 keyboards.push_back(KeyboardDevice(it->second->id(), it->second->type(), | |
| 482 std::string() /* Device name */)); | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 observer->OnKeyboardDevicesUpdated(keyboards); | |
| 487 } | |
| 488 | |
| 489 int EventFactoryEvdev::NextDeviceId() { | 215 int EventFactoryEvdev::NextDeviceId() { |
| 490 return ++last_device_id_; | 216 return ++last_device_id_; |
| 491 } | 217 } |
| 492 | 218 |
| 493 bool EventFactoryEvdev::GetDeviceIdsByType(const EventDeviceType type, | |
| 494 std::vector<int>* device_ids) { | |
| 495 if (device_ids) | |
| 496 device_ids->clear(); | |
| 497 std::vector<int> ids; | |
| 498 | |
| 499 #if defined(USE_EVDEV_GESTURES) | |
| 500 // Ask GesturePropertyProvider for matching devices. | |
| 501 gesture_property_provider_->GetDeviceIdsByType(type, &ids); | |
| 502 #endif | |
| 503 // In the future we can add other device matching logics here. | |
| 504 | |
| 505 if (device_ids) | |
| 506 device_ids->assign(ids.begin(), ids.end()); | |
| 507 return !ids.empty(); | |
| 508 } | |
| 509 | |
| 510 } // namespace ui | 219 } // namespace ui |
| OLD | NEW |