Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: ui/events/x/events_x.cc

Issue 336403005: Use XInput2 events for keyboard events. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments (derat), the sequel. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 UpdateStateFromXKeyEvent(const base::NativeEvent& native_event) {
62 DCHECK((native_event->type == KeyPress) ||
63 (native_event->type == KeyRelease));
sadrul 2014/06/26 12:34:20 I suspect this will need to change once you make t
kpschoedel 2014/06/26 17:24:10 XI2 handling uses UpdateStateFromXGenericEvent; th
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 state_ = native_event->xkey.state;
51 // master_state is the state before key press. We need to track the 69 // master_state is the state before key press. We need to track the
52 // state after key press for floating device. Currently only ctrl, 70 // state after key press for floating device. Currently only ctrl,
53 // shift, alt and caps lock keys are tracked. 71 // shift, alt and caps lock keys are tracked.
54 ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event); 72 ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
55 unsigned int mask = 0; 73 unsigned int mask = StateFromKeyboardCode(keyboard_code);
74 if (native_event->type == KeyPress)
75 state_ |= mask;
76 else
77 state_ &= ~mask;
78 }
56 79
57 switch (keyboard_code) { 80 void UpdateStateFromXGenericEvent(const base::NativeEvent& native_event) {
58 case ui::VKEY_CONTROL: { 81 DCHECK(native_event->type == GenericEvent);
59 mask = ControlMask; 82 XIDeviceEvent* xievent =
60 break; 83 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
61 } 84 DCHECK((xievent->evtype == XI_KeyPress) ||
62 case ui::VKEY_SHIFT: { 85 (xievent->evtype == XI_KeyRelease));
63 mask = ShiftMask; 86 // Floating device can't access the modifer state from master device.
64 break; 87 // We need to track the states of modifier keys in a singleton for
65 } 88 // floating devices such as touch screen. Issue 106426 is one example
66 case ui::VKEY_MENU: { 89 // of why we need the modifier states for floating device.
67 mask = Mod1Mask; 90 state_ = xievent->mods.effective;
68 break; 91 // master_state is the state before key press. We need to track the
69 } 92 // state after key press for floating device. Currently only ctrl,
70 case ui::VKEY_CAPITAL: { 93 // shift, alt and caps lock keys are tracked.
71 mask = LockMask; 94 ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
72 break; 95 unsigned int mask = StateFromKeyboardCode(keyboard_code);
73 } 96 if (native_event->type == XI_KeyPress)
74 default:
75 break;
76 }
77
78 if (native_event->type == KeyPress)
79 state_ |= mask; 97 state_ |= mask;
80 else 98 else
81 state_ &= ~mask; 99 state_ &= ~mask;
82 } 100 }
83 101
84 // Returns the current modifer state in master device. It only contains the 102 // Returns the current modifer state in master device. It only contains the
85 // state of ctrl, shift, alt and caps lock keys. 103 // state of ctrl, shift, alt and caps lock keys.
86 unsigned int state() { return state_; } 104 unsigned int state() { return state_; }
87 105
88 private: 106 private:
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0; 193 fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0;
176 #endif 194 #endif
177 195
178 return GetEventFlagsFromXState(xevent->xkey.state) | 196 return GetEventFlagsFromXState(xevent->xkey.state) |
179 (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) | 197 (IsKeypadKey(XLookupKeysym(&xevent->xkey, 0)) ? ui::EF_NUMPAD_KEY : 0) |
180 (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ? 198 (IsFunctionKey(XLookupKeysym(&xevent->xkey, 0)) ?
181 ui::EF_FUNCTION_KEY : 0) | 199 ui::EF_FUNCTION_KEY : 0) |
182 ime_fabricated_flag; 200 ime_fabricated_flag;
183 } 201 }
184 202
203 int GetEventFlagsFromXGenericEvent(XEvent* xevent) {
204 DCHECK(xevent->type == GenericEvent);
205 XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
206 DCHECK((xievent->evtype == XI_KeyPress) ||
207 (xievent->evtype == XI_KeyRelease));
208 return GetEventFlagsFromXState(xievent->mods.effective) |
209 (IsKeypadKey(
210 XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0))
211 ? ui::EF_NUMPAD_KEY
212 : 0);
213 }
214
185 // Get the event flag for the button in XButtonEvent. During a ButtonPress 215 // 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 216 // 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 217 // 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 218 // 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 219 // 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 220 // 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| 221 // event, |state| would have Button1Mask set but not Button3Mask, and |button|
192 // would be 3. 222 // would be 3.
193 int GetEventFlagsForButton(int button) { 223 int GetEventFlagsForButton(int button) {
194 switch (button) { 224 switch (button) {
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL; 372 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
343 } else if (DeviceDataManagerX11::GetInstance()->IsCMTMetricsEvent( 373 } else if (DeviceDataManagerX11::GetInstance()->IsCMTMetricsEvent(
344 native_event)) { 374 native_event)) {
345 return ET_UMA_DATA; 375 return ET_UMA_DATA;
346 } else if (GetButtonMaskForX2Event(xievent)) { 376 } else if (GetButtonMaskForX2Event(xievent)) {
347 return ET_MOUSE_DRAGGED; 377 return ET_MOUSE_DRAGGED;
348 } else { 378 } else {
349 return ET_MOUSE_MOVED; 379 return ET_MOUSE_MOVED;
350 } 380 }
351 } 381 }
382 case XI_KeyPress:
383 return ET_KEY_PRESSED;
384 case XI_KeyRelease:
385 return ET_KEY_RELEASED;
352 } 386 }
353 } 387 }
354 default: 388 default:
355 break; 389 break;
356 } 390 }
357 return ET_UNKNOWN; 391 return ET_UNKNOWN;
358 } 392 }
359 393
360 int EventFlagsFromNative(const base::NativeEvent& native_event) { 394 int EventFlagsFromNative(const base::NativeEvent& native_event) {
361 switch (native_event->type) { 395 switch (native_event->type) {
362 case KeyPress: 396 case KeyPress:
363 case KeyRelease: { 397 case KeyRelease: {
364 XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event); 398 XModifierStateWatcher::GetInstance()->UpdateStateFromXKeyEvent(
399 native_event);
365 return GetEventFlagsFromXKeyEvent(native_event); 400 return GetEventFlagsFromXKeyEvent(native_event);
366 } 401 }
367 case ButtonPress: 402 case ButtonPress:
368 case ButtonRelease: { 403 case ButtonRelease: {
369 int flags = GetEventFlagsFromXState(native_event->xbutton.state); 404 int flags = GetEventFlagsFromXState(native_event->xbutton.state);
370 const EventType type = EventTypeFromNative(native_event); 405 const EventType type = EventTypeFromNative(native_event);
371 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) 406 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
372 flags |= GetEventFlagsForButton(native_event->xbutton.button); 407 flags |= GetEventFlagsForButton(native_event->xbutton.button);
373 return flags; 408 return flags;
374 } 409 }
(...skipping 15 matching lines...) Expand all
390 GetEventFlagsFromXState(xievent->mods.effective) | 425 GetEventFlagsFromXState(xievent->mods.effective) |
391 GetEventFlagsFromXState( 426 GetEventFlagsFromXState(
392 XModifierStateWatcher::GetInstance()->state()); 427 XModifierStateWatcher::GetInstance()->state());
393 break; 428 break;
394 #endif 429 #endif
395 case XI_ButtonPress: 430 case XI_ButtonPress:
396 case XI_ButtonRelease: { 431 case XI_ButtonRelease: {
397 const bool touch = 432 const bool touch =
398 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid); 433 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
399 int flags = GetButtonMaskForX2Event(xievent) | 434 int flags = GetButtonMaskForX2Event(xievent) |
400 GetEventFlagsFromXState(xievent->mods.effective); 435 GetEventFlagsFromXState(xievent->mods.effective);
401 if (touch) { 436 if (touch) {
402 flags |= GetEventFlagsFromXState( 437 flags |= GetEventFlagsFromXState(
403 XModifierStateWatcher::GetInstance()->state()); 438 XModifierStateWatcher::GetInstance()->state());
404 } 439 }
405 440
406 const EventType type = EventTypeFromNative(native_event); 441 const EventType type = EventTypeFromNative(native_event);
407 int button = EventButtonFromNative(native_event); 442 int button = EventButtonFromNative(native_event);
408 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch) 443 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
409 flags |= GetEventFlagsForButton(button); 444 flags |= GetEventFlagsForButton(button);
410 return flags; 445 return flags;
411 } 446 }
412 case XI_Motion: 447 case XI_Motion:
413 return GetButtonMaskForX2Event(xievent) | 448 return GetButtonMaskForX2Event(xievent) |
414 GetEventFlagsFromXState(xievent->mods.effective); 449 GetEventFlagsFromXState(xievent->mods.effective);
450 case XI_KeyPress:
451 case XI_KeyRelease: {
452 XModifierStateWatcher::GetInstance()->UpdateStateFromXGenericEvent(
453 native_event);
454 return GetEventFlagsFromXGenericEvent(native_event);
455 }
415 } 456 }
416 } 457 }
417 } 458 }
418 return 0; 459 return 0;
419 } 460 }
420 461
421 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { 462 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
422 switch(native_event->type) { 463 switch(native_event->type) {
423 case KeyPress: 464 case KeyPress:
424 case KeyRelease: 465 case KeyRelease:
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 case 6: 624 case 6:
584 return gfx::Vector2d(kWheelScrollAmount, 0); 625 return gfx::Vector2d(kWheelScrollAmount, 0);
585 case 7: 626 case 7:
586 return gfx::Vector2d(-kWheelScrollAmount, 0); 627 return gfx::Vector2d(-kWheelScrollAmount, 0);
587 default: 628 default:
588 return gfx::Vector2d(); 629 return gfx::Vector2d();
589 } 630 }
590 } 631 }
591 632
592 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) { 633 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
593 if (!event || event->type == GenericEvent) 634 if (!event)
594 return NULL; 635 return NULL;
595 XEvent* copy = new XEvent; 636 XEvent* copy = new XEvent;
596 *copy = *event; 637 *copy = *event;
638 if (event->type == GenericEvent) {
639 XIDeviceEvent* xievent_copy = new XIDeviceEvent;
640 *xievent_copy = *static_cast<XIDeviceEvent*>(event->xcookie.data);
641 copy->xcookie.data = xievent_copy;
642 }
597 return copy; 643 return copy;
598 } 644 }
599 645
600 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) { 646 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
647 if (event && event->type == GenericEvent)
648 delete static_cast<XIDeviceEvent*>(event->xcookie.data);
601 delete event; 649 delete event;
602 } 650 }
603 651
604 void ClearTouchIdIfReleased(const base::NativeEvent& xev) { 652 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
605 ui::EventType type = ui::EventTypeFromNative(xev); 653 ui::EventType type = ui::EventTypeFromNative(xev);
606 if (type == ui::ET_TOUCH_CANCELLED || 654 if (type == ui::ET_TOUCH_CANCELLED ||
607 type == ui::ET_TOUCH_RELEASED) { 655 type == ui::ET_TOUCH_RELEASED) {
608 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 656 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
609 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance(); 657 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
610 double tracking_id; 658 double tracking_id;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
732 DeviceDataManagerX11::GetInstance()->GetGestureTimes( 780 DeviceDataManagerX11::GetInstance()->GetGestureTimes(
733 native_event, start_time, end_time); 781 native_event, start_time, end_time);
734 return true; 782 return true;
735 } 783 }
736 784
737 bool IsTouchpadEvent(const base::NativeEvent& event) { 785 bool IsTouchpadEvent(const base::NativeEvent& event) {
738 return DeviceDataManagerX11::GetInstance()->IsTouchpadXInputEvent(event); 786 return DeviceDataManagerX11::GetInstance()->IsTouchpadXInputEvent(event);
739 } 787 }
740 788
741 } // namespace ui 789 } // namespace ui
OLDNEW
« ui/events/keycodes/keyboard_code_conversion_x.cc ('K') | « ui/events/test/events_test_utils_x11.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698