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 11 matching lines...) Expand all Loading... | |
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 Loading... | |
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].slot = i; |
126 events_[i].y_ = info.GetSlotValue(ABS_MT_POSITION_Y, i); | 120 events_[i].type = |
127 events_[i].radius_x_ = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); | 121 events_[i].tracking_id < 0 ? ET_TOUCH_RELEASED : ET_TOUCH_PRESSED; |
128 events_[i].radius_y_ = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); | 122 events_[i].radius_x = info.GetSlotValue(ABS_MT_TOUCH_MAJOR, i); |
129 events_[i].pressure_ = info.GetSlotValue(ABS_MT_PRESSURE, i); | 123 events_[i].radius_y = info.GetSlotValue(ABS_MT_TOUCH_MINOR, i); |
124 events_[i].pressure = info.GetSlotValue(ABS_MT_PRESSURE, i); | |
130 } | 125 } |
131 } | 126 } |
132 | 127 |
133 bool TouchEventConverterEvdev::Reinitialize() { | 128 bool TouchEventConverterEvdev::Reinitialize() { |
134 EventDeviceInfo info; | 129 EventDeviceInfo info; |
135 if (info.Initialize(fd_)) { | 130 if (info.Initialize(fd_)) { |
136 Initialize(info); | 131 Initialize(info); |
137 return true; | 132 return true; |
138 } | 133 } |
139 return false; | 134 return false; |
140 } | 135 } |
141 | 136 |
142 bool TouchEventConverterEvdev::HasTouchscreen() const { | 137 bool TouchEventConverterEvdev::HasTouchscreen() const { |
143 return true; | 138 return true; |
144 } | 139 } |
145 | 140 |
146 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { | 141 gfx::Size TouchEventConverterEvdev::GetTouchscreenSize() const { |
147 return native_size_; | 142 return native_size_; |
148 } | 143 } |
149 | 144 |
150 int TouchEventConverterEvdev::GetTouchPoints() const { | 145 int TouchEventConverterEvdev::GetTouchPoints() const { |
151 return touch_points_; | 146 return touch_points_; |
152 } | 147 } |
153 | 148 |
154 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { | 149 void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { |
155 input_event inputs[MAX_FINGERS * 6 + 1]; | 150 input_event inputs[kNumTouchEvdevSlots * 6 + 1]; |
156 ssize_t read_size = read(fd, inputs, sizeof(inputs)); | 151 ssize_t read_size = read(fd, inputs, sizeof(inputs)); |
157 if (read_size < 0) { | 152 if (read_size < 0) { |
158 if (errno == EINTR || errno == EAGAIN) | 153 if (errno == EINTR || errno == EAGAIN) |
159 return; | 154 return; |
160 if (errno != ENODEV) | 155 if (errno != ENODEV) |
161 PLOG(ERROR) << "error reading device " << path_.value(); | 156 PLOG(ERROR) << "error reading device " << path_.value(); |
162 Stop(); | 157 Stop(); |
163 return; | 158 return; |
164 } | 159 } |
165 | 160 |
166 if (ignore_events_) | 161 if (ignore_events_) |
167 return; | 162 return; |
168 | 163 |
169 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { | 164 for (unsigned i = 0; i < read_size / sizeof(*inputs); i++) { |
170 ProcessInputEvent(inputs[i]); | 165 ProcessInputEvent(inputs[i]); |
171 } | 166 } |
172 } | 167 } |
173 | 168 |
174 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { | 169 void TouchEventConverterEvdev::ProcessInputEvent(const input_event& input) { |
175 if (input.type == EV_SYN) { | 170 if (input.type == EV_SYN) { |
176 ProcessSyn(input); | 171 ProcessSyn(input); |
177 } else if(syn_dropped_) { | 172 } else if (syn_dropped_) { |
178 // Do nothing. This branch indicates we have lost sync with the driver. | 173 // Do nothing. This branch indicates we have lost sync with the driver. |
179 } else if (input.type == EV_ABS) { | 174 } else if (input.type == EV_ABS) { |
180 if (events_.size() <= current_slot_) { | 175 if (events_.size() <= current_slot_) { |
181 LOG(ERROR) << "current_slot_ (" << current_slot_ | 176 LOG(ERROR) << "current_slot_ (" << current_slot_ |
182 << ") >= events_.size() (" << events_.size() << ")"; | 177 << ") >= events_.size() (" << events_.size() << ")"; |
183 } else { | 178 } else { |
184 ProcessAbs(input); | 179 ProcessAbs(input); |
185 } | 180 } |
186 } else if (input.type == EV_KEY) { | 181 } else if (input.type == EV_KEY) { |
187 switch (input.code) { | 182 switch (input.code) { |
188 case BTN_TOUCH: | 183 case BTN_TOUCH: |
189 break; | 184 break; |
190 default: | 185 default: |
191 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; | 186 NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code; |
192 } | 187 } |
193 } else { | 188 } else { |
194 NOTIMPLEMENTED() << "invalid type: " << input.type; | 189 NOTIMPLEMENTED() << "invalid type: " << input.type; |
195 } | 190 } |
196 } | 191 } |
197 | 192 |
198 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { | 193 void TouchEventConverterEvdev::ProcessAbs(const input_event& input) { |
199 switch (input.code) { | 194 switch (input.code) { |
200 case ABS_MT_TOUCH_MAJOR: | 195 case ABS_MT_TOUCH_MAJOR: |
201 // TODO(spang): If we have all of major, minor, and orientation, | 196 // TODO(spang): If we have all of major, minor, and orientation, |
202 // we can scale the ellipse correctly. However on the Pixel we get | 197 // we can scale the ellipse correctly. However on the Pixel we get |
203 // neither minor nor orientation, so this is all we can do. | 198 // neither minor nor orientation, so this is all we can do. |
204 events_[current_slot_].radius_x_ = input.value / 2.0f; | 199 events_[current_slot_].radius_x = input.value / 2.0f; |
205 break; | 200 break; |
206 case ABS_MT_TOUCH_MINOR: | 201 case ABS_MT_TOUCH_MINOR: |
207 events_[current_slot_].radius_y_ = input.value / 2.0f; | 202 events_[current_slot_].radius_y = input.value / 2.0f; |
208 break; | 203 break; |
209 case ABS_MT_POSITION_X: | 204 case ABS_MT_POSITION_X: |
210 events_[current_slot_].x_ = input.value; | 205 events_[current_slot_].x = input.value; |
211 break; | 206 break; |
212 case ABS_MT_POSITION_Y: | 207 case ABS_MT_POSITION_Y: |
213 events_[current_slot_].y_ = input.value; | 208 events_[current_slot_].y = input.value; |
214 break; | 209 break; |
215 case ABS_MT_TRACKING_ID: | 210 case ABS_MT_TRACKING_ID: |
216 if (input.value < 0) { | 211 if (input.value < 0) { |
217 events_[current_slot_].type_ = ET_TOUCH_RELEASED; | 212 events_[current_slot_].type = ET_TOUCH_RELEASED; |
218 } else { | 213 } else { |
219 events_[current_slot_].finger_ = input.value; | 214 events_[current_slot_].tracking_id = input.value; |
220 events_[current_slot_].type_ = ET_TOUCH_PRESSED; | 215 events_[current_slot_].type = ET_TOUCH_PRESSED; |
216 | |
217 // Clear the 'cancelled' bit because ET_TOUCH_PRESSED starts a new | |
218 // touch. | |
219 events_[current_slot_].cancelled = false; | |
spang
2015/03/18 19:20:12
I think this block should be cut down to just:
ev
| |
221 } | 220 } |
222 break; | 221 break; |
223 case ABS_MT_PRESSURE: | 222 case ABS_MT_PRESSURE: |
224 events_[current_slot_].pressure_ = input.value - pressure_min_; | 223 events_[current_slot_].pressure = input.value - pressure_min_; |
225 events_[current_slot_].pressure_ /= pressure_max_ - pressure_min_; | 224 events_[current_slot_].pressure /= pressure_max_ - pressure_min_; |
226 break; | 225 break; |
227 case ABS_MT_SLOT: | 226 case ABS_MT_SLOT: |
228 if (input.value >= 0 && | 227 if (input.value >= 0 && |
229 static_cast<size_t>(input.value) < events_.size()) { | 228 static_cast<size_t>(input.value) < events_.size()) { |
230 current_slot_ = input.value; | 229 current_slot_ = input.value; |
231 } else { | 230 } else { |
232 LOG(ERROR) << "invalid touch event index: " << input.value; | 231 LOG(ERROR) << "invalid touch event index: " << input.value; |
233 return; | 232 return; |
234 } | 233 } |
235 break; | 234 break; |
236 default: | 235 default: |
237 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; | 236 DVLOG(5) << "unhandled code for EV_ABS: " << input.code; |
238 return; | 237 return; |
239 } | 238 } |
240 events_[current_slot_].altered_ = true; | 239 events_[current_slot_].altered = true; |
241 } | 240 } |
242 | 241 |
243 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { | 242 void TouchEventConverterEvdev::ProcessSyn(const input_event& input) { |
244 switch (input.code) { | 243 switch (input.code) { |
245 case SYN_REPORT: | 244 case SYN_REPORT: |
246 if (syn_dropped_) { | 245 if (syn_dropped_) { |
247 // Have to re-initialize. | 246 // Have to re-initialize. |
248 if (Reinitialize()) { | 247 if (Reinitialize()) { |
249 syn_dropped_ = false; | 248 syn_dropped_ = false; |
250 for(InProgressEvents& event: events_) | 249 for(InProgressTouchEvdev& event : events_) |
251 event.altered_ = false; | 250 event.altered = false; |
252 } else { | 251 } else { |
253 LOG(ERROR) << "failed to re-initialize device info"; | 252 LOG(ERROR) << "failed to re-initialize device info"; |
254 } | 253 } |
255 } else { | 254 } else { |
256 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); | 255 ReportEvents(EventConverterEvdev::TimeDeltaFromInputEvent(input)); |
257 } | 256 } |
258 if (is_type_a_) | 257 if (is_type_a_) |
259 current_slot_ = 0; | 258 current_slot_ = 0; |
260 break; | 259 break; |
261 case SYN_MT_REPORT: | 260 case SYN_MT_REPORT: |
262 // For type A devices, we just get a stream of all current contacts, | 261 // For type A devices, we just get a stream of all current contacts, |
263 // in some arbitrary order. | 262 // in some arbitrary order. |
264 events_[current_slot_].type_ = ET_TOUCH_PRESSED; | 263 events_[current_slot_].type = ET_TOUCH_PRESSED; |
265 if (events_.size() - 1 > current_slot_) | 264 if (events_.size() - 1 > current_slot_) |
266 current_slot_++; | 265 current_slot_++; |
267 is_type_a_ = true; | 266 is_type_a_ = true; |
267 | |
268 // TouchNoiseFinder does not support type A devices. | |
269 touch_noise_finder_.reset(); | |
268 break; | 270 break; |
269 case SYN_DROPPED: | 271 case SYN_DROPPED: |
270 // Some buffer has overrun. We ignore all events up to and | 272 // Some buffer has overrun. We ignore all events up to and |
271 // including the next SYN_REPORT. | 273 // including the next SYN_REPORT. |
272 syn_dropped_ = true; | 274 syn_dropped_ = true; |
273 break; | 275 break; |
274 default: | 276 default: |
275 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; | 277 NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code; |
276 } | 278 } |
277 } | 279 } |
278 | 280 |
279 void TouchEventConverterEvdev::ReportEvent(int touch_id, | 281 void TouchEventConverterEvdev::MaybeReportEvent( |
280 const InProgressEvents& event, | 282 const InProgressTouchEvdev& event, |
281 const base::TimeDelta& timestamp) { | 283 const base::TimeDelta& timestamp, |
284 bool* cancelled) { | |
285 *cancelled = event.cancelled; | |
286 if (event.cancelled) | |
287 return; | |
288 | |
289 EventType event_type = event.type; | |
290 if (touch_noise_finder_ && touch_noise_finder_->SlotHasNoise(event.slot)) { | |
spang
2015/03/18 19:20:12
Could we centralize determining the event type her
| |
291 *cancelled = true; | |
292 if (event_type == ET_TOUCH_PRESSED) | |
293 return; | |
294 // Cancel this event and drop subsequent events. | |
295 event_type = ET_TOUCH_CANCELLED; | |
296 } | |
297 | |
282 dispatcher_->DispatchTouchEvent(TouchEventParams( | 298 dispatcher_->DispatchTouchEvent(TouchEventParams( |
283 id_, touch_id, event.type_, gfx::PointF(event.x_, event.y_), | 299 id_, event.slot, event_type, gfx::PointF(event.x, event.y), |
284 gfx::Vector2dF(event.radius_x_, event.radius_y_), event.pressure_, | 300 gfx::Vector2dF(event.radius_x, event.radius_y), event.pressure, |
285 timestamp)); | 301 timestamp)); |
286 } | 302 } |
287 | 303 |
288 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { | 304 void TouchEventConverterEvdev::ReportEvents(base::TimeDelta delta) { |
305 if (touch_noise_finder_) | |
306 touch_noise_finder_->HandleTouches(events_, delta); | |
307 | |
289 for (size_t i = 0; i < events_.size(); i++) { | 308 for (size_t i = 0; i < events_.size(); i++) { |
290 if (events_[i].altered_) { | 309 InProgressTouchEvdev* event = &events_[i]; |
291 ReportEvent(i, events_[i], delta); | 310 if (!event->altered) |
311 continue; | |
292 | 312 |
293 // Subsequent events for this finger will be touch-move until it | 313 bool cancelled = false; |
294 // is released. | 314 MaybeReportEvent(*event, delta, &cancelled); |
295 events_[i].type_ = ET_TOUCH_MOVED; | 315 event->cancelled = cancelled; |
296 events_[i].altered_ = false; | 316 |
317 // Update |event->type| regardless of whether an event was dispatched | |
318 // because TouchNoiseFinder::HandleTouches() needs the touch's uncancelled | |
319 // state to determine whether future touches should be cancelled. | |
flackr
2015/03/17 03:54:15
I think this would still work with the cancelled t
pkotwicz
2015/03/17 16:51:23
SinglePositionTouchNoiseFilter needs to know when
flackr
2015/03/17 16:59:04
Right, I was thinking that we might be able to rec
| |
320 switch (event->type) { | |
321 case ET_TOUCH_PRESSED: | |
322 event->type = ET_TOUCH_MOVED; | |
323 break; | |
324 case ET_TOUCH_RELEASED: | |
325 event->type = ET_UNKNOWN; | |
326 break; | |
327 default: | |
328 break; | |
297 } | 329 } |
330 | |
331 event->altered = false; | |
298 } | 332 } |
299 } | 333 } |
300 | 334 |
301 } // namespace ui | 335 } // namespace ui |
OLD | NEW |