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 "athena/input/accelerator_manager_impl.h"
6
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"
22
23 namespace athena {
24
25 // This wrapper interface provides a common interface that handles global
26 // accelerators as well as local accelerators.
27 class AcceleratorManagerImpl::AcceleratorWrapper {
28 public:
~AcceleratorWrapper()29 virtual ~AcceleratorWrapper() {}
30 virtual void Register(const ui::Accelerator& accelerator,
31 ui::AcceleratorTarget* target) = 0;
32 virtual bool Process(const ui::Accelerator& accelerator) = 0;
33 virtual ui::AcceleratorTarget* GetCurrentTarget(
34 const ui::Accelerator& accelertor) const = 0;
35 };
36
37 namespace {
38
39 // Accelerators inside nested message loop are handled by
40 // wm::NestedAcceleratorController while accelerators in normal case are
41 // handled by wm::AcceleratorFilter. These delegates act bridges in these
42 // two different environment so that AcceleratorManagerImpl can handle
43 // accelerators in an uniform way.
44
45 class NestedAcceleratorDelegate : public wm::NestedAcceleratorDelegate {
46 public:
NestedAcceleratorDelegate(AcceleratorManagerImpl * accelerator_manager)47 explicit NestedAcceleratorDelegate(
48 AcceleratorManagerImpl* accelerator_manager)
49 : accelerator_manager_(accelerator_manager) {}
~NestedAcceleratorDelegate()50 virtual ~NestedAcceleratorDelegate() {}
51
52 private:
53 // wm::NestedAcceleratorDelegate:
ProcessAccelerator(const ui::Accelerator & accelerator)54 virtual Result ProcessAccelerator(
55 const ui::Accelerator& accelerator) OVERRIDE {
56 return accelerator_manager_->Process(accelerator) ? RESULT_PROCESSED
57 : RESULT_NOT_PROCESSED;
58 }
59
60 AcceleratorManagerImpl* accelerator_manager_;
61
62 DISALLOW_COPY_AND_ASSIGN(NestedAcceleratorDelegate);
63 };
64
65 class AcceleratorDelegate : public wm::AcceleratorDelegate {
66 public:
AcceleratorDelegate(AcceleratorManagerImpl * accelerator_manager)67 explicit AcceleratorDelegate(AcceleratorManagerImpl* accelerator_manager)
68 : accelerator_manager_(accelerator_manager) {}
~AcceleratorDelegate()69 virtual ~AcceleratorDelegate() {}
70
71 private:
72 // wm::AcceleratorDelegate:
ProcessAccelerator(const ui::KeyEvent & event,const ui::Accelerator & accelerator,KeyType key_type)73 virtual bool ProcessAccelerator(const ui::KeyEvent& event,
74 const ui::Accelerator& accelerator,
75 KeyType key_type) OVERRIDE {
76 aura::Window* target = static_cast<aura::Window*>(event.target());
77 if (!target->IsRootWindow() &&
78 !accelerator_manager_->IsRegistered(accelerator, AF_RESERVED)) {
79 // TODO(oshima): do the same when the active window is in fullscreen.
80 return false;
81 }
82 return accelerator_manager_->Process(accelerator);
83 }
84
85 AcceleratorManagerImpl* accelerator_manager_;
86 DISALLOW_COPY_AND_ASSIGN(AcceleratorDelegate);
87 };
88
89 class FocusManagerDelegate : public views::FocusManagerDelegate {
90 public:
FocusManagerDelegate(AcceleratorManagerImpl * accelerator_manager)91 explicit FocusManagerDelegate(AcceleratorManagerImpl* accelerator_manager)
92 : accelerator_manager_(accelerator_manager) {}
~FocusManagerDelegate()93 virtual ~FocusManagerDelegate() {}
94
ProcessAccelerator(const ui::Accelerator & accelerator)95 virtual bool ProcessAccelerator(const ui::Accelerator& accelerator) OVERRIDE {
96 return accelerator_manager_->Process(accelerator);
97 }
98
GetCurrentTargetForAccelerator(const ui::Accelerator & accelerator) const99 virtual ui::AcceleratorTarget* GetCurrentTargetForAccelerator(
100 const ui::Accelerator& accelerator) const OVERRIDE {
101 return accelerator_manager_->IsRegistered(accelerator, AF_NONE)
102 ? accelerator_manager_
103 : NULL;
104 }
105
106 private:
107 AcceleratorManagerImpl* accelerator_manager_;
108
109 DISALLOW_COPY_AND_ASSIGN(FocusManagerDelegate);
110 };
111
112 // Key strokes must be sent to web contents to give them a chance to
113 // consume them unless they are reserved, and unhandled key events are
114 // sent back to focus manager asynchronously. This installs the athena's
115 // focus manager that handles athena shell's accelerators.
116 class FocusManagerFactory : public views::FocusManagerFactory {
117 public:
FocusManagerFactory(AcceleratorManagerImpl * accelerator_manager)118 explicit FocusManagerFactory(AcceleratorManagerImpl* accelerator_manager)
119 : accelerator_manager_(accelerator_manager) {}
~FocusManagerFactory()120 virtual ~FocusManagerFactory() {}
121
CreateFocusManager(views::Widget * widget,bool desktop_widget)122 virtual views::FocusManager* CreateFocusManager(
123 views::Widget* widget,
124 bool desktop_widget) OVERRIDE {
125 return new views::FocusManager(
126 widget,
127 desktop_widget ? NULL : new FocusManagerDelegate(accelerator_manager_));
128 }
129
130 private:
131 AcceleratorManagerImpl* accelerator_manager_;
132
133 DISALLOW_COPY_AND_ASSIGN(FocusManagerFactory);
134 };
135
136 class UIAcceleratorManagerWrapper
137 : public AcceleratorManagerImpl::AcceleratorWrapper {
138 public:
UIAcceleratorManagerWrapper()139 UIAcceleratorManagerWrapper()
140 : ui_accelerator_manager_(new ui::AcceleratorManager) {}
~UIAcceleratorManagerWrapper()141 virtual ~UIAcceleratorManagerWrapper() {}
142
Register(const ui::Accelerator & accelerator,ui::AcceleratorTarget * target)143 virtual void Register(const ui::Accelerator& accelerator,
144 ui::AcceleratorTarget* target) OVERRIDE {
145 return ui_accelerator_manager_->Register(
146 accelerator, ui::AcceleratorManager::kNormalPriority, target);
147 }
148
Process(const ui::Accelerator & accelerator)149 virtual bool Process(const ui::Accelerator& accelerator) OVERRIDE {
150 return ui_accelerator_manager_->Process(accelerator);
151 }
152
GetCurrentTarget(const ui::Accelerator & accelerator) const153 virtual ui::AcceleratorTarget* GetCurrentTarget(
154 const ui::Accelerator& accelerator) const OVERRIDE {
155 return ui_accelerator_manager_->GetCurrentTarget(accelerator);
156 }
157
158 private:
159 scoped_ptr<ui::AcceleratorManager> ui_accelerator_manager_;
160
161 DISALLOW_COPY_AND_ASSIGN(UIAcceleratorManagerWrapper);
162 };
163
164 class FocusManagerWrapper : public AcceleratorManagerImpl::AcceleratorWrapper {
165 public:
FocusManagerWrapper(views::FocusManager * focus_manager)166 explicit FocusManagerWrapper(views::FocusManager* focus_manager)
167 : focus_manager_(focus_manager) {}
~FocusManagerWrapper()168 virtual ~FocusManagerWrapper() {}
169
Register(const ui::Accelerator & accelerator,ui::AcceleratorTarget * target)170 virtual void Register(const ui::Accelerator& accelerator,
171 ui::AcceleratorTarget* target) OVERRIDE {
172 return focus_manager_->RegisterAccelerator(
173 accelerator, ui::AcceleratorManager::kNormalPriority, target);
174 }
175
Process(const ui::Accelerator & accelerator)176 virtual bool Process(const ui::Accelerator& accelerator) OVERRIDE {
177 NOTREACHED();
178 return true;
179 }
180
GetCurrentTarget(const ui::Accelerator & accelerator) const181 virtual ui::AcceleratorTarget* GetCurrentTarget(
182 const ui::Accelerator& accelerator) const OVERRIDE {
183 return focus_manager_->GetCurrentTargetForAccelerator(accelerator);
184 }
185
186 private:
187 views::FocusManager* focus_manager_;
188
189 DISALLOW_COPY_AND_ASSIGN(FocusManagerWrapper);
190 };
191
192 } // namespace
193
194 class AcceleratorManagerImpl::InternalData {
195 public:
InternalData(int command_id,AcceleratorHandler * handler,int flags)196 InternalData(int command_id, AcceleratorHandler* handler, int flags)
197 : command_id_(command_id), handler_(handler), flags_(flags) {}
198
IsNonAutoRepeatable() const199 bool IsNonAutoRepeatable() const { return flags_ & AF_NON_AUTO_REPEATABLE; }
IsDebug() const200 bool IsDebug() const { return flags_ & AF_DEBUG; }
flags() const201 int flags() const { return flags_; }
202
IsCommandEnabled() const203 bool IsCommandEnabled() const {
204 return handler_->IsCommandEnabled(command_id_);
205 }
206
OnAcceleratorFired(const ui::Accelerator & accelerator)207 bool OnAcceleratorFired(const ui::Accelerator& accelerator) {
208 return handler_->OnAcceleratorFired(command_id_, accelerator);
209 }
210
211 private:
212 int command_id_;
213 AcceleratorHandler* handler_;
214 int flags_;
215
216 // This class is copyable by design.
217 };
218
219 // static
220 AcceleratorManagerImpl*
CreateGlobalAcceleratorManager()221 AcceleratorManagerImpl::CreateGlobalAcceleratorManager() {
222 return new AcceleratorManagerImpl(new UIAcceleratorManagerWrapper());
223 }
224
CreateForFocusManager(views::FocusManager * focus_manager)225 scoped_ptr<AcceleratorManager> AcceleratorManagerImpl::CreateForFocusManager(
226 views::FocusManager* focus_manager) {
227 return scoped_ptr<AcceleratorManager>(
228 new AcceleratorManagerImpl(new FocusManagerWrapper(focus_manager)))
229 .Pass();
230 }
231
~AcceleratorManagerImpl()232 AcceleratorManagerImpl::~AcceleratorManagerImpl() {
233 nested_accelerator_controller_.reset();
234 accelerator_filter_.reset();
235 // Reset to use the default focus manager because the athena's
236 // FocusManager has the reference to this object.
237 views::FocusManagerFactory::Install(NULL);
238 }
239
Init()240 void AcceleratorManagerImpl::Init() {
241 views::FocusManagerFactory::Install(new FocusManagerFactory(this));
242
243 ui::EventTarget* toplevel = InputManager::Get()->GetTopmostEventTarget();
244 nested_accelerator_controller_.reset(
245 new wm::NestedAcceleratorController(new NestedAcceleratorDelegate(this)));
246
247 scoped_ptr<wm::AcceleratorDelegate> accelerator_delegate(
248 new AcceleratorDelegate(this));
249
250 accelerator_filter_.reset(
251 new wm::AcceleratorFilter(accelerator_delegate.Pass()));
252 toplevel->AddPreTargetHandler(accelerator_filter_.get());
253 }
254
OnRootWindowCreated(aura::Window * root_window)255 void AcceleratorManagerImpl::OnRootWindowCreated(aura::Window* root_window) {
256 aura::client::SetDispatcherClient(root_window,
257 nested_accelerator_controller_.get());
258 }
259
Process(const ui::Accelerator & accelerator)260 bool AcceleratorManagerImpl::Process(const ui::Accelerator& accelerator) {
261 return accelerator_wrapper_->Process(accelerator);
262 }
263
IsRegistered(const ui::Accelerator & accelerator,int flags) const264 bool AcceleratorManagerImpl::IsRegistered(const ui::Accelerator& accelerator,
265 int flags) const {
266 std::map<ui::Accelerator, InternalData>::const_iterator iter =
267 accelerators_.find(accelerator);
268 if (iter == accelerators_.end())
269 return false;
270 DCHECK(accelerator_wrapper_->GetCurrentTarget(accelerator));
271 return flags == AF_NONE || iter->second.flags() & flags;
272 }
273
AcceleratorManagerImpl(AcceleratorWrapper * accelerator_wrapper)274 AcceleratorManagerImpl::AcceleratorManagerImpl(
275 AcceleratorWrapper* accelerator_wrapper)
276 : accelerator_wrapper_(accelerator_wrapper),
277 debug_accelerators_enabled_(switches::IsDebugAcceleratorsEnabled()) {
278 }
279
RegisterAccelerators(const AcceleratorData accelerators[],size_t num_accelerators,AcceleratorHandler * handler)280 void AcceleratorManagerImpl::RegisterAccelerators(
281 const AcceleratorData accelerators[],
282 size_t num_accelerators,
283 AcceleratorHandler* handler) {
284 for (size_t i = 0; i < num_accelerators; ++i)
285 RegisterAccelerator(accelerators[i], handler);
286 }
287
SetDebugAcceleratorsEnabled(bool enabled)288 void AcceleratorManagerImpl::SetDebugAcceleratorsEnabled(bool enabled) {
289 debug_accelerators_enabled_ = enabled;
290 }
291
AcceleratorPressed(const ui::Accelerator & accelerator)292 bool AcceleratorManagerImpl::AcceleratorPressed(
293 const ui::Accelerator& accelerator) {
294 std::map<ui::Accelerator, InternalData>::iterator iter =
295 accelerators_.find(accelerator);
296 DCHECK(iter != accelerators_.end());
297 if (iter == accelerators_.end())
298 return false;
299 InternalData& data = iter->second;
300 if (data.IsDebug() && !debug_accelerators_enabled_)
301 return false;
302 if (accelerator.IsRepeat() && data.IsNonAutoRepeatable())
303 return false;
304 return data.IsCommandEnabled() ? data.OnAcceleratorFired(accelerator) : false;
305 }
306
CanHandleAccelerators() const307 bool AcceleratorManagerImpl::CanHandleAccelerators() const {
308 return true;
309 }
310
RegisterAccelerator(const AcceleratorData & accelerator_data,AcceleratorHandler * handler)311 void AcceleratorManagerImpl::RegisterAccelerator(
312 const AcceleratorData& accelerator_data,
313 AcceleratorHandler* handler) {
314 ui::Accelerator accelerator(accelerator_data.keycode,
315 accelerator_data.keyevent_flags);
316 accelerator.set_type(accelerator_data.trigger_event == TRIGGER_ON_PRESS
317 ? ui::ET_KEY_PRESSED
318 : ui::ET_KEY_RELEASED);
319 accelerator_wrapper_->Register(accelerator, this);
320 accelerators_.insert(
321 std::make_pair(accelerator,
322 InternalData(accelerator_data.command_id,
323 handler,
324 accelerator_data.accelerator_flags)));
325 }
326
327 // static
Get()328 AcceleratorManager* AcceleratorManager::Get() {
329 return InputManager::Get()->GetAcceleratorManager();
330 }
331
332 // static
CreateForFocusManager(views::FocusManager * focus_manager)333 scoped_ptr<AcceleratorManager> AcceleratorManager::CreateForFocusManager(
334 views::FocusManager* focus_manager) {
335 return AcceleratorManagerImpl::CreateForFocusManager(focus_manager).Pass();
336 }
337
338 } // namespace athena
339