OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/base/events.h" | 5 #include "ui/base/events.h" |
6 | 6 |
7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
8 #include <X11/extensions/XInput.h> | 8 #include <X11/extensions/XInput.h> |
9 #include <X11/extensions/XInput2.h> | 9 #include <X11/extensions/XInput2.h> |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 // CMT specific timings | 23 // CMT specific timings |
24 #define AXIS_LABEL_PROP_ABS_START_TIME "Abs Start Timestamp" | 24 #define AXIS_LABEL_PROP_ABS_START_TIME "Abs Start Timestamp" |
25 #define AXIS_LABEL_PROP_ABS_END_TIME "Abs End Timestamp" | 25 #define AXIS_LABEL_PROP_ABS_END_TIME "Abs End Timestamp" |
26 | 26 |
27 // Fling properties | 27 // Fling properties |
28 #define AXIS_LABEL_PROP_ABS_FLING_X "Abs Fling X Velocity" | 28 #define AXIS_LABEL_PROP_ABS_FLING_X "Abs Fling X Velocity" |
29 #define AXIS_LABEL_PROP_ABS_FLING_Y "Abs Fling Y Velocity" | 29 #define AXIS_LABEL_PROP_ABS_FLING_Y "Abs Fling Y Velocity" |
30 #define AXIS_LABEL_PROP_ABS_FLING_STATE "Abs Fling State" | 30 #define AXIS_LABEL_PROP_ABS_FLING_STATE "Abs Fling State" |
31 | 31 |
| 32 // New versions of the valuators, with double values instead of fixed point. |
| 33 #define AXIS_LABEL_PROP_ABS_DBL_START_TIME "Abs Dbl Start Timestamp" |
| 34 #define AXIS_LABEL_PROP_ABS_DBL_END_TIME "Abs Dbl End Timestamp" |
| 35 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VX "Abs Dbl Fling X Velocity" |
| 36 #define AXIS_LABEL_PROP_ABS_DBL_FLING_VY "Abs Dbl Fling Y Velocity" |
| 37 |
32 namespace { | 38 namespace { |
33 | 39 |
34 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+. | 40 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+. |
35 const int kWheelScrollAmount = 53; | 41 const int kWheelScrollAmount = 53; |
36 | 42 |
37 const int kMinWheelButton = 4; | 43 const int kMinWheelButton = 4; |
38 const int kMaxWheelButton = 7; | 44 const int kMaxWheelButton = 7; |
39 | 45 |
40 // A class to support the detection of scroll events, using X11 valuators. | 46 // A class to support the detection of scroll events, using X11 valuators. |
41 class UI_EXPORT CMTEventData { | 47 class UI_EXPORT CMTEventData { |
(...skipping 20 matching lines...) Expand all Loading... |
62 touchpads_[dev_list[i].id] = true; | 68 touchpads_[dev_list[i].id] = true; |
63 } | 69 } |
64 if (dev_list) | 70 if (dev_list) |
65 XFreeDeviceList(dev_list); | 71 XFreeDeviceList(dev_list); |
66 | 72 |
67 XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &count); | 73 XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &count); |
68 Atom x_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_HWHEEL, false); | 74 Atom x_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_HWHEEL, false); |
69 Atom y_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_WHEEL, false); | 75 Atom y_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_WHEEL, false); |
70 Atom start_time = | 76 Atom start_time = |
71 XInternAtom(display, AXIS_LABEL_PROP_ABS_START_TIME, false); | 77 XInternAtom(display, AXIS_LABEL_PROP_ABS_START_TIME, false); |
| 78 Atom start_time_dbl = |
| 79 XInternAtom(display, AXIS_LABEL_PROP_ABS_DBL_START_TIME, false); |
72 Atom end_time = XInternAtom(display, AXIS_LABEL_PROP_ABS_END_TIME, false); | 80 Atom end_time = XInternAtom(display, AXIS_LABEL_PROP_ABS_END_TIME, false); |
| 81 Atom end_time_dbl = |
| 82 XInternAtom(display, AXIS_LABEL_PROP_ABS_DBL_END_TIME, false); |
73 Atom fling_vx = XInternAtom(display, AXIS_LABEL_PROP_ABS_FLING_X, false); | 83 Atom fling_vx = XInternAtom(display, AXIS_LABEL_PROP_ABS_FLING_X, false); |
| 84 Atom fling_vx_dbl = |
| 85 XInternAtom(display, AXIS_LABEL_PROP_ABS_DBL_FLING_VX, false); |
74 Atom fling_vy = XInternAtom(display, AXIS_LABEL_PROP_ABS_FLING_Y, false); | 86 Atom fling_vy = XInternAtom(display, AXIS_LABEL_PROP_ABS_FLING_Y, false); |
| 87 Atom fling_vy_dbl = |
| 88 XInternAtom(display, AXIS_LABEL_PROP_ABS_DBL_FLING_VY, false); |
75 Atom fling_state = | 89 Atom fling_state = |
76 XInternAtom(display, AXIS_LABEL_PROP_ABS_FLING_STATE, false); | 90 XInternAtom(display, AXIS_LABEL_PROP_ABS_FLING_STATE, false); |
77 | 91 |
78 for (int i = 0; i < count; ++i) { | 92 for (int i = 0; i < count; ++i) { |
79 XIDeviceInfo* info = info_list + i; | 93 XIDeviceInfo* info = info_list + i; |
80 | 94 |
81 if (info->use != XISlavePointer && info->use != XIFloatingSlave) | 95 if (info->use != XISlavePointer && info->use != XIFloatingSlave) |
82 continue; | 96 continue; |
83 | 97 |
84 Valuators valuators; | 98 Valuators valuators; |
85 bool is_cmt = false; | 99 bool is_cmt = false; |
86 for (int j = 0; j < info->num_classes; ++j) { | 100 for (int j = 0; j < info->num_classes; ++j) { |
87 if (info->classes[j]->type != XIValuatorClass) | 101 if (info->classes[j]->type != XIValuatorClass) |
88 continue; | 102 continue; |
89 | 103 |
90 XIValuatorClassInfo* v = | 104 XIValuatorClassInfo* v = |
91 reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]); | 105 reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]); |
92 int number = v->number; | 106 int number = v->number; |
93 if (number > valuators.max) | 107 if (number > valuators.max) |
94 valuators.max = number; | 108 valuators.max = number; |
95 if (v->label == x_axis) { | 109 if (v->label == x_axis) { |
96 valuators.scroll_x = number; | 110 valuators.scroll_x = number; |
97 is_cmt = true; | 111 is_cmt = true; |
98 } else if (v->label == y_axis) { | 112 } else if (v->label == y_axis) { |
99 valuators.scroll_y = number; | 113 valuators.scroll_y = number; |
100 is_cmt = true; | 114 is_cmt = true; |
101 } else if (v->label == start_time) { | 115 } else if (v->label == start_time) { |
102 valuators.start_time = number; | 116 valuators.start_time = number; |
103 is_cmt = true; | 117 is_cmt = true; |
| 118 } else if (v->label == start_time_dbl) { |
| 119 valuators.start_time_dbl = number; |
| 120 is_cmt = true; |
104 } else if (v->label == end_time) { | 121 } else if (v->label == end_time) { |
105 valuators.end_time = number; | 122 valuators.end_time = number; |
106 is_cmt = true; | 123 is_cmt = true; |
| 124 } else if (v->label == end_time_dbl) { |
| 125 valuators.end_time_dbl = number; |
| 126 is_cmt = true; |
107 } else if (v->label == fling_vx) { | 127 } else if (v->label == fling_vx) { |
108 valuators.fling_vx = number; | 128 valuators.fling_vx = number; |
109 is_cmt = true; | 129 is_cmt = true; |
| 130 } else if (v->label == fling_vx_dbl) { |
| 131 valuators.fling_vx_dbl = number; |
| 132 is_cmt = true; |
110 } else if (v->label == fling_vy) { | 133 } else if (v->label == fling_vy) { |
111 valuators.fling_vy = number; | 134 valuators.fling_vy = number; |
112 is_cmt = true; | 135 is_cmt = true; |
| 136 } else if (v->label == fling_vy_dbl) { |
| 137 valuators.fling_vy_dbl = number; |
| 138 is_cmt = true; |
113 } else if (v->label == fling_state) { | 139 } else if (v->label == fling_state) { |
114 valuators.fling_state = number; | 140 valuators.fling_state = number; |
115 is_cmt = true; | 141 is_cmt = true; |
116 } | 142 } |
117 } | 143 } |
118 if (is_cmt) { | 144 if (is_cmt) { |
| 145 // Double valuators override fixed point ones. |
| 146 if (valuators.start_time_dbl >= 0) |
| 147 valuators.start_time = -1; |
| 148 if (valuators.end_time_dbl >= 0) |
| 149 valuators.end_time = -1; |
| 150 if (valuators.fling_vx_dbl >= 0) |
| 151 valuators.fling_vx = -1; |
| 152 if (valuators.fling_vy_dbl >= 0) |
| 153 valuators.fling_vy = -1; |
119 device_to_valuators_[info->deviceid] = valuators; | 154 device_to_valuators_[info->deviceid] = valuators; |
120 cmt_devices_[info->deviceid] = true; | 155 cmt_devices_[info->deviceid] = true; |
121 } | 156 } |
122 } | 157 } |
123 XIFreeDeviceInfo(info_list); | 158 XIFreeDeviceInfo(info_list); |
124 } | 159 } |
125 | 160 |
126 bool natural_scroll_enabled() const { return natural_scroll_enabled_; } | 161 bool natural_scroll_enabled() const { return natural_scroll_enabled_; } |
127 void set_natural_scroll_enabled(bool enabled) { | 162 void set_natural_scroll_enabled(bool enabled) { |
128 natural_scroll_enabled_ = enabled; | 163 natural_scroll_enabled_ = enabled; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 *vx = 0; | 226 *vx = 0; |
192 *vy = 0; | 227 *vy = 0; |
193 *is_cancel = false; | 228 *is_cancel = false; |
194 | 229 |
195 const int deviceid = xiev->deviceid; | 230 const int deviceid = xiev->deviceid; |
196 if (!cmt_devices_[deviceid]) | 231 if (!cmt_devices_[deviceid]) |
197 return false; | 232 return false; |
198 | 233 |
199 const float natural_scroll_factor = GetNaturalScrollFactor(deviceid); | 234 const float natural_scroll_factor = GetNaturalScrollFactor(deviceid); |
200 const Valuators v = device_to_valuators_[deviceid]; | 235 const Valuators v = device_to_valuators_[deviceid]; |
201 if (!XIMaskIsSet(xiev->valuators.mask, v.fling_vx) || | 236 if ((!XIMaskIsSet(xiev->valuators.mask, v.fling_vx) && |
202 !XIMaskIsSet(xiev->valuators.mask, v.fling_vy) || | 237 !XIMaskIsSet(xiev->valuators.mask, v.fling_vx_dbl)) || |
| 238 (!XIMaskIsSet(xiev->valuators.mask, v.fling_vy) && |
| 239 !XIMaskIsSet(xiev->valuators.mask, v.fling_vy_dbl)) || |
203 !XIMaskIsSet(xiev->valuators.mask, v.fling_state)) | 240 !XIMaskIsSet(xiev->valuators.mask, v.fling_state)) |
204 return false; | 241 return false; |
205 | 242 |
206 double* valuators = xiev->valuators.values; | 243 double* valuators = xiev->valuators.values; |
207 for (int i = 0; i <= v.max; ++i) { | 244 for (int i = 0; i <= v.max; ++i) { |
208 if (XIMaskIsSet(xiev->valuators.mask, i)) { | 245 if (XIMaskIsSet(xiev->valuators.mask, i)) { |
209 // Convert values to unsigned ints represending ms before storing them, | 246 // Convert values to unsigned ints representing ms before storing them, |
210 // as that is how they were encoded before conversion to doubles. | 247 // as that is how they were encoded before conversion to doubles. |
211 if (v.fling_vx == i) | 248 if (v.fling_vx_dbl == i) { |
| 249 *vx = natural_scroll_factor * *valuators; |
| 250 } else if (v.fling_vx == i) { |
212 *vx = natural_scroll_factor * | 251 *vx = natural_scroll_factor * |
213 (static_cast<int>(*valuators)) / 1000.0f; | 252 static_cast<double>(static_cast<int>(*valuators)) / 1000.0f; |
214 else if (v.fling_vy == i) | 253 } else if (v.fling_vy_dbl == i) { |
| 254 *vy = natural_scroll_factor * *valuators; |
| 255 } else if (v.fling_vy == i) { |
215 *vy = natural_scroll_factor * | 256 *vy = natural_scroll_factor * |
216 (static_cast<int>(*valuators)) / 1000.0f; | 257 static_cast<double>(static_cast<int>(*valuators)) / 1000.0f; |
217 else if (v.fling_state == i) | 258 } else if (v.fling_state == i) { |
218 *is_cancel = !!static_cast<unsigned int>(*valuators); | 259 *is_cancel = !!static_cast<unsigned int>(*valuators); |
| 260 } |
219 valuators++; | 261 valuators++; |
220 } | 262 } |
221 } | 263 } |
222 | 264 |
223 return true; | 265 return true; |
224 } | 266 } |
225 | 267 |
226 bool GetGestureTimes(const XEvent& xev, | 268 bool GetGestureTimes(const XEvent& xev, |
227 double* start_time, | 269 double* start_time, |
228 double* end_time) { | 270 double* end_time) { |
229 *start_time = 0; | 271 *start_time = 0; |
230 *end_time = 0; | 272 *end_time = 0; |
231 | 273 |
232 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); | 274 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); |
233 if (!cmt_devices_[xiev->deviceid]) | 275 if (!cmt_devices_[xiev->deviceid]) |
234 return false; | 276 return false; |
235 | 277 |
236 Valuators v = device_to_valuators_[xiev->deviceid]; | 278 Valuators v = device_to_valuators_[xiev->deviceid]; |
237 if (!XIMaskIsSet(xiev->valuators.mask, v.start_time) || | 279 if ((!XIMaskIsSet(xiev->valuators.mask, v.start_time) && |
238 !XIMaskIsSet(xiev->valuators.mask, v.end_time)) | 280 !XIMaskIsSet(xiev->valuators.mask, v.start_time_dbl)) || |
| 281 (!XIMaskIsSet(xiev->valuators.mask, v.end_time) && |
| 282 !XIMaskIsSet(xiev->valuators.mask, v.end_time_dbl))) |
239 return false; | 283 return false; |
240 | 284 |
241 double* valuators = xiev->valuators.values; | 285 double* valuators = xiev->valuators.values; |
242 for (int i = 0; i <= v.max; ++i) { | 286 for (int i = 0; i <= v.max; ++i) { |
243 if (XIMaskIsSet(xiev->valuators.mask, i)) { | 287 if (XIMaskIsSet(xiev->valuators.mask, i)) { |
244 // Convert values to unsigned ints represending ms before storing them, | 288 if (v.start_time_dbl == i) { |
245 // as that is how they were encoded before conversion to doubles. | 289 *start_time = *valuators; |
246 if (v.start_time == i) | 290 } else if (v.start_time == i) { |
| 291 // Convert values to unsigned ints representing ms before storing |
| 292 // them, as that is how they were encoded before conversion |
| 293 // to doubles. |
247 *start_time = | 294 *start_time = |
248 static_cast<double>(static_cast<unsigned int>(*valuators)) / 1000; | 295 static_cast<double>( |
249 else if (v.end_time == i) | 296 static_cast<unsigned int>(*valuators)) / 1000; |
| 297 } else if (v.end_time_dbl == i) { |
| 298 *end_time = *valuators; |
| 299 } else if (v.end_time == i) { |
| 300 // Convert values to unsigned ints representing ms before storing |
| 301 // them, as that is how they were encoded before conversion |
| 302 // to doubles. |
250 *end_time = | 303 *end_time = |
251 static_cast<double>(static_cast<unsigned int>(*valuators)) / 1000; | 304 static_cast<double>( |
| 305 static_cast<unsigned int>(*valuators)) / 1000; |
| 306 } |
252 valuators++; | 307 valuators++; |
253 } | 308 } |
254 } | 309 } |
255 | 310 |
256 return true; | 311 return true; |
257 } | 312 } |
258 | 313 |
259 private: | 314 private: |
260 // Requirement for Singleton | 315 // Requirement for Singleton |
261 friend struct DefaultSingletonTraits<CMTEventData>; | 316 friend struct DefaultSingletonTraits<CMTEventData>; |
262 | 317 |
263 struct Valuators { | 318 struct Valuators { |
264 int max; | 319 int max; |
265 int scroll_x; | 320 int scroll_x; |
266 int scroll_y; | 321 int scroll_y; |
267 int start_time; | 322 int start_time; |
268 int end_time; | 323 int end_time; |
269 int fling_vx; | 324 int fling_vx; |
270 int fling_vy; | 325 int fling_vy; |
271 int fling_state; | 326 int fling_state; |
| 327 // *_dbl valuators take precedence over the fixed precision versions. |
| 328 int start_time_dbl; |
| 329 int end_time_dbl; |
| 330 int fling_vx_dbl; |
| 331 int fling_vy_dbl; |
272 | 332 |
273 Valuators() | 333 Valuators() |
274 : max(-1), | 334 : max(-1), |
275 scroll_x(-1), | 335 scroll_x(-1), |
276 scroll_y(-1), | 336 scroll_y(-1), |
277 start_time(-1), | 337 start_time(-1), |
278 end_time(-1), | 338 end_time(-1), |
279 fling_vx(-1), | 339 fling_vx(-1), |
280 fling_vy(-1), | 340 fling_vy(-1), |
281 fling_state(-1) { | 341 fling_state(-1), |
282 | 342 start_time_dbl(-1), |
| 343 end_time_dbl(-1), |
| 344 fling_vx_dbl(-1), |
| 345 fling_vy_dbl(-1) { |
283 } | 346 } |
284 | 347 |
285 }; | 348 }; |
286 | 349 |
287 CMTEventData() : natural_scroll_enabled_(true) { | 350 CMTEventData() : natural_scroll_enabled_(true) { |
288 UpdateDeviceList(ui::GetXDisplay()); | 351 UpdateDeviceList(ui::GetXDisplay()); |
289 } | 352 } |
290 | 353 |
291 ~CMTEventData() {} | 354 ~CMTEventData() {} |
292 | 355 |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
655 case ButtonRelease: | 718 case ButtonRelease: |
656 return base::TimeDelta::FromMilliseconds(native_event->xbutton.time); | 719 return base::TimeDelta::FromMilliseconds(native_event->xbutton.time); |
657 break; | 720 break; |
658 case MotionNotify: | 721 case MotionNotify: |
659 return base::TimeDelta::FromMilliseconds(native_event->xmotion.time); | 722 return base::TimeDelta::FromMilliseconds(native_event->xmotion.time); |
660 break; | 723 break; |
661 case GenericEvent: { | 724 case GenericEvent: { |
662 double start, end; | 725 double start, end; |
663 if (GetGestureTimes(native_event, &start, &end)) { | 726 if (GetGestureTimes(native_event, &start, &end)) { |
664 // If the driver supports gesture times, use them. | 727 // If the driver supports gesture times, use them. |
665 return base::TimeDelta::FromMicroseconds(start * 1000000); | 728 return base::TimeDelta::FromMicroseconds(end * 1000000); |
666 } else { | 729 } else { |
667 XIDeviceEvent* xide = | 730 XIDeviceEvent* xide = |
668 static_cast<XIDeviceEvent*>(native_event->xcookie.data); | 731 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
669 return base::TimeDelta::FromMilliseconds(xide->time); | 732 return base::TimeDelta::FromMilliseconds(xide->time); |
670 } | 733 } |
671 break; | 734 break; |
672 } | 735 } |
673 } | 736 } |
674 NOTREACHED(); | 737 NOTREACHED(); |
675 return base::TimeDelta(); | 738 return base::TimeDelta(); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
871 noop->xclient.format = 8; | 934 noop->xclient.format = 8; |
872 DCHECK(!noop->xclient.display); | 935 DCHECK(!noop->xclient.display); |
873 } | 936 } |
874 // Make sure we use atom from current xdisplay, which may | 937 // Make sure we use atom from current xdisplay, which may |
875 // change during the test. | 938 // change during the test. |
876 noop->xclient.message_type = GetNoopEventAtom(); | 939 noop->xclient.message_type = GetNoopEventAtom(); |
877 return noop; | 940 return noop; |
878 } | 941 } |
879 | 942 |
880 } // namespace ui | 943 } // namespace ui |
OLD | NEW |