// Copyright (c) 2013 GitHub, Inc. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #import "browser/api/atom_api_menu_mac.h" #include "base/message_loop.h" #include "base/mac/scoped_sending_event.h" #include "browser/native_window.h" #import "chrome/browser/ui/cocoa/menu_controller.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" namespace atom { namespace api { MenuMac::MenuMac(v8::Handle wrapper) : Menu(wrapper) { } MenuMac::~MenuMac() { } void MenuMac::Popup(NativeWindow* native_window) { scoped_nsobject menu_controller( [[MenuController alloc] initWithModel:model_.get() useWithPopUpButtonCell:NO]); NSWindow* window = native_window->GetNativeWindow(); content::WebContents* web_contents = native_window->GetWebContents(); // Fake out a context menu event. NSEvent* currentEvent = [NSApp currentEvent]; NSPoint position = [window mouseLocationOutsideOfEventStream]; NSTimeInterval eventTime = [currentEvent timestamp]; NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown location:position modifierFlags:NSRightMouseDownMask timestamp:eventTime windowNumber:[window windowNumber] context:nil eventNumber:0 clickCount:1 pressure:1.0]; { // Make sure events can be pumped while the menu is up. MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current()); // 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; // Show the menu. [NSMenu popUpContextMenu:[menu_controller menu] withEvent:clickEvent forView:web_contents->GetView()->GetContentNativeView()]; } } // static Menu* Menu::Create(v8::Handle wrapper) { return new MenuMac(wrapper); } } // namespace api } // namespace atom