From 0fb3c8cb7cd9137d39c15de9eb9d3bb35b3fc673 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Thu, 8 Aug 2019 23:43:33 +0200 Subject: [PATCH] feat: add new options to tray.displayBalloon() (#19544) --- docs/api/tray.md | 10 ++++- shell/browser/api/atom_api_tray.cc | 60 ++++++++++++++++++++++++----- shell/browser/ui/tray_icon.cc | 6 +-- shell/browser/ui/tray_icon.h | 22 +++++++++-- shell/browser/ui/win/notify_icon.cc | 44 +++++++++++++++++---- shell/browser/ui/win/notify_icon.h | 4 +- 6 files changed, 119 insertions(+), 27 deletions(-) diff --git a/docs/api/tray.md b/docs/api/tray.md index f50dcccbf92e..fd10df41a3e2 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -222,12 +222,20 @@ Returns `Boolean` - Whether double click events will be ignored. #### `tray.displayBalloon(options)` _Windows_ * `options` Object - * `icon` ([NativeImage](native-image.md) | String) (optional) - + * `icon` ([NativeImage](native-image.md) | String) (optional) - Icon to use when `iconType` is `custom`. + * `iconType` String (optional) - Can be `none`, `info`, `warning`, `error` or `custom`. Default is `custom`. * `title` String * `content` String + * `largeIcon` Boolean (optional) - The large version of the icon should be used. Default is `true`. Maps to [`NIIF_LARGE_ICON`][NIIF_LARGE_ICON]. + * `noSound` Boolean (optional) - Do not play the associated sound. Default is `false`. Maps to [`NIIF_NOSOUND`][NIIF_NOSOUND]. + * `respectQuietTime` Boolean (optional) - Do not display the balloon notification if the current user is in "quiet time". Default is `false`. Maps to [`NIIF_RESPECT_QUIET_TIME`][NIIF_RESPECT_QUIET_TIME]. Displays a tray balloon. +[NIIF_NOSOUND]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_nosound-0x00000010 +[NIIF_LARGE_ICON]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_large_icon-0x00000020 +[NIIF_RESPECT_QUIET_TIME]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_respect_quiet_time-0x00000080 + #### `tray.removeBalloon()` _Windows_ Removes a tray balloon. diff --git a/shell/browser/api/atom_api_tray.cc b/shell/browser/api/atom_api_tray.cc index 27b6ae7698ea..c446b4046a69 100644 --- a/shell/browser/api/atom_api_tray.cc +++ b/shell/browser/api/atom_api_tray.cc @@ -18,6 +18,39 @@ #include "shell/common/node_includes.h" #include "ui/gfx/image/image.h" +namespace mate { + +template <> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + electron::TrayIcon::IconType* out) { + using IconType = electron::TrayIcon::IconType; + std::string mode; + if (ConvertFromV8(isolate, val, &mode)) { + if (mode == "none") { + *out = IconType::None; + return true; + } else if (mode == "info") { + *out = IconType::Info; + return true; + } else if (mode == "warning") { + *out = IconType::Warning; + return true; + } else if (mode == "error") { + *out = IconType::Error; + return true; + } else if (mode == "custom") { + *out = IconType::Custom; + return true; + } + } + return false; + } +}; + +} // namespace mate + namespace electron { namespace api { @@ -157,22 +190,31 @@ bool Tray::GetIgnoreDoubleClickEvents() { void Tray::DisplayBalloon(mate::Arguments* args, const mate::Dictionary& options) { - mate::Handle icon; - options.Get("icon", &icon); - base::string16 title, content; - if (!options.Get("title", &title) || !options.Get("content", &content)) { + TrayIcon::BalloonOptions balloon_options; + + if (!options.Get("title", &balloon_options.title) || + !options.Get("content", &balloon_options.content)) { args->ThrowError("'title' and 'content' must be defined"); return; } + mate::Handle icon; + options.Get("icon", &icon); + options.Get("iconType", &balloon_options.icon_type); + options.Get("largeIcon", &balloon_options.large_icon); + options.Get("noSound", &balloon_options.no_sound); + options.Get("respectQuietTime", &balloon_options.respect_quiet_time); + + if (!icon.IsEmpty()) { #if defined(OS_WIN) - tray_icon_->DisplayBalloon( - icon.IsEmpty() ? NULL : icon->GetHICON(GetSystemMetrics(SM_CXICON)), - title, content); + balloon_options.icon = icon->GetHICON( + GetSystemMetrics(balloon_options.large_icon ? SM_CXICON : SM_CXSMICON)); #else - tray_icon_->DisplayBalloon(icon.IsEmpty() ? gfx::Image() : icon->image(), - title, content); + balloon_options.icon = icon->image(); #endif + } + + tray_icon_->DisplayBalloon(balloon_options); } void Tray::RemoveBalloon() { diff --git a/shell/browser/ui/tray_icon.cc b/shell/browser/ui/tray_icon.cc index 21bb4c939220..b0d30e7e1d3a 100644 --- a/shell/browser/ui/tray_icon.cc +++ b/shell/browser/ui/tray_icon.cc @@ -6,15 +6,15 @@ namespace electron { +TrayIcon::BalloonOptions::BalloonOptions() = default; + TrayIcon::TrayIcon() {} TrayIcon::~TrayIcon() {} void TrayIcon::SetPressedImage(ImageType image) {} -void TrayIcon::DisplayBalloon(ImageType icon, - const base::string16& title, - const base::string16& contents) {} +void TrayIcon::DisplayBalloon(const BalloonOptions& options) {} void TrayIcon::RemoveBalloon() {} diff --git a/shell/browser/ui/tray_icon.h b/shell/browser/ui/tray_icon.h index beacde407769..1a7c264f6cf4 100644 --- a/shell/browser/ui/tray_icon.h +++ b/shell/browser/ui/tray_icon.h @@ -49,11 +49,27 @@ class TrayIcon { virtual std::string GetTitle() = 0; #endif + enum class IconType { None, Info, Warning, Error, Custom }; + + struct BalloonOptions { + IconType icon_type = IconType::Custom; +#if defined(OS_WIN) + HICON icon = nullptr; +#else + gfx::Image icon; +#endif + base::string16 title; + base::string16 content; + bool large_icon = true; + bool no_sound = false; + bool respect_quiet_time = false; + + BalloonOptions(); + }; + // Displays a notification balloon with the specified contents. // Depending on the platform it might not appear by the icon tray. - virtual void DisplayBalloon(ImageType icon, - const base::string16& title, - const base::string16& contents); + virtual void DisplayBalloon(const BalloonOptions& options); // Removes the notification balloon. virtual void RemoveBalloon(); diff --git a/shell/browser/ui/win/notify_icon.cc b/shell/browser/ui/win/notify_icon.cc index 76987d5783a4..15e7c73d893e 100644 --- a/shell/browser/ui/win/notify_icon.cc +++ b/shell/browser/ui/win/notify_icon.cc @@ -17,6 +17,28 @@ #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/widget/widget.h" +namespace { + +UINT ConvertIconType(electron::TrayIcon::IconType type) { + using IconType = electron::TrayIcon::IconType; + switch (type) { + case IconType::None: + return NIIF_NONE; + case IconType::Info: + return NIIF_INFO; + case IconType::Warning: + return NIIF_WARNING; + case IconType::Error: + return NIIF_ERROR; + case IconType::Custom: + return NIIF_USER; + default: + NOTREACHED() << "Invalid icon type"; + } +} + +} // namespace + namespace electron { NotifyIcon::NotifyIcon(NotifyIconHost* host, UINT id, HWND window, UINT message) @@ -120,18 +142,24 @@ void NotifyIcon::SetToolTip(const std::string& tool_tip) { LOG(WARNING) << "Unable to set tooltip for status tray icon"; } -void NotifyIcon::DisplayBalloon(HICON icon, - const base::string16& title, - const base::string16& contents) { +void NotifyIcon::DisplayBalloon(const BalloonOptions& options) { NOTIFYICONDATA icon_data; InitIconData(&icon_data); icon_data.uFlags |= NIF_INFO; - icon_data.dwInfoFlags = NIIF_INFO; - wcsncpy_s(icon_data.szInfoTitle, title.c_str(), _TRUNCATE); - wcsncpy_s(icon_data.szInfo, contents.c_str(), _TRUNCATE); + wcsncpy_s(icon_data.szInfoTitle, options.title.c_str(), _TRUNCATE); + wcsncpy_s(icon_data.szInfo, options.content.c_str(), _TRUNCATE); icon_data.uTimeout = 0; - icon_data.hBalloonIcon = icon; - icon_data.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON; + icon_data.hBalloonIcon = options.icon; + icon_data.dwInfoFlags = ConvertIconType(options.icon_type); + + if (options.large_icon) + icon_data.dwInfoFlags |= NIIF_LARGE_ICON; + + if (options.no_sound) + icon_data.dwInfoFlags |= NIIF_NOSOUND; + + if (options.respect_quiet_time) + icon_data.dwInfoFlags |= NIIF_RESPECT_QUIET_TIME; BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data); if (!result) diff --git a/shell/browser/ui/win/notify_icon.h b/shell/browser/ui/win/notify_icon.h index bcc5b8138bf4..dfca3373b73d 100644 --- a/shell/browser/ui/win/notify_icon.h +++ b/shell/browser/ui/win/notify_icon.h @@ -58,9 +58,7 @@ class NotifyIcon : public TrayIcon { void SetImage(HICON image) override; void SetPressedImage(HICON image) override; void SetToolTip(const std::string& tool_tip) override; - void DisplayBalloon(HICON icon, - const base::string16& title, - const base::string16& contents) override; + void DisplayBalloon(const BalloonOptions& options) override; void RemoveBalloon() override; void PopUpContextMenu(const gfx::Point& pos, AtomMenuModel* menu_model) override;