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