From e31e98d927b2dcbe562daf03d56a1b04823871ac Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Fri, 28 Jun 2019 14:00:18 -0700 Subject: [PATCH] fix: make tray not block main process (#19035) --- atom/browser/ui/tray_icon_cocoa.h | 3 +++ atom/browser/ui/tray_icon_cocoa.mm | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/atom/browser/ui/tray_icon_cocoa.h b/atom/browser/ui/tray_icon_cocoa.h index 34ace850a79e7..535e19b0c6669 100644 --- a/atom/browser/ui/tray_icon_cocoa.h +++ b/atom/browser/ui/tray_icon_cocoa.h @@ -29,6 +29,7 @@ class TrayIconCocoa : public TrayIcon, public AtomMenuModel::Observer { void SetHighlightMode(TrayIcon::HighlightMode mode) override; void SetIgnoreDoubleClickEvents(bool ignore) override; bool GetIgnoreDoubleClickEvents() override; + void PopUpOnUI(AtomMenuModel* menu_model); void PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model) override; void SetContextMenu(AtomMenuModel* menu_model) override; @@ -48,6 +49,8 @@ class TrayIconCocoa : public TrayIcon, public AtomMenuModel::Observer { // Used for unregistering observer. AtomMenuModel* menu_model_ = nullptr; // weak ref. + base::WeakPtrFactory weak_factory_; + DISALLOW_COPY_AND_ASSIGN(TrayIconCocoa); }; diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 1513e28ea231b..bbcae719bf365 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -8,7 +8,11 @@ #include "atom/browser/ui/cocoa/NSString+ANSI.h" #include "atom/browser/ui/cocoa/atom_menu_controller.h" #include "base/mac/sdk_forward_declarations.h" +#include "base/message_loop/message_loop.h" #include "base/strings/sys_string_conversions.h" +#include "base/task/post_task.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "ui/display/screen.h" #include "ui/events/cocoa/cocoa_event_utils.h" #include "ui/gfx/image/image.h" @@ -326,6 +330,9 @@ - (void)mouseUp:(NSEvent*)event { } - (void)popUpContextMenu:(atom::AtomMenuModel*)menu_model { + // Make sure events can be pumped while the menu is up. + base::MessageLoopCurrent::ScopedNestableTaskAllower allow; + // Show a custom menu. if (menu_model) { base::scoped_nsobject menuController( @@ -333,6 +340,7 @@ - (void)popUpContextMenu:(atom::AtomMenuModel*)menu_model { useDefaultAccelerator:NO]); forceHighlight_ = YES; // Should highlight when showing menu. [self setNeedsDisplay:YES]; + [statusItem_ popUpStatusItemMenu:[menuController menu]]; forceHighlight_ = NO; [self setNeedsDisplay:YES]; @@ -340,8 +348,12 @@ - (void)popUpContextMenu:(atom::AtomMenuModel*)menu_model { } if (menuController_ && ![menuController_ isMenuOpen]) { + // Ensure the UI can update while the menu is fading out. + base::ScopedPumpMessagesInPrivateModes pump_private; + // Redraw the tray icon to show highlight if it is enabled. [self setNeedsDisplay:YES]; + [statusItem_ popUpStatusItemMenu:[menuController_ menu]]; // The popUpStatusItemMenu returns only after the showing menu is closed. // When it returns, we need to redraw the tray icon to not show highlight. @@ -439,7 +451,7 @@ - (BOOL)shouldHighlight { namespace atom { -TrayIconCocoa::TrayIconCocoa() { +TrayIconCocoa::TrayIconCocoa() : weak_factory_(this) { status_item_view_.reset([[StatusItemView alloc] initWithIcon:this]); } @@ -477,9 +489,16 @@ - (BOOL)shouldHighlight { return [status_item_view_ getIgnoreDoubleClickEvents]; } +void TrayIconCocoa::PopUpOnUI(AtomMenuModel* menu_model) { + [status_item_view_ popUpContextMenu:menu_model]; +} + void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model) { - [status_item_view_ popUpContextMenu:menu_model]; + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&TrayIconCocoa::PopUpOnUI, weak_factory_.GetWeakPtr(), + base::Unretained(menu_model))); } void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) {