OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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/base/events.h" |
| 6 |
| 7 #include <X11/extensions/XInput2.h> |
| 8 |
| 9 #include "base/logging.h" |
| 10 #include "ui/base/keycodes/keyboard_code_conversion_x.h" |
| 11 #include "ui/base/touch/touch_factory.h" |
| 12 #include "ui/gfx/point.h" |
| 13 |
| 14 namespace { |
| 15 |
| 16 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+. |
| 17 static int kWheelScrollAmount = 53; |
| 18 |
| 19 int GetEventFlagsFromXState(unsigned int state) { |
| 20 int flags = 0; |
| 21 if (state & ControlMask) |
| 22 flags |= ui::EF_CONTROL_DOWN; |
| 23 if (state & ShiftMask) |
| 24 flags |= ui::EF_SHIFT_DOWN; |
| 25 if (state & Mod1Mask) |
| 26 flags |= ui::EF_ALT_DOWN; |
| 27 if (state & LockMask) |
| 28 flags |= ui::EF_CAPS_LOCK_DOWN; |
| 29 if (state & Button1Mask) |
| 30 flags |= ui::EF_LEFT_BUTTON_DOWN; |
| 31 if (state & Button2Mask) |
| 32 flags |= ui::EF_MIDDLE_BUTTON_DOWN; |
| 33 if (state & Button3Mask) |
| 34 flags |= ui::EF_RIGHT_BUTTON_DOWN; |
| 35 return flags; |
| 36 } |
| 37 |
| 38 // Get the event flag for the button in XButtonEvent. During a ButtonPress |
| 39 // event, |state| in XButtonEvent does not include the button that has just been |
| 40 // pressed. Instead |state| contains flags for the buttons (if any) that had |
| 41 // already been pressed before the current button, and |button| stores the most |
| 42 // current pressed button. So, if you press down left mouse button, and while |
| 43 // pressing it down, press down the right mouse button, then for the latter |
| 44 // event, |state| would have Button1Mask set but not Button3Mask, and |button| |
| 45 // would be 3. |
| 46 int GetEventFlagsForButton(int button) { |
| 47 switch (button) { |
| 48 case 1: |
| 49 return ui::EF_LEFT_BUTTON_DOWN; |
| 50 case 2: |
| 51 return ui::EF_MIDDLE_BUTTON_DOWN; |
| 52 case 3: |
| 53 return ui::EF_RIGHT_BUTTON_DOWN; |
| 54 } |
| 55 DLOG(WARNING) << "Unexpected button (" << button << ") received."; |
| 56 return 0; |
| 57 } |
| 58 |
| 59 int GetButtonMaskForX2Event(XIDeviceEvent* xievent) { |
| 60 int buttonflags = 0; |
| 61 for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) { |
| 62 if (XIMaskIsSet(xievent->buttons.mask, i)) { |
| 63 buttonflags |= GetEventFlagsForButton(i); |
| 64 } |
| 65 } |
| 66 return buttonflags; |
| 67 } |
| 68 |
| 69 ui::EventType GetTouchEventType(const ui::NativeEvent& native_event) { |
| 70 #if defined(USE_XI2_MT) |
| 71 XIEvent* event = static_cast<XIEvent*>(native_event->xcookie.data); |
| 72 switch(event->evtype) { |
| 73 case XI_TouchBegin: |
| 74 return ui::ET_TOUCH_PRESSED; |
| 75 case XI_TouchUpdate: |
| 76 return ui::ET_TOUCH_MOVED; |
| 77 case XI_TouchEnd: |
| 78 return ui::ET_TOUCH_RELEASED; |
| 79 } |
| 80 |
| 81 return ui::ET_UNKNOWN; |
| 82 #else |
| 83 XGenericEventCookie* cookie = &native_event->xcookie; |
| 84 DCHECK_EQ(cookie->evtype, XI_Motion); |
| 85 |
| 86 // Note: We will not generate a _STATIONARY event here. It will be created, |
| 87 // when necessary, by a RWHVV. |
| 88 // TODO(sad): When should _CANCELLED be generated? |
| 89 |
| 90 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); |
| 91 float slot; |
| 92 if (!factory->ExtractTouchParam(*native_event, ui::TouchFactory::TP_SLOT_ID, |
| 93 &slot)) |
| 94 return ui::ET_UNKNOWN; |
| 95 |
| 96 if (!factory->IsSlotUsed(slot)) { |
| 97 // This is a new touch point. |
| 98 return ui::ET_TOUCH_PRESSED; |
| 99 } |
| 100 |
| 101 float tracking; |
| 102 if (!factory->ExtractTouchParam(*native_event, |
| 103 ui::TouchFactory::TP_TRACKING_ID, &tracking)) |
| 104 return ui::ET_UNKNOWN; |
| 105 |
| 106 if (tracking == 0l) { |
| 107 // The touch point has been released. |
| 108 return ui::ET_TOUCH_RELEASED; |
| 109 } |
| 110 |
| 111 return ui::ET_TOUCH_MOVED; |
| 112 #endif // defined(USE_XI2_MT) |
| 113 } |
| 114 |
| 115 } // namespace |
| 116 |
| 117 namespace ui { |
| 118 |
| 119 EventType EventTypeFromNative(const NativeEvent& native_event) { |
| 120 switch (native_event->type) { |
| 121 case KeyPress: |
| 122 return ET_KEY_PRESSED; |
| 123 case KeyRelease: |
| 124 return ET_KEY_RELEASED; |
| 125 case ButtonPress: |
| 126 if (native_event->xbutton.button == 4 || |
| 127 native_event->xbutton.button == 5) |
| 128 return ET_MOUSEWHEEL; |
| 129 return ET_MOUSE_PRESSED; |
| 130 case ButtonRelease: |
| 131 if (native_event->xbutton.button == 4 || |
| 132 native_event->xbutton.button == 5) |
| 133 return ET_MOUSEWHEEL; |
| 134 return ET_MOUSE_RELEASED; |
| 135 case MotionNotify: |
| 136 if (native_event->xmotion.state & |
| 137 (Button1Mask | Button2Mask | Button3Mask)) |
| 138 return ET_MOUSE_DRAGGED; |
| 139 return ET_MOUSE_MOVED; |
| 140 case GenericEvent: { |
| 141 XIDeviceEvent* xievent = |
| 142 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
| 143 if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid)) |
| 144 return GetTouchEventType(native_event); |
| 145 switch (xievent->evtype) { |
| 146 case XI_ButtonPress: |
| 147 return (xievent->detail == 4 || xievent->detail == 5) ? |
| 148 ET_MOUSEWHEEL : ET_MOUSE_PRESSED; |
| 149 case XI_ButtonRelease: |
| 150 return (xievent->detail == 4 || xievent->detail == 5) ? |
| 151 ET_MOUSEWHEEL : ET_MOUSE_RELEASED; |
| 152 case XI_Motion: |
| 153 return GetButtonMaskForX2Event(xievent) ? |
| 154 ET_MOUSE_DRAGGED : ET_MOUSE_MOVED; |
| 155 } |
| 156 } |
| 157 default: |
| 158 NOTREACHED(); |
| 159 break; |
| 160 } |
| 161 return ET_UNKNOWN; |
| 162 } |
| 163 |
| 164 int EventFlagsFromNative(const NativeEvent& native_event) { |
| 165 switch (native_event->type) { |
| 166 case KeyPress: |
| 167 case KeyRelease: |
| 168 return GetEventFlagsFromXState(native_event->xbutton.state); |
| 169 case ButtonPress: |
| 170 case ButtonRelease: |
| 171 return GetEventFlagsFromXState(native_event->xbutton.state) | |
| 172 GetEventFlagsForButton(native_event->xbutton.button); |
| 173 case MotionNotify: |
| 174 return GetEventFlagsFromXState(native_event->xmotion.state); |
| 175 case GenericEvent: { |
| 176 XIDeviceEvent* xievent = |
| 177 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
| 178 bool touch = |
| 179 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid); |
| 180 switch (xievent->evtype) { |
| 181 case XI_ButtonPress: |
| 182 case XI_ButtonRelease: |
| 183 return GetButtonMaskForX2Event(xievent) | |
| 184 GetEventFlagsFromXState(xievent->mods.effective) | |
| 185 (touch ? 0 : GetEventFlagsForButton(xievent->detail)); |
| 186 case XI_Motion: |
| 187 return GetButtonMaskForX2Event(xievent) | |
| 188 GetEventFlagsFromXState(xievent->mods.effective); |
| 189 } |
| 190 } |
| 191 } |
| 192 return 0; |
| 193 } |
| 194 |
| 195 gfx::Point EventLocationFromNative(const NativeEvent& native_event) { |
| 196 switch (native_event->type) { |
| 197 case ButtonPress: |
| 198 case ButtonRelease: |
| 199 return gfx::Point(native_event->xbutton.x, native_event->xbutton.y); |
| 200 case MotionNotify: |
| 201 return gfx::Point(native_event->xmotion.x, native_event->xmotion.y); |
| 202 case GenericEvent: { |
| 203 XIDeviceEvent* xievent = |
| 204 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
| 205 return gfx::Point(static_cast<int>(xievent->event_x), |
| 206 static_cast<int>(xievent->event_y)); |
| 207 } |
| 208 } |
| 209 return gfx::Point(); |
| 210 } |
| 211 |
| 212 KeyboardCode KeyboardCodeFromNative(const NativeEvent& native_event) { |
| 213 return KeyboardCodeFromXKeyEvent(native_event); |
| 214 } |
| 215 |
| 216 bool IsMouseEvent(const NativeEvent& native_event) { |
| 217 if (native_event->type == ButtonPress || |
| 218 native_event->type == ButtonRelease || |
| 219 native_event->type == MotionNotify) |
| 220 return true; |
| 221 if (native_event->type == GenericEvent) { |
| 222 XIDeviceEvent* xievent = |
| 223 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
| 224 return xievent->evtype == XI_ButtonPress || |
| 225 xievent->evtype == XI_ButtonRelease || |
| 226 xievent->evtype == XI_Motion; |
| 227 } |
| 228 return false; |
| 229 } |
| 230 |
| 231 int GetMouseWheelOffset(const NativeEvent& native_event) { |
| 232 if (native_event->type == GenericEvent) { |
| 233 XIDeviceEvent* xiev = |
| 234 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
| 235 return xiev->detail == 4 ? kWheelScrollAmount : -kWheelScrollAmount; |
| 236 } |
| 237 return native_event->xbutton.button == 4 ? |
| 238 kWheelScrollAmount : -kWheelScrollAmount; |
| 239 } |
| 240 |
| 241 } // namespace ui |
OLD | NEW |