Merge pull request #872 from atom/tray-balloon
Add Tray.displayBalloon API on Windows
This commit is contained in:
commit
29b8cd8df7
11 changed files with 141 additions and 45 deletions
|
@ -58,10 +58,10 @@ void MenuMac::PopupAt(Window* window, int x, int y) {
|
||||||
if (!web_contents)
|
if (!web_contents)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NSView* view = web_contents->GetContentNativeView();
|
|
||||||
NSMenu* menu = [menu_controller menu];
|
|
||||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||||
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
||||||
|
NSMenu* menu = [menu_controller menu];
|
||||||
|
NSView* view = web_contents->GetContentNativeView();
|
||||||
|
|
||||||
// Show the menu.
|
// Show the menu.
|
||||||
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
|
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "atom/browser/api/atom_api_menu.h"
|
#include "atom/browser/api/atom_api_menu.h"
|
||||||
#include "atom/browser/ui/tray_icon.h"
|
#include "atom/browser/ui/tray_icon.h"
|
||||||
#include "atom/common/native_mate_converters/image_converter.h"
|
#include "atom/common/native_mate_converters/image_converter.h"
|
||||||
|
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||||
#include "native_mate/constructor.h"
|
#include "native_mate/constructor.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/dictionary.h"
|
||||||
|
|
||||||
|
@ -40,6 +41,18 @@ void Tray::OnDoubleClicked() {
|
||||||
Emit("double-clicked");
|
Emit("double-clicked");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tray::OnBalloonShow() {
|
||||||
|
Emit("balloon-show");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tray::OnBalloonClicked() {
|
||||||
|
Emit("balloon-clicked");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tray::OnBalloonClosed() {
|
||||||
|
Emit("balloon-closed");
|
||||||
|
}
|
||||||
|
|
||||||
void Tray::Destroy() {
|
void Tray::Destroy() {
|
||||||
tray_icon_.reset();
|
tray_icon_.reset();
|
||||||
}
|
}
|
||||||
|
@ -74,6 +87,23 @@ void Tray::SetHighlightMode(mate::Arguments* args, bool highlight) {
|
||||||
tray_icon_->SetHighlightMode(highlight);
|
tray_icon_->SetHighlightMode(highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tray::DisplayBalloon(mate::Arguments* args,
|
||||||
|
const mate::Dictionary& options) {
|
||||||
|
if (!CheckTrayLife(args))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gfx::ImageSkia icon;
|
||||||
|
options.Get("icon", &icon);
|
||||||
|
base::string16 title, content;
|
||||||
|
if (!options.Get("title", &title) ||
|
||||||
|
!options.Get("content", &content)) {
|
||||||
|
args->ThrowError("'title' and 'content' must be defined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
tray_icon_->DisplayBalloon(icon, title, content);
|
||||||
|
}
|
||||||
|
|
||||||
void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) {
|
void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) {
|
||||||
if (!CheckTrayLife(args))
|
if (!CheckTrayLife(args))
|
||||||
return;
|
return;
|
||||||
|
@ -99,6 +129,7 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
|
||||||
.SetMethod("setToolTip", &Tray::SetToolTip)
|
.SetMethod("setToolTip", &Tray::SetToolTip)
|
||||||
.SetMethod("setTitle", &Tray::SetTitle)
|
.SetMethod("setTitle", &Tray::SetTitle)
|
||||||
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
|
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
|
||||||
|
.SetMethod("displayBalloon", &Tray::DisplayBalloon)
|
||||||
.SetMethod("_setContextMenu", &Tray::SetContextMenu);
|
.SetMethod("_setContextMenu", &Tray::SetContextMenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ class ImageSkia;
|
||||||
|
|
||||||
namespace mate {
|
namespace mate {
|
||||||
class Arguments;
|
class Arguments;
|
||||||
|
class Dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
@ -42,6 +43,9 @@ class Tray : public mate::EventEmitter,
|
||||||
// TrayIconObserver:
|
// TrayIconObserver:
|
||||||
void OnClicked() override;
|
void OnClicked() override;
|
||||||
void OnDoubleClicked() override;
|
void OnDoubleClicked() override;
|
||||||
|
void OnBalloonShow() override;
|
||||||
|
void OnBalloonClicked() override;
|
||||||
|
void OnBalloonClosed() override;
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
void SetImage(mate::Arguments* args, const gfx::ImageSkia& image);
|
void SetImage(mate::Arguments* args, const gfx::ImageSkia& image);
|
||||||
|
@ -49,6 +53,7 @@ class Tray : public mate::EventEmitter,
|
||||||
void SetToolTip(mate::Arguments* args, const std::string& tool_tip);
|
void SetToolTip(mate::Arguments* args, const std::string& tool_tip);
|
||||||
void SetTitle(mate::Arguments* args, const std::string& title);
|
void SetTitle(mate::Arguments* args, const std::string& title);
|
||||||
void SetHighlightMode(mate::Arguments* args, bool highlight);
|
void SetHighlightMode(mate::Arguments* args, bool highlight);
|
||||||
|
void DisplayBalloon(mate::Arguments* args, const mate::Dictionary& options);
|
||||||
void SetContextMenu(mate::Arguments* args, Menu* menu);
|
void SetContextMenu(mate::Arguments* args, Menu* menu);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -18,6 +18,11 @@ void TrayIcon::SetTitle(const std::string& title) {
|
||||||
void TrayIcon::SetHighlightMode(bool highlight) {
|
void TrayIcon::SetHighlightMode(bool highlight) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrayIcon::DisplayBalloon(const gfx::ImageSkia& icon,
|
||||||
|
const base::string16& title,
|
||||||
|
const base::string16& contents) {
|
||||||
|
}
|
||||||
|
|
||||||
void TrayIcon::NotifyClicked() {
|
void TrayIcon::NotifyClicked() {
|
||||||
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnClicked());
|
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnClicked());
|
||||||
}
|
}
|
||||||
|
@ -26,4 +31,16 @@ void TrayIcon::NotifyDoubleClicked() {
|
||||||
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDoubleClicked());
|
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnDoubleClicked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrayIcon::NotifyBalloonShow() {
|
||||||
|
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnBalloonShow());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::NotifyBalloonClicked() {
|
||||||
|
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnBalloonClicked());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayIcon::NotifyBalloonClosed() {
|
||||||
|
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnBalloonClosed());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -39,6 +39,12 @@ class TrayIcon {
|
||||||
// works on OS X.
|
// works on OS X.
|
||||||
virtual void SetHighlightMode(bool highlight);
|
virtual void SetHighlightMode(bool highlight);
|
||||||
|
|
||||||
|
// Displays a notification balloon with the specified contents.
|
||||||
|
// Depending on the platform it might not appear by the icon tray.
|
||||||
|
virtual void DisplayBalloon(const gfx::ImageSkia& icon,
|
||||||
|
const base::string16& title,
|
||||||
|
const base::string16& contents);
|
||||||
|
|
||||||
// Set the context menu for this icon.
|
// Set the context menu for this icon.
|
||||||
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;
|
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;
|
||||||
|
|
||||||
|
@ -46,6 +52,9 @@ class TrayIcon {
|
||||||
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }
|
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }
|
||||||
void NotifyClicked();
|
void NotifyClicked();
|
||||||
void NotifyDoubleClicked();
|
void NotifyDoubleClicked();
|
||||||
|
void NotifyBalloonShow();
|
||||||
|
void NotifyBalloonClicked();
|
||||||
|
void NotifyBalloonClosed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TrayIcon();
|
TrayIcon();
|
||||||
|
|
|
@ -11,6 +11,9 @@ class TrayIconObserver {
|
||||||
public:
|
public:
|
||||||
virtual void OnClicked() {}
|
virtual void OnClicked() {}
|
||||||
virtual void OnDoubleClicked() {}
|
virtual void OnDoubleClicked() {}
|
||||||
|
virtual void OnBalloonShow() {}
|
||||||
|
virtual void OnBalloonClicked() {}
|
||||||
|
virtual void OnBalloonClosed() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~TrayIconObserver() {}
|
virtual ~TrayIconObserver() {}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// Copyright (c) 2014 GitHub, Inc.
|
|
||||||
// Use of this source code is governed by the MIT license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef ATOM_BROWSER_UI_TRAY_ICON_WIN_H_
|
|
||||||
#define ATOM_BROWSER_UI_TRAY_ICON_WIN_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "atom/browser/ui/tray_icon.h"
|
|
||||||
|
|
||||||
namespace atom {
|
|
||||||
|
|
||||||
class TrayIconWin : public TrayIcon {
|
|
||||||
public:
|
|
||||||
TrayIconWin();
|
|
||||||
virtual ~TrayIconWin();
|
|
||||||
|
|
||||||
virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE;
|
|
||||||
virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE;
|
|
||||||
virtual void SetToolTip(const std::string& tool_tip) OVERRIDE;
|
|
||||||
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) OVERRIDE;
|
|
||||||
|
|
||||||
private:
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TrayIconWin);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace atom
|
|
||||||
|
|
||||||
#endif // ATOM_BROWSER_UI_TRAY_ICON_WIN_H_
|
|
|
@ -118,19 +118,36 @@ void NotifyIcon::SetToolTip(const std::string& tool_tip) {
|
||||||
LOG(WARNING) << "Unable to set tooltip for status tray icon";
|
LOG(WARNING) << "Unable to set tooltip for status tray icon";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NotifyIcon::DisplayBalloon(const gfx::ImageSkia& icon,
|
||||||
|
const base::string16& title,
|
||||||
|
const base::string16& contents) {
|
||||||
|
NOTIFYICONDATA icon_data;
|
||||||
|
InitIconData(&icon_data);
|
||||||
|
icon_data.uFlags = NIF_INFO;
|
||||||
|
icon_data.dwInfoFlags = NIIF_INFO;
|
||||||
|
wcscpy_s(icon_data.szInfoTitle, title.c_str());
|
||||||
|
wcscpy_s(icon_data.szInfo, contents.c_str());
|
||||||
|
icon_data.uTimeout = 0;
|
||||||
|
|
||||||
|
base::win::Version win_version = base::win::GetVersion();
|
||||||
|
if (!icon.isNull() && win_version != base::win::VERSION_PRE_XP) {
|
||||||
|
balloon_icon_.Set(IconUtil::CreateHICONFromSkBitmap(*icon.bitmap()));
|
||||||
|
icon_data.hBalloonIcon = balloon_icon_.Get();
|
||||||
|
icon_data.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
|
||||||
|
if (!result)
|
||||||
|
LOG(WARNING) << "Unable to create status tray balloon.";
|
||||||
|
}
|
||||||
|
|
||||||
void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) {
|
void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) {
|
||||||
menu_model_ = menu_model;
|
menu_model_ = menu_model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
|
void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
|
||||||
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
|
||||||
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
|
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
|
||||||
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
||||||
} else {
|
|
||||||
memset(icon_data, 0, NOTIFYICONDATA_V3_SIZE);
|
|
||||||
icon_data->cbSize = NOTIFYICONDATA_V3_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
icon_data->hWnd = window_;
|
icon_data->hWnd = window_;
|
||||||
icon_data->uID = icon_id_;
|
icon_data->uID = icon_id_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,10 +43,13 @@ class NotifyIcon : public TrayIcon {
|
||||||
UINT message_id() const { return message_id_; }
|
UINT message_id() const { return message_id_; }
|
||||||
|
|
||||||
// Overridden from TrayIcon:
|
// Overridden from TrayIcon:
|
||||||
virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE;
|
void SetImage(const gfx::ImageSkia& image) override;
|
||||||
virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE;
|
void SetPressedImage(const gfx::ImageSkia& image) override;
|
||||||
virtual void SetToolTip(const std::string& tool_tip) OVERRIDE;
|
void SetToolTip(const std::string& tool_tip) override;
|
||||||
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) OVERRIDE;
|
void DisplayBalloon(const gfx::ImageSkia& icon,
|
||||||
|
const base::string16& title,
|
||||||
|
const base::string16& contents) override;
|
||||||
|
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitIconData(NOTIFYICONDATA* icon_data);
|
void InitIconData(NOTIFYICONDATA* icon_data);
|
||||||
|
@ -66,6 +69,9 @@ class NotifyIcon : public TrayIcon {
|
||||||
// The currently-displayed icon for the window.
|
// The currently-displayed icon for the window.
|
||||||
base::win::ScopedHICON icon_;
|
base::win::ScopedHICON icon_;
|
||||||
|
|
||||||
|
// The currently-displayed icon for the notification balloon.
|
||||||
|
base::win::ScopedHICON balloon_icon_;
|
||||||
|
|
||||||
// The context menu.
|
// The context menu.
|
||||||
ui::SimpleMenuModel* menu_model_;
|
ui::SimpleMenuModel* menu_model_;
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,18 @@ LRESULT CALLBACK NotifyIconHost::WndProc(HWND hwnd,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
switch (lparam) {
|
switch (lparam) {
|
||||||
|
case TB_CHECKBUTTON:
|
||||||
|
win_icon->NotifyBalloonShow();
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case TB_INDETERMINATE:
|
||||||
|
win_icon->NotifyBalloonClicked();
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case TB_HIDEBUTTON:
|
||||||
|
win_icon->NotifyBalloonClosed();
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
case WM_LBUTTONDOWN:
|
case WM_LBUTTONDOWN:
|
||||||
case WM_RBUTTONDOWN:
|
case WM_RBUTTONDOWN:
|
||||||
case WM_CONTEXTMENU:
|
case WM_CONTEXTMENU:
|
||||||
|
|
|
@ -52,7 +52,26 @@ Emitted when the tray icon is clicked.
|
||||||
|
|
||||||
Emitted when the tray icon is double clicked.
|
Emitted when the tray icon is double clicked.
|
||||||
|
|
||||||
This is only implmented on OS X.
|
__Note:__ This is only implemented on OS X.
|
||||||
|
|
||||||
|
### Event: 'balloon-show'
|
||||||
|
|
||||||
|
Emitted when the tray balloon shows.
|
||||||
|
|
||||||
|
__Note:__ This is only implemented on Windows.
|
||||||
|
|
||||||
|
### Event: 'balloon-clicked'
|
||||||
|
|
||||||
|
Emitted when the tray balloon is clicked.
|
||||||
|
|
||||||
|
__Note:__ This is only implemented on Windows.
|
||||||
|
|
||||||
|
### Event: 'balloon-closed'
|
||||||
|
|
||||||
|
Emitted when the tray balloon is closed because of timeout or user manually
|
||||||
|
closes it.
|
||||||
|
|
||||||
|
__Note:__ This is only implemented on Windows.
|
||||||
|
|
||||||
### Tray.destroy()
|
### Tray.destroy()
|
||||||
|
|
||||||
|
@ -92,6 +111,13 @@ Sets whether the tray icon is highlighted when it is clicked.
|
||||||
|
|
||||||
This is only implmented on OS X.
|
This is only implmented on OS X.
|
||||||
|
|
||||||
|
### Tray.displayBalloon(options)
|
||||||
|
|
||||||
|
* `options` Object
|
||||||
|
* `icon` [Image](image.md)
|
||||||
|
* `title` String
|
||||||
|
* `content` String
|
||||||
|
|
||||||
### Tray.setContextMenu(menu)
|
### Tray.setContextMenu(menu)
|
||||||
|
|
||||||
* `menu` Menu
|
* `menu` Menu
|
||||||
|
|
Loading…
Reference in a new issue