| 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> | 7 #include <fcntl.h> |
| 8 #include <linux/input.h> | 8 #include <linux/input.h> |
| 9 | 9 |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/task_runner.h" | 12 #include "base/task_runner.h" |
| 13 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h" | 13 #include "ui/events/ozone/evdev/cursor_delegate_evdev.h" |
| 14 #include "ui/events/ozone/evdev/device_manager_evdev.h" | 14 #include "ui/events/ozone/evdev/device_manager_evdev.h" |
| 15 #include "ui/events/ozone/evdev/event_device_info.h" | 15 #include "ui/events/ozone/evdev/event_device_info.h" |
| 16 #include "ui/events/ozone/evdev/key_event_converter_evdev.h" | 16 #include "ui/events/ozone/evdev/key_event_converter_evdev.h" |
| 17 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" | 17 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" |
| 18 | 18 |
| 19 #if defined(USE_UDEV) | 19 #if defined(USE_UDEV) |
| 20 #include "ui/events/ozone/evdev/device_manager_udev.h" | 20 #include "ui/events/ozone/evdev/device_manager_udev.h" |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 #if defined(USE_EVDEV_GESTURES) |
| 24 #include "ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.h" |
| 25 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cr
os.h" |
| 26 #endif |
| 27 |
| 23 #ifndef EVIOCSCLOCKID | 28 #ifndef EVIOCSCLOCKID |
| 24 #define EVIOCSCLOCKID _IOW('E', 0xa0, int) | 29 #define EVIOCSCLOCKID _IOW('E', 0xa0, int) |
| 25 #endif | 30 #endif |
| 26 | 31 |
| 27 namespace ui { | 32 namespace ui { |
| 28 | 33 |
| 29 namespace { | 34 namespace { |
| 30 | 35 |
| 31 bool IsTouchPad(const EventDeviceInfo& devinfo) { | 36 bool UseGesturesLibraryForDevice(const EventDeviceInfo& devinfo) { |
| 32 if (!devinfo.HasEventType(EV_ABS)) | 37 if (devinfo.HasAbsXY() && !devinfo.IsMappedToScreen()) |
| 33 return false; | 38 return true; // touchpad |
| 34 | 39 |
| 35 return devinfo.HasKeyEvent(BTN_LEFT) || devinfo.HasKeyEvent(BTN_MIDDLE) || | 40 if (devinfo.HasRelXY()) |
| 36 devinfo.HasKeyEvent(BTN_RIGHT) || devinfo.HasKeyEvent(BTN_TOOL_FINGER); | 41 return true; // mouse |
| 42 |
| 43 return false; |
| 37 } | 44 } |
| 38 | 45 |
| 39 bool IsTouchScreen(const EventDeviceInfo& devinfo) { | 46 scoped_ptr<EventConverterEvdev> CreateConverter( |
| 40 return devinfo.HasEventType(EV_ABS) && !IsTouchPad(devinfo); | 47 int fd, |
| 48 const base::FilePath& path, |
| 49 const EventDeviceInfo& devinfo, |
| 50 const EventDispatchCallback& dispatch, |
| 51 EventModifiersEvdev* modifiers, |
| 52 CursorDelegateEvdev* cursor) { |
| 53 #if defined(USE_EVDEV_GESTURES) |
| 54 // Touchpad or mouse: use gestures library. |
| 55 // EventReaderLibevdevCros -> GestureInterpreterLibevdevCros -> DispatchEvent |
| 56 if (UseGesturesLibraryForDevice(devinfo)) { |
| 57 scoped_ptr<GestureInterpreterLibevdevCros> gesture_interp = make_scoped_ptr( |
| 58 new GestureInterpreterLibevdevCros(modifiers, cursor, dispatch)); |
| 59 scoped_ptr<EventReaderLibevdevCros> libevdev_reader = |
| 60 make_scoped_ptr(new EventReaderLibevdevCros( |
| 61 fd, |
| 62 path, |
| 63 gesture_interp.PassAs<EventReaderLibevdevCros::Delegate>())); |
| 64 return libevdev_reader.PassAs<EventConverterEvdev>(); |
| 65 } |
| 66 #endif |
| 67 |
| 68 // Touchscreen: use TouchEventConverterEvdev. |
| 69 scoped_ptr<EventConverterEvdev> converter; |
| 70 if (devinfo.HasAbsXY()) |
| 71 return make_scoped_ptr<EventConverterEvdev>( |
| 72 new TouchEventConverterEvdev(fd, path, devinfo, dispatch)); |
| 73 |
| 74 // Everything else: use KeyEventConverterEvdev. |
| 75 return make_scoped_ptr<EventConverterEvdev>( |
| 76 new KeyEventConverterEvdev(fd, path, modifiers, dispatch)); |
| 41 } | 77 } |
| 42 | 78 |
| 43 // Open an input device. Opening may put the calling thread to sleep, and | 79 // Open an input device. Opening may put the calling thread to sleep, and |
| 44 // therefore should be run on a thread where latency is not critical. We | 80 // therefore should be run on a thread where latency is not critical. We |
| 45 // run it on the FILE thread. | 81 // run it on the FILE thread. |
| 46 // | 82 // |
| 47 // This takes a TaskRunner and runs the reply on that thread, so that we | 83 // This takes a TaskRunner and runs the reply on that thread, so that we |
| 48 // can hop threads if necessary (back to the UI thread). | 84 // can hop threads if necessary (back to the UI thread). |
| 49 void OpenInputDevice( | 85 void OpenInputDevice( |
| 50 const base::FilePath& path, | 86 const base::FilePath& path, |
| 51 EventModifiersEvdev* modifiers, | 87 EventModifiersEvdev* modifiers, |
| 52 CursorDelegateEvdev* cursor, | 88 CursorDelegateEvdev* cursor, |
| 53 scoped_refptr<base::TaskRunner> reply_runner, | 89 scoped_refptr<base::TaskRunner> reply_runner, |
| 90 const EventDispatchCallback& dispatch, |
| 54 base::Callback<void(scoped_ptr<EventConverterEvdev>)> reply_callback) { | 91 base::Callback<void(scoped_ptr<EventConverterEvdev>)> reply_callback) { |
| 55 TRACE_EVENT1("ozone", "OpenInputDevice", "path", path.value()); | 92 TRACE_EVENT1("ozone", "OpenInputDevice", "path", path.value()); |
| 56 | 93 |
| 57 int fd = open(path.value().c_str(), O_RDONLY | O_NONBLOCK); | 94 int fd = open(path.value().c_str(), O_RDONLY | O_NONBLOCK); |
| 58 if (fd < 0) { | 95 if (fd < 0) { |
| 59 PLOG(ERROR) << "Cannot open '" << path.value(); | 96 PLOG(ERROR) << "Cannot open '" << path.value(); |
| 60 return; | 97 return; |
| 61 } | 98 } |
| 62 | 99 |
| 63 // Use monotonic timestamps for events. The touch code in particular | 100 // Use monotonic timestamps for events. The touch code in particular |
| 64 // expects event timestamps to correlate to the monotonic clock | 101 // expects event timestamps to correlate to the monotonic clock |
| 65 // (base::TimeTicks). | 102 // (base::TimeTicks). |
| 66 unsigned int clk = CLOCK_MONOTONIC; | 103 unsigned int clk = CLOCK_MONOTONIC; |
| 67 if (ioctl(fd, EVIOCSCLOCKID, &clk)) | 104 if (ioctl(fd, EVIOCSCLOCKID, &clk)) |
| 68 PLOG(ERROR) << "failed to set CLOCK_MONOTONIC"; | 105 PLOG(ERROR) << "failed to set CLOCK_MONOTONIC"; |
| 69 | 106 |
| 70 EventDeviceInfo devinfo; | 107 EventDeviceInfo devinfo; |
| 71 if (!devinfo.Initialize(fd)) { | 108 if (!devinfo.Initialize(fd)) { |
| 72 LOG(ERROR) << "failed to get device information for " << path.value(); | 109 LOG(ERROR) << "failed to get device information for " << path.value(); |
| 73 close(fd); | 110 close(fd); |
| 74 return; | 111 return; |
| 75 } | 112 } |
| 76 | 113 |
| 77 if (IsTouchPad(devinfo)) { | 114 scoped_ptr<EventConverterEvdev> converter = |
| 78 LOG(WARNING) << "touchpad device not supported: " << path.value(); | 115 CreateConverter(fd, path, devinfo, dispatch, modifiers, cursor); |
| 79 close(fd); | |
| 80 return; | |
| 81 } | |
| 82 | 116 |
| 83 // TODO(spang) Add more device types. | 117 // Reply with the constructed converter. |
| 84 scoped_ptr<EventConverterEvdev> converter; | 118 reply_runner->PostTask(FROM_HERE, |
| 85 if (IsTouchScreen(devinfo)) | 119 base::Bind(reply_callback, base::Passed(&converter))); |
| 86 converter.reset(new TouchEventConverterEvdev(fd, path, devinfo)); | |
| 87 else if (devinfo.HasEventType(EV_KEY)) | |
| 88 converter.reset(new KeyEventConverterEvdev(fd, path, modifiers)); | |
| 89 | |
| 90 if (converter) { | |
| 91 // Reply with the constructed converter. | |
| 92 reply_runner->PostTask( | |
| 93 FROM_HERE, base::Bind(reply_callback, base::Passed(&converter))); | |
| 94 } else { | |
| 95 close(fd); | |
| 96 } | |
| 97 } | 120 } |
| 98 | 121 |
| 99 // Close an input device. Closing may put the calling thread to sleep, and | 122 // Close an input device. Closing may put the calling thread to sleep, and |
| 100 // therefore should be run on a thread where latency is not critical. We | 123 // therefore should be run on a thread where latency is not critical. We |
| 101 // run it on the FILE thread. | 124 // run it on the FILE thread. |
| 102 void CloseInputDevice(const base::FilePath& path, | 125 void CloseInputDevice(const base::FilePath& path, |
| 103 scoped_ptr<EventConverterEvdev> converter) { | 126 scoped_ptr<EventConverterEvdev> converter) { |
| 104 TRACE_EVENT1("ozone", "CloseInputDevice", "path", path.value()); | 127 TRACE_EVENT1("ozone", "CloseInputDevice", "path", path.value()); |
| 105 converter.reset(); | 128 converter.reset(); |
| 106 } | 129 } |
| 107 | 130 |
| 108 } // namespace | 131 } // namespace |
| 109 | 132 |
| 110 EventFactoryEvdev::EventFactoryEvdev() | 133 EventFactoryEvdev::EventFactoryEvdev() |
| 111 : ui_task_runner_(base::MessageLoopProxy::current()), | 134 : ui_task_runner_(base::MessageLoopProxy::current()), |
| 112 file_task_runner_(base::MessageLoopProxy::current()), | 135 file_task_runner_(base::MessageLoopProxy::current()), |
| 113 cursor_(NULL), | 136 cursor_(NULL), |
| 137 dispatch_callback_( |
| 138 base::Bind(base::IgnoreResult(&EventFactoryEvdev::DispatchEvent), |
| 139 base::Unretained(this))), |
| 114 weak_ptr_factory_(this) {} | 140 weak_ptr_factory_(this) {} |
| 115 | 141 |
| 116 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor) | 142 EventFactoryEvdev::EventFactoryEvdev(CursorDelegateEvdev* cursor) |
| 117 : ui_task_runner_(base::MessageLoopProxy::current()), | 143 : ui_task_runner_(base::MessageLoopProxy::current()), |
| 118 file_task_runner_(base::MessageLoopProxy::current()), | 144 file_task_runner_(base::MessageLoopProxy::current()), |
| 119 cursor_(cursor), | 145 cursor_(cursor), |
| 146 dispatch_callback_( |
| 147 base::Bind(base::IgnoreResult(&EventFactoryEvdev::DispatchEvent), |
| 148 base::Unretained(this))), |
| 120 weak_ptr_factory_(this) {} | 149 weak_ptr_factory_(this) {} |
| 121 | 150 |
| 122 EventFactoryEvdev::~EventFactoryEvdev() { STLDeleteValues(&converters_); } | 151 EventFactoryEvdev::~EventFactoryEvdev() { STLDeleteValues(&converters_); } |
| 123 | 152 |
| 153 void EventFactoryEvdev::DispatchEvent(Event* event) { |
| 154 EventFactoryOzone::DispatchEvent(event); |
| 155 } |
| 156 |
| 124 void EventFactoryEvdev::AttachInputDevice( | 157 void EventFactoryEvdev::AttachInputDevice( |
| 125 const base::FilePath& path, | 158 const base::FilePath& path, |
| 126 scoped_ptr<EventConverterEvdev> converter) { | 159 scoped_ptr<EventConverterEvdev> converter) { |
| 127 TRACE_EVENT1("ozone", "AttachInputDevice", "path", path.value()); | 160 TRACE_EVENT1("ozone", "AttachInputDevice", "path", path.value()); |
| 128 CHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 161 CHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 129 | 162 |
| 130 // If we have an existing device, detach it. We don't want two | 163 // If we have an existing device, detach it. We don't want two |
| 131 // devices with the same name open at the same time. | 164 // devices with the same name open at the same time. |
| 132 if (converters_[path]) | 165 if (converters_[path]) |
| 133 DetachInputDevice(path); | 166 DetachInputDevice(path); |
| 134 | 167 |
| 135 // Add initialized device to map. | 168 // Add initialized device to map. |
| 136 converters_[path] = converter.release(); | 169 converters_[path] = converter.release(); |
| 137 converters_[path]->SetDispatchCallback( | |
| 138 base::Bind(base::IgnoreResult(&EventFactoryEvdev::DispatchEvent), | |
| 139 base::Unretained(this))); | |
| 140 converters_[path]->Start(); | 170 converters_[path]->Start(); |
| 141 } | 171 } |
| 142 | 172 |
| 143 void EventFactoryEvdev::OnDeviceAdded(const base::FilePath& path) { | 173 void EventFactoryEvdev::OnDeviceAdded(const base::FilePath& path) { |
| 144 TRACE_EVENT1("ozone", "OnDeviceAdded", "path", path.value()); | 174 TRACE_EVENT1("ozone", "OnDeviceAdded", "path", path.value()); |
| 145 | 175 |
| 146 // Dispatch task to open on FILE thread, since open may block. | 176 // Dispatch task to open on FILE thread, since open may block. |
| 147 file_task_runner_->PostTask( | 177 file_task_runner_->PostTask( |
| 148 FROM_HERE, | 178 FROM_HERE, |
| 149 base::Bind(&OpenInputDevice, | 179 base::Bind(&OpenInputDevice, |
| 150 path, | 180 path, |
| 151 &modifiers_, | 181 &modifiers_, |
| 152 cursor_, | 182 cursor_, |
| 153 ui_task_runner_, | 183 ui_task_runner_, |
| 184 dispatch_callback_, |
| 154 base::Bind(&EventFactoryEvdev::AttachInputDevice, | 185 base::Bind(&EventFactoryEvdev::AttachInputDevice, |
| 155 weak_ptr_factory_.GetWeakPtr(), | 186 weak_ptr_factory_.GetWeakPtr(), |
| 156 path))); | 187 path))); |
| 157 } | 188 } |
| 158 | 189 |
| 159 void EventFactoryEvdev::DetachInputDevice(const base::FilePath& path) { | 190 void EventFactoryEvdev::DetachInputDevice(const base::FilePath& path) { |
| 160 TRACE_EVENT1("ozone", "DetachInputDevice", "path", path.value()); | 191 TRACE_EVENT1("ozone", "DetachInputDevice", "path", path.value()); |
| 161 CHECK(ui_task_runner_->RunsTasksOnCurrentThread()); | 192 CHECK(ui_task_runner_->RunsTasksOnCurrentThread()); |
| 162 | 193 |
| 163 // Remove device from map. | 194 // Remove device from map. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 MouseEvent mouse_event(ET_MOUSE_MOVED, | 241 MouseEvent mouse_event(ET_MOUSE_MOVED, |
| 211 cursor_->location(), | 242 cursor_->location(), |
| 212 cursor_->location(), | 243 cursor_->location(), |
| 213 modifiers_.GetModifierFlags(), | 244 modifiers_.GetModifierFlags(), |
| 214 /* changed_button_flags */ 0); | 245 /* changed_button_flags */ 0); |
| 215 DispatchEvent(&mouse_event); | 246 DispatchEvent(&mouse_event); |
| 216 } | 247 } |
| 217 } | 248 } |
| 218 | 249 |
| 219 } // namespace ui | 250 } // namespace ui |
| OLD | NEW |