Index: trunk/src/ash/sticky_keys/sticky_keys_unittest.cc |
=================================================================== |
--- trunk/src/ash/sticky_keys/sticky_keys_unittest.cc (revision 278418) |
+++ trunk/src/ash/sticky_keys/sticky_keys_unittest.cc (working copy) |
@@ -16,7 +16,8 @@ |
#include "base/memory/scoped_vector.h" |
#include "ui/aura/window.h" |
#include "ui/aura/window_tree_host.h" |
-#include "ui/events/event_source.h" |
+#include "ui/events/event_handler.h" |
+#include "ui/events/event_processor.h" |
#include "ui/events/test/events_test_utils_x11.h" |
#include "ui/events/x/device_data_manager.h" |
@@ -29,7 +30,107 @@ |
} // namespace |
-class StickyKeysTest : public test::AshTestBase { |
+// Keeps a buffer of handled events. |
+class EventBuffer : public ui::EventHandler { |
+ public: |
+ EventBuffer() {} |
+ virtual ~EventBuffer() {} |
+ |
+ void PopEvents(ScopedVector<ui::Event>* events) { |
+ events->clear(); |
+ events->swap(events_); |
+ } |
+ |
+ private: |
+ // ui::EventHandler overrides: |
+ virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE { |
+ events_.push_back(new ui::KeyEvent(*event)); |
+ } |
+ |
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { |
+ if (event->IsMouseWheelEvent()) { |
+ events_.push_back( |
+ new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event))); |
+ } else { |
+ events_.push_back(new ui::MouseEvent(*event)); |
+ } |
+ } |
+ |
+ ScopedVector<ui::Event> events_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EventBuffer); |
+}; |
+ |
+// A testable and StickyKeysHandler. |
+class MockStickyKeysHandlerDelegate : |
+ public StickyKeysHandler::StickyKeysHandlerDelegate { |
+ public: |
+ class Delegate { |
+ public: |
+ virtual aura::Window* GetExpectedTarget() = 0; |
+ virtual void OnShortcutPressed() = 0; |
+ |
+ protected: |
+ virtual ~Delegate() {} |
+ }; |
+ |
+ MockStickyKeysHandlerDelegate(Delegate* delegate) : delegate_(delegate) {} |
+ |
+ virtual ~MockStickyKeysHandlerDelegate() {} |
+ |
+ // StickyKeysHandler override. |
+ virtual void DispatchKeyEvent(ui::KeyEvent* event, |
+ aura::Window* target) OVERRIDE { |
+ ASSERT_EQ(delegate_->GetExpectedTarget(), target); |
+ |
+ // Detect a special shortcut when it is dispatched. This shortcut will |
+ // not be hit in the LOCKED state as this case does not involve the |
+ // delegate. |
+ if (event->type() == ui::ET_KEY_PRESSED && |
+ event->key_code() == ui::VKEY_J && |
+ event->flags() | ui::EF_CONTROL_DOWN) { |
+ delegate_->OnShortcutPressed(); |
+ } |
+ |
+ events_.push_back(new ui::KeyEvent(*event)); |
+ } |
+ |
+ virtual void DispatchMouseEvent(ui::MouseEvent* event, |
+ aura::Window* target) OVERRIDE { |
+ ASSERT_EQ(delegate_->GetExpectedTarget(), target); |
+ events_.push_back( |
+ new ui::MouseEvent(*event, target, target->GetRootWindow())); |
+ } |
+ |
+ virtual void DispatchScrollEvent(ui::ScrollEvent* event, |
+ aura::Window* target) OVERRIDE { |
+ events_.push_back(new ui::ScrollEvent(event->native_event())); |
+ } |
+ |
+ // Returns the count of dispatched events. |
+ size_t GetEventCount() const { |
+ return events_.size(); |
+ } |
+ |
+ // Returns the |index|-th dispatched event. |
+ const ui::Event* GetEvent(size_t index) const { |
+ return events_[index]; |
+ } |
+ |
+ // Clears all previously dispatched events. |
+ void ClearEvents() { |
+ events_.clear(); |
+ } |
+ |
+ private: |
+ ScopedVector<ui::Event> events_; |
+ Delegate* delegate_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MockStickyKeysHandlerDelegate); |
+}; |
+ |
+class StickyKeysTest : public test::AshTestBase, |
+ public MockStickyKeysHandlerDelegate::Delegate { |
protected: |
StickyKeysTest() |
: target_(NULL), |
@@ -50,35 +151,47 @@ |
test::AshTestBase::TearDown(); |
} |
- virtual void OnShortcutPressed() { |
+ // Overridden from MockStickyKeysHandlerDelegate::Delegate: |
+ virtual aura::Window* GetExpectedTarget() OVERRIDE { |
+ return target_ ? target_ : root_window_; |
+ } |
+ |
+ virtual void OnShortcutPressed() OVERRIDE { |
if (target_) { |
delete target_; |
target_ = NULL; |
} |
} |
- ui::KeyEvent* GenerateKey(ui::EventType type, ui::KeyboardCode code) { |
- scoped_xevent_.InitKeyEvent(type, code, 0); |
- ui::KeyEvent* event = new ui::KeyEvent(scoped_xevent_, false); |
+ ui::KeyEvent* GenerateKey(bool is_key_press, ui::KeyboardCode code) { |
+ scoped_xevent_.InitKeyEvent( |
+ is_key_press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED, |
+ code, |
+ 0); |
+ ui::KeyEvent* event = new ui::KeyEvent(scoped_xevent_, false); |
+ ui::Event::DispatcherApi dispatcher(event); |
+ dispatcher.set_target(target_); |
return event; |
} |
// Creates a mouse event backed by a native XInput2 generic button event. |
// This is the standard native event on Chromebooks. |
- ui::MouseEvent* GenerateMouseEvent(ui::EventType type) { |
- return GenerateMouseEventAt(type, gfx::Point()); |
+ ui::MouseEvent* GenerateMouseEvent(bool is_button_press) { |
+ return GenerateMouseEventAt(is_button_press, gfx::Point()); |
} |
// Creates a mouse event backed by a native XInput2 generic button event. |
// The |location| should be in physical pixels. |
- ui::MouseEvent* GenerateMouseEventAt(ui::EventType type, |
+ ui::MouseEvent* GenerateMouseEventAt(bool is_button_press, |
const gfx::Point& location) { |
scoped_xevent_.InitGenericButtonEvent( |
kTouchPadDeviceId, |
- type, |
+ is_button_press ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, |
location, |
0); |
ui::MouseEvent* event = new ui::MouseEvent(scoped_xevent_); |
+ ui::Event::DispatcherApi dispatcher(event); |
+ dispatcher.set_target(target_); |
return event; |
} |
@@ -121,9 +234,14 @@ |
} |
// Creates a synthesized KeyEvent that is not backed by a native event. |
- ui::KeyEvent* GenerateSynthesizedKeyEvent(ui::EventType type, |
- ui::KeyboardCode code) { |
- return new ui::KeyEvent(type, code, 0, true); |
+ ui::KeyEvent* GenerateSynthesizedKeyEvent( |
+ bool is_key_press, ui::KeyboardCode code) { |
+ ui::KeyEvent* event = new ui::KeyEvent( |
+ is_key_press ? ui::ET_KEY_PRESSED : ui::ET_MOUSE_RELEASED, |
+ code, 0, true); |
+ ui::Event::DispatcherApi dispatcher(event); |
+ dispatcher.set_target(target_); |
+ return event; |
} |
// Creates a synthesized MouseEvent that is not backed by a native event. |
@@ -141,9 +259,11 @@ |
// Creates a synthesized mouse press or release event. |
ui::MouseEvent* GenerateSynthesizedMouseClickEvent( |
- ui::EventType type, |
+ bool is_button_press, |
const gfx::Point& location) { |
- return GenerateSynthesizedMouseEventAt(type, location); |
+ return GenerateSynthesizedMouseEventAt( |
+ is_button_press ? ui::ET_MOUSE_PRESSED : ui::ET_MOUSE_RELEASED, |
+ location); |
} |
// Creates a synthesized ET_MOUSE_MOVED event. |
@@ -164,30 +284,24 @@ |
void SendActivateStickyKeyPattern(StickyKeysHandler* handler, |
ui::KeyboardCode key_code) { |
- bool released = false; |
- int down_flags = 0; |
scoped_ptr<ui::KeyEvent> ev; |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, key_code)); |
- handler->HandleKeyEvent(*ev.get(), key_code, &down_flags, &released); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, key_code)); |
- handler->HandleKeyEvent(*ev.get(), key_code, &down_flags, &released); |
+ ev.reset(GenerateKey(true, key_code)); |
+ handler->HandleKeyEvent(ev.get()); |
+ ev.reset(GenerateKey(false, key_code)); |
+ handler->HandleKeyEvent(ev.get()); |
} |
- bool HandleKeyEvent(const ui::KeyEvent& key_event, |
- StickyKeysHandler* handler, |
- int* down, |
- bool* up) { |
- return handler->HandleKeyEvent(key_event, key_event.key_code(), down, up); |
+ void SendActivateStickyKeyPattern(ui::EventProcessor* dispatcher, |
+ ui::KeyboardCode key_code) { |
+ scoped_ptr<ui::KeyEvent> ev; |
+ ev.reset(GenerateKey(true, key_code)); |
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get()); |
+ CHECK(!details.dispatcher_destroyed); |
+ ev.reset(GenerateKey(false, key_code)); |
+ details = dispatcher->OnEventFromSource(ev.get()); |
+ CHECK(!details.dispatcher_destroyed); |
} |
- int HandleKeyEventForDownFlags(const ui::KeyEvent& key_event, |
- StickyKeysHandler* handler) { |
- bool released = false; |
- int down = 0; |
- handler->HandleKeyEvent(key_event, key_event.key_code(), &down, &released); |
- return down; |
- } |
- |
aura::Window* target() { return target_; } |
private: |
@@ -204,7 +318,9 @@ |
TEST_F(StickyKeysTest, BasicOneshotScenarioTest) { |
scoped_ptr<ui::KeyEvent> ev; |
- StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
@@ -212,42 +328,42 @@ |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A)); |
- bool released = false; |
- int mod_down_flags = 0; |
- HandleKeyEvent(*ev.get(), &sticky_key, &mod_down_flags, &released); |
+ ev.reset(GenerateKey(true, ui::VKEY_A)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ |
// Next keyboard event is shift modified. |
- EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN); |
- // Modifier release notification happens. |
- EXPECT_TRUE(released); |
+ EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A)); |
- released = false; |
- mod_down_flags = 0; |
- HandleKeyEvent(*ev.get(), &sticky_key, &mod_down_flags, &released); |
+ ev.reset(GenerateKey(false, ui::VKEY_A)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- // Making sure Shift up keyboard event is available. |
- scoped_ptr<ui::Event> up_event; |
- ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event)); |
- EXPECT_TRUE(up_event.get()); |
- EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type()); |
+ // Making sure Shift up keyboard event is dispatched. |
+ ASSERT_EQ(2U, mock_delegate->GetEventCount()); |
+ EXPECT_EQ(ui::ET_KEY_PRESSED, mock_delegate->GetEvent(0)->type()); |
+ EXPECT_EQ(ui::VKEY_A, |
+ static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(0)) |
+ ->key_code()); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); |
EXPECT_EQ(ui::VKEY_SHIFT, |
- static_cast<const ui::KeyEvent*>(up_event.get())->key_code()); |
+ static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) |
+ ->key_code()); |
// Enabled state is one shot, so next key event should not be shift modified. |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_FALSE(mod_down_flags & ui::EF_SHIFT_DOWN); |
+ ev.reset(GenerateKey(true, ui::VKEY_A)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_FALSE(mod_down_flags & ui::EF_SHIFT_DOWN); |
+ ev.reset(GenerateKey(false, ui::VKEY_A)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_FALSE(ev->flags() & ui::EF_SHIFT_DOWN); |
} |
TEST_F(StickyKeysTest, BasicLockedScenarioTest) { |
scoped_ptr<ui::KeyEvent> ev; |
- StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
@@ -260,24 +376,24 @@ |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
// All keyboard events including keyUp become shift modified. |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_A)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN); |
+ ev.reset(GenerateKey(true, ui::VKEY_A)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_A)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN); |
+ ev.reset(GenerateKey(false, ui::VKEY_A)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); |
// Locked state keeps after normal keyboard event. |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_B)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN); |
+ ev.reset(GenerateKey(true, ui::VKEY_B)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_B)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_SHIFT_DOWN); |
+ ev.reset(GenerateKey(false, ui::VKEY_B)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_SHIFT_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
@@ -288,163 +404,146 @@ |
TEST_F(StickyKeysTest, NonTargetModifierTest) { |
scoped_ptr<ui::KeyEvent> ev; |
- StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_SHIFT_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Non target modifier key does not affect internal state |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(true, ui::VKEY_MENU)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(false, ui::VKEY_MENU)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
// Non target modifier key does not affect internal state |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(true, ui::VKEY_MENU)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(false, ui::VKEY_MENU)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_SHIFT); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
// Non target modifier key does not affect internal state |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_MENU)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(true, ui::VKEY_MENU)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_MENU)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(false, ui::VKEY_MENU)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
} |
TEST_F(StickyKeysTest, NormalShortcutTest) { |
// Sticky keys should not be enabled if we perform a normal shortcut. |
scoped_ptr<ui::KeyEvent> ev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Perform ctrl+n shortcut. |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_N)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
+ ev.reset(GenerateKey(true, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ ev.reset(GenerateKey(true, ui::VKEY_N)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ ev.reset(GenerateKey(false, ui::VKEY_N)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
// Sticky keys should not be enabled afterwards. |
+ ev.reset(GenerateKey(false, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
- |
- // Perform ctrl+n shortcut, releasing ctrl first. |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- ev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- ev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_N)); |
- mod_down_flags = HandleKeyEventForDownFlags(*ev.get(), &sticky_key); |
- |
- // Sticky keys should not be enabled afterwards. |
- EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
} |
TEST_F(StickyKeysTest, NormalModifiedClickTest) { |
scoped_ptr<ui::KeyEvent> kev; |
scoped_ptr<ui::MouseEvent> mev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Perform ctrl+click. |
- kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
- mev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED)); |
- bool released = false; |
- sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released); |
- mev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED)); |
- sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released); |
+ kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
+ mev.reset(GenerateMouseEvent(true)); |
+ sticky_key.HandleMouseEvent(mev.get()); |
+ mev.reset(GenerateMouseEvent(false)); |
+ sticky_key.HandleMouseEvent(mev.get()); |
// Sticky keys should not be enabled afterwards. |
- kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL)); |
- mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
+ kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
} |
TEST_F(StickyKeysTest, MouseMovedModifierTest) { |
scoped_ptr<ui::KeyEvent> kev; |
scoped_ptr<ui::MouseEvent> mev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Press ctrl and handle mouse move events. |
- kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
+ kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(0, 0))); |
- bool released = false; |
- sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleMouseEvent(mev.get()); |
mev.reset(GenerateSynthesizedMouseMoveEvent(gfx::Point(100, 100))); |
- sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleMouseEvent(mev.get()); |
// Sticky keys should be enabled afterwards. |
- kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL)); |
- mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
+ kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
} |
TEST_F(StickyKeysTest, NormalModifiedScrollTest) { |
scoped_ptr<ui::KeyEvent> kev; |
scoped_ptr<ui::ScrollEvent> sev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Perform ctrl+scroll. |
- kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
+ kev.reset(GenerateKey(true, ui::VKEY_CONTROL)); |
sev.reset(GenerateFlingScrollEvent(0, true)); |
- bool released = false; |
- sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(sev.get()); |
sev.reset(GenerateScrollEvent(10)); |
- sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(sev.get()); |
sev.reset(GenerateFlingScrollEvent(10, false)); |
- sticky_key.HandleScrollEvent(*sev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(sev.get()); |
// Sticky keys should not be enabled afterwards. |
- kev.reset(GenerateKey(ui::ET_KEY_RELEASED, ui::VKEY_CONTROL)); |
- mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
+ kev.reset(GenerateKey(false, ui::VKEY_CONTROL)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- EXPECT_EQ(ui::EF_NONE, mod_down_flags); |
} |
TEST_F(StickyKeysTest, MouseEventOneshot) { |
scoped_ptr<ui::MouseEvent> ev; |
scoped_ptr<ui::KeyEvent> kev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); |
@@ -452,47 +551,40 @@ |
// We should still be in the ENABLED state until we get the mouse |
// release event. |
- ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED)); |
- bool released = false; |
- int mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ ev.reset(GenerateMouseEvent(true)); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ ev.reset(GenerateMouseEvent(false)); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Making sure modifier key release event is dispatched in the right order. |
- EXPECT_TRUE(released); |
- scoped_ptr<ui::Event> up_event; |
- ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event)); |
- EXPECT_TRUE(up_event.get()); |
- EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type()); |
+ ASSERT_EQ(2u, mock_delegate->GetEventCount()); |
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, mock_delegate->GetEvent(0)->type()); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); |
EXPECT_EQ(ui::VKEY_CONTROL, |
- static_cast<const ui::KeyEvent*>(up_event.get())->key_code()); |
+ static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) |
+ ->key_code()); |
// Enabled state is one shot, so next click should not be control modified. |
- ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ ev.reset(GenerateMouseEvent(true)); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); |
- ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ ev.reset(GenerateMouseEvent(false)); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); |
} |
TEST_F(StickyKeysTest, MouseEventLocked) { |
scoped_ptr<ui::MouseEvent> ev; |
scoped_ptr<ui::KeyEvent> kev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
@@ -504,44 +596,35 @@ |
// Mouse events should not disable locked mode. |
for (int i = 0; i < 3; ++i) { |
- bool released = false; |
- int mod_down_flags = 0; |
- ev.reset(GenerateMouseEvent(ui::ET_MOUSE_PRESSED)); |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
- ev.reset(GenerateMouseEvent(ui::ET_MOUSE_RELEASED)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ ev.reset(GenerateMouseEvent(true)); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
+ ev.reset(GenerateMouseEvent(false)); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
} |
// Test with mouse wheel. |
for (int i = 0; i < 3; ++i) { |
- bool released = false; |
- int mod_down_flags = 0; |
ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleMouseEvent(ev.get()); |
ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
} |
// Test mixed case with mouse events and key events. |
ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); |
- bool released = false; |
- int mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
- kev.reset(GenerateKey(ui::ET_KEY_PRESSED, ui::VKEY_N)); |
- mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
- mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleMouseEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
+ kev.reset(GenerateKey(true, ui::VKEY_N)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
+ EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); |
+ kev.reset(GenerateKey(false, ui::VKEY_N)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
+ EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
} |
@@ -549,10 +632,14 @@ |
TEST_F(StickyKeysTest, ScrollEventOneshot) { |
scoped_ptr<ui::ScrollEvent> ev; |
scoped_ptr<ui::KeyEvent> kev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
int scroll_deltas[] = {-10, 10}; |
for (int i = 0; i < 2; ++i) { |
+ mock_delegate->ClearEvents(); |
+ |
// Enable sticky keys. |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); |
@@ -561,44 +648,42 @@ |
// Test a scroll sequence. Sticky keys should only be disabled at the end |
// of the scroll sequence. Fling cancel event starts the scroll sequence. |
ev.reset(GenerateFlingScrollEvent(0, true)); |
- bool released = false; |
- int mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
// Scrolls should all be modified but not disable sticky keys. |
for (int j = 0; j < 3; ++j) { |
ev.reset(GenerateScrollEvent(scroll_deltas[i])); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
} |
// Fling start event ends scroll sequence. |
ev.reset(GenerateFlingScrollEvent(scroll_deltas[i], false)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- scoped_ptr<ui::Event> up_event; |
- EXPECT_TRUE(released); |
- ASSERT_EQ(0, sticky_key.GetModifierUpEvent(&up_event)); |
- EXPECT_TRUE(up_event.get()); |
- EXPECT_EQ(ui::ET_KEY_RELEASED, up_event->type()); |
+ ASSERT_EQ(2U, mock_delegate->GetEventCount()); |
+ EXPECT_EQ(ui::ET_SCROLL_FLING_START, mock_delegate->GetEvent(0)->type()); |
+ EXPECT_FLOAT_EQ(scroll_deltas[i], |
+ static_cast<const ui::ScrollEvent*>( |
+ mock_delegate->GetEvent(0))->y_offset()); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, mock_delegate->GetEvent(1)->type()); |
EXPECT_EQ(ui::VKEY_CONTROL, |
- static_cast<const ui::KeyEvent*>(up_event.get())->key_code()); |
+ static_cast<const ui::KeyEvent*>(mock_delegate->GetEvent(1)) |
+ ->key_code()); |
} |
} |
TEST_F(StickyKeysTest, ScrollDirectionChanged) { |
scoped_ptr<ui::ScrollEvent> ev; |
scoped_ptr<ui::KeyEvent> kev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
// Test direction change with both boundary value and negative value. |
const int direction_change_values[2] = {0, -10}; |
@@ -608,26 +693,21 @@ |
// Fling cancel starts scroll sequence. |
ev.reset(GenerateFlingScrollEvent(0, true)); |
- bool released = false; |
- int mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(ev.get()); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
// Test that changing directions in a scroll sequence will |
// return sticky keys to DISABLED state. |
for (int j = 0; j < 3; ++j) { |
ev.reset(GenerateScrollEvent(10)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
} |
ev.reset(GenerateScrollEvent(direction_change_values[i])); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_FALSE(ev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
} |
} |
@@ -635,7 +715,9 @@ |
TEST_F(StickyKeysTest, ScrollEventLocked) { |
scoped_ptr<ui::ScrollEvent> ev; |
scoped_ptr<ui::KeyEvent> kev; |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
// Lock sticky keys. |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); |
@@ -646,45 +728,63 @@ |
for (int i = 0; i < 5; ++i) { |
// Fling cancel starts scroll sequence. |
ev.reset(GenerateFlingScrollEvent(0, true)); |
- bool released = false; |
- int mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(ev.get()); |
ev.reset(GenerateScrollEvent(10)); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
ev.reset(GenerateScrollEvent(-10)); |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ sticky_key.HandleScrollEvent(ev.get()); |
+ EXPECT_TRUE(ev->flags() & ui::EF_CONTROL_DOWN); |
// Fling start ends scroll sequence. |
ev.reset(GenerateFlingScrollEvent(-10, false)); |
- sticky_key.HandleScrollEvent(*ev.get(), &mod_down_flags, &released); |
+ sticky_key.HandleScrollEvent(ev.get()); |
} |
EXPECT_EQ(STICKY_KEY_STATE_LOCKED, sticky_key.current_state()); |
} |
+TEST_F(StickyKeysTest, EventTargetDestroyed) { |
+ scoped_ptr<ui::KeyEvent> ev; |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
+ |
+ target()->Focus(); |
+ |
+ // Go into ENABLED state. |
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
+ SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); |
+ EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
+ |
+ // CTRL+J is a special shortcut that will destroy the event target. |
+ ev.reset(GenerateKey(true, ui::VKEY_J)); |
+ sticky_key.HandleKeyEvent(ev.get()); |
+ EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
+ EXPECT_FALSE(target()); |
+} |
+ |
TEST_F(StickyKeysTest, SynthesizedEvents) { |
// Non-native, internally generated events should be properly handled |
// by sticky keys. |
- StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN); |
+ MockStickyKeysHandlerDelegate* mock_delegate = |
+ new MockStickyKeysHandlerDelegate(this); |
+ StickyKeysHandler sticky_key(ui::EF_CONTROL_DOWN, mock_delegate); |
// Test non-native key events. |
scoped_ptr<ui::KeyEvent> kev; |
SendActivateStickyKeyPattern(&sticky_key, ui::VKEY_CONTROL); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- kev.reset(GenerateSynthesizedKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_K)); |
- int mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
+ EXPECT_TRUE(kev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
- kev.reset(GenerateSynthesizedKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_K)); |
- mod_down_flags = HandleKeyEventForDownFlags(*kev.get(), &sticky_key); |
- EXPECT_FALSE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ kev.reset(GenerateSynthesizedKeyEvent(false, ui::VKEY_K)); |
+ sticky_key.HandleKeyEvent(kev.get()); |
+ EXPECT_FALSE(kev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
// Test non-native mouse events. |
@@ -692,21 +792,216 @@ |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
scoped_ptr<ui::MouseEvent> mev; |
- mev.reset(GenerateSynthesizedMouseClickEvent(ui::ET_MOUSE_PRESSED, |
- gfx::Point(0, 0))); |
- bool released = false; |
- sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
+ mev.reset(GenerateSynthesizedMouseClickEvent(true, gfx::Point(0, 0))); |
+ sticky_key.HandleMouseEvent(mev.get()); |
+ EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_ENABLED, sticky_key.current_state()); |
- mev.reset(GenerateSynthesizedMouseClickEvent(ui::ET_MOUSE_RELEASED, |
- gfx::Point(0, 0))); |
- released = false; |
- mod_down_flags = 0; |
- sticky_key.HandleMouseEvent(*mev.get(), &mod_down_flags, &released); |
- EXPECT_TRUE(mod_down_flags & ui::EF_CONTROL_DOWN); |
- EXPECT_TRUE(released); |
+ mev.reset(GenerateSynthesizedMouseClickEvent(false, gfx::Point(0, 0))); |
+ sticky_key.HandleMouseEvent(mev.get()); |
+ EXPECT_TRUE(mev->flags() & ui::EF_CONTROL_DOWN); |
EXPECT_EQ(STICKY_KEY_STATE_DISABLED, sticky_key.current_state()); |
} |
+TEST_F(StickyKeysTest, KeyEventDispatchImpl) { |
+ // Test the actual key event dispatch implementation. |
+ EventBuffer buffer; |
+ ScopedVector<ui::Event> events; |
+ ui::EventProcessor* dispatcher = |
+ Shell::GetPrimaryRootWindow()->GetHost()->event_processor(); |
+ Shell::GetInstance()->AddPreTargetHandler(&buffer); |
+ Shell::GetInstance()->sticky_keys_controller()->Enable(true); |
+ |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ scoped_ptr<ui::KeyEvent> ev; |
+ buffer.PopEvents(&events); |
+ |
+ // Test key press event is correctly modified and modifier release |
+ // event is sent. |
+ ev.reset(GenerateKey(true, ui::VKEY_C)); |
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get()); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type()); |
+ EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ // Test key release event is not modified. |
+ ev.reset(GenerateKey(false, ui::VKEY_C)); |
+ details = dispatcher->OnEventFromSource(ev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(1u, events.size()); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type()); |
+ EXPECT_EQ(ui::VKEY_C, |
+ static_cast<ui::KeyEvent*>(events[0])->key_code()); |
+ EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ |
+ // Test that synthesized key events are dispatched correctly. |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ buffer.PopEvents(&events); |
+ scoped_ptr<ui::KeyEvent> kev; |
+ kev.reset(GenerateSynthesizedKeyEvent(true, ui::VKEY_K)); |
+ details = dispatcher->OnEventFromSource(kev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type()); |
+ EXPECT_EQ(ui::VKEY_K, static_cast<ui::KeyEvent*>(events[0])->key_code()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ Shell::GetInstance()->RemovePreTargetHandler(&buffer); |
+} |
+ |
+class StickyKeysMouseDispatchTest |
+ : public StickyKeysTest, |
+ public ::testing::WithParamInterface<int> { |
+}; |
+ |
+TEST_P(StickyKeysMouseDispatchTest, MouseEventDispatchImpl) { |
+ int scale_factor = GetParam(); |
+ std::ostringstream display_specs; |
+ display_specs << "1280x1024*" << scale_factor; |
+ UpdateDisplay(display_specs.str()); |
+ |
+ EventBuffer buffer; |
+ ScopedVector<ui::Event> events; |
+ ui::EventProcessor* dispatcher = |
+ Shell::GetPrimaryRootWindow()->GetHost()->event_processor(); |
+ Shell::GetInstance()->AddPreTargetHandler(&buffer); |
+ Shell::GetInstance()->sticky_keys_controller()->Enable(true); |
+ |
+ scoped_ptr<ui::MouseEvent> ev; |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ buffer.PopEvents(&events); |
+ |
+ // Test mouse press event is correctly modified and has correct DIP location. |
+ gfx::Point physical_location(400, 400); |
+ gfx::Point dip_location(physical_location.x() / scale_factor, |
+ physical_location.y() / scale_factor); |
+ ev.reset(GenerateMouseEventAt(true, physical_location)); |
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get()); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(1u, events.size()); |
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(dip_location.ToString(), |
+ static_cast<ui::MouseEvent*>(events[0])->location().ToString()); |
+ |
+ // Test mouse release event is correctly modified and modifier release |
+ // event is sent. The mouse event should have the correct DIP location. |
+ ev.reset(GenerateMouseEventAt(false, physical_location)); |
+ details = dispatcher->OnEventFromSource(ev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(dip_location.ToString(), |
+ static_cast<ui::MouseEvent*>(events[0])->location().ToString()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ // Test synthesized mouse events are dispatched correctly. |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ buffer.PopEvents(&events); |
+ ev.reset(GenerateSynthesizedMouseClickEvent(false, physical_location)); |
+ details = dispatcher->OnEventFromSource(ev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(dip_location.ToString(), |
+ static_cast<ui::MouseEvent*>(events[0])->location().ToString()); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ Shell::GetInstance()->RemovePreTargetHandler(&buffer); |
+} |
+ |
+TEST_P(StickyKeysMouseDispatchTest, MouseWheelEventDispatchImpl) { |
+ int scale_factor = GetParam(); |
+ std::ostringstream display_specs; |
+ display_specs << "1280x1024*" << scale_factor; |
+ UpdateDisplay(display_specs.str()); |
+ |
+ // Test the actual mouse wheel event dispatch implementation. |
+ EventBuffer buffer; |
+ ScopedVector<ui::Event> events; |
+ ui::EventProcessor* dispatcher = |
+ Shell::GetPrimaryRootWindow()->GetHost()->event_processor(); |
+ Shell::GetInstance()->AddPreTargetHandler(&buffer); |
+ Shell::GetInstance()->sticky_keys_controller()->Enable(true); |
+ |
+ scoped_ptr<ui::MouseWheelEvent> ev; |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ buffer.PopEvents(&events); |
+ |
+ // Test positive mouse wheel event is correctly modified and modifier release |
+ // event is sent. |
+ ev.reset(GenerateMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); |
+ ui::EventDispatchDetails details = dispatcher->OnEventFromSource(ev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_TRUE(events[0]->IsMouseWheelEvent()); |
+ EXPECT_EQ(ui::MouseWheelEvent::kWheelDelta / scale_factor, |
+ static_cast<ui::MouseWheelEvent*>(events[0])->y_offset()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ // Test negative mouse wheel event is correctly modified and modifier release |
+ // event is sent. |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ buffer.PopEvents(&events); |
+ |
+ ev.reset(GenerateMouseWheelEvent(-ui::MouseWheelEvent::kWheelDelta)); |
+ details = dispatcher->OnEventFromSource(ev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_TRUE(events[0]->IsMouseWheelEvent()); |
+ EXPECT_EQ(-ui::MouseWheelEvent::kWheelDelta / scale_factor, |
+ static_cast<ui::MouseWheelEvent*>(events[0])->y_offset()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ // Test synthesized mouse wheel events are dispatched correctly. |
+ SendActivateStickyKeyPattern(dispatcher, ui::VKEY_CONTROL); |
+ buffer.PopEvents(&events); |
+ ev.reset( |
+ GenerateSynthesizedMouseWheelEvent(ui::MouseWheelEvent::kWheelDelta)); |
+ details = dispatcher->OnEventFromSource(ev.get()); |
+ ASSERT_FALSE(details.dispatcher_destroyed); |
+ buffer.PopEvents(&events); |
+ EXPECT_EQ(2u, events.size()); |
+ EXPECT_TRUE(events[0]->IsMouseWheelEvent()); |
+ EXPECT_EQ(ui::MouseWheelEvent::kWheelDelta / scale_factor, |
+ static_cast<ui::MouseWheelEvent*>(events[0])->y_offset()); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN); |
+ EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type()); |
+ EXPECT_EQ(ui::VKEY_CONTROL, |
+ static_cast<ui::KeyEvent*>(events[1])->key_code()); |
+ |
+ Shell::GetInstance()->RemovePreTargetHandler(&buffer); |
+} |
+ |
+INSTANTIATE_TEST_CASE_P(DPIScaleFactors, |
+ StickyKeysMouseDispatchTest, |
+ ::testing::Values(1, 2)); |
+ |
} // namespace ash |