From 937b811c8d6843ba87c7092cda78eb6e195cfd78 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 16 May 2013 10:54:37 +0800 Subject: [PATCH] Add Menu.setApplicationMenu API to set main menu of NSApp. --- browser/api/atom_api_menu.cc | 13 ++++++++++--- browser/api/atom_api_menu.h | 2 ++ browser/api/atom_api_menu_mac.h | 6 ++++++ browser/api/atom_api_menu_mac.mm | 23 ++++++++++++++++++++++- browser/api/lib/menu.coffee | 7 ++++++- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/browser/api/atom_api_menu.cc b/browser/api/atom_api_menu.cc index 3d28a637a4c7..2ff18cf0deb5 100644 --- a/browser/api/atom_api_menu.cc +++ b/browser/api/atom_api_menu.cc @@ -60,6 +60,7 @@ Menu::~Menu() { } bool Menu::IsCommandIdChecked(int command_id) const { + v8::HandleScope scope; return CallDelegate(v8::False(), handle(), "isCommandIdChecked", @@ -67,6 +68,7 @@ bool Menu::IsCommandIdChecked(int command_id) const { } bool Menu::IsCommandIdEnabled(int command_id) const { + v8::HandleScope scope; return CallDelegate(v8::True(), handle(), "isCommandIdEnabled", @@ -74,6 +76,7 @@ bool Menu::IsCommandIdEnabled(int command_id) const { } bool Menu::IsCommandIdVisible(int command_id) const { + v8::HandleScope scope; return CallDelegate(v8::True(), handle(), "isCommandIdVisible", @@ -82,6 +85,7 @@ bool Menu::IsCommandIdVisible(int command_id) const { bool Menu::GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) { + v8::HandleScope scope; v8::Handle shortcut = CallDelegate(v8::Undefined(), handle(), "getAcceleratorForCommandId", @@ -95,6 +99,7 @@ bool Menu::GetAcceleratorForCommandId(int command_id, } bool Menu::IsItemForCommandIdDynamic(int command_id) const { + v8::HandleScope scope; return CallDelegate(v8::False(), handle(), "isItemForCommandIdDynamic", @@ -102,6 +107,7 @@ bool Menu::IsItemForCommandIdDynamic(int command_id) const { } string16 Menu::GetLabelForCommandId(int command_id) const { + v8::HandleScope scope; return V8ValueToUTF16(CallDelegate(v8::False(), handle(), "getLabelForCommandId", @@ -109,6 +115,7 @@ string16 Menu::GetLabelForCommandId(int command_id) const { } string16 Menu::GetSublabelForCommandId(int command_id) const { + v8::HandleScope scope; return V8ValueToUTF16(CallDelegate(v8::False(), handle(), "getSubLabelForCommandId", @@ -116,6 +123,7 @@ string16 Menu::GetSublabelForCommandId(int command_id) const { } void Menu::ExecuteCommand(int command_id, int event_flags) { + v8::HandleScope scope; v8::Handle args[] = { v8::String::New("execute"), v8::Integer::New(command_id) @@ -215,9 +223,6 @@ v8::Handle Menu::InsertSeparator(const v8::Arguments &args) { v8::Handle Menu::InsertSubMenu(const v8::Arguments &args) { UNWRAP_MEMNU_AND_CHECK; - // FIXME should rely on js code to keep a reference of submenu and check - // the constructor type of menu object. - if (!args[0]->IsNumber() || !args[1]->IsNumber() || !args[2]->IsString() || @@ -370,6 +375,8 @@ void Menu::Initialize(v8::Handle target) { NODE_SET_PROTOTYPE_METHOD(t, "popup", Popup); target->Set(v8::String::NewSymbol("Menu"), t->GetFunction()); + + NODE_SET_METHOD(target, "setApplicationMenu", SetApplicationMenu); } } // namespace api diff --git a/browser/api/atom_api_menu.h b/browser/api/atom_api_menu.h index 1967f4f78a62..ae64c648e750 100644 --- a/browser/api/atom_api_menu.h +++ b/browser/api/atom_api_menu.h @@ -68,6 +68,8 @@ class Menu : public EventEmitter, static v8::Handle Popup(const v8::Arguments &args); + static v8::Handle SetApplicationMenu(const v8::Arguments &args); + DISALLOW_COPY_AND_ASSIGN(Menu); }; diff --git a/browser/api/atom_api_menu_mac.h b/browser/api/atom_api_menu_mac.h index d4ac19406ebc..9d0e0580a283 100644 --- a/browser/api/atom_api_menu_mac.h +++ b/browser/api/atom_api_menu_mac.h @@ -7,6 +7,8 @@ #include "browser/api/atom_api_menu.h" +#import "chrome/browser/ui/cocoa/menu_controller.h" + namespace atom { namespace api { @@ -19,7 +21,11 @@ class MenuMac : public Menu { protected: virtual void Popup(NativeWindow* window) OVERRIDE; + scoped_nsobject menu_controller_; + private: + friend class Menu; + DISALLOW_COPY_AND_ASSIGN(MenuMac); }; diff --git a/browser/api/atom_api_menu_mac.mm b/browser/api/atom_api_menu_mac.mm index f93b8cb92fba..e31bf5487b75 100644 --- a/browser/api/atom_api_menu_mac.mm +++ b/browser/api/atom_api_menu_mac.mm @@ -7,7 +7,6 @@ #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" @@ -62,6 +61,28 @@ void MenuMac::Popup(NativeWindow* native_window) { } } +// static +v8::Handle Menu::SetApplicationMenu(const v8::Arguments &args) { + v8::HandleScope scope; + + if (!args[0]->IsObject()) + return node::ThrowTypeError("Bad argument"); + + MenuMac* menu = ObjectWrap::Unwrap(args[0]->ToObject()); + if (!menu) + return node::ThrowError("Menu is destroyed"); + + scoped_nsobject menu_controller( + [[MenuController alloc] initWithModel:menu->model_.get() + useWithPopUpButtonCell:NO]); + [NSApp setMainMenu:[menu_controller menu]]; + + // Ensure the menu_controller_ is destroyed after main menu is set. + menu_controller.swap(menu->menu_controller_); + + return v8::Undefined(); +} + // static Menu* Menu::Create(v8::Handle wrapper) { return new MenuMac(wrapper); diff --git a/browser/api/lib/menu.coffee b/browser/api/lib/menu.coffee index f24cc1699204..d0318945c36d 100644 --- a/browser/api/lib/menu.coffee +++ b/browser/api/lib/menu.coffee @@ -1,7 +1,8 @@ EventEmitter = require('events').EventEmitter BrowserWindow = require 'browser_window' -Menu = process.atomBinding('menu').Menu +bindings = process.atomBinding 'menu' +Menu = bindings.Menu Menu::__proto__ = EventEmitter.prototype popup = Menu::popup @@ -24,4 +25,8 @@ Menu::appendRadioItem = (args...) -> @insertRadioItem -1, args... Menu::appendSeparator = (args...) -> @insertSeparator -1, args... Menu::appendSubMenu = (args...) -> @insertSubMenu -1, args... +Menu.setApplicationMenu = (menu) -> + throw new TypeError('Invalid menu') unless menu?.constructor is Menu + bindings.setApplicationMenu menu + module.exports = Menu