| Index: ui/events/x/events_x.cc
|
| diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc
|
| index 5216f31effff845645644084a7ece86526a2f78f..03b7e28d8de9704453e90d7dde5a6e126667863b 100644
|
| --- a/ui/events/x/events_x.cc
|
| +++ b/ui/events/x/events_x.cc
|
| @@ -10,6 +10,7 @@
|
| #include <X11/extensions/XInput2.h>
|
| #include <X11/Xlib.h>
|
| #include <X11/Xutil.h>
|
| +#include <X11/XKBlib.h>
|
|
|
| #include "base/logging.h"
|
| #include "base/memory/singleton.h"
|
| @@ -42,43 +43,55 @@ class XModifierStateWatcher{
|
| return Singleton<XModifierStateWatcher>::get();
|
| }
|
|
|
| - void UpdateStateFromEvent(const base::NativeEvent& native_event) {
|
| + int StateFromKeyboardCode(ui::KeyboardCode keyboard_code) {
|
| + switch (keyboard_code) {
|
| + case ui::VKEY_CONTROL:
|
| + return ControlMask;
|
| + case ui::VKEY_SHIFT:
|
| + return ShiftMask;
|
| + case ui::VKEY_MENU:
|
| + return Mod1Mask;
|
| + case ui::VKEY_CAPITAL:
|
| + return LockMask;
|
| + default:
|
| + return 0;
|
| + }
|
| + }
|
| +
|
| + void UpdateStateFromXEvent(const base::NativeEvent& native_event) {
|
| + ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
|
| + unsigned int mask = StateFromKeyboardCode(keyboard_code);
|
| // Floating device can't access the modifer state from master device.
|
| // We need to track the states of modifier keys in a singleton for
|
| // floating devices such as touch screen. Issue 106426 is one example
|
| // of why we need the modifier states for floating device.
|
| - state_ = native_event->xkey.state;
|
| - // master_state is the state before key press. We need to track the
|
| - // state after key press for floating device. Currently only ctrl,
|
| - // shift, alt and caps lock keys are tracked.
|
| - ui::KeyboardCode keyboard_code = ui::KeyboardCodeFromNative(native_event);
|
| - unsigned int mask = 0;
|
| -
|
| - switch (keyboard_code) {
|
| - case ui::VKEY_CONTROL: {
|
| - mask = ControlMask;
|
| - break;
|
| - }
|
| - case ui::VKEY_SHIFT: {
|
| - mask = ShiftMask;
|
| + switch (native_event->type) {
|
| + case KeyPress:
|
| + state_ = native_event->xkey.state | mask;
|
| break;
|
| - }
|
| - case ui::VKEY_MENU: {
|
| - mask = Mod1Mask;
|
| + case KeyRelease:
|
| + state_ = native_event->xkey.state & ~mask;
|
| break;
|
| - }
|
| - case ui::VKEY_CAPITAL: {
|
| - mask = LockMask;
|
| + case GenericEvent: {
|
| + XIDeviceEvent* xievent =
|
| + static_cast<XIDeviceEvent*>(native_event->xcookie.data);
|
| + switch (xievent->evtype) {
|
| + case XI_KeyPress:
|
| + state_ = xievent->mods.effective |= mask;
|
| + break;
|
| + case XI_KeyRelease:
|
| + state_ = xievent->mods.effective &= ~mask;
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + break;
|
| + }
|
| break;
|
| }
|
| default:
|
| + NOTREACHED();
|
| break;
|
| }
|
| -
|
| - if (native_event->type == KeyPress)
|
| - state_ |= mask;
|
| - else
|
| - state_ &= ~mask;
|
| }
|
|
|
| // Returns the current modifer state in master device. It only contains the
|
| @@ -182,6 +195,18 @@ int GetEventFlagsFromXKeyEvent(XEvent* xevent) {
|
| ime_fabricated_flag;
|
| }
|
|
|
| +int GetEventFlagsFromXGenericEvent(XEvent* xevent) {
|
| + DCHECK(xevent->type == GenericEvent);
|
| + XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
|
| + DCHECK((xievent->evtype == XI_KeyPress) ||
|
| + (xievent->evtype == XI_KeyRelease));
|
| + return GetEventFlagsFromXState(xievent->mods.effective) |
|
| + (IsKeypadKey(
|
| + XkbKeycodeToKeysym(xievent->display, xievent->detail, 0, 0))
|
| + ? ui::EF_NUMPAD_KEY
|
| + : 0);
|
| +}
|
| +
|
| // Get the event flag for the button in XButtonEvent. During a ButtonPress
|
| // event, |state| in XButtonEvent does not include the button that has just been
|
| // pressed. Instead |state| contains flags for the buttons (if any) that had
|
| @@ -354,10 +379,13 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) {
|
| return ET_UMA_DATA;
|
| } else if (GetButtonMaskForX2Event(xievent)) {
|
| return ET_MOUSE_DRAGGED;
|
| - } else {
|
| - return ET_MOUSE_MOVED;
|
| }
|
| + return ET_MOUSE_MOVED;
|
| }
|
| + case XI_KeyPress:
|
| + return ET_KEY_PRESSED;
|
| + case XI_KeyRelease:
|
| + return ET_KEY_RELEASED;
|
| }
|
| }
|
| default:
|
| @@ -370,7 +398,7 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) {
|
| switch (native_event->type) {
|
| case KeyPress:
|
| case KeyRelease: {
|
| - XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event);
|
| + XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(native_event);
|
| return GetEventFlagsFromXKeyEvent(native_event);
|
| }
|
| case ButtonPress:
|
| @@ -406,7 +434,7 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) {
|
| const bool touch =
|
| TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid);
|
| int flags = GetButtonMaskForX2Event(xievent) |
|
| - GetEventFlagsFromXState(xievent->mods.effective);
|
| + GetEventFlagsFromXState(xievent->mods.effective);
|
| if (touch) {
|
| flags |= GetEventFlagsFromXState(
|
| XModifierStateWatcher::GetInstance()->state());
|
| @@ -419,8 +447,14 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) {
|
| return flags;
|
| }
|
| case XI_Motion:
|
| - return GetButtonMaskForX2Event(xievent) |
|
| - GetEventFlagsFromXState(xievent->mods.effective);
|
| + return GetButtonMaskForX2Event(xievent) |
|
| + GetEventFlagsFromXState(xievent->mods.effective);
|
| + case XI_KeyPress:
|
| + case XI_KeyRelease: {
|
| + XModifierStateWatcher::GetInstance()->UpdateStateFromXEvent(
|
| + native_event);
|
| + return GetEventFlagsFromXGenericEvent(native_event);
|
| + }
|
| }
|
| }
|
| }
|
|
|