Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(984)

Side by Side Diff: ui/views/controls/menu/menu_event_filter.cc

Issue 1138523006: Enable keyboard accelerators while a menu is open (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Handling oshima's comments Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/views/controls/menu/menu_event_filter.h"
6
7 #include "ui/aura/window.h"
8 #include "ui/aura/window_property.h"
9 #include "ui/base/accelerators/accelerator.h"
10 #include "ui/events/keycodes/keyboard_code_conversion.h"
11 #include "ui/views/controls/menu/menu_controller.h"
12
13 DECLARE_WINDOW_PROPERTY_TYPE(views::MenuEventFilter::Delegate*);
14
15 DEFINE_LOCAL_WINDOW_PROPERTY_KEY(views::MenuEventFilter::Delegate*,
16 kMenuEventFilterDelegateKey,
17 nullptr);
18
19 namespace views {
20
21 namespace {
22
23 const int kKeyFlagsMask = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN |
24 ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN;
25
26 // Defines a NULL-Object delegate for non-ash platforms.
27 class DefaultMenuDelegate : public MenuEventFilter::Delegate {
28 public:
29 DefaultMenuDelegate() {}
30 ~DefaultMenuDelegate() override {}
31
32 // MenuEventFilter::Delegate:
33 void StoreInHistory(const ui::Accelerator& accelerator) override {}
34 bool ProcessAccelerator(const ui::Accelerator& accelerator,
35 MenuEventFilter* owner) override {
36 return true;
37 }
38
39 private:
40 DISALLOW_COPY_AND_ASSIGN(DefaultMenuDelegate);
41 };
42
43 } // namespace
44
45 MenuEventFilter::MenuEventFilter()
46 : default_delegate_(new DefaultMenuDelegate),
47 filter_delegate_(nullptr) {
48 }
49
50 MenuEventFilter::~MenuEventFilter() {
51 }
52
53 // static
54 void MenuEventFilter::SetMenuEventFilterDelegate(
55 aura::Window* root_window,
56 MenuEventFilter::Delegate* delegate) {
57 DCHECK(root_window);
58 DCHECK(delegate);
59 DCHECK_EQ(root_window->GetRootWindow(), root_window);
60 root_window->SetProperty(kMenuEventFilterDelegateKey, delegate);
61 }
62
63 // static
64 MenuEventFilter::Delegate* MenuEventFilter::GetMenuEventFilterDelegate(
65 aura::Window* root_window) {
66 DCHECK(root_window);
67 DCHECK_EQ(root_window->GetRootWindow(), root_window);
68 return root_window->GetProperty(kMenuEventFilterDelegateKey);
69 }
70
71 void MenuEventFilter::OnKeyEvent(ui::KeyEvent* event) {
72 DCHECK(event);
73
74 MenuEventFilter::Delegate* delegate =
75 filter_delegate_ ? filter_delegate_ : default_delegate_.get();
76 DCHECK(delegate);
77
78 // First record the current accelerator (this is normally done by the
79 // AcceleratorFilter, but since the MenuEventFilter will precede the
80 // AcceleratorFilter in the pre-target handlers list, we have to do it here).
81 ui::Accelerator accelerator(*event);
82 delegate->StoreInHistory(accelerator);
83
84 MenuController* menu_controller = MenuController::GetActiveInstance();
85 CHECK(menu_controller);
86
87 bool should_stop_propagation = true;
88 const int flags = event->flags();
89 if (event->type() != ui::ET_KEY_PRESSED || (flags & kKeyFlagsMask) != 0) {
pkotwicz 2015/06/16 16:04:59 There's a bunch of subtle differences between Menu
afakhry 2015/06/16 23:56:39 Right, in the old code, we call MenuController::Se
pkotwicz 2015/06/17 14:26:24 I prefer making these subtle changes in a differen
pkotwicz 2015/07/10 17:33:21 I still think that making these changes in a separ
90 should_stop_propagation =
91 delegate->ProcessAccelerator(accelerator, this);
92 } else {
93 if (menu_controller->OnKeyDown(event->key_code())) {
94 char c = ui::GetCharacterFromKeyCode(event->key_code(), flags);
95 if (!menu_controller->SelectByChar(c)) {
96 should_stop_propagation = delegate->ProcessAccelerator(accelerator,
97 this);
98 }
99 }
100 }
101
102 if (menu_controller->exit_type() != MenuController::EXIT_NONE)
103 menu_controller->TerminateNestedMessageLoop();
104
105 if (should_stop_propagation)
106 event->StopPropagation();
pkotwicz 2015/06/16 16:04:59 Mnemonics are only run when base::RunLoop has fini
afakhry 2015/06/16 23:56:39 That's exactly what we're doing here, right? Take
pkotwicz 2015/06/17 14:26:24 Sorry that I was unclear. In your CL, if a user pr
afakhry 2015/06/17 18:48:00 Thanks for clarifying. I understand what you mean
pkotwicz 2015/06/18 19:45:57 I am unsure what the right thing to do is. It woul
107 }
108
109 void MenuEventFilter::OnTouchEvent(ui::TouchEvent* event) {
110 if (event->type() == ui::ET_TOUCH_RELEASED ||
111 event->type() == ui::ET_TOUCH_CANCELLED) {
112 // Don't allow the event copy to clear the native touch id
113 // mapping, or we'll lose the mapping before the initial event
114 // has finished being dispatched.
115 event->set_should_remove_native_touch_id_mapping(false);
116 }
117 }
118
119 void MenuEventFilter::SetDelegate(MenuEventFilter::Delegate* delegate) {
120 DCHECK(delegate);
121 filter_delegate_ = delegate;
122 }
123
124 void MenuEventFilter::ClearDelegate() {
125 filter_delegate_ = nullptr;
126 }
127
128 void MenuEventFilter::CloseMenu() const {
129 MenuController* menu_controller = MenuController::GetActiveInstance();
130 CHECK(menu_controller);
131 menu_controller->CancelAll();
132 }
133
134 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698