From 2fba05b5e70e5d71f89c350dd42d096bb0f71016 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 18:43:11 +0800 Subject: [PATCH 1/3] Add `menu` parameter for Tray.popUpContextMenu --- atom/browser/api/atom_api_tray.cc | 4 +++- atom/browser/ui/tray_icon.cc | 3 ++- atom/browser/ui/tray_icon.h | 4 +++- atom/browser/ui/tray_icon_cocoa.h | 3 ++- atom/browser/ui/tray_icon_cocoa.mm | 3 ++- atom/browser/ui/win/notify_icon.cc | 5 +++-- atom/browser/ui/win/notify_icon.h | 3 ++- docs/api/tray.md | 8 ++++++-- 8 files changed, 23 insertions(+), 10 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 5e32657f008a..1e1c7c304d82 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -137,9 +137,11 @@ void Tray::DisplayBalloon(mate::Arguments* args, } void Tray::PopUpContextMenu(mate::Arguments* args) { + Menu* menu = nullptr; + args->GetNext(&menu); gfx::Point pos; args->GetNext(&pos); - tray_icon_->PopUpContextMenu(pos); + tray_icon_->PopUpContextMenu(pos, menu ? menu->model() : nullptr); } void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) { diff --git a/atom/browser/ui/tray_icon.cc b/atom/browser/ui/tray_icon.cc index 1696aab276b1..60923c2ad0a6 100644 --- a/atom/browser/ui/tray_icon.cc +++ b/atom/browser/ui/tray_icon.cc @@ -26,7 +26,8 @@ void TrayIcon::DisplayBalloon(const gfx::Image& icon, const base::string16& contents) { } -void TrayIcon::PopUpContextMenu(const gfx::Point& pos) { +void TrayIcon::PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) { } void TrayIcon::NotifyClicked(const gfx::Rect& bounds, int modifiers) { diff --git a/atom/browser/ui/tray_icon.h b/atom/browser/ui/tray_icon.h index bc29acd8a255..c80ff08d6a52 100644 --- a/atom/browser/ui/tray_icon.h +++ b/atom/browser/ui/tray_icon.h @@ -47,7 +47,9 @@ class TrayIcon { const base::string16& title, const base::string16& contents); - virtual void PopUpContextMenu(const gfx::Point& pos); + // Popups the menu. + virtual void PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model); // Set the context menu for this icon. virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0; diff --git a/atom/browser/ui/tray_icon_cocoa.h b/atom/browser/ui/tray_icon_cocoa.h index 7781c93a1c03..59e2241aa480 100644 --- a/atom/browser/ui/tray_icon_cocoa.h +++ b/atom/browser/ui/tray_icon_cocoa.h @@ -29,7 +29,8 @@ class TrayIconCocoa : public TrayIcon, void SetToolTip(const std::string& tool_tip) override; void SetTitle(const std::string& title) override; void SetHighlightMode(bool highlight) override; - void PopUpContextMenu(const gfx::Point& pos) override; + void PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) override; void SetContextMenu(ui::SimpleMenuModel* menu_model) override; protected: diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index e25f8ab5c201..5005234ab131 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -338,7 +338,8 @@ void TrayIconCocoa::SetHighlightMode(bool highlight) { [status_item_view_ setHighlight:highlight]; } -void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos) { +void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) { [status_item_view_ popUpContextMenu]; } diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index b2ca4bceedd1..133ab068da7b 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -66,7 +66,7 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, return; } else if (!double_button_click) { // single right click if (menu_model_) - PopUpContextMenu(cursor_pos); + PopUpContextMenu(cursor_pos, menu_model_); else NotifyRightClicked(gfx::Rect(rect), modifiers); } @@ -142,7 +142,8 @@ void NotifyIcon::DisplayBalloon(const gfx::Image& icon, LOG(WARNING) << "Unable to create status tray balloon."; } -void NotifyIcon::PopUpContextMenu(const gfx::Point& pos) { +void NotifyIcon::PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) { // Returns if context menu isn't set. if (!menu_model_) return; diff --git a/atom/browser/ui/win/notify_icon.h b/atom/browser/ui/win/notify_icon.h index d368dec71327..8ee600033e94 100644 --- a/atom/browser/ui/win/notify_icon.h +++ b/atom/browser/ui/win/notify_icon.h @@ -52,7 +52,8 @@ class NotifyIcon : public TrayIcon { void DisplayBalloon(const gfx::Image& icon, const base::string16& title, const base::string16& contents) override; - void PopUpContextMenu(const gfx::Point& pos) override; + void PopUpContextMenu(const gfx::Point& pos, + ui::SimpleMenuModel* menu_model) override; void SetContextMenu(ui::SimpleMenuModel* menu_model) override; private: diff --git a/docs/api/tray.md b/docs/api/tray.md index f230c324ec08..08a43638be14 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -187,12 +187,16 @@ when the tray icon is clicked. Defaults to true. Displays a tray balloon. -### `Tray.popUpContextMenu([position])` _OS X_ _Windows_ +### `Tray.popUpContextMenu([menu, position])` _OS X_ _Windows_ -* `position` Object (optional)- The pop up position. +* `menu` Menu (optional) +* `position` Object (optional) - The pop up position. * `x` Integer * `y` Integer +Popups the context menu of tray icon. When `menu` is passed, the `menu` will +showed instead of the tray's context menu. + The `position` is only available on Windows, and it is (0, 0) by default. ### `Tray.setContextMenu(menu)` From 3cdd0f35c7d501572164a13051c2bb7ea6ac808f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 19:05:22 +0800 Subject: [PATCH 2/3] mac: Implement menu parameter --- atom/browser/api/atom_api_tray.cc | 4 ++-- atom/browser/ui/tray_icon_cocoa.mm | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_tray.cc b/atom/browser/api/atom_api_tray.cc index 1e1c7c304d82..3b1a3a6321bb 100644 --- a/atom/browser/api/atom_api_tray.cc +++ b/atom/browser/api/atom_api_tray.cc @@ -137,11 +137,11 @@ void Tray::DisplayBalloon(mate::Arguments* args, } void Tray::PopUpContextMenu(mate::Arguments* args) { - Menu* menu = nullptr; + mate::Handle menu; args->GetNext(&menu); gfx::Point pos; args->GetNext(&pos); - tray_icon_->PopUpContextMenu(pos, menu ? menu->model() : nullptr); + tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model()); } void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) { diff --git a/atom/browser/ui/tray_icon_cocoa.mm b/atom/browser/ui/tray_icon_cocoa.mm index 5005234ab131..997ac6fd3134 100644 --- a/atom/browser/ui/tray_icon_cocoa.mm +++ b/atom/browser/ui/tray_icon_cocoa.mm @@ -23,6 +23,7 @@ const CGFloat kVerticalTitleMargin = 2; atom::TrayIconCocoa* trayIcon_; // weak AtomMenuController* menuController_; // weak BOOL isHighlightEnable_; + BOOL forceHighlight_; BOOL inMouseEventSequence_; base::scoped_nsobject image_; base::scoped_nsobject alternateImage_; @@ -39,6 +40,8 @@ const CGFloat kVerticalTitleMargin = 2; image_.reset([image copy]); trayIcon_ = icon; isHighlightEnable_ = YES; + forceHighlight_ = NO; + inMouseEventSequence_ = NO; if ((self = [super initWithFrame: CGRectZero])) { // Setup the image view. @@ -238,7 +241,19 @@ const CGFloat kVerticalTitleMargin = 2; [self setNeedsDisplay:YES]; } -- (void)popUpContextMenu { +- (void)popUpContextMenu:(ui::SimpleMenuModel*)menu_model { + // Show a custom menu. + if (menu_model) { + base::scoped_nsobject menuController( + [[AtomMenuController alloc] initWithModel:menu_model]); + forceHighlight_ = YES; // Should highlight when showing menu. + [self setNeedsDisplay:YES]; + [statusItem_ popUpStatusItemMenu:[menuController menu]]; + forceHighlight_ = NO; + [self setNeedsDisplay:YES]; + return; + } + if (menuController_ && ![menuController_ isMenuOpen]) { // Redraw the dray icon to show highlight if it is enabled. [self setNeedsDisplay:YES]; @@ -288,6 +303,8 @@ const CGFloat kVerticalTitleMargin = 2; } - (BOOL)shouldHighlight { + if (isHighlightEnable_ && forceHighlight_) + return true; BOOL isMenuOpen = menuController_ && [menuController_ isMenuOpen]; return isHighlightEnable_ && (inMouseEventSequence_ || isMenuOpen); } @@ -340,7 +357,7 @@ void TrayIconCocoa::SetHighlightMode(bool highlight) { void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos, ui::SimpleMenuModel* menu_model) { - [status_item_view_ popUpContextMenu]; + [status_item_view_ popUpContextMenu:menu_model]; } void TrayIconCocoa::SetContextMenu(ui::SimpleMenuModel* menu_model) { From 615ce45849db3d0c2db785d3dce8e2450d9e197c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 2 Dec 2015 19:58:10 +0800 Subject: [PATCH 3/3] win: Implement menu parameter --- atom/browser/ui/win/notify_icon.cc | 21 +++++++++++---------- atom/browser/ui/win/notify_icon.h | 3 +-- atom/browser/ui/win/notify_icon_host.cc | 4 ---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index 133ab068da7b..1ac29f1360cb 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -13,6 +13,7 @@ #include "ui/gfx/image/image.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" +#include "ui/gfx/screen.h" #include "ui/views/controls/menu/menu_runner.h" namespace atom { @@ -45,8 +46,7 @@ NotifyIcon::~NotifyIcon() { Shell_NotifyIcon(NIM_DELETE, &icon_data); } -void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, - int modifiers, +void NotifyIcon::HandleClickEvent(int modifiers, bool left_mouse_click, bool double_button_click) { NOTIFYICONIDENTIFIER icon_id; @@ -66,7 +66,7 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, return; } else if (!double_button_click) { // single right click if (menu_model_) - PopUpContextMenu(cursor_pos, menu_model_); + PopUpContextMenu(gfx::Point(), menu_model_); else NotifyRightClicked(gfx::Rect(rect), modifiers); } @@ -145,22 +145,23 @@ void NotifyIcon::DisplayBalloon(const gfx::Image& icon, void NotifyIcon::PopUpContextMenu(const gfx::Point& pos, ui::SimpleMenuModel* menu_model) { // Returns if context menu isn't set. - if (!menu_model_) + if (!menu_model) return; // Set our window as the foreground window, so the context menu closes when // we click away from it. if (!SetForegroundWindow(window_)) return; + // Show menu at mouse's position by default. + gfx::Rect rect(pos, gfx::Size()); + if (pos.IsOrigin()) + rect.set_origin(gfx::Screen::GetNativeScreen()->GetCursorScreenPoint()); + views::MenuRunner menu_runner( - menu_model_, + menu_model, views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS); ignore_result(menu_runner.RunMenuAt( - NULL, - NULL, - gfx::Rect(pos, gfx::Size()), - views::MENU_ANCHOR_TOPLEFT, - ui::MENU_SOURCE_MOUSE)); + NULL, NULL, rect, views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE)); } void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) { diff --git a/atom/browser/ui/win/notify_icon.h b/atom/browser/ui/win/notify_icon.h index 8ee600033e94..23608c7c7ab6 100644 --- a/atom/browser/ui/win/notify_icon.h +++ b/atom/browser/ui/win/notify_icon.h @@ -33,8 +33,7 @@ class NotifyIcon : public TrayIcon { // Handles a click event from the user - if |left_button_click| is true and // there is a registered observer, passes the click event to the observer, // otherwise displays the context menu if there is one. - void HandleClickEvent(const gfx::Point& cursor_pos, - int modifiers, + void HandleClickEvent(int modifiers, bool left_button_click, bool double_button_click); diff --git a/atom/browser/ui/win/notify_icon_host.cc b/atom/browser/ui/win/notify_icon_host.cc index 2c84837e714d..a0d4287ff614 100644 --- a/atom/browser/ui/win/notify_icon_host.cc +++ b/atom/browser/ui/win/notify_icon_host.cc @@ -15,7 +15,6 @@ #include "base/win/win_util.h" #include "base/win/wrapped_window_proc.h" #include "ui/events/event_constants.h" -#include "ui/gfx/screen.h" #include "ui/gfx/win/hwnd_util.h" namespace atom { @@ -172,10 +171,7 @@ LRESULT CALLBACK NotifyIconHost::WndProc(HWND hwnd, case WM_CONTEXTMENU: // Walk our icons, find which one was clicked on, and invoke its // HandleClickEvent() method. - gfx::Point cursor_pos( - gfx::Screen::GetNativeScreen()->GetCursorScreenPoint()); win_icon->HandleClickEvent( - cursor_pos, GetKeyboardModifers(), (lparam == WM_LBUTTONDOWN || lparam == WM_LBUTTONDBLCLK), (lparam == WM_LBUTTONDBLCLK || lparam == WM_RBUTTONDBLCLK));