Convert sticky keys to a chromeos::EventRewriter phase.

BUG=354035
TEST=unit_tests,ash_unittests,manual
R=sadrul@chromium.org,derat@chromium.org

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278342 0039d316-1c4b-4281-b951-d872f2087c98
parent 0dade4d2
...@@ -889,13 +889,6 @@ void Shell::Init(const ShellInitParams& init_params) { ...@@ -889,13 +889,6 @@ void Shell::Init(const ShellInitParams& init_params) {
// The order in which event filters are added is significant. // The order in which event filters are added is significant.
#if defined(OS_CHROMEOS)
// The StickyKeysController also rewrites events and must be added
// before observers, but after the EventRewriterEventFilter.
sticky_keys_controller_.reset(new StickyKeysController);
AddPreTargetHandler(sticky_keys_controller_.get());
#endif
// wm::UserActivityDetector passes events to observers, so let them get // wm::UserActivityDetector passes events to observers, so let them get
// rewritten first. // rewritten first.
user_activity_detector_.reset(new ::wm::UserActivityDetector); user_activity_detector_.reset(new ::wm::UserActivityDetector);
...@@ -930,6 +923,10 @@ void Shell::Init(const ShellInitParams& init_params) { ...@@ -930,6 +923,10 @@ void Shell::Init(const ShellInitParams& init_params) {
keyboard::InitializeKeyboard(); keyboard::InitializeKeyboard();
#endif #endif
#if defined(OS_CHROMEOS)
sticky_keys_controller_.reset(new StickyKeysController);
#endif
lock_state_controller_.reset(new LockStateController); lock_state_controller_.reset(new LockStateController);
power_button_controller_.reset(new PowerButtonController( power_button_controller_.reset(new PowerButtonController(
lock_state_controller_.get())); lock_state_controller_.get()));
......
This diff is collapsed.
This diff is collapsed.
...@@ -7,47 +7,14 @@ ...@@ -7,47 +7,14 @@
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/sticky_keys/sticky_keys_controller.h"
#include "ash/test/ash_test_base.h" #include "ash/test/ash_test_base.h"
#include "base/memory/scoped_ptr.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_processor.h"
namespace ash { namespace ash {
class StickyKeysOverlayTest : public test::AshTestBase { class StickyKeysOverlayTest : public test::AshTestBase {
public: public:
StickyKeysOverlayTest() : StickyKeysOverlayTest() {}
controller_(NULL),
overlay_(NULL) {}
virtual ~StickyKeysOverlayTest() {} virtual ~StickyKeysOverlayTest() {}
virtual void SetUp() OVERRIDE {
test::AshTestBase::SetUp();
controller_ = Shell::GetInstance()->sticky_keys_controller();
controller_->Enable(true);
overlay_ = controller_->GetOverlayForTest();
ASSERT_TRUE(overlay_);
}
void PressAndReleaseKey(ui::KeyboardCode code) {
SendKeyEvent(ui::ET_KEY_PRESSED, code);
SendKeyEvent(ui::ET_KEY_RELEASED, code);
}
void SendKeyEvent(ui::EventType type, ui::KeyboardCode code) {
ui::KeyEvent event(type, code, 0, false);
ui::Event::DispatcherApi dispatcher(&event);
dispatcher.set_target(Shell::GetInstance()->GetPrimaryRootWindow());
ui::EventDispatchDetails details = Shell::GetPrimaryRootWindow()->
GetHost()->event_processor()->OnEventFromSource(&event);
CHECK(!details.dispatcher_destroyed);
}
StickyKeysController* controller_;
StickyKeysOverlay* overlay_;
}; };
TEST_F(StickyKeysOverlayTest, OverlayVisibility) { TEST_F(StickyKeysOverlayTest, OverlayVisibility) {
...@@ -71,168 +38,7 @@ TEST_F(StickyKeysOverlayTest, ModifierKeyState) { ...@@ -71,168 +38,7 @@ TEST_F(StickyKeysOverlayTest, ModifierKeyState) {
overlay.GetModifierKeyState(ui::EF_CONTROL_DOWN)); overlay.GetModifierKeyState(ui::EF_CONTROL_DOWN));
} }
TEST_F(StickyKeysOverlayTest, OneModifierEnabled) { // Additional sticky key overlay tests that depend on chromeos::EventRewriter
EXPECT_FALSE(overlay_->is_visible()); // are now in chrome/browser/chromeos/events/event_rewriter_unittest.cc .
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
// Pressing modifier key should show overlay.
PressAndReleaseKey(ui::VKEY_CONTROL);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
// Pressing a normal key should hide overlay.
PressAndReleaseKey(ui::VKEY_T);
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
}
TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
// Pressing two modifiers should show overlay.
PressAndReleaseKey(ui::VKEY_SHIFT);
PressAndReleaseKey(ui::VKEY_CONTROL);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
// Pressing a normal key should hide overlay.
PressAndReleaseKey(ui::VKEY_N);
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
}
TEST_F(StickyKeysOverlayTest, LockedModifier) {
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
// Pressing a modifier key twice should lock modifier and show overlay.
PressAndReleaseKey(ui::VKEY_LMENU);
PressAndReleaseKey(ui::VKEY_LMENU);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
// Pressing a normal key should not hide overlay.
PressAndReleaseKey(ui::VKEY_D);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
}
TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
// Pressing a modifier key twice should lock modifier and show overlay.
PressAndReleaseKey(ui::VKEY_CONTROL);
PressAndReleaseKey(ui::VKEY_CONTROL);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
// Pressing another modifier key should still show overlay.
PressAndReleaseKey(ui::VKEY_SHIFT);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
// Pressing a normal key should not hide overlay but disable normal modifier.
PressAndReleaseKey(ui::VKEY_D);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
}
TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
// Enable modifiers.
PressAndReleaseKey(ui::VKEY_CONTROL);
PressAndReleaseKey(ui::VKEY_SHIFT);
PressAndReleaseKey(ui::VKEY_SHIFT);
PressAndReleaseKey(ui::VKEY_LMENU);
EXPECT_TRUE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_LOCKED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_ENABLED,
overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
// Disable modifiers and overlay should be hidden.
PressAndReleaseKey(ui::VKEY_CONTROL);
PressAndReleaseKey(ui::VKEY_CONTROL);
PressAndReleaseKey(ui::VKEY_SHIFT);
PressAndReleaseKey(ui::VKEY_LMENU);
PressAndReleaseKey(ui::VKEY_LMENU);
EXPECT_FALSE(overlay_->is_visible());
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
EXPECT_EQ(STICKY_KEY_STATE_DISABLED,
overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
}
TEST_F(StickyKeysOverlayTest, ModifierVisibility) {
// All but AltGr and Mod3 should initially be visible.
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
// Turn all modifiers on.
controller_->SetModifiersEnabled(true, true);
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
// Turn off Mod3.
controller_->SetModifiersEnabled(false, true);
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
// Turn off AltGr.
controller_->SetModifiersEnabled(true, false);
EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
// Turn off AltGr and Mod3.
controller_->SetModifiersEnabled(false, false);
EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
}
} // namespace ash } // namespace ash
This diff is collapsed.
...@@ -730,11 +730,6 @@ void ChromeBrowserMainPartsChromeos::PreBrowserStart() { ...@@ -730,11 +730,6 @@ void ChromeBrowserMainPartsChromeos::PreBrowserStart() {
// Start the CrOS input device UMA watcher // Start the CrOS input device UMA watcher
DeviceUMA::GetInstance(); DeviceUMA::GetInstance();
#endif #endif
keyboard_event_rewriters_.reset(new EventRewriterController());
keyboard_event_rewriters_->AddEventRewriter(
scoped_ptr<ui::EventRewriter>(new KeyboardDrivenEventRewriter()));
keyboard_event_rewriters_->AddEventRewriter(
scoped_ptr<ui::EventRewriter>(new EventRewriter()));
// -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun() // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
// -- immediately after ChildProcess::WaitForDebugger(). // -- immediately after ChildProcess::WaitForDebugger().
...@@ -757,7 +752,13 @@ void ChromeBrowserMainPartsChromeos::PostBrowserStart() { ...@@ -757,7 +752,13 @@ void ChromeBrowserMainPartsChromeos::PostBrowserStart() {
// These are dependent on the ash::Shell singleton already having been // These are dependent on the ash::Shell singleton already having been
// initialized. // initialized.
power_button_observer_.reset(new PowerButtonObserver); power_button_observer_.reset(new PowerButtonObserver);
data_promo_notification_.reset(new DataPromoNotification()), data_promo_notification_.reset(new DataPromoNotification());
keyboard_event_rewriters_.reset(new EventRewriterController());
keyboard_event_rewriters_->AddEventRewriter(
scoped_ptr<ui::EventRewriter>(new KeyboardDrivenEventRewriter()));
keyboard_event_rewriters_->AddEventRewriter(scoped_ptr<ui::EventRewriter>(
new EventRewriter(ash::Shell::GetInstance()->sticky_keys_controller())));
keyboard_event_rewriters_->Init(); keyboard_event_rewriters_->Init();
ChromeBrowserMainPartsLinux::PostBrowserStart(); ChromeBrowserMainPartsLinux::PostBrowserStart();
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#include <vector> #include <vector>
#include "ash/sticky_keys/sticky_keys_controller.h"
#include "ash/wm/window_state.h" #include "ash/wm/window_state.h"
#include "ash/wm/window_util.h" #include "ash/wm/window_util.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h"
#include "base/prefs/pref_service.h" #include "base/prefs/pref_service.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/sys_info.h" #include "base/sys_info.h"
...@@ -153,12 +155,24 @@ void UpdateX11EventMask(int ui_flags, unsigned int* x_flags) { ...@@ -153,12 +155,24 @@ void UpdateX11EventMask(int ui_flags, unsigned int* x_flags) {
} }
#endif #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 } // namespace
EventRewriter::EventRewriter() EventRewriter::EventRewriter(ash::StickyKeysController* sticky_keys_controller)
: last_device_id_(kBadDeviceId), : last_device_id_(kBadDeviceId),
ime_keyboard_for_testing_(NULL), 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) #if defined(USE_X11)
ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
if (base::SysInfo::IsRunningOnChromeOS()) { if (base::SysInfo::IsRunningOnChromeOS()) {
...@@ -190,35 +204,38 @@ void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event, ...@@ -190,35 +204,38 @@ void EventRewriter::RewriteLocatedEventForTesting(const ui::Event& event,
ui::EventRewriteStatus EventRewriter::RewriteEvent( ui::EventRewriteStatus EventRewriter::RewriteEvent(
const ui::Event& event, const ui::Event& event,
scoped_ptr<ui::Event>* rewritten_event) { scoped_ptr<ui::Event>* rewritten_event) {
#if defined(USE_X11) if ((event.type() == ui::ET_KEY_PRESSED) ||
// Do not rewrite an event sent by ui_controls::SendKeyPress(). See (event.type() == ui::ET_KEY_RELEASED)) {
// crbug.com/136465. return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event),
XEvent* xev = event.native_event(); rewritten_event);
if (xev && xev->xany.send_event) }
return ui::EVENT_REWRITE_CONTINUE; if (event.IsMouseEvent()) {
#endif return RewriteMouseEvent(static_cast<const ui::MouseEvent&>(event),
switch (event.type()) {
case ui::ET_KEY_PRESSED:
case ui::ET_KEY_RELEASED:
return RewriteKeyEvent(static_cast<const ui::KeyEvent&>(event),
rewritten_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.type() == ui::ET_TOUCH_PRESSED) ||
(event.type() == ui::ET_TOUCH_RELEASED)) {
return RewriteTouchEvent(static_cast<const ui::TouchEvent&>(event),
rewritten_event);
}
if (event.IsScrollEvent()) {
return RewriteScrollEvent(static_cast<const ui::ScrollEvent&>(event),
rewritten_event);
}
return ui::EVENT_REWRITE_CONTINUE;
} }
ui::EventRewriteStatus EventRewriter::NextDispatchEvent( ui::EventRewriteStatus EventRewriter::NextDispatchEvent(
const ui::Event& last_event, const ui::Event& last_event,
scoped_ptr<ui::Event>* new_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(); NOTREACHED();
return ui::EVENT_REWRITE_CONTINUE; return ui::EVENT_REWRITE_CONTINUE;
} }
...@@ -333,14 +350,33 @@ ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( ...@@ -333,14 +350,33 @@ ui::EventRewriteStatus EventRewriter::RewriteKeyEvent(
const ui::KeyEvent& key_event, const ui::KeyEvent& key_event,
scoped_ptr<ui::Event>* rewritten_event) { scoped_ptr<ui::Event>* rewritten_event) {
MutableKeyState state = {key_event.flags(), key_event.key_code()}; MutableKeyState state = {key_event.flags(), key_event.key_code()};
RewriteModifierKeys(key_event, &state); bool is_send_event = IsSendEvent(key_event);
RewriteNumPadKeys(key_event, &state); if (!is_send_event) {
RewriteExtendedKeys(key_event, &state); RewriteModifierKeys(key_event, &state);
RewriteFunctionKeys(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) && 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; 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); ui::KeyEvent* rewritten_key_event = new ui::KeyEvent(key_event);
rewritten_event->reset(rewritten_key_event); rewritten_event->reset(rewritten_key_event);
rewritten_key_event->set_flags(state.flags); rewritten_key_event->set_flags(state.flags);
...@@ -360,16 +396,26 @@ ui::EventRewriteStatus EventRewriter::RewriteKeyEvent( ...@@ -360,16 +396,26 @@ ui::EventRewriteStatus EventRewriter::RewriteKeyEvent(
state.key_code, state.flags & ui::EF_SHIFT_DOWN)); state.key_code, state.flags & ui::EF_SHIFT_DOWN));
} }
#endif #endif
return ui::EVENT_REWRITE_REWRITTEN; return status;
} }
ui::EventRewriteStatus EventRewriter::RewriteMouseEvent( ui::EventRewriteStatus EventRewriter::RewriteMouseEvent(
const ui::MouseEvent& mouse_event, const ui::MouseEvent& mouse_event,
scoped_ptr<ui::Event>* rewritten_event) { scoped_ptr<ui::Event>* rewritten_event) {
int flags = mouse_event.flags(); int flags = mouse_event.flags();
RewriteLocatedEvent(mouse_event, &flags); if ((mouse_event.type() == ui::ET_MOUSE_PRESSED) ||
if (mouse_event.flags() == flags) (mouse_event.type() == ui::ET_MOUSE_RELEASED)) {
RewriteLocatedEvent(mouse_event, &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; 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); ui::MouseEvent* rewritten_mouse_event = new ui::MouseEvent(mouse_event);
rewritten_event->reset(rewritten_mouse_event); rewritten_event->reset(rewritten_mouse_event);
rewritten_mouse_event->set_flags(flags); rewritten_mouse_event->set_flags(flags);
...@@ -397,7 +443,7 @@ ui::EventRewriteStatus EventRewriter::RewriteMouseEvent( ...@@ -397,7 +443,7 @@ ui::EventRewriteStatus EventRewriter::RewriteMouseEvent(
} }
} }
#endif #endif
return ui::EVENT_REWRITE_REWRITTEN; return status;
} }
ui::EventRewriteStatus EventRewriter::RewriteTouchEvent( ui::EventRewriteStatus EventRewriter::RewriteTouchEvent(
...@@ -424,6 +470,32 @@ ui::EventRewriteStatus EventRewriter::RewriteTouchEvent( ...@@ -424,6 +470,32 @@ ui::EventRewriteStatus EventRewriter::RewriteTouchEvent(
return ui::EVENT_REWRITE_REWRITTEN; 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, 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 ||
......
...@@ -23,6 +23,10 @@ typedef union _XEvent XEvent; ...@@ -23,6 +23,10 @@ typedef union _XEvent XEvent;
class PrefService; class PrefService;
namespace ash {
class StickyKeysController;
}
namespace chromeos { namespace chromeos {
namespace input_method { namespace input_method {
class ImeKeyboard; class ImeKeyboard;
...@@ -51,7 +55,10 @@ class EventRewriter ...@@ -51,7 +55,10 @@ class EventRewriter
kDeviceAppleKeyboard, kDeviceAppleKeyboard,
}; };
EventRewriter(); // Does not take ownership of the |sticky_keys_controller|, which may also
// be NULL (for testing without ash), in which case sticky key operations
// don't happen.
explicit EventRewriter(ash::StickyKeysController* sticky_keys_controller);
virtual ~EventRewriter(); virtual ~EventRewriter();
// Calls DeviceAddedInternal. // Calls DeviceAddedInternal.
...@@ -98,7 +105,7 @@ class EventRewriter ...@@ -98,7 +105,7 @@ class EventRewriter
#endif #endif
private: private:
// Things that internal rewriter phases can change about an Event. // Things that keyboard-related rewriter phases can change about an Event.
struct MutableKeyState { struct MutableKeyState {
int flags; int flags;
ui::KeyboardCode key_code; ui::KeyboardCode key_code;
...@@ -157,6 +164,9 @@ class EventRewriter ...@@ -157,6 +164,9 @@ class EventRewriter
ui::EventRewriteStatus RewriteTouchEvent( ui::EventRewriteStatus RewriteTouchEvent(
const ui::TouchEvent& touch_event, const ui::TouchEvent& touch_event,
scoped_ptr<ui::Event>* rewritten_event); scoped_ptr<ui::Event>* rewritten_event);
ui::EventRewriteStatus RewriteScrollEvent(
const ui::ScrollEvent& scroll_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.
...@@ -175,6 +185,10 @@ class EventRewriter ...@@ -175,6 +185,10 @@ class EventRewriter
chromeos::input_method::ImeKeyboard* ime_keyboard_for_testing_; chromeos::input_method::ImeKeyboard* ime_keyboard_for_testing_;
const PrefService* pref_service_for_testing_; const PrefService* pref_service_for_testing_;
// The sticky keys controller is not owned here;
// at time of writing it is a singleton in ash::Shell>
ash::StickyKeysController* sticky_keys_controller_;
DISALLOW_COPY_AND_ASSIGN(EventRewriter); DISALLOW_COPY_AND_ASSIGN(EventRewriter);
}; };
......
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