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

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

Issue 331993009: MacViews: Run native Cocoa context menus to support Services. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/controls/menu/menu_runner.h" 5 #include "ui/views/controls/menu/menu_runner_impl.h"
6 6
7 #include <set> 7 #include "ui/native_theme/native_theme.h"
8
9 #include "base/memory/weak_ptr.h"
10 #include "ui/base/models/menu_model.h"
11 #include "ui/views/controls/button/menu_button.h" 8 #include "ui/views/controls/button/menu_button.h"
12 #include "ui/views/controls/menu/menu_controller.h" 9 #include "ui/views/controls/menu/menu_controller.h"
13 #include "ui/views/controls/menu/menu_controller_delegate.h"
14 #include "ui/views/controls/menu/menu_delegate.h" 10 #include "ui/views/controls/menu/menu_delegate.h"
15 #include "ui/views/controls/menu/menu_item_view.h" 11 #include "ui/views/controls/menu/menu_item_view.h"
16 #include "ui/views/controls/menu/menu_model_adapter.h"
17 #include "ui/views/controls/menu/menu_runner_handler.h"
18 #include "ui/views/widget/widget.h" 12 #include "ui/views/widget/widget.h"
19 13
20 #if defined(OS_WIN) 14 #if defined(OS_WIN)
21 #include "base/win/win_util.h" 15 #include "base/win/win_util.h"
22 #endif 16 #endif
23 17
24 namespace views { 18 namespace views {
25
26 namespace internal { 19 namespace internal {
27 20
28 // Manages the menu. To destroy a MenuRunnerImpl invoke Release(). Release()
29 // deletes immediately if the menu isn't showing. If the menu is showing
30 // Release() cancels the menu and when the nested RunMenuAt() call returns
31 // deletes itself and the menu.
32 class MenuRunnerImpl : public internal::MenuControllerDelegate {
33 public:
34 explicit MenuRunnerImpl(MenuItemView* menu);
35
36 MenuItemView* menu() { return menu_; }
37
38 bool running() const { return running_; }
39
40 // See description above class for details.
41 void Release();
42
43 // Runs the menu.
44 MenuRunner::RunResult RunMenuAt(Widget* parent,
45 MenuButton* button,
46 const gfx::Rect& bounds,
47 MenuAnchorPosition anchor,
48 int32 types) WARN_UNUSED_RESULT;
49
50 void Cancel();
51
52 // Returns the time from the event which closed the menu - or 0.
53 base::TimeDelta closing_event_time() const;
54
55 // MenuControllerDelegate:
56 virtual void DropMenuClosed(NotifyType type, MenuItemView* menu) OVERRIDE;
57 virtual void SiblingMenuCreated(MenuItemView* menu) OVERRIDE;
58
59 private:
60 virtual ~MenuRunnerImpl();
61
62 // Cleans up after the menu is no longer showing. |result| is the menu that
63 // the user selected, or NULL if nothing was selected.
64 MenuRunner::RunResult MenuDone(MenuItemView* result, int mouse_event_flags);
65
66 // Returns true if mnemonics should be shown in the menu.
67 bool ShouldShowMnemonics(MenuButton* button);
68
69 // The menu. We own this. We don't use scoped_ptr as the destructor is
70 // protected and we're a friend.
71 MenuItemView* menu_;
72
73 // Any sibling menus. Does not include |menu_|. We own these too.
74 std::set<MenuItemView*> sibling_menus_;
75
76 // Created and set as the delegate of the MenuItemView if Release() is
77 // invoked. This is done to make sure the delegate isn't notified after
78 // Release() is invoked. We do this as we assume the delegate is no longer
79 // valid if MenuRunner has been deleted.
80 scoped_ptr<MenuDelegate> empty_delegate_;
81
82 // Are we in run waiting for it to return?
83 bool running_;
84
85 // Set if |running_| and Release() has been invoked.
86 bool delete_after_run_;
87
88 // Are we running for a drop?
89 bool for_drop_;
90
91 // The controller.
92 MenuController* controller_;
93
94 // Do we own the controller?
95 bool owns_controller_;
96
97 // The timestamp of the event which closed the menu - or 0.
98 base::TimeDelta closing_event_time_;
99
100 // Used to detect deletion of |this| when notifying delegate of success.
101 base::WeakPtrFactory<MenuRunnerImpl> weak_factory_;
102
103 DISALLOW_COPY_AND_ASSIGN(MenuRunnerImpl);
104 };
105
106 MenuRunnerImpl::MenuRunnerImpl(MenuItemView* menu) 21 MenuRunnerImpl::MenuRunnerImpl(MenuItemView* menu)
107 : menu_(menu), 22 : menu_(menu),
108 running_(false), 23 running_(false),
109 delete_after_run_(false), 24 delete_after_run_(false),
110 for_drop_(false), 25 for_drop_(false),
111 controller_(NULL), 26 controller_(NULL),
112 owns_controller_(false), 27 owns_controller_(false),
113 closing_event_time_(base::TimeDelta()), 28 closing_event_time_(base::TimeDelta()),
114 weak_factory_(this) { 29 weak_factory_(this) {
115 } 30 }
116 31
32 bool MenuRunnerImpl::running() const {
33 return running_;
tapted 2014/06/25 08:30:28 can this just do holder_->running()?
Andre 2014/06/27 01:18:08 I'm not sure what you mean, we are the holder_ her
tapted 2014/06/27 11:14:35 oops - the diff probably threw me
34 }
35
117 void MenuRunnerImpl::Release() { 36 void MenuRunnerImpl::Release() {
118 if (running_) { 37 if (running_) {
119 if (delete_after_run_) 38 if (delete_after_run_)
120 return; // We already canceled. 39 return; // We already canceled.
121 40
122 // The menu is running a nested message loop, we can't delete it now 41 // The menu is running a nested message loop, we can't delete it now
123 // otherwise the stack would be in a really bad state (many frames would 42 // otherwise the stack would be in a really bad state (many frames would
124 // have deleted objects on them). Instead cancel the menu, when it returns 43 // have deleted objects on them). Instead cancel the menu, when it returns
125 // Holder will delete itself. 44 // Holder will delete itself.
126 delete_after_run_ = true; 45 delete_after_run_ = true;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 controller = NULL; 93 controller = NULL;
175 } 94 }
176 } 95 }
177 96
178 running_ = true; 97 running_ = true;
179 for_drop_ = (types & MenuRunner::FOR_DROP) != 0; 98 for_drop_ = (types & MenuRunner::FOR_DROP) != 0;
180 bool has_mnemonics = (types & MenuRunner::HAS_MNEMONICS) != 0 && !for_drop_; 99 bool has_mnemonics = (types & MenuRunner::HAS_MNEMONICS) != 0 && !for_drop_;
181 owns_controller_ = false; 100 owns_controller_ = false;
182 if (!controller) { 101 if (!controller) {
183 // No menus are showing, show one. 102 // No menus are showing, show one.
184 ui::NativeTheme* theme = parent ? parent->GetNativeTheme() : 103 ui::NativeTheme* theme =
185 ui::NativeTheme::instance(); 104 parent ? parent->GetNativeTheme() : ui::NativeTheme::instance();
186 controller = new MenuController(theme, !for_drop_, this); 105 controller = new MenuController(theme, !for_drop_, this);
187 owns_controller_ = true; 106 owns_controller_ = true;
188 } 107 }
189 controller->set_is_combobox((types & MenuRunner::COMBOBOX) != 0); 108 controller->set_is_combobox((types & MenuRunner::COMBOBOX) != 0);
190 controller_ = controller; 109 controller_ = controller;
191 menu_->set_controller(controller_); 110 menu_->set_controller(controller_);
192 menu_->PrepareForRun(owns_controller_, 111 menu_->PrepareForRun(owns_controller_,
193 has_mnemonics, 112 has_mnemonics,
194 !for_drop_ && ShouldShowMnemonics(button)); 113 !for_drop_ && ShouldShowMnemonics(button));
195 114
(...skipping 30 matching lines...) Expand all
226 } 145 }
227 146
228 void MenuRunnerImpl::SiblingMenuCreated(MenuItemView* menu) { 147 void MenuRunnerImpl::SiblingMenuCreated(MenuItemView* menu) {
229 if (menu != menu_ && sibling_menus_.count(menu) == 0) 148 if (menu != menu_ && sibling_menus_.count(menu) == 0)
230 sibling_menus_.insert(menu); 149 sibling_menus_.insert(menu);
231 } 150 }
232 151
233 MenuRunnerImpl::~MenuRunnerImpl() { 152 MenuRunnerImpl::~MenuRunnerImpl() {
234 delete menu_; 153 delete menu_;
235 for (std::set<MenuItemView*>::iterator i = sibling_menus_.begin(); 154 for (std::set<MenuItemView*>::iterator i = sibling_menus_.begin();
236 i != sibling_menus_.end(); ++i) 155 i != sibling_menus_.end();
156 ++i)
237 delete *i; 157 delete *i;
238 } 158 }
239 159
240 MenuRunner::RunResult MenuRunnerImpl::MenuDone(MenuItemView* result, 160 MenuRunner::RunResult MenuRunnerImpl::MenuDone(MenuItemView* result,
241 int mouse_event_flags) { 161 int mouse_event_flags) {
242 menu_->RemoveEmptyMenus(); 162 menu_->RemoveEmptyMenus();
243 menu_->set_controller(NULL); 163 menu_->set_controller(NULL);
244 164
245 if (owns_controller_) { 165 if (owns_controller_) {
246 // We created the controller and need to delete it. 166 // We created the controller and need to delete it.
(...skipping 25 matching lines...) Expand all
272 bool show_mnemonics = button ? button->HasFocus() : false; 192 bool show_mnemonics = button ? button->HasFocus() : false;
273 #if defined(OS_WIN) 193 #if defined(OS_WIN)
274 // This is only needed on Windows. 194 // This is only needed on Windows.
275 if (!show_mnemonics) 195 if (!show_mnemonics)
276 show_mnemonics = base::win::IsAltPressed(); 196 show_mnemonics = base::win::IsAltPressed();
277 #endif 197 #endif
278 return show_mnemonics; 198 return show_mnemonics;
279 } 199 }
280 200
281 } // namespace internal 201 } // namespace internal
282
283 MenuRunner::MenuRunner(ui::MenuModel* menu_model)
284 : menu_model_adapter_(new MenuModelAdapter(menu_model)),
285 holder_(new internal::MenuRunnerImpl(menu_model_adapter_->CreateMenu())) {
286 }
287
288 MenuRunner::MenuRunner(MenuItemView* menu)
289 : holder_(new internal::MenuRunnerImpl(menu)) {
290 }
291
292 MenuRunner::~MenuRunner() {
293 holder_->Release();
294 }
295
296 MenuItemView* MenuRunner::GetMenu() {
297 return holder_->menu();
298 }
299
300 MenuRunner::RunResult MenuRunner::RunMenuAt(Widget* parent,
301 MenuButton* button,
302 const gfx::Rect& bounds,
303 MenuAnchorPosition anchor,
304 ui::MenuSourceType source_type,
305 int32 types) {
306 if (runner_handler_.get()) {
307 return runner_handler_->RunMenuAt(parent, button, bounds, anchor,
308 source_type, types);
309 }
310
311 // The parent of the nested menu will have created a DisplayChangeListener, so
312 // we avoid creating a DisplayChangeListener if nested. Drop menus are
313 // transient, so we don't cancel in that case.
314 if ((types & (IS_NESTED | FOR_DROP)) == 0 && parent) {
315 display_change_listener_.reset(
316 internal::DisplayChangeListener::Create(parent, this));
317 }
318
319 if (types & CONTEXT_MENU) {
320 switch (source_type) {
321 case ui::MENU_SOURCE_NONE:
322 case ui::MENU_SOURCE_KEYBOARD:
323 case ui::MENU_SOURCE_MOUSE:
324 anchor = MENU_ANCHOR_TOPLEFT;
325 break;
326 case ui::MENU_SOURCE_TOUCH:
327 case ui::MENU_SOURCE_TOUCH_EDIT_MENU:
328 anchor = MENU_ANCHOR_BOTTOMCENTER;
329 break;
330 default:
331 break;
332 }
333 }
334
335 return holder_->RunMenuAt(parent, button, bounds, anchor, types);
336 }
337
338 bool MenuRunner::IsRunning() const {
339 return holder_->running();
340 }
341
342 void MenuRunner::Cancel() {
343 holder_->Cancel();
344 }
345
346 base::TimeDelta MenuRunner::closing_event_time() const {
347 return holder_->closing_event_time();
348 }
349
350 void MenuRunner::SetRunnerHandler(
351 scoped_ptr<MenuRunnerHandler> runner_handler) {
352 runner_handler_ = runner_handler.Pass();
353 }
354
355 } // namespace views 202 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698