diff --git a/atom/browser/api/atom_api_menu_mac.h b/atom/browser/api/atom_api_menu_mac.h index d318b7bdc0..4539efb26c 100644 --- a/atom/browser/api/atom_api_menu_mac.h +++ b/atom/browser/api/atom_api_menu_mac.h @@ -20,6 +20,8 @@ class MenuMac : public Menu { MenuMac(v8::Isolate* isolate, v8::Local wrapper); void PopupAt(Window* window, int x, int y, int positioning_item) override; + void PopupOnUI(const base::WeakPtr& native_window, + int x, int y, int positioning_item); base::scoped_nsobject menu_controller_; @@ -28,6 +30,8 @@ class MenuMac : public Menu { static void SendActionToFirstResponder(const std::string& action); + base::WeakPtrFactory weak_factory_; + DISALLOW_COPY_AND_ASSIGN(MenuMac); }; diff --git a/atom/browser/api/atom_api_menu_mac.mm b/atom/browser/api/atom_api_menu_mac.mm index 9e901d1098..ed4dae372e 100644 --- a/atom/browser/api/atom_api_menu_mac.mm +++ b/atom/browser/api/atom_api_menu_mac.mm @@ -6,10 +6,12 @@ #include "atom/browser/native_window.h" #include "atom/browser/unresponsive_suppressor.h" +#include "base/mac/scoped_sending_event.h" #include "base/message_loop/message_loop.h" #include "base/strings/sys_string_conversions.h" #include "brightray/browser/inspectable_web_contents.h" #include "brightray/browser/inspectable_web_contents_view.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" #include "atom/common/node_includes.h" @@ -19,13 +21,24 @@ namespace atom { namespace api { MenuMac::MenuMac(v8::Isolate* isolate, v8::Local wrapper) - : Menu(isolate, wrapper) { + : Menu(isolate, wrapper), + weak_factory_(this) { } void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) { NativeWindow* native_window = window->window(); if (!native_window) return; + + content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, + base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(), + native_window->GetWeakPtr(), x, y, positioning_item)); +} + +void MenuMac::PopupOnUI(const base::WeakPtr& native_window, + int x, int y, int positioning_item) { + if (!native_window) + return; brightray::InspectableWebContents* web_contents = native_window->inspectable_web_contents(); if (!web_contents) @@ -69,11 +82,24 @@ void MenuMac::PopupAt(Window* window, int x, int y, int positioning_item) { if (rightmostMenuPoint > screenRight) position.x = position.x - [menu size].width; - // Don't emit unresponsive event when showing menu. - atom::UnresponsiveSuppressor suppressor; + { + // Make sure events can be pumped while the menu is up. + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); - // Show the menu. - [menu popUpMenuPositioningItem:item atLocation:position inView:view]; + // One of the events that could be pumped is |window.close()|. + // User-initiated event-tracking loops protect against this by + // setting flags in -[CrApplication sendEvent:], but since + // web-content menus are initiated by IPC message the setup has to + // be done manually. + base::mac::ScopedSendingEvent sendingEventScoper; + + // Don't emit unresponsive event when showing menu. + atom::UnresponsiveSuppressor suppressor; + + // Show the menu. + [menu popUpMenuPositioningItem:item atLocation:position inView:view]; + } } // static