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

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: Post rebase, make KeyboardCodeFromXKeyEvent() not modify its argument. 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));
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) {
sadrul 2014/07/10 16:03:06 We are duping some amount of code and comment here
kpschoedel 2014/07/10 17:22:40 Done.
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)
sadrul 2014/07/10 16:03:06 native_event->type is going to be GenericEvent her
kpschoedel 2014/07/10 17:22:40 Done.
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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) { 377 if (GetFlingData(native_event, NULL, NULL, NULL, NULL, &is_cancel)) {
348 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START; 378 return is_cancel ? ET_SCROLL_FLING_CANCEL : ET_SCROLL_FLING_START;
349 } else if (DeviceDataManagerX11::GetInstance()->IsScrollEvent( 379 } else if (DeviceDataManagerX11::GetInstance()->IsScrollEvent(
350 native_event)) { 380 native_event)) {
351 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL; 381 return IsTouchpadEvent(native_event) ? ET_SCROLL : ET_MOUSEWHEEL;
352 } else if (DeviceDataManagerX11::GetInstance()->IsCMTMetricsEvent( 382 } else if (DeviceDataManagerX11::GetInstance()->IsCMTMetricsEvent(
353 native_event)) { 383 native_event)) {
354 return ET_UMA_DATA; 384 return ET_UMA_DATA;
355 } else if (GetButtonMaskForX2Event(xievent)) { 385 } else if (GetButtonMaskForX2Event(xievent)) {
356 return ET_MOUSE_DRAGGED; 386 return ET_MOUSE_DRAGGED;
357 } else { 387 } else {
sadrul 2014/07/10 16:03:06 Remove the else here, and just do a 'return ET_MOU
kpschoedel 2014/07/10 17:22:39 Done.
358 return ET_MOUSE_MOVED; 388 return ET_MOUSE_MOVED;
359 } 389 }
360 } 390 }
391 case XI_KeyPress:
392 return ET_KEY_PRESSED;
393 case XI_KeyRelease:
394 return ET_KEY_RELEASED;
361 } 395 }
362 } 396 }
363 default: 397 default:
364 break; 398 break;
365 } 399 }
366 return ET_UNKNOWN; 400 return ET_UNKNOWN;
367 } 401 }
368 402
369 int EventFlagsFromNative(const base::NativeEvent& native_event) { 403 int EventFlagsFromNative(const base::NativeEvent& native_event) {
370 switch (native_event->type) { 404 switch (native_event->type) {
371 case KeyPress: 405 case KeyPress:
372 case KeyRelease: { 406 case KeyRelease: {
373 XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event); 407 XModifierStateWatcher::GetInstance()->UpdateStateFromXKeyEvent(
408 native_event);
374 return GetEventFlagsFromXKeyEvent(native_event); 409 return GetEventFlagsFromXKeyEvent(native_event);
375 } 410 }
376 case ButtonPress: 411 case ButtonPress:
377 case ButtonRelease: { 412 case ButtonRelease: {
378 int flags = GetEventFlagsFromXState(native_event->xbutton.state); 413 int flags = GetEventFlagsFromXState(native_event->xbutton.state);
379 const EventType type = EventTypeFromNative(native_event); 414 const EventType type = EventTypeFromNative(native_event);
380 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) 415 if (type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED)
381 flags |= GetEventFlagsForButton(native_event->xbutton.button); 416 flags |= GetEventFlagsForButton(native_event->xbutton.button);
382 return flags; 417 return flags;
383 } 418 }
(...skipping 15 matching lines...) Expand all
399 GetEventFlagsFromXState(xievent->mods.effective) | 434 GetEventFlagsFromXState(xievent->mods.effective) |
400 GetEventFlagsFromXState( 435 GetEventFlagsFromXState(
401 XModifierStateWatcher::GetInstance()->state()); 436 XModifierStateWatcher::GetInstance()->state());
402 break; 437 break;
403 #endif 438 #endif
404 case XI_ButtonPress: 439 case XI_ButtonPress:
405 case XI_ButtonRelease: { 440 case XI_ButtonRelease: {
406 const bool touch = 441 const bool touch =
407 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid); 442 TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
408 int flags = GetButtonMaskForX2Event(xievent) | 443 int flags = GetButtonMaskForX2Event(xievent) |
409 GetEventFlagsFromXState(xievent->mods.effective); 444 GetEventFlagsFromXState(xievent->mods.effective);
410 if (touch) { 445 if (touch) {
411 flags |= GetEventFlagsFromXState( 446 flags |= GetEventFlagsFromXState(
412 XModifierStateWatcher::GetInstance()->state()); 447 XModifierStateWatcher::GetInstance()->state());
413 } 448 }
414 449
415 const EventType type = EventTypeFromNative(native_event); 450 const EventType type = EventTypeFromNative(native_event);
416 int button = EventButtonFromNative(native_event); 451 int button = EventButtonFromNative(native_event);
417 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch) 452 if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
418 flags |= GetEventFlagsForButton(button); 453 flags |= GetEventFlagsForButton(button);
419 return flags; 454 return flags;
420 } 455 }
421 case XI_Motion: 456 case XI_Motion:
422 return GetButtonMaskForX2Event(xievent) | 457 return GetButtonMaskForX2Event(xievent) |
423 GetEventFlagsFromXState(xievent->mods.effective); 458 GetEventFlagsFromXState(xievent->mods.effective);
459 case XI_KeyPress:
460 case XI_KeyRelease: {
461 XModifierStateWatcher::GetInstance()->UpdateStateFromXGenericEvent(
462 native_event);
463 return GetEventFlagsFromXGenericEvent(native_event);
464 }
424 } 465 }
425 } 466 }
426 } 467 }
427 return 0; 468 return 0;
428 } 469 }
429 470
430 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { 471 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
431 switch(native_event->type) { 472 switch(native_event->type) {
432 case KeyPress: 473 case KeyPress:
433 case KeyRelease: 474 case KeyRelease:
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 case 6: 633 case 6:
593 return gfx::Vector2d(kWheelScrollAmount, 0); 634 return gfx::Vector2d(kWheelScrollAmount, 0);
594 case 7: 635 case 7:
595 return gfx::Vector2d(-kWheelScrollAmount, 0); 636 return gfx::Vector2d(-kWheelScrollAmount, 0);
596 default: 637 default:
597 return gfx::Vector2d(); 638 return gfx::Vector2d();
598 } 639 }
599 } 640 }
600 641
601 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) { 642 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
602 if (!event || event->type == GenericEvent) 643 if (!event)
603 return NULL; 644 return NULL;
604 XEvent* copy = new XEvent; 645 XEvent* copy = new XEvent;
605 *copy = *event; 646 *copy = *event;
647 if (event->type == GenericEvent) {
648 XIDeviceEvent* xievent_copy = new XIDeviceEvent;
649 *xievent_copy = *static_cast<XIDeviceEvent*>(event->xcookie.data);
650 copy->xcookie.data = xievent_copy;
651 }
606 return copy; 652 return copy;
sadrul 2014/07/10 16:03:06 We should not make a copy of a XI2 event here. Wha
kpschoedel 2014/07/10 17:22:40 Evidently none that's covered by unit_tests ash_un
607 } 653 }
608 654
609 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) { 655 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
656 if (event && event->type == GenericEvent)
657 delete static_cast<XIDeviceEvent*>(event->xcookie.data);
610 delete event; 658 delete event;
611 } 659 }
612 660
613 void ClearTouchIdIfReleased(const base::NativeEvent& xev) { 661 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
614 ui::EventType type = ui::EventTypeFromNative(xev); 662 ui::EventType type = ui::EventTypeFromNative(xev);
615 if (type == ui::ET_TOUCH_CANCELLED || 663 if (type == ui::ET_TOUCH_CANCELLED ||
616 type == ui::ET_TOUCH_RELEASED) { 664 type == ui::ET_TOUCH_RELEASED) {
617 ui::TouchFactory* factory = ui::TouchFactory::GetInstance(); 665 ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
618 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance(); 666 ui::DeviceDataManagerX11* manager = ui::DeviceDataManagerX11::GetInstance();
619 double tracking_id; 667 double tracking_id;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 DeviceDataManagerX11::GetInstance()->GetGestureTimes( 789 DeviceDataManagerX11::GetInstance()->GetGestureTimes(
742 native_event, start_time, end_time); 790 native_event, start_time, end_time);
743 return true; 791 return true;
744 } 792 }
745 793
746 bool IsTouchpadEvent(const base::NativeEvent& event) { 794 bool IsTouchpadEvent(const base::NativeEvent& event) {
747 return DeviceDataManagerX11::GetInstance()->IsTouchpadXInputEvent(event); 795 return DeviceDataManagerX11::GetInstance()->IsTouchpadXInputEvent(event);
748 } 796 }
749 797
750 } // namespace ui 798 } // namespace ui
OLDNEW
« ui/events/keycodes/keyboard_code_conversion_x.h ('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