Index: chrome/browser/chromeos/events/event_rewriter.cc |
diff --git a/chrome/browser/chromeos/events/event_rewriter.cc b/chrome/browser/chromeos/events/event_rewriter.cc |
index eee24f7c2c6ca6a0ae2a9ad1a4d5fe39cd99f77f..9697cb9b758879056697801ba265378afef7d64c 100644 |
--- a/chrome/browser/chromeos/events/event_rewriter.cc |
+++ b/chrome/browser/chromeos/events/event_rewriter.cc |
@@ -6,10 +6,12 @@ |
#include <vector> |
+#include "ash/sticky_keys/sticky_keys_controller.h" |
#include "ash/wm/window_state.h" |
#include "ash/wm/window_util.h" |
#include "base/command_line.h" |
#include "base/logging.h" |
+#include "base/macros.h" |
#include "base/prefs/pref_service.h" |
#include "base/strings/string_util.h" |
#include "base/sys_info.h" |
@@ -153,12 +155,24 @@ void UpdateX11EventMask(int ui_flags, unsigned int* x_flags) { |
} |
#endif |
+bool IsSendEvent(const ui::Event& event) { |
+#if defined(USE_X11) |
+ // Do not rewrite an event sent by ui_controls::SendKeyPress(). See |
+ // crbug.com/136465. |
+ XEvent* xev = event.native_event(); |
+ if (xev && xev->xany.send_event) |
+ return true; |
+#endif |
+ return false; |
+} |
+ |
} // namespace |
-EventRewriter::EventRewriter() |
+EventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller) |
: last_device_id_(kBadDeviceId), |
ime_keyboard_for_testing_(NULL), |
- pref_service_for_testing_(NULL) { |
+ pref_service_for_testing_(NULL), |
+ sticky_keys_controller_(sticky_keys_controller) { |
#if defined(USE_X11) |
ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); |
if (base::SysInfo::IsRunningOnChromeOS()) { |
@@ -190,35 +204,43 @@ void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event, |
ui::EventRewriteStatus EventRewriter::RewriteEvent( |
const ui::Event& event, |
scoped_ptr<ui::Event>* rewritten_event) { |
-#if defined(USE_X11) |
- // Do not rewrite an event sent by ui_controls::SendKeyPress(). See |
- // crbug.com/136465. |
- XEvent* xev = event.native_event(); |
- if (xev && xev->xany.send_event) |
- return ui::EVENT_REWRITE_CONTINUE; |
-#endif |
- switch (event.type()) { |
- case ui::ET_KEY_PRESSED: |
- case ui::ET_KEY_RELEASED: |
- return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event), |
+ if ((event.type() == ui::ET_KEY_PRESSED) || |
+ (event.type() == ui::ET_KEY_RELEASED)) { |
+ return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event), |
+ rewritten_event); |
+ } |
+ if ((event.type() == ui::ET_MOUSE_PRESSED) || |
+ (event.type() == ui::ET_MOUSE_RELEASED)) { |
+ return RewriteMouseButtonEvent(static_cast<const ui::MouseEvent&>(event), |
+ rewritten_event); |
+ } |
+ if (event.type() == ui::ET_MOUSEWHEEL) { |
+ return RewriteMouseWheelEvent( |
+ static_cast<const ui::MouseWheelEvent&>(event), rewritten_event); |
+ } |
+ if ((event.type() == ui::ET_TOUCH_PRESSED) || |
+ (event.type() == ui::ET_TOUCH_RELEASED)) { |
+ return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event), |
rewritten_event); |
- case ui::ET_MOUSE_PRESSED: |
- case ui::ET_MOUSE_RELEASED: |
- return RewriteMouseEvent(static_cast<const ui::MouseEvent&>(event), |
- rewritten_event); |
- case ui::ET_TOUCH_PRESSED: |
- case ui::ET_TOUCH_RELEASED: |
- return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event), |
- rewritten_event); |
- default: |
- return ui::EVENT_REWRITE_CONTINUE; |
} |
- NOTREACHED(); |
+ if (event.IsScrollEvent()) { |
+ return RewriteScrollEvent(static_cast<const ui::ScrollEvent&>(event), |
+ rewritten_event); |
+ } |
+ return ui::EVENT_REWRITE_CONTINUE; |
} |
ui::EventRewriteStatus EventRewriter::NextDispatchEvent( |
const ui::Event& last_event, |
scoped_ptr<ui::Event>* new_event) { |
+ if (sticky_keys_controller_) { |
+ // In the case of sticky keys, we know what the events obtained here are: |
+ // modifier key releases that match the ones previously discarded. So, we |
+ // know that they don't have to be passed through the post-sticky key |
+ // rewriting phases, |RewriteExtendedKeys()| and |RewriteFunctionKeys()|, |
+ // because those phases do nothing with modifier key releases. |
+ return sticky_keys_controller_->NextDispatchEvent(new_event); |
+ } |
NOTREACHED(); |
return ui::EVENT_REWRITE_CONTINUE; |
} |
@@ -333,14 +355,33 @@ 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); |
+ bool is_send_event = IsSendEvent(key_event); |
+ if (!is_send_event) { |
+ RewriteModifierKeys(key_event, &state); |
+ RewriteNumPadKeys(key_event, &state); |
+ } |
+ ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; |
+ if (sticky_keys_controller_) { |
+ status = sticky_keys_controller_->RewriteKeyEvent( |
+ key_event, state.key_code, &state.flags); |
+ if (status == ui::EVENT_REWRITE_DISCARD) |
+ return ui::EVENT_REWRITE_DISCARD; |
+ } |
+ if (!is_send_event) { |
+ RewriteExtendedKeys(key_event, &state); |
+ RewriteFunctionKeys(key_event, &state); |
+ } |
if ((key_event.flags() == state.flags) && |
- (key_event.key_code() == state.key_code)) { |
+ (key_event.key_code() == state.key_code) && |
+ (status == ui::EVENT_REWRITE_CONTINUE)) { |
return ui::EVENT_REWRITE_CONTINUE; |
} |
+ // Sticky keys may have returned a result other than |EVENT_REWRITE_CONTINUE|, |
+ // in which case we need to preserve that return status. Alternatively, we |
+ // might be here because key_event changed, in which case we need to return |
+ // |EVENT_REWRITE_REWRITTEN|. |
+ if (status == ui::EVENT_REWRITE_CONTINUE) |
+ status = ui::EVENT_REWRITE_REWRITTEN; |
ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event); |
rewritten_event->reset(rewritten_key_event); |
rewritten_key_event->set_flags(state.flags); |
@@ -360,16 +401,23 @@ ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( |
state.key_code, state.flags & ui::EF_SHIFT_DOWN)); |
} |
#endif |
- return ui::EVENT_REWRITE_REWRITTEN; |
+ return status; |
} |
-ui::EventRewriteStatus EventRewriter::RewriteMouseEvent( |
+ui::EventRewriteStatus EventRewriter::RewriteMouseButtonEvent( |
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) |
+ ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; |
+ if (sticky_keys_controller_) |
+ status = sticky_keys_controller_->RewriteMouseEvent(mouse_event, &flags); |
+ if ((mouse_event.flags() == flags) && |
+ (status == ui::EVENT_REWRITE_CONTINUE)) { |
return ui::EVENT_REWRITE_CONTINUE; |
+ } |
+ if (status == ui::EVENT_REWRITE_CONTINUE) |
+ status = ui::EVENT_REWRITE_REWRITTEN; |
ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event); |
rewritten_event->reset(rewritten_mouse_event); |
rewritten_mouse_event->set_flags(flags); |
@@ -397,7 +445,52 @@ ui::EventRewriteStatus EventRewriter::RewriteMouseEvent( |
} |
} |
#endif |
- return ui::EVENT_REWRITE_REWRITTEN; |
+ return status; |
+} |
+ |
+ui::EventRewriteStatus EventRewriter::RewriteMouseWheelEvent( |
+ const ui::MouseWheelEvent& wheel_event, |
+ scoped_ptr<ui::Event>* rewritten_event) { |
+ if (!sticky_keys_controller_) |
+ return ui::EVENT_REWRITE_CONTINUE; |
+ int flags = wheel_event.flags(); |
+ ui::EventRewriteStatus status = |
+ sticky_keys_controller_->RewriteMouseEvent(wheel_event, &flags); |
+ if ((wheel_event.flags() == flags) && |
+ (status == ui::EVENT_REWRITE_CONTINUE)) { |
+ return ui::EVENT_REWRITE_CONTINUE; |
+ } |
+ if (status == ui::EVENT_REWRITE_CONTINUE) |
+ status = ui::EVENT_REWRITE_REWRITTEN; |
+ ui::MouseWheelEvent* rewritten_wheel_event = |
+ new ui::MouseWheelEvent(wheel_event); |
+ rewritten_event->reset(rewritten_wheel_event); |
+ rewritten_wheel_event->set_flags(flags); |
+#if defined(USE_X11) |
+ XEvent* xev = rewritten_wheel_event->native_event(); |
+ if (xev) { |
+ switch (xev->type) { |
+ case ButtonPress: |
+ case ButtonRelease: { |
+ XButtonEvent* xbutton = &(xev->xbutton); |
+ UpdateX11EventMask(rewritten_wheel_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_wheel_event->flags(), |
+ reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
+ break; |
+ } |
+ default: |
+ NOTREACHED(); |
+ } |
+ } |
+#endif |
+ return status; |
} |
ui::EventRewriteStatus EventRewriter::RewriteTouchEvent( |
@@ -424,6 +517,32 @@ ui::EventRewriteStatus EventRewriter::RewriteTouchEvent( |
return ui::EVENT_REWRITE_REWRITTEN; |
} |
+ui::EventRewriteStatus EventRewriter::RewriteScrollEvent( |
+ const ui::ScrollEvent& scroll_event, |
+ scoped_ptr<ui::Event>* rewritten_event) { |
+ int flags = scroll_event.flags(); |
+ ui::EventRewriteStatus status = ui::EVENT_REWRITE_CONTINUE; |
+ if (sticky_keys_controller_) |
+ status = sticky_keys_controller_->RewriteScrollEvent(scroll_event, &flags); |
+ if (status == ui::EVENT_REWRITE_CONTINUE) |
+ return status; |
+ ui::ScrollEvent* rewritten_scroll_event = new ui::ScrollEvent(scroll_event); |
+ rewritten_event->reset(rewritten_scroll_event); |
+ rewritten_scroll_event->set_flags(flags); |
+#if defined(USE_X11) |
+ XEvent* xev = rewritten_scroll_event->native_event(); |
+ if (xev) { |
+ XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xev->xcookie.data); |
+ if (xievent) { |
+ UpdateX11EventMask( |
+ rewritten_scroll_event->flags(), |
+ reinterpret_cast<unsigned int*>(&xievent->mods.effective)); |
+ } |
+ } |
+#endif |
+ return status; |
+} |
+ |
void EventRewriter::RewriteModifierKeys(const ui::KeyEvent& key_event, |
MutableKeyState* state) { |
DCHECK(key_event.type() == ui::ET_KEY_PRESSED || |