feat: add tray.closeContextMenu() (#21807)

This commit is contained in:
Shelley Vohr 2020-01-22 15:25:17 -08:00 committed by GitHub
parent 87af95be3e
commit b90537a629
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 45 additions and 2 deletions

View file

@ -277,6 +277,10 @@ be shown instead of the tray icon's context menu.
The `position` is only available on Windows, and it is (0, 0) by default. The `position` is only available on Windows, and it is (0, 0) by default.
#### `tray.closeContextMenu()` _macOS_ _Windows_
Closes an open context menu, as set by `tray.setContextMenu()`.
#### `tray.setContextMenu(menu)` #### `tray.setContextMenu(menu)`
* `menu` Menu | null * `menu` Menu | null

View file

@ -239,6 +239,10 @@ void Tray::PopUpContextMenu(gin_helper::Arguments* args) {
tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model()); tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model());
} }
void Tray::CloseContextMenu() {
tray_icon_->CloseContextMenu();
}
void Tray::SetContextMenu(gin_helper::ErrorThrower thrower, void Tray::SetContextMenu(gin_helper::ErrorThrower thrower,
v8::Local<v8::Value> arg) { v8::Local<v8::Value> arg) {
gin::Handle<Menu> menu; gin::Handle<Menu> menu;
@ -276,6 +280,7 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
.SetMethod("removeBalloon", &Tray::RemoveBalloon) .SetMethod("removeBalloon", &Tray::RemoveBalloon)
.SetMethod("focus", &Tray::Focus) .SetMethod("focus", &Tray::Focus)
.SetMethod("popUpContextMenu", &Tray::PopUpContextMenu) .SetMethod("popUpContextMenu", &Tray::PopUpContextMenu)
.SetMethod("closeContextMenu", &Tray::CloseContextMenu)
.SetMethod("setContextMenu", &Tray::SetContextMenu) .SetMethod("setContextMenu", &Tray::SetContextMenu)
.SetMethod("getBounds", &Tray::GetBounds); .SetMethod("getBounds", &Tray::GetBounds);
} }

View file

@ -78,6 +78,7 @@ class Tray : public gin_helper::TrackableObject<Tray>, public TrayIconObserver {
void RemoveBalloon(); void RemoveBalloon();
void Focus(); void Focus();
void PopUpContextMenu(gin_helper::Arguments* args); void PopUpContextMenu(gin_helper::Arguments* args);
void CloseContextMenu();
void SetContextMenu(gin_helper::ErrorThrower thrower, void SetContextMenu(gin_helper::ErrorThrower thrower,
v8::Local<v8::Value> arg); v8::Local<v8::Value> arg);
gfx::Rect GetBounds(); gfx::Rect GetBounds();

View file

@ -23,6 +23,8 @@ void TrayIcon::Focus() {}
void TrayIcon::PopUpContextMenu(const gfx::Point& pos, void TrayIcon::PopUpContextMenu(const gfx::Point& pos,
AtomMenuModel* menu_model) {} AtomMenuModel* menu_model) {}
void TrayIcon::CloseContextMenu() {}
gfx::Rect TrayIcon::GetBounds() { gfx::Rect TrayIcon::GetBounds() {
return gfx::Rect(); return gfx::Rect();
} }

View file

@ -81,6 +81,8 @@ class TrayIcon {
virtual void PopUpContextMenu(const gfx::Point& pos, virtual void PopUpContextMenu(const gfx::Point& pos,
AtomMenuModel* menu_model); AtomMenuModel* menu_model);
virtual void CloseContextMenu();
// Set the context menu for this icon. // Set the context menu for this icon.
virtual void SetContextMenu(AtomMenuModel* menu_model) = 0; virtual void SetContextMenu(AtomMenuModel* menu_model) = 0;

View file

@ -32,6 +32,7 @@ class TrayIconCocoa : public TrayIcon {
void PopUpOnUI(AtomMenuModel* menu_model); void PopUpOnUI(AtomMenuModel* menu_model);
void PopUpContextMenu(const gfx::Point& pos, void PopUpContextMenu(const gfx::Point& pos,
AtomMenuModel* menu_model) override; AtomMenuModel* menu_model) override;
void CloseContextMenu() override;
void SetContextMenu(AtomMenuModel* menu_model) override; void SetContextMenu(AtomMenuModel* menu_model) override;
gfx::Rect GetBounds() override; gfx::Rect GetBounds() override;

View file

@ -194,6 +194,12 @@
} }
} }
- (void)closeContextMenu {
if (menuController_) {
[menuController_ cancel];
}
}
- (void)rightMouseUp:(NSEvent*)event { - (void)rightMouseUp:(NSEvent*)event {
trayIcon_->NotifyRightClicked( trayIcon_->NotifyRightClicked(
gfx::ScreenRectFromNSRect(event.window.frame), gfx::ScreenRectFromNSRect(event.window.frame),
@ -315,6 +321,10 @@ void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos,
base::Unretained(menu_model))); base::Unretained(menu_model)));
} }
void TrayIconCocoa::CloseContextMenu() {
[status_item_view_ closeContextMenu];
}
void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) { void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) {
if (menu_model) { if (menu_model) {
// Create native menu. // Create native menu.

View file

@ -199,8 +199,7 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
return; return;
// Cancel current menu if there is one. // Cancel current menu if there is one.
if (menu_runner_ && menu_runner_->IsRunning()) CloseContextMenu();
menu_runner_->Cancel();
// Show menu at mouse's position by default. // Show menu at mouse's position by default.
gfx::Rect rect(pos, gfx::Size()); gfx::Rect rect(pos, gfx::Size());
@ -231,6 +230,12 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
ui::MENU_SOURCE_MOUSE); ui::MENU_SOURCE_MOUSE);
} }
void NotifyIcon::CloseContextMenu() {
if (menu_runner_ && menu_runner_->IsRunning()) {
menu_runner_->Cancel();
}
}
void NotifyIcon::SetContextMenu(AtomMenuModel* menu_model) { void NotifyIcon::SetContextMenu(AtomMenuModel* menu_model) {
menu_model_ = menu_model; menu_model_ = menu_model;
} }

View file

@ -63,6 +63,7 @@ class NotifyIcon : public TrayIcon {
void Focus() override; void Focus() override;
void PopUpContextMenu(const gfx::Point& pos, void PopUpContextMenu(const gfx::Point& pos,
AtomMenuModel* menu_model) override; AtomMenuModel* menu_model) override;
void CloseContextMenu() override;
void SetContextMenu(AtomMenuModel* menu_model) override; void SetContextMenu(AtomMenuModel* menu_model) override;
gfx::Rect GetBounds() override; gfx::Rect GetBounds() override;

View file

@ -63,6 +63,18 @@ describe('tray module', () => {
}) })
}) })
describe('tray.closeContextMenu()', () => {
ifit(process.platform === 'win32')('does not crash when called more than once', function (done) {
tray.setContextMenu(Menu.buildFromTemplate([{ label: 'Test' }]))
setTimeout(() => {
tray.closeContextMenu()
tray.closeContextMenu()
done()
})
tray.popUpContextMenu()
})
})
describe('tray.getBounds()', () => { describe('tray.getBounds()', () => {
afterEach(() => { tray.destroy() }) afterEach(() => { tray.destroy() })