Home | History | Annotate | Download | only in x
      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 #include <X11/XKBlib.h>
     14 
     15 #include "base/logging.h"
     16 #include "base/memory/singleton.h"
     17 #include "ui/events/event.h"
     18 #include "ui/events/event_utils.h"
     19 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
     20 #include "ui/events/x/device_data_manager_x11.h"
     21 #include "ui/events/x/device_list_cache_x.h"
     22 #include "ui/events/x/touch_factory_x11.h"
     23 #include "ui/gfx/display.h"
     24 #include "ui/gfx/point.h"
     25 #include "ui/gfx/rect.h"
     26 #include "ui/gfx/screen.h"
     27 #include "ui/gfx/x/x11_atom_cache.h"
     28 #include "ui/gfx/x/x11_types.h"
     29 
     30 namespace {
     31 
     32 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
     33 const int kWheelScrollAmount = 53;
     34 
     35 const int kMinWheelButton = 4;
     36 const int kMaxWheelButton = 7;
     37 
     38 // A class to track current modifier state on master device. Only track ctrl,
     39 // alt, shift and caps lock keys currently. The tracked state can then be used
     40 // by floating device.
     41 class XModifierStateWatcher{
     42  public:
     43   static XModifierStateWatcher* GetInstance() {
     44     return Singleton<XModifierStateWatcher>::get();
     45   }
     46 
     47   int StateFromKeyboardCode(ui::KeyboardCode keyboard_code) {
     48     switch (keyboard_code) {
     49       case ui::VKEY_CONTROL:
     50         return ControlMask;
     51       case ui::VKEY_SHIFT:
     52         return ShiftMask;
     53       case ui::VKEY_MENU:
     54         return Mod1Mask;
     55       case ui::VKEY_CAPITAL:
     56         return LockMask;
     57       default:
     58         return 0;
     59     }
     60   }
     61 
     62   void UpdateStateFromXEvent(const base::NativeEvent& native_event) {
     63     ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
     64     unsigned int mask = StateFromKeyboardCode(keyboard_code);
     65     // Floating device can't access the modifer state from master device.
     66     // We need to track the states of modifier keys in a singleton for
     67     // floating devices such as touch screen. Issue 106426 is one example
     68     // of why we need the modifier states for floating device.
     69     switch (native_event->type) {
     70       case KeyPress:
     71         state_ = native_event->xkey.state | mask;
     72         break;
     73       case KeyRelease:
     74         state_ = native_event->xkey.state & ~mask;
     75         break;
     76       case GenericEvent: {
     77         XIDeviceEvent* xievent =
     78             static_cast<XIDeviceEvent*>(native_event->xcookie.data);
     79         switch (xievent->evtype) {
     80           case XI_KeyPress:
     81             state_ = xievent->mods.effective |= mask;
     82             break;
     83           case XI_KeyRelease:
     84             state_ = xievent->mods.effective &= ~mask;
     85             break;
     86           default:
     87             NOTREACHED();
     88             break;
     89         }
     90         break;
     91       }
     92       default:
     93         NOTREACHED();
     94         break;
     95     }
     96   }
     97 
     98   // Returns the current modifer state in master device. It only contains the
     99   // state of ctrl, shift, alt and caps lock keys.
    100   unsigned int state() { return state_; }
    101 
    102  private:
    103   friend struct DefaultSingletonTraits<XModifierStateWatcher>;
    104 
    105   XModifierStateWatcher() : state_(0) { }
    106 
    107   unsigned int state_;
    108 
    109   DISALLOW_COPY_AND_ASSIGN(XModifierStateWatcher);
    110 };
    111 
    112 #if defined(USE_XI2_MT)
    113 // Detects if a touch event is a driver-generated 'special event'.
    114 // A 'special event' is a touch event with maximum radius and pressure at
    115 // location (0, 0).
    116 // This needs to be done in a cleaner way: http://crbug.com/169256
    117 bool TouchEventIsGeneratedHack(const base::NativeEvent& native_event) {
    118   XIDeviceEvent* event =
    119       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    120   CHECK(event->evtype == XI_TouchBegin ||
    121         event->evtype == XI_TouchUpdate ||
    122         event->evtype == XI_TouchEnd);
    123 
    124   // Force is normalized to [0, 1].
    125   if (ui::GetTouchForce(native_event) < 1.0f)
    126     return false;
    127 
    128   if (ui::EventLocationFromNative(native_event) != gfx::Point())
    129     return false;
    130 
    131   // Radius is in pixels, and the valuator is the diameter in pixels.
    132   double radius = ui::GetTouchRadiusX(native_event), min, max;
    133   unsigned int deviceid =
    134       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
    135   if (!ui::DeviceDataManagerX11::GetInstance()->GetDataRange(
    136       deviceid, ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, &min, &max)) {
    137     return false;
    138   }
    139 
    140   return radius * 2 == max;
    141 }
    142 #endif
    143 
    144 int GetEventFlagsFromXState(unsigned int state) {
    145   int flags = 0;
    146   if (state & ControlMask)
    147     flags |= ui::EF_CONTROL_DOWN;
    148   if (state & ShiftMask)
    149     flags |= ui::EF_SHIFT_DOWN;
    150   if (state & Mod1Mask)
    151     flags |= ui::EF_ALT_DOWN;
    152   if (state & LockMask)
    153     flags |= ui::EF_CAPS_LOCK_DOWN;
    154   if (state & Mod3Mask)
    155     flags |= ui::EF_MOD3_DOWN;
    156   if (state & Mod4Mask)
    157     flags |= ui::EF_COMMAND_DOWN;
    158   if (state & Mod5Mask)
    159     flags |= ui::EF_ALTGR_DOWN;
    160   if (state & Button1Mask)
    161     flags |= ui::EF_LEFT_MOUSE_BUTTON;
    162   if (state & Button2Mask)
    163     flags |= ui::EF_MIDDLE_MOUSE_BUTTON;
    164   if (state & Button3Mask)
    165     flags |= ui::EF_RIGHT_MOUSE_BUTTON;
    166   return flags;
    167 }
    168 
    169 int GetEventFlagsFromXKeyEvent(XEvent* xevent) {
    170   DCHECK(xevent->type == KeyPress || xevent->type == KeyRelease);
    171 
    172 #if defined(OS_CHROMEOS)
    173   const int ime_fabricated_flag = 0;
    174 #else
    175   // XIM fabricates key events for the character compositions by XK_Multi_key.
    176   // For example, when a user hits XK_Multi_key, XK_apostrophe, and XK_e in
    177   // order to input "", then XIM generates a key event with keycode=0 and
    178   // state=0 for the composition, and the sequence of X11 key events will be
    179   // XK_Multi_key, XK_apostrophe, **NoSymbol**, and XK_e.  If the user used
    180   // shift key and/or caps lock key, state can be ShiftMask, LockMask or both.
    181   //
    182   // We have to send these fabricated key events to XIM so it can correctly
    183   // handle the character compositions.
    184   const unsigned int shift_lock_mask = ShiftMask | LockMask;
    185   const bool fabricated_by_xim =
    186       xevent->xkey.keycode == 0 &&
    187       (xevent->xkey.state & ~shift_lock_mask) == 0;
    188   const int ime_fabricated_flag =
    189       fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0;
    190 #endif
    191 
    192   return GetEventFlagsFromXState(xevent->xkey.state) |
    193       (xevent->xkey.send_event ? ui::EF_FINAL : 0) |
    194       (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) |
    195       (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ?
    196           ui::EF_FUNCTION_KEY : 0) |
    197       ime_fabricated_flag;
    198 }
    199 
    200 int GetEventFlagsFromXGenericEvent(XEvent* xevent) {
    201   DCHECK(xevent->type == GenericEvent);
    202   XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
    203   DCHECK((xievent->evtype == XI_KeyPress) ||
    204          (xievent->evtype == XI_KeyRelease));
    205   return GetEventFlagsFromXState(xievent->mods.effective) |
    206          (xevent->xkey.send_event ? ui::EF_FINAL : 0) |
    207          (IsKeypadKey(
    208               XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0))
    209               ? ui::EF_NUMPAD_KEY
    210               : 0);
    211 }
    212 
    213 // Get the event flag for the button in XButtonEvent. During a ButtonPress
    214 // event, |state| in XButtonEvent does not include the button that has just been
    215 // pressed. Instead |state| contains flags for the buttons (if any) that had
    216 // already been pressed before the current button, and |button| stores the most
    217 // current pressed button. So, if you press down left mouse button, and while
    218 // pressing it down, press down the right mouse button, then for the latter
    219 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
    220 // would be 3.
    221 int GetEventFlagsForButton(int button) {
    222   switch (button) {
    223     case 1:
    224       return ui::EF_LEFT_MOUSE_BUTTON;
    225     case 2:
    226       return ui::EF_MIDDLE_MOUSE_BUTTON;
    227     case 3:
    228       return ui::EF_RIGHT_MOUSE_BUTTON;
    229     default:
    230       return 0;
    231   }
    232 }
    233 
    234 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
    235   int buttonflags = 0;
    236   for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
    237     if (XIMaskIsSet(xievent->buttons.mask, i)) {
    238       int button = (xievent->sourceid == xievent->deviceid) ?
    239           ui::DeviceDataManagerX11::GetInstance()->GetMappedButton(i) : i;
    240       buttonflags |= GetEventFlagsForButton(button);
    241     }
    242   }
    243   return buttonflags;
    244 }
    245 
    246 ui::EventType GetTouchEventType(const base::NativeEvent& native_event) {
    247   XIDeviceEvent* event =
    248       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    249 #if defined(USE_XI2_MT)
    250   switch(event->evtype) {
    251     case XI_TouchBegin:
    252       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
    253                                                        ui::ET_TOUCH_PRESSED;
    254     case XI_TouchUpdate:
    255       return TouchEventIsGeneratedHack(native_event) ? ui::ET_UNKNOWN :
    256                                                        ui::ET_TOUCH_MOVED;
    257     case XI_TouchEnd:
    258       return TouchEventIsGeneratedHack(native_event) ? ui::ET_TOUCH_CANCELLED :
    259                                                        ui::ET_TOUCH_RELEASED;
    260   }
    261 #endif  // defined(USE_XI2_MT)
    262 
    263   DCHECK(ui::TouchFactory::GetInstance()->IsTouchDevice(event->sourceid));
    264   switch (event->evtype) {
    265     case XI_ButtonPress:
    266       return ui::ET_TOUCH_PRESSED;
    267     case XI_ButtonRelease:
    268       return ui::ET_TOUCH_RELEASED;
    269     case XI_Motion:
    270       // Should not convert any emulated Motion event from touch device to
    271       // touch event.
    272       if (!(event->flags & XIPointerEmulated) &&
    273           GetButtonMaskForX2Event(event))
    274         return ui::ET_TOUCH_MOVED;
    275       return ui::ET_UNKNOWN;
    276     default:
    277       NOTREACHED();
    278   }
    279   return ui::ET_UNKNOWN;
    280 }
    281 
    282 double GetTouchParamFromXEvent(XEvent* xev,
    283                               ui::DeviceDataManagerX11::DataType val,
    284                               double default_value) {
    285   ui::DeviceDataManagerX11::GetInstance()->GetEventData(
    286       *xev, val, &default_value);
    287   return default_value;
    288 }
    289 
    290 void ScaleTouchRadius(XEvent* xev, double* radius) {
    291   DCHECK_EQ(GenericEvent, xev->type);
    292   XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev->xcookie.data);
    293   ui::DeviceDataManagerX11::GetInstance()->ApplyTouchRadiusScale(
    294       xiev->sourceid, radius);
    295 }
    296 
    297 unsigned int UpdateX11EventFlags(int ui_flags, unsigned int old_x_flags) {
    298   static struct {
    299     int ui;
    300     int x;
    301   } flags[] = {
    302     {ui::EF_CONTROL_DOWN, ControlMask},
    303     {ui::EF_SHIFT_DOWN, ShiftMask},
    304     {ui::EF_ALT_DOWN, Mod1Mask},
    305     {ui::EF_CAPS_LOCK_DOWN, LockMask},
    306     {ui::EF_ALTGR_DOWN, Mod5Mask},
    307     {ui::EF_COMMAND_DOWN, Mod4Mask},
    308     {ui::EF_MOD3_DOWN, Mod3Mask},
    309     {ui::EF_NUMPAD_KEY, Mod2Mask},
    310     {ui::EF_LEFT_MOUSE_BUTTON, Button1Mask},
    311     {ui::EF_MIDDLE_MOUSE_BUTTON, Button2Mask},
    312     {ui::EF_RIGHT_MOUSE_BUTTON, Button3Mask},
    313   };
    314   unsigned int new_x_flags = old_x_flags;
    315   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(flags); ++i) {
    316     if (ui_flags & flags[i].ui)
    317       new_x_flags |= flags[i].x;
    318     else
    319       new_x_flags &= ~flags[i].x;
    320   }
    321   return new_x_flags;
    322 }
    323 
    324 unsigned int UpdateX11EventButton(int ui_flag, unsigned int old_x_button) {
    325   switch (ui_flag) {
    326     case ui::EF_LEFT_MOUSE_BUTTON:
    327       return Button1;
    328     case ui::EF_MIDDLE_MOUSE_BUTTON:
    329       return Button2;
    330     case ui::EF_RIGHT_MOUSE_BUTTON:
    331       return Button3;
    332     default:
    333       return old_x_button;
    334   }
    335   NOTREACHED();
    336 }
    337 
    338 bool GetGestureTimes(const base::NativeEvent& native_event,
    339                      double* start_time,
    340                      double* end_time) {
    341   if (!ui::DeviceDataManagerX11::GetInstance()->HasGestureTimes(native_event))
    342     return false;
    343 
    344   double start_time_, end_time_;
    345   if (!start_time)
    346     start_time = &start_time_;
    347   if (!end_time)
    348     end_time = &end_time_;
    349 
    350   ui::DeviceDataManagerX11::GetInstance()->GetGestureTimes(
    351       native_event, start_time, end_time);
    352   return true;
    353 }
    354 
    355 }  // namespace
    356 
    357 namespace ui {
    358 
    359 void UpdateDeviceList() {
    360   XDisplay* display = gfx::GetXDisplay();
    361   DeviceListCacheX::GetInstance()->UpdateDeviceList(display);
    362   TouchFactory::GetInstance()->UpdateDeviceList(display);
    363   DeviceDataManagerX11::GetInstance()->UpdateDeviceList(display);
    364 }
    365 
    366 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
    367   // Allow the DeviceDataManager to block the event. If blocked return
    368   // ET_UNKNOWN as the type so this event will not be further processed.
    369   // NOTE: During some events unittests there is no device data manager.
    370   if (DeviceDataManager::HasInstance() &&
    371       static_cast<DeviceDataManagerX11*>(DeviceDataManager::GetInstance())->
    372           IsEventBlocked(native_event)) {
    373     return ET_UNKNOWN;
    374   }
    375 
    376   switch (native_event->type) {
    377     case KeyPress:
    378       return ET_KEY_PRESSED;
    379     case KeyRelease:
    380       return ET_KEY_RELEASED;
    381     case ButtonPress:
    382       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
    383           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
    384         return ET_MOUSEWHEEL;
    385       return ET_MOUSE_PRESSED;
    386     case ButtonRelease:
    387       // Drop wheel events; we should've already scrolled on the press.
    388       if (static_cast<int>(native_event->xbutton.button) >= kMinWheelButton &&
    389           static_cast<int>(native_event->xbutton.button) <= kMaxWheelButton)
    390         return ET_UNKNOWN;
    391       return ET_MOUSE_RELEASED;
    392     case MotionNotify:
    393       if (native_event->xmotion.state &
    394           (Button1Mask | Button2Mask | Button3Mask))
    395         return ET_MOUSE_DRAGGED;
    396       return ET_MOUSE_MOVED;
    397     case EnterNotify:
    398       // The standard on Windows is to send a MouseMove event when the mouse
    399       // first enters a window instead of sending a special mouse enter event.
    400       // To be consistent we follow the same style.
    401       return ET_MOUSE_MOVED;
    402     case LeaveNotify:
    403       return ET_MOUSE_EXITED;
    404     case GenericEvent: {
    405       TouchFactory* factory = TouchFactory::GetInstance();
    406       if (!factory->ShouldProcessXI2Event(native_event))
    407         return ET_UNKNOWN;
    408 
    409       XIDeviceEvent* xievent =
    410           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    411 
    412       // This check works only for master and floating slave devices. That is
    413       // why it is necessary to check for the XI_Touch* events in the following
    414       // switch statement to account for attached-slave touchscreens.
    415       if (factory->IsTouchDevice(xievent->sourceid))
    416         return GetTouchEventType(native_event);
    417 
    418       switch (xievent->evtype) {
    419         case XI_TouchBegin:
    420           return ui::ET_TOUCH_PRESSED;
    421         case XI_TouchUpdate:
    422           return ui::ET_TOUCH_MOVED;
    423         case XI_TouchEnd:
    424           return ui::ET_TOUCH_RELEASED;
    425         case XI_ButtonPress: {
    426           int button = EventButtonFromNative(native_event);
    427           if (button >= kMinWheelButton && button <= kMaxWheelButton)
    428             return ET_MOUSEWHEEL;
    429           return ET_MOUSE_PRESSED;
    430         }
    431         case XI_ButtonRelease: {
    432           int button = EventButtonFromNative(native_event);
    433           // Drop wheel events; we should've already scrolled on the press.
    434           if (button >= kMinWheelButton && button <= kMaxWheelButton)
    435             return ET_UNKNOWN;
    436           return ET_MOUSE_RELEASED;
    437         }
    438         case XI_Motion: {
    439           bool is_cancel;
    440           DeviceDataManagerX11* devices = DeviceDataManagerX11::GetInstance();
    441           if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel))
    442             return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
    443           if (devices->IsScrollEvent(native_event)) {
    444             return devices->IsTouchpadXInputEvent(native_event) ? ET_SCROLL
    445                                                                 : ET_MOUSEWHEEL;
    446           }
    447           if (devices->IsCMTMetricsEvent(native_event))
    448             return ET_UMA_DATA;
    449           if (GetButtonMaskForX2Event(xievent))
    450             return ET_MOUSE_DRAGGED;
    451           return ET_MOUSE_MOVED;
    452         }
    453         case XI_KeyPress:
    454           return ET_KEY_PRESSED;
    455         case XI_KeyRelease:
    456           return ET_KEY_RELEASED;
    457       }
    458     }
    459     default:
    460       break;
    461   }
    462   return ET_UNKNOWN;
    463 }
    464 
    465 int EventFlagsFromNative(const base::NativeEvent& native_event) {
    466   switch (native_event->type) {
    467     case KeyPress:
    468     case KeyRelease: {
    469       XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event);
    470       return GetEventFlagsFromXKeyEvent(native_event);
    471     }
    472     case ButtonPress:
    473     case ButtonRelease: {
    474       int flags = GetEventFlagsFromXState(native_event->xbutton.state);
    475       const EventType type = EventTypeFromNative(native_event);
    476       if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
    477         flags |= GetEventFlagsForButton(native_event->xbutton.button);
    478       return flags;
    479     }
    480     case EnterNotify:
    481     case LeaveNotify:
    482       return GetEventFlagsFromXState(native_event->xcrossing.state);
    483     case MotionNotify:
    484       return GetEventFlagsFromXState(native_event->xmotion.state);
    485     case GenericEvent: {
    486       XIDeviceEvent* xievent =
    487           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    488 
    489       switch (xievent->evtype) {
    490 #if defined(USE_XI2_MT)
    491         case XI_TouchBegin:
    492         case XI_TouchUpdate:
    493         case XI_TouchEnd:
    494           return GetButtonMaskForX2Event(xievent) |
    495                  GetEventFlagsFromXState(xievent->mods.effective) |
    496                  GetEventFlagsFromXState(
    497                      XModifierStateWatcher::GetInstance()->state());
    498           break;
    499 #endif
    500         case XI_ButtonPress:
    501         case XI_ButtonRelease: {
    502           const bool touch =
    503               TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
    504           int flags = GetButtonMaskForX2Event(xievent) |
    505                       GetEventFlagsFromXState(xievent->mods.effective);
    506           if (touch) {
    507             flags |= GetEventFlagsFromXState(
    508                 XModifierStateWatcher::GetInstance()->state());
    509           }
    510 
    511           const EventType type = EventTypeFromNative(native_event);
    512           int button = EventButtonFromNative(native_event);
    513           if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
    514             flags |= GetEventFlagsForButton(button);
    515           return flags;
    516         }
    517         case XI_Motion:
    518           return GetButtonMaskForX2Event(xievent) |
    519                  GetEventFlagsFromXState(xievent->mods.effective);
    520         case XI_KeyPress:
    521         case XI_KeyRelease: {
    522           XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
    523               native_event);
    524           return GetEventFlagsFromXGenericEvent(native_event);
    525         }
    526       }
    527     }
    528   }
    529   return 0;
    530 }
    531 
    532 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
    533   switch(native_event->type) {
    534     case KeyPress:
    535     case KeyRelease:
    536       return base::TimeDelta::FromMilliseconds(native_event->xkey.time);
    537     case ButtonPress:
    538     case ButtonRelease:
    539       return base::TimeDelta::FromMilliseconds(native_event->xbutton.time);
    540       break;
    541     case MotionNotify:
    542       return base::TimeDelta::FromMilliseconds(native_event->xmotion.time);
    543       break;
    544     case EnterNotify:
    545     case LeaveNotify:
    546       return base::TimeDelta::FromMilliseconds(native_event->xcrossing.time);
    547       break;
    548     case GenericEvent: {
    549       double start, end;
    550       double touch_timestamp;
    551       if (GetGestureTimes(native_event, &start, &end)) {
    552         // If the driver supports gesture times, use them.
    553         return base::TimeDelta::FromMicroseconds(end * 1000000);
    554       } else if (DeviceDataManagerX11::GetInstance()->GetEventData(
    555           *native_event,
    556           DeviceDataManagerX11::DT_TOUCH_RAW_TIMESTAMP,
    557           &touch_timestamp)) {
    558         return base::TimeDelta::FromMicroseconds(touch_timestamp * 1000000);
    559       } else {
    560         XIDeviceEvent* xide =
    561             static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    562         return base::TimeDelta::FromMilliseconds(xide->time);
    563       }
    564       break;
    565     }
    566   }
    567   NOTREACHED();
    568   return base::TimeDelta();
    569 }
    570 
    571 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
    572   switch (native_event->type) {
    573     case EnterNotify:
    574     case LeaveNotify:
    575       return gfx::Point(native_event->xcrossing.x, native_event->xcrossing.y);
    576     case ButtonPress:
    577     case ButtonRelease:
    578       return gfx::Point(native_event->xbutton.x, native_event->xbutton.y);
    579     case MotionNotify:
    580       return gfx::Point(native_event->xmotion.x, native_event->xmotion.y);
    581     case GenericEvent: {
    582       XIDeviceEvent* xievent =
    583           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    584       float x = xievent->event_x;
    585       float y = xievent->event_y;
    586 #if defined(OS_CHROMEOS)
    587       switch (xievent->evtype) {
    588         case XI_TouchBegin:
    589         case XI_TouchUpdate:
    590         case XI_TouchEnd:
    591           ui::DeviceDataManagerX11::GetInstance()->ApplyTouchTransformer(
    592               xievent->deviceid, &x, &y);
    593           break;
    594         default:
    595           break;
    596       }
    597 #endif  // defined(OS_CHROMEOS)
    598       return gfx::Point(static_cast<int>(x), static_cast<int>(y));
    599     }
    600   }
    601   return gfx::Point();
    602 }
    603 
    604 gfx::Point EventSystemLocationFromNative(
    605     const base::NativeEvent& native_event) {
    606   switch (native_event->type) {
    607     case EnterNotify:
    608     case LeaveNotify: {
    609       return gfx::Point(native_event->xcrossing.x_root,
    610                         native_event->xcrossing.y_root);
    611     }
    612     case ButtonPress:
    613     case ButtonRelease: {
    614       return gfx::Point(native_event->xbutton.x_root,
    615                         native_event->xbutton.y_root);
    616     }
    617     case MotionNotify: {
    618       return gfx::Point(native_event->xmotion.x_root,
    619                         native_event->xmotion.y_root);
    620     }
    621     case GenericEvent: {
    622       XIDeviceEvent* xievent =
    623           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    624       return gfx::Point(xievent->root_x, xievent->root_y);
    625     }
    626   }
    627 
    628   return gfx::Point();
    629 }
    630 
    631 int EventButtonFromNative(const base::NativeEvent& native_event) {
    632   CHECK_EQ(GenericEvent, native_event->type);
    633   XIDeviceEvent* xievent =
    634       static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    635   int button = xievent->detail;
    636 
    637   return (xievent->sourceid == xievent->deviceid) ?
    638          DeviceDataManagerX11::GetInstance()->GetMappedButton(button) : button;
    639 }
    640 
    641 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
    642   return KeyboardCodeFromXKeyEvent(native_event);
    643 }
    644 
    645 const char* CodeFromNative(const base::NativeEvent& native_event) {
    646   return CodeFromXEvent(native_event);
    647 }
    648 
    649 uint32 PlatformKeycodeFromNative(const base::NativeEvent& native_event) {
    650   XKeyEvent* xkey = NULL;
    651   XEvent xkey_from_xi2;
    652   switch (native_event->type) {
    653     case KeyPress:
    654     case KeyRelease:
    655       xkey = &native_event->xkey;
    656       break;
    657     case GenericEvent: {
    658       XIDeviceEvent* xievent =
    659           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    660       switch (xievent->evtype) {
    661         case XI_KeyPress:
    662         case XI_KeyRelease:
    663           // Build an XKeyEvent corresponding to the XI2 event,
    664           // so that we can call XLookupString on it.
    665           InitXKeyEventFromXIDeviceEvent(*native_event, &xkey_from_xi2);
    666           xkey = &xkey_from_xi2.xkey;
    667           break;
    668         default:
    669           NOTREACHED();
    670           break;
    671       }
    672       break;
    673     }
    674     default:
    675       NOTREACHED();
    676       break;
    677   }
    678   KeySym keysym = XK_VoidSymbol;
    679   if (xkey)
    680     XLookupString(xkey, NULL, 0, &keysym, NULL);
    681   return keysym;
    682 }
    683 
    684 bool IsCharFromNative(const base::NativeEvent& native_event) {
    685   return false;
    686 }
    687 
    688 int GetChangedMouseButtonFlagsFromNative(
    689     const base::NativeEvent& native_event) {
    690   switch (native_event->type) {
    691     case ButtonPress:
    692     case ButtonRelease:
    693       return GetEventFlagsFromXState(native_event->xbutton.state);
    694     case GenericEvent: {
    695       XIDeviceEvent* xievent =
    696           static_cast<XIDeviceEvent*>(native_event->xcookie.data);
    697       switch (xievent->evtype) {
    698         case XI_ButtonPress:
    699         case XI_ButtonRelease:
    700           return GetEventFlagsForButton(EventButtonFromNative(native_event));
    701         default:
    702           break;
    703       }
    704     }
    705     default:
    706       break;
    707   }
    708   return 0;
    709 }
    710 
    711 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
    712   float x_offset, y_offset;
    713   if (GetScrollOffsets(
    714       native_event, &x_offset, &y_offset, NULL, NULL, NULL)) {
    715     return gfx::Vector2d(static_cast<int>(x_offset),
    716                          static_cast<int>(y_offset));
    717   }
    718 
    719   int button = native_event->type == GenericEvent ?
    720       EventButtonFromNative(native_event) : native_event->xbutton.button;
    721 
    722   switch (button) {
    723     case 4:
    724       return gfx::Vector2d(0, kWheelScrollAmount);
    725     case 5:
    726       return gfx::Vector2d(0, -kWheelScrollAmount);
    727     case 6:
    728       return gfx::Vector2d(kWheelScrollAmount, 0);
    729     case 7:
    730       return gfx::Vector2d(-kWheelScrollAmount, 0);
    731     default:
    732       return gfx::Vector2d();
    733   }
    734 }
    735 
    736 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
    737   if (!event || event->type == GenericEvent)
    738     return NULL;
    739   XEvent* copy = new XEvent;
    740   *copy = *event;
    741   return copy;
    742 }
    743 
    744 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
    745   delete event;
    746 }
    747 
    748 void IncrementTouchIdRefCount(const base::NativeEvent& xev) {
    749   ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
    750   double tracking_id;
    751   if (!manager->GetEventData(
    752           *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
    753     return;
    754   }
    755 
    756   ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    757   factory->AcquireSlotForTrackingID(tracking_id);
    758 }
    759 
    760 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
    761   ui::EventType type = ui::EventTypeFromNative(xev);
    762   if (type == ui::ET_TOUCH_CANCELLED ||
    763       type == ui::ET_TOUCH_RELEASED) {
    764     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    765     ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
    766     double tracking_id;
    767     if (manager->GetEventData(
    768         *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
    769       factory->ReleaseSlotForTrackingID(tracking_id);
    770     }
    771   }
    772 }
    773 
    774 int GetTouchId(const base::NativeEvent& xev) {
    775   double slot = 0;
    776   ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
    777   double tracking_id;
    778   if (!manager->GetEventData(
    779       *xev, ui::DeviceDataManagerX11::DT_TOUCH_TRACKING_ID, &tracking_id)) {
    780     LOG(ERROR) << "Could not get the tracking ID for the event. Using 0.";
    781   } else {
    782     ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
    783     slot = factory->GetSlotForTrackingID(tracking_id);
    784   }
    785   return slot;
    786 }
    787 
    788 float GetTouchRadiusX(const base::NativeEvent& native_event) {
    789   double radius = GetTouchParamFromXEvent(native_event,
    790       ui::DeviceDataManagerX11::DT_TOUCH_MAJOR, 0.0) / 2.0;
    791   ScaleTouchRadius(native_event, &radius);
    792   return radius;
    793 }
    794 
    795 float GetTouchRadiusY(const base::NativeEvent& native_event) {
    796   double radius = GetTouchParamFromXEvent(native_event,
    797       ui::DeviceDataManagerX11::DT_TOUCH_MINOR, 0.0) / 2.0;
    798   ScaleTouchRadius(native_event, &radius);
    799   return radius;
    800 }
    801 
    802 float GetTouchAngle(const base::NativeEvent& native_event) {
    803   return GetTouchParamFromXEvent(native_event,
    804       ui::DeviceDataManagerX11::DT_TOUCH_ORIENTATION, 0.0) / 2.0;
    805 }
    806 
    807 float GetTouchForce(const base::NativeEvent& native_event) {
    808   double force = 0.0;
    809   force = GetTouchParamFromXEvent(native_event,
    810       ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, 0.0);
    811   unsigned int deviceid =
    812       static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
    813   // Force is normalized to fall into [0, 1]
    814   if (!ui::DeviceDataManagerX11::GetInstance()->NormalizeData(
    815       deviceid, ui::DeviceDataManagerX11::DT_TOUCH_PRESSURE, &force))
    816     force = 0.0;
    817   return force;
    818 }
    819 
    820 bool GetScrollOffsets(const base::NativeEvent& native_event,
    821                       float* x_offset,
    822                       float* y_offset,
    823                       float* x_offset_ordinal,
    824                       float* y_offset_ordinal,
    825                       int* finger_count) {
    826   if (!DeviceDataManagerX11::GetInstance()->IsScrollEvent(native_event))
    827     return false;
    828 
    829   // Temp values to prevent passing NULLs to DeviceDataManager.
    830   float x_offset_, y_offset_;
    831   float x_offset_ordinal_, y_offset_ordinal_;
    832   int finger_count_;
    833   if (!x_offset)
    834     x_offset = &x_offset_;
    835   if (!y_offset)
    836     y_offset = &y_offset_;
    837   if (!x_offset_ordinal)
    838     x_offset_ordinal = &x_offset_ordinal_;
    839   if (!y_offset_ordinal)
    840     y_offset_ordinal = &y_offset_ordinal_;
    841   if (!finger_count)
    842     finger_count = &finger_count_;
    843 
    844   DeviceDataManagerX11::GetInstance()->GetScrollOffsets(
    845       native_event,
    846       x_offset, y_offset,
    847       x_offset_ordinal, y_offset_ordinal,
    848       finger_count);
    849   return true;
    850 }
    851 
    852 bool GetFlingData(const base::NativeEvent& native_event,
    853                   float* vx,
    854                   float* vy,
    855                   float* vx_ordinal,
    856                   float* vy_ordinal,
    857                   bool* is_cancel) {
    858   if (!DeviceDataManagerX11::GetInstance()->IsFlingEvent(native_event))
    859     return false;
    860 
    861   float vx_, vy_;
    862   float vx_ordinal_, vy_ordinal_;
    863   bool is_cancel_;
    864   if (!vx)
    865     vx = &vx_;
    866   if (!vy)
    867     vy = &vy_;
    868   if (!vx_ordinal)
    869     vx_ordinal = &vx_ordinal_;
    870   if (!vy_ordinal)
    871     vy_ordinal = &vy_ordinal_;
    872   if (!is_cancel)
    873     is_cancel = &is_cancel_;
    874 
    875   DeviceDataManagerX11::GetInstance()->GetFlingData(
    876       native_event, vx, vy, vx_ordinal, vy_ordinal, is_cancel);
    877   return true;
    878 }
    879 
    880 void UpdateX11EventForFlags(Event* event) {
    881   XEvent* xev = event->native_event();
    882   if (!xev)
    883     return;
    884   switch (xev->type) {
    885     case KeyPress:
    886     case KeyRelease:
    887       xev->xkey.state = UpdateX11EventFlags(event->flags(), xev->xkey.state);
    888       break;
    889     case ButtonPress:
    890     case ButtonRelease:
    891       xev->xbutton.state =
    892           UpdateX11EventFlags(event->flags(), xev->xbutton.state);
    893       break;
    894     case GenericEvent: {
    895       XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
    896       DCHECK(xievent);
    897       xievent->mods.effective =
    898           UpdateX11EventFlags(event->flags(), xievent->mods.effective);
    899       break;
    900     }
    901     default:
    902       break;
    903   }
    904 }
    905 
    906 void UpdateX11EventForChangedButtonFlags(MouseEvent* event) {
    907   XEvent* xev = event->native_event();
    908   if (!xev)
    909     return;
    910   switch (xev->type) {
    911     case ButtonPress:
    912     case ButtonRelease:
    913       xev->xbutton.button = UpdateX11EventButton(event->changed_button_flags(),
    914                                                  xev->xbutton.button);
    915       break;
    916     case GenericEvent: {
    917       XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
    918       CHECK(xievent && (xievent->evtype == XI_ButtonPress ||
    919                         xievent->evtype == XI_ButtonRelease));
    920       xievent->detail =
    921           UpdateX11EventButton(event->changed_button_flags(), xievent->detail);
    922       break;
    923     }
    924     default:
    925       break;
    926   }
    927 }
    928 
    929 }  // namespace ui
    930