OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/events/event_constants.h" | 5 #include "ui/events/event_constants.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <string.h> | 8 #include <string.h> |
9 #include <X11/extensions/XInput.h> | 9 #include <X11/extensions/XInput.h> |
10 #include <X11/extensions/XInput2.h> | 10 #include <X11/extensions/XInput2.h> |
11 #include <X11/Xlib.h> | 11 #include <X11/Xlib.h> |
12 #include <X11/Xutil.h> | 12 #include <X11/Xutil.h> |
| 13 #include <X11/XKBlib.h> |
13 | 14 |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/memory/singleton.h" | 16 #include "base/memory/singleton.h" |
16 #include "ui/events/event_utils.h" | 17 #include "ui/events/event_utils.h" |
17 #include "ui/events/keycodes/keyboard_code_conversion_x.h" | 18 #include "ui/events/keycodes/keyboard_code_conversion_x.h" |
18 #include "ui/events/x/device_data_manager_x11.h" | 19 #include "ui/events/x/device_data_manager_x11.h" |
19 #include "ui/events/x/device_list_cache_x.h" | 20 #include "ui/events/x/device_list_cache_x.h" |
20 #include "ui/events/x/touch_factory_x11.h" | 21 #include "ui/events/x/touch_factory_x11.h" |
21 #include "ui/gfx/display.h" | 22 #include "ui/gfx/display.h" |
22 #include "ui/gfx/point.h" | 23 #include "ui/gfx/point.h" |
(...skipping 12 matching lines...) Expand all Loading... |
35 | 36 |
36 // A class to track current modifier state on master device. Only track ctrl, | 37 // 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 // alt, shift and caps lock keys currently. The tracked state can then be used |
38 // by floating device. | 39 // by floating device. |
39 class XModifierStateWatcher{ | 40 class XModifierStateWatcher{ |
40 public: | 41 public: |
41 static XModifierStateWatcher* GetInstance() { | 42 static XModifierStateWatcher* GetInstance() { |
42 return Singleton<XModifierStateWatcher>::get(); | 43 return Singleton<XModifierStateWatcher>::get(); |
43 } | 44 } |
44 | 45 |
45 void UpdateStateFromEvent(const base::NativeEvent& native_event) { | 46 int StateFromKeyboardCode(ui::KeyboardCode keyboard_code) { |
| 47 switch (keyboard_code) { |
| 48 case ui::VKEY_CONTROL: |
| 49 return ControlMask; |
| 50 case ui::VKEY_SHIFT: |
| 51 return ShiftMask; |
| 52 case ui::VKEY_MENU: |
| 53 return Mod1Mask; |
| 54 case ui::VKEY_CAPITAL: |
| 55 return LockMask; |
| 56 default: |
| 57 return 0; |
| 58 } |
| 59 } |
| 60 |
| 61 void UpdateStateFromXEvent(const base::NativeEvent& native_event) { |
| 62 ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event); |
| 63 unsigned int mask = StateFromKeyboardCode(keyboard_code); |
46 // Floating device can't access the modifer state from master device. | 64 // 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 | 65 // 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 | 66 // floating devices such as touch screen. Issue 106426 is one example |
49 // of why we need the modifier states for floating device. | 67 // of why we need the modifier states for floating device. |
50 state_ = native_event->xkey.state; | 68 switch (native_event->type) { |
51 // master_state is the state before key press. We need to track the | 69 case KeyPress: |
52 // state after key press for floating device. Currently only ctrl, | 70 state_ = native_event->xkey.state | mask; |
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; | 71 break; |
61 } | 72 case KeyRelease: |
62 case ui::VKEY_SHIFT: { | 73 state_ = native_event->xkey.state & ~mask; |
63 mask = ShiftMask; | |
64 break; | 74 break; |
65 } | 75 case GenericEvent: { |
66 case ui::VKEY_MENU: { | 76 XIDeviceEvent* xievent = |
67 mask = Mod1Mask; | 77 static_cast<XIDeviceEvent*>(native_event->xcookie.data); |
68 break; | 78 switch (xievent->evtype) { |
69 } | 79 case XI_KeyPress: |
70 case ui::VKEY_CAPITAL: { | 80 state_ = xievent->mods.effective |= mask; |
71 mask = LockMask; | 81 break; |
| 82 case XI_KeyRelease: |
| 83 state_ = xievent->mods.effective &= ~mask; |
| 84 break; |
| 85 default: |
| 86 NOTREACHED(); |
| 87 break; |
| 88 } |
72 break; | 89 break; |
73 } | 90 } |
74 default: | 91 default: |
| 92 NOTREACHED(); |
75 break; | 93 break; |
76 } | 94 } |
77 | |
78 if (native_event->type == KeyPress) | |
79 state_ |= mask; | |
80 else | |
81 state_ &= ~mask; | |
82 } | 95 } |
83 | 96 |
84 // Returns the current modifer state in master device. It only contains the | 97 // Returns the current modifer state in master device. It only contains the |
85 // state of ctrl, shift, alt and caps lock keys. | 98 // state of ctrl, shift, alt and caps lock keys. |
86 unsigned int state() { return state_; } | 99 unsigned int state() { return state_; } |
87 | 100 |
88 private: | 101 private: |
89 friend struct DefaultSingletonTraits<XModifierStateWatcher>; | 102 friend struct DefaultSingletonTraits<XModifierStateWatcher>; |
90 | 103 |
91 XModifierStateWatcher() : state_(0) { } | 104 XModifierStateWatcher() : state_(0) { } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0; | 188 fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0; |
176 #endif | 189 #endif |
177 | 190 |
178 return GetEventFlagsFromXState(xevent->xkey.state) | | 191 return GetEventFlagsFromXState(xevent->xkey.state) | |
179 (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) | | 192 (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) | |
180 (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ? | 193 (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ? |
181 ui::EF_FUNCTION_KEY : 0) | | 194 ui::EF_FUNCTION_KEY : 0) | |
182 ime_fabricated_flag; | 195 ime_fabricated_flag; |
183 } | 196 } |
184 | 197 |
| 198 int GetEventFlagsFromXGenericEvent(XEvent* xevent) { |
| 199 DCHECK(xevent->type == GenericEvent); |
| 200 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); |
| 201 DCHECK((xievent->evtype == XI_KeyPress) || |
| 202 (xievent->evtype == XI_KeyRelease)); |
| 203 return GetEventFlagsFromXState(xievent->mods.effective) | |
| 204 (IsKeypadKey( |
| 205 XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0)) |
| 206 ? ui::EF_NUMPAD_KEY |
| 207 : 0); |
| 208 } |
| 209 |
185 // Get the event flag for the button in XButtonEvent. During a ButtonPress | 210 // 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 | 211 // 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 | 212 // 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 | 213 // 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 | 214 // 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 | 215 // 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| | 216 // event, |state| would have Button1Mask set but not Button3Mask, and |button| |
192 // would be 3. | 217 // would be 3. |
193 int GetEventFlagsForButton(int button) { | 218 int GetEventFlagsForButton(int button) { |
194 switch (button) { | 219 switch (button) { |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) { | 372 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) { |
348 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START; | 373 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START; |
349 } else if (DeviceDataManagerX11::GetInstance()->IsScrollEvent( | 374 } else if (DeviceDataManagerX11::GetInstance()->IsScrollEvent( |
350 native_event)) { | 375 native_event)) { |
351 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL; | 376 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL; |
352 } else if (DeviceDataManagerX11::GetInstance()->IsCMTMetricsEvent( | 377 } else if (DeviceDataManagerX11::GetInstance()->IsCMTMetricsEvent( |
353 native_event)) { | 378 native_event)) { |
354 return ET_UMA_DATA; | 379 return ET_UMA_DATA; |
355 } else if (GetButtonMaskForX2Event(xievent)) { | 380 } else if (GetButtonMaskForX2Event(xievent)) { |
356 return ET_MOUSE_DRAGGED; | 381 return ET_MOUSE_DRAGGED; |
357 } else { | |
358 return ET_MOUSE_MOVED; | |
359 } | 382 } |
| 383 return ET_MOUSE_MOVED; |
360 } | 384 } |
| 385 case XI_KeyPress: |
| 386 return ET_KEY_PRESSED; |
| 387 case XI_KeyRelease: |
| 388 return ET_KEY_RELEASED; |
361 } | 389 } |
362 } | 390 } |
363 default: | 391 default: |
364 break; | 392 break; |
365 } | 393 } |
366 return ET_UNKNOWN; | 394 return ET_UNKNOWN; |
367 } | 395 } |
368 | 396 |
369 int EventFlagsFromNative(const base::NativeEvent& native_event) { | 397 int EventFlagsFromNative(const base::NativeEvent& native_event) { |
370 switch (native_event->type) { | 398 switch (native_event->type) { |
371 case KeyPress: | 399 case KeyPress: |
372 case KeyRelease: { | 400 case KeyRelease: { |
373 XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event); | 401 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event); |
374 return GetEventFlagsFromXKeyEvent(native_event); | 402 return GetEventFlagsFromXKeyEvent(native_event); |
375 } | 403 } |
376 case ButtonPress: | 404 case ButtonPress: |
377 case ButtonRelease: { | 405 case ButtonRelease: { |
378 int flags = GetEventFlagsFromXState(native_event->xbutton.state); | 406 int flags = GetEventFlagsFromXState(native_event->xbutton.state); |
379 const EventType type = EventTypeFromNative(native_event); | 407 const EventType type = EventTypeFromNative(native_event); |
380 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) | 408 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) |
381 flags |= GetEventFlagsForButton(native_event->xbutton.button); | 409 flags |= GetEventFlagsForButton(native_event->xbutton.button); |
382 return flags; | 410 return flags; |
383 } | 411 } |
(...skipping 15 matching lines...) Expand all Loading... |
399 GetEventFlagsFromXState(xievent->mods.effective) | | 427 GetEventFlagsFromXState(xievent->mods.effective) | |
400 GetEventFlagsFromXState( | 428 GetEventFlagsFromXState( |
401 XModifierStateWatcher::GetInstance()->state()); | 429 XModifierStateWatcher::GetInstance()->state()); |
402 break; | 430 break; |
403 #endif | 431 #endif |
404 case XI_ButtonPress: | 432 case XI_ButtonPress: |
405 case XI_ButtonRelease: { | 433 case XI_ButtonRelease: { |
406 const bool touch = | 434 const bool touch = |
407 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid); | 435 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid); |
408 int flags = GetButtonMaskForX2Event(xievent) | | 436 int flags = GetButtonMaskForX2Event(xievent) | |
409 GetEventFlagsFromXState(xievent->mods.effective); | 437 GetEventFlagsFromXState(xievent->mods.effective); |
410 if (touch) { | 438 if (touch) { |
411 flags |= GetEventFlagsFromXState( | 439 flags |= GetEventFlagsFromXState( |
412 XModifierStateWatcher::GetInstance()->state()); | 440 XModifierStateWatcher::GetInstance()->state()); |
413 } | 441 } |
414 | 442 |
415 const EventType type = EventTypeFromNative(native_event); | 443 const EventType type = EventTypeFromNative(native_event); |
416 int button = EventButtonFromNative(native_event); | 444 int button = EventButtonFromNative(native_event); |
417 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch) | 445 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch) |
418 flags |= GetEventFlagsForButton(button); | 446 flags |= GetEventFlagsForButton(button); |
419 return flags; | 447 return flags; |
420 } | 448 } |
421 case XI_Motion: | 449 case XI_Motion: |
422 return GetButtonMaskForX2Event(xievent) | | 450 return GetButtonMaskForX2Event(xievent) | |
423 GetEventFlagsFromXState(xievent->mods.effective); | 451 GetEventFlagsFromXState(xievent->mods.effective); |
| 452 case XI_KeyPress: |
| 453 case XI_KeyRelease: { |
| 454 XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent( |
| 455 native_event); |
| 456 return GetEventFlagsFromXGenericEvent(native_event); |
| 457 } |
424 } | 458 } |
425 } | 459 } |
426 } | 460 } |
427 return 0; | 461 return 0; |
428 } | 462 } |
429 | 463 |
430 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { | 464 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { |
431 switch(native_event->type) { | 465 switch(native_event->type) { |
432 case KeyPress: | 466 case KeyPress: |
433 case KeyRelease: | 467 case KeyRelease: |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
741 DeviceDataManagerX11::GetInstance()->GetGestureTimes( | 775 DeviceDataManagerX11::GetInstance()->GetGestureTimes( |
742 native_event, start_time, end_time); | 776 native_event, start_time, end_time); |
743 return true; | 777 return true; |
744 } | 778 } |
745 | 779 |
746 bool IsTouchpadEvent(const base::NativeEvent& event) { | 780 bool IsTouchpadEvent(const base::NativeEvent& event) { |
747 return DeviceDataManagerX11::GetInstance()->IsTouchpadXInputEvent(event); | 781 return DeviceDataManagerX11::GetInstance()->IsTouchpadXInputEvent(event); |
748 } | 782 } |
749 | 783 |
750 } // namespace ui | 784 } // namespace ui |
OLD | NEW |