Chromium Code Reviews| 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 if (!base::StringToInt(parts[3], &cal->bezel_bottom)) | 53 if (!base::StringToInt(parts[3], &cal->bezel_bottom)) |
| 54 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; | 54 DLOG(ERROR) << "Incorrect bottom border calibration value passed."; |
| 55 } | 55 } |
| 56 } | 56 } |
| 57 | 57 |
| 58 } // namespace | 58 } // namespace |
| 59 | 59 |
| 60 namespace ui { | 60 namespace ui { |
| 61 | 61 |
| 62 TouchEventConverterEvdev::InProgressEvents::InProgressEvents() | 62 TouchEventConverterEvdev::InProgressEvents::InProgressEvents() |
| 63 : x_(0), | 63 : altered_(false), |
| 64 x_(0), | |
| 64 y_(0), | 65 y_(0), |
| 65 id_(-1), | 66 id_(-1), |
| 66 finger_(-1), | 67 finger_(-1), |
| 67 type_(ET_UNKNOWN), | 68 type_(ET_UNKNOWN), |
| 68 radius_x_(0), | 69 radius_x_(0), |
| 69 radius_y_(0), | 70 radius_y_(0), |
| 70 pressure_(0) { | 71 pressure_(0) { |
| 71 } | 72 } |
| 72 | 73 |
| 73 TouchEventConverterEvdev::TouchEventConverterEvdev( | 74 TouchEventConverterEvdev::TouchEventConverterEvdev( |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; | 107 y_num_tuxels_ -= cal.bezel_top + cal.bezel_bottom; |
| 107 | 108 |
| 108 VLOG(1) << "applying touch calibration: " | 109 VLOG(1) << "applying touch calibration: " |
| 109 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, | 110 << base::StringPrintf("[%d, %d, %d, %d]", cal.bezel_left, |
| 110 cal.bezel_right, cal.bezel_top, | 111 cal.bezel_right, cal.bezel_top, |
| 111 cal.bezel_bottom); | 112 cal.bezel_bottom); |
| 112 } | 113 } |
| 113 | 114 |
| 114 native_size_ = gfx::Size(x_num_tuxels_, y_num_tuxels_); | 115 native_size_ = gfx::Size(x_num_tuxels_, y_num_tuxels_); |
| 115 | 116 |
| 116 for (int i = 0; | 117 events_.resize( |
| 117 i < std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, MAX_FINGERS); | 118 std::min<int>(info.GetAbsMaximum(ABS_MT_SLOT) + 1, MAX_FINGERS)); |
| 118 ++i) { | 119 for (int i = 0; i < events_.size(); ++i) { |
| 119 events_[i].finger_ = info.GetSlotValue(ABS_MT_TRACKING_ID, i); | 120 events_[i].finger_ = info.GetSlotValue(ABS_MT_TRACKING_ID, i); |
| 120 events_[i].type_ = | 121 events_[i].type_ = |
| 121 events_[i].finger_ < 0 ? ET_TOUCH_RELEASED : ET_TOUCH_PRESSED; | 122 events_[i].finger_ < 0 ? ET_TOUCH_RELEASED : ET_TOUCH_PRESSED; |
| 122 events_[i].x_ = info.GetSlotValue(ABS_MT_POSITION_X, i); | 123 events_[i].x_ = info.GetSlotValue(ABS_MT_POSITION_X, i); |
| 123 events_[i].y_ = info.GetSlotValue(ABS_MT_POSITION_Y, i); | 124 events_[i].y_ = info.GetSlotValue(ABS_MT_POSITION_Y, i); |
| 124 events_[i].radius_x_ = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); | 125 events_[i].radius_x_ = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); |
| 125 events_[i].radius_y_ = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); | 126 events_[i].radius_y_ = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); |
| 126 events_[i].pressure_ = info.GetSlotValue(ABS_MT_PRESSURE, i); | 127 events_[i].pressure_ = info.GetSlotValue(ABS_MT_PRESSURE, i); |
| 127 } | 128 } |
| 128 } | 129 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 163 ProcessInputEvent(inputs[i]); | 164 ProcessInputEvent(inputs[i]); |
| 164 } | 165 } |
| 165 } | 166 } |
| 166 | 167 |
| 167 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { | 168 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { |
| 168 if (input.type == EV_SYN) { | 169 if (input.type == EV_SYN) { |
| 169 ProcessSyn(input); | 170 ProcessSyn(input); |
| 170 } else if(syn_dropped_) { | 171 } else if(syn_dropped_) { |
| 171 // 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. |
| 172 } else if (input.type == EV_ABS) { | 173 } else if (input.type == EV_ABS) { |
| 173 if (current_slot_ >= MAX_FINGERS) { | |
| 174 LOG(ERROR) << "too many touch events: " << current_slot_; | |
| 175 return; | |
| 176 } | |
| 177 ProcessAbs(input); | 174 ProcessAbs(input); |
| 178 } else if (input.type == EV_KEY) { | 175 } else if (input.type == EV_KEY) { |
| 179 switch (input.code) { | 176 switch (input.code) { |
| 180 case BTN_TOUCH: | 177 case BTN_TOUCH: |
| 181 break; | 178 break; |
| 182 default: | 179 default: |
| 183 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; | 180 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
| 184 } | 181 } |
| 185 } else { | 182 } else { |
| 186 NOTIMPLEMENTED() << "invalid type: " << input.type; | 183 NOTIMPLEMENTED() << "invalid type: " << input.type; |
| 187 } | 184 } |
| 188 } | 185 } |
| 189 | 186 |
| 190 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { | 187 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { |
| 191 switch (input.code) { | 188 switch (input.code) { |
| 192 case ABS_MT_TOUCH_MAJOR: | 189 case ABS_MT_TOUCH_MAJOR: |
| 193 altered_slots_.set(current_slot_); | |
| 194 // TODO(spang): If we have all of major, minor, and orientation, | 190 // TODO(spang): If we have all of major, minor, and orientation, |
| 195 // we can scale the ellipse correctly. However on the Pixel we get | 191 // we can scale the ellipse correctly. However on the Pixel we get |
| 196 // neither minor nor orientation, so this is all we can do. | 192 // neither minor nor orientation, so this is all we can do. |
| 197 events_[current_slot_].radius_x_ = input.value / 2.0f; | 193 events_[current_slot_].radius_x_ = input.value / 2.0f; |
| 198 break; | 194 break; |
| 199 case ABS_MT_TOUCH_MINOR: | 195 case ABS_MT_TOUCH_MINOR: |
| 200 altered_slots_.set(current_slot_); | |
| 201 events_[current_slot_].radius_y_ = input.value / 2.0f; | 196 events_[current_slot_].radius_y_ = input.value / 2.0f; |
| 202 break; | 197 break; |
| 203 case ABS_MT_POSITION_X: | 198 case ABS_MT_POSITION_X: |
| 204 altered_slots_.set(current_slot_); | |
| 205 events_[current_slot_].x_ = input.value; | 199 events_[current_slot_].x_ = input.value; |
| 206 break; | 200 break; |
| 207 case ABS_MT_POSITION_Y: | 201 case ABS_MT_POSITION_Y: |
| 208 altered_slots_.set(current_slot_); | |
| 209 events_[current_slot_].y_ = input.value; | 202 events_[current_slot_].y_ = input.value; |
| 210 break; | 203 break; |
| 211 case ABS_MT_TRACKING_ID: | 204 case ABS_MT_TRACKING_ID: |
| 212 altered_slots_.set(current_slot_); | |
| 213 if (input.value < 0) { | 205 if (input.value < 0) { |
| 214 events_[current_slot_].type_ = ET_TOUCH_RELEASED; | 206 events_[current_slot_].type_ = ET_TOUCH_RELEASED; |
| 215 } else { | 207 } else { |
| 216 events_[current_slot_].finger_ = input.value; | 208 events_[current_slot_].finger_ = input.value; |
| 217 events_[current_slot_].type_ = ET_TOUCH_PRESSED; | 209 events_[current_slot_].type_ = ET_TOUCH_PRESSED; |
| 218 } | 210 } |
| 219 break; | 211 break; |
| 220 case ABS_MT_PRESSURE: | 212 case ABS_MT_PRESSURE: |
| 221 altered_slots_.set(current_slot_); | |
| 222 events_[current_slot_].pressure_ = input.value - pressure_min_; | 213 events_[current_slot_].pressure_ = input.value - pressure_min_; |
| 223 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; | 214 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; |
| 224 break; | 215 break; |
| 225 case ABS_MT_SLOT: | 216 case ABS_MT_SLOT: |
| 226 if (input.value >= MAX_FINGERS) { | 217 if (input.value >= 0 && input.value < events_.size()) { |
| 227 LOG(ERROR) << "multi-touch slot " << input.value | 218 current_slot_ = input.value; |
| 228 << " exceeds MAX_FINGERS"; | 219 } else { |
| 229 break; | 220 LOG(ERROR) << "invalid touch event index: " << input.value; |
| 221 return; | |
| 230 } | 222 } |
| 231 current_slot_ = input.value; | |
| 232 altered_slots_.set(current_slot_); | |
| 233 break; | 223 break; |
| 234 default: | 224 default: |
| 235 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; | 225 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; |
| 226 return; | |
| 236 } | 227 } |
| 228 events_[current_slot_].altered_ = true; | |
| 237 } | 229 } |
| 238 | 230 |
| 239 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { | 231 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { |
| 240 switch (input.code) { | 232 switch (input.code) { |
| 241 case SYN_REPORT: | 233 case SYN_REPORT: |
| 242 if (syn_dropped_) { | 234 if (syn_dropped_) { |
| 243 // Have to re-initialize. | 235 // Have to re-initialize. |
| 244 if (Reinitialize()) { | 236 if (Reinitialize()) { |
| 245 syn_dropped_ = false; | 237 syn_dropped_ = false; |
| 246 altered_slots_.reset(); | 238 events_.clear(); |
| 247 } else { | 239 } else { |
| 248 LOG(ERROR) << "failed to re-initialize device info"; | 240 LOG(ERROR) << "failed to re-initialize device info"; |
| 249 } | 241 } |
| 250 } else { | 242 } else { |
| 251 ReportEvents(base::TimeDelta::FromMicroseconds( | 243 ReportEvents(base::TimeDelta::FromMicroseconds( |
| 252 input.time.tv_sec * 1000000 + input.time.tv_usec)); | 244 input.time.tv_sec * 1000000 + input.time.tv_usec)); |
| 253 } | 245 } |
| 254 if (is_type_a_) | 246 if (is_type_a_) |
| 255 current_slot_ = 0; | 247 current_slot_ = 0; |
| 256 break; | 248 break; |
| 257 case SYN_MT_REPORT: | 249 case SYN_MT_REPORT: |
| 258 // For type A devices, we just get a stream of all current contacts, | 250 // For type A devices, we just get a stream of all current contacts, |
| 259 // in some arbitrary order. | 251 // in some arbitrary order. |
| 260 events_[current_slot_++].type_ = ET_TOUCH_PRESSED; | 252 if (events_.size() > current_slot_) |
| 253 events_[current_slot_++].type_ = ET_TOUCH_PRESSED; | |
|
spang
2015/02/03 17:05:23
if current_slot_ == size() - 1 then ++ here will p
achaulk
2015/02/04 16:40:34
Oops, good catch
| |
| 261 is_type_a_ = true; | 254 is_type_a_ = true; |
| 262 break; | 255 break; |
| 263 case SYN_DROPPED: | 256 case SYN_DROPPED: |
| 264 // Some buffer has overrun. We ignore all events up to and | 257 // Some buffer has overrun. We ignore all events up to and |
| 265 // including the next SYN_REPORT. | 258 // including the next SYN_REPORT. |
| 266 syn_dropped_ = true; | 259 syn_dropped_ = true; |
| 267 break; | 260 break; |
| 268 default: | 261 default: |
| 269 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; | 262 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; |
| 270 } | 263 } |
| 271 } | 264 } |
| 272 | 265 |
| 273 void TouchEventConverterEvdev::ReportEvent(int touch_id, | 266 void TouchEventConverterEvdev::ReportEvent(int touch_id, |
| 274 const InProgressEvents& event, | 267 const InProgressEvents& event, |
| 275 const base::TimeDelta& timestamp) { | 268 const base::TimeDelta& timestamp) { |
| 276 dispatcher_->DispatchTouchEvent(TouchEventParams( | 269 dispatcher_->DispatchTouchEvent(TouchEventParams( |
| 277 id_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), | 270 id_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), |
| 278 gfx::Vector2dF(event.radius_x_, event.radius_y_), event.pressure_, | 271 gfx::Vector2dF(event.radius_x_, event.radius_y_), event.pressure_, |
| 279 timestamp)); | 272 timestamp)); |
| 280 } | 273 } |
| 281 | 274 |
| 282 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { | 275 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { |
| 283 for (int i = 0; i < MAX_FINGERS; i++) { | 276 for (size_t i = 0; i < events_.size(); i++) { |
| 284 if (altered_slots_[i]) { | 277 if (events_[i].altered_) { |
| 285 ReportEvent(i, events_[i], delta); | 278 ReportEvent(i, events_[i], delta); |
| 286 | 279 |
| 287 // Subsequent events for this finger will be touch-move until it | 280 // Subsequent events for this finger will be touch-move until it |
| 288 // is released. | 281 // is released. |
| 289 events_[i].type_ = ET_TOUCH_MOVED; | 282 events_[i].type_ = ET_TOUCH_MOVED; |
| 283 events_[i].altered_ = false; | |
| 290 } | 284 } |
| 291 } | 285 } |
| 292 altered_slots_.reset(); | |
| 293 } | 286 } |
| 294 | 287 |
| 295 } // namespace ui | 288 } // namespace ui |
| OLD | NEW |