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

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

Issue 1775533002: Fixes incorrect clearing of hot-tracked state when context menu is opened from a menu item (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moves hot_button tracking from MenuController to MenuController::State (unit test) Created 4 years, 9 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
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/macros.h" 9 #include "base/macros.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 356
357 // If there are multiple matches this is the index of the item after the 357 // If there are multiple matches this is the index of the item after the
358 // currently selected item whose mnemonic matches. This may remain -1 even 358 // currently selected item whose mnemonic matches. This may remain -1 even
359 // though there are matches. 359 // though there are matches.
360 int next_match; 360 int next_match;
361 }; 361 };
362 362
363 // MenuController:State ------------------------------------------------------ 363 // MenuController:State ------------------------------------------------------
364 364
365 MenuController::State::State() 365 MenuController::State::State()
366 : item(NULL), 366 : item(nullptr),
367 hot_button(nullptr),
367 submenu_open(false), 368 submenu_open(false),
368 anchor(MENU_ANCHOR_TOPLEFT), 369 anchor(MENU_ANCHOR_TOPLEFT),
369 context_menu(false) { 370 context_menu(false) {
370 } 371 }
371 372
372 MenuController::State::State(const State& other) = default; 373 MenuController::State::State(const State& other) = default;
373 374
374 MenuController::State::~State() {} 375 MenuController::State::~State() {}
375 376
376 // MenuController ------------------------------------------------------------ 377 // MenuController ------------------------------------------------------------
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 } 418 }
418 } 419 }
419 } 420 }
420 421
421 bool nested_menu = showing_; 422 bool nested_menu = showing_;
422 if (showing_) { 423 if (showing_) {
423 // Only support nesting of blocking_run menus, nesting of 424 // Only support nesting of blocking_run menus, nesting of
424 // blocking/non-blocking shouldn't be needed. 425 // blocking/non-blocking shouldn't be needed.
425 DCHECK(blocking_run_); 426 DCHECK(blocking_run_);
426 427
428 state_.hot_button = hot_button_;
429 hot_button_ = nullptr;
427 // We're already showing, push the current state. 430 // We're already showing, push the current state.
428 menu_stack_.push_back( 431 menu_stack_.push_back(
429 std::make_pair(state_, make_linked_ptr(pressed_lock_.release()))); 432 std::make_pair(state_, make_linked_ptr(pressed_lock_.release())));
430 433
431 // The context menu should be owned by the same parent. 434 // The context menu should be owned by the same parent.
432 DCHECK_EQ(owner_, parent); 435 DCHECK_EQ(owner_, parent);
433 } else { 436 } else {
434 showing_ = true; 437 showing_ = true;
435 438
436 #if defined(USE_AURA) 439 #if defined(USE_AURA)
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 554
552 current_mouse_pressed_state_ |= event.changed_button_flags(); 555 current_mouse_pressed_state_ |= event.changed_button_flags();
553 556
554 if (forward_to_root) { 557 if (forward_to_root) {
555 ui::MouseEvent event_for_root(event); 558 ui::MouseEvent event_for_root(event);
556 // Reset hot-tracking if a different view is getting a mouse press. 559 // Reset hot-tracking if a different view is getting a mouse press.
557 ConvertLocatedEventForRootView(source, forward_to_root, &event_for_root); 560 ConvertLocatedEventForRootView(source, forward_to_root, &event_for_root);
558 View* view = 561 View* view =
559 forward_to_root->GetEventHandlerForPoint(event_for_root.location()); 562 forward_to_root->GetEventHandlerForPoint(event_for_root.location());
560 CustomButton* button = CustomButton::AsCustomButton(view); 563 CustomButton* button = CustomButton::AsCustomButton(view);
561 if (hot_button_ && hot_button_ != button) 564 if (hot_button_ != button)
562 SetHotTrackedButton(nullptr); 565 SetHotTrackedButton(button);
563 566
564 // Empty menu items are always handled by the menu controller. 567 // Empty menu items are always handled by the menu controller.
565 if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) { 568 if (!view || view->id() != MenuItemView::kEmptyMenuItemViewID) {
566 bool processed = forward_to_root->ProcessMousePressed(event_for_root); 569 bool processed = forward_to_root->ProcessMousePressed(event_for_root);
567 // If the event was processed, the root view becomes our current mouse 570 // If the event was processed, the root view becomes our current mouse
568 // handler... 571 // handler...
569 if (processed && !current_mouse_event_target_) { 572 if (processed && !current_mouse_event_target_) {
570 current_mouse_event_target_ = forward_to_root; 573 current_mouse_event_target_ = forward_to_root;
571 } 574 }
572 575
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 830
828 void MenuController::ViewHierarchyChanged( 831 void MenuController::ViewHierarchyChanged(
829 SubmenuView* source, 832 SubmenuView* source,
830 const View::ViewHierarchyChangedDetails& details) { 833 const View::ViewHierarchyChangedDetails& details) {
831 if (!details.is_add) { 834 if (!details.is_add) {
832 // If the current mouse handler is removed, remove it as the handler. 835 // If the current mouse handler is removed, remove it as the handler.
833 if (details.child == current_mouse_event_target_) { 836 if (details.child == current_mouse_event_target_) {
834 current_mouse_event_target_ = nullptr; 837 current_mouse_event_target_ = nullptr;
835 current_mouse_pressed_state_ = 0; 838 current_mouse_pressed_state_ = 0;
836 } 839 }
837 // Update |hot_button_| if it gets removed while a menu is up. 840 // Update |hot_button_| (both in |this| and in |menu_stack_| if it gets
838 if (details.child == hot_button_) 841 // removed while a menu is up.
842 if (details.child == hot_button_) {
839 hot_button_ = nullptr; 843 hot_button_ = nullptr;
844 for (auto nested_state : menu_stack_) {
845 State& state = nested_state.first;
846 if (details.child == state.hot_button)
847 state.hot_button = nullptr;
848 }
849 }
840 } 850 }
841 } 851 }
842 852
843 bool MenuController::GetDropFormats( 853 bool MenuController::GetDropFormats(
844 SubmenuView* source, 854 SubmenuView* source,
845 int* formats, 855 int* formats,
846 std::set<ui::Clipboard::FormatType>* format_types) { 856 std::set<ui::Clipboard::FormatType>* format_types) {
847 return source->GetMenuItem()->GetDelegate()->GetDropFormats( 857 return source->GetMenuItem()->GetDelegate()->GetDropFormats(
848 source->GetMenuItem(), formats, format_types); 858 source->GetMenuItem(), formats, format_types);
849 } 859 }
(...skipping 1692 matching lines...) Expand 10 before | Expand all | Expand 10 after
2542 #endif 2552 #endif
2543 2553
2544 linked_ptr<MenuButton::PressedLock> nested_pressed_lock; 2554 linked_ptr<MenuButton::PressedLock> nested_pressed_lock;
2545 bool nested_menu = !menu_stack_.empty(); 2555 bool nested_menu = !menu_stack_.empty();
2546 if (nested_menu) { 2556 if (nested_menu) {
2547 DCHECK(!menu_stack_.empty()); 2557 DCHECK(!menu_stack_.empty());
2548 // We're running from within a menu, restore the previous state. 2558 // We're running from within a menu, restore the previous state.
2549 // The menus are already showing, so we don't have to show them. 2559 // The menus are already showing, so we don't have to show them.
2550 state_ = menu_stack_.back().first; 2560 state_ = menu_stack_.back().first;
2551 pending_state_ = menu_stack_.back().first; 2561 pending_state_ = menu_stack_.back().first;
2562 hot_button_ = state_.hot_button;
2552 nested_pressed_lock = menu_stack_.back().second; 2563 nested_pressed_lock = menu_stack_.back().second;
2553 menu_stack_.pop_back(); 2564 menu_stack_.pop_back();
2554 // Even though the menus are nested, there may not be nested delegates. 2565 // Even though the menus are nested, there may not be nested delegates.
2555 if (delegate_stack_.size() > 1) { 2566 if (delegate_stack_.size() > 1) {
2556 delegate_stack_.pop_back(); 2567 delegate_stack_.pop_back();
2557 delegate_ = delegate_stack_.back().first; 2568 delegate_ = delegate_stack_.back().first;
2558 async_run_ = delegate_stack_.back().second; 2569 async_run_ = delegate_stack_.back().second;
2559 } 2570 }
2560 } else { 2571 } else {
2561 #if defined(USE_AURA) 2572 #if defined(USE_AURA)
(...skipping 19 matching lines...) Expand all
2581 SetSelection(nullptr, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); 2592 SetSelection(nullptr, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT);
2582 2593
2583 // Set exit_all_, which makes sure all nested loops exit immediately. 2594 // Set exit_all_, which makes sure all nested loops exit immediately.
2584 if (exit_type_ != EXIT_DESTROYED) 2595 if (exit_type_ != EXIT_DESTROYED)
2585 SetExitType(EXIT_ALL); 2596 SetExitType(EXIT_ALL);
2586 } else { 2597 } else {
2587 TerminateNestedMessageLoopIfNecessary(); 2598 TerminateNestedMessageLoopIfNecessary();
2588 } 2599 }
2589 } 2600 }
2590 2601
2591 // Reset our pressed lock to the previous state's, if there was one. 2602 // Reset our pressed lock and hot-tracked state to the previous state's, if
2592 // The lock handles the case if the button was destroyed. 2603 // they were active. The lock handles the case if the button was destroyed.
2593 pressed_lock_.reset(nested_pressed_lock.release()); 2604 pressed_lock_.reset(nested_pressed_lock.release());
2605 if (hot_button_)
2606 hot_button_->SetHotTracked(true);
jonross 2016/03/24 18:48:18 Is it possible for this hot_button_ to no longer b
sky 2016/03/24 19:12:56 In looking at it, this method is confusingly named
2594 2607
2595 return result; 2608 return result;
2596 } 2609 }
2597 2610
2598 void MenuController::HandleMouseLocation(SubmenuView* source, 2611 void MenuController::HandleMouseLocation(SubmenuView* source,
2599 const gfx::Point& mouse_location) { 2612 const gfx::Point& mouse_location) {
2600 if (showing_submenu_) 2613 if (showing_submenu_)
2601 return; 2614 return;
2602 2615
2603 // Ignore mouse events if we're closing the menu. 2616 // Ignore mouse events if we're closing the menu.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2646 return; 2659 return;
2647 } 2660 }
2648 if (hot_button_) 2661 if (hot_button_)
2649 hot_button_->SetHotTracked(false); 2662 hot_button_->SetHotTracked(false);
2650 hot_button_ = hot_button; 2663 hot_button_ = hot_button;
2651 if (hot_button) 2664 if (hot_button)
2652 hot_button->SetHotTracked(true); 2665 hot_button->SetHotTracked(true);
2653 } 2666 }
2654 2667
2655 } // namespace views 2668 } // 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