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/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_++; | |
|
Ben Goodger (Google)
2012/04/26 02:34:54
can you dcheck that this never exceeds the max you
oshima
2012/04/26 03:05:27
+1
| |
| 321 #if defined(USE_AURA) | 323 #if defined(USE_AURA) |
| 322 aura::client::GetDispatcherClient( | 324 aura::client::GetDispatcherClient( |
| 323 parent->GetNativeWindow()->GetRootWindow())-> | 325 parent->GetNativeWindow()->GetRootWindow())-> |
| 324 RunWithDispatcher(this, parent->GetNativeWindow(), true); | 326 RunWithDispatcher(this, parent->GetNativeWindow(), true); |
| 325 #else | 327 #else |
| 326 { | 328 { |
| 327 MessageLoopForUI* loop = MessageLoopForUI::current(); | 329 MessageLoopForUI* loop = MessageLoopForUI::current(); |
| 328 MessageLoop::ScopedNestableTaskAllower allow(loop); | 330 MessageLoop::ScopedNestableTaskAllower allow(loop); |
| 329 loop->RunWithDispatcher(this); | 331 loop->RunWithDispatcher(this); |
| 330 } | 332 } |
| 331 #endif | 333 #endif |
| 334 message_loop_depth_--; | |
| 332 | 335 |
| 333 if (ViewsDelegate::views_delegate) | 336 if (ViewsDelegate::views_delegate) |
| 334 ViewsDelegate::views_delegate->ReleaseRef(); | 337 ViewsDelegate::views_delegate->ReleaseRef(); |
| 335 | 338 |
| 336 // Close any open menus. | 339 // Close any open menus. |
| 337 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); | 340 SetSelection(NULL, SELECTION_UPDATE_IMMEDIATELY | SELECTION_EXIT); |
| 338 | 341 |
| 339 if (nested_menu) { | 342 if (nested_menu) { |
| 340 DCHECK(!menu_stack_.empty()); | 343 DCHECK(!menu_stack_.empty()); |
| 341 // We're running from within a menu, restore the previous state. | 344 // 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), | 1023 drop_target_(NULL), |
| 1021 drop_position_(MenuDelegate::DROP_UNKNOWN), | 1024 drop_position_(MenuDelegate::DROP_UNKNOWN), |
| 1022 owner_(NULL), | 1025 owner_(NULL), |
| 1023 possible_drag_(false), | 1026 possible_drag_(false), |
| 1024 drag_in_progress_(false), | 1027 drag_in_progress_(false), |
| 1025 valid_drop_coordinates_(false), | 1028 valid_drop_coordinates_(false), |
| 1026 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), | 1029 last_drop_operation_(MenuDelegate::DROP_UNKNOWN), |
| 1027 showing_submenu_(false), | 1030 showing_submenu_(false), |
| 1028 menu_button_(NULL), | 1031 menu_button_(NULL), |
| 1029 active_mouse_view_(NULL), | 1032 active_mouse_view_(NULL), |
| 1030 delegate_(delegate) { | 1033 delegate_(delegate), |
| 1034 message_loop_depth_(0) { | |
| 1031 active_instance_ = this; | 1035 active_instance_ = this; |
| 1032 } | 1036 } |
| 1033 | 1037 |
| 1034 MenuController::~MenuController() { | 1038 MenuController::~MenuController() { |
| 1035 DCHECK(!showing_); | 1039 DCHECK(!showing_); |
| 1036 if (active_instance_ == this) | 1040 if (active_instance_ == this) |
| 1037 active_instance_ = NULL; | 1041 active_instance_ = NULL; |
| 1038 StopShowTimer(); | 1042 StopShowTimer(); |
| 1039 StopCancelAllTimer(); | 1043 StopCancelAllTimer(); |
| 1040 } | 1044 } |
| (...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1965 | 1969 |
| 1966 // Reset the active_mouse_view_ before sending mouse capture lost. That way if | 1970 // 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. | 1971 // it calls back to us, we aren't in a weird state. |
| 1968 View* active_view = active_mouse_view_; | 1972 View* active_view = active_mouse_view_; |
| 1969 active_mouse_view_ = NULL; | 1973 active_mouse_view_ = NULL; |
| 1970 active_view->OnMouseCaptureLost(); | 1974 active_view->OnMouseCaptureLost(); |
| 1971 } | 1975 } |
| 1972 | 1976 |
| 1973 void MenuController::SetExitType(ExitType type) { | 1977 void MenuController::SetExitType(ExitType type) { |
| 1974 exit_type_ = type; | 1978 exit_type_ = type; |
| 1975 #if defined(USE_AURA) | 1979 // Exit nested message loops as soon as possible. We do this as |
| 1976 // On aura, closing menu may not trigger next native event, which | 1980 // MessageLoop::Dispatcher is only invoked before native events, which means |
| 1977 // is necessary to exit from nested loop (See Dispatch methods). | 1981 // 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. | 1982 // the next native message. By using QuitNow() we ensures the nested message |
| 1979 // crbug.com/104684. | 1983 // loop returns as soon as possible and avoids having deleted views classes |
| 1980 if (exit_type_ == EXIT_ALL || exit_type_ == EXIT_DESTROYED) { | 1984 // (such as widgets and rootviews) on the stack when the nested message loop |
| 1981 owner_->GetNativeView()->GetRootWindow()->PostNativeEvent( | 1985 // stops. |
| 1982 ui::CreateNoopEvent()); | 1986 // |
| 1983 } | 1987 // It's safe to invoke QuitNow multiple times, it only effects the current |
| 1984 #endif | 1988 // loop. |
| 1989 if (exit_type_ != EXIT_NONE && message_loop_depth_) | |
| 1990 MessageLoop::current()->QuitNow(); | |
| 1985 } | 1991 } |
| 1986 | 1992 |
| 1987 void MenuController::HandleMouseLocation(SubmenuView* source, | 1993 void MenuController::HandleMouseLocation(SubmenuView* source, |
| 1988 const gfx::Point& mouse_location) { | 1994 const gfx::Point& mouse_location) { |
| 1989 if (showing_submenu_) | 1995 if (showing_submenu_) |
| 1990 return; | 1996 return; |
| 1991 | 1997 |
| 1992 MenuPart part = GetMenuPart(source, mouse_location); | 1998 MenuPart part = GetMenuPart(source, mouse_location); |
| 1993 | 1999 |
| 1994 UpdateScrolling(part); | 2000 UpdateScrolling(part); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 2006 (!pending_state_.item->HasSubmenu() || | 2012 (!pending_state_.item->HasSubmenu() || |
| 2007 !pending_state_.item->GetSubmenu()->IsShowing())) { | 2013 !pending_state_.item->GetSubmenu()->IsShowing())) { |
| 2008 // On exit if the user hasn't selected an item with a submenu, move the | 2014 // On exit if the user hasn't selected an item with a submenu, move the |
| 2009 // selection back to the parent menu item. | 2015 // selection back to the parent menu item. |
| 2010 SetSelection(pending_state_.item->GetParentMenuItem(), | 2016 SetSelection(pending_state_.item->GetParentMenuItem(), |
| 2011 SELECTION_OPEN_SUBMENU); | 2017 SELECTION_OPEN_SUBMENU); |
| 2012 } | 2018 } |
| 2013 } | 2019 } |
| 2014 | 2020 |
| 2015 } // namespace views | 2021 } // namespace views |
| OLD | NEW |