Upstream version 7.36.149.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 #include <X11/Xutil.h>
13
14 #include "base/logging.h"
15 #include "base/memory/singleton.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 & Mod4Mask)
141     flags |= ui::EF_COMMAND_DOWN;
142   if (state & Mod5Mask)
143     flags |= ui::EF_ALTGR_DOWN;
144   if (state & Button1Mask)
145     flags |= ui::EF_LEFT_MOUSE_BUTTON;
146   if (state & Button2Mask)
147     flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
148   if (state & Button3Mask)
149     flags |= ui::EF_RIGHT_MOUSE_BUTTON;
150   return flags;
151 }
152
153 int GetEventFlagsFromXKeyEvent(XEvent* xevent) {
154   DCHECK(xevent->type == KeyPress || xevent->type == KeyRelease);
155
156 #if defined(OS_CHROMEOS)
157   const int ime_fabricated_flag = 0;
158 #else
159   // XIM fabricates key events for the character compositions by XK_Multi_key.
160   // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in
161   // order to input "é", then XIM generates a key event with keycode=0 and
162   // state=0 for the composition, and the sequence of X11 key events will be
163   // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e.
164   //
165   // We have to send these fabricated key events to XIM so it can correctly
166   // handle the character compositions.
167   const bool fabricated_by_xim =
168       xevent->xkey.keycode == 0 && xevent->xkey.state == 0;
169   const int ime_fabricated_flag =
170       fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0;
171 #endif
172
173   return GetEventFlagsFromXState(xevent->xkey.state) |
174       (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) |
175       ime_fabricated_flag;
176 }
177
178 // Get the event flag for the button in XButtonEvent. During a ButtonPress
179 // event, |state| in XButtonEvent does not include the button that has just been
180 // pressed. Instead |state| contains flags for the buttons (if any) that had
181 // already been pressed before the current button, and |button| stores the most
182 // current pressed button. So, if you press down left mouse button, and while
183 // pressing it down, press down the right mouse button, then for the latter
184 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
185 // would be 3.
186 int GetEventFlagsForButton(int button) {
187   switch (button) {
188     case 1:
189       return ui::EF_LEFT_MOUSE_BUTTON;
190     case 2:
191       return ui::EF_MIDDLE_MOUSE_BUTTON;
192     case 3:
193       return ui::EF_RIGHT_MOUSE_BUTTON;
194     default:
195       return 0;
196   }
197 }
198
199 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
200   int buttonflags = 0;
201   for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
202     if (XIMaskIsSet(xievent->buttons.mask, i)) {
203       int button = (xievent->sourceid == xievent->deviceid) ?
204                    ui::DeviceDataManager::GetInstance()->GetMappedButton(i) : i;
205       buttonflags |= GetEventFlagsForButton(button);
206     }
207   }
208   return buttonflags;
209 }
210
211 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
212   XIDeviceEvent* event =
213       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
214 #if defined(USE_XI2_MT)
215   switch(event->evtype) {
216     case XI_TouchBegin:
217       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
218                                                        ui::ET_TOUCH_PRESSED;
219     case XI_TouchUpdate:
220       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
221                                                        ui::ET_TOUCH_MOVED;
222     case XI_TouchEnd:
223       return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED :
224                                                        ui::ET_TOUCH_RELEASED;
225   }
226 #endif  // defined(USE_XI2_MT)
227
228   DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid));
229   switch (event->evtype) {
230     case XI_ButtonPress:
231       return ui::ET_TOUCH_PRESSED;
232     case XI_ButtonRelease:
233       return ui::ET_TOUCH_RELEASED;
234     case XI_Motion:
235       // Should not convert any emulated Motion event from touch device to
236       // touch event.
237       if (!(event->flags & XIPointerEmulated) &&
238           GetButtonMaskForX2Event(event))
239         return ui::ET_TOUCH_MOVED;
240       return ui::ET_UNKNOWN;
241     default:
242       NOTREACHED();
243   }
244   return ui::ET_UNKNOWN;
245 }
246
247 double GetTouchParamFromXEvent(XEvent* xev,
248                               ui::DeviceDataManager::DataType val,
249                               double default_value) {
250   ui::DeviceDataManager::GetInstance()->GetEventData(
251       *xev, val, &default_value);
252   return default_value;
253 }
254
255 }  // namespace
256
257 namespace ui {
258
259 void UpdateDeviceList() {
260   XDisplay* display = gfx::GetXDisplay();
261   DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
262   TouchFactory::GetInstance()->UpdateDeviceList(display);
263   DeviceDataManager::GetInstance()->UpdateDeviceList(display);
264 }
265
266 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
267   switch (native_event->type) {
268     case KeyPress:
269       return ET_KEY_PRESSED;
270     case KeyRelease:
271       return ET_KEY_RELEASED;
272     case ButtonPress:
273       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
274           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
275         return ET_MOUSEWHEEL;
276       return ET_MOUSE_PRESSED;
277     case ButtonRelease:
278       // Drop wheel events; we should've already scrolled on the press.
279       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
280           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
281         return ET_UNKNOWN;
282       return ET_MOUSE_RELEASED;
283     case MotionNotify:
284       if (native_event->xmotion.state &
285           (Button1Mask | Button2Mask | Button3Mask))
286         return ET_MOUSE_DRAGGED;
287       return ET_MOUSE_MOVED;
288     case EnterNotify:
289       // The standard on Windows is to send a MouseMove event when the mouse
290       // first enters a window instead of sending a special mouse enter event.
291       // To be consistent we follow the same style.
292       return ET_MOUSE_MOVED;
293     case LeaveNotify:
294       return ET_MOUSE_EXITED;
295     case GenericEvent: {
296       TouchFactory* factory = TouchFactory::GetInstance();
297       if (!factory->ShouldProcessXI2Event(native_event))
298         return ET_UNKNOWN;
299
300       XIDeviceEvent* xievent =
301           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
302
303       // This check works only for master and floating slave devices. That is
304       // why it is necessary to check for the XI_Touch* events in the following
305       // switch statement to account for attached-slave touchscreens.
306       if (factory->IsTouchDevice(xievent->sourceid))
307         return GetTouchEventType(native_event);
308
309       switch (xievent->evtype) {
310         case XI_TouchBegin:
311           return ui::ET_TOUCH_PRESSED;
312         case XI_TouchUpdate:
313           return ui::ET_TOUCH_MOVED;
314         case XI_TouchEnd:
315           return ui::ET_TOUCH_RELEASED;
316         case XI_ButtonPress: {
317           int button = EventButtonFromNative(native_event);
318           if (button >= kMinWheelButton && button <= kMaxWheelButton)
319             return ET_MOUSEWHEEL;
320           return ET_MOUSE_PRESSED;
321         }
322         case XI_ButtonRelease: {
323           int button = EventButtonFromNative(native_event);
324           // Drop wheel events; we should've already scrolled on the press.
325           if (button >= kMinWheelButton && button <= kMaxWheelButton)
326             return ET_UNKNOWN;
327           return ET_MOUSE_RELEASED;
328         }
329         case XI_Motion: {
330           bool is_cancel;
331           if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) {
332             return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
333           } else if (DeviceDataManager::GetInstance()->IsScrollEvent(
334               native_event)) {
335             return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
336           } else if (DeviceDataManager::GetInstance()->IsCMTMetricsEvent(
337               native_event)) {
338             return ET_UMA_DATA;
339           } else if (GetButtonMaskForX2Event(xievent)) {
340             return ET_MOUSE_DRAGGED;
341           } else {
342             return ET_MOUSE_MOVED;
343           }
344         }
345       }
346     }
347     default:
348       break;
349   }
350   return ET_UNKNOWN;
351 }
352
353 int EventFlagsFromNative(const base::NativeEvent& native_event) {
354   switch (native_event->type) {
355     case KeyPress:
356     case KeyRelease: {
357       XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event);
358       return GetEventFlagsFromXKeyEvent(native_event);
359     }
360     case ButtonPress:
361     case ButtonRelease: {
362       int flags = GetEventFlagsFromXState(native_event->xbutton.state);
363       const EventType type = EventTypeFromNative(native_event);
364       if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
365         flags |= GetEventFlagsForButton(native_event->xbutton.button);
366       return flags;
367     }
368     case EnterNotify:
369     case LeaveNotify:
370       return GetEventFlagsFromXState(native_event->xcrossing.state);
371     case MotionNotify:
372       return GetEventFlagsFromXState(native_event->xmotion.state);
373     case GenericEvent: {
374       XIDeviceEvent* xievent =
375           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
376
377       switch (xievent->evtype) {
378 #if defined(USE_XI2_MT)
379         case XI_TouchBegin:
380         case XI_TouchUpdate:
381         case XI_TouchEnd:
382           return GetButtonMaskForX2Event(xievent) |
383                  GetEventFlagsFromXState(xievent->mods.effective) |
384                  GetEventFlagsFromXState(
385                      XModifierStateWatcher::GetInstance()->state());
386           break;
387 #endif
388         case XI_ButtonPress:
389         case XI_ButtonRelease: {
390           const bool touch =
391               TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
392           int flags = GetButtonMaskForX2Event(xievent) |
393               GetEventFlagsFromXState(xievent->mods.effective);
394           if (touch) {
395             flags |= GetEventFlagsFromXState(
396                 XModifierStateWatcher::GetInstance()->state());
397           }
398
399           const EventType type = EventTypeFromNative(native_event);
400           int button = EventButtonFromNative(native_event);
401           if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
402             flags |= GetEventFlagsForButton(button);
403           return flags;
404         }
405         case XI_Motion:
406            return GetButtonMaskForX2Event(xievent) |
407                   GetEventFlagsFromXState(xievent->mods.effective);
408       }
409     }
410   }
411   return 0;
412 }
413
414 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
415   switch(native_event->type) {
416     case KeyPress:
417     case KeyRelease:
418       return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
419     case ButtonPress:
420     case ButtonRelease:
421       return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
422       break;
423     case MotionNotify:
424       return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
425       break;
426     case EnterNotify:
427     case LeaveNotify:
428       return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
429       break;
430     case GenericEvent: {
431       double start, end;
432       double touch_timestamp;
433       if (GetGestureTimes(native_event, &start, &end)) {
434         // If the driver supports gesture times, use them.
435         return base::TimeDelta::FromMicroseconds(end * 1000000);
436       } else if (DeviceDataManager::GetInstance()->GetEventData(*native_event,
437                  DeviceDataManager::DT_TOUCH_RAW_TIMESTAMP, &touch_timestamp)) {
438         return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
439       } else {
440         XIDeviceEvent* xide =
441             static_cast<XIDeviceEvent*>(native_event->xcookie.data);
442         return base::TimeDelta::FromMilliseconds(xide->time);
443       }
444       break;
445     }
446   }
447   NOTREACHED();
448   return base::TimeDelta();
449 }
450
451 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
452   switch (native_event->type) {
453     case EnterNotify:
454     case LeaveNotify:
455       return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
456     case ButtonPress:
457     case ButtonRelease:
458       return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
459     case MotionNotify:
460       return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
461     case GenericEvent: {
462       XIDeviceEvent* xievent =
463           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
464       return gfx::Point(static_cast<int>(xievent->event_x),
465                         static_cast<int>(xievent->event_y));
466     }
467   }
468   return gfx::Point();
469 }
470
471 gfx::Point EventSystemLocationFromNative(
472     const base::NativeEvent& native_event) {
473   switch (native_event->type) {
474     case EnterNotify:
475     case LeaveNotify: {
476       return gfx::Point(native_event->xcrossing.x_root,
477                         native_event->xcrossing.y_root);
478     }
479     case ButtonPress:
480     case ButtonRelease: {
481       return gfx::Point(native_event->xbutton.x_root,
482                         native_event->xbutton.y_root);
483     }
484     case MotionNotify: {
485       return gfx::Point(native_event->xmotion.x_root,
486                         native_event->xmotion.y_root);
487     }
488     case GenericEvent: {
489       XIDeviceEvent* xievent =
490           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
491       return gfx::Point(xievent->root_x, xievent->root_y);
492     }
493   }
494
495   return gfx::Point();
496 }
497
498 int EventButtonFromNative(const base::NativeEvent& native_event) {
499   CHECK_EQ(GenericEvent, native_event->type);
500   XIDeviceEvent* xievent =
501       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
502   int button = xievent->detail;
503
504   return (xievent->sourceid == xievent->deviceid) ?
505          DeviceDataManager::GetInstance()->GetMappedButton(button) : button;
506 }
507
508 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
509   return KeyboardCodeFromXKeyEvent(native_event);
510 }
511
512 const char* CodeFromNative(const base::NativeEvent& native_event) {
513   return CodeFromXEvent(native_event);
514 }
515
516 int GetChangedMouseButtonFlagsFromNative(
517     const base::NativeEvent& native_event) {
518   switch (native_event->type) {
519     case ButtonPress:
520     case ButtonRelease:
521       return GetEventFlagsFromXState(native_event->xbutton.state);
522     case GenericEvent: {
523       XIDeviceEvent* xievent =
524           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
525       switch (xievent->evtype) {
526         case XI_ButtonPress:
527         case XI_ButtonRelease:
528           return GetEventFlagsForButton(EventButtonFromNative(native_event));
529         default:
530           break;
531       }
532     }
533     default:
534       break;
535   }
536   return 0;
537 }
538
539 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
540   float x_offset, y_offset;
541   if (GetScrollOffsets(
542       native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
543     return gfx::Vector2d(static_cast<int>(x_offset),
544                          static_cast<int>(y_offset));
545   }
546
547   int button = native_event->type == GenericEvent ?
548       EventButtonFromNative(native_event) : native_event->xbutton.button;
549
550   switch (button) {
551     case 4:
552       return gfx::Vector2d(0, kWheelScrollAmount);
553     case 5:
554       return gfx::Vector2d(0, -kWheelScrollAmount);
555     case 6:
556       return gfx::Vector2d(kWheelScrollAmount, 0);
557     case 7:
558       return gfx::Vector2d(-kWheelScrollAmount, 0);
559     default:
560       return gfx::Vector2d();
561   }
562 }
563
564 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
565   if (!event || event->type == GenericEvent)
566     return NULL;
567   XEvent* copy = new XEvent;
568   *copy = *event;
569   return copy;
570 }
571
572 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
573   delete event;
574 }
575
576 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
577   ui::EventType type = ui::EventTypeFromNative(xev);
578   if (type == ui::ET_TOUCH_CANCELLED ||
579       type == ui::ET_TOUCH_RELEASED) {
580     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
581     ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
582     double tracking_id;
583     if (manager->GetEventData(
584         *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
585       factory->ReleaseSlotForTrackingID(tracking_id);
586     }
587   }
588 }
589
590 int GetTouchId(const base::NativeEvent& xev) {
591   double slot = 0;
592   ui::DeviceDataManager* manager = ui::DeviceDataManager::GetInstance();
593   double tracking_id;
594   if (!manager->GetEventData(
595       *xev, ui::DeviceDataManager::DT_TOUCH_TRACKING_ID, &tracking_id)) {
596     LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
597   } else {
598     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
599     slot = factory->GetSlotForTrackingID(tracking_id);
600   }
601   return slot;
602 }
603
604 float GetTouchRadiusX(const base::NativeEvent& native_event) {
605   return GetTouchParamFromXEvent(native_event,
606       ui::DeviceDataManager::DT_TOUCH_MAJOR, 0.0) / 2.0;
607 }
608
609 float GetTouchRadiusY(const base::NativeEvent& native_event) {
610   return GetTouchParamFromXEvent(native_event,
611       ui::DeviceDataManager::DT_TOUCH_MINOR, 0.0) / 2.0;
612 }
613
614 float GetTouchAngle(const base::NativeEvent& native_event) {
615   return GetTouchParamFromXEvent(native_event,
616       ui::DeviceDataManager::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
617 }
618
619 float GetTouchForce(const base::NativeEvent& native_event) {
620   double force = 0.0;
621   force = GetTouchParamFromXEvent(native_event,
622       ui::DeviceDataManager::DT_TOUCH_PRESSURE, 0.0);
623   unsigned int deviceid =
624       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
625   // Force is normalized to fall into [0, 1]
626   if (!ui::DeviceDataManager::GetInstance()->NormalizeData(
627       deviceid, ui::DeviceDataManager::DT_TOUCH_PRESSURE, &force))
628     force = 0.0;
629   return force;
630 }
631
632 bool GetScrollOffsets(const base::NativeEvent& native_event,
633                       float* x_offset,
634                       float* y_offset,
635                       float* x_offset_ordinal,
636                       float* y_offset_ordinal,
637                       int* finger_count) {
638   if (!DeviceDataManager::GetInstance()->IsScrollEvent(native_event))
639     return false;
640
641   // Temp values to prevent passing NULLs to DeviceDataManager.
642   float x_offset_, y_offset_;
643   float x_offset_ordinal_, y_offset_ordinal_;
644   int finger_count_;
645   if (!x_offset)
646     x_offset = &x_offset_;
647   if (!y_offset)
648     y_offset = &y_offset_;
649   if (!x_offset_ordinal)
650     x_offset_ordinal = &x_offset_ordinal_;
651   if (!y_offset_ordinal)
652     y_offset_ordinal = &y_offset_ordinal_;
653   if (!finger_count)
654     finger_count = &finger_count_;
655
656   DeviceDataManager::GetInstance()->GetScrollOffsets(
657       native_event,
658       x_offset, y_offset,
659       x_offset_ordinal, y_offset_ordinal,
660       finger_count);
661   return true;
662 }
663
664 bool GetFlingData(const base::NativeEvent& native_event,
665                   float* vx,
666                   float* vy,
667                   float* vx_ordinal,
668                   float* vy_ordinal,
669                   bool* is_cancel) {
670   if (!DeviceDataManager::GetInstance()->IsFlingEvent(native_event))
671     return false;
672
673   float vx_, vy_;
674   float vx_ordinal_, vy_ordinal_;
675   bool is_cancel_;
676   if (!vx)
677     vx = &vx_;
678   if (!vy)
679     vy = &vy_;
680   if (!vx_ordinal)
681     vx_ordinal = &vx_ordinal_;
682   if (!vy_ordinal)
683     vy_ordinal = &vy_ordinal_;
684   if (!is_cancel)
685     is_cancel = &is_cancel_;
686
687   DeviceDataManager::GetInstance()->GetFlingData(
688       native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
689   return true;
690 }
691
692 bool GetGestureTimes(const base::NativeEvent& native_event,
693                      double* start_time,
694                      double* end_time) {
695   if (!DeviceDataManager::GetInstance()->HasGestureTimes(native_event))
696     return false;
697
698   double start_time_, end_time_;
699   if (!start_time)
700     start_time = &start_time_;
701   if (!end_time)
702     end_time = &end_time_;
703
704   DeviceDataManager::GetInstance()->GetGestureTimes(
705       native_event, start_time, end_time);
706   return true;
707 }
708
709 bool IsTouchpadEvent(const base::NativeEvent& event) {
710   return DeviceDataManager::GetInstance()->IsTouchpadXInputEvent(event);
711 }
712
713 }  // namespace ui