Browse Source

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

Shelley Vohr 5 years ago
parent
commit
b90537a629

+ 4 - 0
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

+ 5 - 0
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<v8::Value> arg) {
   gin::Handle<Menu> 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);
 }

+ 1 - 0
shell/browser/api/atom_api_tray.h

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

+ 2 - 0
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();
 }

+ 2 - 0
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;
 

+ 1 - 0
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;
 

+ 10 - 0
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.

+ 7 - 2
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;
 }

+ 1 - 0
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;
 

+ 12 - 0
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() })