1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/events/event_rewriter.h"
6
7#include <vector>
8
9#include "ash/shell.h"
10#include "ash/sticky_keys/sticky_keys_controller.h"
11#include "ash/sticky_keys/sticky_keys_overlay.h"
12#include "ash/test/ash_test_base.h"
13#include "ash/wm/window_state.h"
14#include "base/basictypes.h"
15#include "base/command_line.h"
16#include "base/prefs/pref_member.h"
17#include "base/strings/stringprintf.h"
18#include "chrome/browser/chromeos/input_method/input_method_configuration.h"
19#include "chrome/browser/chromeos/input_method/mock_input_method_manager.h"
20#include "chrome/browser/chromeos/login/users/mock_user_manager.h"
21#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
22#include "chrome/browser/chromeos/preferences.h"
23#include "chrome/common/pref_names.h"
24#include "chrome/test/base/testing_pref_service_syncable.h"
25#include "chromeos/chromeos_switches.h"
26#include "chromeos/ime/fake_ime_keyboard.h"
27#include "testing/gtest/include/gtest/gtest.h"
28#include "ui/aura/window.h"
29#include "ui/aura/window_tree_host.h"
30#include "ui/events/event.h"
31#include "ui/events/event_rewriter.h"
32#include "ui/events/test/events_test_utils.h"
33#include "ui/events/test/test_event_processor.h"
34
35#if defined(USE_X11)
36#include <X11/keysym.h>
37
38#include "ui/events/event_utils.h"
39#include "ui/events/test/events_test_utils_x11.h"
40#include "ui/events/x/touch_factory_x11.h"
41#include "ui/gfx/x/x11_types.h"
42#endif
43
44namespace {
45
46// The device id of the test touchpad device.
47const unsigned int kTouchPadDeviceId = 1;
48const int kKeyboardDeviceId = 2;
49const int kMasterKeyboardDeviceId = 3;
50
51std::string GetExpectedResultAsString(ui::KeyboardCode ui_keycode,
52                                      int ui_flags,
53                                      ui::EventType ui_type) {
54  return base::StringPrintf("ui_keycode=0x%X ui_flags=0x%X ui_type=%d",
55                            ui_keycode,
56                            ui_flags & ~ui::EF_IS_REPEAT,
57                            ui_type);
58}
59
60std::string GetKeyEventAsString(const ui::KeyEvent& keyevent) {
61  return GetExpectedResultAsString(
62      keyevent.key_code(), keyevent.flags(), keyevent.type());
63}
64
65std::string GetRewrittenEventAsString(chromeos::EventRewriter* rewriter,
66                                      ui::KeyboardCode ui_keycode,
67                                      int ui_flags,
68                                      ui::EventType ui_type) {
69  const ui::KeyEvent event(ui_type, ui_keycode, ui_flags);
70  scoped_ptr<ui::Event> new_event;
71  rewriter->RewriteEvent(event, &new_event);
72  if (new_event)
73    return GetKeyEventAsString(
74        static_cast<const ui::KeyEvent&>(*new_event.get()));
75  return GetKeyEventAsString(event);
76}
77
78// Table entry for simple single key event rewriting tests.
79struct KeyTestCase {
80  enum {
81    // Test types:
82    TEST_VKEY = 1 << 0,  // Test ui::KeyEvent with no native event
83    TEST_X11  = 1 << 1,  // Test ui::KeyEvent with native XKeyEvent
84    TEST_ALL  = TEST_VKEY|TEST_X11,
85    // Special test flags:
86    NUMPAD    = 1 << 8,  // Set EF_NUMPAD_KEY on native-based event, because
87                         // |XKeysymForWindowsKeyCode()| can not distinguish
88                         // between pairs like XK_Insert and XK_KP_Insert.
89  };
90  int test;
91  ui::EventType type;
92  struct {
93    ui::KeyboardCode key_code;
94    int flags;
95  } input, expected;
96};
97
98#if defined(USE_X11)
99// Check rewriting of an X11-based key event.
100void CheckX11KeyTestCase(const std::string& expected,
101                         chromeos::EventRewriter* rewriter,
102                         const KeyTestCase& test,
103                         XEvent* xevent) {
104  ui::KeyEvent xkey_event(xevent);
105  if (test.test & KeyTestCase::NUMPAD)
106    xkey_event.set_flags(xkey_event.flags() | ui::EF_NUMPAD_KEY);
107  // Verify that the X11-based key event is as expected.
108  EXPECT_EQ(GetExpectedResultAsString(
109                     test.input.key_code, test.input.flags, test.type),
110            GetKeyEventAsString(xkey_event));
111  // Rewrite the event and check the result.
112  scoped_ptr<ui::Event> new_event;
113  rewriter->RewriteEvent(xkey_event, &new_event);
114  ui::KeyEvent& rewritten_key_event =
115      new_event ? *static_cast<ui::KeyEvent*>(new_event.get()) : xkey_event;
116  EXPECT_EQ(expected, GetKeyEventAsString(rewritten_key_event));
117  if ((rewritten_key_event.key_code() != ui::VKEY_UNKNOWN) &&
118      (rewritten_key_event.native_event()->xkey.keycode != 0)) {
119    // Build a new ui::KeyEvent from the rewritten native component,
120    // and check that it also matches the rewritten event.
121    EXPECT_TRUE(rewritten_key_event.native_event());
122    ui::KeyEvent from_native_event(rewritten_key_event.native_event());
123    EXPECT_EQ(expected, GetKeyEventAsString(from_native_event));
124  }
125}
126#endif
127
128// Tests a single stateless key rewrite operation.
129// |i| is a an identifying number to locate failing tests in the tables.
130void CheckKeyTestCase(chromeos::EventRewriter* rewriter,
131                      const KeyTestCase& test) {
132  std::string expected =
133      GetExpectedResultAsString(
134               test.expected.key_code, test.expected.flags, test.type);
135
136  if (test.test & KeyTestCase::TEST_VKEY) {
137    // Check rewriting of a non-native-based key event.
138    EXPECT_EQ(
139        expected,
140        GetRewrittenEventAsString(
141                 rewriter, test.input.key_code, test.input.flags, test.type));
142  }
143
144#if defined(USE_X11)
145  if (test.test & KeyTestCase::TEST_X11) {
146    ui::ScopedXI2Event xev;
147    // Test an XKeyEvent.
148    xev.InitKeyEvent(test.type, test.input.key_code, test.input.flags);
149    XEvent* xevent = xev;
150    DCHECK((xevent->type == KeyPress) || (xevent->type == KeyRelease));
151    if (xevent->xkey.keycode)
152      CheckX11KeyTestCase(expected, rewriter, test, xevent);
153    // Test an XI2 GenericEvent.
154    xev.InitGenericKeyEvent(kMasterKeyboardDeviceId,
155                            kKeyboardDeviceId,
156                            test.type,
157                            test.input.key_code,
158                            test.input.flags);
159    xevent = xev;
160    DCHECK(xevent->type == GenericEvent);
161    XIDeviceEvent* xievent = static_cast<XIDeviceEvent*>(xevent->xcookie.data);
162    DCHECK((xievent->evtype == XI_KeyPress) ||
163           (xievent->evtype == XI_KeyRelease));
164    if (xievent->detail)
165      CheckX11KeyTestCase(expected, rewriter, test, xevent);
166  }
167#endif
168}
169
170// Table entry for simple single function key event rewriting tests.
171struct FunctionKeyTestCase {
172  ui::EventType type;
173  struct {
174    ui::KeyboardCode key_code;
175    int flags;
176  } input, vkey_expected, native_expected;
177};
178
179// Tests a single stateless function key rewrite operation.
180// |i| is a an identifying number to locate failing tests in the tables.
181// Function key mapping differs from the other key mappings because the
182// EF_FUNCTION_KEY flag is set during ui::KeyEvent construction when passing in
183// a native X11 event and the flag is not set when using other constructors.
184void CheckFunctionKeyTestCase(chromeos::EventRewriter* rewriter,
185                              const FunctionKeyTestCase& test) {
186  std::string vkey_expected =
187      GetExpectedResultAsString(
188          test.vkey_expected.key_code,
189          test.vkey_expected.flags,
190          test.type);
191  // Check rewriting of a non-native-based key event.
192  EXPECT_EQ(
193      vkey_expected,
194      GetRewrittenEventAsString(
195               rewriter, test.input.key_code, test.input.flags, test.type));
196
197#if defined(USE_X11)
198  ui::ScopedXI2Event xev;
199  xev.InitKeyEvent(test.type, test.input.key_code, test.input.flags);
200  XEvent* xevent = xev;
201  if (xevent->xkey.keycode) {
202    ui::KeyEvent xkey_event(xevent);
203    // Rewrite the event and check the result.
204    scoped_ptr<ui::Event> new_event;
205    rewriter->RewriteEvent(xkey_event, &new_event);
206    ui::KeyEvent& rewritten_key_event =
207        new_event ? *static_cast<ui::KeyEvent*>(new_event.get()) : xkey_event;
208    std::string native_expected =
209        GetExpectedResultAsString(
210            test.native_expected.key_code,
211            test.native_expected.flags,
212            test.type);
213    EXPECT_EQ(native_expected, GetKeyEventAsString(rewritten_key_event));
214  }
215#endif
216}
217
218}  // namespace
219
220namespace chromeos {
221
222class EventRewriterTest : public ash::test::AshTestBase {
223 public:
224  EventRewriterTest()
225      : mock_user_manager_(new chromeos::MockUserManager),
226        user_manager_enabler_(mock_user_manager_),
227        input_method_manager_mock_(NULL) {}
228  virtual ~EventRewriterTest() {}
229
230  virtual void SetUp() {
231    // Mocking user manager because the real one needs to be called on UI thread
232    EXPECT_CALL(*mock_user_manager_, IsLoggedInAsGuest())
233        .WillRepeatedly(testing::Return(false));
234    input_method_manager_mock_ =
235        new chromeos::input_method::MockInputMethodManager;
236    chromeos::input_method::InitializeForTesting(
237        input_method_manager_mock_);  // pass ownership
238
239    AshTestBase::SetUp();
240  }
241
242  virtual void TearDown() {
243    AshTestBase::TearDown();
244    // Shutdown() deletes the IME mock object.
245    chromeos::input_method::Shutdown();
246  }
247
248 protected:
249  void TestRewriteNumPadKeys();
250  void TestRewriteNumPadKeysOnAppleKeyboard();
251
252  const ui::MouseEvent* RewriteMouseButtonEvent(
253      chromeos::EventRewriter* rewriter,
254      const ui::MouseEvent& event,
255      scoped_ptr<ui::Event>* new_event) {
256    rewriter->RewriteMouseButtonEventForTesting(event, new_event);
257    return *new_event ? static_cast<const ui::MouseEvent*>(new_event->get())
258                      : &event;
259  }
260
261  chromeos::MockUserManager* mock_user_manager_;  // Not owned.
262  chromeos::ScopedUserManagerEnabler user_manager_enabler_;
263  chromeos::input_method::MockInputMethodManager* input_method_manager_mock_;
264};
265
266TEST_F(EventRewriterTest, TestRewriteCommandToControl) {
267  // First, test with a PC keyboard.
268  TestingPrefServiceSyncable prefs;
269  EventRewriter rewriter(NULL);
270  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
271  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
272  rewriter.set_pref_service_for_testing(&prefs);
273
274  KeyTestCase pc_keyboard_tests[] = {
275      // VKEY_A, Alt modifier.
276      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
277       {ui::VKEY_A, ui::EF_ALT_DOWN},
278       {ui::VKEY_A, ui::EF_ALT_DOWN}},
279
280      // VKEY_A, Win modifier.
281      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
282       {ui::VKEY_A, ui::EF_COMMAND_DOWN},
283       {ui::VKEY_A, ui::EF_COMMAND_DOWN}},
284
285      // VKEY_A, Alt+Win modifier.
286      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
287       {ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
288       {ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN}},
289
290      // VKEY_LWIN (left Windows key), Alt modifier.
291      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
292       {ui::VKEY_LWIN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
293       {ui::VKEY_LWIN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN}},
294
295      // VKEY_RWIN (right Windows key), Alt modifier.
296      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
297       {ui::VKEY_RWIN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
298       {ui::VKEY_RWIN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN}},
299  };
300
301  for (size_t i = 0; i < arraysize(pc_keyboard_tests); ++i) {
302    SCOPED_TRACE(i);
303    CheckKeyTestCase(&rewriter, pc_keyboard_tests[i]);
304  }
305
306  // An Apple keyboard reusing the ID, zero.
307  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
308  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
309
310  KeyTestCase apple_keyboard_tests[] = {
311      // VKEY_A, Alt modifier.
312      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
313       {ui::VKEY_A, ui::EF_ALT_DOWN},
314       {ui::VKEY_A, ui::EF_ALT_DOWN}},
315
316      // VKEY_A, Win modifier.
317      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
318       {ui::VKEY_A, ui::EF_COMMAND_DOWN},
319       {ui::VKEY_A, ui::EF_CONTROL_DOWN}},
320
321      // VKEY_A, Alt+Win modifier.
322      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
323       {ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
324       {ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN}},
325
326      // VKEY_LWIN (left Windows key), Alt modifier.
327      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
328       {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
329       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}},
330
331      // VKEY_RWIN (right Windows key), Alt modifier.
332      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
333       {ui::VKEY_RWIN, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
334       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}},
335  };
336
337  for (size_t i = 0; i < arraysize(apple_keyboard_tests); ++i) {
338    SCOPED_TRACE(i);
339    CheckKeyTestCase(&rewriter, apple_keyboard_tests[i]);
340  }
341}
342
343// For crbug.com/133896.
344TEST_F(EventRewriterTest, TestRewriteCommandToControlWithControlRemapped) {
345  // Remap Control to Alt.
346  TestingPrefServiceSyncable prefs;
347  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
348  IntegerPrefMember control;
349  control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
350  control.SetValue(chromeos::input_method::kAltKey);
351
352  EventRewriter rewriter(NULL);
353  rewriter.set_pref_service_for_testing(&prefs);
354  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
355  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
356
357  KeyTestCase pc_keyboard_tests[] = {// Control should be remapped to Alt.
358                                     {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
359                                      {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN},
360                                      {ui::VKEY_MENU, ui::EF_ALT_DOWN}},
361  };
362
363  for (size_t i = 0; i < arraysize(pc_keyboard_tests); ++i) {
364    SCOPED_TRACE(i);
365    CheckKeyTestCase(&rewriter, pc_keyboard_tests[i]);
366  }
367
368  // An Apple keyboard reusing the ID, zero.
369  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
370  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
371
372  KeyTestCase apple_keyboard_tests[] = {
373      // VKEY_LWIN (left Command key) with  Alt modifier. The remapped Command
374      // key should never be re-remapped to Alt.
375      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
376       {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
377       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}},
378
379      // VKEY_RWIN (right Command key) with  Alt modifier. The remapped Command
380      // key should never be re-remapped to Alt.
381      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
382       {ui::VKEY_RWIN, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
383       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN}},
384  };
385
386  for (size_t i = 0; i < arraysize(apple_keyboard_tests); ++i) {
387    SCOPED_TRACE(i);
388    CheckKeyTestCase(&rewriter, apple_keyboard_tests[i]);
389  }
390}
391
392void EventRewriterTest::TestRewriteNumPadKeys() {
393  TestingPrefServiceSyncable prefs;
394  EventRewriter rewriter(NULL);
395  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
396  rewriter.set_pref_service_for_testing(&prefs);
397
398  KeyTestCase tests[] = {
399      // XK_KP_Insert (= NumPad 0 without Num Lock), no modifier.
400      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
401       {ui::VKEY_INSERT, ui::EF_NUMPAD_KEY},
402       {ui::VKEY_NUMPAD0, ui::EF_NUMPAD_KEY}},
403
404      // XK_KP_Insert (= NumPad 0 without Num Lock), Alt modifier.
405      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
406       {ui::VKEY_INSERT, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
407       {ui::VKEY_NUMPAD0, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
408
409      // XK_KP_Delete (= NumPad . without Num Lock), Alt modifier.
410      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
411       {ui::VKEY_DELETE, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
412       {ui::VKEY_DECIMAL, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
413
414      // XK_KP_End (= NumPad 1 without Num Lock), Alt modifier.
415      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
416       {ui::VKEY_END, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
417       {ui::VKEY_NUMPAD1, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
418
419      // XK_KP_Down (= NumPad 2 without Num Lock), Alt modifier.
420      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
421       {ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
422       {ui::VKEY_NUMPAD2, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
423
424      // XK_KP_Next (= NumPad 3 without Num Lock), Alt modifier.
425      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
426       {ui::VKEY_NEXT, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
427       {ui::VKEY_NUMPAD3, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
428
429      // XK_KP_Left (= NumPad 4 without Num Lock), Alt modifier.
430      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
431       {ui::VKEY_LEFT, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
432       {ui::VKEY_NUMPAD4, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
433
434      // XK_KP_Begin (= NumPad 5 without Num Lock), Alt modifier.
435      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
436       {ui::VKEY_CLEAR, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
437       {ui::VKEY_NUMPAD5, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
438
439      // XK_KP_Right (= NumPad 6 without Num Lock), Alt modifier.
440      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
441       {ui::VKEY_RIGHT, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
442       {ui::VKEY_NUMPAD6, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
443
444      // XK_KP_Home (= NumPad 7 without Num Lock), Alt modifier.
445      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
446       {ui::VKEY_HOME, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
447       {ui::VKEY_NUMPAD7, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
448
449      // XK_KP_Up (= NumPad 8 without Num Lock), Alt modifier.
450      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
451       {ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
452       {ui::VKEY_NUMPAD8, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
453
454      // XK_KP_Prior (= NumPad 9 without Num Lock), Alt modifier.
455      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
456       {ui::VKEY_PRIOR, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY},
457       {ui::VKEY_NUMPAD9, ui::EF_ALT_DOWN | ui::EF_NUMPAD_KEY}},
458
459      // XK_KP_0 (= NumPad 0 with Num Lock), Num Lock modifier.
460      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
461       {ui::VKEY_NUMPAD0, ui::EF_NUMPAD_KEY},
462       {ui::VKEY_NUMPAD0, ui::EF_NUMPAD_KEY}},
463
464      // XK_KP_DECIMAL (= NumPad . with Num Lock), Num Lock modifier.
465      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
466       {ui::VKEY_DECIMAL, ui::EF_NUMPAD_KEY},
467       {ui::VKEY_DECIMAL, ui::EF_NUMPAD_KEY}},
468
469      // XK_KP_1 (= NumPad 1 with Num Lock), Num Lock modifier.
470      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
471       {ui::VKEY_NUMPAD1, ui::EF_NUMPAD_KEY},
472       {ui::VKEY_NUMPAD1, ui::EF_NUMPAD_KEY}},
473
474      // XK_KP_2 (= NumPad 2 with Num Lock), Num Lock modifier.
475      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
476       {ui::VKEY_NUMPAD2, ui::EF_NUMPAD_KEY},
477       {ui::VKEY_NUMPAD2, ui::EF_NUMPAD_KEY}},
478
479      // XK_KP_3 (= NumPad 3 with Num Lock), Num Lock modifier.
480      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
481       {ui::VKEY_NUMPAD3, ui::EF_NUMPAD_KEY},
482       {ui::VKEY_NUMPAD3, ui::EF_NUMPAD_KEY}},
483
484      // XK_KP_4 (= NumPad 4 with Num Lock), Num Lock modifier.
485      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
486       {ui::VKEY_NUMPAD4, ui::EF_NUMPAD_KEY},
487       {ui::VKEY_NUMPAD4, ui::EF_NUMPAD_KEY}},
488
489      // XK_KP_5 (= NumPad 5 with Num Lock), Num Lock modifier.
490      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
491       {ui::VKEY_NUMPAD5, ui::EF_NUMPAD_KEY},
492       {ui::VKEY_NUMPAD5, ui::EF_NUMPAD_KEY}},
493
494      // XK_KP_6 (= NumPad 6 with Num Lock), Num Lock modifier.
495      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
496       {ui::VKEY_NUMPAD6, ui::EF_NUMPAD_KEY},
497       {ui::VKEY_NUMPAD6, ui::EF_NUMPAD_KEY}},
498
499      // XK_KP_7 (= NumPad 7 with Num Lock), Num Lock modifier.
500      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
501       {ui::VKEY_NUMPAD7, ui::EF_NUMPAD_KEY},
502       {ui::VKEY_NUMPAD7, ui::EF_NUMPAD_KEY}},
503
504      // XK_KP_8 (= NumPad 8 with Num Lock), Num Lock modifier.
505      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
506       {ui::VKEY_NUMPAD8, ui::EF_NUMPAD_KEY},
507       {ui::VKEY_NUMPAD8, ui::EF_NUMPAD_KEY}},
508
509      // XK_KP_9 (= NumPad 9 with Num Lock), Num Lock modifier.
510      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
511       {ui::VKEY_NUMPAD9, ui::EF_NUMPAD_KEY},
512       {ui::VKEY_NUMPAD9, ui::EF_NUMPAD_KEY}},
513  };
514
515  for (size_t i = 0; i < arraysize(tests); ++i) {
516    SCOPED_TRACE(i);
517    CheckKeyTestCase(&rewriter, tests[i]);
518  }
519}
520
521TEST_F(EventRewriterTest, TestRewriteNumPadKeys) {
522  TestRewriteNumPadKeys();
523}
524
525TEST_F(EventRewriterTest, TestRewriteNumPadKeysWithDiamondKeyFlag) {
526  // Make sure the num lock works correctly even when Diamond key exists.
527  const CommandLine original_cl(*CommandLine::ForCurrentProcess());
528  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
529      chromeos::switches::kHasChromeOSDiamondKey, "");
530
531  TestRewriteNumPadKeys();
532  *CommandLine::ForCurrentProcess() = original_cl;
533}
534
535// Tests if the rewriter can handle a Command + Num Pad event.
536void EventRewriterTest::TestRewriteNumPadKeysOnAppleKeyboard() {
537  TestingPrefServiceSyncable prefs;
538  EventRewriter rewriter(NULL);
539  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "Apple Keyboard");
540  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
541  rewriter.set_pref_service_for_testing(&prefs);
542
543  KeyTestCase tests[] = {
544      // XK_KP_End (= NumPad 1 without Num Lock), Win modifier.
545      // The result should be "Num Pad 1 with Control + Num Lock modifiers".
546      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
547       {ui::VKEY_END, ui::EF_COMMAND_DOWN | ui::EF_NUMPAD_KEY},
548       {ui::VKEY_NUMPAD1, ui::EF_CONTROL_DOWN | ui::EF_NUMPAD_KEY}},
549
550      // XK_KP_1 (= NumPad 1 with Num Lock), Win modifier.
551      // The result should also be "Num Pad 1 with Control + Num Lock
552      // modifiers".
553      {KeyTestCase::TEST_ALL|KeyTestCase::NUMPAD, ui::ET_KEY_PRESSED,
554       {ui::VKEY_NUMPAD1, ui::EF_COMMAND_DOWN | ui::EF_NUMPAD_KEY},
555       {ui::VKEY_NUMPAD1, ui::EF_CONTROL_DOWN | ui::EF_NUMPAD_KEY}},
556  };
557
558  for (size_t i = 0; i < arraysize(tests); ++i) {
559    SCOPED_TRACE(i);
560    CheckKeyTestCase(&rewriter, tests[i]);
561  }
562}
563
564TEST_F(EventRewriterTest, TestRewriteNumPadKeysOnAppleKeyboard) {
565  TestRewriteNumPadKeysOnAppleKeyboard();
566}
567
568TEST_F(EventRewriterTest,
569       TestRewriteNumPadKeysOnAppleKeyboardWithDiamondKeyFlag) {
570  // Makes sure the num lock works correctly even when Diamond key exists.
571  const CommandLine original_cl(*CommandLine::ForCurrentProcess());
572  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
573      chromeos::switches::kHasChromeOSDiamondKey, "");
574
575  TestRewriteNumPadKeysOnAppleKeyboard();
576  *CommandLine::ForCurrentProcess() = original_cl;
577}
578
579TEST_F(EventRewriterTest, TestRewriteModifiersNoRemap) {
580  TestingPrefServiceSyncable prefs;
581  EventRewriter rewriter(NULL);
582  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
583  rewriter.set_pref_service_for_testing(&prefs);
584
585  KeyTestCase tests[] = {
586      // Press Search. Confirm the event is not rewritten.
587      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
588       {ui::VKEY_LWIN, ui::EF_NONE},
589       {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN}},
590
591      // Press left Control. Confirm the event is not rewritten.
592      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
593       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN},
594       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
595
596      // Press right Control. Confirm the event is not rewritten.
597      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
598       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN},
599       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
600
601      // Press left Alt. Confirm the event is not rewritten.
602      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
603       {ui::VKEY_MENU, ui::EF_ALT_DOWN},
604       {ui::VKEY_MENU, ui::EF_ALT_DOWN}},
605
606      // Press right Alt. Confirm the event is not rewritten.
607      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
608       {ui::VKEY_MENU, ui::EF_ALT_DOWN},
609       {ui::VKEY_MENU, ui::EF_ALT_DOWN}},
610
611      // Test KeyRelease event, just in case.
612      // Release Search. Confirm the release event is not rewritten.
613      {KeyTestCase::TEST_ALL, ui::ET_KEY_RELEASED,
614       {ui::VKEY_LWIN, ui::EF_NONE},
615       {ui::VKEY_LWIN, ui::EF_NONE}},
616  };
617
618  for (size_t i = 0; i < arraysize(tests); ++i) {
619    SCOPED_TRACE(i);
620    CheckKeyTestCase(&rewriter, tests[i]);
621  }
622}
623
624TEST_F(EventRewriterTest, TestRewriteModifiersNoRemapMultipleKeys) {
625  TestingPrefServiceSyncable prefs;
626  EventRewriter rewriter(NULL);
627  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
628  rewriter.set_pref_service_for_testing(&prefs);
629
630  KeyTestCase tests[] = {
631      // Press Alt with Shift. Confirm the event is not rewritten.
632      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
633       {ui::VKEY_MENU, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN},
634       {ui::VKEY_MENU, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}},
635
636      // Press Search with Caps Lock mask. Confirm the event is not rewritten.
637      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
638       {ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN},
639       {ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN | ui::EF_COMMAND_DOWN}},
640
641      // Release Search with Caps Lock mask. Confirm the event is not rewritten.
642      {KeyTestCase::TEST_ALL, ui::ET_KEY_RELEASED,
643       {ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN},
644       {ui::VKEY_LWIN, ui::EF_CAPS_LOCK_DOWN}},
645
646      // Press Shift+Ctrl+Alt+Search+A. Confirm the event is not rewritten.
647      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
648       {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
649                        ui::EF_COMMAND_DOWN},
650       {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
651                        ui::EF_COMMAND_DOWN}},
652  };
653
654  for (size_t i = 0; i < arraysize(tests); ++i) {
655    SCOPED_TRACE(i);
656    CheckKeyTestCase(&rewriter, tests[i]);
657  }
658}
659
660TEST_F(EventRewriterTest, TestRewriteModifiersDisableSome) {
661  // Disable Search and Control keys.
662  TestingPrefServiceSyncable prefs;
663  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
664  IntegerPrefMember search;
665  search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
666  search.SetValue(chromeos::input_method::kVoidKey);
667  IntegerPrefMember control;
668  control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
669  control.SetValue(chromeos::input_method::kVoidKey);
670
671  EventRewriter rewriter(NULL);
672  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
673  rewriter.set_pref_service_for_testing(&prefs);
674
675  KeyTestCase disabled_modifier_tests[] = {
676      // Press Alt with Shift. This key press shouldn't be affected by the
677      // pref. Confirm the event is not rewritten.
678      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
679       {ui::VKEY_MENU, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN},
680       {ui::VKEY_MENU, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN}},
681
682      // Press Search. Confirm the event is now VKEY_UNKNOWN.
683      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
684       {ui::VKEY_LWIN, ui::EF_NONE},
685       {ui::VKEY_UNKNOWN, ui::EF_NONE}},
686
687      // Press Control. Confirm the event is now VKEY_UNKNOWN.
688      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
689       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN},
690       {ui::VKEY_UNKNOWN, ui::EF_NONE}},
691
692      // Press Control+Search. Confirm the event is now VKEY_UNKNOWN
693      // without any modifiers.
694      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
695       {ui::VKEY_LWIN, ui::EF_CONTROL_DOWN},
696       {ui::VKEY_UNKNOWN, ui::EF_NONE}},
697
698      // Press Control+Search+a. Confirm the event is now VKEY_A without any
699      // modifiers.
700      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
701       {ui::VKEY_A, ui::EF_CONTROL_DOWN},
702       {ui::VKEY_A, ui::EF_NONE}},
703
704      // Press Control+Search+Alt+a. Confirm the event is now VKEY_A only with
705      // the Alt modifier.
706      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
707       {ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN},
708       {ui::VKEY_A, ui::EF_ALT_DOWN}},
709  };
710
711  for (size_t i = 0; i < arraysize(disabled_modifier_tests); ++i) {
712    SCOPED_TRACE(i);
713    CheckKeyTestCase(&rewriter, disabled_modifier_tests[i]);
714  }
715
716  // Remap Alt to Control.
717  IntegerPrefMember alt;
718  alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
719  alt.SetValue(chromeos::input_method::kControlKey);
720
721  KeyTestCase tests[] = {
722      // Press left Alt. Confirm the event is now VKEY_CONTROL
723      // even though the Control key itself is disabled.
724      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
725       {ui::VKEY_MENU, ui::EF_ALT_DOWN},
726       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
727
728      // Press Alt+a. Confirm the event is now Control+a even though the Control
729      // key itself is disabled.
730      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
731       {ui::VKEY_A, ui::EF_ALT_DOWN},
732       {ui::VKEY_A, ui::EF_CONTROL_DOWN}},
733  };
734
735  for (size_t i = 0; i < arraysize(tests); ++i) {
736    SCOPED_TRACE(i);
737    CheckKeyTestCase(&rewriter, tests[i]);
738  }
739}
740
741TEST_F(EventRewriterTest, TestRewriteModifiersRemapToControl) {
742  // Remap Search to Control.
743  TestingPrefServiceSyncable prefs;
744  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
745  IntegerPrefMember search;
746  search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
747  search.SetValue(chromeos::input_method::kControlKey);
748
749  EventRewriter rewriter(NULL);
750  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
751  rewriter.set_pref_service_for_testing(&prefs);
752
753  KeyTestCase s_tests[] = {
754      // Press Search. Confirm the event is now VKEY_CONTROL.
755      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
756       {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN},
757       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
758  };
759
760  for (size_t i = 0; i < arraysize(s_tests); ++i) {
761    SCOPED_TRACE(i);
762    CheckKeyTestCase(&rewriter, s_tests[i]);
763  }
764
765  // Remap Alt to Control too.
766  IntegerPrefMember alt;
767  alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
768  alt.SetValue(chromeos::input_method::kControlKey);
769
770  KeyTestCase sa_tests[] = {
771      // Press Alt. Confirm the event is now VKEY_CONTROL.
772      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
773       {ui::VKEY_MENU, ui::EF_ALT_DOWN},
774       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
775
776      // Press Alt+Search. Confirm the event is now VKEY_CONTROL.
777      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
778       {ui::VKEY_LWIN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
779       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
780
781      // Press Control+Alt+Search. Confirm the event is now VKEY_CONTROL.
782      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
783       {ui::VKEY_LWIN,
784        ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
785       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
786
787      // Press Shift+Control+Alt+Search. Confirm the event is now Control with
788      // Shift and Control modifiers.
789      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
790       {ui::VKEY_LWIN, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
791                           ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
792       {ui::VKEY_CONTROL, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}},
793
794      // Press Shift+Control+Alt+Search+B. Confirm the event is now B with Shift
795      // and Control modifiers.
796      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
797       {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
798                        ui::EF_COMMAND_DOWN},
799       {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}},
800  };
801
802  for (size_t i = 0; i < arraysize(sa_tests); ++i) {
803    SCOPED_TRACE(i);
804    CheckKeyTestCase(&rewriter, sa_tests[i]);
805  }
806}
807
808TEST_F(EventRewriterTest, TestRewriteModifiersRemapToEscape) {
809  // Remap Search to ESC.
810  TestingPrefServiceSyncable prefs;
811  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
812  IntegerPrefMember search;
813  search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
814  search.SetValue(chromeos::input_method::kEscapeKey);
815
816  EventRewriter rewriter(NULL);
817  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
818  rewriter.set_pref_service_for_testing(&prefs);
819
820  KeyTestCase tests[] = {// Press Search. Confirm the event is now VKEY_ESCAPE.
821                         {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
822                          {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN},
823                          {ui::VKEY_ESCAPE, ui::EF_NONE}},
824  };
825
826  for (size_t i = 0; i < arraysize(tests); ++i) {
827    SCOPED_TRACE(i);
828    CheckKeyTestCase(&rewriter, tests[i]);
829  }
830}
831
832TEST_F(EventRewriterTest, TestRewriteModifiersRemapMany) {
833  // Remap Search to Alt.
834  TestingPrefServiceSyncable prefs;
835  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
836  IntegerPrefMember search;
837  search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
838  search.SetValue(chromeos::input_method::kAltKey);
839
840  EventRewriter rewriter(NULL);
841  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
842  rewriter.set_pref_service_for_testing(&prefs);
843
844  KeyTestCase s2a_tests[] = {
845      // Press Search. Confirm the event is now VKEY_MENU.
846      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
847       {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN},
848       {ui::VKEY_MENU, ui::EF_ALT_DOWN}},
849  };
850
851  for (size_t i = 0; i < arraysize(s2a_tests); ++i) {
852    SCOPED_TRACE(i);
853    CheckKeyTestCase(&rewriter, s2a_tests[i]);
854  }
855
856  // Remap Alt to Control.
857  IntegerPrefMember alt;
858  alt.Init(prefs::kLanguageRemapAltKeyTo, &prefs);
859  alt.SetValue(chromeos::input_method::kControlKey);
860
861  KeyTestCase a2c_tests[] = {
862      // Press left Alt. Confirm the event is now VKEY_CONTROL.
863      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
864       {ui::VKEY_MENU, ui::EF_ALT_DOWN},
865       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
866      // Press Shift+comma. Verify that only the flags are changed.
867      // The X11 portion of the test addresses crbug.com/390263 by verifying
868      // that the X keycode remains that for ',<' and not for 105-key '<>'.
869      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
870       {ui::VKEY_OEM_COMMA, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN},
871       {ui::VKEY_OEM_COMMA, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}},
872      // Press Shift+9. Verify that only the flags are changed.
873      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
874       {ui::VKEY_9, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN},
875       {ui::VKEY_9, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN}},
876  };
877
878  for (size_t i = 0; i < arraysize(a2c_tests); ++i) {
879    SCOPED_TRACE(i);
880    CheckKeyTestCase(&rewriter, a2c_tests[i]);
881  }
882
883  // Remap Control to Search.
884  IntegerPrefMember control;
885  control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
886  control.SetValue(chromeos::input_method::kSearchKey);
887
888  KeyTestCase c2s_tests[] = {
889      // Press left Control. Confirm the event is now VKEY_LWIN.
890      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
891       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN},
892       {ui::VKEY_LWIN, ui::EF_COMMAND_DOWN}},
893
894      // Then, press all of the three, Control+Alt+Search.
895      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
896       {ui::VKEY_LWIN,
897        ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
898       {ui::VKEY_MENU,
899        ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN}},
900
901      // Press Shift+Control+Alt+Search.
902      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
903       {ui::VKEY_LWIN, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
904                           ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
905       {ui::VKEY_MENU, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
906                           ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN}},
907
908      // Press Shift+Control+Alt+Search+B
909      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
910       {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
911                        ui::EF_COMMAND_DOWN},
912       {ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN |
913                        ui::EF_COMMAND_DOWN}},
914  };
915
916  for (size_t i = 0; i < arraysize(c2s_tests); ++i) {
917    SCOPED_TRACE(i);
918    CheckKeyTestCase(&rewriter, c2s_tests[i]);
919  }
920}
921
922TEST_F(EventRewriterTest, TestRewriteModifiersRemapToCapsLock) {
923  // Remap Search to Caps Lock.
924  TestingPrefServiceSyncable prefs;
925  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
926  IntegerPrefMember search;
927  search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
928  search.SetValue(chromeos::input_method::kCapsLockKey);
929
930  chromeos::input_method::FakeImeKeyboard ime_keyboard;
931  EventRewriter rewriter(NULL);
932  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
933  rewriter.set_pref_service_for_testing(&prefs);
934  rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
935  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
936
937  // Press Search.
938  EXPECT_EQ(
939      GetExpectedResultAsString(ui::VKEY_CAPITAL,
940                                ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
941                                ui::ET_KEY_PRESSED),
942      GetRewrittenEventAsString(
943          &rewriter, ui::VKEY_LWIN, ui::EF_COMMAND_DOWN, ui::ET_KEY_PRESSED));
944  // Confirm that the Caps Lock status is changed.
945  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
946
947  // Release Search.
948  EXPECT_EQ(GetExpectedResultAsString(
949                ui::VKEY_CAPITAL, ui::EF_NONE, ui::ET_KEY_RELEASED),
950            GetRewrittenEventAsString(
951                &rewriter, ui::VKEY_LWIN, ui::EF_NONE, ui::ET_KEY_RELEASED));
952  // Confirm that the Caps Lock status is not changed.
953  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
954
955  // Press Search.
956  EXPECT_EQ(
957      GetExpectedResultAsString(ui::VKEY_CAPITAL,
958                                ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
959                                ui::ET_KEY_PRESSED),
960      GetRewrittenEventAsString(&rewriter,
961                                ui::VKEY_LWIN,
962                                ui::EF_COMMAND_DOWN | ui::EF_CAPS_LOCK_DOWN,
963                                ui::ET_KEY_PRESSED));
964  // Confirm that the Caps Lock status is changed.
965  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
966
967  // Release Search.
968  EXPECT_EQ(GetExpectedResultAsString(
969                ui::VKEY_CAPITAL, ui::EF_NONE, ui::ET_KEY_RELEASED),
970            GetRewrittenEventAsString(
971                &rewriter, ui::VKEY_LWIN, ui::EF_NONE, ui::ET_KEY_RELEASED));
972  // Confirm that the Caps Lock status is not changed.
973  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
974
975  // Press Caps Lock (on an external keyboard).
976  EXPECT_EQ(GetExpectedResultAsString(ui::VKEY_CAPITAL,
977                                      ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
978                                      ui::ET_KEY_PRESSED),
979            GetRewrittenEventAsString(&rewriter,
980                                      ui::VKEY_CAPITAL,
981                                      ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
982                                      ui::ET_KEY_PRESSED));
983
984  // Confirm that calling RewriteForTesting() does not change the state of
985  // |ime_keyboard|. In this case, X Window system itself should change the
986  // Caps Lock state, not ash::EventRewriter.
987  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
988
989  // Release Caps Lock (on an external keyboard).
990  EXPECT_EQ(GetExpectedResultAsString(
991                ui::VKEY_CAPITAL, ui::EF_NONE, ui::ET_KEY_RELEASED),
992            GetRewrittenEventAsString(
993                &rewriter, ui::VKEY_CAPITAL, ui::EF_NONE, ui::ET_KEY_RELEASED));
994  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
995}
996
997TEST_F(EventRewriterTest, TestRewriteCapsLock) {
998  TestingPrefServiceSyncable prefs;
999  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1000
1001  chromeos::input_method::FakeImeKeyboard ime_keyboard;
1002  EventRewriter rewriter(NULL);
1003  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1004  rewriter.set_pref_service_for_testing(&prefs);
1005  rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1006  EXPECT_FALSE(ime_keyboard.caps_lock_is_enabled_);
1007
1008  // On Chrome OS, CapsLock is mapped to F16 with Mod3Mask.
1009  EXPECT_EQ(GetExpectedResultAsString(ui::VKEY_CAPITAL,
1010                                      ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1011                                      ui::ET_KEY_PRESSED),
1012            GetRewrittenEventAsString(
1013                &rewriter, ui::VKEY_F16, ui::EF_MOD3_DOWN, ui::ET_KEY_PRESSED));
1014  EXPECT_TRUE(ime_keyboard.caps_lock_is_enabled_);
1015}
1016
1017TEST_F(EventRewriterTest, TestRewriteDiamondKey) {
1018  TestingPrefServiceSyncable prefs;
1019  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1020
1021  chromeos::input_method::FakeImeKeyboard ime_keyboard;
1022  EventRewriter rewriter(NULL);
1023  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1024  rewriter.set_pref_service_for_testing(&prefs);
1025  rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1026
1027  KeyTestCase tests[] = {
1028      // F15 should work as Ctrl when --has-chromeos-diamond-key is not
1029      // specified.
1030      {KeyTestCase::TEST_VKEY,
1031       ui::ET_KEY_PRESSED,
1032       {ui::VKEY_F15, ui::EF_NONE},
1033       {ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN}},
1034
1035      {KeyTestCase::TEST_VKEY,
1036       ui::ET_KEY_RELEASED,
1037       {ui::VKEY_F15, ui::EF_NONE},
1038       {ui::VKEY_CONTROL, ui::EF_NONE}},
1039
1040      // However, Mod2Mask should not be rewritten to CtrlMask when
1041      // --has-chromeos-diamond-key is not specified.
1042      {KeyTestCase::TEST_VKEY,
1043       ui::ET_KEY_PRESSED,
1044       {ui::VKEY_A, ui::EF_NONE},
1045       {ui::VKEY_A, ui::EF_NONE}},
1046  };
1047
1048  for (size_t i = 0; i < arraysize(tests); ++i) {
1049    SCOPED_TRACE(i);
1050    CheckKeyTestCase(&rewriter, tests[i]);
1051  }
1052}
1053
1054TEST_F(EventRewriterTest, TestRewriteDiamondKeyWithFlag) {
1055  const CommandLine original_cl(*CommandLine::ForCurrentProcess());
1056  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1057      chromeos::switches::kHasChromeOSDiamondKey, "");
1058
1059  TestingPrefServiceSyncable prefs;
1060  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1061
1062  chromeos::input_method::FakeImeKeyboard ime_keyboard;
1063  EventRewriter rewriter(NULL);
1064  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1065  rewriter.set_pref_service_for_testing(&prefs);
1066  rewriter.set_ime_keyboard_for_testing(&ime_keyboard);
1067
1068  // By default, F15 should work as Control.
1069  EXPECT_EQ(GetExpectedResultAsString(
1070                ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN, ui::ET_KEY_PRESSED),
1071            GetRewrittenEventAsString(
1072                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_PRESSED));
1073  // Check that Control is applied to a subsequent key press.
1074  EXPECT_EQ(GetExpectedResultAsString(
1075                ui::VKEY_A, ui::EF_CONTROL_DOWN, ui::ET_KEY_PRESSED),
1076            GetRewrittenEventAsString(
1077                &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1078  // Release F15
1079  EXPECT_EQ(GetExpectedResultAsString(
1080                ui::VKEY_CONTROL, ui::EF_NONE, ui::ET_KEY_RELEASED),
1081            GetRewrittenEventAsString(
1082                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_RELEASED));
1083  // Check that Control is no longer applied to a subsequent key press.
1084  EXPECT_EQ(
1085      GetExpectedResultAsString(ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED),
1086      GetRewrittenEventAsString(
1087          &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1088
1089  IntegerPrefMember diamond;
1090  diamond.Init(prefs::kLanguageRemapDiamondKeyTo, &prefs);
1091  diamond.SetValue(chromeos::input_method::kVoidKey);
1092
1093  EXPECT_EQ(GetExpectedResultAsString(
1094                ui::VKEY_UNKNOWN, ui::EF_NONE, ui::ET_KEY_PRESSED),
1095            GetRewrittenEventAsString(
1096                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_PRESSED));
1097  // Check that no modifier is applied to another key.
1098  EXPECT_EQ(
1099      GetExpectedResultAsString(ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED),
1100      GetRewrittenEventAsString(
1101          &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1102
1103  diamond.SetValue(chromeos::input_method::kControlKey);
1104
1105  EXPECT_EQ(GetExpectedResultAsString(
1106                ui::VKEY_CONTROL, ui::EF_CONTROL_DOWN, ui::ET_KEY_PRESSED),
1107            GetRewrittenEventAsString(
1108                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_PRESSED));
1109  // Check that Control is applied to a subsequent key press.
1110  EXPECT_EQ(GetExpectedResultAsString(
1111                ui::VKEY_A, ui::EF_CONTROL_DOWN, ui::ET_KEY_PRESSED),
1112            GetRewrittenEventAsString(
1113                &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1114  // Release F15
1115  EXPECT_EQ(GetExpectedResultAsString(
1116                ui::VKEY_CONTROL, ui::EF_NONE, ui::ET_KEY_RELEASED),
1117            GetRewrittenEventAsString(
1118                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_RELEASED));
1119  // Check that Control is no longer applied to a subsequent key press.
1120  EXPECT_EQ(
1121      GetExpectedResultAsString(ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED),
1122      GetRewrittenEventAsString(
1123          &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1124
1125  diamond.SetValue(chromeos::input_method::kAltKey);
1126
1127  EXPECT_EQ(GetExpectedResultAsString(
1128                ui::VKEY_MENU, ui::EF_ALT_DOWN, ui::ET_KEY_PRESSED),
1129            GetRewrittenEventAsString(
1130                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_PRESSED));
1131  // Check that Alt is applied to a subsequent key press.
1132  EXPECT_EQ(GetExpectedResultAsString(
1133                ui::VKEY_A, ui::EF_ALT_DOWN, ui::ET_KEY_PRESSED),
1134            GetRewrittenEventAsString(
1135                &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1136  // Release F15
1137  EXPECT_EQ(GetExpectedResultAsString(
1138                ui::VKEY_MENU, ui::EF_NONE, ui::ET_KEY_RELEASED),
1139            GetRewrittenEventAsString(
1140                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_RELEASED));
1141  // Check that Alt is no longer applied to a subsequent key press.
1142  EXPECT_EQ(
1143      GetExpectedResultAsString(ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED),
1144      GetRewrittenEventAsString(
1145          &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1146
1147  diamond.SetValue(chromeos::input_method::kCapsLockKey);
1148
1149  EXPECT_EQ(GetExpectedResultAsString(ui::VKEY_CAPITAL,
1150                                      ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1151                                      ui::ET_KEY_PRESSED),
1152            GetRewrittenEventAsString(
1153                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_PRESSED));
1154  // Check that Caps is applied to a subsequent key press.
1155  EXPECT_EQ(GetExpectedResultAsString(ui::VKEY_A,
1156                                      ui::EF_CAPS_LOCK_DOWN | ui::EF_MOD3_DOWN,
1157                                      ui::ET_KEY_PRESSED),
1158            GetRewrittenEventAsString(
1159                &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1160  // Release F15
1161  EXPECT_EQ(GetExpectedResultAsString(
1162                ui::VKEY_CAPITAL, ui::EF_NONE, ui::ET_KEY_RELEASED),
1163            GetRewrittenEventAsString(
1164                &rewriter, ui::VKEY_F15, ui::EF_NONE, ui::ET_KEY_RELEASED));
1165  // Check that Control is no longer applied to a subsequent key press.
1166  EXPECT_EQ(
1167      GetExpectedResultAsString(ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED),
1168      GetRewrittenEventAsString(
1169          &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1170
1171  *CommandLine::ForCurrentProcess() = original_cl;
1172}
1173
1174TEST_F(EventRewriterTest, TestRewriteCapsLockToControl) {
1175  // Remap CapsLock to Control.
1176  TestingPrefServiceSyncable prefs;
1177  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1178  IntegerPrefMember control;
1179  control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1180  control.SetValue(chromeos::input_method::kControlKey);
1181
1182  EventRewriter rewriter(NULL);
1183  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1184  rewriter.set_pref_service_for_testing(&prefs);
1185
1186  KeyTestCase tests[] = {
1187      // Press CapsLock+a. Confirm that Mod3Mask is rewritten to ControlMask.
1188      // On Chrome OS, CapsLock works as a Mod3 modifier.
1189      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1190       {ui::VKEY_A, ui::EF_MOD3_DOWN},
1191       {ui::VKEY_A, ui::EF_CONTROL_DOWN}},
1192
1193      // Press Control+CapsLock+a. Confirm that Mod3Mask is rewritten to
1194      // ControlMask
1195      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1196       {ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_MOD3_DOWN},
1197       {ui::VKEY_A, ui::EF_CONTROL_DOWN}},
1198
1199      // Press Alt+CapsLock+a. Confirm that Mod3Mask is rewritten to
1200      // ControlMask.
1201      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1202       {ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_MOD3_DOWN},
1203       {ui::VKEY_A, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN}},
1204  };
1205
1206  for (size_t i = 0; i < arraysize(tests); ++i) {
1207    SCOPED_TRACE(i);
1208    CheckKeyTestCase(&rewriter, tests[i]);
1209  }
1210}
1211
1212TEST_F(EventRewriterTest, TestRewriteCapsLockMod3InUse) {
1213  // Remap CapsLock to Control.
1214  TestingPrefServiceSyncable prefs;
1215  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1216  IntegerPrefMember control;
1217  control.Init(prefs::kLanguageRemapCapsLockKeyTo, &prefs);
1218  control.SetValue(chromeos::input_method::kControlKey);
1219
1220  EventRewriter rewriter(NULL);
1221  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1222  rewriter.set_pref_service_for_testing(&prefs);
1223  input_method_manager_mock_->set_mod3_used(true);
1224
1225  // Press CapsLock+a. Confirm that Mod3Mask is NOT rewritten to ControlMask
1226  // when Mod3Mask is already in use by the current XKB layout.
1227  EXPECT_EQ(
1228      GetExpectedResultAsString(ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED),
1229      GetRewrittenEventAsString(
1230          &rewriter, ui::VKEY_A, ui::EF_NONE, ui::ET_KEY_PRESSED));
1231
1232  input_method_manager_mock_->set_mod3_used(false);
1233}
1234
1235TEST_F(EventRewriterTest, TestRewriteExtendedKeys) {
1236  TestingPrefServiceSyncable prefs;
1237  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1238  EventRewriter rewriter(NULL);
1239  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1240  rewriter.set_last_keyboard_device_id_for_testing(kKeyboardDeviceId);
1241  rewriter.set_pref_service_for_testing(&prefs);
1242
1243  KeyTestCase tests[] = {
1244      // Alt+Backspace -> Delete
1245      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1246       {ui::VKEY_BACK, ui::EF_ALT_DOWN},
1247       {ui::VKEY_DELETE, ui::EF_NONE}},
1248      // Control+Alt+Backspace -> Control+Delete
1249      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1250       {ui::VKEY_BACK, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN},
1251       {ui::VKEY_DELETE, ui::EF_CONTROL_DOWN}},
1252      // Search+Alt+Backspace -> Alt+Backspace
1253      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1254       {ui::VKEY_BACK, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
1255       {ui::VKEY_BACK, ui::EF_ALT_DOWN}},
1256      // Search+Control+Alt+Backspace -> Control+Alt+Backspace
1257      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1258       {ui::VKEY_BACK,
1259        ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN},
1260       {ui::VKEY_BACK, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN}},
1261      // Alt+Up -> Prior
1262      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1263       {ui::VKEY_UP, ui::EF_ALT_DOWN},
1264       {ui::VKEY_PRIOR, ui::EF_NONE}},
1265      // Alt+Down -> Next
1266      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1267       {ui::VKEY_DOWN, ui::EF_ALT_DOWN},
1268       {ui::VKEY_NEXT, ui::EF_NONE}},
1269      // Ctrl+Alt+Up -> Home
1270      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1271       {ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN},
1272       {ui::VKEY_HOME, ui::EF_NONE}},
1273      // Ctrl+Alt+Down -> End
1274      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1275       {ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN},
1276       {ui::VKEY_END, ui::EF_NONE}},
1277
1278      // Search+Alt+Up -> Alt+Up
1279      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1280       {ui::VKEY_UP, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
1281       {ui::VKEY_UP, ui::EF_ALT_DOWN}},
1282      // Search+Alt+Down -> Alt+Down
1283      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1284       {ui::VKEY_DOWN, ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN},
1285       {ui::VKEY_DOWN, ui::EF_ALT_DOWN}},
1286      // Search+Ctrl+Alt+Up -> Search+Ctrl+Alt+Up
1287      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1288       {ui::VKEY_UP,
1289        ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN},
1290       {ui::VKEY_UP, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN}},
1291      // Search+Ctrl+Alt+Down -> Ctrl+Alt+Down
1292      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1293       {ui::VKEY_DOWN,
1294        ui::EF_COMMAND_DOWN | ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN},
1295       {ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN}},
1296
1297      // Period -> Period
1298      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1299       {ui::VKEY_OEM_PERIOD, ui::EF_NONE},
1300       {ui::VKEY_OEM_PERIOD, ui::EF_NONE}},
1301
1302      // Search+Backspace -> Delete
1303      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1304       {ui::VKEY_BACK, ui::EF_COMMAND_DOWN},
1305       {ui::VKEY_DELETE, ui::EF_NONE}},
1306      // Search+Up -> Prior
1307      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1308       {ui::VKEY_UP, ui::EF_COMMAND_DOWN},
1309       {ui::VKEY_PRIOR, ui::EF_NONE}},
1310      // Search+Down -> Next
1311      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1312       {ui::VKEY_DOWN, ui::EF_COMMAND_DOWN},
1313       {ui::VKEY_NEXT, ui::EF_NONE}},
1314      // Search+Left -> Home
1315      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1316       {ui::VKEY_LEFT, ui::EF_COMMAND_DOWN},
1317       {ui::VKEY_HOME, ui::EF_NONE}},
1318      // Control+Search+Left -> Home
1319      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1320       {ui::VKEY_LEFT, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN},
1321       {ui::VKEY_HOME, ui::EF_CONTROL_DOWN}},
1322      // Search+Right -> End
1323      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1324       {ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN},
1325       {ui::VKEY_END, ui::EF_NONE}},
1326      // Control+Search+Right -> End
1327      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1328       {ui::VKEY_RIGHT, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN},
1329       {ui::VKEY_END, ui::EF_CONTROL_DOWN}},
1330      // Search+Period -> Insert
1331      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1332       {ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN},
1333       {ui::VKEY_INSERT, ui::EF_NONE}},
1334      // Control+Search+Period -> Control+Insert
1335      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1336       {ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN},
1337       {ui::VKEY_INSERT, ui::EF_CONTROL_DOWN}}};
1338
1339  for (size_t i = 0; i < arraysize(tests); ++i) {
1340    SCOPED_TRACE(i);
1341    CheckKeyTestCase(&rewriter, tests[i]);
1342  }
1343}
1344
1345TEST_F(EventRewriterTest, TestRewriteFunctionKeys) {
1346  TestingPrefServiceSyncable prefs;
1347  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1348  EventRewriter rewriter(NULL);
1349  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1350  rewriter.set_pref_service_for_testing(&prefs);
1351
1352  FunctionKeyTestCase tests[] = {
1353      // F1 -> Back
1354      {ui::ET_KEY_PRESSED,
1355       {ui::VKEY_F1, ui::EF_NONE},
1356       {ui::VKEY_BROWSER_BACK, ui::EF_NONE},
1357       {ui::VKEY_BROWSER_BACK, ui::EF_FUNCTION_KEY}},
1358      {ui::ET_KEY_PRESSED,
1359       {ui::VKEY_F1, ui::EF_CONTROL_DOWN},
1360       {ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN},
1361       {ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1362      {ui::ET_KEY_PRESSED,
1363       {ui::VKEY_F1, ui::EF_ALT_DOWN},
1364       {ui::VKEY_BROWSER_BACK, ui::EF_ALT_DOWN},
1365       {ui::VKEY_BROWSER_BACK, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1366      // F2 -> Forward
1367      {ui::ET_KEY_PRESSED,
1368       {ui::VKEY_F2, ui::EF_NONE},
1369       {ui::VKEY_BROWSER_FORWARD, ui::EF_NONE},
1370       {ui::VKEY_BROWSER_FORWARD, ui::EF_FUNCTION_KEY}},
1371      {ui::ET_KEY_PRESSED,
1372       {ui::VKEY_F2, ui::EF_CONTROL_DOWN},
1373       {ui::VKEY_BROWSER_FORWARD, ui::EF_CONTROL_DOWN},
1374       {ui::VKEY_BROWSER_FORWARD, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1375      {ui::ET_KEY_PRESSED,
1376       {ui::VKEY_F2, ui::EF_ALT_DOWN},
1377       {ui::VKEY_BROWSER_FORWARD, ui::EF_ALT_DOWN},
1378       {ui::VKEY_BROWSER_FORWARD, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1379      // F3 -> Refresh
1380      {ui::ET_KEY_PRESSED,
1381       {ui::VKEY_F3, ui::EF_NONE},
1382       {ui::VKEY_BROWSER_REFRESH, ui::EF_NONE},
1383       {ui::VKEY_BROWSER_REFRESH, ui::EF_FUNCTION_KEY}},
1384      {ui::ET_KEY_PRESSED,
1385       {ui::VKEY_F3, ui::EF_CONTROL_DOWN},
1386       {ui::VKEY_BROWSER_REFRESH, ui::EF_CONTROL_DOWN},
1387       {ui::VKEY_BROWSER_REFRESH, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1388      {ui::ET_KEY_PRESSED,
1389       {ui::VKEY_F3, ui::EF_ALT_DOWN},
1390       {ui::VKEY_BROWSER_REFRESH, ui::EF_ALT_DOWN},
1391       {ui::VKEY_BROWSER_REFRESH, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1392      // F4 -> Launch App 2
1393      {ui::ET_KEY_PRESSED,
1394       {ui::VKEY_F4, ui::EF_NONE},
1395       {ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_NONE},
1396       {ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_FUNCTION_KEY}},
1397      {ui::ET_KEY_PRESSED,
1398       {ui::VKEY_F4, ui::EF_CONTROL_DOWN},
1399       {ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_CONTROL_DOWN},
1400       {ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1401      {ui::ET_KEY_PRESSED,
1402       {ui::VKEY_F4, ui::EF_ALT_DOWN},
1403       {ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_ALT_DOWN},
1404       {ui::VKEY_MEDIA_LAUNCH_APP2, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1405      // F5 -> Launch App 1
1406      {ui::ET_KEY_PRESSED,
1407       {ui::VKEY_F5, ui::EF_NONE},
1408       {ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE},
1409       {ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_FUNCTION_KEY}},
1410      {ui::ET_KEY_PRESSED,
1411       {ui::VKEY_F5, ui::EF_CONTROL_DOWN},
1412       {ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN},
1413       {ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1414      {ui::ET_KEY_PRESSED,
1415       {ui::VKEY_F5, ui::EF_ALT_DOWN},
1416       {ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_ALT_DOWN},
1417       {ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1418      // F6 -> Brightness down
1419      {ui::ET_KEY_PRESSED,
1420       {ui::VKEY_F6, ui::EF_NONE},
1421       {ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE},
1422       {ui::VKEY_BRIGHTNESS_DOWN, ui::EF_FUNCTION_KEY}},
1423      {ui::ET_KEY_PRESSED,
1424       {ui::VKEY_F6, ui::EF_CONTROL_DOWN},
1425       {ui::VKEY_BRIGHTNESS_DOWN, ui::EF_CONTROL_DOWN},
1426       {ui::VKEY_BRIGHTNESS_DOWN, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1427      {ui::ET_KEY_PRESSED,
1428       {ui::VKEY_F6, ui::EF_ALT_DOWN},
1429       {ui::VKEY_BRIGHTNESS_DOWN, ui::EF_ALT_DOWN},
1430       {ui::VKEY_BRIGHTNESS_DOWN, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1431      // F7 -> Brightness up
1432      {ui::ET_KEY_PRESSED,
1433       {ui::VKEY_F7, ui::EF_NONE},
1434       {ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE},
1435       {ui::VKEY_BRIGHTNESS_UP, ui::EF_FUNCTION_KEY}},
1436      {ui::ET_KEY_PRESSED,
1437       {ui::VKEY_F7, ui::EF_CONTROL_DOWN},
1438       {ui::VKEY_BRIGHTNESS_UP, ui::EF_CONTROL_DOWN},
1439       {ui::VKEY_BRIGHTNESS_UP, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1440      {ui::ET_KEY_PRESSED,
1441       {ui::VKEY_F7, ui::EF_ALT_DOWN},
1442       {ui::VKEY_BRIGHTNESS_UP, ui::EF_ALT_DOWN},
1443       {ui::VKEY_BRIGHTNESS_UP, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1444      // F8 -> Volume Mute
1445      {ui::ET_KEY_PRESSED,
1446       {ui::VKEY_F8, ui::EF_NONE},
1447       {ui::VKEY_VOLUME_MUTE, ui::EF_NONE},
1448       {ui::VKEY_VOLUME_MUTE, ui::EF_FUNCTION_KEY}},
1449      {ui::ET_KEY_PRESSED,
1450       {ui::VKEY_F8, ui::EF_CONTROL_DOWN},
1451       {ui::VKEY_VOLUME_MUTE, ui::EF_CONTROL_DOWN},
1452       {ui::VKEY_VOLUME_MUTE, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1453      {ui::ET_KEY_PRESSED,
1454       {ui::VKEY_F8, ui::EF_ALT_DOWN},
1455       {ui::VKEY_VOLUME_MUTE, ui::EF_ALT_DOWN},
1456       {ui::VKEY_VOLUME_MUTE, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1457      // F9 -> Volume Down
1458      {ui::ET_KEY_PRESSED,
1459       {ui::VKEY_F9, ui::EF_NONE},
1460       {ui::VKEY_VOLUME_DOWN, ui::EF_NONE},
1461       {ui::VKEY_VOLUME_DOWN, ui::EF_FUNCTION_KEY}},
1462      {ui::ET_KEY_PRESSED,
1463       {ui::VKEY_F9, ui::EF_CONTROL_DOWN},
1464       {ui::VKEY_VOLUME_DOWN, ui::EF_CONTROL_DOWN},
1465       {ui::VKEY_VOLUME_DOWN, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1466      {ui::ET_KEY_PRESSED,
1467       {ui::VKEY_F9, ui::EF_ALT_DOWN},
1468       {ui::VKEY_VOLUME_DOWN, ui::EF_ALT_DOWN},
1469       {ui::VKEY_VOLUME_DOWN, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1470      // F10 -> Volume Up
1471      {ui::ET_KEY_PRESSED,
1472       {ui::VKEY_F10, ui::EF_NONE},
1473       {ui::VKEY_VOLUME_UP, ui::EF_NONE},
1474       {ui::VKEY_VOLUME_UP, ui::EF_FUNCTION_KEY}},
1475      {ui::ET_KEY_PRESSED,
1476       {ui::VKEY_F10, ui::EF_CONTROL_DOWN},
1477       {ui::VKEY_VOLUME_UP, ui::EF_CONTROL_DOWN},
1478       {ui::VKEY_VOLUME_UP, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1479      {ui::ET_KEY_PRESSED,
1480       {ui::VKEY_F10, ui::EF_ALT_DOWN},
1481       {ui::VKEY_VOLUME_UP, ui::EF_ALT_DOWN},
1482       {ui::VKEY_VOLUME_UP, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1483      // F11 -> F11
1484      {ui::ET_KEY_PRESSED,
1485       {ui::VKEY_F11, ui::EF_NONE},
1486       {ui::VKEY_F11, ui::EF_NONE},
1487       {ui::VKEY_F11, ui::EF_FUNCTION_KEY}},
1488      {ui::ET_KEY_PRESSED,
1489       {ui::VKEY_F11, ui::EF_CONTROL_DOWN},
1490       {ui::VKEY_F11, ui::EF_CONTROL_DOWN},
1491       {ui::VKEY_F11, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1492      {ui::ET_KEY_PRESSED,
1493       {ui::VKEY_F11, ui::EF_ALT_DOWN},
1494       {ui::VKEY_F11, ui::EF_ALT_DOWN},
1495       {ui::VKEY_F11, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1496      // F12 -> F12
1497      {ui::ET_KEY_PRESSED,
1498       {ui::VKEY_F12, ui::EF_NONE},
1499       {ui::VKEY_F12, ui::EF_NONE},
1500       {ui::VKEY_F12, ui::EF_FUNCTION_KEY}},
1501      {ui::ET_KEY_PRESSED,
1502       {ui::VKEY_F12, ui::EF_CONTROL_DOWN},
1503       {ui::VKEY_F12, ui::EF_CONTROL_DOWN},
1504       {ui::VKEY_F12, ui::EF_CONTROL_DOWN | ui::EF_FUNCTION_KEY}},
1505      {ui::ET_KEY_PRESSED,
1506       {ui::VKEY_F12, ui::EF_ALT_DOWN},
1507       {ui::VKEY_F12, ui::EF_ALT_DOWN},
1508       {ui::VKEY_F12, ui::EF_ALT_DOWN | ui::EF_FUNCTION_KEY}},
1509
1510      // The number row should not be rewritten without Search key.
1511      {ui::ET_KEY_PRESSED,
1512       {ui::VKEY_1, ui::EF_NONE},
1513       {ui::VKEY_1, ui::EF_NONE},
1514       {ui::VKEY_1, ui::EF_NONE}},
1515      {ui::ET_KEY_PRESSED,
1516       {ui::VKEY_2, ui::EF_NONE},
1517       {ui::VKEY_2, ui::EF_NONE},
1518       {ui::VKEY_2, ui::EF_NONE}},
1519      {ui::ET_KEY_PRESSED,
1520       {ui::VKEY_3, ui::EF_NONE},
1521       {ui::VKEY_3, ui::EF_NONE},
1522       {ui::VKEY_3, ui::EF_NONE}},
1523      {ui::ET_KEY_PRESSED,
1524       {ui::VKEY_4, ui::EF_NONE},
1525       {ui::VKEY_4, ui::EF_NONE},
1526       {ui::VKEY_4, ui::EF_NONE}},
1527      {ui::ET_KEY_PRESSED,
1528       {ui::VKEY_5, ui::EF_NONE},
1529       {ui::VKEY_5, ui::EF_NONE},
1530       {ui::VKEY_5, ui::EF_NONE}},
1531      {ui::ET_KEY_PRESSED,
1532       {ui::VKEY_6, ui::EF_NONE},
1533       {ui::VKEY_6, ui::EF_NONE},
1534       {ui::VKEY_6, ui::EF_NONE}},
1535      {ui::ET_KEY_PRESSED,
1536       {ui::VKEY_7, ui::EF_NONE},
1537       {ui::VKEY_7, ui::EF_NONE},
1538       {ui::VKEY_7, ui::EF_NONE}},
1539      {ui::ET_KEY_PRESSED,
1540       {ui::VKEY_8, ui::EF_NONE},
1541       {ui::VKEY_8, ui::EF_NONE},
1542       {ui::VKEY_8, ui::EF_NONE}},
1543      {ui::ET_KEY_PRESSED,
1544       {ui::VKEY_9, ui::EF_NONE},
1545       {ui::VKEY_9, ui::EF_NONE},
1546       {ui::VKEY_9, ui::EF_NONE}},
1547      {ui::ET_KEY_PRESSED,
1548       {ui::VKEY_0, ui::EF_NONE},
1549       {ui::VKEY_0, ui::EF_NONE},
1550       {ui::VKEY_0, ui::EF_NONE}},
1551      {ui::ET_KEY_PRESSED,
1552       {ui::VKEY_OEM_MINUS, ui::EF_NONE},
1553       {ui::VKEY_OEM_MINUS, ui::EF_NONE},
1554       {ui::VKEY_OEM_MINUS, ui::EF_NONE}},
1555      {ui::ET_KEY_PRESSED,
1556       {ui::VKEY_OEM_PLUS, ui::EF_NONE},
1557       {ui::VKEY_OEM_PLUS, ui::EF_NONE},
1558       {ui::VKEY_OEM_PLUS, ui::EF_NONE}},
1559
1560      // The number row should be rewritten as the F<number> row with Search
1561      // key.
1562      {ui::ET_KEY_PRESSED,
1563       {ui::VKEY_1, ui::EF_COMMAND_DOWN},
1564       {ui::VKEY_F1, ui::EF_NONE},
1565       {ui::VKEY_F1, ui::EF_NONE}},
1566      {ui::ET_KEY_PRESSED,
1567       {ui::VKEY_2, ui::EF_COMMAND_DOWN},
1568       {ui::VKEY_F2, ui::EF_NONE},
1569       {ui::VKEY_F2, ui::EF_NONE}},
1570      {ui::ET_KEY_PRESSED,
1571       {ui::VKEY_3, ui::EF_COMMAND_DOWN},
1572       {ui::VKEY_F3, ui::EF_NONE},
1573       {ui::VKEY_F3, ui::EF_NONE}},
1574      {ui::ET_KEY_PRESSED,
1575       {ui::VKEY_4, ui::EF_COMMAND_DOWN},
1576       {ui::VKEY_F4, ui::EF_NONE},
1577       {ui::VKEY_F4, ui::EF_NONE}},
1578      {ui::ET_KEY_PRESSED,
1579       {ui::VKEY_5, ui::EF_COMMAND_DOWN},
1580       {ui::VKEY_F5, ui::EF_NONE},
1581       {ui::VKEY_F5, ui::EF_NONE}},
1582      {ui::ET_KEY_PRESSED,
1583       {ui::VKEY_6, ui::EF_COMMAND_DOWN},
1584       {ui::VKEY_F6, ui::EF_NONE},
1585       {ui::VKEY_F6, ui::EF_NONE}},
1586      {ui::ET_KEY_PRESSED,
1587       {ui::VKEY_7, ui::EF_COMMAND_DOWN},
1588       {ui::VKEY_F7, ui::EF_NONE},
1589       {ui::VKEY_F7, ui::EF_NONE}},
1590      {ui::ET_KEY_PRESSED,
1591       {ui::VKEY_8, ui::EF_COMMAND_DOWN},
1592       {ui::VKEY_F8, ui::EF_NONE},
1593       {ui::VKEY_F8, ui::EF_NONE}},
1594      {ui::ET_KEY_PRESSED,
1595       {ui::VKEY_9, ui::EF_COMMAND_DOWN},
1596       {ui::VKEY_F9, ui::EF_NONE},
1597       {ui::VKEY_F9, ui::EF_NONE}},
1598      {ui::ET_KEY_PRESSED,
1599       {ui::VKEY_0, ui::EF_COMMAND_DOWN},
1600       {ui::VKEY_F10, ui::EF_NONE},
1601       {ui::VKEY_F10, ui::EF_NONE}},
1602      {ui::ET_KEY_PRESSED,
1603       {ui::VKEY_OEM_MINUS, ui::EF_COMMAND_DOWN},
1604       {ui::VKEY_F11, ui::EF_NONE},
1605       {ui::VKEY_F11, ui::EF_NONE}},
1606      {ui::ET_KEY_PRESSED,
1607       {ui::VKEY_OEM_PLUS, ui::EF_COMMAND_DOWN},
1608       {ui::VKEY_F12, ui::EF_NONE},
1609       {ui::VKEY_F12, ui::EF_NONE}},
1610
1611      // The function keys should not be rewritten with Search key pressed.
1612      {ui::ET_KEY_PRESSED,
1613       {ui::VKEY_F1, ui::EF_COMMAND_DOWN},
1614       {ui::VKEY_F1, ui::EF_NONE},
1615       {ui::VKEY_F1, ui::EF_FUNCTION_KEY}},
1616      {ui::ET_KEY_PRESSED,
1617       {ui::VKEY_F2, ui::EF_COMMAND_DOWN},
1618       {ui::VKEY_F2, ui::EF_NONE},
1619       {ui::VKEY_F2, ui::EF_FUNCTION_KEY}},
1620      {ui::ET_KEY_PRESSED,
1621       {ui::VKEY_F3, ui::EF_COMMAND_DOWN},
1622       {ui::VKEY_F3, ui::EF_NONE},
1623       {ui::VKEY_F3, ui::EF_FUNCTION_KEY}},
1624      {ui::ET_KEY_PRESSED,
1625       {ui::VKEY_F4, ui::EF_COMMAND_DOWN},
1626       {ui::VKEY_F4, ui::EF_NONE},
1627       {ui::VKEY_F4, ui::EF_FUNCTION_KEY}},
1628      {ui::ET_KEY_PRESSED,
1629       {ui::VKEY_F5, ui::EF_COMMAND_DOWN},
1630       {ui::VKEY_F5, ui::EF_NONE},
1631       {ui::VKEY_F5, ui::EF_FUNCTION_KEY}},
1632      {ui::ET_KEY_PRESSED,
1633       {ui::VKEY_F6, ui::EF_COMMAND_DOWN},
1634       {ui::VKEY_F6, ui::EF_NONE},
1635       {ui::VKEY_F6, ui::EF_FUNCTION_KEY}},
1636      {ui::ET_KEY_PRESSED,
1637       {ui::VKEY_F7, ui::EF_COMMAND_DOWN},
1638       {ui::VKEY_F7, ui::EF_NONE},
1639       {ui::VKEY_F7, ui::EF_FUNCTION_KEY}},
1640      {ui::ET_KEY_PRESSED,
1641       {ui::VKEY_F8, ui::EF_COMMAND_DOWN},
1642       {ui::VKEY_F8, ui::EF_NONE},
1643       {ui::VKEY_F8, ui::EF_FUNCTION_KEY}},
1644      {ui::ET_KEY_PRESSED,
1645       {ui::VKEY_F9, ui::EF_COMMAND_DOWN},
1646       {ui::VKEY_F9, ui::EF_NONE},
1647       {ui::VKEY_F9, ui::EF_FUNCTION_KEY}},
1648      {ui::ET_KEY_PRESSED,
1649       {ui::VKEY_F10, ui::EF_COMMAND_DOWN},
1650       {ui::VKEY_F10, ui::EF_NONE},
1651       {ui::VKEY_F10, ui::EF_FUNCTION_KEY}},
1652      {ui::ET_KEY_PRESSED,
1653       {ui::VKEY_F11, ui::EF_COMMAND_DOWN},
1654       {ui::VKEY_F11, ui::EF_NONE},
1655       {ui::VKEY_F11, ui::EF_FUNCTION_KEY}},
1656      {ui::ET_KEY_PRESSED,
1657       {ui::VKEY_F12, ui::EF_COMMAND_DOWN},
1658       {ui::VKEY_F12, ui::EF_NONE},
1659       {ui::VKEY_F12, ui::EF_FUNCTION_KEY}},
1660  };
1661
1662  for (size_t i = 0; i < arraysize(tests); ++i) {
1663    SCOPED_TRACE(i);
1664    CheckFunctionKeyTestCase(&rewriter, tests[i]);
1665  }
1666}
1667
1668TEST_F(EventRewriterTest, TestRewriteExtendedKeysWithSearchRemapped) {
1669  const CommandLine original_cl(*CommandLine::ForCurrentProcess());
1670
1671  // Remap Search to Control.
1672  TestingPrefServiceSyncable prefs;
1673  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1674  IntegerPrefMember search;
1675  search.Init(prefs::kLanguageRemapSearchKeyTo, &prefs);
1676  search.SetValue(chromeos::input_method::kControlKey);
1677
1678  EventRewriter rewriter(NULL);
1679  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1680  rewriter.set_pref_service_for_testing(&prefs);
1681
1682  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1683      chromeos::switches::kHasChromeOSKeyboard, "");
1684
1685  KeyTestCase tests[] = {
1686      // Alt+Search+Down -> End
1687      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1688       {ui::VKEY_DOWN, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
1689       {ui::VKEY_END, ui::EF_NONE}},
1690
1691      // Shift+Alt+Search+Down -> Shift+End
1692      {KeyTestCase::TEST_ALL, ui::ET_KEY_PRESSED,
1693       {ui::VKEY_DOWN,
1694        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN},
1695       {ui::VKEY_END, ui::EF_SHIFT_DOWN}},
1696  };
1697
1698  for (size_t i = 0; i < arraysize(tests); ++i) {
1699    SCOPED_TRACE(i);
1700    CheckKeyTestCase(&rewriter, tests[i]);
1701  }
1702
1703  *CommandLine::ForCurrentProcess() = original_cl;
1704}
1705
1706TEST_F(EventRewriterTest, TestRewriteKeyEventSentByXSendEvent) {
1707  // Remap Control to Alt.
1708  TestingPrefServiceSyncable prefs;
1709  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1710  IntegerPrefMember control;
1711  control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1712  control.SetValue(chromeos::input_method::kAltKey);
1713
1714  EventRewriter rewriter(NULL);
1715  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1716  rewriter.set_pref_service_for_testing(&prefs);
1717
1718  // Send left control press.
1719  {
1720    ui::KeyEvent keyevent(
1721        ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, ui::EF_FINAL);
1722    scoped_ptr<ui::Event> new_event;
1723    // Control should NOT be remapped to Alt if EF_FINAL is set.
1724    EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
1725              rewriter.RewriteEvent(keyevent, &new_event));
1726    EXPECT_FALSE(new_event);
1727  }
1728#if defined(USE_X11)
1729  // Send left control press, using XI2 native events.
1730  {
1731    ui::ScopedXI2Event xev;
1732    xev.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_CONTROL, 0);
1733    XEvent* xevent = xev;
1734    xevent->xkey.keycode = XKeysymToKeycode(gfx::GetXDisplay(), XK_Control_L);
1735    xevent->xkey.send_event = True;  // XSendEvent() always does this.
1736    ui::KeyEvent keyevent(xev);
1737    scoped_ptr<ui::Event> new_event;
1738    // Control should NOT be remapped to Alt if send_event
1739    // flag in the event is True.
1740    EXPECT_EQ(ui::EVENT_REWRITE_CONTINUE,
1741              rewriter.RewriteEvent(keyevent, &new_event));
1742    EXPECT_FALSE(new_event);
1743  }
1744#endif
1745}
1746
1747TEST_F(EventRewriterTest, TestRewriteNonNativeEvent) {
1748  // Remap Control to Alt.
1749  TestingPrefServiceSyncable prefs;
1750  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1751  IntegerPrefMember control;
1752  control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1753  control.SetValue(chromeos::input_method::kAltKey);
1754
1755  EventRewriter rewriter(NULL);
1756  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1757  rewriter.set_pref_service_for_testing(&prefs);
1758
1759  const int kTouchId = 2;
1760  gfx::Point location(0, 0);
1761  ui::TouchEvent press(
1762      ui::ET_TOUCH_PRESSED, location, kTouchId, base::TimeDelta());
1763  press.set_flags(ui::EF_CONTROL_DOWN);
1764#if defined(USE_X11)
1765  ui::UpdateX11EventForFlags(&press);
1766#endif
1767
1768  scoped_ptr<ui::Event> new_event;
1769  rewriter.RewriteEvent(press, &new_event);
1770  EXPECT_TRUE(new_event);
1771  // Control should be remapped to Alt.
1772  EXPECT_EQ(ui::EF_ALT_DOWN,
1773            new_event->flags() & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN));
1774}
1775
1776// Keeps a buffer of handled events.
1777class EventBuffer : public ui::test::TestEventProcessor {
1778 public:
1779  EventBuffer() {}
1780  virtual ~EventBuffer() {}
1781
1782  void PopEvents(ScopedVector<ui::Event>* events) {
1783    events->clear();
1784    events->swap(events_);
1785  }
1786
1787 private:
1788  // ui::EventProcessor overrides:
1789  virtual ui::EventDispatchDetails OnEventFromSource(
1790      ui::Event* event) OVERRIDE {
1791    if (event->IsKeyEvent()) {
1792      events_.push_back(new ui::KeyEvent(*static_cast<ui::KeyEvent*>(event)));
1793    } else if (event->IsMouseWheelEvent()) {
1794      events_.push_back(
1795          new ui::MouseWheelEvent(*static_cast<ui::MouseWheelEvent*>(event)));
1796    } else if (event->IsMouseEvent()) {
1797      events_.push_back(
1798          new ui::MouseEvent(*static_cast<ui::MouseEvent*>(event)));
1799    }
1800    return ui::EventDispatchDetails();
1801  }
1802
1803  ScopedVector<ui::Event> events_;
1804
1805  DISALLOW_COPY_AND_ASSIGN(EventBuffer);
1806};
1807
1808// Trivial EventSource that does nothing but send events.
1809class TestEventSource : public ui::EventSource {
1810 public:
1811  explicit TestEventSource(ui::EventProcessor* processor)
1812      : processor_(processor) {}
1813  virtual ui::EventProcessor* GetEventProcessor() OVERRIDE {
1814    return processor_;
1815  }
1816  ui::EventDispatchDetails Send(ui::Event* event) {
1817    return SendEventToProcessor(event);
1818  }
1819
1820 private:
1821  ui::EventProcessor* processor_;
1822};
1823
1824// Tests of event rewriting that depend on the Ash window manager.
1825class EventRewriterAshTest : public ash::test::AshTestBase {
1826 public:
1827  EventRewriterAshTest()
1828      : source_(&buffer_),
1829        mock_user_manager_(new chromeos::MockUserManager),
1830        user_manager_enabler_(mock_user_manager_) {}
1831  virtual ~EventRewriterAshTest() {}
1832
1833  bool RewriteFunctionKeys(const ui::Event& event,
1834                           scoped_ptr<ui::Event>* rewritten_event) {
1835    return rewriter_->RewriteEvent(event, rewritten_event);
1836  }
1837
1838  ui::EventDispatchDetails Send(ui::Event* event) {
1839    return source_.Send(event);
1840  }
1841
1842  void SendKeyEvent(ui::EventType type, ui::KeyboardCode key_code) {
1843    ui::KeyEvent press(type, key_code, ui::EF_NONE);
1844    ui::EventDispatchDetails details = Send(&press);
1845    CHECK(!details.dispatcher_destroyed);
1846  }
1847
1848  void SendActivateStickyKeyPattern(ui::KeyboardCode key_code) {
1849    SendKeyEvent(ui::ET_KEY_PRESSED, key_code);
1850    SendKeyEvent(ui::ET_KEY_RELEASED, key_code);
1851  }
1852
1853 protected:
1854  TestingPrefServiceSyncable* prefs() { return &prefs_; }
1855
1856  void PopEvents(ScopedVector<ui::Event>* events) {
1857    buffer_.PopEvents(events);
1858  }
1859
1860  virtual void SetUp() OVERRIDE {
1861    AshTestBase::SetUp();
1862    sticky_keys_controller_ =
1863        ash::Shell::GetInstance()->sticky_keys_controller();
1864    rewriter_.reset(new EventRewriter(sticky_keys_controller_));
1865    chromeos::Preferences::RegisterProfilePrefs(prefs_.registry());
1866    rewriter_->set_pref_service_for_testing(&prefs_);
1867#if defined(USE_X11)
1868    ui::SetUpTouchPadForTest(kTouchPadDeviceId);
1869#endif
1870    source_.AddEventRewriter(rewriter_.get());
1871    sticky_keys_controller_->Enable(true);
1872  }
1873
1874  virtual void TearDown() OVERRIDE {
1875    rewriter_.reset();
1876    AshTestBase::TearDown();
1877  }
1878
1879 protected:
1880  ash::StickyKeysController* sticky_keys_controller_;
1881
1882 private:
1883  scoped_ptr<EventRewriter> rewriter_;
1884
1885  EventBuffer buffer_;
1886  TestEventSource source_;
1887
1888  chromeos::MockUserManager* mock_user_manager_;  // Not owned.
1889  chromeos::ScopedUserManagerEnabler user_manager_enabler_;
1890  TestingPrefServiceSyncable prefs_;
1891
1892  DISALLOW_COPY_AND_ASSIGN(EventRewriterAshTest);
1893};
1894
1895TEST_F(EventRewriterAshTest, TopRowKeysAreFunctionKeys) {
1896  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(1));
1897  ash::wm::WindowState* window_state = ash::wm::GetWindowState(window.get());
1898  window_state->Activate();
1899  ScopedVector<ui::Event> events;
1900
1901  // Create a simulated keypress of F1 targetted at the window.
1902  ui::KeyEvent press_f1(ui::ET_KEY_PRESSED, ui::VKEY_F1, ui::EF_NONE);
1903
1904  // Simulate an apps v2 window that has requested top row keys as function
1905  // keys. The event should not be rewritten.
1906  window_state->set_top_row_keys_are_function_keys(true);
1907  ui::EventDispatchDetails details = Send(&press_f1);
1908  ASSERT_FALSE(details.dispatcher_destroyed);
1909  PopEvents(&events);
1910  EXPECT_EQ(1u, events.size());
1911  EXPECT_EQ(
1912      GetExpectedResultAsString(ui::VKEY_F1, ui::EF_NONE, ui::ET_KEY_PRESSED),
1913      GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
1914
1915  // The event should also not be rewritten if the send-function-keys pref is
1916  // additionally set, for both apps v2 and regular windows.
1917  BooleanPrefMember send_function_keys_pref;
1918  send_function_keys_pref.Init(prefs::kLanguageSendFunctionKeys, prefs());
1919  send_function_keys_pref.SetValue(true);
1920  window_state->set_top_row_keys_are_function_keys(false);
1921  details = Send(&press_f1);
1922  ASSERT_FALSE(details.dispatcher_destroyed);
1923  PopEvents(&events);
1924  EXPECT_EQ(1u, events.size());
1925  EXPECT_EQ(
1926      GetExpectedResultAsString(ui::VKEY_F1, ui::EF_NONE, ui::ET_KEY_PRESSED),
1927      GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
1928
1929  // If the pref isn't set when an event is sent to a regular window, F1 is
1930  // rewritten to the back key.
1931  send_function_keys_pref.SetValue(false);
1932  details = Send(&press_f1);
1933  ASSERT_FALSE(details.dispatcher_destroyed);
1934  PopEvents(&events);
1935  EXPECT_EQ(1u, events.size());
1936  EXPECT_EQ(GetExpectedResultAsString(
1937                ui::VKEY_BROWSER_BACK, ui::EF_NONE, ui::ET_KEY_PRESSED),
1938            GetKeyEventAsString(*static_cast<ui::KeyEvent*>(events[0])));
1939}
1940
1941TEST_F(EventRewriterTest, TestRewrittenModifierClick) {
1942  std::vector<unsigned int> device_list;
1943  device_list.push_back(10);
1944  ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
1945
1946  // Remap Control to Alt.
1947  TestingPrefServiceSyncable prefs;
1948  chromeos::Preferences::RegisterProfilePrefs(prefs.registry());
1949  IntegerPrefMember control;
1950  control.Init(prefs::kLanguageRemapControlKeyTo, &prefs);
1951  control.SetValue(chromeos::input_method::kAltKey);
1952
1953  EventRewriter rewriter(NULL);
1954  rewriter.KeyboardDeviceAddedForTesting(kKeyboardDeviceId, "PC Keyboard");
1955  rewriter.set_pref_service_for_testing(&prefs);
1956
1957  // Check that Control + Left Button is converted (via Alt + Left Button)
1958  // to Right Button.
1959  ui::ScopedXI2Event xev;
1960  xev.InitGenericButtonEvent(10,
1961                             ui::ET_MOUSE_PRESSED,
1962                             gfx::Point(),
1963                             ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN);
1964  ui::MouseEvent press(xev);
1965  // Sanity check.
1966  EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
1967  EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON | ui::EF_CONTROL_DOWN, press.flags());
1968  scoped_ptr<ui::Event> new_event;
1969  const ui::MouseEvent* result =
1970      RewriteMouseButtonEvent(&rewriter, press, &new_event);
1971  EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
1972  EXPECT_FALSE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
1973  EXPECT_FALSE(ui::EF_CONTROL_DOWN & result->flags());
1974  EXPECT_FALSE(ui::EF_ALT_DOWN & result->flags());
1975  EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
1976}
1977
1978TEST_F(EventRewriterTest, DontRewriteIfNotRewritten) {
1979  // TODO(kpschoedel): pending changes for crbug.com/360377
1980  // to |chromeos::EventRewriter::RewriteLocatedEvent()
1981  std::vector<unsigned int> device_list;
1982  device_list.push_back(10);
1983  device_list.push_back(11);
1984  ui::TouchFactory::GetInstance()->SetPointerDeviceForTest(device_list);
1985  TestingPrefServiceSyncable prefs;
1986  EventRewriter rewriter(NULL);
1987  rewriter.set_pref_service_for_testing(&prefs);
1988  const int kLeftAndAltFlag = ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN;
1989
1990  // Test Alt + Left click.
1991  {
1992    ui::MouseEvent press(ui::ET_MOUSE_PRESSED,
1993                         gfx::Point(),
1994                         gfx::Point(),
1995                         kLeftAndAltFlag,
1996                         ui::EF_LEFT_MOUSE_BUTTON);
1997    ui::EventTestApi test_press(&press);
1998    test_press.set_source_device_id(10);
1999    // Sanity check.
2000    EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2001    EXPECT_EQ(kLeftAndAltFlag, press.flags());
2002    scoped_ptr<ui::Event> new_event;
2003    const ui::MouseEvent* result =
2004        RewriteMouseButtonEvent(&rewriter, press, &new_event);
2005    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2006    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2007    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2008  }
2009  {
2010    ui::MouseEvent release(ui::ET_MOUSE_RELEASED,
2011                           gfx::Point(),
2012                           gfx::Point(),
2013                           kLeftAndAltFlag,
2014                           ui::EF_LEFT_MOUSE_BUTTON);
2015    ui::EventTestApi test_release(&release);
2016    test_release.set_source_device_id(10);
2017    scoped_ptr<ui::Event> new_event;
2018    const ui::MouseEvent* result =
2019        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2020    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2021    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2022    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2023  }
2024#if defined(USE_X11)
2025  // Test Alt + Left click, using XI2 native events.
2026  {
2027    ui::ScopedXI2Event xev;
2028    xev.InitGenericButtonEvent(
2029        10, ui::ET_MOUSE_PRESSED, gfx::Point(), kLeftAndAltFlag);
2030    ui::MouseEvent press(xev);
2031    // Sanity check.
2032    EXPECT_EQ(ui::ET_MOUSE_PRESSED, press.type());
2033    EXPECT_EQ(kLeftAndAltFlag, press.flags());
2034    scoped_ptr<ui::Event> new_event;
2035    const ui::MouseEvent* result =
2036        RewriteMouseButtonEvent(&rewriter, press, &new_event);
2037    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2038    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2039    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2040  }
2041  {
2042    ui::ScopedXI2Event xev;
2043    xev.InitGenericButtonEvent(
2044        10, ui::ET_MOUSE_RELEASED, gfx::Point(), kLeftAndAltFlag);
2045    ui::MouseEvent release(xev);
2046    scoped_ptr<ui::Event> new_event;
2047    const ui::MouseEvent* result =
2048        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2049    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2050    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2051    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2052  }
2053#endif
2054
2055  // No ALT in frst click.
2056  {
2057    ui::MouseEvent press(ui::ET_MOUSE_PRESSED,
2058                         gfx::Point(),
2059                         gfx::Point(),
2060                         ui::EF_LEFT_MOUSE_BUTTON,
2061                         ui::EF_LEFT_MOUSE_BUTTON);
2062    ui::EventTestApi test_press(&press);
2063    test_press.set_source_device_id(10);
2064    scoped_ptr<ui::Event> new_event;
2065    const ui::MouseEvent* result =
2066        RewriteMouseButtonEvent(&rewriter, press, &new_event);
2067    EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2068    EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2069  }
2070  {
2071    ui::MouseEvent release(ui::ET_MOUSE_RELEASED,
2072                           gfx::Point(),
2073                           gfx::Point(),
2074                           kLeftAndAltFlag,
2075                           ui::EF_LEFT_MOUSE_BUTTON);
2076    ui::EventTestApi test_release(&release);
2077    test_release.set_source_device_id(10);
2078    scoped_ptr<ui::Event> new_event;
2079    const ui::MouseEvent* result =
2080        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2081    EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2082    EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2083  }
2084#if defined(USE_X11)
2085  // No ALT in frst click, using XI2 native events.
2086  {
2087    ui::ScopedXI2Event xev;
2088    xev.InitGenericButtonEvent(
2089        10, ui::ET_MOUSE_PRESSED, gfx::Point(), ui::EF_LEFT_MOUSE_BUTTON);
2090    ui::MouseEvent press(xev);
2091    scoped_ptr<ui::Event> new_event;
2092    const ui::MouseEvent* result =
2093        RewriteMouseButtonEvent(&rewriter, press, &new_event);
2094    EXPECT_TRUE(ui::EF_LEFT_MOUSE_BUTTON & result->flags());
2095    EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2096  }
2097  {
2098    ui::ScopedXI2Event xev;
2099    xev.InitGenericButtonEvent(
2100        10, ui::ET_MOUSE_RELEASED, gfx::Point(), kLeftAndAltFlag);
2101    ui::MouseEvent release(xev);
2102    scoped_ptr<ui::Event> new_event;
2103    const ui::MouseEvent* result =
2104        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2105    EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2106    EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2107  }
2108#endif
2109
2110  // ALT on different device.
2111  {
2112    ui::MouseEvent press(ui::ET_MOUSE_PRESSED,
2113                         gfx::Point(),
2114                         gfx::Point(),
2115                         kLeftAndAltFlag,
2116                         ui::EF_LEFT_MOUSE_BUTTON);
2117    ui::EventTestApi test_press(&press);
2118    test_press.set_source_device_id(11);
2119    scoped_ptr<ui::Event> new_event;
2120    const ui::MouseEvent* result =
2121        RewriteMouseButtonEvent(&rewriter, press, &new_event);
2122    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2123    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2124    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2125  }
2126  {
2127    ui::MouseEvent release(ui::ET_MOUSE_RELEASED,
2128                           gfx::Point(),
2129                           gfx::Point(),
2130                           kLeftAndAltFlag,
2131                           ui::EF_LEFT_MOUSE_BUTTON);
2132    ui::EventTestApi test_release(&release);
2133    test_release.set_source_device_id(10);
2134    scoped_ptr<ui::Event> new_event;
2135    const ui::MouseEvent* result =
2136        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2137    EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2138    EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2139  }
2140  {
2141    ui::MouseEvent release(ui::ET_MOUSE_RELEASED,
2142                           gfx::Point(),
2143                           gfx::Point(),
2144                           kLeftAndAltFlag,
2145                           ui::EF_LEFT_MOUSE_BUTTON);
2146    ui::EventTestApi test_release(&release);
2147    test_release.set_source_device_id(11);
2148    scoped_ptr<ui::Event> new_event;
2149    const ui::MouseEvent* result =
2150        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2151    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2152    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2153    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2154  }
2155#if defined(USE_X11)
2156  // ALT on different device, using XI2 native events.
2157  {
2158    ui::ScopedXI2Event xev;
2159    xev.InitGenericButtonEvent(
2160        11, ui::ET_MOUSE_PRESSED, gfx::Point(), kLeftAndAltFlag);
2161    ui::MouseEvent press(xev);
2162    scoped_ptr<ui::Event> new_event;
2163    const ui::MouseEvent* result =
2164        RewriteMouseButtonEvent(&rewriter, press, &new_event);
2165    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2166    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2167    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2168  }
2169  {
2170    ui::ScopedXI2Event xev;
2171    xev.InitGenericButtonEvent(
2172        10, ui::ET_MOUSE_RELEASED, gfx::Point(), kLeftAndAltFlag);
2173    ui::MouseEvent release(xev);
2174    scoped_ptr<ui::Event> new_event;
2175    const ui::MouseEvent* result =
2176        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2177    EXPECT_TRUE((ui::EF_LEFT_MOUSE_BUTTON | ui::EF_ALT_DOWN) & result->flags());
2178    EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, result->changed_button_flags());
2179  }
2180  {
2181    ui::ScopedXI2Event xev;
2182    xev.InitGenericButtonEvent(
2183        11, ui::ET_MOUSE_RELEASED, gfx::Point(), kLeftAndAltFlag);
2184    ui::MouseEvent release(xev);
2185    scoped_ptr<ui::Event> new_event;
2186    const ui::MouseEvent* result =
2187        RewriteMouseButtonEvent(&rewriter, release, &new_event);
2188    EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & result->flags());
2189    EXPECT_FALSE(kLeftAndAltFlag & result->flags());
2190    EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, result->changed_button_flags());
2191  }
2192#endif
2193}
2194
2195TEST_F(EventRewriterAshTest, StickyKeyEventDispatchImpl) {
2196  // Test the actual key event dispatch implementation.
2197  ScopedVector<ui::Event> events;
2198
2199  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2200  PopEvents(&events);
2201  EXPECT_EQ(1u, events.size());
2202  EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
2203  EXPECT_EQ(ui::VKEY_CONTROL,
2204            static_cast<ui::KeyEvent*>(events[0])->key_code());
2205
2206  // Test key press event is correctly modified and modifier release
2207  // event is sent.
2208  ui::KeyEvent press(ui::ET_KEY_PRESSED, ui::VKEY_C, ui::EF_NONE);
2209  ui::EventDispatchDetails details = Send(&press);
2210  PopEvents(&events);
2211  EXPECT_EQ(2u, events.size());
2212  EXPECT_EQ(ui::ET_KEY_PRESSED, events[0]->type());
2213  EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
2214  EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2215  EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2216  EXPECT_EQ(ui::VKEY_CONTROL,
2217            static_cast<ui::KeyEvent*>(events[1])->key_code());
2218
2219  // Test key release event is not modified.
2220  ui::KeyEvent release(ui::ET_KEY_RELEASED, ui::VKEY_C, ui::EF_NONE);
2221  details = Send(&release);
2222  ASSERT_FALSE(details.dispatcher_destroyed);
2223  PopEvents(&events);
2224  EXPECT_EQ(1u, events.size());
2225  EXPECT_EQ(ui::ET_KEY_RELEASED, events[0]->type());
2226  EXPECT_EQ(ui::VKEY_C, static_cast<ui::KeyEvent*>(events[0])->key_code());
2227  EXPECT_FALSE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2228}
2229
2230TEST_F(EventRewriterAshTest, MouseEventDispatchImpl) {
2231  ScopedVector<ui::Event> events;
2232
2233  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2234  PopEvents(&events);
2235
2236  // Test mouse press event is correctly modified.
2237  gfx::Point location(0, 0);
2238  ui::MouseEvent press(ui::ET_MOUSE_PRESSED,
2239                       location,
2240                       location,
2241                       ui::EF_LEFT_MOUSE_BUTTON,
2242                       ui::EF_LEFT_MOUSE_BUTTON);
2243  ui::EventDispatchDetails details = Send(&press);
2244  ASSERT_FALSE(details.dispatcher_destroyed);
2245  PopEvents(&events);
2246  EXPECT_EQ(1u, events.size());
2247  EXPECT_EQ(ui::ET_MOUSE_PRESSED, events[0]->type());
2248  EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2249
2250  // Test mouse release event is correctly modified and modifier release
2251  // event is sent. The mouse event should have the correct DIP location.
2252  ui::MouseEvent release(ui::ET_MOUSE_RELEASED,
2253                         location,
2254                         location,
2255                         ui::EF_LEFT_MOUSE_BUTTON,
2256                         ui::EF_LEFT_MOUSE_BUTTON);
2257  details = Send(&release);
2258  ASSERT_FALSE(details.dispatcher_destroyed);
2259  PopEvents(&events);
2260  EXPECT_EQ(2u, events.size());
2261  EXPECT_EQ(ui::ET_MOUSE_RELEASED, events[0]->type());
2262  EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2263  EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2264  EXPECT_EQ(ui::VKEY_CONTROL,
2265            static_cast<ui::KeyEvent*>(events[1])->key_code());
2266}
2267
2268TEST_F(EventRewriterAshTest, MouseWheelEventDispatchImpl) {
2269  ScopedVector<ui::Event> events;
2270
2271  // Test positive mouse wheel event is correctly modified and modifier release
2272  // event is sent.
2273  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2274  PopEvents(&events);
2275  gfx::Point location(0, 0);
2276  ui::MouseEvent mev(ui::ET_MOUSEWHEEL,
2277                     location,
2278                     location,
2279                     ui::EF_LEFT_MOUSE_BUTTON,
2280                     ui::EF_LEFT_MOUSE_BUTTON);
2281  ui::MouseWheelEvent positive(mev, 0, ui::MouseWheelEvent::kWheelDelta);
2282  ui::EventDispatchDetails details = Send(&positive);
2283  ASSERT_FALSE(details.dispatcher_destroyed);
2284  PopEvents(&events);
2285  EXPECT_EQ(2u, events.size());
2286  EXPECT_TRUE(events[0]->IsMouseWheelEvent());
2287  EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2288  EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2289  EXPECT_EQ(ui::VKEY_CONTROL,
2290            static_cast<ui::KeyEvent*>(events[1])->key_code());
2291
2292  // Test negative mouse wheel event is correctly modified and modifier release
2293  // event is sent.
2294  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2295  PopEvents(&events);
2296  ui::MouseWheelEvent negative(mev, 0, -ui::MouseWheelEvent::kWheelDelta);
2297  details = Send(&negative);
2298  ASSERT_FALSE(details.dispatcher_destroyed);
2299  PopEvents(&events);
2300  EXPECT_EQ(2u, events.size());
2301  EXPECT_TRUE(events[0]->IsMouseWheelEvent());
2302  EXPECT_TRUE(events[0]->flags() & ui::EF_CONTROL_DOWN);
2303  EXPECT_EQ(ui::ET_KEY_RELEASED, events[1]->type());
2304  EXPECT_EQ(ui::VKEY_CONTROL,
2305            static_cast<ui::KeyEvent*>(events[1])->key_code());
2306}
2307
2308class StickyKeysOverlayTest : public EventRewriterAshTest {
2309 public:
2310  StickyKeysOverlayTest() : overlay_(NULL) {}
2311
2312  virtual ~StickyKeysOverlayTest() {}
2313
2314  virtual void SetUp() OVERRIDE {
2315    EventRewriterAshTest::SetUp();
2316    overlay_ = sticky_keys_controller_->GetOverlayForTest();
2317    ASSERT_TRUE(overlay_);
2318  }
2319
2320  ash::StickyKeysOverlay* overlay_;
2321};
2322
2323TEST_F(StickyKeysOverlayTest, OneModifierEnabled) {
2324  EXPECT_FALSE(overlay_->is_visible());
2325  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2326            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2327
2328  // Pressing modifier key should show overlay.
2329  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2330  EXPECT_TRUE(overlay_->is_visible());
2331  EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2332            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2333
2334  // Pressing a normal key should hide overlay.
2335  SendActivateStickyKeyPattern(ui::VKEY_T);
2336  EXPECT_FALSE(overlay_->is_visible());
2337  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2338            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2339}
2340
2341TEST_F(StickyKeysOverlayTest, TwoModifiersEnabled) {
2342  EXPECT_FALSE(overlay_->is_visible());
2343  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2344            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2345  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2346            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2347
2348  // Pressing two modifiers should show overlay.
2349  SendActivateStickyKeyPattern(ui::VKEY_SHIFT);
2350  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2351  EXPECT_TRUE(overlay_->is_visible());
2352  EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2353            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2354  EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2355            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2356
2357  // Pressing a normal key should hide overlay.
2358  SendActivateStickyKeyPattern(ui::VKEY_N);
2359  EXPECT_FALSE(overlay_->is_visible());
2360  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2361            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2362  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2363            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2364}
2365
2366TEST_F(StickyKeysOverlayTest, LockedModifier) {
2367  EXPECT_FALSE(overlay_->is_visible());
2368  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2369            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2370
2371  // Pressing a modifier key twice should lock modifier and show overlay.
2372  SendActivateStickyKeyPattern(ui::VKEY_LMENU);
2373  SendActivateStickyKeyPattern(ui::VKEY_LMENU);
2374  EXPECT_TRUE(overlay_->is_visible());
2375  EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2376            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2377
2378  // Pressing a normal key should not hide overlay.
2379  SendActivateStickyKeyPattern(ui::VKEY_D);
2380  EXPECT_TRUE(overlay_->is_visible());
2381  EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2382            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2383}
2384
2385TEST_F(StickyKeysOverlayTest, LockedAndNormalModifier) {
2386  EXPECT_FALSE(overlay_->is_visible());
2387  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2388            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2389  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2390            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2391
2392  // Pressing a modifier key twice should lock modifier and show overlay.
2393  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2394  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2395  EXPECT_TRUE(overlay_->is_visible());
2396  EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2397            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2398
2399  // Pressing another modifier key should still show overlay.
2400  SendActivateStickyKeyPattern(ui::VKEY_SHIFT);
2401  EXPECT_TRUE(overlay_->is_visible());
2402  EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2403            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2404  EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2405            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2406
2407  // Pressing a normal key should not hide overlay but disable normal modifier.
2408  SendActivateStickyKeyPattern(ui::VKEY_D);
2409  EXPECT_TRUE(overlay_->is_visible());
2410  EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2411            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2412  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2413            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2414}
2415
2416TEST_F(StickyKeysOverlayTest, ModifiersDisabled) {
2417  EXPECT_FALSE(overlay_->is_visible());
2418  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2419            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2420  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2421            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2422  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2423            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2424
2425  // Enable modifiers.
2426  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2427  SendActivateStickyKeyPattern(ui::VKEY_SHIFT);
2428  SendActivateStickyKeyPattern(ui::VKEY_SHIFT);
2429  SendActivateStickyKeyPattern(ui::VKEY_LMENU);
2430
2431  EXPECT_TRUE(overlay_->is_visible());
2432  EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2433            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2434  EXPECT_EQ(ash::STICKY_KEY_STATE_LOCKED,
2435            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2436  EXPECT_EQ(ash::STICKY_KEY_STATE_ENABLED,
2437            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2438
2439  // Disable modifiers and overlay should be hidden.
2440  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2441  SendActivateStickyKeyPattern(ui::VKEY_CONTROL);
2442  SendActivateStickyKeyPattern(ui::VKEY_SHIFT);
2443  SendActivateStickyKeyPattern(ui::VKEY_LMENU);
2444  SendActivateStickyKeyPattern(ui::VKEY_LMENU);
2445
2446  EXPECT_FALSE(overlay_->is_visible());
2447  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2448            overlay_->GetModifierKeyState(ui::EF_CONTROL_DOWN));
2449  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2450            overlay_->GetModifierKeyState(ui::EF_SHIFT_DOWN));
2451  EXPECT_EQ(ash::STICKY_KEY_STATE_DISABLED,
2452            overlay_->GetModifierKeyState(ui::EF_ALT_DOWN));
2453}
2454
2455TEST_F(StickyKeysOverlayTest, ModifierVisibility) {
2456  // All but AltGr and Mod3 should initially be visible.
2457  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
2458  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
2459  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
2460  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2461  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2462
2463  // Turn all modifiers on.
2464  sticky_keys_controller_->SetModifiersEnabled(true, true);
2465  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_CONTROL_DOWN));
2466  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_SHIFT_DOWN));
2467  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALT_DOWN));
2468  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2469  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2470
2471  // Turn off Mod3.
2472  sticky_keys_controller_->SetModifiersEnabled(false, true);
2473  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2474  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2475
2476  // Turn off AltGr.
2477  sticky_keys_controller_->SetModifiersEnabled(true, false);
2478  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2479  EXPECT_TRUE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2480
2481  // Turn off AltGr and Mod3.
2482  sticky_keys_controller_->SetModifiersEnabled(false, false);
2483  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_ALTGR_DOWN));
2484  EXPECT_FALSE(overlay_->GetModifierVisible(ui::EF_MOD3_DOWN));
2485}
2486
2487}  // namespace chromeos
2488