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

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),
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 native_size_ = gfx::Size(x_num_tuxels_, y_num_tuxels_); 111 native_size_ = gfx::Size(x_num_tuxels_, y_num_tuxels_);
119 112
120 events_.resize(touch_points_); 113 events_.resize(touch_points_);
121 for (size_t i = 0; i < events_.size(); ++i) { 114 for (size_t i = 0; i < events_.size(); ++i) {
122 events_[i].finger_ = info.GetSlotValue(ABS_MT_TRACKING_ID, i); 115 events_[i].x = info.GetSlotValue(ABS_MT_POSITION_X, i);
123 events_[i].type_ = 116 events_[i].y = info.GetSlotValue(ABS_MT_POSITION_Y, i);
124 events_[i].finger_ < 0 ? ET_TOUCH_RELEASED : ET_TOUCH_PRESSED; 117 events_[i].tracking_id = info.GetSlotValue(ABS_MT_TRACKING_ID, i);
125 events_[i].x_ = info.GetSlotValue(ABS_MT_POSITION_X, i); 118 events_[i].touching = (events_[i].tracking_id >= 0);
126 events_[i].y_ = info.GetSlotValue(ABS_MT_POSITION_Y, i); 119 events_[i].slot = i;
127 events_[i].radius_x_ = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); 120 events_[i].radius_x = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i);
128 events_[i].radius_y_ = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); 121 events_[i].radius_y = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i);
129 events_[i].pressure_ = info.GetSlotValue(ABS_MT_PRESSURE, i); 122 events_[i].pressure = info.GetSlotValue(ABS_MT_PRESSURE, i);
130 } 123 }
131 } 124 }
132 125
133 bool TouchEventConverterEvdev::Reinitialize() { 126 bool TouchEventConverterEvdev::Reinitialize() {
134 EventDeviceInfo info; 127 EventDeviceInfo info;
135 if (info.Initialize(fd_)) { 128 if (info.Initialize(fd_)) {
136 Initialize(info); 129 Initialize(info);
137 return true; 130 return true;
138 } 131 }
139 return false; 132 return false;
140 } 133 }
141 134
142 bool TouchEventConverterEvdev::HasTouchscreen() const { 135 bool TouchEventConverterEvdev::HasTouchscreen() const {
143 return true; 136 return true;
144 } 137 }
145 138
146 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { 139 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const {
147 return native_size_; 140 return native_size_;
148 } 141 }
149 142
150 int TouchEventConverterEvdev::GetTouchPoints() const { 143 int TouchEventConverterEvdev::GetTouchPoints() const {
151 return touch_points_; 144 return touch_points_;
152 } 145 }
153 146
154 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { 147 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) {
155 input_event inputs[MAX_FINGERS * 6 + 1]; 148 input_event inputs[kNumTouchEvdevSlots * 6 + 1];
156 ssize_t read_size = read(fd, inputs, sizeof(inputs)); 149 ssize_t read_size = read(fd, inputs, sizeof(inputs));
157 if (read_size < 0) { 150 if (read_size < 0) {
158 if (errno == EINTR || errno == EAGAIN) 151 if (errno == EINTR || errno == EAGAIN)
159 return; 152 return;
160 if (errno != ENODEV) 153 if (errno != ENODEV)
161 PLOG(ERROR) << "error reading device " << path_.value(); 154 PLOG(ERROR) << "error reading device " << path_.value();
162 Stop(); 155 Stop();
163 return; 156 return;
164 } 157 }
165 158
166 if (ignore_events_) 159 if (ignore_events_)
167 return; 160 return;
168 161
169 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { 162 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) {
170 ProcessInputEvent(inputs[i]); 163 ProcessInputEvent(inputs[i]);
171 } 164 }
172 } 165 }
173 166
174 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { 167 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) {
175 if (input.type == EV_SYN) { 168 if (input.type == EV_SYN) {
176 ProcessSyn(input); 169 ProcessSyn(input);
177 } else if(syn_dropped_) { 170 } else if (syn_dropped_) {
178 // Do nothing. This branch indicates we have lost sync with the driver. 171 // Do nothing. This branch indicates we have lost sync with the driver.
179 } else if (input.type == EV_ABS) { 172 } else if (input.type == EV_ABS) {
180 if (events_.size() <= current_slot_) { 173 if (events_.size() <= current_slot_) {
181 LOG(ERROR) << "current_slot_ (" << current_slot_ 174 LOG(ERROR) << "current_slot_ (" << current_slot_
182 << ") >= events_.size() (" << events_.size() << ")"; 175 << ") >= events_.size() (" << events_.size() << ")";
183 } else { 176 } else {
184 ProcessAbs(input); 177 ProcessAbs(input);
185 } 178 }
186 } else if (input.type == EV_KEY) { 179 } else if (input.type == EV_KEY) {
187 switch (input.code) { 180 switch (input.code) {
188 case BTN_TOUCH: 181 case BTN_TOUCH:
189 break; 182 break;
190 default: 183 default:
191 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; 184 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code;
192 } 185 }
193 } else { 186 } else {
194 NOTIMPLEMENTED() << "invalid type: " << input.type; 187 NOTIMPLEMENTED() << "invalid type: " << input.type;
195 } 188 }
196 } 189 }
197 190
198 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { 191 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) {
199 switch (input.code) { 192 switch (input.code) {
200 case ABS_MT_TOUCH_MAJOR: 193 case ABS_MT_TOUCH_MAJOR:
201 // TODO(spang): If we have all of major, minor, and orientation, 194 // TODO(spang): If we have all of major, minor, and orientation,
202 // we can scale the ellipse correctly. However on the Pixel we get 195 // we can scale the ellipse correctly. However on the Pixel we get
203 // neither minor nor orientation, so this is all we can do. 196 // neither minor nor orientation, so this is all we can do.
204 events_[current_slot_].radius_x_ = input.value / 2.0f; 197 events_[current_slot_].radius_x = input.value / 2.0f;
205 break; 198 break;
206 case ABS_MT_TOUCH_MINOR: 199 case ABS_MT_TOUCH_MINOR:
207 events_[current_slot_].radius_y_ = input.value / 2.0f; 200 events_[current_slot_].radius_y = input.value / 2.0f;
208 break; 201 break;
209 case ABS_MT_POSITION_X: 202 case ABS_MT_POSITION_X:
210 events_[current_slot_].x_ = input.value; 203 events_[current_slot_].x = input.value;
211 break; 204 break;
212 case ABS_MT_POSITION_Y: 205 case ABS_MT_POSITION_Y:
213 events_[current_slot_].y_ = input.value; 206 events_[current_slot_].y = input.value;
214 break; 207 break;
215 case ABS_MT_TRACKING_ID: 208 case ABS_MT_TRACKING_ID:
216 if (input.value < 0) { 209 if (input.value < 0) {
217 events_[current_slot_].type_ = ET_TOUCH_RELEASED; 210 events_[current_slot_].touching = false;
218 } else { 211 } else {
219 events_[current_slot_].finger_ = input.value; 212 events_[current_slot_].touching = true;
220 events_[current_slot_].type_ = ET_TOUCH_PRESSED; 213 events_[current_slot_].cancelled = false;
221 } 214 }
215 events_[current_slot_].tracking_id = input.value;
222 break; 216 break;
223 case ABS_MT_PRESSURE: 217 case ABS_MT_PRESSURE:
224 events_[current_slot_].pressure_ = input.value - pressure_min_; 218 events_[current_slot_].pressure = input.value - pressure_min_;
225 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; 219 events_[current_slot_].pressure /= pressure_max_ - pressure_min_;
226 break; 220 break;
227 case ABS_MT_SLOT: 221 case ABS_MT_SLOT:
228 if (input.value >= 0 && 222 if (input.value >= 0 &&
229 static_cast<size_t>(input.value) < events_.size()) { 223 static_cast<size_t>(input.value) < events_.size()) {
230 current_slot_ = input.value; 224 current_slot_ = input.value;
231 } else { 225 } else {
232 LOG(ERROR) << "invalid touch event index: " << input.value; 226 LOG(ERROR) << "invalid touch event index: " << input.value;
233 return; 227 return;
234 } 228 }
235 break; 229 break;
236 default: 230 default:
237 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; 231 DVLOG(5) << "unhandled code for EV_ABS: " << input.code;
238 return; 232 return;
239 } 233 }
240 events_[current_slot_].altered_ = true; 234 events_[current_slot_].altered = true;
241 } 235 }
242 236
243 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { 237 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) {
244 switch (input.code) { 238 switch (input.code) {
245 case SYN_REPORT: 239 case SYN_REPORT:
246 if (syn_dropped_) { 240 if (syn_dropped_) {
247 // Have to re-initialize. 241 // Have to re-initialize.
248 if (Reinitialize()) { 242 if (Reinitialize()) {
249 syn_dropped_ = false; 243 syn_dropped_ = false;
250 for(InProgressEvents& event: events_) 244 for(InProgressTouchEvdev& event : events_)
251 event.altered_ = false; 245 event.altered = false;
252 } else { 246 } else {
253 LOG(ERROR) << "failed to re-initialize device info"; 247 LOG(ERROR) << "failed to re-initialize device info";
254 } 248 }
255 } else { 249 } else {
256 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); 250 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input));
257 } 251 }
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;
268 break; 252 break;
269 case SYN_DROPPED: 253 case SYN_DROPPED:
270 // Some buffer has overrun. We ignore all events up to and 254 // Some buffer has overrun. We ignore all events up to and
271 // including the next SYN_REPORT. 255 // including the next SYN_REPORT.
272 syn_dropped_ = true; 256 syn_dropped_ = true;
273 break; 257 break;
274 default: 258 default:
275 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; 259 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code;
276 } 260 }
277 } 261 }
278 262
279 void TouchEventConverterEvdev::ReportEvent(int touch_id, 263 EventType TouchEventConverterEvdev::GetEventTypeForTouch(
280 const InProgressEvents& event, 264 const InProgressTouchEvdev& touch) {
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_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), 283 id_, event.slot, 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_)
290 touch_noise_finder_->HandleTouches(events_, delta);
291
289 for (size_t i = 0; i < events_.size(); i++) { 292 for (size_t i = 0; i < events_.size(); i++) {
290 if (events_[i].altered_) { 293 InProgressTouchEvdev* event = &events_[i];
291 ReportEvent(i, events_[i], delta); 294 if (!event->altered)
295 continue;
292 296
293 // Subsequent events for this finger will be touch-move until it 297 EventType event_type = GetEventTypeForTouch(*event);
294 // is released. 298 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED)
295 events_[i].type_ = ET_TOUCH_MOVED; 299 event->cancelled = true;
296 events_[i].altered_ = false; 300
297 } 301 if (event_type != ET_UNKNOWN)
302 ReportEvent(*event, event_type, delta);
303
304 event->was_touching = event->touching;
305 event->altered = false;
298 } 306 }
299 } 307 }
300 308
301 } // namespace ui 309 } // 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