Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ui / events / x / events_x.cc
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
3 // found in the LICENSE file.
4
5 #include "ui/events/event_constants.h"
6
7 #include <cmath>
8 #include <string.h>
9 #include <X11/extensions/XInput.h>
10 #include <X11/extensions/XInput2.h>
11 #include <X11/Xlib.h>
12
13 #include "base/logging.h"
14 #include "base/memory/singleton.h"
15 #include "base/message_loop/message_pump_x11.h"
16 #include "ui/events/event_utils.h"
17 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
18 #include "ui/events/x/device_data_manager.h"
19 #include "ui/events/x/device_list_cache_x.h"
20 #include "ui/events/x/touch_factory_x11.h"
21 #include "ui/gfx/display.h"
22 #include "ui/gfx/point.h"
23 #include "ui/gfx/rect.h"
24 #include "ui/gfx/screen.h"
25 #include "ui/gfx/x/x11_atom_cache.h"
26 #include "ui/gfx/x/x11_types.h"
27
28 namespace {
29
30 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
31 const int kWheelScrollAmount = 53;
32
33 const int kMinWheelButton = 4;
34 const int kMaxWheelButton = 7;
35
36 // A class to track current modifier state on master device. Only track ctrl,
37 // alt, shift and caps lock keys currently. The tracked state can then be used
38 // by floating device.
39 class XModifierStateWatcher{
40  public:
41   static XModifierStateWatcher* GetInstance() {
42     return Singleton<XModifierStateWatcher>::get();
43   }
44
45   void UpdateStateFromEvent(const base::NativeEvent& native_event) {
46     // Floating device can't access the modifer state from master device.
47     // We need to track the states of modifier keys in a singleton for
48     // floating devices such as touch screen. Issue 106426 is one example
49     // of why we need the modifier states for floating device.
50     state_ = native_event->xkey.state;
51     // master_state is the state before key press. We need to track the
52     // state after key press for floating device. Currently only ctrl,
53     // shift, alt and caps lock keys are tracked.
54     ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
55     unsigned int mask = 0;
56
57     switch (keyboard_code) {
58       case ui::VKEY_CONTROL: {
59         mask = ControlMask;
60         break;
61       }
62       case ui::VKEY_SHIFT: {
63         mask = ShiftMask;
64         break;
65       }
66       case ui::VKEY_MENU: {
67         mask = Mod1Mask;
68         break;
69       }
70       case ui::VKEY_CAPITAL: {
71         mask = LockMask;
72         break;
73       }
74       default:
75         break;
76     }
77
78     if (native_event->type == KeyPress)
79       state_ |= mask;
80     else
81       state_ &= ~mask;
82   }
83
84   // Returns the current modifer state in master device. It only contains the
85   // state of ctrl, shift, alt and caps lock keys.
86   unsigned int state() { return state_; }
87
88  private:
89   friend struct DefaultSingletonTraits<XModifierStateWatcher>;
90
91   XModifierStateWatcher() : state_(0) { }
92
93   unsigned int state_;
94
95   DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher);
96 };
97
98 #if defined(USE_XI2_MT)
99 // Detects if a touch event is a driver-generated 'special event'.
100 // A 'special event' is a touch event with maximum radius and pressure at
101 // location (0, 0).
102 // This needs to be done in a cleaner way: http://crbug.com/169256
103 bool TouchEventIsGeneratedHack(const base::NativeEvent& native_event) {
104   XIDeviceEvent* event =
105       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
106   CHECK(event->evtype == XI_TouchBegin ||
107         event->evtype == XI_TouchUpdate ||
108         event->evtype == XI_TouchEnd);
109
110   // Force is normalized to [0, 1].
111   if (ui::GetTouchForce(native_event) < 1.0f)
112     return false;
113
114   if (ui::EventLocationFromNative(native_event) != gfx::Point())
115     return false;
116
117   // Radius is in pixels, and the valuator is the diameter in pixels.
118   double radius = ui::GetTouchRadiusX(native_event), min, max;
119   unsigned int deviceid =
120       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
121   if (!ui::DeviceDataManager::GetInstance()->GetDataRange(
122       deviceid, ui::DeviceDataManager::DT_TOUCH_MAJOR, &min, &max)) {
123     return false;
124   }
125
126   return radius * 2 == max;
127 }
128 #endif
129
130 int GetEventFlagsFromXState(unsigned int state) {
131   int flags = 0;
132   if (state & ControlMask)
133     flags |= ui::EF_CONTROL_DOWN;
134   if (state & ShiftMask)
135     flags |= ui::EF_SHIFT_DOWN;
136   if (state & Mod1Mask)
137     flags |= ui::EF_ALT_DOWN;
138   if (state & LockMask)
139     flags |= ui::EF_CAPS_LOCK_DOWN;
140   if (state & Mod5Mask)
141     flags |= ui::EF_ALTGR_DOWN;
142   if (state & Button1Mask)
143     flags |= ui::EF_LEFT_MOUSE_BUTTON;
144   if (state & Button2Mask)
145     flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
146   if (state & Button3Mask)
147     flags |= ui::EF_RIGHT_MOUSE_BUTTON;
148   return flags;
149 }
150
151 // Get the event flag for the button in XButtonEvent. During a ButtonPress
152 // event, |state| in XButtonEvent does not include the button that has just been
153 // pressed. Instead |state| contains flags for the buttons (if any) that had
154 // already been pressed before the current button, and |button| stores the most
155 // current pressed button. So, if you press down left mouse button, and while
156 // pressing it down, press down the right mouse button, then for the latter
157 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
158 // would be 3.
159 int GetEventFlagsForButton(int button) {
160   switch (button) {
161     case 1:
162       return ui::EF_LEFT_MOUSE_BUTTON;
163     case 2:
164       return ui::EF_MIDDLE_MOUSE_BUTTON;
165     case 3:
166       return ui::EF_RIGHT_MOUSE_BUTTON;
167     default:
168       return 0;
169   }
170 }
171
172 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
173   int buttonflags = 0;
174   for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
175     if (XIMaskIsSet(xievent->buttons.mask, i)) {
176       int button = (xievent->sourceid == xievent->deviceid) ?
177                    ui::DeviceDataManager::GetInstance()->GetMappedButton(i) : i;
178       buttonflags |= GetEventFlagsForButton(button);
179     }
180   }
181   return buttonflags;
182 }
183
184 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
185   XIDeviceEvent* event =
186       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
187 #if defined(USE_XI2_MT)
188   switch(event->evtype) {
189     case XI_TouchBegin:
190       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
191                                                        ui::ET_TOUCH_PRESSED;
192     case XI_TouchUpdate:
193       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
194                                                        ui::ET_TOUCH_MOVED;
195     case XI_TouchEnd:
196       return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED :
197                                                        ui::ET_TOUCH_RELEASED;
198   }
199 #endif  // defined(USE_XI2_MT)
200
201   DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid));
202   switch (event->evtype) {
203     case XI_ButtonPress:
204       return ui::ET_TOUCH_PRESSED;
205     case XI_ButtonRelease:
206       return ui::ET_TOUCH_RELEASED;
207     case XI_Motion:
208       // Should not convert any emulated Motion event from touch device to
209       // touch event.
210       if (!(event->flags & XIPointerEmulated) &&
211           GetButtonMaskForX2Event(event))
212         return ui::ET_TOUCH_MOVED;
213       return ui::ET_UNKNOWN;
214     default:
215       NOTREACHED();
216   }
217   return ui::ET_UNKNOWN;
218 }
219
220 double GetTouchParamFromXEvent(XEvent* xev,
221                               ui::DeviceDataManager::DataType val,
222                               double default_value) {
223   ui::DeviceDataManager::GetInstance()->GetEventData(
224       *xev, val, &default_value);
225   return default_value;
226 }
227
228 }  // namespace
229
230 namespace ui {
231
232 void UpdateDeviceList() {
233   XDisplay* display = gfx::GetXDisplay();
234   DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
235   TouchFactory::GetInstance()->UpdateDeviceList(display);
236   DeviceDataManager::GetInstance()->UpdateDeviceList(display);
237 }
238
239 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
240   switch (native_event->type) {
241     case KeyPress:
242       return ET_KEY_PRESSED;
243     case KeyRelease:
244       return ET_KEY_RELEASED;
245     case ButtonPress:
246       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
247           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
248         return ET_MOUSEWHEEL;
249       return ET_MOUSE_PRESSED;
250     case ButtonRelease:
251       // Drop wheel events; we should've already scrolled on the press.
252       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
253           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
254         return ET_UNKNOWN;
255       return ET_MOUSE_RELEASED;
256     case MotionNotify:
257       if (native_event->xmotion.state &
258           (Button1Mask | Button2Mask | Button3Mask))
259         return ET_MOUSE_DRAGGED;
260       return ET_MOUSE_MOVED;
261     case EnterNotify:
262       // The standard on Windows is to send a MouseMove event when the mouse
263       // first enters a window instead of sending a special mouse enter event.
264       // To be consistent we follow the same style.
265       return ET_MOUSE_MOVED;
266     case LeaveNotify:
267       return ET_MOUSE_EXITED;
268     case GenericEvent: {
269       TouchFactory* factory = TouchFactory::GetInstance();
270       if (!factory->ShouldProcessXI2Event(native_event))
271         return ET_UNKNOWN;
272
273       XIDeviceEvent* xievent =
274           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
275
276       // This check works only for master and floating slave devices. That is
277       // why it is necessary to check for the XI_Touch* events in the following
278       // switch statement to account for attached-slave touchscreens.
279       if (factory->IsTouchDevice(xievent->sourceid))
280         return GetTouchEventType(native_event);
281
282       switch (xievent->evtype) {
283         case XI_TouchBegin:
284           return ui::ET_TOUCH_PRESSED;
285         case XI_TouchUpdate:
286           return ui::ET_TOUCH_MOVED;
287         case XI_TouchEnd:
288           return ui::ET_TOUCH_RELEASED;
289         case XI_ButtonPress: {
290           int button = EventButtonFromNative(native_event);
291           if (button >= kMinWheelButton && button <= kMaxWheelButton)
292             return ET_MOUSEWHEEL;
293           return ET_MOUSE_PRESSED;
294         }
295         case XI_ButtonRelease: {
296           int button = EventButtonFromNative(native_event);
297           // Drop wheel events; we should've already scrolled on the press.
298           if (button >= kMinWheelButton && button <= kMaxWheelButton)
299             return ET_UNKNOWN;
300           return ET_MOUSE_RELEASED;
301         }
302         case XI_Motion: {
303           bool is_cancel;
304           if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) {
305             return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
306           } else if (DeviceDataManager::GetInstance()->IsScrollEvent(
307               native_event)) {
308             return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
309           } else if (DeviceDataManager::GetInstance()->IsCMTMetricsEvent(
310               native_event)) {
311             return ET_UMA_DATA;
312           } else if (GetButtonMaskForX2Event(xievent)) {
313             return ET_MOUSE_DRAGGED;
314           } else {
315             return ET_MOUSE_MOVED;
316           }
317         }
318       }
319     }
320     default:
321       break;
322   }
323   return ET_UNKNOWN;
324 }
325
326 int EventFlagsFromNative(const base::NativeEvent& native_event) {
327   switch (native_event->type) {
328     case KeyPress:
329     case KeyRelease: {
330       XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event);
331       return GetEventFlagsFromXState(native_event->xkey.state);
332     }
333     case ButtonPress:
334     case ButtonRelease: {
335       int flags = GetEventFlagsFromXState(native_event->xbutton.state);
336       const EventType type = EventTypeFromNative(native_event);
337       if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
338         flags |= GetEventFlagsForButton(native_event->xbutton.button);
339       return flags;
340     }
341     case EnterNotify:
342     case LeaveNotify:
343       return GetEventFlagsFromXState(native_event->xcrossing.state);
344     case MotionNotify:
345       return GetEventFlagsFromXState(native_event->xmotion.state);
346     case GenericEvent: {
347       XIDeviceEvent* xievent =
348           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
349
350       switch (xievent->evtype) {
351 #if defined(USE_XI2_MT)
352         case XI_TouchBegin:
353         case XI_TouchUpdate:
354         case XI_TouchEnd:
355           return GetButtonMaskForX2Event(xievent) |
356                  GetEventFlagsFromXState(xievent->mods.effective) |
357                  GetEventFlagsFromXState(
358                      XModifierStateWatcher::GetInstance()->state());
359           break;
360 #endif
361         case XI_ButtonPress:
362         case XI_ButtonRelease: {
363           const bool touch =
364               TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
365           int flags = GetButtonMaskForX2Event(xievent) |
366               GetEventFlagsFromXState(xievent->mods.effective);
367           if (touch) {
368             flags |= GetEventFlagsFromXState(
369                 XModifierStateWatcher::GetInstance()->state());
370           }
371
372           const EventType type = EventTypeFromNative(native_event);
373           int button = EventButtonFromNative(native_event);
374           if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
375             flags |= GetEventFlagsForButton(button);
376           return flags;
377         }
378         case XI_Motion:
379            return GetButtonMaskForX2Event(xievent) |
380                   GetEventFlagsFromXState(xievent->mods.effective);
381       }
382     }
383   }
384   return 0;
385 }
386
387 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
388   switch(native_event->type) {
389     case KeyPress:
390     case KeyRelease:
391       return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
392     case ButtonPress:
393     case ButtonRelease:
394       return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
395       break;
396     case MotionNotify:
397       return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
398       break;
399     case EnterNotify:
400     case LeaveNotify:
401       return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
402       break;
403     case GenericEvent: {
404       double start, end;
405       double touch_timestamp;
406       if (GetGestureTimes(native_event, &start, &end)) {
407         // If the driver supports gesture times, use them.
408         return base::TimeDelta::FromMicroseconds(end * 1000000);
409       } else if (DeviceDataManager::GetInstance()->GetEventData(*native_event,
410                  DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP, &touch_timestamp)) {
411         return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
412       } else {
413         XIDeviceEvent* xide =
414             static_cast<XIDeviceEvent*>(native_event->xcookie.data);
415         return base::TimeDelta::FromMilliseconds(xide->time);
416       }
417       break;
418     }
419   }
420   NOTREACHED();
421   return base::TimeDelta();
422 }
423
424 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
425   switch (native_event->type) {
426     case EnterNotify:
427     case LeaveNotify:
428       return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
429     case ButtonPress:
430     case ButtonRelease:
431       return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
432     case MotionNotify:
433       return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
434     case GenericEvent: {
435       XIDeviceEvent* xievent =
436           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
437       return gfx::Point(static_cast<int>(xievent->event_x),
438                         static_cast<int>(xievent->event_y));
439     }
440   }
441   return gfx::Point();
442 }
443
444 gfx::Point EventSystemLocationFromNative(
445     const base::NativeEvent& native_event) {
446   switch (native_event->type) {
447     case EnterNotify:
448     case LeaveNotify: {
449       return gfx::Point(native_event->xcrossing.x_root,
450                         native_event->xcrossing.y_root);
451     }
452     case ButtonPress:
453     case ButtonRelease: {
454       return gfx::Point(native_event->xbutton.x_root,
455                         native_event->xbutton.y_root);
456     }
457     case MotionNotify: {
458       return gfx::Point(native_event->xmotion.x_root,
459                         native_event->xmotion.y_root);
460     }
461     case GenericEvent: {
462       XIDeviceEvent* xievent =
463           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
464       return gfx::Point(xievent->root_x, xievent->root_y);
465     }
466   }
467
468   return gfx::Point();
469 }
470
471 int EventButtonFromNative(const base::NativeEvent& native_event) {
472   CHECK_EQ(GenericEvent, native_event->type);
473   XIDeviceEvent* xievent =
474       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
475   int button = xievent->detail;
476
477   return (xievent->sourceid == xievent->deviceid) ?
478          DeviceDataManager::GetInstance()->GetMappedButton(button) : button;
479 }
480
481 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
482   return KeyboardCodeFromXKeyEvent(native_event);
483 }
484
485 const char* CodeFromNative(const base::NativeEvent& native_event) {
486   return CodeFromXEvent(native_event);
487 }
488
489 int GetChangedMouseButtonFlagsFromNative(
490     const base::NativeEvent& native_event) {
491   switch (native_event->type) {
492     case ButtonPress:
493     case ButtonRelease:
494       return GetEventFlagsFromXState(native_event->xbutton.state);
495     case GenericEvent: {
496       XIDeviceEvent* xievent =
497           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
498       switch (xievent->evtype) {
499         case XI_ButtonPress:
500         case XI_ButtonRelease:
501           return GetEventFlagsForButton(EventButtonFromNative(native_event));
502         default:
503           break;
504       }
505     }
506     default:
507       break;
508   }
509   return 0;
510 }
511
512 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
513   float x_offset, y_offset;
514   if (GetScrollOffsets(
515       native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
516     return gfx::Vector2d(static_cast<int>(x_offset),
517                          static_cast<int>(y_offset));
518   }
519
520   int button = native_event->type == GenericEvent ?
521       EventButtonFromNative(native_event) : native_event->xbutton.button;
522
523   switch (button) {
524     case 4:
525       return gfx::Vector2d(0, kWheelScrollAmount);
526     case 5:
527       return gfx::Vector2d(0, -kWheelScrollAmount);
528     default:
529       // TODO(derat): Do something for horizontal scrolls (buttons 6 and 7)?
530       return gfx::Vector2d();
531   }
532 }
533
534 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
535   ui::EventType type = ui::EventTypeFromNative(xev);
536   if (type == ui::ET_TOUCH_CANCELLED ||
537       type == ui::ET_TOUCH_RELEASED) {
538     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
539     ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
540     double tracking_id;
541     if (manager->GetEventData(
542         *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
543       factory->ReleaseSlotForTrackingID(tracking_id);
544     }
545   }
546 }
547
548 int GetTouchId(const base::NativeEvent& xev) {
549   double slot = 0;
550 #if defined(ENABLE_XI21_MT)
551   // If using XInput2.1 for multi-touch support, the slot is tracked by the
552   // source id of each device event.
553   XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
554   slot = xievent->sourceid;
555 #endif
556   ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
557   double tracking_id;
558   if (!manager->GetEventData(
559       *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
560     LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
561   } else {
562     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
563     slot = factory->GetSlotForTrackingID(tracking_id);
564   }
565   return slot;
566 }
567
568 float GetTouchRadiusX(const base::NativeEvent& native_event) {
569   return GetTouchParamFromXEvent(native_event,
570       ui::DeviceDataManager::DT_TOUCH_MAJOR, 0.0) / 2.0;
571 }
572
573 float GetTouchRadiusY(const base::NativeEvent& native_event) {
574   return GetTouchParamFromXEvent(native_event,
575       ui::DeviceDataManager::DT_TOUCH_MINOR, 0.0) / 2.0;
576 }
577
578 float GetTouchAngle(const base::NativeEvent& native_event) {
579   return GetTouchParamFromXEvent(native_event,
580       ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
581 }
582
583 float GetTouchForce(const base::NativeEvent& native_event) {
584   double force = 0.0;
585   force = GetTouchParamFromXEvent(native_event,
586       ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0.0);
587   unsigned int deviceid =
588       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
589   // Force is normalized to fall into [0, 1]
590   if (!ui::DeviceDataManager::GetInstance()->NormalizeData(
591       deviceid, ui::DeviceDataManager::DT_TOUCH_PRESSURE, &force))
592     force = 0.0;
593   return force;
594 }
595
596 bool GetScrollOffsets(const base::NativeEvent& native_event,
597                       float* x_offset,
598                       float* y_offset,
599                       float* x_offset_ordinal,
600                       float* y_offset_ordinal,
601                       int* finger_count) {
602   if (!DeviceDataManager::GetInstance()->IsScrollEvent(native_event))
603     return false;
604
605   // Temp values to prevent passing NULLs to DeviceDataManager.
606   float x_offset_, y_offset_;
607   float x_offset_ordinal_, y_offset_ordinal_;
608   int finger_count_;
609   if (!x_offset)
610     x_offset = &x_offset_;
611   if (!y_offset)
612     y_offset = &y_offset_;
613   if (!x_offset_ordinal)
614     x_offset_ordinal = &x_offset_ordinal_;
615   if (!y_offset_ordinal)
616     y_offset_ordinal = &y_offset_ordinal_;
617   if (!finger_count)
618     finger_count = &finger_count_;
619
620   DeviceDataManager::GetInstance()->GetScrollOffsets(
621       native_event,
622       x_offset, y_offset,
623       x_offset_ordinal, y_offset_ordinal,
624       finger_count);
625   return true;
626 }
627
628 bool GetFlingData(const base::NativeEvent& native_event,
629                   float* vx,
630                   float* vy,
631                   float* vx_ordinal,
632                   float* vy_ordinal,
633                   bool* is_cancel) {
634   if (!DeviceDataManager::GetInstance()->IsFlingEvent(native_event))
635     return false;
636
637   float vx_, vy_;
638   float vx_ordinal_, vy_ordinal_;
639   bool is_cancel_;
640   if (!vx)
641     vx = &vx_;
642   if (!vy)
643     vy = &vy_;
644   if (!vx_ordinal)
645     vx_ordinal = &vx_ordinal_;
646   if (!vy_ordinal)
647     vy_ordinal = &vy_ordinal_;
648   if (!is_cancel)
649     is_cancel = &is_cancel_;
650
651   DeviceDataManager::GetInstance()->GetFlingData(
652       native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
653   return true;
654 }
655
656 bool GetGestureTimes(const base::NativeEvent& native_event,
657                      double* start_time,
658                      double* end_time) {
659   if (!DeviceDataManager::GetInstance()->HasGestureTimes(native_event))
660     return false;
661
662   double start_time_, end_time_;
663   if (!start_time)
664     start_time = &start_time_;
665   if (!end_time)
666     end_time = &end_time_;
667
668   DeviceDataManager::GetInstance()->GetGestureTimes(
669       native_event, start_time, end_time);
670   return true;
671 }
672
673 void SetNaturalScroll(bool enabled) {
674   DeviceDataManager::GetInstance()->set_natural_scroll_enabled(enabled);
675 }
676
677 bool IsNaturalScrollEnabled() {
678   return DeviceDataManager::GetInstance()->natural_scroll_enabled();
679 }
680
681 bool IsTouchpadEvent(const base::NativeEvent& event) {
682   return DeviceDataManager::GetInstance()->IsTouchpadXInputEvent(event);
683 }
684
685 }  // namespace ui