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/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 39 #include "ui/views/widget/widget.h" | 39 #include "ui/views/widget/widget.h" |
| 40 | 40 |
| 41 #if defined(OS_WIN) | 41 #if defined(OS_WIN) |
| 42 #include "ui/aura/window_tree_host.h" | 42 #include "ui/aura/window_tree_host.h" |
| 43 #include "ui/base/win/internal_constants.h" | 43 #include "ui/base/win/internal_constants.h" |
| 44 #include "ui/display/win/screen_win.h" | 44 #include "ui/display/win/screen_win.h" |
| 45 #include "ui/views/win/hwnd_util.h" | 45 #include "ui/views/win/hwnd_util.h" |
| 46 #endif | 46 #endif |
| 47 | 47 |
| 48 #if defined(USE_AURA) | 48 #if defined(USE_AURA) |
| 49 #include "ui/views/controls/menu/activation_change_observer_impl.h" | |
| 49 #include "ui/views/controls/menu/menu_key_event_handler.h" | 50 #include "ui/views/controls/menu/menu_key_event_handler.h" |
| 50 #endif | 51 #endif |
| 51 | 52 |
| 52 using base::Time; | 53 using base::Time; |
| 53 using base::TimeDelta; | 54 using base::TimeDelta; |
| 54 using ui::OSExchangeData; | 55 using ui::OSExchangeData; |
| 55 | 56 |
| 56 namespace views { | 57 namespace views { |
| 57 | 58 |
| 58 namespace { | 59 namespace { |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 if (event && event->type() == ui::ET_MOUSE_PRESSED) { | 414 if (event && event->type() == ui::ET_MOUSE_PRESSED) { |
| 414 gfx::Point screen_loc( | 415 gfx::Point screen_loc( |
| 415 static_cast<const ui::MouseEvent*>(event)->location()); | 416 static_cast<const ui::MouseEvent*>(event)->location()); |
| 416 View::ConvertPointToScreen( | 417 View::ConvertPointToScreen( |
| 417 static_cast<View*>(event->target()), &screen_loc); | 418 static_cast<View*>(event->target()), &screen_loc); |
| 418 menu_start_mouse_press_loc_ = screen_loc; | 419 menu_start_mouse_press_loc_ = screen_loc; |
| 419 } | 420 } |
| 420 } | 421 } |
| 421 } | 422 } |
| 422 | 423 |
| 423 bool nested_menu = showing_; | 424 // If we are already showing, this new menu is being nested. Such as context |
| 425 // menus on top of normal menus. | |
| 424 if (showing_) { | 426 if (showing_) { |
| 425 // Only support nesting of blocking_run menus, nesting of | 427 // Only support nesting of blocking_run menus, nesting of |
| 426 // blocking/non-blocking shouldn't be needed. | 428 // blocking/non-blocking shouldn't be needed. |
| 427 DCHECK(blocking_run_); | 429 DCHECK(blocking_run_); |
| 428 | 430 |
| 429 state_.hot_button = hot_button_; | 431 state_.hot_button = hot_button_; |
| 430 hot_button_ = nullptr; | 432 hot_button_ = nullptr; |
| 431 // We're already showing, push the current state. | 433 // We're already showing, push the current state. |
| 432 menu_stack_.push_back( | 434 menu_stack_.push_back( |
| 433 std::make_pair(state_, make_linked_ptr(pressed_lock_.release()))); | 435 std::make_pair(state_, make_linked_ptr(pressed_lock_.release()))); |
| 434 | 436 |
| 435 // The context menu should be owned by the same parent. | 437 // The context menu should be owned by the same parent. |
| 436 DCHECK_EQ(owner_, parent); | 438 DCHECK_EQ(owner_, parent); |
| 437 } else { | 439 } else { |
| 438 showing_ = true; | 440 showing_ = true; |
| 439 | 441 |
| 442 if (owner_) | |
| 443 owner_->RemoveObserver(this); | |
| 444 owner_ = parent; | |
| 445 if (owner_) | |
| 446 owner_->AddObserver(this); | |
| 447 | |
| 440 #if defined(USE_AURA) | 448 #if defined(USE_AURA) |
| 441 // Only create a MenuKeyEventHandler for non-nested menus. Nested menus will | 449 // Only create a MenuKeyEventHandler and ActivationChnageObserver for |
|
sky
2016/08/01 21:39:45
'Chnage'->Change
jonross
2016/08/02 15:03:25
Done.
| |
| 442 // use the existing one. | 450 // non-nested menus. Nested menus will use the existing one. |
| 451 activation_change_observer_.reset( | |
| 452 new ActivationChangeObserverImpl(this, owner_)); | |
| 443 key_event_handler_.reset(new MenuKeyEventHandler); | 453 key_event_handler_.reset(new MenuKeyEventHandler); |
| 444 #endif | 454 #endif |
| 445 } | 455 } |
| 446 | 456 |
| 447 // Reset current state. | 457 // Reset current state. |
| 448 pending_state_ = State(); | 458 pending_state_ = State(); |
| 449 state_ = State(); | 459 state_ = State(); |
| 450 UpdateInitialLocation(bounds, position, context_menu); | 460 UpdateInitialLocation(bounds, position, context_menu); |
| 451 | 461 |
| 452 if (owner_) | |
| 453 owner_->RemoveObserver(this); | |
| 454 owner_ = parent; | |
| 455 if (owner_) | |
| 456 owner_->AddObserver(this); | |
| 457 | |
| 458 // Set the selection, which opens the initial menu. | 462 // Set the selection, which opens the initial menu. |
| 459 SetSelection(root, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); | 463 SetSelection(root, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); |
| 460 | 464 |
| 461 if (!blocking_run_) { | 465 if (!blocking_run_) { |
| 462 if (!is_nested_drag) { | 466 if (!is_nested_drag) { |
| 463 // Start the timer to hide the menu. This is needed as we get no | 467 // Start the timer to hide the menu. This is needed as we get no |
| 464 // notification when the drag has finished. | 468 // notification when the drag has finished. |
| 465 StartCancelAllTimer(); | 469 StartCancelAllTimer(); |
| 466 } | 470 } |
| 467 return NULL; | 471 return NULL; |
| 468 } | 472 } |
| 469 | 473 |
| 470 if (button) | 474 if (button) |
| 471 pressed_lock_.reset(new MenuButton::PressedLock(button)); | 475 pressed_lock_.reset(new MenuButton::PressedLock(button)); |
| 472 | 476 |
| 473 // Make sure Chrome doesn't attempt to shut down while the menu is showing. | 477 // Make sure Chrome doesn't attempt to shut down while the menu is showing. |
| 474 if (ViewsDelegate::GetInstance()) | 478 if (ViewsDelegate::GetInstance()) |
| 475 ViewsDelegate::GetInstance()->AddRef(); | 479 ViewsDelegate::GetInstance()->AddRef(); |
| 476 | 480 |
| 477 if (async_run_) | 481 if (async_run_) |
| 478 return nullptr; | 482 return nullptr; |
| 479 | 483 |
| 480 // We need to turn on nestable tasks as in some situations (pressing alt-f for | 484 // We need to turn on nestable tasks as in some situations (pressing alt-f for |
| 481 // one) the menus are run from a task. If we don't do this and are invoked | 485 // one) the menus are run from a task. If we don't do this and are invoked |
| 482 // from a task none of the tasks we schedule are processed and the menu | 486 // from a task none of the tasks we schedule are processed and the menu |
| 483 // appears totally broken. | 487 // appears totally broken. |
| 484 message_loop_depth_++; | 488 message_loop_depth_++; |
| 485 DCHECK_LE(message_loop_depth_, 2); | 489 DCHECK_LE(message_loop_depth_, 2); |
| 486 RunMessageLoop(nested_menu); | 490 RunMessageLoop(); |
| 487 message_loop_depth_--; | 491 message_loop_depth_--; |
| 488 | 492 |
| 489 if (ViewsDelegate::GetInstance()) | 493 if (ViewsDelegate::GetInstance()) |
| 490 ViewsDelegate::GetInstance()->ReleaseRef(); | 494 ViewsDelegate::GetInstance()->ReleaseRef(); |
| 491 | 495 |
| 492 if (result_event_flags) | 496 if (result_event_flags) |
| 493 *result_event_flags = accept_event_flags_; | 497 *result_event_flags = accept_event_flags_; |
| 494 | 498 |
| 495 // The nested message loop could have been killed externally. Check to see if | 499 // The nested message loop could have been killed externally. Check to see if |
| 496 // there are nested asynchronous menus to shutdown. | 500 // there are nested asynchronous menus to shutdown. |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1079 View::ConvertPointFromScreen( | 1083 View::ConvertPointFromScreen( |
| 1080 root_submenu->GetWidget()->GetRootView(), &point); | 1084 root_submenu->GetWidget()->GetRootView(), &point); |
| 1081 HandleMouseLocation(submenu, point); | 1085 HandleMouseLocation(submenu, point); |
| 1082 } | 1086 } |
| 1083 } | 1087 } |
| 1084 | 1088 |
| 1085 void MenuController::OnWidgetDestroying(Widget* widget) { | 1089 void MenuController::OnWidgetDestroying(Widget* widget) { |
| 1086 DCHECK_EQ(owner_, widget); | 1090 DCHECK_EQ(owner_, widget); |
| 1087 owner_->RemoveObserver(this); | 1091 owner_->RemoveObserver(this); |
| 1088 owner_ = NULL; | 1092 owner_ = NULL; |
| 1089 message_loop_->ClearOwner(); | |
| 1090 } | 1093 } |
| 1091 | 1094 |
| 1092 bool MenuController::IsCancelAllTimerRunningForTest() { | 1095 bool MenuController::IsCancelAllTimerRunningForTest() { |
| 1093 return cancel_all_timer_.IsRunning(); | 1096 return cancel_all_timer_.IsRunning(); |
| 1094 } | 1097 } |
| 1095 | 1098 |
| 1096 // static | 1099 // static |
| 1097 void MenuController::TurnOffMenuSelectionHoldForTest() { | 1100 void MenuController::TurnOffMenuSelectionHoldForTest() { |
| 1098 menu_selection_hold_time_ms = -1; | 1101 menu_selection_hold_time_ms = -1; |
| 1099 } | 1102 } |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1380 MenuController::~MenuController() { | 1383 MenuController::~MenuController() { |
| 1381 DCHECK(!showing_); | 1384 DCHECK(!showing_); |
| 1382 if (owner_) | 1385 if (owner_) |
| 1383 owner_->RemoveObserver(this); | 1386 owner_->RemoveObserver(this); |
| 1384 if (active_instance_ == this) | 1387 if (active_instance_ == this) |
| 1385 active_instance_ = NULL; | 1388 active_instance_ = NULL; |
| 1386 StopShowTimer(); | 1389 StopShowTimer(); |
| 1387 StopCancelAllTimer(); | 1390 StopCancelAllTimer(); |
| 1388 } | 1391 } |
| 1389 | 1392 |
| 1390 void MenuController::RunMessageLoop(bool nested_menu) { | 1393 void MenuController::RunMessageLoop() { |
| 1391 message_loop_->Run(this, owner_, nested_menu); | 1394 message_loop_->Run(); |
| 1392 } | 1395 } |
| 1393 | 1396 |
| 1394 bool MenuController::SendAcceleratorToHotTrackedView() { | 1397 bool MenuController::SendAcceleratorToHotTrackedView() { |
| 1395 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); | 1398 CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item); |
| 1396 if (!hot_view) | 1399 if (!hot_view) |
| 1397 return false; | 1400 return false; |
| 1398 | 1401 |
| 1399 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE); | 1402 ui::Accelerator accelerator(ui::VKEY_RETURN, ui::EF_NONE); |
| 1400 hot_view->AcceleratorPressed(accelerator); | 1403 hot_view->AcceleratorPressed(accelerator); |
| 1401 CustomButton* button = static_cast<CustomButton*>(hot_view); | 1404 CustomButton* button = static_cast<CustomButton*>(hot_view); |
| (...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2603 nested_pressed_lock = menu_stack_.back().second; | 2606 nested_pressed_lock = menu_stack_.back().second; |
| 2604 menu_stack_.pop_back(); | 2607 menu_stack_.pop_back(); |
| 2605 // Even though the menus are nested, there may not be nested delegates. | 2608 // Even though the menus are nested, there may not be nested delegates. |
| 2606 if (delegate_stack_.size() > 1) { | 2609 if (delegate_stack_.size() > 1) { |
| 2607 delegate_stack_.pop_back(); | 2610 delegate_stack_.pop_back(); |
| 2608 delegate_ = delegate_stack_.back().first; | 2611 delegate_ = delegate_stack_.back().first; |
| 2609 async_run_ = delegate_stack_.back().second; | 2612 async_run_ = delegate_stack_.back().second; |
| 2610 } | 2613 } |
| 2611 } else { | 2614 } else { |
| 2612 #if defined(USE_AURA) | 2615 #if defined(USE_AURA) |
| 2616 activation_change_observer_.reset(); | |
| 2613 key_event_handler_.reset(); | 2617 key_event_handler_.reset(); |
| 2614 #endif | 2618 #endif |
| 2615 | 2619 |
| 2616 showing_ = false; | 2620 showing_ = false; |
| 2617 did_capture_ = false; | 2621 did_capture_ = false; |
| 2618 } | 2622 } |
| 2619 | 2623 |
| 2620 MenuItemView* result = result_; | 2624 MenuItemView* result = result_; |
| 2621 // In case we're nested, reset |result_|. | 2625 // In case we're nested, reset |result_|. |
| 2622 result_ = nullptr; | 2626 result_ = nullptr; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2703 if (hot_button_) | 2707 if (hot_button_) |
| 2704 hot_button_->SetHotTracked(false); | 2708 hot_button_->SetHotTracked(false); |
| 2705 hot_button_ = hot_button; | 2709 hot_button_ = hot_button; |
| 2706 if (hot_button) { | 2710 if (hot_button) { |
| 2707 hot_button->SetHotTracked(true); | 2711 hot_button->SetHotTracked(true); |
| 2708 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); | 2712 hot_button->NotifyAccessibilityEvent(ui::AX_EVENT_SELECTION, true); |
| 2709 } | 2713 } |
| 2710 } | 2714 } |
| 2711 | 2715 |
| 2712 } // namespace views | 2716 } // namespace views |
| OLD | NEW |