| Index: ui/events/x/events_x.cc
|
| diff --git a/ui/events/x/events_x.cc b/ui/events/x/events_x.cc
|
| index 69cf733e003a987b795a572aa65d6b81b891b9d5..f2e59c5ec7c94e7b86a27a07a9e0f62b3f1df6e4 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,7 +43,24 @@ 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 UpdateStateFromXKeyEvent(const base::NativeEvent& native_event) {
|
| + DCHECK((native_event->type == KeyPress) ||
|
| + (native_event->type == KeyRelease));
|
| // 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
|
| @@ -52,35 +70,35 @@ class XModifierStateWatcher{
|
| // 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;
|
| - break;
|
| - }
|
| - case ui::VKEY_MENU: {
|
| - mask = Mod1Mask;
|
| - break;
|
| - }
|
| - case ui::VKEY_CAPITAL: {
|
| - mask = LockMask;
|
| - break;
|
| - }
|
| - default:
|
| - break;
|
| - }
|
| -
|
| + unsigned int mask = StateFromKeyboardCode(keyboard_code);
|
| if (native_event->type == KeyPress)
|
| state_ |= mask;
|
| else
|
| state_ &= ~mask;
|
| }
|
|
|
| + void UpdateStateFromXGenericEvent(const base::NativeEvent& native_event) {
|
| + DCHECK(native_event->type == GenericEvent);
|
| + XIDeviceEvent* xievent =
|
| + static_cast<XIDeviceEvent*>(native_event->xcookie.data);
|
| + DCHECK((xievent->evtype == XI_KeyPress) ||
|
| + (xievent->evtype == XI_KeyRelease));
|
| + // 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_ = xievent->mods.effective;
|
| + // 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 = StateFromKeyboardCode(keyboard_code);
|
| + if (native_event->type == XI_KeyPress)
|
| + state_ |= mask;
|
| + else
|
| + state_ &= ~mask;
|
| + }
|
| +
|
| // Returns the current modifer state in master device. It only contains the
|
| // state of ctrl, shift, alt and caps lock keys.
|
| unsigned int state() { return state_; }
|
| @@ -182,6 +200,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
|
| @@ -349,6 +379,10 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) {
|
| return ET_MOUSE_MOVED;
|
| }
|
| }
|
| + case XI_KeyPress:
|
| + return ET_KEY_PRESSED;
|
| + case XI_KeyRelease:
|
| + return ET_KEY_RELEASED;
|
| }
|
| }
|
| default:
|
| @@ -361,7 +395,8 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) {
|
| switch (native_event->type) {
|
| case KeyPress:
|
| case KeyRelease: {
|
| - XModifierStateWatcher::GetInstance()->UpdateStateFromEvent(native_event);
|
| + XModifierStateWatcher::GetInstance()->UpdateStateFromXKeyEvent(
|
| + native_event);
|
| return GetEventFlagsFromXKeyEvent(native_event);
|
| }
|
| case ButtonPress:
|
| @@ -397,7 +432,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());
|
| @@ -410,8 +445,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()->UpdateStateFromXGenericEvent(
|
| + native_event);
|
| + return GetEventFlagsFromXGenericEvent(native_event);
|
| + }
|
| }
|
| }
|
| }
|
| @@ -590,14 +631,21 @@ gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
|
| }
|
|
|
| base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
|
| - if (!event || event->type == GenericEvent)
|
| + if (!event)
|
| return NULL;
|
| XEvent* copy = new XEvent;
|
| *copy = *event;
|
| + if (event->type == GenericEvent) {
|
| + XIDeviceEvent* xievent_copy = new XIDeviceEvent;
|
| + *xievent_copy = *static_cast<XIDeviceEvent*>(event->xcookie.data);
|
| + copy->xcookie.data = xievent_copy;
|
| + }
|
| return copy;
|
| }
|
|
|
| void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
|
| + if (event && event->type == GenericEvent)
|
| + delete static_cast<XIDeviceEvent*>(event->xcookie.data);
|
| delete event;
|
| }
|
|
|
|
|