Index: chrome/browser/chromeos/system_key_event_listener_browsertest.cc |
diff --git a/chrome/browser/chromeos/system_key_event_listener_browsertest.cc b/chrome/browser/chromeos/system_key_event_listener_browsertest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..08508feca8c89b7cb966b031eb2870b022b3f197 |
--- /dev/null |
+++ b/chrome/browser/chromeos/system_key_event_listener_browsertest.cc |
@@ -0,0 +1,209 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <X11/keysym.h> |
+ |
+#include <cstring> |
+ |
+#include "base/message_loop.h" |
+#include "chrome/browser/chromeos/input_method/input_method_manager.h" |
+#include "chrome/browser/chromeos/input_method/xkeyboard.h" |
+#include "chrome/browser/chromeos/system_key_event_listener.h" |
+#include "chrome/test/base/in_process_browser_test.h" |
+#include "chrome/test/base/ui_test_utils.h" |
+#include "ui/base/x/x11_util.h" |
+ |
+#include <X11/Xlib.h> // should be here since it #defines lots of macros. |
+ |
+namespace chromeos { |
+ |
+class SystemKeyEventListenerTest : public InProcessBrowserTest { |
+ public: |
+ SystemKeyEventListenerTest() |
+ : manager_(input_method::InputMethodManager::GetInstance()), |
+ initial_caps_lock_state_(manager_->GetXKeyboard()->CapsLockIsEnabled()), |
+ num_lock_mask_(manager_->GetXKeyboard()->GetNumLockMask()), |
+ listener_(NULL) { |
+ CHECK(num_lock_mask_); |
+ } |
+ |
+ protected: |
+ class CapsLockObserver : public SystemKeyEventListener::CapsLockObserver { |
+ public: |
+ CapsLockObserver() { |
+ } |
+ |
+ private: |
+ virtual void OnCapsLockChange(bool enabled) { |
+ MessageLoopForUI::current()->Quit(); |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CapsLockObserver); |
+ }; |
+ |
+ // Start listening for X events. |
+ virtual void SetUpOnMainThread() OVERRIDE { |
+ SystemKeyEventListener::Initialize(); |
+ listener_ = SystemKeyEventListener::GetInstance(); |
+ } |
+ |
+ // Stop listening for X events. |
+ virtual void CleanUpOnMainThread() OVERRIDE { |
+ SystemKeyEventListener::Shutdown(); |
+ listener_ = NULL; |
+ MessageLoopForUI::current()->RunAllPending(); |
+ } |
+ |
+ // Feed a key event to SystemKeyEventListener. Returnes true if the event is |
+ // consumed by the listener. |
+ bool SendFakeEvent(KeySym keysym, int modifiers, bool is_press) { |
+ scoped_ptr<XEvent> event(SynthesizeKeyEvent(keysym, modifiers, is_press)); |
+ // It seems that the Xvfb fake X server in build bots ignores a key event |
+ // synthesized by XTestFakeKeyEvent() or XSendEvent(). We just call |
+ // ProcessedXEvent() instead. |
+ return listener_->ProcessedXEvent(event.get()); |
+ } |
+ |
+ input_method::InputMethodManager* manager_; |
+ const bool initial_caps_lock_state_; |
+ const unsigned int num_lock_mask_; |
+ SystemKeyEventListener* listener_; |
+ CapsLockObserver observer_; |
+ |
+ private: |
+ XEvent* SynthesizeKeyEvent(KeySym keysym, int modifiers, bool is_press) { |
+ XEvent* event = new XEvent; |
+ std::memset(event, 0, sizeof(XEvent)); |
+ |
+ Display* display = ui::GetXDisplay(); |
+ Window focused; |
+ int dummy; |
+ XGetInputFocus(display, &focused, &dummy); |
+ |
+ XKeyEvent* key_event = &event->xkey; |
+ key_event->display = display; |
+ key_event->keycode = XKeysymToKeycode(display, keysym); |
+ key_event->root = ui::GetX11RootWindow(); |
+ key_event->same_screen = True; |
+ key_event->send_event = False; |
+ key_event->state = modifiers; |
+ key_event->subwindow = None; |
+ key_event->time = CurrentTime; |
+ key_event->type = is_press ? KeyPress : KeyRelease; |
+ key_event->window = focused; |
+ key_event->x = key_event->x_root = key_event->y = key_event->y_root = 1; |
+ |
+ return event; |
+ } |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SystemKeyEventListenerTest); |
+}; |
+ |
+// Tests if the current Caps Lock status is toggled and OnCapsLockChange method |
+// is called when both Shift keys are pressed. |
+IN_PROC_BROWSER_TEST_F(SystemKeyEventListenerTest, TestCapsLock) { |
+ listener_->AddCapsLockObserver(&observer_); |
+ |
+ // Press both Shift keys. Note that ProcessedXEvent() returns false even when |
+ // the second Shift key is pressed. |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, 0, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask, false)); |
+ // Enter a new message loop and wait for OnCapsLockChange() to be called. |
+ ui_test_utils::RunMessageLoop(); |
+ // Make sure the Caps Lock status is actually changed. |
+ EXPECT_EQ( |
+ !initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ // Test all other Shift_L/R combinations. |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, 0, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, 0, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ !initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, 0, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ // Restore the original state. |
+ listener_->RemoveCapsLockObserver(&observer_); |
+ manager_->GetXKeyboard()->SetCapsLockEnabled(initial_caps_lock_state_); |
+} |
+ |
+// Tests the same above, but with Num Lock. Pressing both Shift keys should |
+// toggle Caps Lock even when Num Lock is enabled. See crosbug.com/23067. |
+IN_PROC_BROWSER_TEST_F(SystemKeyEventListenerTest, TestCapsLockWithNumLock) { |
+ listener_->AddCapsLockObserver(&observer_); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | num_lock_mask_, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | num_lock_mask_, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ !initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | num_lock_mask_, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | num_lock_mask_, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | num_lock_mask_, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | num_lock_mask_, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ !initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | num_lock_mask_, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | num_lock_mask_, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | num_lock_mask_, false)); |
+ ui_test_utils::RunMessageLoop(); |
+ EXPECT_EQ( |
+ initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ listener_->RemoveCapsLockObserver(&observer_); |
+ manager_->GetXKeyboard()->SetCapsLockEnabled(initial_caps_lock_state_); |
+} |
+ |
+// Test pressing Shift_L+R with an another modifier like Control. Caps Lock |
+// status should not be changed this time. |
+IN_PROC_BROWSER_TEST_F(SystemKeyEventListenerTest, TestCapsLockWithControl) { |
+ listener_->AddCapsLockObserver(&observer_); |
+ |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ControlMask, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | ControlMask, true)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_R, ShiftMask | ControlMask, false)); |
+ EXPECT_FALSE(SendFakeEvent(XK_Shift_L, ShiftMask | ControlMask, false)); |
+ EXPECT_EQ( |
+ initial_caps_lock_state_, manager_->GetXKeyboard()->CapsLockIsEnabled()); |
+ |
+ listener_->RemoveCapsLockObserver(&observer_); |
+ manager_->GetXKeyboard()->SetCapsLockEnabled(initial_caps_lock_state_); |
+} |
+ |
+// TODO(yusukes): Test IME hot keys. |
+ |
+} // namespace chromeos |