OLD | NEW |
(Empty) | |
| 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/ozone/evdev/event_factory_evdev.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/task_runner.h" |
| 9 #include "base/thread_task_runner_handle.h" |
| 10 #include "base/threading/worker_pool.h" |
| 11 #include "base/time/time.h" |
| 12 #include "base/trace_event/trace_event.h" |
| 13 #include "ui/events/devices/device_data_manager.h" |
| 14 #include "ui/events/devices/input_device.h" |
| 15 #include "ui/events/event_utils.h" |
| 16 #include "ui/events/ozone/device/device_event.h" |
| 17 #include "ui/events/ozone/device/device_manager.h" |
| 18 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h" |
| 19 #include "ui/events/ozone/evdev/input_controller_evdev.h" |
| 20 #include "ui/events/ozone/evdev/input_device_factory_evdev.h" |
| 21 #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h" |
| 22 #include "ui/events/ozone/evdev/input_injector_evdev.h" |
| 23 #include "ui/events/ozone/evdev/touch_evdev_types.h" |
| 24 |
| 25 namespace ui { |
| 26 |
| 27 namespace { |
| 28 |
| 29 // Thread safe dispatcher proxy for EventFactoryEvdev. |
| 30 // |
| 31 // This is used on the device I/O thread for dispatching to UI. |
| 32 class ProxyDeviceEventDispatcher : public DeviceEventDispatcherEvdev { |
| 33 public: |
| 34 ProxyDeviceEventDispatcher( |
| 35 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner, |
| 36 base::WeakPtr<EventFactoryEvdev> event_factory_evdev) |
| 37 : ui_thread_runner_(ui_thread_runner), |
| 38 event_factory_evdev_(event_factory_evdev) {} |
| 39 ~ProxyDeviceEventDispatcher() override {} |
| 40 |
| 41 // DeviceEventDispatcher: |
| 42 void DispatchKeyEvent(const KeyEventParams& params) override { |
| 43 ui_thread_runner_->PostTask(FROM_HERE, |
| 44 base::Bind(&EventFactoryEvdev::DispatchKeyEvent, |
| 45 event_factory_evdev_, params)); |
| 46 } |
| 47 |
| 48 void DispatchMouseMoveEvent(const MouseMoveEventParams& params) override { |
| 49 ui_thread_runner_->PostTask( |
| 50 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent, |
| 51 event_factory_evdev_, params)); |
| 52 } |
| 53 |
| 54 void DispatchMouseButtonEvent(const MouseButtonEventParams& params) override { |
| 55 ui_thread_runner_->PostTask( |
| 56 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseButtonEvent, |
| 57 event_factory_evdev_, params)); |
| 58 } |
| 59 |
| 60 void DispatchMouseWheelEvent(const MouseWheelEventParams& params) override { |
| 61 ui_thread_runner_->PostTask( |
| 62 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseWheelEvent, |
| 63 event_factory_evdev_, params)); |
| 64 } |
| 65 |
| 66 void DispatchScrollEvent(const ScrollEventParams& params) override { |
| 67 ui_thread_runner_->PostTask( |
| 68 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchScrollEvent, |
| 69 event_factory_evdev_, params)); |
| 70 } |
| 71 |
| 72 void DispatchTouchEvent(const TouchEventParams& params) override { |
| 73 ui_thread_runner_->PostTask( |
| 74 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchTouchEvent, |
| 75 event_factory_evdev_, params)); |
| 76 } |
| 77 |
| 78 void DispatchKeyboardDevicesUpdated( |
| 79 const std::vector<KeyboardDevice>& devices) override { |
| 80 ui_thread_runner_->PostTask( |
| 81 FROM_HERE, |
| 82 base::Bind(&EventFactoryEvdev::DispatchKeyboardDevicesUpdated, |
| 83 event_factory_evdev_, devices)); |
| 84 } |
| 85 void DispatchTouchscreenDevicesUpdated( |
| 86 const std::vector<TouchscreenDevice>& devices) override { |
| 87 ui_thread_runner_->PostTask( |
| 88 FROM_HERE, |
| 89 base::Bind(&EventFactoryEvdev::DispatchTouchscreenDevicesUpdated, |
| 90 event_factory_evdev_, devices)); |
| 91 } |
| 92 void DispatchMouseDevicesUpdated( |
| 93 const std::vector<InputDevice>& devices) override { |
| 94 ui_thread_runner_->PostTask( |
| 95 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseDevicesUpdated, |
| 96 event_factory_evdev_, devices)); |
| 97 } |
| 98 void DispatchTouchpadDevicesUpdated( |
| 99 const std::vector<InputDevice>& devices) override { |
| 100 ui_thread_runner_->PostTask( |
| 101 FROM_HERE, |
| 102 base::Bind(&EventFactoryEvdev::DispatchTouchpadDevicesUpdated, |
| 103 event_factory_evdev_, devices)); |
| 104 } |
| 105 void DispatchDeviceListsComplete() override { |
| 106 ui_thread_runner_->PostTask( |
| 107 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchDeviceListsComplete, |
| 108 event_factory_evdev_)); |
| 109 } |
| 110 |
| 111 private: |
| 112 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_runner_; |
| 113 base::WeakPtr<EventFactoryEvdev> event_factory_evdev_; |
| 114 }; |
| 115 |
| 116 } // namespace |
| 117 |
| 118 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor, |
| 119 DeviceManager* device_manager, |
| 120 KeyboardLayoutEngine* keyboard_layout) |
| 121 : device_manager_(device_manager), |
| 122 keyboard_(&modifiers_, |
| 123 keyboard_layout, |
| 124 base::Bind(&EventFactoryEvdev::DispatchUiEvent, |
| 125 base::Unretained(this))), |
| 126 cursor_(cursor), |
| 127 input_controller_(&keyboard_, &button_map_), |
| 128 touch_id_generator_(0), |
| 129 weak_ptr_factory_(this) { |
| 130 DCHECK(device_manager_); |
| 131 } |
| 132 |
| 133 EventFactoryEvdev::~EventFactoryEvdev() { |
| 134 } |
| 135 |
| 136 void EventFactoryEvdev::Init() { |
| 137 DCHECK(!initialized_); |
| 138 |
| 139 StartThread(); |
| 140 |
| 141 initialized_ = true; |
| 142 } |
| 143 |
| 144 scoped_ptr<SystemInputInjector> EventFactoryEvdev::CreateSystemInputInjector() { |
| 145 // Use forwarding dispatcher for the injector rather than dispatching |
| 146 // directly. We cannot assume it is safe to (re-)enter ui::Event dispatch |
| 147 // synchronously from the injection point. |
| 148 scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher( |
| 149 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(), |
| 150 weak_ptr_factory_.GetWeakPtr())); |
| 151 return make_scoped_ptr( |
| 152 new InputInjectorEvdev(proxy_dispatcher.Pass(), cursor_)); |
| 153 } |
| 154 |
| 155 void EventFactoryEvdev::DispatchKeyEvent(const KeyEventParams& params) { |
| 156 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchKeyEvent", "device", |
| 157 params.device_id); |
| 158 keyboard_.OnKeyChange(params.code, params.down, params.suppress_auto_repeat, |
| 159 params.timestamp, params.device_id); |
| 160 } |
| 161 |
| 162 void EventFactoryEvdev::DispatchMouseMoveEvent( |
| 163 const MouseMoveEventParams& params) { |
| 164 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseMoveEvent", "device", |
| 165 params.device_id); |
| 166 MouseEvent event(ui::ET_MOUSE_MOVED, params.location, params.location, |
| 167 params.timestamp, modifiers_.GetModifierFlags(), |
| 168 /* changed_button_flags */ 0); |
| 169 event.set_source_device_id(params.device_id); |
| 170 DispatchUiEvent(&event); |
| 171 } |
| 172 |
| 173 void EventFactoryEvdev::DispatchMouseButtonEvent( |
| 174 const MouseButtonEventParams& params) { |
| 175 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseButtonEvent", "device", |
| 176 params.device_id); |
| 177 |
| 178 // Mouse buttons can be remapped, touchpad taps & clicks cannot. |
| 179 unsigned int button = params.button; |
| 180 if (params.allow_remap) |
| 181 button = button_map_.GetMappedButton(button); |
| 182 |
| 183 int modifier = EVDEV_MODIFIER_NONE; |
| 184 switch (button) { |
| 185 case BTN_LEFT: |
| 186 modifier = EVDEV_MODIFIER_LEFT_MOUSE_BUTTON; |
| 187 break; |
| 188 case BTN_RIGHT: |
| 189 modifier = EVDEV_MODIFIER_RIGHT_MOUSE_BUTTON; |
| 190 break; |
| 191 case BTN_MIDDLE: |
| 192 modifier = EVDEV_MODIFIER_MIDDLE_MOUSE_BUTTON; |
| 193 break; |
| 194 case BTN_BACK: |
| 195 modifier = EVDEV_MODIFIER_BACK_MOUSE_BUTTON; |
| 196 break; |
| 197 case BTN_FORWARD: |
| 198 modifier = EVDEV_MODIFIER_FORWARD_MOUSE_BUTTON; |
| 199 break; |
| 200 default: |
| 201 return; |
| 202 } |
| 203 |
| 204 int flag = modifiers_.GetEventFlagFromModifier(modifier); |
| 205 bool was_down = modifiers_.GetModifierFlags() & flag; |
| 206 modifiers_.UpdateModifier(modifier, params.down); |
| 207 bool down = modifiers_.GetModifierFlags() & flag; |
| 208 |
| 209 // Suppress nested clicks. EventModifiersEvdev counts presses, we only |
| 210 // dispatch an event on 0-1 (first press) and 1-0 (last release) transitions. |
| 211 if (down == was_down) |
| 212 return; |
| 213 |
| 214 MouseEvent event(params.down ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, |
| 215 params.location, params.location, params.timestamp, |
| 216 modifiers_.GetModifierFlags() | flag, |
| 217 /* changed_button_flags */ flag); |
| 218 event.set_source_device_id(params.device_id); |
| 219 DispatchUiEvent(&event); |
| 220 } |
| 221 |
| 222 void EventFactoryEvdev::DispatchMouseWheelEvent( |
| 223 const MouseWheelEventParams& params) { |
| 224 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchMouseWheelEvent", "device", |
| 225 params.device_id); |
| 226 MouseWheelEvent event(params.delta, params.location, params.location, |
| 227 params.timestamp, modifiers_.GetModifierFlags(), |
| 228 0 /* changed_button_flags */); |
| 229 event.set_source_device_id(params.device_id); |
| 230 DispatchUiEvent(&event); |
| 231 } |
| 232 |
| 233 void EventFactoryEvdev::DispatchScrollEvent(const ScrollEventParams& params) { |
| 234 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchScrollEvent", "device", |
| 235 params.device_id); |
| 236 ScrollEvent event(params.type, params.location, params.timestamp, |
| 237 modifiers_.GetModifierFlags(), params.delta.x(), |
| 238 params.delta.y(), params.ordinal_delta.x(), |
| 239 params.ordinal_delta.y(), params.finger_count); |
| 240 event.set_source_device_id(params.device_id); |
| 241 DispatchUiEvent(&event); |
| 242 } |
| 243 |
| 244 void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) { |
| 245 TRACE_EVENT1("evdev", "EventFactoryEvdev::DispatchTouchEvent", "device", |
| 246 params.device_id); |
| 247 |
| 248 float x = params.location.x(); |
| 249 float y = params.location.y(); |
| 250 double radius_x = params.radii.x(); |
| 251 double radius_y = params.radii.y(); |
| 252 |
| 253 // Transform the event to align touches to the image based on display mode. |
| 254 DeviceDataManager::GetInstance()->ApplyTouchTransformer(params.device_id, &x, |
| 255 &y); |
| 256 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id, |
| 257 &radius_x); |
| 258 DeviceDataManager::GetInstance()->ApplyTouchRadiusScale(params.device_id, |
| 259 &radius_y); |
| 260 |
| 261 // params.slot is guaranteed to be < kNumTouchEvdevSlots. |
| 262 int touch_id = touch_id_generator_.GetGeneratedID( |
| 263 params.device_id * kNumTouchEvdevSlots + params.slot); |
| 264 TouchEvent touch_event(params.type, gfx::PointF(x, y), |
| 265 modifiers_.GetModifierFlags(), touch_id, |
| 266 params.timestamp, radius_x, radius_y, |
| 267 /* angle */ 0.f, params.pressure); |
| 268 touch_event.set_source_device_id(params.device_id); |
| 269 DispatchUiEvent(&touch_event); |
| 270 |
| 271 if (params.type == ET_TOUCH_RELEASED || params.type == ET_TOUCH_CANCELLED) { |
| 272 touch_id_generator_.ReleaseGeneratedID(touch_event.touch_id()); |
| 273 } |
| 274 } |
| 275 |
| 276 void EventFactoryEvdev::DispatchUiEvent(Event* event) { |
| 277 // DispatchEvent takes PlatformEvent which is void*. This function |
| 278 // wraps it with the real type. |
| 279 DispatchEvent(event); |
| 280 } |
| 281 |
| 282 void EventFactoryEvdev::DispatchKeyboardDevicesUpdated( |
| 283 const std::vector<KeyboardDevice>& devices) { |
| 284 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchKeyboardDevicesUpdated"); |
| 285 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); |
| 286 observer->OnKeyboardDevicesUpdated(devices); |
| 287 } |
| 288 |
| 289 void EventFactoryEvdev::DispatchTouchscreenDevicesUpdated( |
| 290 const std::vector<TouchscreenDevice>& devices) { |
| 291 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchscreenDevicesUpdated"); |
| 292 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); |
| 293 observer->OnTouchscreenDevicesUpdated(devices); |
| 294 } |
| 295 |
| 296 void EventFactoryEvdev::DispatchMouseDevicesUpdated( |
| 297 const std::vector<InputDevice>& devices) { |
| 298 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchMouseDevicesUpdated"); |
| 299 |
| 300 // There's no list of mice in DeviceDataManager. |
| 301 input_controller_.set_has_mouse(devices.size() != 0); |
| 302 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); |
| 303 observer->OnMouseDevicesUpdated(devices); |
| 304 } |
| 305 |
| 306 void EventFactoryEvdev::DispatchTouchpadDevicesUpdated( |
| 307 const std::vector<InputDevice>& devices) { |
| 308 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchTouchpadDevicesUpdated"); |
| 309 |
| 310 // There's no list of touchpads in DeviceDataManager. |
| 311 input_controller_.set_has_touchpad(devices.size() != 0); |
| 312 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); |
| 313 observer->OnTouchpadDevicesUpdated(devices); |
| 314 } |
| 315 |
| 316 void EventFactoryEvdev::DispatchDeviceListsComplete() { |
| 317 TRACE_EVENT0("evdev", "EventFactoryEvdev::DispatchDeviceListsComplete"); |
| 318 DeviceHotplugEventObserver* observer = DeviceDataManager::GetInstance(); |
| 319 observer->OnDeviceListsComplete(); |
| 320 } |
| 321 |
| 322 void EventFactoryEvdev::OnDeviceEvent(const DeviceEvent& event) { |
| 323 if (event.device_type() != DeviceEvent::INPUT) |
| 324 return; |
| 325 |
| 326 switch (event.action_type()) { |
| 327 case DeviceEvent::ADD: |
| 328 case DeviceEvent::CHANGE: { |
| 329 TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceAdded", "path", |
| 330 event.path().value()); |
| 331 input_device_factory_proxy_->AddInputDevice(NextDeviceId(), event.path()); |
| 332 break; |
| 333 } |
| 334 case DeviceEvent::REMOVE: { |
| 335 TRACE_EVENT1("evdev", "EventFactoryEvdev::OnDeviceRemoved", "path", |
| 336 event.path().value()); |
| 337 input_device_factory_proxy_->RemoveInputDevice(event.path()); |
| 338 break; |
| 339 } |
| 340 } |
| 341 } |
| 342 |
| 343 void EventFactoryEvdev::OnDispatcherListChanged() { |
| 344 if (!initialized_) |
| 345 Init(); |
| 346 } |
| 347 |
| 348 void EventFactoryEvdev::WarpCursorTo(gfx::AcceleratedWidget widget, |
| 349 const gfx::PointF& location) { |
| 350 if (!cursor_) |
| 351 return; |
| 352 |
| 353 cursor_->MoveCursorTo(widget, location); |
| 354 |
| 355 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 356 FROM_HERE, base::Bind(&EventFactoryEvdev::DispatchMouseMoveEvent, |
| 357 weak_ptr_factory_.GetWeakPtr(), |
| 358 MouseMoveEventParams(-1 /* device_id */, |
| 359 cursor_->GetLocation(), |
| 360 EventTimeForNow()))); |
| 361 } |
| 362 |
| 363 int EventFactoryEvdev::NextDeviceId() { |
| 364 return ++last_device_id_; |
| 365 } |
| 366 |
| 367 void EventFactoryEvdev::StartThread() { |
| 368 // Set up device factory. |
| 369 scoped_ptr<DeviceEventDispatcherEvdev> proxy_dispatcher( |
| 370 new ProxyDeviceEventDispatcher(base::ThreadTaskRunnerHandle::Get(), |
| 371 weak_ptr_factory_.GetWeakPtr())); |
| 372 thread_.Start(proxy_dispatcher.Pass(), cursor_, |
| 373 base::Bind(&EventFactoryEvdev::OnThreadStarted, |
| 374 weak_ptr_factory_.GetWeakPtr())); |
| 375 } |
| 376 |
| 377 void EventFactoryEvdev::OnThreadStarted( |
| 378 scoped_ptr<InputDeviceFactoryEvdevProxy> input_device_factory) { |
| 379 TRACE_EVENT0("evdev", "EventFactoryEvdev::OnThreadStarted"); |
| 380 input_device_factory_proxy_ = input_device_factory.Pass(); |
| 381 |
| 382 // Hook up device configuration. |
| 383 input_controller_.SetInputDeviceFactory(input_device_factory_proxy_.get()); |
| 384 |
| 385 // Scan & monitor devices. |
| 386 device_manager_->AddObserver(this); |
| 387 device_manager_->ScanDevices(this); |
| 388 |
| 389 // Notify device thread that initial scan is done. |
| 390 input_device_factory_proxy_->OnStartupScanComplete(); |
| 391 } |
| 392 |
| 393 } // namespace ui |
OLD | NEW |