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

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

Issue 2263693003: Add palm suppression feature to EventConverterEvdev (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@stylus
Patch Set: fixed unit tests Created 4 years, 3 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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 touch_noise_finder_.reset(new TouchNoiseFinder); 122 touch_noise_finder_.reset(new TouchNoiseFinder);
123 } 123 }
124 touch_evdev_debug_buffer_.Initialize(devinfo); 124 touch_evdev_debug_buffer_.Initialize(devinfo);
125 } 125 }
126 126
127 TouchEventConverterEvdev::~TouchEventConverterEvdev() { 127 TouchEventConverterEvdev::~TouchEventConverterEvdev() {
128 } 128 }
129 129
130 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) { 130 void TouchEventConverterEvdev::Initialize(const EventDeviceInfo& info) {
131 has_mt_ = info.HasMultitouch(); 131 has_mt_ = info.HasMultitouch();
132 has_pen_ = info.HasKeyEvent(BTN_TOOL_PEN);
132 133
133 if (has_mt_) { 134 if (has_mt_) {
134 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE); 135 pressure_min_ = info.GetAbsMinimum(ABS_MT_PRESSURE);
135 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE); 136 pressure_max_ = info.GetAbsMaximum(ABS_MT_PRESSURE);
136 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X); 137 x_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_X);
137 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1; 138 x_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_X) - x_min_tuxels_ + 1;
138 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y); 139 y_min_tuxels_ = info.GetAbsMinimum(ABS_MT_POSITION_Y);
139 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1; 140 y_num_tuxels_ = info.GetAbsMaximum(ABS_MT_POSITION_Y) - y_min_tuxels_ + 1;
140 touch_points_ = 141 touch_points_ =
141 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots); 142 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, kNumTouchEvdevSlots);
143 major_max_ = info.GetAbsMaximum(ABS_MT_TOUCH_MAJOR);
142 current_slot_ = info.GetAbsValue(ABS_MT_SLOT); 144 current_slot_ = info.GetAbsValue(ABS_MT_SLOT);
143 } else { 145 } else {
144 pressure_min_ = info.GetAbsMinimum(ABS_PRESSURE); 146 pressure_min_ = info.GetAbsMinimum(ABS_PRESSURE);
145 pressure_max_ = info.GetAbsMaximum(ABS_PRESSURE); 147 pressure_max_ = info.GetAbsMaximum(ABS_PRESSURE);
146 x_min_tuxels_ = info.GetAbsMinimum(ABS_X); 148 x_min_tuxels_ = info.GetAbsMinimum(ABS_X);
147 x_num_tuxels_ = info.GetAbsMaximum(ABS_X) - x_min_tuxels_ + 1; 149 x_num_tuxels_ = info.GetAbsMaximum(ABS_X) - x_min_tuxels_ + 1;
148 y_min_tuxels_ = info.GetAbsMinimum(ABS_Y); 150 y_min_tuxels_ = info.GetAbsMinimum(ABS_Y);
149 y_num_tuxels_ = info.GetAbsMaximum(ABS_Y) - y_min_tuxels_ + 1; 151 y_num_tuxels_ = info.GetAbsMaximum(ABS_Y) - y_min_tuxels_ + 1;
150 touch_points_ = 1; 152 touch_points_ = 1;
153 major_max_ = 0;
151 current_slot_ = 0; 154 current_slot_ = 0;
152 } 155 }
153 156
154 quirk_left_mouse_button_ = 157 quirk_left_mouse_button_ =
155 !has_mt_ && !info.HasKeyEvent(BTN_TOUCH) && info.HasKeyEvent(BTN_LEFT); 158 !has_mt_ && !info.HasKeyEvent(BTN_TOUCH) && info.HasKeyEvent(BTN_LEFT);
156 159
157 // Apply --touch-calibration. 160 // Apply --touch-calibration.
158 if (type() == INPUT_DEVICE_INTERNAL) { 161 if (type() == INPUT_DEVICE_INTERNAL) {
159 TouchCalibration cal = {}; 162 TouchCalibration cal = {};
160 GetTouchCalibration(&cal); 163 GetTouchCalibration(&cal);
(...skipping 20 matching lines...) Expand all
181 ABS_MT_TRACKING_ID, i, kTrackingIdForUnusedSlot); 184 ABS_MT_TRACKING_ID, i, kTrackingIdForUnusedSlot);
182 events_[i].touching = (events_[i].tracking_id >= 0); 185 events_[i].touching = (events_[i].tracking_id >= 0);
183 events_[i].slot = i; 186 events_[i].slot = i;
184 187
185 // Dirty the slot so we'll update the consumer at the first opportunity. 188 // Dirty the slot so we'll update the consumer at the first opportunity.
186 // We can't dispatch here as this is currently called on the worker pool. 189 // We can't dispatch here as this is currently called on the worker pool.
187 // TODO(spang): Move initialization off worker pool. 190 // TODO(spang): Move initialization off worker pool.
188 events_[i].altered = true; 191 events_[i].altered = true;
189 192
190 // Optional bits. 193 // Optional bits.
191 events_[i].radius_x = 194 int touch_major =
192 info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MAJOR, i, 0) / 2.0f; 195 info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MAJOR, i, 0);
196 events_[i].radius_x = touch_major / 2.0f;
193 events_[i].radius_y = 197 events_[i].radius_y =
194 info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MINOR, i, 0) / 2.0f; 198 info.GetAbsMtSlotValueWithDefault(ABS_MT_TOUCH_MINOR, i, 0) / 2.0f;
195 events_[i].pressure = ScalePressure( 199 events_[i].pressure = ScalePressure(
196 info.GetAbsMtSlotValueWithDefault(ABS_MT_PRESSURE, i, 0)); 200 info.GetAbsMtSlotValueWithDefault(ABS_MT_PRESSURE, i, 0));
201 events_[i].cancelled = (major_max_ > 0 && touch_major == major_max_);
197 } 202 }
198 } else { 203 } else {
199 // TODO(spang): Add key state to EventDeviceInfo to allow initial contact. 204 // TODO(spang): Add key state to EventDeviceInfo to allow initial contact.
200 // (and make sure to take into account quirk_left_mouse_button_) 205 // (and make sure to take into account quirk_left_mouse_button_)
201 events_[0].x = 0; 206 events_[0].x = 0;
202 events_[0].y = 0; 207 events_[0].y = 0;
203 events_[0].tracking_id = kTrackingIdForUnusedSlot; 208 events_[0].tracking_id = kTrackingIdForUnusedSlot;
204 events_[0].touching = false; 209 events_[0].touching = false;
205 events_[0].slot = 0; 210 events_[0].slot = 0;
206 events_[0].radius_x = 0; 211 events_[0].radius_x = 0;
207 events_[0].radius_y = 0; 212 events_[0].radius_y = 0;
208 events_[0].pressure = 0; 213 events_[0].pressure = 0;
209 events_[0].tool_code = 0; 214 events_[0].tool_code = 0;
215 events_[0].cancelled = false;
210 } 216 }
211 } 217 }
212 218
213 void TouchEventConverterEvdev::Reinitialize() { 219 void TouchEventConverterEvdev::Reinitialize() {
214 ReleaseButtons(); 220 ReleaseButtons();
215 221
216 EventDeviceInfo info; 222 EventDeviceInfo info;
217 if (!info.Initialize(fd_, path_)) { 223 if (!info.Initialize(fd_, path_)) {
218 LOG(ERROR) << "Failed to synchronize state for touch device: " 224 LOG(ERROR) << "Failed to synchronize state for touch device: "
219 << path_.value(); 225 << path_.value();
220 Stop(); 226 Stop();
221 return; 227 return;
222 } 228 }
223 Initialize(info); 229 Initialize(info);
224 } 230 }
225 231
226 bool TouchEventConverterEvdev::HasTouchscreen() const { 232 bool TouchEventConverterEvdev::HasTouchscreen() const {
227 return true; 233 return true;
228 } 234 }
229 235
236 bool TouchEventConverterEvdev::HasPen() const {
237 return has_pen_;
238 }
239
230 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { 240 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const {
231 return gfx::Size(x_num_tuxels_, y_num_tuxels_); 241 return gfx::Size(x_num_tuxels_, y_num_tuxels_);
232 } 242 }
233 243
234 int TouchEventConverterEvdev::GetTouchPoints() const { 244 int TouchEventConverterEvdev::GetTouchPoints() const {
235 return touch_points_; 245 return touch_points_;
236 } 246 }
237 247
238 void TouchEventConverterEvdev::OnEnabled() { 248 void TouchEventConverterEvdev::OnEnabled() {
239 ReportEvents(EventTimeForNow());
240 } 249 }
241 250
242 void TouchEventConverterEvdev::OnDisabled() { 251 void TouchEventConverterEvdev::OnDisabled() {
243 ReleaseTouches(); 252 ReleaseTouches();
244 ReleaseButtons(); 253 ReleaseButtons();
254 if (enable_palm_suppression_callback_) {
255 enable_palm_suppression_callback_.Run(false);
256 }
245 } 257 }
246 258
247 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { 259 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) {
248 TRACE_EVENT1("evdev", 260 TRACE_EVENT1("evdev",
249 "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", 261 "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd",
250 fd); 262 fd);
251 263
252 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; 264 input_event inputs[kNumTouchEvdevSlots * 6 + 1];
253 ssize_t read_size = read(fd, inputs, sizeof(inputs)); 265 ssize_t read_size = read(fd, inputs, sizeof(inputs));
254 if (read_size < 0) { 266 if (read_size < 0) {
255 if (errno == EINTR || errno == EAGAIN) 267 if (errno == EINTR || errno == EAGAIN)
256 return; 268 return;
257 if (errno != ENODEV) 269 if (errno != ENODEV)
258 PLOG(ERROR) << "error reading device " << path_.value(); 270 PLOG(ERROR) << "error reading device " << path_.value();
259 Stop(); 271 Stop();
260 return; 272 return;
261 } 273 }
262 274
263 if (!enabled_) {
264 dropped_events_ = true;
265 return;
266 }
267
268 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { 275 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) {
269 if (!has_mt_) { 276 if (!has_mt_) {
270 // Emulate the device as an MT device with only 1 slot by inserting extra 277 // Emulate the device as an MT device with only 1 slot by inserting extra
271 // MT protocol events in the stream. 278 // MT protocol events in the stream.
272 EmulateMultitouchEvent(inputs[i]); 279 EmulateMultitouchEvent(inputs[i]);
273 } 280 }
274 281
275 ProcessMultitouchEvent(inputs[i]); 282 ProcessMultitouchEvent(inputs[i]);
276 } 283 }
277 } 284 }
278 285
279 void TouchEventConverterEvdev::DumpTouchEventLog(const char* filename) { 286 void TouchEventConverterEvdev::DumpTouchEventLog(const char* filename) {
280 touch_evdev_debug_buffer_.DumpLog(filename); 287 touch_evdev_debug_buffer_.DumpLog(filename);
281 } 288 }
282 289
283 void TouchEventConverterEvdev::SetTouchEventLoggingEnabled(bool enabled) { 290 void TouchEventConverterEvdev::SetTouchEventLoggingEnabled(bool enabled) {
284 touch_logging_enabled_ = enabled; 291 touch_logging_enabled_ = enabled;
285 } 292 }
286 293
294 void TouchEventConverterEvdev::SetPalmSuppressionCallback(
295 const base::Callback<void(bool)>& callback) {
296 enable_palm_suppression_callback_ = callback;
297 }
298
287 void TouchEventConverterEvdev::ProcessMultitouchEvent( 299 void TouchEventConverterEvdev::ProcessMultitouchEvent(
288 const input_event& input) { 300 const input_event& input) {
289 if (touch_logging_enabled_) 301 if (touch_logging_enabled_)
290 touch_evdev_debug_buffer_.ProcessEvent(current_slot_, &input); 302 touch_evdev_debug_buffer_.ProcessEvent(current_slot_, &input);
291 303
292 if (input.type == EV_SYN) { 304 if (input.type == EV_SYN) {
293 ProcessSyn(input); 305 ProcessSyn(input);
294 } else if (dropped_events_) { 306 } else if (dropped_events_) {
295 // Do nothing. This branch indicates we have lost sync with the driver. 307 // Do nothing. This branch indicates we have lost sync with the driver.
296 } else if (input.type == EV_ABS) { 308 } else if (input.type == EV_ABS) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 // Do not change tool types while touching to prevent inconsistencies 362 // Do not change tool types while touching to prevent inconsistencies
351 // from switching between Mouse and TouchEvents. 363 // from switching between Mouse and TouchEvents.
352 if (events_[current_slot_].was_touching) 364 if (events_[current_slot_].was_touching)
353 break; 365 break;
354 366
355 if (input.value > 0) { 367 if (input.value > 0) {
356 events_[current_slot_].tool_code = input.code; 368 events_[current_slot_].tool_code = input.code;
357 } else { 369 } else {
358 events_[current_slot_].tool_code = 0; 370 events_[current_slot_].tool_code = 0;
359 } 371 }
372 events_[current_slot_].altered = true;
360 break; 373 break;
361 default: 374 default:
362 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; 375 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code;
363 } 376 }
364 } 377 }
365 378
366 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { 379 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) {
367 switch (input.code) { 380 switch (input.code) {
368 case ABS_MT_TOUCH_MAJOR: 381 case ABS_MT_TOUCH_MAJOR:
369 // TODO(spang): If we have all of major, minor, and orientation, 382 // TODO(spang): If we have all of major, minor, and orientation,
370 // we can scale the ellipse correctly. However on the Pixel we get 383 // we can scale the ellipse correctly. However on the Pixel we get
371 // neither minor nor orientation, so this is all we can do. 384 // neither minor nor orientation, so this is all we can do.
372 events_[current_slot_].radius_x = input.value / 2.0f; 385 events_[current_slot_].radius_x = input.value / 2.0f;
386
387 // The MT protocol cannot communicate cancelled touches, so some kernel
388 // drivers will identify palms by setting touch major to max.
389 if (major_max_ > 0 && input.value == major_max_)
390 events_[current_slot_].cancelled = true;
373 break; 391 break;
374 case ABS_MT_TOUCH_MINOR: 392 case ABS_MT_TOUCH_MINOR:
375 events_[current_slot_].radius_y = input.value / 2.0f; 393 events_[current_slot_].radius_y = input.value / 2.0f;
376 break; 394 break;
377 case ABS_MT_POSITION_X: 395 case ABS_MT_POSITION_X:
378 events_[current_slot_].x = input.value; 396 events_[current_slot_].x = input.value;
379 break; 397 break;
380 case ABS_MT_POSITION_Y: 398 case ABS_MT_POSITION_Y:
381 events_[current_slot_].y = input.value; 399 events_[current_slot_].y = input.value;
382 break; 400 break;
(...skipping 29 matching lines...) Expand all
412 // including the next SYN_REPORT. 430 // including the next SYN_REPORT.
413 dropped_events_ = true; 431 dropped_events_ = true;
414 break; 432 break;
415 default: 433 default:
416 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; 434 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code;
417 } 435 }
418 } 436 }
419 437
420 EventType TouchEventConverterEvdev::GetEventTypeForTouch( 438 EventType TouchEventConverterEvdev::GetEventTypeForTouch(
421 const InProgressTouchEvdev& touch) { 439 const InProgressTouchEvdev& touch) {
422 if (touch.cancelled) 440 if (touch.was_cancelled)
423 return ET_UNKNOWN; 441 return ET_UNKNOWN;
424 442
425 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(touch.slot)) { 443 if (touch.cancelled)
426 if (touch.touching && !touch.was_touching) 444 return touch.was_touching ? ET_TOUCH_CANCELLED : ET_UNKNOWN;
427 return ET_UNKNOWN;
428 return ET_TOUCH_CANCELLED;
429 }
430 445
431 if (touch.touching) 446 if (touch.touching)
432 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED; 447 return touch.was_touching ? ET_TOUCH_MOVED : ET_TOUCH_PRESSED;
433 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN; 448 return touch.was_touching ? ET_TOUCH_RELEASED : ET_UNKNOWN;
434 } 449 }
435 450
436 void TouchEventConverterEvdev::ReportTouchEvent( 451 void TouchEventConverterEvdev::ReportTouchEvent(
437 const InProgressTouchEvdev& event, 452 const InProgressTouchEvdev& event,
438 EventType event_type, 453 EventType event_type,
439 base::TimeTicks timestamp) { 454 base::TimeTicks timestamp) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 } 488 }
474 489
475 if (touch_noise_finder_) 490 if (touch_noise_finder_)
476 touch_noise_finder_->HandleTouches(events_, timestamp); 491 touch_noise_finder_->HandleTouches(events_, timestamp);
477 492
478 for (size_t i = 0; i < events_.size(); i++) { 493 for (size_t i = 0; i < events_.size(); i++) {
479 InProgressTouchEvdev* event = &events_[i]; 494 InProgressTouchEvdev* event = &events_[i];
480 if (!event->altered) 495 if (!event->altered)
481 continue; 496 continue;
482 497
498 if (enable_palm_suppression_callback_)
499 enable_palm_suppression_callback_.Run(event->tool_code > 0);
500
501 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(event->slot))
502 event->cancelled = true;
503
483 if (event->tool_code > 0) { 504 if (event->tool_code > 0) {
484 ReportStylusEvent(*event, timestamp); 505 ReportStylusEvent(*event, timestamp);
485 } else { 506 } else {
486 EventType event_type = GetEventTypeForTouch(*event); 507 EventType event_type = GetEventTypeForTouch(*event);
487 if (event_type == ET_UNKNOWN || event_type == ET_TOUCH_CANCELLED)
488 event->cancelled = true;
489
490 if (event_type != ET_UNKNOWN) 508 if (event_type != ET_UNKNOWN)
491 ReportTouchEvent(*event, event_type, timestamp); 509 ReportTouchEvent(*event, event_type, timestamp);
492 } 510 }
493 511
512 event->was_cancelled = event->cancelled;
494 event->was_touching = event->touching; 513 event->was_touching = event->touching;
495 event->altered = false; 514 event->altered = false;
496 event->btn_left.changed = false; 515 event->btn_left.changed = false;
497 event->btn_right.changed = false; 516 event->btn_right.changed = false;
498 event->btn_middle.changed = false; 517 event->btn_middle.changed = false;
499 } 518 }
500 } 519 }
501 520
502 void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) { 521 void TouchEventConverterEvdev::UpdateTrackingId(int slot, int tracking_id) {
503 InProgressTouchEvdev* event = &events_[slot]; 522 InProgressTouchEvdev* event = &events_[slot];
504 523
505 if (event->tracking_id == tracking_id) 524 if (event->tracking_id == tracking_id)
506 return; 525 return;
507 526
508 event->tracking_id = tracking_id; 527 event->tracking_id = tracking_id;
509 event->touching = (tracking_id >= 0); 528 event->touching = (tracking_id >= 0);
510 event->altered = true; 529 event->altered = true;
511 530
512 if (tracking_id >= 0) 531 if (tracking_id >= 0) {
513 event->cancelled = false; 532 event->was_cancelled = false;
533 event->cancelled = !enabled_;
534 }
514 } 535 }
515 536
516 void TouchEventConverterEvdev::ReleaseTouches() { 537 void TouchEventConverterEvdev::ReleaseTouches() {
517 for (size_t slot = 0; slot < events_.size(); slot++) 538 for (size_t slot = 0; slot < events_.size(); slot++) {
518 UpdateTrackingId(slot, kTrackingIdForUnusedSlot); 539 events_[slot].cancelled = true;
540 events_[slot].altered = true;
541 }
519 542
520 ReportEvents(EventTimeForNow()); 543 ReportEvents(EventTimeForNow());
521 } 544 }
522 545
523 void TouchEventConverterEvdev::ReleaseButtons() { 546 void TouchEventConverterEvdev::ReleaseButtons() {
524 for (size_t slot = 0; slot < events_.size(); slot++) { 547 for (size_t slot = 0; slot < events_.size(); slot++) {
525 InProgressTouchEvdev* event = &events_[slot]; 548 InProgressTouchEvdev* event = &events_[slot];
526 549
527 if (event->btn_left.down) { 550 if (event->btn_left.down) {
528 event->btn_left.down = false; 551 event->btn_left.down = false;
(...skipping 17 matching lines...) Expand all
546 if (pressure_max_ - pressure_min_) 569 if (pressure_max_ - pressure_min_)
547 pressure /= pressure_max_ - pressure_min_; 570 pressure /= pressure_max_ - pressure_min_;
548 return pressure; 571 return pressure;
549 } 572 }
550 573
551 int TouchEventConverterEvdev::NextTrackingId() { 574 int TouchEventConverterEvdev::NextTrackingId() {
552 return next_tracking_id_++ & kMaxTrackingId; 575 return next_tracking_id_++ & kMaxTrackingId;
553 } 576 }
554 577
555 } // namespace ui 578 } // 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