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.
5 #include "athena/input/accelerator_manager_impl.h"
7 #include "athena/input/public/input_manager.h"
8 #include "athena/util/switches.h"
9 #include "base/logging.h"
10 #include "ui/aura/window.h"
11 #include "ui/base/accelerators/accelerator_manager.h"
12 #include "ui/events/event.h"
13 #include "ui/events/event_target.h"
14 #include "ui/views/focus/focus_manager.h"
15 #include "ui/views/focus/focus_manager_delegate.h"
16 #include "ui/views/focus/focus_manager_factory.h"
17 #include "ui/wm/core/accelerator_delegate.h"
18 #include "ui/wm/core/accelerator_filter.h"
19 #include "ui/wm/core/nested_accelerator_controller.h"
20 #include "ui/wm/core/nested_accelerator_delegate.h"
21 #include "ui/wm/public/dispatcher_client.h"
25 // This wrapper interface provides a common interface that handles global
26 // accelerators as well as local accelerators.
27 class AcceleratorManagerImpl::AcceleratorWrapper
{
29 virtual ~AcceleratorWrapper() {}
30 virtual void Register(const ui::Accelerator
& accelerator
,
31 ui::AcceleratorTarget
* target
) = 0;
32 virtual void Unregister(const ui::Accelerator
& accelerator
,
33 ui::AcceleratorTarget
* target
) = 0;
34 virtual bool Process(const ui::Accelerator
& accelerator
) = 0;
35 virtual ui::AcceleratorTarget
* GetCurrentTarget(
36 const ui::Accelerator
& accelertor
) const = 0;
41 // Accelerators inside nested message loop are handled by
42 // wm::NestedAcceleratorController while accelerators in normal case are
43 // handled by wm::AcceleratorFilter. These delegates act bridges in these
44 // two different environment so that AcceleratorManagerImpl can handle
45 // accelerators in an uniform way.
47 class NestedAcceleratorDelegate
: public wm::NestedAcceleratorDelegate
{
49 explicit NestedAcceleratorDelegate(
50 AcceleratorManagerImpl
* accelerator_manager
)
51 : accelerator_manager_(accelerator_manager
) {}
52 ~NestedAcceleratorDelegate() override
{}
55 // wm::NestedAcceleratorDelegate:
56 Result
ProcessAccelerator(const ui::Accelerator
& accelerator
) override
{
57 return accelerator_manager_
->Process(accelerator
) ? RESULT_PROCESSED
58 : RESULT_NOT_PROCESSED
;
61 AcceleratorManagerImpl
* accelerator_manager_
;
63 DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorDelegate
);
66 class AcceleratorDelegate
: public wm::AcceleratorDelegate
{
68 explicit AcceleratorDelegate(AcceleratorManagerImpl
* accelerator_manager
)
69 : accelerator_manager_(accelerator_manager
) {}
70 ~AcceleratorDelegate() override
{}
73 // wm::AcceleratorDelegate:
74 bool ProcessAccelerator(const ui::KeyEvent
& event
,
75 const ui::Accelerator
& accelerator
,
76 KeyType key_type
) override
{
77 aura::Window
* target
= static_cast<aura::Window
*>(event
.target());
78 if (!target
->IsRootWindow() &&
79 !accelerator_manager_
->IsRegistered(accelerator
, AF_RESERVED
)) {
80 // TODO(oshima): do the same when the active window is in fullscreen.
83 return accelerator_manager_
->Process(accelerator
);
86 AcceleratorManagerImpl
* accelerator_manager_
;
88 DISALLOW_COPY_AND_ASSIGN(AcceleratorDelegate
);
91 class FocusManagerDelegate
: public views::FocusManagerDelegate
{
93 explicit FocusManagerDelegate(AcceleratorManagerImpl
* accelerator_manager
)
94 : accelerator_manager_(accelerator_manager
) {}
95 ~FocusManagerDelegate() override
{}
97 bool ProcessAccelerator(const ui::Accelerator
& accelerator
) override
{
98 return accelerator_manager_
->Process(accelerator
);
101 ui::AcceleratorTarget
* GetCurrentTargetForAccelerator(
102 const ui::Accelerator
& accelerator
) const override
{
103 return accelerator_manager_
->IsRegistered(accelerator
, AF_NONE
)
104 ? accelerator_manager_
109 AcceleratorManagerImpl
* accelerator_manager_
;
111 DISALLOW_COPY_AND_ASSIGN(FocusManagerDelegate
);
114 // Key strokes must be sent to web contents to give them a chance to
115 // consume them unless they are reserved, and unhandled key events are
116 // sent back to focus manager asynchronously. This installs the athena's
117 // focus manager that handles athena shell's accelerators.
118 class FocusManagerFactory
: public views::FocusManagerFactory
{
120 explicit FocusManagerFactory(AcceleratorManagerImpl
* accelerator_manager
)
121 : accelerator_manager_(accelerator_manager
) {}
122 ~FocusManagerFactory() override
{}
124 views::FocusManager
* CreateFocusManager(views::Widget
* widget
,
125 bool desktop_widget
) override
{
126 return new views::FocusManager(
128 desktop_widget
? nullptr
129 : new FocusManagerDelegate(accelerator_manager_
));
133 AcceleratorManagerImpl
* accelerator_manager_
;
135 DISALLOW_COPY_AND_ASSIGN(FocusManagerFactory
);
138 class UIAcceleratorManagerWrapper
139 : public AcceleratorManagerImpl::AcceleratorWrapper
{
141 UIAcceleratorManagerWrapper()
142 : ui_accelerator_manager_(new ui::AcceleratorManager
) {}
143 ~UIAcceleratorManagerWrapper() override
{}
145 virtual void Register(const ui::Accelerator
& accelerator
,
146 ui::AcceleratorTarget
* target
) override
{
147 ui_accelerator_manager_
->Register(
148 accelerator
, ui::AcceleratorManager::kNormalPriority
, target
);
151 virtual void Unregister(const ui::Accelerator
& accelerator
,
152 ui::AcceleratorTarget
* target
) override
{
153 ui_accelerator_manager_
->Unregister(accelerator
, target
);
156 virtual bool Process(const ui::Accelerator
& accelerator
) override
{
157 return ui_accelerator_manager_
->Process(accelerator
);
160 virtual ui::AcceleratorTarget
* GetCurrentTarget(
161 const ui::Accelerator
& accelerator
) const override
{
162 return ui_accelerator_manager_
->GetCurrentTarget(accelerator
);
166 scoped_ptr
<ui::AcceleratorManager
> ui_accelerator_manager_
;
168 DISALLOW_COPY_AND_ASSIGN(UIAcceleratorManagerWrapper
);
171 class FocusManagerWrapper
: public AcceleratorManagerImpl::AcceleratorWrapper
{
173 explicit FocusManagerWrapper(views::FocusManager
* focus_manager
)
174 : focus_manager_(focus_manager
) {}
175 ~FocusManagerWrapper() override
{}
177 virtual void Register(const ui::Accelerator
& accelerator
,
178 ui::AcceleratorTarget
* target
) override
{
179 return focus_manager_
->RegisterAccelerator(
180 accelerator
, ui::AcceleratorManager::kNormalPriority
, target
);
183 virtual void Unregister(const ui::Accelerator
& accelerator
,
184 ui::AcceleratorTarget
* target
) override
{
185 focus_manager_
->UnregisterAccelerator(accelerator
, target
);
188 virtual bool Process(const ui::Accelerator
& accelerator
) override
{
193 virtual ui::AcceleratorTarget
* GetCurrentTarget(
194 const ui::Accelerator
& accelerator
) const override
{
195 return focus_manager_
->GetCurrentTargetForAccelerator(accelerator
);
199 views::FocusManager
* focus_manager_
;
201 DISALLOW_COPY_AND_ASSIGN(FocusManagerWrapper
);
206 class AcceleratorManagerImpl::InternalData
{
208 InternalData(int command_id
, AcceleratorHandler
* handler
, int flags
)
209 : command_id_(command_id
), handler_(handler
), flags_(flags
) {}
211 bool IsNonAutoRepeatable() const { return flags_
& AF_NON_AUTO_REPEATABLE
; }
212 bool IsDebug() const { return flags_
& AF_DEBUG
; }
213 int flags() const { return flags_
; }
215 bool IsCommandEnabled() const {
216 return handler_
->IsCommandEnabled(command_id_
);
219 bool OnAcceleratorFired(const ui::Accelerator
& accelerator
) {
220 return handler_
->OnAcceleratorFired(command_id_
, accelerator
);
225 AcceleratorHandler
* handler_
;
228 // This class is copyable by design.
232 AcceleratorManagerImpl
*
233 AcceleratorManagerImpl::CreateGlobalAcceleratorManager() {
234 return new AcceleratorManagerImpl(new UIAcceleratorManagerWrapper(), true);
237 scoped_ptr
<AcceleratorManager
> AcceleratorManagerImpl::CreateForFocusManager(
238 views::FocusManager
* focus_manager
) {
239 return scoped_ptr
<AcceleratorManager
>(
240 new AcceleratorManagerImpl(new FocusManagerWrapper(focus_manager
),
244 AcceleratorManagerImpl::~AcceleratorManagerImpl() {
245 nested_accelerator_controller_
.reset();
246 accelerator_filter_
.reset();
247 // Reset to use the default focus manager because the athena's
248 // FocusManager has the reference to this object.
250 views::FocusManagerFactory::Install(nullptr);
253 void AcceleratorManagerImpl::Init() {
255 views::FocusManagerFactory::Install(new FocusManagerFactory(this));
257 ui::EventTarget
* toplevel
= InputManager::Get()->GetTopmostEventTarget();
258 nested_accelerator_controller_
.reset(
259 new wm::NestedAcceleratorController(new NestedAcceleratorDelegate(this)));
261 scoped_ptr
<wm::AcceleratorDelegate
> accelerator_delegate(
262 new AcceleratorDelegate(this));
264 accelerator_filter_
.reset(
265 new wm::AcceleratorFilter(accelerator_delegate
.Pass()));
266 toplevel
->AddPreTargetHandler(accelerator_filter_
.get());
269 void AcceleratorManagerImpl::OnRootWindowCreated(aura::Window
* root_window
) {
270 aura::client::SetDispatcherClient(root_window
,
271 nested_accelerator_controller_
.get());
274 bool AcceleratorManagerImpl::Process(const ui::Accelerator
& accelerator
) {
275 return accelerator_wrapper_
->Process(accelerator
);
278 bool AcceleratorManagerImpl::IsRegistered(const ui::Accelerator
& accelerator
,
280 std::map
<ui::Accelerator
, InternalData
>::const_iterator iter
=
281 accelerators_
.find(accelerator
);
282 if (iter
== accelerators_
.end())
284 DCHECK(accelerator_wrapper_
->GetCurrentTarget(accelerator
));
285 return flags
== AF_NONE
|| iter
->second
.flags() & flags
;
288 AcceleratorManagerImpl::AcceleratorManagerImpl(
289 AcceleratorWrapper
* accelerator_wrapper
,
291 : accelerator_wrapper_(accelerator_wrapper
),
292 debug_accelerators_enabled_(switches::IsDebugAcceleratorsEnabled()),
296 void AcceleratorManagerImpl::RegisterAccelerators(
297 const AcceleratorData accelerators
[],
298 size_t num_accelerators
,
299 AcceleratorHandler
* handler
) {
300 for (size_t i
= 0; i
< num_accelerators
; ++i
)
301 RegisterAccelerator(accelerators
[i
], handler
);
304 void AcceleratorManagerImpl::SetDebugAcceleratorsEnabled(bool enabled
) {
305 debug_accelerators_enabled_
= enabled
;
308 bool AcceleratorManagerImpl::AcceleratorPressed(
309 const ui::Accelerator
& accelerator
) {
310 std::map
<ui::Accelerator
, InternalData
>::iterator iter
=
311 accelerators_
.find(accelerator
);
312 DCHECK(iter
!= accelerators_
.end());
313 if (iter
== accelerators_
.end())
315 InternalData
& data
= iter
->second
;
316 if (data
.IsDebug() && !debug_accelerators_enabled_
)
318 if (accelerator
.IsRepeat() && data
.IsNonAutoRepeatable())
320 return data
.IsCommandEnabled() ? data
.OnAcceleratorFired(accelerator
) : false;
323 bool AcceleratorManagerImpl::CanHandleAccelerators() const {
327 void AcceleratorManagerImpl::RegisterAccelerator(
328 const AcceleratorData
& accelerator_data
,
329 AcceleratorHandler
* handler
) {
330 ui::Accelerator
accelerator(accelerator_data
.keycode
,
331 accelerator_data
.keyevent_flags
);
332 accelerator
.set_type(accelerator_data
.trigger_event
== TRIGGER_ON_PRESS
334 : ui::ET_KEY_RELEASED
);
335 accelerator_wrapper_
->Register(accelerator
, this);
336 accelerators_
.insert(
337 std::make_pair(accelerator
,
338 InternalData(accelerator_data
.command_id
,
340 accelerator_data
.accelerator_flags
)));
343 void AcceleratorManagerImpl::UnregisterAccelerator(
344 const AcceleratorData
& accelerator_data
,
345 AcceleratorHandler
* handler
) {
346 ui::Accelerator
accelerator(accelerator_data
.keycode
,
347 accelerator_data
.keyevent_flags
);
348 accelerator
.set_type(accelerator_data
.trigger_event
== TRIGGER_ON_PRESS
350 : ui::ET_KEY_RELEASED
);
351 accelerator_wrapper_
->Unregister(accelerator
, this);
352 accelerators_
.erase(accelerator
);
356 AcceleratorManager
* AcceleratorManager::Get() {
357 return InputManager::Get()->GetAcceleratorManager();
361 scoped_ptr
<AcceleratorManager
> AcceleratorManager::CreateForFocusManager(
362 views::FocusManager
* focus_manager
) {
363 return AcceleratorManagerImpl::CreateForFocusManager(focus_manager
).Pass();
366 } // namespace athena