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 |