diff --git a/docs/api/tray.md b/docs/api/tray.md index 720c9528d80d..2bed1202f62b 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -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. +#### `tray.closeContextMenu()` _macOS_ _Windows_ + +Closes an open context menu, as set by `tray.setContextMenu()`. + #### `tray.setContextMenu(menu)` * `menu` Menu | null diff --git a/shell/browser/api/atom_api_tray.cc b/shell/browser/api/atom_api_tray.cc index af0a061caecc..ae0dfc6769dd 100644 --- a/shell/browser/api/atom_api_tray.cc +++ b/shell/browser/api/atom_api_tray.cc @@ -239,6 +239,10 @@ void Tray::PopUpContextMenu(gin_helper::Arguments* args) { tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model()); } +void Tray::CloseContextMenu() { + tray_icon_->CloseContextMenu(); +} + void Tray::SetContextMenu(gin_helper::ErrorThrower thrower, v8::Local arg) { gin::Handle menu; @@ -276,6 +280,7 @@ void Tray::BuildPrototype(v8::Isolate* isolate, .SetMethod("removeBalloon", &Tray::RemoveBalloon) .SetMethod("focus", &Tray::Focus) .SetMethod("popUpContextMenu", &Tray::PopUpContextMenu) + .SetMethod("closeContextMenu", &Tray::CloseContextMenu) .SetMethod("setContextMenu", &Tray::SetContextMenu) .SetMethod("getBounds", &Tray::GetBounds); } diff --git a/shell/browser/api/atom_api_tray.h b/shell/browser/api/atom_api_tray.h index a78c5f793779..2dd9f528884b 100644 --- a/shell/browser/api/atom_api_tray.h +++ b/shell/browser/api/atom_api_tray.h @@ -78,6 +78,7 @@ class Tray : public gin_helper::TrackableObject, public TrayIconObserver { void RemoveBalloon(); void Focus(); void PopUpContextMenu(gin_helper::Arguments* args); + void CloseContextMenu(); void SetContextMenu(gin_helper::ErrorThrower thrower, v8::Local arg); gfx::Rect GetBounds(); diff --git a/shell/browser/ui/tray_icon.cc b/shell/browser/ui/tray_icon.cc index 4d8828286ad3..aac7b3cc7948 100644 --- a/shell/browser/ui/tray_icon.cc +++ b/shell/browser/ui/tray_icon.cc @@ -23,6 +23,8 @@ void TrayIcon::Focus() {} void TrayIcon::PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model) {} +void TrayIcon::CloseContextMenu() {} + gfx::Rect TrayIcon::GetBounds() { return gfx::Rect(); } diff --git a/shell/browser/ui/tray_icon.h b/shell/browser/ui/tray_icon.h index e8b01501beaf..b13413a2fa3b 100644 --- a/shell/browser/ui/tray_icon.h +++ b/shell/browser/ui/tray_icon.h @@ -81,6 +81,8 @@ class TrayIcon { virtual void PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model); + virtual void CloseContextMenu(); + // Set the context menu for this icon. virtual void SetContextMenu(AtomMenuModel* menu_model) = 0; diff --git a/shell/browser/ui/tray_icon_cocoa.h b/shell/browser/ui/tray_icon_cocoa.h index 7b38fa84c505..93cb97e1e19e 100644 --- a/shell/browser/ui/tray_icon_cocoa.h +++ b/shell/browser/ui/tray_icon_cocoa.h @@ -32,6 +32,7 @@ class TrayIconCocoa : public TrayIcon { void PopUpOnUI(AtomMenuModel* menu_model); void PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model) override; + void CloseContextMenu() override; void SetContextMenu(AtomMenuModel* menu_model) override; gfx::Rect GetBounds() override; diff --git a/shell/browser/ui/tray_icon_cocoa.mm b/shell/browser/ui/tray_icon_cocoa.mm index 7efd6152bc3e..239e8cec2c33 100644 --- a/shell/browser/ui/tray_icon_cocoa.mm +++ b/shell/browser/ui/tray_icon_cocoa.mm @@ -194,6 +194,12 @@ } } +- (void)closeContextMenu { + if (menuController_) { + [menuController_ cancel]; + } +} + - (void)rightMouseUp:(NSEvent*)event { trayIcon_->NotifyRightClicked( gfx::ScreenRectFromNSRect(event.window.frame), @@ -315,6 +321,10 @@ void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos, base::Unretained(menu_model))); } +void TrayIconCocoa::CloseContextMenu() { + [status_item_view_ closeContextMenu]; +} + void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) { if (menu_model) { // Create native menu. diff --git a/shell/browser/ui/win/notify_icon.cc b/shell/browser/ui/win/notify_icon.cc index 2567f8b91fec..9a800794b6f6 100644 --- a/shell/browser/ui/win/notify_icon.cc +++ b/shell/browser/ui/win/notify_icon.cc @@ -199,8 +199,7 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos, return; // Cancel current menu if there is one. - if (menu_runner_ && menu_runner_->IsRunning()) - menu_runner_->Cancel(); + CloseContextMenu(); // Show menu at mouse's position by default. gfx::Rect rect(pos, gfx::Size()); @@ -231,6 +230,12 @@ void NotifyIcon::PopUpContextMenu(const gfx::Point& pos, ui::MENU_SOURCE_MOUSE); } +void NotifyIcon::CloseContextMenu() { + if (menu_runner_ && menu_runner_->IsRunning()) { + menu_runner_->Cancel(); + } +} + void NotifyIcon::SetContextMenu(AtomMenuModel* menu_model) { menu_model_ = menu_model; } diff --git a/shell/browser/ui/win/notify_icon.h b/shell/browser/ui/win/notify_icon.h index 9dc29beda4df..8484bc38ba49 100644 --- a/shell/browser/ui/win/notify_icon.h +++ b/shell/browser/ui/win/notify_icon.h @@ -63,6 +63,7 @@ class NotifyIcon : public TrayIcon { void Focus() override; void PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model) override; + void CloseContextMenu() override; void SetContextMenu(AtomMenuModel* menu_model) override; gfx::Rect GetBounds() override; diff --git a/spec-main/api-tray-spec.ts b/spec-main/api-tray-spec.ts index b47c0665395b..baee28f2c6a0 100644 --- a/spec-main/api-tray-spec.ts +++ b/spec-main/api-tray-spec.ts @@ -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()', () => { afterEach(() => { tray.destroy() })