Commit 6dc41e14 authored by sadrul@chromium.org's avatar sadrul@chromium.org

aura-x11: Add support for xmodmap'ed pointer buttons.

BUG=106305
TEST=manually

Review URL: http://codereview.chromium.org/8793002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113441 0039d316-1c4b-4281-b951-d872f2087c98
parent 58f66ede
...@@ -151,30 +151,6 @@ WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) { ...@@ -151,30 +151,6 @@ WebKit::WebUChar GetControlCharacter(int windows_key_code, bool shift) {
return 0; return 0;
} }
WebKit::WebMouseEvent::Button ButtonFromXButton(int button) {
switch (button) {
case 1:
return WebKit::WebMouseEvent::ButtonLeft;
case 2:
return WebKit::WebMouseEvent::ButtonMiddle;
case 3:
return WebKit::WebMouseEvent::ButtonRight;
default:
break;
}
return WebKit::WebMouseEvent::ButtonNone;
}
WebKit::WebMouseEvent::Button ButtonFromXState(int state) {
if (state & Button1MotionMask)
return WebKit::WebMouseEvent::ButtonLeft;
if (state & Button2MotionMask)
return WebKit::WebMouseEvent::ButtonMiddle;
if (state & Button3MotionMask)
return WebKit::WebMouseEvent::ButtonRight;
return WebKit::WebMouseEvent::ButtonNone;
}
// We have to count clicks (for double-clicks) manually. // We have to count clicks (for double-clicks) manually.
unsigned int g_num_clicks = 0; unsigned int g_num_clicks = 0;
double g_last_click_time = 0.0; double g_last_click_time = 0.0;
......
...@@ -39,6 +39,7 @@ void CheckXEventForConsistency(XEvent* xevent) { ...@@ -39,6 +39,7 @@ void CheckXEventForConsistency(XEvent* xevent) {
static bool expect_master_event = false; static bool expect_master_event = false;
static XIDeviceEvent slave_event; static XIDeviceEvent slave_event;
static gfx::Point slave_location; static gfx::Point slave_location;
static int slave_button;
// Note: If an event comes from a slave pointer device, then it will be // Note: If an event comes from a slave pointer device, then it will be
// followed by the same event, but reported from its master pointer device. // followed by the same event, but reported from its master pointer device.
...@@ -62,6 +63,7 @@ void CheckXEventForConsistency(XEvent* xevent) { ...@@ -62,6 +63,7 @@ void CheckXEventForConsistency(XEvent* xevent) {
if (xievent->sourceid == xievent->deviceid) { if (xievent->sourceid == xievent->deviceid) {
slave_event = *xievent; slave_event = *xievent;
slave_location = ui::EventLocationFromNative(xevent); slave_location = ui::EventLocationFromNative(xevent);
slave_button = ui::EventButtonFromNative(xevent);
expect_master_event = true; expect_master_event = true;
} else if (was_expecting_master_event) { } else if (was_expecting_master_event) {
CHECK_EQ(slave_location.x(), ui::EventLocationFromNative(xevent).x()); CHECK_EQ(slave_location.x(), ui::EventLocationFromNative(xevent).x());
...@@ -69,7 +71,7 @@ void CheckXEventForConsistency(XEvent* xevent) { ...@@ -69,7 +71,7 @@ void CheckXEventForConsistency(XEvent* xevent) {
CHECK_EQ(slave_event.type, xievent->type); CHECK_EQ(slave_event.type, xievent->type);
CHECK_EQ(slave_event.evtype, xievent->evtype); CHECK_EQ(slave_event.evtype, xievent->evtype);
CHECK_EQ(slave_event.detail, xievent->detail); CHECK_EQ(slave_button, ui::EventButtonFromNative(xevent));
CHECK_EQ(slave_event.flags, xievent->flags); CHECK_EQ(slave_event.flags, xievent->flags);
CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len); CHECK_EQ(slave_event.buttons.mask_len, xievent->buttons.mask_len);
CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len); CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len);
...@@ -471,10 +473,19 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch( ...@@ -471,10 +473,19 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
break; break;
} }
case MappingNotify: { case MappingNotify: {
if (xev->xmapping.request == MappingModifier || switch (xev->xmapping.request) {
xev->xmapping.request == MappingKeyboard) case MappingModifier:
case MappingKeyboard:
XRefreshKeyboardMapping(&xev->xmapping); XRefreshKeyboardMapping(&xev->xmapping);
break; break;
case MappingPointer:
ui::UpdateButtonMap();
break;
default:
NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
break;
}
break;
} }
case MotionNotify: { case MotionNotify: {
// Discard all but the most recent motion event that targets the same // Discard all but the most recent motion event that targets the same
......
...@@ -80,6 +80,14 @@ UI_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event); ...@@ -80,6 +80,14 @@ UI_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event);
UI_EXPORT gfx::Point EventLocationFromNative( UI_EXPORT gfx::Point EventLocationFromNative(
const base::NativeEvent& native_event); const base::NativeEvent& native_event);
#if defined(USE_X11)
// Returns the 'real' button for an event. The button reported in slave events
// does not take into account any remapping (e.g. using xmodmap), while the
// button reported in master events do. This is a utility function to always
// return the mapped button.
UI_EXPORT int EventButtonFromNative(const base::NativeEvent& native_event);
#endif
// Returns the KeyboardCode from a native event. // Returns the KeyboardCode from a native event.
UI_EXPORT KeyboardCode KeyboardCodeFromNative( UI_EXPORT KeyboardCode KeyboardCodeFromNative(
const base::NativeEvent& native_event); const base::NativeEvent& native_event);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h" #include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/touch/touch_factory.h" #include "ui/base/touch/touch_factory.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/point.h" #include "ui/gfx/point.h"
#if !defined(TOOLKIT_USES_GTK) #if !defined(TOOLKIT_USES_GTK)
...@@ -78,7 +79,9 @@ int GetButtonMaskForX2Event(XIDeviceEvent* xievent) { ...@@ -78,7 +79,9 @@ int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
int buttonflags = 0; int buttonflags = 0;
for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) { for (int i = 0; i < 8 * xievent->buttons.mask_len; i++) {
if (XIMaskIsSet(xievent->buttons.mask, i)) { if (XIMaskIsSet(xievent->buttons.mask, i)) {
buttonflags |= GetEventFlagsForButton(i); int button = (xievent->sourceid == xievent->deviceid) ?
ui::GetMappedButton(i) : i;
buttonflags |= GetEventFlagsForButton(button);
} }
} }
return buttonflags; return buttonflags;
...@@ -189,15 +192,16 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) { ...@@ -189,15 +192,16 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) {
static_cast<XIDeviceEvent*>(native_event->xcookie.data); static_cast<XIDeviceEvent*>(native_event->xcookie.data);
if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid)) if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid))
return GetTouchEventType(native_event); return GetTouchEventType(native_event);
int button = EventButtonFromNative(native_event);
switch (xievent->evtype) { switch (xievent->evtype) {
case XI_ButtonPress: case XI_ButtonPress:
if (xievent->detail >= kMinWheelButton && if (button >= kMinWheelButton &&
xievent->detail <= kMaxWheelButton) button <= kMaxWheelButton)
return ET_MOUSEWHEEL; return ET_MOUSEWHEEL;
return ET_MOUSE_PRESSED; return ET_MOUSE_PRESSED;
case XI_ButtonRelease: case XI_ButtonRelease:
if (xievent->detail >= kMinWheelButton && if (button >= kMinWheelButton &&
xievent->detail <= kMaxWheelButton) button <= kMaxWheelButton)
return ET_MOUSEWHEEL; return ET_MOUSEWHEEL;
return ET_MOUSE_RELEASED; return ET_MOUSE_RELEASED;
case XI_Motion: case XI_Motion:
...@@ -237,8 +241,9 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) { ...@@ -237,8 +241,9 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) {
int flags = GetButtonMaskForX2Event(xievent) | int flags = GetButtonMaskForX2Event(xievent) |
GetEventFlagsFromXState(xievent->mods.effective); GetEventFlagsFromXState(xievent->mods.effective);
const EventType type = EventTypeFromNative(native_event); const EventType type = EventTypeFromNative(native_event);
int button = EventButtonFromNative(native_event);
if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch) if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
flags |= GetEventFlagsForButton(xievent->detail); flags |= GetEventFlagsForButton(button);
return flags; return flags;
} }
case XI_Motion: case XI_Motion:
...@@ -285,6 +290,16 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { ...@@ -285,6 +290,16 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
return gfx::Point(); return gfx::Point();
} }
int EventButtonFromNative(const base::NativeEvent& native_event) {
CHECK_EQ(GenericEvent, native_event->type);
XIDeviceEvent* xievent =
static_cast<XIDeviceEvent*>(native_event->xcookie.data);
int button = xievent->detail;
return (xievent->sourceid == xievent->deviceid) ?
ui::GetMappedButton(button) : button;
}
KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) { KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
return KeyboardCodeFromXKeyEvent(native_event); return KeyboardCodeFromXKeyEvent(native_event);
} }
...@@ -306,13 +321,10 @@ bool IsMouseEvent(const base::NativeEvent& native_event) { ...@@ -306,13 +321,10 @@ bool IsMouseEvent(const base::NativeEvent& native_event) {
int GetMouseWheelOffset(const base::NativeEvent& native_event) { int GetMouseWheelOffset(const base::NativeEvent& native_event) {
int button; int button;
if (native_event->type == GenericEvent) { if (native_event->type == GenericEvent)
XIDeviceEvent* xiev = button = EventButtonFromNative(native_event);
static_cast<XIDeviceEvent*>(native_event->xcookie.data); else
button = xiev->detail;
} else {
button = native_event->xbutton.button; button = native_event->xbutton.button;
}
switch (button) { switch (button) {
case 4: case 4:
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/string_util.h" #include "base/string_util.h"
...@@ -138,6 +139,36 @@ class XCursorCache { ...@@ -138,6 +139,36 @@ class XCursorCache {
DISALLOW_COPY_AND_ASSIGN(XCursorCache); DISALLOW_COPY_AND_ASSIGN(XCursorCache);
}; };
// A singleton object that remembers remappings of mouse buttons.
class XButtonMap {
public:
static XButtonMap* GetInstance() {
return Singleton<XButtonMap>::get();
}
void UpdateMapping() {
count_ = XGetPointerMapping(ui::GetXDisplay(), map_, arraysize(map_));
}
int GetMappedButton(int button) {
return button > 0 && button <= count_ ? map_[button - 1] : button;
}
private:
friend struct DefaultSingletonTraits<XButtonMap>;
XButtonMap() {
UpdateMapping();
}
~XButtonMap() {}
unsigned char map_[256];
int count_;
DISALLOW_COPY_AND_ASSIGN(XButtonMap);
};
} // namespace } // namespace
bool XDisplayExists() { bool XDisplayExists() {
...@@ -833,6 +864,14 @@ bool IsX11WindowFullScreen(XID window) { ...@@ -833,6 +864,14 @@ bool IsX11WindowFullScreen(XID window) {
#endif #endif
} }
int GetMappedButton(int button) {
return XButtonMap::GetInstance()->GetMappedButton(button);
}
void UpdateButtonMap() {
XButtonMap::GetInstance()->UpdateMapping();
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// These functions are declared in x11_util_internal.h because they require // These functions are declared in x11_util_internal.h because they require
// XLib.h to be included, and it conflicts with many other headers. // XLib.h to be included, and it conflicts with many other headers.
......
...@@ -228,6 +228,13 @@ UI_EXPORT void SetDefaultX11ErrorHandlers(); ...@@ -228,6 +228,13 @@ UI_EXPORT void SetDefaultX11ErrorHandlers();
// Return true if a given window is in full-screen mode. // Return true if a given window is in full-screen mode.
UI_EXPORT bool IsX11WindowFullScreen(XID window); UI_EXPORT bool IsX11WindowFullScreen(XID window);
// Returns the mapped button.
int GetMappedButton(int button);
// Updates button mapping. This is usually called when a MappingNotify event is
// received.
UI_EXPORT void UpdateButtonMap();
} // namespace ui } // namespace ui
#endif // UI_BASE_X_X11_UTIL_H_ #endif // UI_BASE_X_X11_UTIL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment