diff --git a/atom/browser/ui/views/menu_delegate.cc b/atom/browser/ui/views/menu_delegate.cc index 00aa956e6c81..b1c9c0b6c7f3 100644 --- a/atom/browser/ui/views/menu_delegate.cc +++ b/atom/browser/ui/views/menu_delegate.cc @@ -97,6 +97,9 @@ void MenuDelegate::WillHideMenu(views::MenuItemView* menu) { void MenuDelegate::OnMenuClosed(views::MenuItemView* menu, views::MenuRunner::RunResult result) { + // Only switch to new menu when current menu is closed. + if (button_to_open_) + button_to_open_->Activate(nullptr); delete this; } @@ -106,18 +109,22 @@ views::MenuItemView* MenuDelegate::GetSiblingMenu( views::MenuAnchorPosition* anchor, bool* has_mnemonics, views::MenuButton**) { + // TODO(zcbenz): We should follow Chromium's logics on implementing the + // sibling menu switches, this code is almost a hack. views::MenuButton* button; AtomMenuModel* model; if (menu_bar_->GetMenuButtonFromScreenPoint(screen_point, &model, &button) && button->tag() != id_) { - DCHECK(menu_runner_->IsRunning()); - menu_runner_->Cancel(); - // After canceling the menu, we need to wait until next tick - // so we are out of nested message loop. - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(base::IgnoreResult(&views::MenuButton::Activate), - base::Unretained(button), nullptr)); + bool switch_in_progress = !!button_to_open_; + // Always update target to open. + button_to_open_ = button; + // Switching menu asyncnously to avoid crash. + if (!switch_in_progress) { + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&views::MenuRunner::Cancel, + base::Unretained(menu_runner_.get()))); + } } return nullptr; diff --git a/atom/browser/ui/views/menu_delegate.h b/atom/browser/ui/views/menu_delegate.h index 909c78a416e5..21874dfa5c5f 100644 --- a/atom/browser/ui/views/menu_delegate.h +++ b/atom/browser/ui/views/menu_delegate.h @@ -55,6 +55,9 @@ class MenuDelegate : public views::MenuDelegate { std::unique_ptr adapter_; std::unique_ptr menu_runner_; + // The menu button to switch to. + views::MenuButton* button_to_open_ = nullptr; + DISALLOW_COPY_AND_ASSIGN(MenuDelegate); };