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 "ash/accelerators/nested_accelerator_delegate.h"
6
7#include "ash/accelerators/accelerator_controller.h"
8#include "ash/shell.h"
9#include "ui/aura/window_event_dispatcher.h"
10#include "ui/base/accelerators/accelerator.h"
11#include "ui/events/event.h"
12#include "ui/events/event_constants.h"
13#include "ui/events/event_utils.h"
14#include "ui/views/controls/menu/menu_controller.h"
15
16namespace ash {
17namespace {
18
19bool IsPossibleAcceleratorNotForMenu(const ui::Accelerator& accelerator) {
20  // For shortcuts generated by Ctrl or Alt plus a letter, number or
21  // the tab key, we want to exit the context menu first and then
22  // repost the event. That allows for the shortcut execution after
23  // the context menu has exited.
24  if (accelerator.type() == ui::ET_KEY_PRESSED &&
25      (accelerator.modifiers() & (ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN))) {
26    const ui::KeyboardCode key_code = accelerator.key_code();
27    if ((key_code >= ui::VKEY_A && key_code <= ui::VKEY_Z) ||
28        (key_code >= ui::VKEY_0 && key_code <= ui::VKEY_9) ||
29        (key_code == ui::VKEY_TAB)) {
30      return true;
31    }
32  }
33  return false;
34}
35
36bool ShouldProcessAcceleratorNow(const ui::Accelerator& accelerator) {
37  if (!IsPossibleAcceleratorNotForMenu(accelerator))
38    return true;
39
40  if (views::MenuController* menu_controller =
41          views::MenuController::GetActiveInstance()) {
42    menu_controller->CancelAll();
43    return false;
44  }
45  return true;
46}
47
48}  // namespace
49
50NestedAcceleratorDelegate::NestedAcceleratorDelegate() {
51}
52
53NestedAcceleratorDelegate::~NestedAcceleratorDelegate() {
54}
55
56NestedAcceleratorDelegate::Result NestedAcceleratorDelegate::ProcessAccelerator(
57    const ui::Accelerator& accelerator) {
58  if (!ShouldProcessAcceleratorNow(accelerator))
59    return RESULT_PROCESS_LATER;
60
61  ash::AcceleratorController* accelerator_controller =
62      ash::Shell::GetInstance()->accelerator_controller();
63  if (!accelerator_controller)
64    return RESULT_NOT_PROCESSED;
65  return accelerator_controller->Process(accelerator) ? RESULT_PROCESSED
66                                                      : RESULT_NOT_PROCESSED;
67}
68
69}  // namespace ash
70