Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |