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/touch_event_converter_evdev.h" | 5 #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <linux/input.h> | 9 #include <linux/input.h> |
10 #include <poll.h> | 10 #include <poll.h> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "base/message_loop/message_loop.h" | 22 #include "base/message_loop/message_loop.h" |
23 #include "base/strings/string_number_conversions.h" | 23 #include "base/strings/string_number_conversions.h" |
24 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
25 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
26 #include "ui/events/devices/device_data_manager.h" | 26 #include "ui/events/devices/device_data_manager.h" |
27 #include "ui/events/devices/device_util_linux.h" | 27 #include "ui/events/devices/device_util_linux.h" |
28 #include "ui/events/event.h" | 28 #include "ui/events/event.h" |
29 #include "ui/events/event_constants.h" | 29 #include "ui/events/event_constants.h" |
30 #include "ui/events/event_switches.h" | 30 #include "ui/events/event_switches.h" |
31 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" | 31 #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" |
32 #include "ui/events/ozone/evdev/touch_evdev_types.h" | |
33 #include "ui/events/ozone/evdev/touch_noise/touch_noise_finder.h" | |
34 | 32 |
35 namespace { | 33 namespace { |
36 | 34 |
37 struct TouchCalibration { | 35 struct TouchCalibration { |
38 int bezel_left; | 36 int bezel_left; |
39 int bezel_right; | 37 int bezel_right; |
40 int bezel_top; | 38 int bezel_top; |
41 int bezel_bottom; | 39 int bezel_bottom; |
42 }; | 40 }; |
43 | 41 |
(...skipping 10 matching lines...) Expand all Loading... |
54 DLOG(ERROR) << "Incorrect top border calibration value passed."; | 52 DLOG(ERROR) << "Incorrect top border calibration value passed."; |
55 if (!base::StringToInt(parts[3], &cal->bezel_bottom)) | 53 if (!base::StringToInt(parts[3], &cal->bezel_bottom)) |
56 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; | 54 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; |
57 } | 55 } |
58 } | 56 } |
59 | 57 |
60 } // namespace | 58 } // namespace |
61 | 59 |
62 namespace ui { | 60 namespace ui { |
63 | 61 |
| 62 TouchEventConverterEvdev::InProgressEvents::InProgressEvents() |
| 63 : altered_(false), |
| 64 x_(0), |
| 65 y_(0), |
| 66 id_(-1), |
| 67 finger_(-1), |
| 68 type_(ET_UNKNOWN), |
| 69 radius_x_(0), |
| 70 radius_y_(0), |
| 71 pressure_(0) { |
| 72 } |
| 73 |
64 TouchEventConverterEvdev::TouchEventConverterEvdev( | 74 TouchEventConverterEvdev::TouchEventConverterEvdev( |
65 int fd, | 75 int fd, |
66 base::FilePath path, | 76 base::FilePath path, |
67 int id, | 77 int id, |
68 InputDeviceType type, | 78 InputDeviceType type, |
69 DeviceEventDispatcherEvdev* dispatcher) | 79 DeviceEventDispatcherEvdev* dispatcher) |
70 : EventConverterEvdev(fd, path, id, type), | 80 : EventConverterEvdev(fd, path, id, type), |
71 dispatcher_(dispatcher), | 81 dispatcher_(dispatcher), |
72 syn_dropped_(false), | 82 syn_dropped_(false), |
| 83 is_type_a_(false), |
73 touch_points_(0), | 84 touch_points_(0), |
74 current_slot_(0) { | 85 current_slot_(0) { |
75 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
76 switches::kExtraTouchNoiseFiltering)) { | |
77 touch_noise_finder_.reset(new TouchNoiseFinder); | |
78 } | |
79 } | 86 } |
80 | 87 |
81 TouchEventConverterEvdev::~TouchEventConverterEvdev() { | 88 TouchEventConverterEvdev::~TouchEventConverterEvdev() { |
82 Stop(); | 89 Stop(); |
83 close(fd_); | 90 close(fd_); |
84 } | 91 } |
85 | 92 |
86 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { | 93 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { |
87 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); | 94 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); |
88 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); | 95 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); |
89 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); | 96 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); |
90 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; | 97 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; |
91 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); | 98 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); |
92 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; | 99 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; |
93 touch_points_ = | 100 touch_points_ = |
94 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots); | 101 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, MAX_FINGERS); |
95 | 102 |
96 // Apply --touch-calibration. | 103 // Apply --touch-calibration. |
97 if (type() == INPUT_DEVICE_INTERNAL) { | 104 if (type() == INPUT_DEVICE_INTERNAL) { |
98 TouchCalibration cal = {}; | 105 TouchCalibration cal = {}; |
99 GetTouchCalibration(&cal); | 106 GetTouchCalibration(&cal); |
100 x_min_tuxels_ += cal.bezel_left; | 107 x_min_tuxels_ += cal.bezel_left; |
101 x_num_tuxels_ -= cal.bezel_left + cal.bezel_right; | 108 x_num_tuxels_ -= cal.bezel_left + cal.bezel_right; |
102 y_min_tuxels_ += cal.bezel_top; | 109 y_min_tuxels_ += cal.bezel_top; |
103 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; | 110 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; |
104 | 111 |
105 VLOG(1) << "applying touch calibration: " | 112 VLOG(1) << "applying touch calibration: " |
106 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, | 113 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, |
107 cal.bezel_right, cal.bezel_top, | 114 cal.bezel_right, cal.bezel_top, |
108 cal.bezel_bottom); | 115 cal.bezel_bottom); |
109 } | 116 } |
110 | 117 |
111 native_size_ = gfx::Size(x_num_tuxels_, y_num_tuxels_); | 118 native_size_ = gfx::Size(x_num_tuxels_, y_num_tuxels_); |
112 | 119 |
113 events_.resize(touch_points_); | 120 events_.resize(touch_points_); |
114 for (size_t i = 0; i < events_.size(); ++i) { | 121 for (size_t i = 0; i < events_.size(); ++i) { |
115 events_[i].x = info.GetSlotValue(ABS_MT_POSITION_X, i); | 122 events_[i].finger_ = info.GetSlotValue(ABS_MT_TRACKING_ID, i); |
116 events_[i].y = info.GetSlotValue(ABS_MT_POSITION_Y, i); | 123 events_[i].type_ = |
117 events_[i].tracking_id = info.GetSlotValue(ABS_MT_TRACKING_ID, i); | 124 events_[i].finger_ < 0 ? ET_TOUCH_RELEASED : ET_TOUCH_PRESSED; |
118 events_[i].touching = (events_[i].tracking_id >= 0); | 125 events_[i].x_ = info.GetSlotValue(ABS_MT_POSITION_X, i); |
119 events_[i].slot = i; | 126 events_[i].y_ = info.GetSlotValue(ABS_MT_POSITION_Y, i); |
120 events_[i].radius_x = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); | 127 events_[i].radius_x_ = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); |
121 events_[i].radius_y = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); | 128 events_[i].radius_y_ = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); |
122 events_[i].pressure = info.GetSlotValue(ABS_MT_PRESSURE, i); | 129 events_[i].pressure_ = info.GetSlotValue(ABS_MT_PRESSURE, i); |
123 } | 130 } |
124 } | 131 } |
125 | 132 |
126 bool TouchEventConverterEvdev::Reinitialize() { | 133 bool TouchEventConverterEvdev::Reinitialize() { |
127 EventDeviceInfo info; | 134 EventDeviceInfo info; |
128 if (info.Initialize(fd_)) { | 135 if (info.Initialize(fd_)) { |
129 Initialize(info); | 136 Initialize(info); |
130 return true; | 137 return true; |
131 } | 138 } |
132 return false; | 139 return false; |
133 } | 140 } |
134 | 141 |
135 bool TouchEventConverterEvdev::HasTouchscreen() const { | 142 bool TouchEventConverterEvdev::HasTouchscreen() const { |
136 return true; | 143 return true; |
137 } | 144 } |
138 | 145 |
139 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { | 146 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { |
140 return native_size_; | 147 return native_size_; |
141 } | 148 } |
142 | 149 |
143 int TouchEventConverterEvdev::GetTouchPoints() const { | 150 int TouchEventConverterEvdev::GetTouchPoints() const { |
144 return touch_points_; | 151 return touch_points_; |
145 } | 152 } |
146 | 153 |
147 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { | 154 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
148 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; | 155 input_event inputs[MAX_FINGERS * 6 + 1]; |
149 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | 156 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
150 if (read_size < 0) { | 157 if (read_size < 0) { |
151 if (errno == EINTR || errno == EAGAIN) | 158 if (errno == EINTR || errno == EAGAIN) |
152 return; | 159 return; |
153 if (errno != ENODEV) | 160 if (errno != ENODEV) |
154 PLOG(ERROR) << "error reading device " << path_.value(); | 161 PLOG(ERROR) << "error reading device " << path_.value(); |
155 Stop(); | 162 Stop(); |
156 return; | 163 return; |
157 } | 164 } |
158 | 165 |
159 if (ignore_events_) | 166 if (ignore_events_) |
160 return; | 167 return; |
161 | 168 |
162 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { | 169 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { |
163 ProcessInputEvent(inputs[i]); | 170 ProcessInputEvent(inputs[i]); |
164 } | 171 } |
165 } | 172 } |
166 | 173 |
167 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { | 174 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { |
168 if (input.type == EV_SYN) { | 175 if (input.type == EV_SYN) { |
169 ProcessSyn(input); | 176 ProcessSyn(input); |
170 } else if (syn_dropped_) { | 177 } else if(syn_dropped_) { |
171 // Do nothing. This branch indicates we have lost sync with the driver. | 178 // Do nothing. This branch indicates we have lost sync with the driver. |
172 } else if (input.type == EV_ABS) { | 179 } else if (input.type == EV_ABS) { |
173 if (events_.size() <= current_slot_) { | 180 if (events_.size() <= current_slot_) { |
174 LOG(ERROR) << "current_slot_ (" << current_slot_ | 181 LOG(ERROR) << "current_slot_ (" << current_slot_ |
175 << ") >= events_.size() (" << events_.size() << ")"; | 182 << ") >= events_.size() (" << events_.size() << ")"; |
176 } else { | 183 } else { |
177 ProcessAbs(input); | 184 ProcessAbs(input); |
178 } | 185 } |
179 } else if (input.type == EV_KEY) { | 186 } else if (input.type == EV_KEY) { |
180 switch (input.code) { | 187 switch (input.code) { |
181 case BTN_TOUCH: | 188 case BTN_TOUCH: |
182 break; | 189 break; |
183 default: | 190 default: |
184 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; | 191 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
185 } | 192 } |
186 } else { | 193 } else { |
187 NOTIMPLEMENTED() << "invalid type: " << input.type; | 194 NOTIMPLEMENTED() << "invalid type: " << input.type; |
188 } | 195 } |
189 } | 196 } |
190 | 197 |
191 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { | 198 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { |
192 switch (input.code) { | 199 switch (input.code) { |
193 case ABS_MT_TOUCH_MAJOR: | 200 case ABS_MT_TOUCH_MAJOR: |
194 // TODO(spang): If we have all of major, minor, and orientation, | 201 // TODO(spang): If we have all of major, minor, and orientation, |
195 // we can scale the ellipse correctly. However on the Pixel we get | 202 // we can scale the ellipse correctly. However on the Pixel we get |
196 // neither minor nor orientation, so this is all we can do. | 203 // neither minor nor orientation, so this is all we can do. |
197 events_[current_slot_].radius_x = input.value / 2.0f; | 204 events_[current_slot_].radius_x_ = input.value / 2.0f; |
198 break; | 205 break; |
199 case ABS_MT_TOUCH_MINOR: | 206 case ABS_MT_TOUCH_MINOR: |
200 events_[current_slot_].radius_y = input.value / 2.0f; | 207 events_[current_slot_].radius_y_ = input.value / 2.0f; |
201 break; | 208 break; |
202 case ABS_MT_POSITION_X: | 209 case ABS_MT_POSITION_X: |
203 events_[current_slot_].x = input.value; | 210 events_[current_slot_].x_ = input.value; |
204 break; | 211 break; |
205 case ABS_MT_POSITION_Y: | 212 case ABS_MT_POSITION_Y: |
206 events_[current_slot_].y = input.value; | 213 events_[current_slot_].y_ = input.value; |
207 break; | 214 break; |
208 case ABS_MT_TRACKING_ID: | 215 case ABS_MT_TRACKING_ID: |
209 if (input.value < 0) { | 216 if (input.value < 0) { |
210 events_[current_slot_].touching = false; | 217 events_[current_slot_].type_ = ET_TOUCH_RELEASED; |
211 } else { | 218 } else { |
212 events_[current_slot_].touching = true; | 219 events_[current_slot_].finger_ = input.value; |
213 events_[current_slot_].cancelled = false; | 220 events_[current_slot_].type_ = ET_TOUCH_PRESSED; |
214 } | 221 } |
215 events_[current_slot_].tracking_id = input.value; | |
216 break; | 222 break; |
217 case ABS_MT_PRESSURE: | 223 case ABS_MT_PRESSURE: |
218 events_[current_slot_].pressure = input.value - pressure_min_; | 224 events_[current_slot_].pressure_ = input.value - pressure_min_; |
219 events_[current_slot_].pressure /= pressure_max_ - pressure_min_; | 225 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; |
220 break; | 226 break; |
221 case ABS_MT_SLOT: | 227 case ABS_MT_SLOT: |
222 if (input.value >= 0 && | 228 if (input.value >= 0 && |
223 static_cast<size_t>(input.value) < events_.size()) { | 229 static_cast<size_t>(input.value) < events_.size()) { |
224 current_slot_ = input.value; | 230 current_slot_ = input.value; |
225 } else { | 231 } else { |
226 LOG(ERROR) << "invalid touch event index: " << input.value; | 232 LOG(ERROR) << "invalid touch event index: " << input.value; |
227 return; | 233 return; |
228 } | 234 } |
229 break; | 235 break; |
230 default: | 236 default: |
231 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; | 237 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; |
232 return; | 238 return; |
233 } | 239 } |
234 events_[current_slot_].altered = true; | 240 events_[current_slot_].altered_ = true; |
235 } | 241 } |
236 | 242 |
237 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { | 243 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { |
238 switch (input.code) { | 244 switch (input.code) { |
239 case SYN_REPORT: | 245 case SYN_REPORT: |
240 if (syn_dropped_) { | 246 if (syn_dropped_) { |
241 // Have to re-initialize. | 247 // Have to re-initialize. |
242 if (Reinitialize()) { | 248 if (Reinitialize()) { |
243 syn_dropped_ = false; | 249 syn_dropped_ = false; |
244 for(InProgressTouchEvdev& event : events_) | 250 for(InProgressEvents& event: events_) |
245 event.altered = false; | 251 event.altered_ = false; |
246 } else { | 252 } else { |
247 LOG(ERROR) << "failed to re-initialize device info"; | 253 LOG(ERROR) << "failed to re-initialize device info"; |
248 } | 254 } |
249 } else { | 255 } else { |
250 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); | 256 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); |
251 } | 257 } |
| 258 if (is_type_a_) |
| 259 current_slot_ = 0; |
| 260 break; |
| 261 case SYN_MT_REPORT: |
| 262 // For type A devices, we just get a stream of all current contacts, |
| 263 // in some arbitrary order. |
| 264 events_[current_slot_].type_ = ET_TOUCH_PRESSED; |
| 265 if (events_.size() - 1 > current_slot_) |
| 266 current_slot_++; |
| 267 is_type_a_ = true; |
252 break; | 268 break; |
253 case SYN_DROPPED: | 269 case SYN_DROPPED: |
254 // Some buffer has overrun. We ignore all events up to and | 270 // Some buffer has overrun. We ignore all events up to and |
255 // including the next SYN_REPORT. | 271 // including the next SYN_REPORT. |
256 syn_dropped_ = true; | 272 syn_dropped_ = true; |
257 break; | 273 break; |
258 default: | 274 default: |
259 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; | 275 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; |
260 } | 276 } |
261 } | 277 } |
262 | 278 |
263 EventType TouchEventConverterEvdev::GetEventTypeForTouch( | 279 void TouchEventConverterEvdev::ReportEvent(int touch_id, |
264 const InProgressTouchEvdev& touch) { | 280 const InProgressEvents& event, |
265 if (touch.cancelled) | |
266 return ET_UNKNOWN; | |
267 | |
268 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(touch.slot)) { | |
269 if (touch.touching && !touch.was_touching) | |
270 return ET_UNKNOWN; | |
271 return ET_TOUCH_CANCELLED; | |
272 } | |
273 | |
274 if (touch.touching) | |
275 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; | |
276 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; | |
277 } | |
278 | |
279 void TouchEventConverterEvdev::ReportEvent(const InProgressTouchEvdev& event, | |
280 EventType event_type, | |
281 const base::TimeDelta& timestamp) { | 281 const base::TimeDelta& timestamp) { |
282 dispatcher_->DispatchTouchEvent(TouchEventParams( | 282 dispatcher_->DispatchTouchEvent(TouchEventParams( |
283 id_, event.slot, event_type, gfx::PointF(event.x, event.y), | 283 id_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), |
284 gfx::Vector2dF(event.radius_x, event.radius_y), event.pressure, | 284 gfx::Vector2dF(event.radius_x_, event.radius_y_), event.pressure_, |
285 timestamp)); | 285 timestamp)); |
286 } | 286 } |
287 | 287 |
288 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { | 288 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { |
289 if (touch_noise_finder_) | 289 for (size_t i = 0; i < events_.size(); i++) { |
290 touch_noise_finder_->HandleTouches(events_, delta); | 290 if (events_[i].altered_) { |
| 291 ReportEvent(i, events_[i], delta); |
291 | 292 |
292 for (size_t i = 0; i < events_.size(); i++) { | 293 // Subsequent events for this finger will be touch-move until it |
293 InProgressTouchEvdev* event = &events_[i]; | 294 // is released. |
294 if (!event->altered) | 295 events_[i].type_ = ET_TOUCH_MOVED; |
295 continue; | 296 events_[i].altered_ = false; |
296 | 297 } |
297 EventType event_type = GetEventTypeForTouch(*event); | |
298 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED) | |
299 event->cancelled = true; | |
300 | |
301 if (event_type != ET_UNKNOWN) | |
302 ReportEvent(*event, event_type, delta); | |
303 | |
304 event->was_touching = event->touching; | |
305 event->altered = false; | |
306 } | 298 } |
307 } | 299 } |
308 | 300 |
309 } // namespace ui | 301 } // namespace ui |
OLD | NEW |