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) {
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.
unsigned int g_num_clicks = 0;
double g_last_click_time = 0.0;
......
......@@ -39,6 +39,7 @@ void CheckXEventForConsistency(XEvent* xevent) {
static bool expect_master_event = false;
static XIDeviceEvent slave_event;
static gfx::Point slave_location;
static int slave_button;
// 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.
......@@ -62,6 +63,7 @@ void CheckXEventForConsistency(XEvent* xevent) {
if (xievent->sourceid == xievent->deviceid) {
slave_event = *xievent;
slave_location = ui::EventLocationFromNative(xevent);
slave_button = ui::EventButtonFromNative(xevent);
expect_master_event = true;
} else if (was_expecting_master_event) {
CHECK_EQ(slave_location.x(), ui::EventLocationFromNative(xevent).x());
......@@ -69,7 +71,7 @@ void CheckXEventForConsistency(XEvent* xevent) {
CHECK_EQ(slave_event.type, xievent->type);
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.buttons.mask_len, xievent->buttons.mask_len);
CHECK_EQ(slave_event.valuators.mask_len, xievent->valuators.mask_len);
......@@ -471,9 +473,18 @@ base::MessagePumpDispatcher::DispatchStatus RootWindowHostLinux::Dispatch(
break;
}
case MappingNotify: {
if (xev->xmapping.request == MappingModifier ||
xev->xmapping.request == MappingKeyboard)
XRefreshKeyboardMapping(&xev->xmapping);
switch (xev->xmapping.request) {
case MappingModifier:
case MappingKeyboard:
XRefreshKeyboardMapping(&xev->xmapping);
break;
case MappingPointer:
ui::UpdateButtonMap();
break;
default:
NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
break;
}
break;
}
case MotionNotify: {
......
......@@ -80,6 +80,14 @@ UI_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event);
UI_EXPORT gfx::Point EventLocationFromNative(
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.
UI_EXPORT KeyboardCode KeyboardCodeFromNative(
const base::NativeEvent& native_event);
......
......@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "ui/base/keycodes/keyboard_code_conversion_x.h"
#include "ui/base/touch/touch_factory.h"
#include "ui/base/x/x11_util.h"
#include "ui/gfx/point.h"
#if !defined(TOOLKIT_USES_GTK)
......@@ -78,7 +79,9 @@ int GetButtonMaskForX2Event(XIDeviceEvent* xievent) {
int buttonflags = 0;
for (int i = 0; i < 8 * xievent->buttons.mask_len; 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;
......@@ -189,15 +192,16 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) {
static_cast<XIDeviceEvent*>(native_event->xcookie.data);
if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid))
return GetTouchEventType(native_event);
int button = EventButtonFromNative(native_event);
switch (xievent->evtype) {
case XI_ButtonPress:
if (xievent->detail >= kMinWheelButton &&
xievent->detail <= kMaxWheelButton)
if (button >= kMinWheelButton &&
button <= kMaxWheelButton)
return ET_MOUSEWHEEL;
return ET_MOUSE_PRESSED;
case XI_ButtonRelease:
if (xievent->detail >= kMinWheelButton &&
xievent->detail <= kMaxWheelButton)
if (button >= kMinWheelButton &&
button <= kMaxWheelButton)
return ET_MOUSEWHEEL;
return ET_MOUSE_RELEASED;
case XI_Motion:
......@@ -237,8 +241,9 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) {
int flags = GetButtonMaskForX2Event(xievent) |
GetEventFlagsFromXState(xievent->mods.effective);
const EventType type = EventTypeFromNative(native_event);
int button = EventButtonFromNative(native_event);
if ((type == ET_MOUSE_PRESSED || type == ET_MOUSE_RELEASED) && !touch)
flags |= GetEventFlagsForButton(xievent->detail);
flags |= GetEventFlagsForButton(button);
return flags;
}
case XI_Motion:
......@@ -285,6 +290,16 @@ gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
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) {
return KeyboardCodeFromXKeyEvent(native_event);
}
......@@ -306,13 +321,10 @@ bool IsMouseEvent(const base::NativeEvent& native_event) {
int GetMouseWheelOffset(const base::NativeEvent& native_event) {
int button;
if (native_event->type == GenericEvent) {
XIDeviceEvent* xiev =
static_cast<XIDeviceEvent*>(native_event->xcookie.data);
button = xiev->detail;
} else {
if (native_event->type == GenericEvent)
button = EventButtonFromNative(native_event);
else
button = native_event->xbutton.button;
}
switch (button) {
case 4:
#if defined(OS_CHROMEOS)
......
......@@ -18,6 +18,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/singleton.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
......@@ -138,6 +139,36 @@ class 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
bool XDisplayExists() {
......@@ -833,6 +864,14 @@ bool IsX11WindowFullScreen(XID window) {
#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
// XLib.h to be included, and it conflicts with many other headers.
......
......@@ -228,6 +228,13 @@ UI_EXPORT void SetDefaultX11ErrorHandlers();
// Return true if a given window is in full-screen mode.
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
#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