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
23namespace athena {
24
25// This wrapper interface provides a common interface that handles global
26// accelerators as well as local accelerators.
27class AcceleratorManagerImpl::AcceleratorWrapper {
28 public:
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
37namespace {
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
45class NestedAcceleratorDelegate : public wm::NestedAcceleratorDelegate {
46 public:
47  explicit NestedAcceleratorDelegate(
48      AcceleratorManagerImpl* accelerator_manager)
49      : accelerator_manager_(accelerator_manager) {}
50  virtual ~NestedAcceleratorDelegate() {}
51
52 private:
53  // wm::NestedAcceleratorDelegate:
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
65class AcceleratorDelegate : public wm::AcceleratorDelegate {
66 public:
67  explicit AcceleratorDelegate(AcceleratorManagerImpl* accelerator_manager)
68      : accelerator_manager_(accelerator_manager) {}
69  virtual ~AcceleratorDelegate() {}
70
71 private:
72  // wm::AcceleratorDelegate:
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
89class FocusManagerDelegate : public views::FocusManagerDelegate {
90 public:
91  explicit FocusManagerDelegate(AcceleratorManagerImpl* accelerator_manager)
92      : accelerator_manager_(accelerator_manager) {}
93  virtual ~FocusManagerDelegate() {}
94
95  virtual bool ProcessAccelerator(const ui::Accelerator& accelerator) OVERRIDE {
96    return accelerator_manager_->Process(accelerator);
97  }
98
99  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.
116class FocusManagerFactory : public views::FocusManagerFactory {
117 public:
118  explicit FocusManagerFactory(AcceleratorManagerImpl* accelerator_manager)
119      : accelerator_manager_(accelerator_manager) {}
120  virtual ~FocusManagerFactory() {}
121
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
136class UIAcceleratorManagerWrapper
137    : public AcceleratorManagerImpl::AcceleratorWrapper {
138 public:
139  UIAcceleratorManagerWrapper()
140      : ui_accelerator_manager_(new ui::AcceleratorManager) {}
141  virtual ~UIAcceleratorManagerWrapper() {}
142
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
149  virtual bool Process(const ui::Accelerator& accelerator) OVERRIDE {
150    return ui_accelerator_manager_->Process(accelerator);
151  }
152
153  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
164class FocusManagerWrapper : public AcceleratorManagerImpl::AcceleratorWrapper {
165 public:
166  explicit FocusManagerWrapper(views::FocusManager* focus_manager)
167      : focus_manager_(focus_manager) {}
168  virtual ~FocusManagerWrapper() {}
169
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
176  virtual bool Process(const ui::Accelerator& accelerator) OVERRIDE {
177    NOTREACHED();
178    return true;
179  }
180
181  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
194class AcceleratorManagerImpl::InternalData {
195 public:
196  InternalData(int command_id, AcceleratorHandler* handler, int flags)
197      : command_id_(command_id), handler_(handler), flags_(flags) {}
198
199  bool IsNonAutoRepeatable() const { return flags_ & AF_NON_AUTO_REPEATABLE; }
200  bool IsDebug() const { return flags_ & AF_DEBUG; }
201  int flags() const { return flags_; }
202
203  bool IsCommandEnabled() const {
204    return handler_->IsCommandEnabled(command_id_);
205  }
206
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
220AcceleratorManagerImpl*
221AcceleratorManagerImpl::CreateGlobalAcceleratorManager() {
222  return new AcceleratorManagerImpl(new UIAcceleratorManagerWrapper());
223}
224
225scoped_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
232AcceleratorManagerImpl::~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
240void 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
255void AcceleratorManagerImpl::OnRootWindowCreated(aura::Window* root_window) {
256  aura::client::SetDispatcherClient(root_window,
257                                    nested_accelerator_controller_.get());
258}
259
260bool AcceleratorManagerImpl::Process(const ui::Accelerator& accelerator) {
261  return accelerator_wrapper_->Process(accelerator);
262}
263
264bool 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
274AcceleratorManagerImpl::AcceleratorManagerImpl(
275    AcceleratorWrapper* accelerator_wrapper)
276    : accelerator_wrapper_(accelerator_wrapper),
277      debug_accelerators_enabled_(switches::IsDebugAcceleratorsEnabled()) {
278}
279
280void 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
288void AcceleratorManagerImpl::SetDebugAcceleratorsEnabled(bool enabled) {
289  debug_accelerators_enabled_ = enabled;
290}
291
292bool 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
307bool AcceleratorManagerImpl::CanHandleAccelerators() const {
308  return true;
309}
310
311void 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
328AcceleratorManager* AcceleratorManager::Get() {
329  return InputManager::Get()->GetAcceleratorManager();
330}
331
332// static
333scoped_ptr<AcceleratorManager> AcceleratorManager::CreateForFocusManager(
334    views::FocusManager* focus_manager) {
335  return AcceleratorManagerImpl::CreateForFocusManager(focus_manager).Pass();
336}
337
338}  // namespace athena
339