1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "ui/wm/core/nested_accelerator_controller.h" 6 7#include "base/bind.h" 8#include "base/event_types.h" 9#include "base/message_loop/message_loop.h" 10#include "ui/aura/test/aura_test_base.h" 11#include "ui/aura/test/test_windows.h" 12#include "ui/aura/window.h" 13#include "ui/aura/window_event_dispatcher.h" 14#include "ui/base/accelerators/accelerator.h" 15#include "ui/base/accelerators/accelerator.h" 16#include "ui/base/accelerators/accelerator_manager.h" 17#include "ui/events/event_constants.h" 18#include "ui/events/event_utils.h" 19#include "ui/events/platform/platform_event_dispatcher.h" 20#include "ui/events/platform/platform_event_source.h" 21#include "ui/events/platform/scoped_event_dispatcher.h" 22#include "ui/wm/core/nested_accelerator_delegate.h" 23#include "ui/wm/public/dispatcher_client.h" 24 25#if defined(USE_X11) 26#include <X11/Xlib.h> 27#include "ui/events/test/events_test_utils_x11.h" 28#endif // USE_X11 29 30namespace wm { 31namespace test { 32 33namespace { 34 35class MockDispatcher : public ui::PlatformEventDispatcher { 36 public: 37 MockDispatcher() : num_key_events_dispatched_(0) {} 38 39 int num_key_events_dispatched() { return num_key_events_dispatched_; } 40 41 private: 42 // ui::PlatformEventDispatcher: 43 virtual bool CanDispatchEvent(const ui::PlatformEvent& event) OVERRIDE { 44 return true; 45 } 46 virtual uint32_t DispatchEvent(const ui::PlatformEvent& event) OVERRIDE { 47 if (ui::EventTypeFromNative(event) == ui::ET_KEY_RELEASED) 48 num_key_events_dispatched_++; 49 return ui::POST_DISPATCH_NONE; 50 } 51 52 int num_key_events_dispatched_; 53 54 DISALLOW_COPY_AND_ASSIGN(MockDispatcher); 55}; 56 57class TestTarget : public ui::AcceleratorTarget { 58 public: 59 TestTarget() : accelerator_pressed_count_(0) {} 60 virtual ~TestTarget() {} 61 62 int accelerator_pressed_count() const { return accelerator_pressed_count_; } 63 64 // Overridden from ui::AcceleratorTarget: 65 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE { 66 accelerator_pressed_count_++; 67 return true; 68 } 69 virtual bool CanHandleAccelerators() const OVERRIDE { return true; } 70 71 private: 72 int accelerator_pressed_count_; 73 74 DISALLOW_COPY_AND_ASSIGN(TestTarget); 75}; 76 77void DispatchKeyReleaseA(aura::Window* root_window) { 78// Sending both keydown and keyup is necessary here because the accelerator 79// manager only checks a keyup event following a keydown event. See 80// ShouldHandle() in ui/base/accelerators/accelerator_manager.cc for details. 81#if defined(OS_WIN) 82 MSG native_event_down = {NULL, WM_KEYDOWN, ui::VKEY_A, 0}; 83 aura::WindowTreeHost* host = root_window->GetHost(); 84 host->PostNativeEvent(native_event_down); 85 MSG native_event_up = {NULL, WM_KEYUP, ui::VKEY_A, 0}; 86 host->PostNativeEvent(native_event_up); 87#elif defined(USE_X11) 88 ui::ScopedXI2Event native_event; 89 native_event.InitKeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_A, 0); 90 aura::WindowTreeHost* host = root_window->GetHost(); 91 host->PostNativeEvent(native_event); 92 native_event.InitKeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_A, 0); 93 host->PostNativeEvent(native_event); 94#endif 95 // Make sure the inner message-loop terminates after dispatching the events. 96 base::MessageLoop::current()->PostTask( 97 FROM_HERE, base::MessageLoop::current()->QuitClosure()); 98} 99 100class MockNestedAcceleratorDelegate : public NestedAcceleratorDelegate { 101 public: 102 MockNestedAcceleratorDelegate() 103 : accelerator_manager_(new ui::AcceleratorManager) {} 104 virtual ~MockNestedAcceleratorDelegate() {} 105 106 // NestedAcceleratorDelegate: 107 virtual Result ProcessAccelerator( 108 const ui::Accelerator& accelerator) OVERRIDE { 109 return accelerator_manager_->Process(accelerator) ? 110 RESULT_PROCESSED : RESULT_NOT_PROCESSED; 111 } 112 113 void Register(const ui::Accelerator& accelerator, 114 ui::AcceleratorTarget* target) { 115 accelerator_manager_->Register( 116 accelerator, ui::AcceleratorManager::kNormalPriority, target); 117 } 118 119 private: 120 scoped_ptr<ui::AcceleratorManager> accelerator_manager_; 121 122 DISALLOW_COPY_AND_ASSIGN(MockNestedAcceleratorDelegate); 123}; 124 125class NestedAcceleratorTest : public aura::test::AuraTestBase { 126 public: 127 NestedAcceleratorTest() {} 128 virtual ~NestedAcceleratorTest() {} 129 130 virtual void SetUp() OVERRIDE { 131 AuraTestBase::SetUp(); 132 delegate_ = new MockNestedAcceleratorDelegate(); 133 nested_accelerator_controller_.reset( 134 new NestedAcceleratorController(delegate_)); 135 aura::client::SetDispatcherClient(root_window(), 136 nested_accelerator_controller_.get()); 137 } 138 139 virtual void TearDown() OVERRIDE { 140 aura::client::SetDispatcherClient(root_window(), NULL); 141 AuraTestBase::TearDown(); 142 delegate_ = NULL; 143 nested_accelerator_controller_.reset(); 144 } 145 146 MockNestedAcceleratorDelegate* delegate() { return delegate_; } 147 148 private: 149 scoped_ptr<NestedAcceleratorController> nested_accelerator_controller_; 150 MockNestedAcceleratorDelegate* delegate_; 151 152 DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorTest); 153}; 154 155} // namespace 156 157// Aura window above lock screen in z order. 158// http://crbug.com/396494 159TEST_F(NestedAcceleratorTest, DISABLED_AssociatedWindowAboveLockScreen) { 160 // TODO(oshima|sadrul): remove when Win implements PES. 161 if (!ui::PlatformEventSource::GetInstance()) 162 return; 163 MockDispatcher inner_dispatcher; 164 scoped_ptr<aura::Window> mock_lock_container( 165 CreateNormalWindow(0, root_window(), NULL)); 166 aura::test::CreateTestWindowWithId(1, mock_lock_container.get()); 167 168 scoped_ptr<aura::Window> associated_window( 169 CreateNormalWindow(2, root_window(), NULL)); 170 EXPECT_TRUE(aura::test::WindowIsAbove(associated_window.get(), 171 mock_lock_container.get())); 172 173 DispatchKeyReleaseA(root_window()); 174 scoped_ptr<ui::ScopedEventDispatcher> override_dispatcher = 175 ui::PlatformEventSource::GetInstance()->OverrideDispatcher( 176 &inner_dispatcher); 177 aura::client::DispatcherRunLoop run_loop( 178 aura::client::GetDispatcherClient(root_window()), NULL); 179 run_loop.Run(); 180 EXPECT_EQ(1, inner_dispatcher.num_key_events_dispatched()); 181} 182 183// Test that the nested dispatcher handles accelerators. 184// http://crbug.com/396494 185TEST_F(NestedAcceleratorTest, DISABLED_AcceleratorsHandled) { 186 // TODO(oshima|sadrul): remove when Win implements PES. 187 if (!ui::PlatformEventSource::GetInstance()) 188 return; 189 MockDispatcher inner_dispatcher; 190 ui::Accelerator accelerator(ui::VKEY_A, ui::EF_NONE); 191 accelerator.set_type(ui::ET_KEY_RELEASED); 192 TestTarget target; 193 delegate()->Register(accelerator, &target); 194 195 DispatchKeyReleaseA(root_window()); 196 scoped_ptr<ui::ScopedEventDispatcher> override_dispatcher = 197 ui::PlatformEventSource::GetInstance()->OverrideDispatcher( 198 &inner_dispatcher); 199 aura::client::DispatcherRunLoop run_loop( 200 aura::client::GetDispatcherClient(root_window()), NULL); 201 run_loop.Run(); 202 EXPECT_EQ(0, inner_dispatcher.num_key_events_dispatched()); 203 EXPECT_EQ(1, target.accelerator_pressed_count()); 204} 205 206} // namespace test 207} // namespace wm 208