1// Copyright (c) 2012 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 "ash/accelerators/accelerator_controller.h"
6
7#include "ash/accelerators/accelerator_table.h"
8#include "ash/accessibility_delegate.h"
9#include "ash/ash_switches.h"
10#include "ash/display/display_manager.h"
11#include "ash/ime_control_delegate.h"
12#include "ash/screen_util.h"
13#include "ash/shell.h"
14#include "ash/shell_window_ids.h"
15#include "ash/system/brightness_control_delegate.h"
16#include "ash/system/keyboard_brightness/keyboard_brightness_control_delegate.h"
17#include "ash/system/tray/system_tray_delegate.h"
18#include "ash/test/ash_test_base.h"
19#include "ash/test/display_manager_test_api.h"
20#include "ash/test/test_screenshot_delegate.h"
21#include "ash/test/test_session_state_animator.h"
22#include "ash/test/test_shell_delegate.h"
23#include "ash/test/test_volume_control_delegate.h"
24#include "ash/volume_control_delegate.h"
25#include "ash/wm/lock_state_controller.h"
26#include "ash/wm/window_state.h"
27#include "ash/wm/window_util.h"
28#include "ash/wm/wm_event.h"
29#include "base/command_line.h"
30#include "ui/aura/client/aura_constants.h"
31#include "ui/aura/test/test_window_delegate.h"
32#include "ui/aura/test/test_windows.h"
33#include "ui/aura/window.h"
34#include "ui/events/event.h"
35#include "ui/events/event_processor.h"
36#include "ui/events/test/event_generator.h"
37#include "ui/gfx/screen.h"
38#include "ui/views/widget/widget.h"
39
40#if defined(USE_X11)
41#include <X11/Xlib.h>
42#include "ui/events/test/events_test_utils_x11.h"
43#endif
44
45namespace ash {
46
47namespace {
48
49class TestTarget : public ui::AcceleratorTarget {
50 public:
51  TestTarget() : accelerator_pressed_count_(0), accelerator_repeat_count_(0) {}
52  virtual ~TestTarget() {}
53
54  int accelerator_pressed_count() const {
55    return accelerator_pressed_count_;
56  }
57
58  int accelerator_repeat_count() const { return accelerator_repeat_count_; }
59
60  void reset() {
61    accelerator_pressed_count_ = 0;
62    accelerator_repeat_count_ = 0;
63  }
64
65  // Overridden from ui::AcceleratorTarget:
66  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
67  virtual bool CanHandleAccelerators() const OVERRIDE;
68
69 private:
70  int accelerator_pressed_count_;
71  int accelerator_repeat_count_;
72
73  DISALLOW_COPY_AND_ASSIGN(TestTarget);
74};
75
76class ReleaseAccelerator : public ui::Accelerator {
77 public:
78  ReleaseAccelerator(ui::KeyboardCode keycode, int modifiers)
79      : ui::Accelerator(keycode, modifiers) {
80    set_type(ui::ET_KEY_RELEASED);
81  }
82};
83
84class DummyBrightnessControlDelegate : public BrightnessControlDelegate {
85 public:
86  explicit DummyBrightnessControlDelegate(bool consume)
87      : consume_(consume),
88        handle_brightness_down_count_(0),
89        handle_brightness_up_count_(0) {
90  }
91  virtual ~DummyBrightnessControlDelegate() {}
92
93  virtual bool HandleBrightnessDown(
94      const ui::Accelerator& accelerator) OVERRIDE {
95    ++handle_brightness_down_count_;
96    last_accelerator_ = accelerator;
97    return consume_;
98  }
99  virtual bool HandleBrightnessUp(const ui::Accelerator& accelerator) OVERRIDE {
100    ++handle_brightness_up_count_;
101    last_accelerator_ = accelerator;
102    return consume_;
103  }
104  virtual void SetBrightnessPercent(double percent, bool gradual) OVERRIDE {}
105  virtual void GetBrightnessPercent(
106      const base::Callback<void(double)>& callback) OVERRIDE {
107    callback.Run(100.0);
108  }
109
110  int handle_brightness_down_count() const {
111    return handle_brightness_down_count_;
112  }
113  int handle_brightness_up_count() const {
114    return handle_brightness_up_count_;
115  }
116  const ui::Accelerator& last_accelerator() const {
117    return last_accelerator_;
118  }
119
120 private:
121  const bool consume_;
122  int handle_brightness_down_count_;
123  int handle_brightness_up_count_;
124  ui::Accelerator last_accelerator_;
125
126  DISALLOW_COPY_AND_ASSIGN(DummyBrightnessControlDelegate);
127};
128
129class DummyImeControlDelegate : public ImeControlDelegate {
130 public:
131  explicit DummyImeControlDelegate(bool consume)
132      : consume_(consume),
133        handle_next_ime_count_(0),
134        handle_previous_ime_count_(0),
135        handle_switch_ime_count_(0) {
136  }
137  virtual ~DummyImeControlDelegate() {}
138
139  virtual void HandleNextIme() OVERRIDE {
140    ++handle_next_ime_count_;
141  }
142  virtual bool HandlePreviousIme(const ui::Accelerator& accelerator) OVERRIDE {
143    ++handle_previous_ime_count_;
144    last_accelerator_ = accelerator;
145    return consume_;
146  }
147  virtual bool HandleSwitchIme(const ui::Accelerator& accelerator) OVERRIDE {
148    ++handle_switch_ime_count_;
149    last_accelerator_ = accelerator;
150    return consume_;
151  }
152
153  int handle_next_ime_count() const {
154    return handle_next_ime_count_;
155  }
156  int handle_previous_ime_count() const {
157    return handle_previous_ime_count_;
158  }
159  int handle_switch_ime_count() const {
160    return handle_switch_ime_count_;
161  }
162  const ui::Accelerator& last_accelerator() const {
163    return last_accelerator_;
164  }
165  virtual ui::Accelerator RemapAccelerator(
166      const ui::Accelerator& accelerator) OVERRIDE {
167    return ui::Accelerator(accelerator);
168  }
169
170 private:
171  const bool consume_;
172  int handle_next_ime_count_;
173  int handle_previous_ime_count_;
174  int handle_switch_ime_count_;
175  ui::Accelerator last_accelerator_;
176
177  DISALLOW_COPY_AND_ASSIGN(DummyImeControlDelegate);
178};
179
180class DummyKeyboardBrightnessControlDelegate
181    : public KeyboardBrightnessControlDelegate {
182 public:
183  explicit DummyKeyboardBrightnessControlDelegate(bool consume)
184      : consume_(consume),
185        handle_keyboard_brightness_down_count_(0),
186        handle_keyboard_brightness_up_count_(0) {
187  }
188  virtual ~DummyKeyboardBrightnessControlDelegate() {}
189
190  virtual bool HandleKeyboardBrightnessDown(
191      const ui::Accelerator& accelerator) OVERRIDE {
192    ++handle_keyboard_brightness_down_count_;
193    last_accelerator_ = accelerator;
194    return consume_;
195  }
196
197  virtual bool HandleKeyboardBrightnessUp(
198      const ui::Accelerator& accelerator) OVERRIDE {
199    ++handle_keyboard_brightness_up_count_;
200    last_accelerator_ = accelerator;
201    return consume_;
202  }
203
204  int handle_keyboard_brightness_down_count() const {
205    return handle_keyboard_brightness_down_count_;
206  }
207
208  int handle_keyboard_brightness_up_count() const {
209    return handle_keyboard_brightness_up_count_;
210  }
211
212  const ui::Accelerator& last_accelerator() const {
213    return last_accelerator_;
214  }
215
216 private:
217  const bool consume_;
218  int handle_keyboard_brightness_down_count_;
219  int handle_keyboard_brightness_up_count_;
220  ui::Accelerator last_accelerator_;
221
222  DISALLOW_COPY_AND_ASSIGN(DummyKeyboardBrightnessControlDelegate);
223};
224
225bool TestTarget::AcceleratorPressed(const ui::Accelerator& accelerator) {
226  if (accelerator.IsRepeat())
227    ++accelerator_repeat_count_;
228  else
229    ++accelerator_pressed_count_;
230  return true;
231}
232
233bool TestTarget::CanHandleAccelerators() const {
234  return true;
235}
236
237}  // namespace
238
239class AcceleratorControllerTest : public test::AshTestBase {
240 public:
241  AcceleratorControllerTest() {}
242  virtual ~AcceleratorControllerTest() {}
243
244 protected:
245  void EnableInternalDisplay() {
246    test::DisplayManagerTestApi(Shell::GetInstance()->display_manager()).
247        SetFirstDisplayAsInternalDisplay();
248  }
249
250  static AcceleratorController* GetController();
251
252  // Several functions to access ExitWarningHandler (as friend).
253  static void StubForTest(ExitWarningHandler* ewh) {
254    ewh->stub_timer_for_test_ = true;
255  }
256  static void Reset(ExitWarningHandler* ewh) {
257    ewh->state_ = ExitWarningHandler::IDLE;
258  }
259  static void SimulateTimerExpired(ExitWarningHandler* ewh) {
260    ewh->TimerAction();
261  }
262  static bool is_ui_shown(ExitWarningHandler* ewh) {
263    return !!ewh->widget_;
264  }
265  static bool is_idle(ExitWarningHandler* ewh) {
266    return ewh->state_ == ExitWarningHandler::IDLE;
267  }
268  static bool is_exiting(ExitWarningHandler* ewh) {
269    return ewh->state_ == ExitWarningHandler::EXITING;
270  }
271
272 private:
273  DISALLOW_COPY_AND_ASSIGN(AcceleratorControllerTest);
274};
275
276AcceleratorController* AcceleratorControllerTest::GetController() {
277  return Shell::GetInstance()->accelerator_controller();
278}
279
280#if !defined(OS_WIN)
281// Double press of exit shortcut => exiting
282TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestDoublePress) {
283  ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
284  ui::Accelerator release(press);
285  release.set_type(ui::ET_KEY_RELEASED);
286  ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
287  ASSERT_TRUE(!!ewh);
288  StubForTest(ewh);
289  EXPECT_TRUE(is_idle(ewh));
290  EXPECT_FALSE(is_ui_shown(ewh));
291  EXPECT_TRUE(GetController()->Process(press));
292  EXPECT_FALSE(GetController()->Process(release));
293  EXPECT_FALSE(is_idle(ewh));
294  EXPECT_TRUE(is_ui_shown(ewh));
295  EXPECT_TRUE(GetController()->Process(press));  // second press before timer.
296  EXPECT_FALSE(GetController()->Process(release));
297  SimulateTimerExpired(ewh);
298  EXPECT_TRUE(is_exiting(ewh));
299  EXPECT_FALSE(is_ui_shown(ewh));
300  Reset(ewh);
301}
302
303// Single press of exit shortcut before timer => idle
304TEST_F(AcceleratorControllerTest, ExitWarningHandlerTestSinglePress) {
305  ui::Accelerator press(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN);
306  ui::Accelerator release(press);
307  release.set_type(ui::ET_KEY_RELEASED);
308  ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
309  ASSERT_TRUE(!!ewh);
310  StubForTest(ewh);
311  EXPECT_TRUE(is_idle(ewh));
312  EXPECT_FALSE(is_ui_shown(ewh));
313  EXPECT_TRUE(GetController()->Process(press));
314  EXPECT_FALSE(GetController()->Process(release));
315  EXPECT_FALSE(is_idle(ewh));
316  EXPECT_TRUE(is_ui_shown(ewh));
317  SimulateTimerExpired(ewh);
318  EXPECT_TRUE(is_idle(ewh));
319  EXPECT_FALSE(is_ui_shown(ewh));
320  Reset(ewh);
321}
322
323// Shutdown ash with exit warning bubble open should not crash.
324TEST_F(AcceleratorControllerTest, LingeringExitWarningBubble) {
325  ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
326  ASSERT_TRUE(!!ewh);
327  StubForTest(ewh);
328
329  // Trigger once to show the bubble.
330  ewh->HandleAccelerator();
331  EXPECT_FALSE(is_idle(ewh));
332  EXPECT_TRUE(is_ui_shown(ewh));
333
334  // Exit ash and there should be no crash
335}
336#endif  // !defined(OS_WIN)
337
338TEST_F(AcceleratorControllerTest, Register) {
339  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
340  TestTarget target;
341  GetController()->Register(accelerator_a, &target);
342
343  // The registered accelerator is processed.
344  EXPECT_TRUE(GetController()->Process(accelerator_a));
345  EXPECT_EQ(1, target.accelerator_pressed_count());
346}
347
348TEST_F(AcceleratorControllerTest, RegisterMultipleTarget) {
349  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
350  TestTarget target1;
351  GetController()->Register(accelerator_a, &target1);
352  TestTarget target2;
353  GetController()->Register(accelerator_a, &target2);
354
355  // If multiple targets are registered with the same accelerator, the target
356  // registered later processes the accelerator.
357  EXPECT_TRUE(GetController()->Process(accelerator_a));
358  EXPECT_EQ(0, target1.accelerator_pressed_count());
359  EXPECT_EQ(1, target2.accelerator_pressed_count());
360}
361
362TEST_F(AcceleratorControllerTest, Unregister) {
363  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
364  TestTarget target;
365  GetController()->Register(accelerator_a, &target);
366  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
367  GetController()->Register(accelerator_b, &target);
368
369  // Unregistering a different accelerator does not affect the other
370  // accelerator.
371  GetController()->Unregister(accelerator_b, &target);
372  EXPECT_TRUE(GetController()->Process(accelerator_a));
373  EXPECT_EQ(1, target.accelerator_pressed_count());
374
375  // The unregistered accelerator is no longer processed.
376  target.reset();
377  GetController()->Unregister(accelerator_a, &target);
378  EXPECT_FALSE(GetController()->Process(accelerator_a));
379  EXPECT_EQ(0, target.accelerator_pressed_count());
380}
381
382TEST_F(AcceleratorControllerTest, UnregisterAll) {
383  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
384  TestTarget target1;
385  GetController()->Register(accelerator_a, &target1);
386  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
387  GetController()->Register(accelerator_b, &target1);
388  const ui::Accelerator accelerator_c(ui::VKEY_C, ui::EF_NONE);
389  TestTarget target2;
390  GetController()->Register(accelerator_c, &target2);
391  GetController()->UnregisterAll(&target1);
392
393  // All the accelerators registered for |target1| are no longer processed.
394  EXPECT_FALSE(GetController()->Process(accelerator_a));
395  EXPECT_FALSE(GetController()->Process(accelerator_b));
396  EXPECT_EQ(0, target1.accelerator_pressed_count());
397
398  // UnregisterAll with a different target does not affect the other target.
399  EXPECT_TRUE(GetController()->Process(accelerator_c));
400  EXPECT_EQ(1, target2.accelerator_pressed_count());
401}
402
403TEST_F(AcceleratorControllerTest, Process) {
404  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
405  TestTarget target1;
406  GetController()->Register(accelerator_a, &target1);
407
408  // The registered accelerator is processed.
409  EXPECT_TRUE(GetController()->Process(accelerator_a));
410  EXPECT_EQ(1, target1.accelerator_pressed_count());
411
412  // The non-registered accelerator is not processed.
413  const ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_NONE);
414  EXPECT_FALSE(GetController()->Process(accelerator_b));
415}
416
417TEST_F(AcceleratorControllerTest, IsRegistered) {
418  const ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
419  const ui::Accelerator accelerator_shift_a(ui::VKEY_A, ui::EF_SHIFT_DOWN);
420  TestTarget target;
421  GetController()->Register(accelerator_a, &target);
422  EXPECT_TRUE(GetController()->IsRegistered(accelerator_a));
423  EXPECT_FALSE(GetController()->IsRegistered(accelerator_shift_a));
424  GetController()->UnregisterAll(&target);
425  EXPECT_FALSE(GetController()->IsRegistered(accelerator_a));
426}
427
428TEST_F(AcceleratorControllerTest, WindowSnap) {
429  scoped_ptr<aura::Window> window(
430      CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
431  const ui::Accelerator dummy;
432
433  wm::WindowState* window_state = wm::GetWindowState(window.get());
434
435  window_state->Activate();
436
437  {
438    GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
439    gfx::Rect expected_bounds = wm::GetDefaultLeftSnappedWindowBoundsInParent(
440        window.get());
441    EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
442  }
443  {
444    GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
445    gfx::Rect expected_bounds = wm::GetDefaultRightSnappedWindowBoundsInParent(
446        window.get());
447    EXPECT_EQ(expected_bounds.ToString(), window->bounds().ToString());
448  }
449  {
450    gfx::Rect normal_bounds = window_state->GetRestoreBoundsInParent();
451
452    GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
453    EXPECT_TRUE(window_state->IsMaximized());
454    EXPECT_NE(normal_bounds.ToString(), window->bounds().ToString());
455
456    GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
457    EXPECT_FALSE(window_state->IsMaximized());
458    // Window gets restored to its restore bounds since side-maximized state
459    // is treated as a "maximized" state.
460    EXPECT_EQ(normal_bounds.ToString(), window->bounds().ToString());
461
462    GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
463    GetController()->PerformAction(WINDOW_SNAP_LEFT, dummy);
464    EXPECT_FALSE(window_state->IsMaximized());
465
466    GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
467    GetController()->PerformAction(WINDOW_SNAP_RIGHT, dummy);
468    EXPECT_FALSE(window_state->IsMaximized());
469
470    GetController()->PerformAction(TOGGLE_MAXIMIZED, dummy);
471    EXPECT_TRUE(window_state->IsMaximized());
472    GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
473    EXPECT_FALSE(window_state->IsMaximized());
474    EXPECT_TRUE(window_state->IsMinimized());
475    window_state->Restore();
476    window_state->Activate();
477  }
478  {
479    GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
480    EXPECT_TRUE(window_state->IsMinimized());
481  }
482}
483
484TEST_F(AcceleratorControllerTest, CenterWindowAccelerator) {
485  scoped_ptr<aura::Window> window(
486      CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
487  const ui::Accelerator dummy;
488  wm::WindowState* window_state = wm::GetWindowState(window.get());
489  window_state->Activate();
490
491  // Center the window using accelerator.
492  GetController()->PerformAction(WINDOW_POSITION_CENTER, dummy);
493  gfx::Rect work_area =
494      Shell::GetScreen()->GetDisplayNearestWindow(window.get()).work_area();
495  gfx::Rect bounds = window->GetBoundsInScreen();
496  EXPECT_NEAR(bounds.x() - work_area.x(),
497              work_area.right() - bounds.right(),
498              1);
499  EXPECT_NEAR(bounds.y() - work_area.y(),
500              work_area.bottom() - bounds.bottom(),
501              1);
502
503  // Add the window to docked container and try to center it.
504  window->SetBounds(gfx::Rect(0, 0, 20, 20));
505  aura::Window* docked_container = Shell::GetContainer(
506      window->GetRootWindow(), kShellWindowId_DockedContainer);
507  docked_container->AddChild(window.get());
508  gfx::Rect docked_bounds = window->GetBoundsInScreen();
509  GetController()->PerformAction(WINDOW_POSITION_CENTER, dummy);
510  // It should not get centered and should remain docked.
511  EXPECT_EQ(kShellWindowId_DockedContainer, window->parent()->id());
512  EXPECT_EQ(docked_bounds.ToString(), window->GetBoundsInScreen().ToString());
513}
514
515TEST_F(AcceleratorControllerTest, AutoRepeat) {
516  ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_CONTROL_DOWN);
517  accelerator_a.set_type(ui::ET_KEY_PRESSED);
518  TestTarget target_a;
519  GetController()->Register(accelerator_a, &target_a);
520  ui::Accelerator accelerator_b(ui::VKEY_B, ui::EF_CONTROL_DOWN);
521  accelerator_b.set_type(ui::ET_KEY_PRESSED);
522  TestTarget target_b;
523  GetController()->Register(accelerator_b, &target_b);
524
525  ui::test::EventGenerator& generator = GetEventGenerator();
526  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
527  generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
528
529  EXPECT_EQ(1, target_a.accelerator_pressed_count());
530  EXPECT_EQ(0, target_a.accelerator_repeat_count());
531
532  // Long press should generate one
533  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
534  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
535  EXPECT_EQ(2, target_a.accelerator_pressed_count());
536  EXPECT_EQ(1, target_a.accelerator_repeat_count());
537  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
538  EXPECT_EQ(2, target_a.accelerator_pressed_count());
539  EXPECT_EQ(2, target_a.accelerator_repeat_count());
540  generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
541  EXPECT_EQ(2, target_a.accelerator_pressed_count());
542  EXPECT_EQ(2, target_a.accelerator_repeat_count());
543
544  // Long press was intercepted by another key press.
545  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
546  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
547  generator.PressKey(ui::VKEY_B, ui::EF_CONTROL_DOWN);
548  generator.ReleaseKey(ui::VKEY_B, ui::EF_CONTROL_DOWN);
549  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
550  generator.PressKey(ui::VKEY_A, ui::EF_CONTROL_DOWN | ui::EF_IS_REPEAT);
551  generator.ReleaseKey(ui::VKEY_A, ui::EF_CONTROL_DOWN);
552
553  EXPECT_EQ(1, target_b.accelerator_pressed_count());
554  EXPECT_EQ(0, target_b.accelerator_repeat_count());
555  EXPECT_EQ(4, target_a.accelerator_pressed_count());
556  EXPECT_EQ(4, target_a.accelerator_repeat_count());
557}
558
559TEST_F(AcceleratorControllerTest, Previous) {
560  ui::test::EventGenerator& generator = GetEventGenerator();
561  generator.PressKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
562  generator.ReleaseKey(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
563
564  EXPECT_EQ(ui::VKEY_VOLUME_MUTE,
565            GetController()->previous_accelerator_for_test().key_code());
566  EXPECT_EQ(ui::EF_NONE,
567            GetController()->previous_accelerator_for_test().modifiers());
568
569  generator.PressKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN);
570  generator.ReleaseKey(ui::VKEY_TAB, ui::EF_CONTROL_DOWN);
571
572  EXPECT_EQ(ui::VKEY_TAB,
573            GetController()->previous_accelerator_for_test().key_code());
574  EXPECT_EQ(ui::EF_CONTROL_DOWN,
575            GetController()->previous_accelerator_for_test().modifiers());
576}
577
578TEST_F(AcceleratorControllerTest, DontRepeatToggleFullscreen) {
579  const AcceleratorData accelerators[] = {
580      {true, ui::VKEY_J, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN},
581      {true, ui::VKEY_K, ui::EF_ALT_DOWN, TOGGLE_FULLSCREEN},
582  };
583  GetController()->RegisterAccelerators(accelerators, arraysize(accelerators));
584
585  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
586  params.context = CurrentContext();
587  params.bounds = gfx::Rect(5, 5, 20, 20);
588  views::Widget* widget = new views::Widget;
589  widget->Init(params);
590  widget->Show();
591  widget->Activate();
592  widget->GetNativeView()->SetProperty(aura::client::kCanMaximizeKey, true);
593
594  ui::test::EventGenerator& generator = GetEventGenerator();
595  wm::WindowState* window_state = wm::GetWindowState(widget->GetNativeView());
596
597  // Toggling not suppressed.
598  generator.PressKey(ui::VKEY_J, ui::EF_ALT_DOWN);
599  EXPECT_TRUE(window_state->IsFullscreen());
600
601  // The same accelerator - toggling suppressed.
602  generator.PressKey(ui::VKEY_J, ui::EF_ALT_DOWN | ui::EF_IS_REPEAT);
603  EXPECT_TRUE(window_state->IsFullscreen());
604
605  // Different accelerator.
606  generator.PressKey(ui::VKEY_K, ui::EF_ALT_DOWN);
607  EXPECT_FALSE(window_state->IsFullscreen());
608}
609
610// TODO(oshima): Fix this test to use EventGenerator.
611#if defined(OS_WIN)
612// crbug.com/317592
613#define MAYBE_ProcessOnce DISABLED_ProcessOnce
614#else
615#define MAYBE_ProcessOnce ProcessOnce
616#endif
617
618#if defined(OS_WIN) || defined(USE_X11)
619TEST_F(AcceleratorControllerTest, MAYBE_ProcessOnce) {
620  ui::Accelerator accelerator_a(ui::VKEY_A, ui::EF_NONE);
621  TestTarget target;
622  GetController()->Register(accelerator_a, &target);
623
624  // The accelerator is processed only once.
625  ui::EventProcessor* dispatcher =
626      Shell::GetPrimaryRootWindow()->GetHost()->event_processor();
627#if defined(OS_WIN)
628  MSG msg1 = { NULL, WM_KEYDOWN, ui::VKEY_A, 0 };
629  ui::KeyEvent key_event1(msg1);
630  key_event1.SetTranslated(true);
631  ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&key_event1);
632  EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed);
633
634  MSG msg2 = { NULL, WM_CHAR, L'A', 0 };
635  ui::KeyEvent key_event2(msg2);
636  key_event2.SetTranslated(true);
637  details = dispatcher->OnEventFromSource(&key_event2);
638  EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed);
639
640  MSG msg3 = { NULL, WM_KEYUP, ui::VKEY_A, 0 };
641  ui::KeyEvent key_event3(msg3);
642  key_event3.SetTranslated(true);
643  details = dispatcher->OnEventFromSource(&key_event3);
644  EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed);
645#elif defined(USE_X11)
646  ui::ScopedXI2Event key_event;
647  key_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0);
648  ui::KeyEvent key_event1(key_event);
649  key_event1.SetTranslated(true);
650  ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&key_event1);
651  EXPECT_TRUE(key_event1.handled() || details.dispatcher_destroyed);
652
653  ui::KeyEvent key_event2('A', ui::VKEY_A, ui::EF_NONE);
654  key_event2.SetTranslated(true);
655  details = dispatcher->OnEventFromSource(&key_event2);
656  EXPECT_FALSE(key_event2.handled() || details.dispatcher_destroyed);
657
658  key_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0);
659  ui::KeyEvent key_event3(key_event);
660  key_event3.SetTranslated(true);
661  details = dispatcher->OnEventFromSource(&key_event3);
662  EXPECT_FALSE(key_event3.handled() || details.dispatcher_destroyed);
663#endif
664  EXPECT_EQ(1, target.accelerator_pressed_count());
665}
666#endif
667
668TEST_F(AcceleratorControllerTest, GlobalAccelerators) {
669  // CycleBackward
670  EXPECT_TRUE(GetController()->Process(
671      ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
672  // CycleForward
673  EXPECT_TRUE(
674      GetController()->Process(ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
675  // CycleLinear
676  EXPECT_TRUE(GetController()->Process(
677      ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_NONE)));
678
679#if defined(OS_CHROMEOS)
680  // Take screenshot / partial screenshot
681  // True should always be returned regardless of the existence of the delegate.
682  {
683    test::TestScreenshotDelegate* delegate = GetScreenshotDelegate();
684    delegate->set_can_take_screenshot(false);
685    EXPECT_TRUE(GetController()->Process(
686        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
687    EXPECT_TRUE(
688        GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
689    EXPECT_TRUE(GetController()->Process(ui::Accelerator(
690        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
691
692    delegate->set_can_take_screenshot(true);
693    EXPECT_EQ(0, delegate->handle_take_screenshot_count());
694    EXPECT_TRUE(GetController()->Process(
695        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
696    EXPECT_EQ(1, delegate->handle_take_screenshot_count());
697    EXPECT_TRUE(
698        GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
699    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
700    EXPECT_TRUE(GetController()->Process(ui::Accelerator(
701        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
702    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
703  }
704#endif
705  const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
706  const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
707  const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
708  {
709    TestVolumeControlDelegate* delegate =
710        new TestVolumeControlDelegate(false);
711    ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
712        scoped_ptr<VolumeControlDelegate>(delegate).Pass());
713    EXPECT_EQ(0, delegate->handle_volume_mute_count());
714    EXPECT_FALSE(GetController()->Process(volume_mute));
715    EXPECT_EQ(1, delegate->handle_volume_mute_count());
716    EXPECT_EQ(volume_mute, delegate->last_accelerator());
717    EXPECT_EQ(0, delegate->handle_volume_down_count());
718    EXPECT_FALSE(GetController()->Process(volume_down));
719    EXPECT_EQ(1, delegate->handle_volume_down_count());
720    EXPECT_EQ(volume_down, delegate->last_accelerator());
721    EXPECT_EQ(0, delegate->handle_volume_up_count());
722    EXPECT_FALSE(GetController()->Process(volume_up));
723    EXPECT_EQ(1, delegate->handle_volume_up_count());
724    EXPECT_EQ(volume_up, delegate->last_accelerator());
725  }
726  {
727    TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate(true);
728    ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
729        scoped_ptr<VolumeControlDelegate>(delegate).Pass());
730    EXPECT_EQ(0, delegate->handle_volume_mute_count());
731    EXPECT_TRUE(GetController()->Process(volume_mute));
732    EXPECT_EQ(1, delegate->handle_volume_mute_count());
733    EXPECT_EQ(volume_mute, delegate->last_accelerator());
734    EXPECT_EQ(0, delegate->handle_volume_down_count());
735    EXPECT_TRUE(GetController()->Process(volume_down));
736    EXPECT_EQ(1, delegate->handle_volume_down_count());
737    EXPECT_EQ(volume_down, delegate->last_accelerator());
738    EXPECT_EQ(0, delegate->handle_volume_up_count());
739    EXPECT_TRUE(GetController()->Process(volume_up));
740    EXPECT_EQ(1, delegate->handle_volume_up_count());
741    EXPECT_EQ(volume_up, delegate->last_accelerator());
742  }
743#if defined(OS_CHROMEOS)
744  // Brightness
745  // ui::VKEY_BRIGHTNESS_DOWN/UP are not defined on Windows.
746  const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
747  const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
748  {
749    DummyBrightnessControlDelegate* delegate =
750        new DummyBrightnessControlDelegate(false);
751    GetController()->SetBrightnessControlDelegate(
752        scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
753    EXPECT_EQ(0, delegate->handle_brightness_down_count());
754    EXPECT_FALSE(GetController()->Process(brightness_down));
755    EXPECT_EQ(1, delegate->handle_brightness_down_count());
756    EXPECT_EQ(brightness_down, delegate->last_accelerator());
757    EXPECT_EQ(0, delegate->handle_brightness_up_count());
758    EXPECT_FALSE(GetController()->Process(brightness_up));
759    EXPECT_EQ(1, delegate->handle_brightness_up_count());
760    EXPECT_EQ(brightness_up, delegate->last_accelerator());
761  }
762  {
763    DummyBrightnessControlDelegate* delegate =
764        new DummyBrightnessControlDelegate(true);
765    GetController()->SetBrightnessControlDelegate(
766        scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
767    EXPECT_EQ(0, delegate->handle_brightness_down_count());
768    EXPECT_TRUE(GetController()->Process(brightness_down));
769    EXPECT_EQ(1, delegate->handle_brightness_down_count());
770    EXPECT_EQ(brightness_down, delegate->last_accelerator());
771    EXPECT_EQ(0, delegate->handle_brightness_up_count());
772    EXPECT_TRUE(GetController()->Process(brightness_up));
773    EXPECT_EQ(1, delegate->handle_brightness_up_count());
774    EXPECT_EQ(brightness_up, delegate->last_accelerator());
775  }
776
777  // Keyboard brightness
778  const ui::Accelerator alt_brightness_down(ui::VKEY_BRIGHTNESS_DOWN,
779                                            ui::EF_ALT_DOWN);
780  const ui::Accelerator alt_brightness_up(ui::VKEY_BRIGHTNESS_UP,
781                                          ui::EF_ALT_DOWN);
782  {
783    EXPECT_TRUE(GetController()->Process(alt_brightness_down));
784    EXPECT_TRUE(GetController()->Process(alt_brightness_up));
785    DummyKeyboardBrightnessControlDelegate* delegate =
786        new DummyKeyboardBrightnessControlDelegate(false);
787    GetController()->SetKeyboardBrightnessControlDelegate(
788        scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass());
789    EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count());
790    EXPECT_FALSE(GetController()->Process(alt_brightness_down));
791    EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count());
792    EXPECT_EQ(alt_brightness_down, delegate->last_accelerator());
793    EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count());
794    EXPECT_FALSE(GetController()->Process(alt_brightness_up));
795    EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count());
796    EXPECT_EQ(alt_brightness_up, delegate->last_accelerator());
797  }
798  {
799    DummyKeyboardBrightnessControlDelegate* delegate =
800        new DummyKeyboardBrightnessControlDelegate(true);
801    GetController()->SetKeyboardBrightnessControlDelegate(
802        scoped_ptr<KeyboardBrightnessControlDelegate>(delegate).Pass());
803    EXPECT_EQ(0, delegate->handle_keyboard_brightness_down_count());
804    EXPECT_TRUE(GetController()->Process(alt_brightness_down));
805    EXPECT_EQ(1, delegate->handle_keyboard_brightness_down_count());
806    EXPECT_EQ(alt_brightness_down, delegate->last_accelerator());
807    EXPECT_EQ(0, delegate->handle_keyboard_brightness_up_count());
808    EXPECT_TRUE(GetController()->Process(alt_brightness_up));
809    EXPECT_EQ(1, delegate->handle_keyboard_brightness_up_count());
810    EXPECT_EQ(alt_brightness_up, delegate->last_accelerator());
811  }
812#endif
813
814#if !defined(NDEBUG)
815  // ToggleDesktopBackgroundMode
816  EXPECT_TRUE(GetController()->Process(
817      ui::Accelerator(ui::VKEY_B, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)));
818#if !defined(OS_LINUX)
819  // ToggleDesktopFullScreen (not implemented yet on Linux)
820  EXPECT_TRUE(GetController()->Process(
821      ui::Accelerator(ui::VKEY_F11, ui::EF_CONTROL_DOWN)));
822#endif  // OS_LINUX
823#endif  // !NDEBUG
824
825#if !defined(OS_WIN)
826  // Exit
827  ExitWarningHandler* ewh = GetController()->GetExitWarningHandlerForTest();
828  ASSERT_TRUE(!!ewh);
829  StubForTest(ewh);
830  EXPECT_TRUE(is_idle(ewh));
831  EXPECT_FALSE(is_ui_shown(ewh));
832  EXPECT_TRUE(GetController()->Process(
833      ui::Accelerator(ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
834  EXPECT_FALSE(is_idle(ewh));
835  EXPECT_TRUE(is_ui_shown(ewh));
836  SimulateTimerExpired(ewh);
837  EXPECT_TRUE(is_idle(ewh));
838  EXPECT_FALSE(is_ui_shown(ewh));
839  Reset(ewh);
840#endif
841
842  // New tab
843  EXPECT_TRUE(GetController()->Process(
844      ui::Accelerator(ui::VKEY_T, ui::EF_CONTROL_DOWN)));
845
846  // New incognito window
847  EXPECT_TRUE(GetController()->Process(
848      ui::Accelerator(ui::VKEY_N, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
849
850  // New window
851  EXPECT_TRUE(GetController()->Process(
852      ui::Accelerator(ui::VKEY_N, ui::EF_CONTROL_DOWN)));
853
854  // Restore tab
855  EXPECT_TRUE(GetController()->Process(
856      ui::Accelerator(ui::VKEY_T, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
857
858  // Show task manager
859  EXPECT_TRUE(GetController()->Process(
860      ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN)));
861
862#if defined(OS_CHROMEOS)
863  // Open file manager
864  EXPECT_TRUE(GetController()->Process(
865      ui::Accelerator(ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
866
867  // Lock screen
868  // NOTE: Accelerators that do not work on the lock screen need to be
869  // tested before the sequence below is invoked because it causes a side
870  // effect of locking the screen.
871  EXPECT_TRUE(GetController()->Process(
872      ui::Accelerator(ui::VKEY_L, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
873#endif
874}
875
876TEST_F(AcceleratorControllerTest, GlobalAcceleratorsToggleAppList) {
877  AccessibilityDelegate* delegate =
878          ash::Shell::GetInstance()->accessibility_delegate();
879  EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
880
881  // The press event should not open the AppList, the release should instead.
882  EXPECT_FALSE(
883      GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
884  EXPECT_EQ(ui::VKEY_LWIN,
885            GetController()->previous_accelerator_for_test().key_code());
886
887  EXPECT_TRUE(
888      GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
889  EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
890
891  // When spoken feedback is on, the AppList should not toggle.
892  delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
893  EXPECT_FALSE(
894      GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
895  EXPECT_FALSE(
896      GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
897  delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
898  EXPECT_TRUE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
899
900  EXPECT_FALSE(
901      GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
902  EXPECT_TRUE(
903      GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
904  EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
905
906  // When spoken feedback is on, the AppList should not toggle.
907  delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
908  EXPECT_FALSE(
909      GetController()->Process(ui::Accelerator(ui::VKEY_LWIN, ui::EF_NONE)));
910  EXPECT_FALSE(
911      GetController()->Process(ReleaseAccelerator(ui::VKEY_LWIN, ui::EF_NONE)));
912  delegate->ToggleSpokenFeedback(A11Y_NOTIFICATION_NONE);
913  EXPECT_FALSE(ash::Shell::GetInstance()->GetAppListTargetVisibility());
914}
915
916TEST_F(AcceleratorControllerTest, ImeGlobalAccelerators) {
917  // Test IME shortcuts.
918  {
919    const ui::Accelerator control_space(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
920    const ui::Accelerator convert(ui::VKEY_CONVERT, ui::EF_NONE);
921    const ui::Accelerator non_convert(ui::VKEY_NONCONVERT, ui::EF_NONE);
922    const ui::Accelerator wide_half_1(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE);
923    const ui::Accelerator wide_half_2(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE);
924    const ui::Accelerator hangul(ui::VKEY_HANGUL, ui::EF_NONE);
925    EXPECT_FALSE(GetController()->Process(control_space));
926    EXPECT_FALSE(GetController()->Process(convert));
927    EXPECT_FALSE(GetController()->Process(non_convert));
928    EXPECT_FALSE(GetController()->Process(wide_half_1));
929    EXPECT_FALSE(GetController()->Process(wide_half_2));
930    EXPECT_FALSE(GetController()->Process(hangul));
931    DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true);
932    GetController()->SetImeControlDelegate(
933        scoped_ptr<ImeControlDelegate>(delegate).Pass());
934    EXPECT_EQ(0, delegate->handle_previous_ime_count());
935    EXPECT_TRUE(GetController()->Process(control_space));
936    EXPECT_EQ(1, delegate->handle_previous_ime_count());
937    EXPECT_EQ(0, delegate->handle_switch_ime_count());
938    EXPECT_TRUE(GetController()->Process(convert));
939    EXPECT_EQ(1, delegate->handle_switch_ime_count());
940    EXPECT_TRUE(GetController()->Process(non_convert));
941    EXPECT_EQ(2, delegate->handle_switch_ime_count());
942    EXPECT_TRUE(GetController()->Process(wide_half_1));
943    EXPECT_EQ(3, delegate->handle_switch_ime_count());
944    EXPECT_TRUE(GetController()->Process(wide_half_2));
945    EXPECT_EQ(4, delegate->handle_switch_ime_count());
946    EXPECT_TRUE(GetController()->Process(hangul));
947    EXPECT_EQ(5, delegate->handle_switch_ime_count());
948  }
949
950  // Test IME shortcuts that are triggered on key release.
951  {
952    const ui::Accelerator shift_alt_press(ui::VKEY_MENU,
953                                          ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
954    const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
955    const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT,
956                                          ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
957    const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
958
959    DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true);
960    GetController()->SetImeControlDelegate(
961        scoped_ptr<ImeControlDelegate>(delegate).Pass());
962    EXPECT_EQ(0, delegate->handle_next_ime_count());
963    EXPECT_FALSE(GetController()->Process(shift_alt_press));
964    EXPECT_FALSE(GetController()->Process(shift_alt));
965    EXPECT_EQ(1, delegate->handle_next_ime_count());
966    EXPECT_FALSE(GetController()->Process(alt_shift_press));
967    EXPECT_FALSE(GetController()->Process(alt_shift));
968    EXPECT_EQ(2, delegate->handle_next_ime_count());
969
970    // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
971    // released.
972    const ui::Accelerator shift_alt_x_press(
973        ui::VKEY_X,
974        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
975    const ReleaseAccelerator shift_alt_x(ui::VKEY_X,
976                                         ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
977
978    EXPECT_FALSE(GetController()->Process(shift_alt_press));
979    EXPECT_FALSE(GetController()->Process(shift_alt_x_press));
980    EXPECT_FALSE(GetController()->Process(shift_alt_x));
981    EXPECT_FALSE(GetController()->Process(shift_alt));
982    EXPECT_EQ(2, delegate->handle_next_ime_count());
983
984    // But we _should_ if X is either VKEY_RETURN or VKEY_SPACE.
985    // TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
986    const ui::Accelerator shift_alt_return_press(
987        ui::VKEY_RETURN,
988        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
989    const ReleaseAccelerator shift_alt_return(
990        ui::VKEY_RETURN,
991        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
992
993    EXPECT_FALSE(GetController()->Process(shift_alt_press));
994    EXPECT_FALSE(GetController()->Process(shift_alt_return_press));
995    EXPECT_FALSE(GetController()->Process(shift_alt_return));
996    EXPECT_FALSE(GetController()->Process(shift_alt));
997    EXPECT_EQ(3, delegate->handle_next_ime_count());
998
999    const ui::Accelerator shift_alt_space_press(
1000        ui::VKEY_SPACE,
1001        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1002    const ReleaseAccelerator shift_alt_space(
1003        ui::VKEY_SPACE,
1004        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1005
1006    EXPECT_FALSE(GetController()->Process(shift_alt_press));
1007    EXPECT_FALSE(GetController()->Process(shift_alt_space_press));
1008    EXPECT_FALSE(GetController()->Process(shift_alt_space));
1009    EXPECT_FALSE(GetController()->Process(shift_alt));
1010    EXPECT_EQ(4, delegate->handle_next_ime_count());
1011  }
1012
1013#if defined(OS_CHROMEOS)
1014  // Test IME shortcuts again with unnormalized accelerators (Chrome OS only).
1015  {
1016    const ui::Accelerator shift_alt_press(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1017    const ReleaseAccelerator shift_alt(ui::VKEY_MENU, ui::EF_SHIFT_DOWN);
1018    const ui::Accelerator alt_shift_press(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1019    const ReleaseAccelerator alt_shift(ui::VKEY_SHIFT, ui::EF_ALT_DOWN);
1020
1021    DummyImeControlDelegate* delegate = new DummyImeControlDelegate(true);
1022    GetController()->SetImeControlDelegate(
1023        scoped_ptr<ImeControlDelegate>(delegate).Pass());
1024    EXPECT_EQ(0, delegate->handle_next_ime_count());
1025    EXPECT_FALSE(GetController()->Process(shift_alt_press));
1026    EXPECT_FALSE(GetController()->Process(shift_alt));
1027    EXPECT_EQ(1, delegate->handle_next_ime_count());
1028    EXPECT_FALSE(GetController()->Process(alt_shift_press));
1029    EXPECT_FALSE(GetController()->Process(alt_shift));
1030    EXPECT_EQ(2, delegate->handle_next_ime_count());
1031
1032    // We should NOT switch IME when e.g. Shift+Alt+X is pressed and X is
1033    // released.
1034    const ui::Accelerator shift_alt_x_press(
1035        ui::VKEY_X,
1036        ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1037    const ReleaseAccelerator shift_alt_x(ui::VKEY_X,
1038                                         ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1039
1040    EXPECT_FALSE(GetController()->Process(shift_alt_press));
1041    EXPECT_FALSE(GetController()->Process(shift_alt_x_press));
1042    EXPECT_FALSE(GetController()->Process(shift_alt_x));
1043    EXPECT_FALSE(GetController()->Process(shift_alt));
1044    EXPECT_EQ(2, delegate->handle_next_ime_count());
1045  }
1046#endif
1047}
1048
1049// TODO(nona|mazda): Remove this when crbug.com/139556 in a better way.
1050TEST_F(AcceleratorControllerTest, ImeGlobalAcceleratorsWorkaround139556) {
1051  // The workaround for crbug.com/139556 depends on the fact that we don't
1052  // use Shift+Alt+Enter/Space with ET_KEY_PRESSED as an accelerator. Test it.
1053  const ui::Accelerator shift_alt_return_press(
1054      ui::VKEY_RETURN,
1055      ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1056  EXPECT_FALSE(GetController()->Process(shift_alt_return_press));
1057  const ui::Accelerator shift_alt_space_press(
1058      ui::VKEY_SPACE,
1059      ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN);
1060  EXPECT_FALSE(GetController()->Process(shift_alt_space_press));
1061}
1062
1063TEST_F(AcceleratorControllerTest, PreferredReservedAccelerators) {
1064#if defined(OS_CHROMEOS)
1065  // Power key is reserved on chromeos.
1066  EXPECT_TRUE(GetController()->IsReserved(
1067      ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
1068  EXPECT_FALSE(GetController()->IsPreferred(
1069      ui::Accelerator(ui::VKEY_POWER, ui::EF_NONE)));
1070#endif
1071  // ALT+Tab are not reserved but preferred.
1072  EXPECT_FALSE(GetController()->IsReserved(
1073      ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
1074  EXPECT_FALSE(GetController()->IsReserved(
1075      ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
1076  EXPECT_TRUE(GetController()->IsPreferred(
1077      ui::Accelerator(ui::VKEY_TAB, ui::EF_ALT_DOWN)));
1078  EXPECT_TRUE(GetController()->IsPreferred(
1079      ui::Accelerator(ui::VKEY_TAB, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)));
1080
1081  // Others are not reserved nor preferred
1082  EXPECT_FALSE(GetController()->IsReserved(
1083      ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1084  EXPECT_FALSE(GetController()->IsPreferred(
1085      ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1086  EXPECT_FALSE(GetController()->IsReserved(
1087      ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
1088  EXPECT_FALSE(GetController()->IsPreferred(
1089      ui::Accelerator(ui::VKEY_TAB, ui::EF_NONE)));
1090  EXPECT_FALSE(GetController()->IsReserved(
1091      ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
1092  EXPECT_FALSE(GetController()->IsPreferred(
1093      ui::Accelerator(ui::VKEY_A, ui::EF_NONE)));
1094}
1095
1096namespace {
1097
1098class PreferredReservedAcceleratorsTest : public test::AshTestBase {
1099 public:
1100  PreferredReservedAcceleratorsTest() {}
1101  virtual ~PreferredReservedAcceleratorsTest() {}
1102
1103  // test::AshTestBase:
1104  virtual void SetUp() OVERRIDE {
1105    AshTestBase::SetUp();
1106    Shell::GetInstance()->lock_state_controller()->
1107        set_animator_for_test(new test::TestSessionStateAnimator);
1108  }
1109
1110 private:
1111  DISALLOW_COPY_AND_ASSIGN(PreferredReservedAcceleratorsTest);
1112};
1113
1114}  // namespace
1115
1116TEST_F(PreferredReservedAcceleratorsTest, AcceleratorsWithFullscreen) {
1117  aura::Window* w1 = CreateTestWindowInShellWithId(0);
1118  aura::Window* w2 = CreateTestWindowInShellWithId(1);
1119  wm::ActivateWindow(w1);
1120
1121  wm::WMEvent fullscreen(wm::WM_EVENT_FULLSCREEN);
1122  wm::WindowState* w1_state = wm::GetWindowState(w1);
1123  w1_state->OnWMEvent(&fullscreen);
1124  ASSERT_TRUE(w1_state->IsFullscreen());
1125
1126  ui::test::EventGenerator& generator = GetEventGenerator();
1127#if defined(OS_CHROMEOS)
1128  // Power key (reserved) should always be handled.
1129  LockStateController::TestApi test_api(
1130      Shell::GetInstance()->lock_state_controller());
1131  EXPECT_FALSE(test_api.is_animating_lock());
1132  generator.PressKey(ui::VKEY_POWER, ui::EF_NONE);
1133  EXPECT_TRUE(test_api.is_animating_lock());
1134#endif
1135
1136  // A fullscreen window can consume ALT-TAB (preferred).
1137  ASSERT_EQ(w1, wm::GetActiveWindow());
1138  generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
1139  ASSERT_EQ(w1, wm::GetActiveWindow());
1140  ASSERT_NE(w2, wm::GetActiveWindow());
1141
1142  // ALT-TAB is non repeatable. Press A to cancel the
1143  // repeat record.
1144  generator.PressKey(ui::VKEY_A, ui::EF_NONE);
1145  generator.ReleaseKey(ui::VKEY_A, ui::EF_NONE);
1146
1147  // A normal window shouldn't consume preferred accelerator.
1148  wm::WMEvent normal(wm::WM_EVENT_NORMAL);
1149  w1_state->OnWMEvent(&normal);
1150  ASSERT_FALSE(w1_state->IsFullscreen());
1151
1152  EXPECT_EQ(w1, wm::GetActiveWindow());
1153  generator.PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
1154  ASSERT_NE(w1, wm::GetActiveWindow());
1155  ASSERT_EQ(w2, wm::GetActiveWindow());
1156}
1157
1158#if defined(OS_CHROMEOS)
1159TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) {
1160  std::set<AcceleratorAction> all_actions;
1161  for (size_t i = 0 ; i < kAcceleratorDataLength; ++i)
1162    all_actions.insert(kAcceleratorData[i].action);
1163#if !defined(NDEBUG)
1164  std::set<AcceleratorAction> all_desktop_actions;
1165  for (size_t i = 0 ; i < kDesktopAcceleratorDataLength; ++i)
1166    all_desktop_actions.insert(kDesktopAcceleratorData[i].action);
1167#endif
1168
1169  std::set<AcceleratorAction> actionsAllowedAtModalWindow;
1170  for (size_t k = 0 ; k < kActionsAllowedAtModalWindowLength; ++k)
1171    actionsAllowedAtModalWindow.insert(kActionsAllowedAtModalWindow[k]);
1172  for (std::set<AcceleratorAction>::const_iterator it =
1173           actionsAllowedAtModalWindow.begin();
1174       it != actionsAllowedAtModalWindow.end(); ++it) {
1175    EXPECT_TRUE(all_actions.find(*it) != all_actions.end()
1176
1177#if !defined(NDEBUG)
1178                || all_desktop_actions.find(*it) != all_desktop_actions.end()
1179#endif
1180                )
1181        << " action from kActionsAllowedAtModalWindow"
1182        << " not found in kAcceleratorData or kDesktopAcceleratorData. "
1183        << "action: " << *it;
1184  }
1185  scoped_ptr<aura::Window> window(
1186      CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1187  const ui::Accelerator dummy;
1188  wm::ActivateWindow(window.get());
1189  Shell::GetInstance()->SimulateModalWindowOpenForTesting(true);
1190  for (std::set<AcceleratorAction>::const_iterator it = all_actions.begin();
1191       it != all_actions.end(); ++it) {
1192    if (actionsAllowedAtModalWindow.find(*it) ==
1193        actionsAllowedAtModalWindow.end()) {
1194      EXPECT_TRUE(GetController()->PerformAction(*it, dummy))
1195          << " for action (disallowed at modal window): " << *it;
1196    }
1197  }
1198  //  Testing of top row (F5-F10) accelerators that should still work
1199  //  when a modal window is open
1200  //
1201  // Screenshot
1202  {
1203    test::TestScreenshotDelegate* delegate = GetScreenshotDelegate();
1204    delegate->set_can_take_screenshot(false);
1205    EXPECT_TRUE(GetController()->Process(
1206        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
1207    EXPECT_TRUE(
1208        GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1209    EXPECT_TRUE(GetController()->Process(ui::Accelerator(
1210        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
1211    delegate->set_can_take_screenshot(true);
1212    EXPECT_EQ(0, delegate->handle_take_screenshot_count());
1213    EXPECT_TRUE(GetController()->Process(
1214        ui::Accelerator(ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_CONTROL_DOWN)));
1215    EXPECT_EQ(1, delegate->handle_take_screenshot_count());
1216    EXPECT_TRUE(
1217        GetController()->Process(ui::Accelerator(ui::VKEY_PRINT, ui::EF_NONE)));
1218    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
1219    EXPECT_TRUE(GetController()->Process(ui::Accelerator(
1220        ui::VKEY_MEDIA_LAUNCH_APP1, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)));
1221    EXPECT_EQ(2, delegate->handle_take_screenshot_count());
1222  }
1223  // Brightness
1224  const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
1225  const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
1226  {
1227    DummyBrightnessControlDelegate* delegate =
1228        new DummyBrightnessControlDelegate(false);
1229    GetController()->SetBrightnessControlDelegate(
1230        scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
1231    EXPECT_EQ(0, delegate->handle_brightness_down_count());
1232    EXPECT_FALSE(GetController()->Process(brightness_down));
1233    EXPECT_EQ(1, delegate->handle_brightness_down_count());
1234    EXPECT_EQ(brightness_down, delegate->last_accelerator());
1235    EXPECT_EQ(0, delegate->handle_brightness_up_count());
1236    EXPECT_FALSE(GetController()->Process(brightness_up));
1237    EXPECT_EQ(1, delegate->handle_brightness_up_count());
1238    EXPECT_EQ(brightness_up, delegate->last_accelerator());
1239  }
1240  {
1241    DummyBrightnessControlDelegate* delegate =
1242        new DummyBrightnessControlDelegate(true);
1243    GetController()->SetBrightnessControlDelegate(
1244        scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
1245    EXPECT_EQ(0, delegate->handle_brightness_down_count());
1246    EXPECT_TRUE(GetController()->Process(brightness_down));
1247    EXPECT_EQ(1, delegate->handle_brightness_down_count());
1248    EXPECT_EQ(brightness_down, delegate->last_accelerator());
1249    EXPECT_EQ(0, delegate->handle_brightness_up_count());
1250    EXPECT_TRUE(GetController()->Process(brightness_up));
1251    EXPECT_EQ(1, delegate->handle_brightness_up_count());
1252    EXPECT_EQ(brightness_up, delegate->last_accelerator());
1253  }
1254  // Volume
1255  const ui::Accelerator volume_mute(ui::VKEY_VOLUME_MUTE, ui::EF_NONE);
1256  const ui::Accelerator volume_down(ui::VKEY_VOLUME_DOWN, ui::EF_NONE);
1257  const ui::Accelerator volume_up(ui::VKEY_VOLUME_UP, ui::EF_NONE);
1258  {
1259    EXPECT_TRUE(GetController()->Process(volume_mute));
1260    EXPECT_TRUE(GetController()->Process(volume_down));
1261    EXPECT_TRUE(GetController()->Process(volume_up));
1262    TestVolumeControlDelegate* delegate =
1263        new TestVolumeControlDelegate(false);
1264    ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1265        scoped_ptr<VolumeControlDelegate>(delegate).Pass());
1266    EXPECT_EQ(0, delegate->handle_volume_mute_count());
1267    EXPECT_FALSE(GetController()->Process(volume_mute));
1268    EXPECT_EQ(1, delegate->handle_volume_mute_count());
1269    EXPECT_EQ(volume_mute, delegate->last_accelerator());
1270    EXPECT_EQ(0, delegate->handle_volume_down_count());
1271    EXPECT_FALSE(GetController()->Process(volume_down));
1272    EXPECT_EQ(1, delegate->handle_volume_down_count());
1273    EXPECT_EQ(volume_down, delegate->last_accelerator());
1274    EXPECT_EQ(0, delegate->handle_volume_up_count());
1275    EXPECT_FALSE(GetController()->Process(volume_up));
1276    EXPECT_EQ(1, delegate->handle_volume_up_count());
1277    EXPECT_EQ(volume_up, delegate->last_accelerator());
1278  }
1279  {
1280    TestVolumeControlDelegate* delegate = new TestVolumeControlDelegate(true);
1281    ash::Shell::GetInstance()->system_tray_delegate()->SetVolumeControlDelegate(
1282        scoped_ptr<VolumeControlDelegate>(delegate).Pass());
1283    EXPECT_EQ(0, delegate->handle_volume_mute_count());
1284    EXPECT_TRUE(GetController()->Process(volume_mute));
1285    EXPECT_EQ(1, delegate->handle_volume_mute_count());
1286    EXPECT_EQ(volume_mute, delegate->last_accelerator());
1287    EXPECT_EQ(0, delegate->handle_volume_down_count());
1288    EXPECT_TRUE(GetController()->Process(volume_down));
1289    EXPECT_EQ(1, delegate->handle_volume_down_count());
1290    EXPECT_EQ(volume_down, delegate->last_accelerator());
1291    EXPECT_EQ(0, delegate->handle_volume_up_count());
1292    EXPECT_TRUE(GetController()->Process(volume_up));
1293    EXPECT_EQ(1, delegate->handle_volume_up_count());
1294    EXPECT_EQ(volume_up, delegate->last_accelerator());
1295  }
1296}
1297#endif
1298
1299TEST_F(AcceleratorControllerTest, DisallowedWithNoWindow) {
1300  const ui::Accelerator dummy;
1301  AccessibilityDelegate* delegate =
1302      ash::Shell::GetInstance()->accessibility_delegate();
1303
1304  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1305    delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
1306    EXPECT_TRUE(
1307        GetController()->PerformAction(kActionsNeedingWindow[i], dummy));
1308    EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED);
1309  }
1310
1311  // Make sure we don't alert if we do have a window.
1312  scoped_ptr<aura::Window> window;
1313  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1314    window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1315    wm::ActivateWindow(window.get());
1316    delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
1317    GetController()->PerformAction(kActionsNeedingWindow[i], dummy);
1318    EXPECT_NE(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED);
1319  }
1320
1321  // Don't alert if we have a minimized window either.
1322  for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
1323    window.reset(CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
1324    wm::ActivateWindow(window.get());
1325    GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
1326    delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
1327    GetController()->PerformAction(kActionsNeedingWindow[i], dummy);
1328    EXPECT_NE(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED);
1329  }
1330}
1331
1332}  // namespace ash
1333