Skip to content

Commit

Permalink
feat: add new options to tray.displayBalloon()
Browse files Browse the repository at this point in the history
  • Loading branch information
Milan Burda authored and miniak committed Jul 31, 2019
1 parent d660519 commit bdf5765
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 27 deletions.
10 changes: 9 additions & 1 deletion docs/api/tray.md
Expand Up @@ -255,12 +255,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.popUpContextMenu([menu, position])` _macOS_ _Windows_

* `menu` Menu (optional)
Expand Down
57 changes: 48 additions & 9 deletions shell/browser/api/atom_api_tray.cc
Expand Up @@ -44,6 +44,36 @@ struct Converter<electron::TrayIcon::HighlightMode> {
return false;
}
};

template <>
struct Converter<electron::TrayIcon::IconType> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> 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 {
Expand Down Expand Up @@ -189,22 +219,31 @@ bool Tray::GetIgnoreDoubleClickEvents() {

void Tray::DisplayBalloon(mate::Arguments* args,
const mate::Dictionary& options) {
mate::Handle<NativeImage> 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<NativeImage> 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::PopUpContextMenu(mate::Arguments* args) {
Expand Down
6 changes: 3 additions & 3 deletions shell/browser/ui/tray_icon.cc
Expand Up @@ -6,6 +6,8 @@

namespace electron {

TrayIcon::BalloonOptions::BalloonOptions() = default;

TrayIcon::TrayIcon() {}

TrayIcon::~TrayIcon() {}
Expand All @@ -14,9 +16,7 @@ void TrayIcon::SetPressedImage(ImageType image) {}

void TrayIcon::SetHighlightMode(TrayIcon::HighlightMode mode) {}

void TrayIcon::DisplayBalloon(ImageType icon,
const base::string16& title,
const base::string16& contents) {}
void TrayIcon::DisplayBalloon(const BalloonOptions& options) {}

void TrayIcon::PopUpContextMenu(const gfx::Point& pos,
AtomMenuModel* menu_model) {}
Expand Down
22 changes: 19 additions & 3 deletions shell/browser/ui/tray_icon.h
Expand Up @@ -57,11 +57,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);

// Popups the menu.
virtual void PopUpContextMenu(const gfx::Point& pos,
Expand Down
44 changes: 36 additions & 8 deletions shell/browser/ui/win/notify_icon.cc
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 1 addition & 3 deletions shell/browser/ui/win/notify_icon.h
Expand Up @@ -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 PopUpContextMenu(const gfx::Point& pos,
AtomMenuModel* menu_model) override;
void SetContextMenu(AtomMenuModel* menu_model) override;
Expand Down

0 comments on commit bdf5765

Please sign in to comment.