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