| 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/time.h" | 9 #include "base/time.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 owner_ = parent; | 299 owner_ = parent; |
| 300 | 300 |
| 301 // Set the selection, which opens the initial menu. | 301 // Set the selection, which opens the initial menu. |
| 302 SetSelection(root, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); | 302 SetSelection(root, SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY); |
| 303 | 303 |
| 304 if (!blocking_run_) { | 304 if (!blocking_run_) { |
| 305 // Start the timer to hide the menu. This is needed as we get no | 305 // Start the timer to hide the menu. This is needed as we get no |
| 306 // notification when the drag has finished. | 306 // notification when the drag has finished. |
| 307 StartCancelAllTimer(); | 307 StartCancelAllTimer(); |
| 308 return NULL; | 308 return NULL; |
| 309 } else if (button) { | 309 } |
| 310 |
| 311 if (button) |
| 310 menu_button_ = button; | 312 menu_button_ = button; |
| 311 } | |
| 312 | 313 |
| 313 // Make sure Chrome doesn't attempt to shut down while the menu is showing. | 314 // Make sure Chrome doesn't attempt to shut down while the menu is showing. |
| 314 if (ViewsDelegate::views_delegate) | 315 if (ViewsDelegate::views_delegate) |
| 315 ViewsDelegate::views_delegate->AddRef(); | 316 ViewsDelegate::views_delegate->AddRef(); |
| 316 | 317 |
| 317 // We need to turn on nestable tasks as in some situations (pressing alt-f for | 318 // We need to turn on nestable tasks as in some situations (pressing alt-f for |
| 318 // one) the menus are run from a task. If we don't do this and are invoked | 319 // one) the menus are run from a task. If we don't do this and are invoked |
| 319 // from a task none of the tasks we schedule are processed and the menu | 320 // from a task none of the tasks we schedule are processed and the menu |
| 320 // appears totally broken. | 321 // appears totally broken. |
| 322 message_loop_depth_++; |
| 323 DCHECK_LE(message_loop_depth_, 2); |
| 321 #if defined(USE_AURA) | 324 #if defined(USE_AURA) |
| 322 aura::client::GetDispatcherClient( | 325 aura::client::GetDispatcherClient( |
| 323 parent->GetNativeWindow()->GetRootWindow())-> | 326 parent->GetNativeWindow()->GetRootWindow())-> |
| 324 RunWithDispatcher(this, parent->GetNativeWindow(), true); | 327 RunWithDispatcher(this, parent->GetNativeWindow(), true); |
| 325 #else | 328 #else |
| 326 { | 329 { |
| 327 MessageLoopForUI* loop = MessageLoopForUI::current(); | 330 MessageLoopForUI* loop = MessageLoopForUI::current(); |
| 328 MessageLoop::ScopedNestableTaskAllower allow(loop); | 331 MessageLoop::ScopedNestableTaskAllower allow(loop); |
| 329 loop->RunWithDispatcher(this); | 332 loop->RunWithDispatcher(this); |
| 330 } | 333 } |
| 331 #endif | 334 #endif |
| 335 message_loop_depth_--; |
| 332 | 336 |
| 333 if (ViewsDelegate::views_delegate) | 337 if (ViewsDelegate::views_delegate) |
| 334 ViewsDelegate::views_delegate->ReleaseRef(); | 338 ViewsDelegate::views_delegate->ReleaseRef(); |
| 335 | 339 |
| 336 // Close any open menus. | 340 // Close any open menus. |
| 337 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); | 341 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); |
| 338 | 342 |
| 339 if (nested_menu) { | 343 if (nested_menu) { |
| 340 DCHECK(!menu_stack_.empty()); | 344 DCHECK(!menu_stack_.empty()); |
| 341 // We're running from within a menu, restore the previous state. | 345 // We're running from within a menu, restore the previous state. |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1020 drop_target_(NULL), | 1024 drop_target_(NULL), |
| 1021 drop_position_(MenuDelegate::DROP_UNKNOWN), | 1025 drop_position_(MenuDelegate::DROP_UNKNOWN), |
| 1022 owner_(NULL), | 1026 owner_(NULL), |
| 1023 possible_drag_(false), | 1027 possible_drag_(false), |
| 1024 drag_in_progress_(false), | 1028 drag_in_progress_(false), |
| 1025 valid_drop_coordinates_(false), | 1029 valid_drop_coordinates_(false), |
| 1026 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), | 1030 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), |
| 1027 showing_submenu_(false), | 1031 showing_submenu_(false), |
| 1028 menu_button_(NULL), | 1032 menu_button_(NULL), |
| 1029 active_mouse_view_(NULL), | 1033 active_mouse_view_(NULL), |
| 1030 delegate_(delegate) { | 1034 delegate_(delegate), |
| 1035 message_loop_depth_(0) { |
| 1031 active_instance_ = this; | 1036 active_instance_ = this; |
| 1032 } | 1037 } |
| 1033 | 1038 |
| 1034 MenuController::~MenuController() { | 1039 MenuController::~MenuController() { |
| 1035 DCHECK(!showing_); | 1040 DCHECK(!showing_); |
| 1036 if (active_instance_ == this) | 1041 if (active_instance_ == this) |
| 1037 active_instance_ = NULL; | 1042 active_instance_ = NULL; |
| 1038 StopShowTimer(); | 1043 StopShowTimer(); |
| 1039 StopCancelAllTimer(); | 1044 StopCancelAllTimer(); |
| 1040 } | 1045 } |
| (...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1965 | 1970 |
| 1966 // Reset the active_mouse_view_ before sending mouse capture lost. That way if | 1971 // Reset the active_mouse_view_ before sending mouse capture lost. That way if |
| 1967 // it calls back to us, we aren't in a weird state. | 1972 // it calls back to us, we aren't in a weird state. |
| 1968 View* active_view = active_mouse_view_; | 1973 View* active_view = active_mouse_view_; |
| 1969 active_mouse_view_ = NULL; | 1974 active_mouse_view_ = NULL; |
| 1970 active_view->OnMouseCaptureLost(); | 1975 active_view->OnMouseCaptureLost(); |
| 1971 } | 1976 } |
| 1972 | 1977 |
| 1973 void MenuController::SetExitType(ExitType type) { | 1978 void MenuController::SetExitType(ExitType type) { |
| 1974 exit_type_ = type; | 1979 exit_type_ = type; |
| 1975 #if defined(USE_AURA) | 1980 // Exit nested message loops as soon as possible. We do this as |
| 1976 // On aura, closing menu may not trigger next native event, which | 1981 // MessageLoop::Dispatcher is only invoked before native events, which means |
| 1977 // is necessary to exit from nested loop (See Dispatch methods). | 1982 // its entirely possible for a Widget::CloseNow() task to be processed before |
| 1978 // Send non-op event so that Dispatch method will always be called. | 1983 // the next native message. By using QuitNow() we ensures the nested message |
| 1979 // crbug.com/104684. | 1984 // loop returns as soon as possible and avoids having deleted views classes |
| 1980 if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) { | 1985 // (such as widgets and rootviews) on the stack when the nested message loop |
| 1981 owner_->GetNativeView()->GetRootWindow()->PostNativeEvent( | 1986 // stops. |
| 1982 ui::CreateNoopEvent()); | 1987 // |
| 1983 } | 1988 // It's safe to invoke QuitNow multiple times, it only effects the current |
| 1984 #endif | 1989 // loop. |
| 1990 if (exit_type_ != EXIT_NONE && message_loop_depth_) |
| 1991 MessageLoop::current()->QuitNow(); |
| 1985 } | 1992 } |
| 1986 | 1993 |
| 1987 void MenuController::HandleMouseLocation(SubmenuView* source, | 1994 void MenuController::HandleMouseLocation(SubmenuView* source, |
| 1988 const gfx::Point& mouse_location) { | 1995 const gfx::Point& mouse_location) { |
| 1989 if (showing_submenu_) | 1996 if (showing_submenu_) |
| 1990 return; | 1997 return; |
| 1991 | 1998 |
| 1992 MenuPart part = GetMenuPart(source, mouse_location); | 1999 MenuPart part = GetMenuPart(source, mouse_location); |
| 1993 | 2000 |
| 1994 UpdateScrolling(part); | 2001 UpdateScrolling(part); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2006 (!pending_state_.item->HasSubmenu() || | 2013 (!pending_state_.item->HasSubmenu() || |
| 2007 !pending_state_.item->GetSubmenu()->IsShowing())) { | 2014 !pending_state_.item->GetSubmenu()->IsShowing())) { |
| 2008 // On exit if the user hasn't selected an item with a submenu, move the | 2015 // On exit if the user hasn't selected an item with a submenu, move the |
| 2009 // selection back to the parent menu item. | 2016 // selection back to the parent menu item. |
| 2010 SetSelection(pending_state_.item->GetParentMenuItem(), | 2017 SetSelection(pending_state_.item->GetParentMenuItem(), |
| 2011 SELECTION_OPEN_SUBMENU); | 2018 SELECTION_OPEN_SUBMENU); |
| 2012 } | 2019 } |
| 2013 } | 2020 } |
| 2014 | 2021 |
| 2015 } // namespace views | 2022 } // namespace views |
| OLD | NEW |