9fec9df2bf9bcf18d5f9947a3d96e0c4229a8662
[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     case 6:
529       return gfx::Vector2d(kWheelScrollAmount, 0);
530     case 7:
531       return gfx::Vector2d(-kWheelScrollAmount, 0);
532     default:
533       return gfx::Vector2d();
534   }
535 }
536
537 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
538   ui::EventType type = ui::EventTypeFromNative(xev);
539   if (type == ui::ET_TOUCH_CANCELLED ||
540       type == ui::ET_TOUCH_RELEASED) {
541     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
542     ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
543     double tracking_id;
544     if (manager->GetEventData(
545         *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
546       factory->ReleaseSlotForTrackingID(tracking_id);
547     }
548   }
549 }
550
551 int GetTouchId(const base::NativeEvent& xev) {
552   double slot = 0;
553   ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
554   double tracking_id;
555   if (!manager->GetEventData(
556       *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
557     LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
558   } else {
559     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
560     slot = factory->GetSlotForTrackingID(tracking_id);
561   }
562   return slot;
563 }
564
565 float GetTouchRadiusX(const base::NativeEvent& native_event) {
566   return GetTouchParamFromXEvent(native_event,
567       ui::DeviceDataManager::DT_TOUCH_MAJOR, 0.0) / 2.0;
568 }
569
570 float GetTouchRadiusY(const base::NativeEvent& native_event) {
571   return GetTouchParamFromXEvent(native_event,
572       ui::DeviceDataManager::DT_TOUCH_MINOR, 0.0) / 2.0;
573 }
574
575 float GetTouchAngle(const base::NativeEvent& native_event) {
576   return GetTouchParamFromXEvent(native_event,
577       ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
578 }
579
580 float GetTouchForce(const base::NativeEvent& native_event) {
581   double force = 0.0;
582   force = GetTouchParamFromXEvent(native_event,
583       ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0.0);
584   unsigned int deviceid =
585       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
586   // Force is normalized to fall into [0, 1]
587   if (!ui::DeviceDataManager::GetInstance()->NormalizeData(
588       deviceid, ui::DeviceDataManager::DT_TOUCH_PRESSURE, &force))
589     force = 0.0;
590   return force;
591 }
592
593 bool GetScrollOffsets(const base::NativeEvent& native_event,
594                       float* x_offset,
595                       float* y_offset,
596                       float* x_offset_ordinal,
597                       float* y_offset_ordinal,
598                       int* finger_count) {
599   if (!DeviceDataManager::GetInstance()->IsScrollEvent(native_event))
600     return false;
601
602   // Temp values to prevent passing NULLs to DeviceDataManager.
603   float x_offset_, y_offset_;
604   float x_offset_ordinal_, y_offset_ordinal_;
605   int finger_count_;
606   if (!x_offset)
607     x_offset = &x_offset_;
608   if (!y_offset)
609     y_offset = &y_offset_;
610   if (!x_offset_ordinal)
611     x_offset_ordinal = &x_offset_ordinal_;
612   if (!y_offset_ordinal)
613     y_offset_ordinal = &y_offset_ordinal_;
614   if (!finger_count)
615     finger_count = &finger_count_;
616
617   DeviceDataManager::GetInstance()->GetScrollOffsets(
618       native_event,
619       x_offset, y_offset,
620       x_offset_ordinal, y_offset_ordinal,
621       finger_count);
622   return true;
623 }
624
625 bool GetFlingData(const base::NativeEvent& native_event,
626                   float* vx,
627                   float* vy,
628                   float* vx_ordinal,
629                   float* vy_ordinal,
630                   bool* is_cancel) {
631   if (!DeviceDataManager::GetInstance()->IsFlingEvent(native_event))
632     return false;
633
634   float vx_, vy_;
635   float vx_ordinal_, vy_ordinal_;
636   bool is_cancel_;
637   if (!vx)
638     vx = &vx_;
639   if (!vy)
640     vy = &vy_;
641   if (!vx_ordinal)
642     vx_ordinal = &vx_ordinal_;
643   if (!vy_ordinal)
644     vy_ordinal = &vy_ordinal_;
645   if (!is_cancel)
646     is_cancel = &is_cancel_;
647
648   DeviceDataManager::GetInstance()->GetFlingData(
649       native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
650   return true;
651 }
652
653 bool GetGestureTimes(const base::NativeEvent& native_event,
654                      double* start_time,
655                      double* end_time) {
656   if (!DeviceDataManager::GetInstance()->HasGestureTimes(native_event))
657     return false;
658
659   double start_time_, end_time_;
660   if (!start_time)
661     start_time = &start_time_;
662   if (!end_time)
663     end_time = &end_time_;
664
665   DeviceDataManager::GetInstance()->GetGestureTimes(
666       native_event, start_time, end_time);
667   return true;
668 }
669
670 void SetNaturalScroll(bool enabled) {
671   DeviceDataManager::GetInstance()->set_natural_scroll_enabled(enabled);
672 }
673
674 bool IsNaturalScrollEnabled() {
675   return DeviceDataManager::GetInstance()->natural_scroll_enabled();
676 }
677
678 bool IsTouchpadEvent(const base::NativeEvent& event) {
679   return DeviceDataManager::GetInstance()->IsTouchpadXInputEvent(event);
680 }
681
682 }  // namespace ui