Make Alt+Button1 -> Button3 respect remapped modifiers.

Update native modifier state to reflect the rewritten ui::Event state before the X11 mouse code uses it.

Also splits code for the various ui::Event subclasses out of RewriteEvent() for clarity.

BUG=372485
R=sadrul@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274568 0039d316-1c4b-4281-b951-d872f2087c98
parent b155037c
...@@ -184,9 +184,7 @@ EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting( ...@@ -184,9 +184,7 @@ EventRewriter::DeviceType EventRewriter::DeviceAddedForTesting(
void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event, void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event,
int* flags) { int* flags) {
MutableKeyState state = {*flags, ui::VKEY_UNKNOWN}; RewriteLocatedEvent(event, flags);
RewriteLocatedEvent(event, &state);
*flags = state.flags;
} }
ui::EventRewriteStatus EventRewriter::RewriteEvent( ui::EventRewriteStatus EventRewriter::RewriteEvent(
...@@ -201,56 +199,17 @@ ui::EventRewriteStatus EventRewriter::RewriteEvent( ...@@ -201,56 +199,17 @@ ui::EventRewriteStatus EventRewriter::RewriteEvent(
#endif #endif
switch (event.type()) { switch (event.type()) {
case ui::ET_KEY_PRESSED: case ui::ET_KEY_PRESSED:
case ui::ET_KEY_RELEASED: { case ui::ET_KEY_RELEASED:
const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event),
MutableKeyState state = {key_event.flags(), key_event.key_code()}; rewritten_event);
RewriteModifierKeys(key_event, &state);
RewriteNumPadKeys(key_event, &state);
RewriteExtendedKeys(key_event, &state);
RewriteFunctionKeys(key_event, &state);
if ((key_event.flags() != state.flags) ||
(key_event.key_code() != state.key_code)) {
ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event);
rewritten_event->reset(rewritten_key_event);
rewritten_key_event->set_flags(state.flags);
rewritten_key_event->set_key_code(state.key_code);
rewritten_key_event->set_character(
ui::GetCharacterFromKeyCode(state.key_code, state.flags));
rewritten_key_event->NormalizeFlags();
#if defined(USE_X11)
xev = rewritten_key_event->native_event();
if (xev) {
XKeyEvent* xkey = &(xev->xkey);
UpdateX11EventMask(state.flags, &xkey->state);
xkey->keycode = XKeysymToKeycode(
gfx::GetXDisplay(),
ui::XKeysymForWindowsKeyCode(state.key_code,
state.flags & ui::EF_SHIFT_DOWN));
}
#endif
return ui::EVENT_REWRITE_REWRITTEN;
}
return ui::EVENT_REWRITE_CONTINUE;
}
case ui::ET_MOUSE_PRESSED: case ui::ET_MOUSE_PRESSED:
case ui::ET_MOUSE_RELEASED: case ui::ET_MOUSE_RELEASED:
return RewriteMouseEvent(static_cast<const ui::MouseEvent&>(event),
rewritten_event);
case ui::ET_TOUCH_PRESSED: case ui::ET_TOUCH_PRESSED:
case ui::ET_TOUCH_RELEASED: { case ui::ET_TOUCH_RELEASED:
MutableKeyState state = {event.flags(), ui::VKEY_UNKNOWN}; return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event),
RewriteLocatedEvent(event, &state); rewritten_event);
if (event.flags() != state.flags) {
if (event.IsMouseEvent()) {
rewritten_event->reset(
new ui::MouseEvent(static_cast<const ui::MouseEvent&>(event)));
} else {
rewritten_event->reset(
new ui::TouchEvent(static_cast<const ui::TouchEvent&>(event)));
}
rewritten_event->get()->set_flags(state.flags);
return ui::EVENT_REWRITE_REWRITTEN;
}
return ui::EVENT_REWRITE_CONTINUE;
}
default: default:
return ui::EVENT_REWRITE_CONTINUE; return ui::EVENT_REWRITE_CONTINUE;
} }
...@@ -370,6 +329,101 @@ bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode( ...@@ -370,6 +329,101 @@ bool EventRewriter::RewriteWithKeyboardRemappingsByKeyCode(
return false; return false;
} }
ui::EventRewriteStatus EventRewriter::RewriteKeyEvent(
const ui::KeyEvent& key_event,
scoped_ptr<ui::Event>* rewritten_event) {
MutableKeyState state = {key_event.flags(), key_event.key_code()};
RewriteModifierKeys(key_event, &state);
RewriteNumPadKeys(key_event, &state);
RewriteExtendedKeys(key_event, &state);
RewriteFunctionKeys(key_event, &state);
if ((key_event.flags() == state.flags) &&
(key_event.key_code() == state.key_code)) {
return ui::EVENT_REWRITE_CONTINUE;
}
ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event);
rewritten_event->reset(rewritten_key_event);
rewritten_key_event->set_flags(state.flags);
rewritten_key_event->set_key_code(state.key_code);
rewritten_key_event->set_character(
ui::GetCharacterFromKeyCode(state.key_code, state.flags));
rewritten_key_event->NormalizeFlags();
#if defined(USE_X11)
XEvent* xev = rewritten_key_event->native_event();
if (xev) {
CHECK(xev->type == KeyPress || xev->type == KeyRelease);
XKeyEvent* xkey = &(xev->xkey);
UpdateX11EventMask(rewritten_key_event->flags(), &xkey->state);
xkey->keycode =
XKeysymToKeycode(gfx::GetXDisplay(),
ui::XKeysymForWindowsKeyCode(
state.key_code, state.flags & ui::EF_SHIFT_DOWN));
}
#endif
return ui::EVENT_REWRITE_REWRITTEN;
}
ui::EventRewriteStatus EventRewriter::RewriteMouseEvent(
const ui::MouseEvent& mouse_event,
scoped_ptr<ui::Event>* rewritten_event) {
int flags = mouse_event.flags();
RewriteLocatedEvent(mouse_event, &flags);
if (mouse_event.flags() == flags)
return ui::EVENT_REWRITE_CONTINUE;
ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event);
rewritten_event->reset(rewritten_mouse_event);
rewritten_mouse_event->set_flags(flags);
#if defined(USE_X11)
XEvent* xev = rewritten_mouse_event->native_event();
if (xev) {
switch (xev->type) {
case ButtonPress:
case ButtonRelease: {
XButtonEvent* xbutton = &(xev->xbutton);
UpdateX11EventMask(rewritten_mouse_event->flags(), &xbutton->state);
break;
}
case GenericEvent: {
XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
CHECK(xievent->evtype == XI_ButtonPress ||
xievent->evtype == XI_ButtonRelease);
UpdateX11EventMask(
rewritten_mouse_event->flags(),
reinterpret_cast<unsigned int*>(&xievent->mods.effective));
break;
}
default:
NOTREACHED();
}
}
#endif
return ui::EVENT_REWRITE_REWRITTEN;
}
ui::EventRewriteStatus EventRewriter::RewriteTouchEvent(
const ui::TouchEvent& touch_event,
scoped_ptr<ui::Event>* rewritten_event) {
int flags = touch_event.flags();
RewriteLocatedEvent(touch_event, &flags);
if (touch_event.flags() == flags)
return ui::EVENT_REWRITE_CONTINUE;
ui::TouchEvent* rewritten_touch_event = new ui::TouchEvent(touch_event);
rewritten_event->reset(rewritten_touch_event);
rewritten_touch_event->set_flags(flags);
#if defined(USE_X11)
XEvent* xev = rewritten_touch_event->native_event();
if (xev) {
XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data);
if (xievent) {
UpdateX11EventMask(
rewritten_touch_event->flags(),
reinterpret_cast<unsigned int*>(&xievent->mods.effective));
}
}
#endif
return ui::EVENT_REWRITE_REWRITTEN;
}
void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event, void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event,
MutableKeyState* state) { MutableKeyState* state) {
DCHECK(key_event.type() == ui::ET_KEY_PRESSED || DCHECK(key_event.type() == ui::ET_KEY_PRESSED ||
...@@ -659,13 +713,13 @@ void EventRewriter::RewriteFunctionKeys(const ui::KeyEvent& key_event, ...@@ -659,13 +713,13 @@ void EventRewriter::RewriteFunctionKeys(const ui::KeyEvent& key_event,
} }
void EventRewriter::RewriteLocatedEvent(const ui::Event& event, void EventRewriter::RewriteLocatedEvent(const ui::Event& event,
MutableKeyState* state) { int* flags) {
const PrefService* pref_service = GetPrefService(); const PrefService* pref_service = GetPrefService();
if (!pref_service) if (!pref_service)
return; return;
// First, remap modifier masks. // First, remap modifier masks.
state->flags = GetRemappedModifierMasks(*pref_service, event, state->flags); *flags = GetRemappedModifierMasks(*pref_service, event, *flags);
#if defined(USE_X11) #if defined(USE_X11)
// TODO(kpschoedel): de-X11 with unified device ids from crbug.com/360377 // TODO(kpschoedel): de-X11 with unified device ids from crbug.com/360377
...@@ -675,13 +729,15 @@ void EventRewriter::RewriteLocatedEvent(const ui::Event& event, ...@@ -675,13 +729,15 @@ void EventRewriter::RewriteLocatedEvent(const ui::Event& event,
XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data); XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease) if (xievent->evtype != XI_ButtonPress && xievent->evtype != XI_ButtonRelease)
return; return;
UpdateX11EventMask(*flags,
reinterpret_cast<unsigned int*>(&xievent->mods.effective));
// Then, remap Alt+Button1 to Button3. // Then, remap Alt+Button1 to Button3.
if ((xievent->evtype == XI_ButtonPress || if ((xievent->evtype == XI_ButtonPress ||
pressed_device_ids_.count(xievent->sourceid)) && pressed_device_ids_.count(xievent->sourceid)) &&
(xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) { (xievent->mods.effective & Mod1Mask) && xievent->detail == Button1) {
state->flags &= ~(ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON); *flags &= ~(ui::EF_ALT_DOWN | ui::EF_LEFT_MOUSE_BUTTON);
state->flags |= ui::EF_RIGHT_MOUSE_BUTTON; *flags |= ui::EF_RIGHT_MOUSE_BUTTON;
xievent->mods.effective &= ~Mod1Mask; xievent->mods.effective &= ~Mod1Mask;
xievent->detail = Button3; xievent->detail = Button3;
if (xievent->evtype == XI_ButtonRelease) { if (xievent->evtype == XI_ButtonRelease) {
......
...@@ -147,13 +147,24 @@ class EventRewriter ...@@ -147,13 +147,24 @@ class EventRewriter
const MutableKeyState& input, const MutableKeyState& input,
MutableKeyState* remapped_state); MutableKeyState* remapped_state);
// Rewrite a particular kind of event.
ui::EventRewriteStatus RewriteKeyEvent(
const ui::KeyEvent& key_event,
scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus RewriteMouseEvent(
const ui::MouseEvent& mouse_event,
scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus RewriteTouchEvent(
const ui::TouchEvent& touch_event,
scoped_ptr<ui::Event>* rewritten_event);
// Rewriter phases. These can inspect the original |event|, but operate using // Rewriter phases. These can inspect the original |event|, but operate using
// the current |state|, which may have been modified by previous phases. // the current |state|, which may have been modified by previous phases.
void RewriteModifierKeys(const ui::KeyEvent& event, MutableKeyState* state); void RewriteModifierKeys(const ui::KeyEvent& event, MutableKeyState* state);
void RewriteNumPadKeys(const ui::KeyEvent& event, MutableKeyState* state); void RewriteNumPadKeys(const ui::KeyEvent& event, MutableKeyState* state);
void RewriteExtendedKeys(const ui::KeyEvent& event, MutableKeyState* state); void RewriteExtendedKeys(const ui::KeyEvent& event, MutableKeyState* state);
void RewriteFunctionKeys(const ui::KeyEvent& event, MutableKeyState* state); void RewriteFunctionKeys(const ui::KeyEvent& event, MutableKeyState* state);
void RewriteLocatedEvent(const ui::Event& event, MutableKeyState* state); void RewriteLocatedEvent(const ui::Event& event, int* flags);
// A set of device IDs whose press event has been rewritten. // A set of device IDs whose press event has been rewritten.
std::set<int> pressed_device_ids_; std::set<int> pressed_device_ids_;
......
...@@ -1565,6 +1565,39 @@ TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) { ...@@ -1565,6 +1565,39 @@ TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) {
*static_cast<const ui::KeyEvent*>(rewritten_event.get()))); *static_cast<const ui::KeyEvent*>(rewritten_event.get())));
} }
TEST_F(EventRewriterTest, TestRewrittenModifierClick) {
std::vector<unsigned int> device_list;
device_list.push_back(10);
ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
// Remap Control to Alt.
TestingPrefServiceSyncable prefs;
chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
IntegerPrefMember control;
control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
control.SetValue(chromeos::input_method::kAltKey);
EventRewriter rewriter;
rewriter.set_pref_service_for_testing(&prefs);
// Check that Control + Left Button is converted (via Alt + Left Button)
// to Right Button.
ui::ScopedXI2Event xev;
xev.InitGenericButtonEvent(10,
ui::ET_MOUSE_PRESSED,
gfx::Point(),
ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN);
ui::MouseEvent press(xev);
// Sanity check.
EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN, press.flags());
int flags = RewriteMouseEvent(&rewriter, press);
EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & flags);
EXPECT_FALSE(ui::EF_CONTROL_DOWN & flags);
EXPECT_FALSE(ui::EF_ALT_DOWN & flags);
}
TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) { TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) {
std::vector<unsigned int> device_list; std::vector<unsigned int> device_list;
device_list.push_back(10); device_list.push_back(10);
......
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