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

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

Issue 10154013: Fixes crash in closing menus. There are two issues here: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixor Created 8 years, 8 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 | Annotate | Revision Log
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/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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698