Commit 7f926755 authored by oshima@chromium.org's avatar oshima@chromium.org

Rewrite release event only if press event was rewritten for a given device.

BUG=330567
TEST=TBD

Review URL: https://codereview.chromium.org/144423006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@247912 0039d316-1c4b-4281-b951-d872f2087c98
parent 5ded5277
......@@ -1003,15 +1003,20 @@ void EventRewriter::RewriteLocatedEvent(ui::LocatedEvent* event) {
xievent->mods.effective = remapped_native_modifiers;
// Then, remap Alt+Button1 to Button3.
if ((xievent->mods.effective & Mod1Mask) && xievent->detail == 1) {
if ((xievent->evtype == XI_ButtonPress ||
pressed_device_ids_.count(xievent->sourceid)) &&
(xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) {
xievent->mods.effective &= ~Mod1Mask;
xievent->detail = 3;
xievent->detail = Button3;
if (xievent->evtype == XI_ButtonRelease) {
// On the release clear the left button from the existing state and the
// mods, and set the right button.
XISetMask(xievent->buttons.mask, 3);
XIClearMask(xievent->buttons.mask, 1);
XISetMask(xievent->buttons.mask, Button3);
XIClearMask(xievent->buttons.mask, Button1);
xievent->mods.effective &= ~Button1Mask;
pressed_device_ids_.erase(xievent->sourceid);
} else {
pressed_device_ids_.insert(xievent->sourceid);
}
}
......
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_ASH_EVENT_REWRITER_H_
#include <map>
#include <set>
#include <string>
#include "ash/event_rewriter_delegate.h"
......@@ -78,6 +79,7 @@ class EventRewriter : public ash::EventRewriterDelegate,
private:
friend class EventRewriterAshTest;
friend class EventRewriterTest;
// ash::EventRewriterDelegate overrides:
virtual ash::EventRewriterDelegate::Action RewriteOrFilterKeyEvent(
......@@ -223,6 +225,9 @@ class EventRewriter : public ash::EventRewriterDelegate,
// A mapping from X11 KeySym keys to KeyCode values.
base::hash_map<unsigned long, unsigned long> keysym_to_keycode_map_;
// A set of device IDs whose press event has been rewritten.
std::set<int> pressed_device_ids_;
chromeos::input_method::XKeyboard* xkeyboard_for_testing_;
scoped_ptr<chromeos::KeyboardDrivenEventRewriter>
......
......@@ -29,6 +29,7 @@
#include "chromeos/ime/mock_xkeyboard.h"
#include "ui/aura/window.h"
#include "ui/events/test/events_test_utils_x11.h"
#include "ui/events/x/touch_factory_x11.h"
#include "ui/gfx/x/x11_types.h"
namespace {
......@@ -63,6 +64,8 @@ std::string GetExpectedResultAsString(ui::KeyboardCode ui_keycode,
ui_keycode, ui_flags, ui_type, x_keycode, x_state, x_type);
}
} // namespace
class EventRewriterTest : public testing::Test {
public:
EventRewriterTest()
......@@ -180,6 +183,11 @@ class EventRewriterTest : public testing::Test {
void TestRewriteNumPadKeys();
void TestRewriteNumPadKeysOnAppleKeyboard();
void RewriteLocatedEvent(EventRewriter* rewriter,
ui::LocatedEvent* event) {
rewriter->RewriteLocatedEvent(event);
}
Display* display_;
const KeyCode keycode_a_;
const KeyCode keycode_alt_l_;
......@@ -270,7 +278,6 @@ class EventRewriterTest : public testing::Test {
chromeos::input_method::MockInputMethodManager* input_method_manager_mock_;
};
} // namespace
#else
class EventRewriterTest : public testing::Test {
public:
......@@ -2380,4 +2387,76 @@ TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) {
ASSERT_EQ(ui::VKEY_BROWSER_BACK, press_f1.key_code());
}
TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) {
std::vector<unsigned int> device_list;
device_list.push_back(10);
device_list.push_back(11);
ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
TestingPrefServiceSyncable prefs;
EventRewriter rewriter;
rewriter.set_pref_service_for_testing(&prefs);
const int kLeftAndAltFlag = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN;
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(10, ui::ET_MOUSE_PRESSED, kLeftAndAltFlag);
ui::MouseEvent press(xev);
// Sanity check.
EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
EXPECT_EQ(kLeftAndAltFlag, press.flags());
RewriteLocatedEvent(&rewriter, &press);
EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & press.flags());
}
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag);
ui::MouseEvent release(xev);
RewriteLocatedEvent(&rewriter, &release);
EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & release.flags());
}
// No ALT in frst click.
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(
10, ui::ET_MOUSE_PRESSED, ui::EF_LEFT_MOUSE_BUTTON);
ui::MouseEvent press(xev);
RewriteLocatedEvent(&rewriter, &press);
EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & press.flags());
}
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag);
ui::MouseEvent release(xev);
RewriteLocatedEvent(&rewriter, &release);
EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) &
release.flags());
}
// ALT on different device.
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(11, ui::ET_MOUSE_PRESSED, kLeftAndAltFlag);
ui::MouseEvent press(xev);
RewriteLocatedEvent(&rewriter, &press);
EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & press.flags());
}
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(10, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag);
ui::MouseEvent release(xev);
RewriteLocatedEvent(&rewriter, &release);
EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) &
release.flags());
}
{
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(11, ui::ET_MOUSE_RELEASED, kLeftAndAltFlag);
ui::MouseEvent release(xev);
RewriteLocatedEvent(&rewriter, &release);
EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & release.flags());
}
}
#endif // OS_CHROMEOS
......@@ -40,6 +40,20 @@ int XKeyEventType(ui::EventType type) {
}
}
int XIButtonEventType(ui::EventType type) {
switch (type) {
case ui::ET_MOUSEWHEEL:
case ui::ET_MOUSE_PRESSED:
// The button release X events for mouse wheels are dropped by Aura.
return XI_ButtonPress;
case ui::ET_MOUSE_RELEASED:
return XI_ButtonRelease;
default:
NOTREACHED();
return 0;
}
}
// Converts EventType to XButtonEvent type.
int XButtonEventType(ui::EventType type) {
switch (type) {
......@@ -74,14 +88,12 @@ unsigned int XButtonEventButton(ui::EventType type,
if (type == ui::ET_MOUSEWHEEL)
return Button4;
switch (flags) {
case ui::EF_LEFT_MOUSE_BUTTON:
if (flags & ui::EF_LEFT_MOUSE_BUTTON)
return Button1;
case ui::EF_MIDDLE_MOUSE_BUTTON:
if (flags & ui::EF_MIDDLE_MOUSE_BUTTON)
return Button2;
case ui::EF_RIGHT_MOUSE_BUTTON:
if (flags & ui::EF_RIGHT_MOUSE_BUTTON)
return Button3;
}
return 0;
}
......@@ -111,7 +123,11 @@ XEvent* CreateXInput2Event(int deviceid,
xiev->detail = tracking_id;
xiev->event_x = location.x();
xiev->event_y = location.y();
if (evtype == XI_ButtonPress || evtype == XI_ButtonRelease) {
xiev->buttons.mask_len = 8;
xiev->buttons.mask = new unsigned char[xiev->buttons.mask_len];
memset(xiev->buttons.mask, 0, xiev->buttons.mask_len);
}
return event;
}
......@@ -149,6 +165,18 @@ void ScopedXI2Event::InitKeyEvent(EventType type,
event_->xkey.same_screen = 1;
}
void ScopedXI2Event::InitGenericButtonEvent(int deviceid,
EventType type,
int flags) {
Cleanup();
event_.reset(CreateXInput2Event(deviceid,
XIButtonEventType(type), 0, gfx::Point()));
XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(event_->xcookie.data);
xievent->mods.effective = XEventState(flags);
xievent->detail = XButtonEventButton(type, flags);
XISetMask(xievent->buttons.mask, xievent->detail);
}
void ScopedXI2Event::InitButtonEvent(EventType type,
int flags) {
Cleanup();
......@@ -238,6 +266,7 @@ void ScopedXI2Event::Cleanup() {
if (xiev) {
delete[] xiev->valuators.mask;
delete[] xiev->valuators.values;
delete[] xiev->buttons.mask;
delete xiev;
}
}
......
......@@ -41,6 +41,10 @@ class ScopedXI2Event {
void InitButtonEvent(EventType type,
int flags);
void InitGenericButtonEvent(int deviceid,
EventType type,
int flags);
void InitMouseWheelEvent(int wheel_delta,
int flags);
......
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