Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: ui/events/ozone/evdev/touch_event_converter_evdev.cc

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

Powered by Google App Engine
This is Rietveld 408576698