Add Menu.closePopup API on macOS
This commit is contained in:
parent
947556a23f
commit
6a023dc4fe
8 changed files with 48 additions and 11 deletions
|
@ -176,7 +176,8 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
|
||||
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
|
||||
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
|
||||
.SetMethod("popupAt", &Menu::PopupAt);
|
||||
.SetMethod("popupAt", &Menu::PopupAt)
|
||||
.SetMethod("closePopupAt", &Menu::ClosePopupAt);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
|
|
@ -55,6 +55,7 @@ class Menu : public mate::TrackableObject<Menu>,
|
|||
|
||||
virtual void PopupAt(Window* window, int x, int y, int positioning_item,
|
||||
bool async) = 0;
|
||||
virtual void ClosePopupAt(int32_t window_id) = 0;
|
||||
|
||||
std::unique_ptr<AtomMenuModel> model_;
|
||||
Menu* parent_;
|
||||
|
|
|
@ -7,10 +7,13 @@
|
|||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#import "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
|
||||
using base::scoped_nsobject;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
@ -22,9 +25,12 @@ class MenuMac : public Menu {
|
|||
void PopupAt(
|
||||
Window* window, int x, int y, int positioning_item, bool async) override;
|
||||
void PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int x, int y, int positioning_item, bool async);
|
||||
int32_t window_id, int x, int y, int positioning_item,
|
||||
bool async);
|
||||
void ClosePopupAt(int32_t window_id) override;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
std::map<int32_t, scoped_nsobject<AtomMenuController>> popup_controllers_;
|
||||
|
||||
private:
|
||||
friend class Menu;
|
||||
|
|
|
@ -34,8 +34,8 @@ void MenuMac::PopupAt(
|
|||
return;
|
||||
|
||||
auto popup = base::Bind(&MenuMac::PopupOnUI, weak_factory_.GetWeakPtr(),
|
||||
native_window->GetWeakPtr(), x, y, positioning_item,
|
||||
async);
|
||||
native_window->GetWeakPtr(), window->ID(), x, y,
|
||||
positioning_item, async);
|
||||
if (async)
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, popup);
|
||||
else
|
||||
|
@ -43,7 +43,8 @@ void MenuMac::PopupAt(
|
|||
}
|
||||
|
||||
void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
||||
int x, int y, int positioning_item, bool async) {
|
||||
int32_t window_id, int x, int y, int positioning_item,
|
||||
bool async) {
|
||||
if (!native_window)
|
||||
return;
|
||||
brightray::InspectableWebContents* web_contents =
|
||||
|
@ -51,10 +52,12 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
|||
if (!web_contents)
|
||||
return;
|
||||
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()
|
||||
auto close_callback = base::Bind(&MenuMac::ClosePopupAt,
|
||||
weak_factory_.GetWeakPtr(), window_id);
|
||||
popup_controllers_[window_id] = base::scoped_nsobject<AtomMenuController>(
|
||||
[[AtomMenuController alloc] initWithModel:model()
|
||||
useDefaultAccelerator:NO]);
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
NSMenu* menu = [popup_controllers_[window_id] menu];
|
||||
NSView* view = web_contents->GetView()->GetNativeView();
|
||||
|
||||
// Which menu item to show.
|
||||
|
@ -91,6 +94,7 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
|||
|
||||
|
||||
if (async) {
|
||||
[popup_controllers_[window_id] setCloseCallback:close_callback];
|
||||
// Make sure events can be pumped while the menu is up.
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
|
@ -109,9 +113,14 @@ void MenuMac::PopupOnUI(const base::WeakPtr<NativeWindow>& native_window,
|
|||
// Don't emit unresponsive event when showing menu.
|
||||
atom::UnresponsiveSuppressor suppressor;
|
||||
[menu popUpMenuPositioningItem:item atLocation:position inView:view];
|
||||
close_callback.Run();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuMac::ClosePopupAt(int32_t window_id) {
|
||||
popup_controllers_.erase(window_id);
|
||||
}
|
||||
|
||||
// static
|
||||
void Menu::SetApplicationMenu(Menu* base_menu) {
|
||||
MenuMac* menu = static_cast<MenuMac*>(base_menu);
|
||||
|
|
|
@ -51,6 +51,8 @@ class Window : public mate::TrackableObject<Window>,
|
|||
|
||||
NativeWindow* window() const { return window_.get(); }
|
||||
|
||||
int32_t ID() const;
|
||||
|
||||
protected:
|
||||
Window(v8::Isolate* isolate, v8::Local<v8::Object> wrapper,
|
||||
const mate::Dictionary& options);
|
||||
|
@ -202,7 +204,6 @@ class Window : public mate::TrackableObject<Window>,
|
|||
|
||||
void SetVibrancy(mate::Arguments* args);
|
||||
|
||||
int32_t ID() const;
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
|
||||
// Remove this window from parent window's |child_windows_|.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/mac/scoped_nsobject.h"
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
|
@ -27,6 +28,7 @@ class AtomMenuModel;
|
|||
base::scoped_nsobject<NSMenu> menu_;
|
||||
BOOL isMenuOpen_;
|
||||
BOOL useDefaultAccelerator_;
|
||||
base::Callback<void()> closeCallback;
|
||||
}
|
||||
|
||||
@property(nonatomic, assign) atom::AtomMenuModel* model;
|
||||
|
@ -35,6 +37,8 @@ class AtomMenuModel;
|
|||
// to the contents of the model after calling this will not be noticed.
|
||||
- (id)initWithModel:(atom::AtomMenuModel*)model useDefaultAccelerator:(BOOL)use;
|
||||
|
||||
- (void)setCloseCallback:(const base::Callback<void()>&)callback;
|
||||
|
||||
// Populate current NSMenu with |model|.
|
||||
- (void)populateWithModel:(atom::AtomMenuModel*)model;
|
||||
|
||||
|
|
|
@ -71,6 +71,10 @@ Role kRolesMap[] = {
|
|||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setCloseCallback:(const base::Callback<void()>&)callback {
|
||||
closeCallback = callback;
|
||||
}
|
||||
|
||||
- (void)populateWithModel:(atom::AtomMenuModel*)model {
|
||||
if (!menu_)
|
||||
return;
|
||||
|
@ -265,8 +269,10 @@ Role kRolesMap[] = {
|
|||
|
||||
- (void)menuDidClose:(NSMenu*)menu {
|
||||
if (isMenuOpen_) {
|
||||
model_->MenuWillClose();
|
||||
isMenuOpen_ = NO;
|
||||
model_->MenuWillClose();
|
||||
if (!closeCallback.is_null())
|
||||
closeCallback.Run();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,15 @@ Menu.prototype.popup = function (window, x, y, positioningItem) {
|
|||
this.popupAt(window, x, y, positioningItem, asyncPopup)
|
||||
}
|
||||
|
||||
Menu.prototype.closePopup = function (window) {
|
||||
if (window == null || window.constructor !== BrowserWindow) {
|
||||
window = BrowserWindow.getFocusedWindow()
|
||||
}
|
||||
if (window != null) {
|
||||
this.closePopupAt(window.id)
|
||||
}
|
||||
}
|
||||
|
||||
Menu.prototype.append = function (item) {
|
||||
return this.insert(this.getItemCount(), item)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue