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

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

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