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

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

Issue 1515203002: Update closing of nested asynchronous menus (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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_controller.h" 5 #include "ui/views/controls/menu/menu_controller.h"
6 6
7 #include "base/i18n/case_conversion.h" 7 #include "base/i18n/case_conversion.h"
8 #include "base/i18n/rtl.h" 8 #include "base/i18n/rtl.h"
9 #include "base/strings/utf_string_conversions.h" 9 #include "base/strings/utf_string_conversions.h"
10 #include "base/time/time.h" 10 #include "base/time/time.h"
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 if (!blocking_run_) { 409 if (!blocking_run_) {
410 // If we didn't block the caller we need to notify the menu, which 410 // If we didn't block the caller we need to notify the menu, which
411 // triggers deleting us. 411 // triggers deleting us.
412 DCHECK(selected); 412 DCHECK(selected);
413 showing_ = false; 413 showing_ = false;
414 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, 414 delegate_->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
415 selected->GetRootMenuItem(), accept_event_flags_); 415 selected->GetRootMenuItem(), accept_event_flags_);
416 // WARNING: the call to MenuClosed deletes us. 416 // WARNING: the call to MenuClosed deletes us.
417 return; 417 return;
418 } 418 }
419 if (async_run_) { 419 ExitAsyncRun();
420 internal::MenuControllerDelegate* delegate = delegate_;
421 MenuItemView* result = ExitMenuRun();
422 delegate->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
423 result, accept_event_flags_);
424 }
425 } 420 }
426 421
427 void MenuController::AddNestedDelegate( 422 void MenuController::AddNestedDelegate(
428 internal::MenuControllerDelegate* delegate) { 423 internal::MenuControllerDelegate* delegate) {
429 delegate_stack_.push_back(std::make_pair(delegate, async_run_)); 424 delegate_stack_.push_back(std::make_pair(delegate, async_run_));
430 delegate_ = delegate; 425 delegate_ = delegate;
431 } 426 }
432 427
433 void MenuController::SetAsyncRun(bool is_async) { 428 void MenuController::SetAsyncRun(bool is_async) {
434 delegate_stack_.back().second = is_async; 429 delegate_stack_.back().second = is_async;
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 drop_target = drop_target->GetParentMenuItem(); 804 drop_target = drop_target->GetParentMenuItem();
810 805
811 if (!IsBlockingRun()) { 806 if (!IsBlockingRun()) {
812 delegate_->OnMenuClosed( 807 delegate_->OnMenuClosed(
813 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE, 808 internal::MenuControllerDelegate::DONT_NOTIFY_DELEGATE,
814 item->GetRootMenuItem(), accept_event_flags_); 809 item->GetRootMenuItem(), accept_event_flags_);
815 } 810 }
816 811
817 // WARNING: the call to MenuClosed deletes us. 812 // WARNING: the call to MenuClosed deletes us.
818 813
814 // ExitAsyncRun can delete us, however CloseAllNestedMenus enqueues work which
sky 2015/12/11 18:37:46 I'm nervous of posting the task. What work is caus
jonross 2016/01/06 21:18:31 The shutdown enqueues the closing the current widg
sky 2016/01/06 22:20:56 What do you mean by 'corrupted buffer that is rele
jonross 2016/01/08 20:52:01 I'm seeing a few memory errors: - Found a corru
815 // our deletion interferes with. Perform exit afterwards.
816 base::MessageLoopForUI::current()->PostTask(
817 FROM_HERE,
818 base::Bind(&MenuController::ExitAsyncRun, weak_factory_.GetWeakPtr()));
819 return drop_target->GetDelegate()->OnPerformDrop( 819 return drop_target->GetDelegate()->OnPerformDrop(
820 drop_target, drop_position, event); 820 drop_target, drop_position, event);
821 } 821 }
822 822
823 void MenuController::OnDragEnteredScrollButton(SubmenuView* source, 823 void MenuController::OnDragEnteredScrollButton(SubmenuView* source,
824 bool is_up) { 824 bool is_up) {
825 MenuPart part; 825 MenuPart part;
826 part.type = is_up ? MenuPart::SCROLL_UP : MenuPart::SCROLL_DOWN; 826 part.type = is_up ? MenuPart::SCROLL_UP : MenuPart::SCROLL_DOWN;
827 part.submenu = source; 827 part.submenu = source;
828 UpdateScrolling(part); 828 UpdateScrolling(part);
(...skipping 18 matching lines...) Expand all
847 void MenuController::OnDragComplete(bool should_close) { 847 void MenuController::OnDragComplete(bool should_close) {
848 DCHECK(drag_in_progress_); 848 DCHECK(drag_in_progress_);
849 drag_in_progress_ = false; 849 drag_in_progress_ = false;
850 // During a drag, mouse events are processed directly by the widget, and not 850 // During a drag, mouse events are processed directly by the widget, and not
851 // sent to the MenuController. At drag completion, reset pressed state and 851 // sent to the MenuController. At drag completion, reset pressed state and
852 // the event target. 852 // the event target.
853 current_mouse_pressed_state_ = 0; 853 current_mouse_pressed_state_ = 0;
854 current_mouse_event_target_ = nullptr; 854 current_mouse_event_target_ = nullptr;
855 if (showing_ && should_close && GetActiveInstance() == this) { 855 if (showing_ && should_close && GetActiveInstance() == this) {
856 CloseAllNestedMenus(); 856 CloseAllNestedMenus();
857 Cancel(EXIT_ALL); 857 if (async_run_) {
858 base::MessageLoopForUI::current()->PostTask(
859 FROM_HERE,
860 base::Bind(&MenuController::CancelAll, weak_factory_.GetWeakPtr()));
861 } else {
862 Cancel(EXIT_ALL);
863 }
858 } 864 }
859 } 865 }
860 866
861 ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent( 867 ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
862 base::char16 character, 868 base::char16 character,
863 ui::KeyboardCode key_code) { 869 ui::KeyboardCode key_code) {
864 if (exit_type() == MenuController::EXIT_ALL || 870 if (exit_type() == MenuController::EXIT_ALL ||
865 exit_type() == MenuController::EXIT_DESTROYED) { 871 exit_type() == MenuController::EXIT_DESTROYED) {
866 TerminateNestedMessageLoop(); 872 TerminateNestedMessageLoop();
867 return ui::POST_DISPATCH_PERFORM_DEFAULT; 873 return ui::POST_DISPATCH_PERFORM_DEFAULT;
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1190 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()), 1196 active_mouse_view_id_(ViewStorage::GetInstance()->CreateStorageID()),
1191 delegate_(delegate), 1197 delegate_(delegate),
1192 message_loop_depth_(0), 1198 message_loop_depth_(0),
1193 closing_event_time_(base::TimeDelta()), 1199 closing_event_time_(base::TimeDelta()),
1194 menu_start_time_(base::TimeTicks()), 1200 menu_start_time_(base::TimeTicks()),
1195 async_run_(false), 1201 async_run_(false),
1196 is_combobox_(false), 1202 is_combobox_(false),
1197 item_selected_by_touch_(false), 1203 item_selected_by_touch_(false),
1198 current_mouse_event_target_(nullptr), 1204 current_mouse_event_target_(nullptr),
1199 current_mouse_pressed_state_(0), 1205 current_mouse_pressed_state_(0),
1200 message_loop_(MenuMessageLoop::Create()) { 1206 message_loop_(MenuMessageLoop::Create()),
1207 weak_factory_(this) {
1201 delegate_stack_.push_back(std::make_pair(delegate_, async_run_)); 1208 delegate_stack_.push_back(std::make_pair(delegate_, async_run_));
1202 active_instance_ = this; 1209 active_instance_ = this;
1203 } 1210 }
1204 1211
1205 MenuController::~MenuController() { 1212 MenuController::~MenuController() {
1206 DCHECK(!showing_); 1213 DCHECK(!showing_);
1207 if (owner_) 1214 if (owner_)
1208 owner_->RemoveObserver(this); 1215 owner_->RemoveObserver(this);
1209 if (active_instance_ == this) 1216 if (active_instance_ == this)
1210 active_instance_ = NULL; 1217 active_instance_ = NULL;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 void MenuController::Accept(MenuItemView* item, int event_flags) { 1274 void MenuController::Accept(MenuItemView* item, int event_flags) {
1268 DCHECK(IsBlockingRun()); 1275 DCHECK(IsBlockingRun());
1269 result_ = item; 1276 result_ = item;
1270 if (item && !menu_stack_.empty() && 1277 if (item && !menu_stack_.empty() &&
1271 !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) { 1278 !item->GetDelegate()->ShouldCloseAllMenusOnExecute(item->GetCommand())) {
1272 SetExitType(EXIT_OUTERMOST); 1279 SetExitType(EXIT_OUTERMOST);
1273 } else { 1280 } else {
1274 SetExitType(EXIT_ALL); 1281 SetExitType(EXIT_ALL);
1275 } 1282 }
1276 accept_event_flags_ = event_flags; 1283 accept_event_flags_ = event_flags;
1277 if (async_run_) { 1284 ExitAsyncRun();
1278 internal::MenuControllerDelegate* delegate = delegate_;
1279 MenuItemView* result = ExitMenuRun();
1280 delegate->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
1281 result, accept_event_flags_);
1282 }
1283 } 1285 }
1284 1286
1285 bool MenuController::ShowSiblingMenu(SubmenuView* source, 1287 bool MenuController::ShowSiblingMenu(SubmenuView* source,
1286 const gfx::Point& mouse_location) { 1288 const gfx::Point& mouse_location) {
1287 if (!menu_stack_.empty() || !pressed_lock_.get()) 1289 if (!menu_stack_.empty() || !pressed_lock_.get())
1288 return false; 1290 return false;
1289 1291
1290 View* source_view = source->GetScrollViewContainer(); 1292 View* source_view = source->GetScrollViewContainer();
1291 if (mouse_location.x() >= 0 && 1293 if (mouse_location.x() >= 0 &&
1292 mouse_location.x() < source_view->width() && 1294 mouse_location.x() < source_view->width() &&
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2410 // the current loop. 2412 // the current loop.
2411 bool quit_now = exit_type_ != EXIT_NONE && message_loop_depth_; 2413 bool quit_now = exit_type_ != EXIT_NONE && message_loop_depth_;
2412 if (quit_now) 2414 if (quit_now)
2413 TerminateNestedMessageLoop(); 2415 TerminateNestedMessageLoop();
2414 } 2416 }
2415 2417
2416 void MenuController::TerminateNestedMessageLoop() { 2418 void MenuController::TerminateNestedMessageLoop() {
2417 message_loop_->QuitNow(); 2419 message_loop_->QuitNow();
2418 } 2420 }
2419 2421
2422 void MenuController::ExitAsyncRun() {
2423 if (!async_run_)
2424 return;
2425 bool nested = delegate_stack_.size() > 1;
2426 // ExitMenuRun unwinds nested delegates
2427 internal::MenuControllerDelegate* delegate = delegate_;
2428 MenuItemView* result = ExitMenuRun();
2429 delegate->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE,
2430 result, accept_event_flags_);
2431 if (nested && exit_type_ == EXIT_ALL)
2432 ExitAsyncRun();
2433 }
2434
2420 MenuItemView* MenuController::ExitMenuRun() { 2435 MenuItemView* MenuController::ExitMenuRun() {
2421 // Release the lock which prevents Chrome from shutting down while the menu is 2436 // Release the lock which prevents Chrome from shutting down while the menu is
2422 // showing. 2437 // showing.
2423 if (async_run_ && ViewsDelegate::GetInstance()) 2438 if (async_run_ && ViewsDelegate::GetInstance())
2424 ViewsDelegate::GetInstance()->ReleaseRef(); 2439 ViewsDelegate::GetInstance()->ReleaseRef();
2425 2440
2426 // Close any open menus. 2441 // Close any open menus.
2427 SetSelection(nullptr, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 2442 SetSelection(nullptr, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
2428 2443
2429 #if defined(OS_WIN) 2444 #if defined(OS_WIN)
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2530 } 2545 }
2531 } 2546 }
2532 2547
2533 gfx::Screen* MenuController::GetScreen() { 2548 gfx::Screen* MenuController::GetScreen() {
2534 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL; 2549 Widget* root = owner_ ? owner_->GetTopLevelWidget() : NULL;
2535 return root ? gfx::Screen::GetScreenFor(root->GetNativeView()) 2550 return root ? gfx::Screen::GetScreenFor(root->GetNativeView())
2536 : gfx::Screen::GetNativeScreen(); 2551 : gfx::Screen::GetNativeScreen();
2537 } 2552 }
2538 2553
2539 } // namespace views 2554 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/menu/menu_controller.h ('k') | ui/views/controls/menu/menu_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698