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)
|
||||
return;
|
||||
|
||||
NSView* view = web_contents->GetContentNativeView();
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller(
|
||||
[[AtomMenuController alloc] initWithModel:model_.get()]);
|
||||
NSMenu* menu = [menu_controller menu];
|
||||
NSView* view = web_contents->GetContentNativeView();
|
||||
|
||||
// Show the menu.
|
||||
[menu popUpMenuPositioningItem:[menu itemAtIndex:0]
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/ui/tray_icon.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/dictionary.h"
|
||||
|
||||
|
@ -40,6 +41,18 @@ void Tray::OnDoubleClicked() {
|
|||
Emit("double-clicked");
|
||||
}
|
||||
|
||||
void Tray::OnBalloonShow() {
|
||||
Emit("balloon-show");
|
||||
}
|
||||
|
||||
void Tray::OnBalloonClicked() {
|
||||
Emit("balloon-clicked");
|
||||
}
|
||||
|
||||
void Tray::OnBalloonClosed() {
|
||||
Emit("balloon-closed");
|
||||
}
|
||||
|
||||
void Tray::Destroy() {
|
||||
tray_icon_.reset();
|
||||
}
|
||||
|
@ -74,6 +87,23 @@ void Tray::SetHighlightMode(mate::Arguments* args, bool 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) {
|
||||
if (!CheckTrayLife(args))
|
||||
return;
|
||||
|
@ -99,6 +129,7 @@ void Tray::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("setToolTip", &Tray::SetToolTip)
|
||||
.SetMethod("setTitle", &Tray::SetTitle)
|
||||
.SetMethod("setHighlightMode", &Tray::SetHighlightMode)
|
||||
.SetMethod("displayBalloon", &Tray::DisplayBalloon)
|
||||
.SetMethod("_setContextMenu", &Tray::SetContextMenu);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ class ImageSkia;
|
|||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
@ -42,6 +43,9 @@ class Tray : public mate::EventEmitter,
|
|||
// TrayIconObserver:
|
||||
void OnClicked() override;
|
||||
void OnDoubleClicked() override;
|
||||
void OnBalloonShow() override;
|
||||
void OnBalloonClicked() override;
|
||||
void OnBalloonClosed() override;
|
||||
|
||||
void Destroy();
|
||||
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 SetTitle(mate::Arguments* args, const std::string& title);
|
||||
void SetHighlightMode(mate::Arguments* args, bool highlight);
|
||||
void DisplayBalloon(mate::Arguments* args, const mate::Dictionary& options);
|
||||
void SetContextMenu(mate::Arguments* args, Menu* menu);
|
||||
|
||||
private:
|
||||
|
|
|
@ -18,6 +18,11 @@ void TrayIcon::SetTitle(const std::string& title) {
|
|||
void TrayIcon::SetHighlightMode(bool highlight) {
|
||||
}
|
||||
|
||||
void TrayIcon::DisplayBalloon(const gfx::ImageSkia& icon,
|
||||
const base::string16& title,
|
||||
const base::string16& contents) {
|
||||
}
|
||||
|
||||
void TrayIcon::NotifyClicked() {
|
||||
FOR_EACH_OBSERVER(TrayIconObserver, observers_, OnClicked());
|
||||
}
|
||||
|
@ -26,4 +31,16 @@ void TrayIcon::NotifyDoubleClicked() {
|
|||
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
|
||||
|
|
|
@ -39,6 +39,12 @@ class TrayIcon {
|
|||
// works on OS X.
|
||||
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.
|
||||
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;
|
||||
|
||||
|
@ -46,6 +52,9 @@ class TrayIcon {
|
|||
void RemoveObserver(TrayIconObserver* obs) { observers_.RemoveObserver(obs); }
|
||||
void NotifyClicked();
|
||||
void NotifyDoubleClicked();
|
||||
void NotifyBalloonShow();
|
||||
void NotifyBalloonClicked();
|
||||
void NotifyBalloonClosed();
|
||||
|
||||
protected:
|
||||
TrayIcon();
|
||||
|
|
|
@ -11,6 +11,9 @@ class TrayIconObserver {
|
|||
public:
|
||||
virtual void OnClicked() {}
|
||||
virtual void OnDoubleClicked() {}
|
||||
virtual void OnBalloonShow() {}
|
||||
virtual void OnBalloonClicked() {}
|
||||
virtual void OnBalloonClosed() {}
|
||||
|
||||
protected:
|
||||
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";
|
||||
}
|
||||
|
||||
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) {
|
||||
menu_model_ = menu_model;
|
||||
}
|
||||
|
||||
void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
|
||||
if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
|
||||
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
|
||||
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
||||
} else {
|
||||
memset(icon_data, 0, NOTIFYICONDATA_V3_SIZE);
|
||||
icon_data->cbSize = NOTIFYICONDATA_V3_SIZE;
|
||||
}
|
||||
|
||||
memset(icon_data, 0, sizeof(NOTIFYICONDATA));
|
||||
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
||||
icon_data->hWnd = window_;
|
||||
icon_data->uID = icon_id_;
|
||||
}
|
||||
|
|
|
@ -43,10 +43,13 @@ class NotifyIcon : public TrayIcon {
|
|||
UINT message_id() const { return message_id_; }
|
||||
|
||||
// Overridden from TrayIcon:
|
||||
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;
|
||||
void SetImage(const gfx::ImageSkia& image) override;
|
||||
void SetPressedImage(const gfx::ImageSkia& image) override;
|
||||
void SetToolTip(const std::string& tool_tip) override;
|
||||
void DisplayBalloon(const gfx::ImageSkia& icon,
|
||||
const base::string16& title,
|
||||
const base::string16& contents) override;
|
||||
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
|
||||
|
||||
private:
|
||||
void InitIconData(NOTIFYICONDATA* icon_data);
|
||||
|
@ -66,6 +69,9 @@ class NotifyIcon : public TrayIcon {
|
|||
// The currently-displayed icon for the window.
|
||||
base::win::ScopedHICON icon_;
|
||||
|
||||
// The currently-displayed icon for the notification balloon.
|
||||
base::win::ScopedHICON balloon_icon_;
|
||||
|
||||
// The context menu.
|
||||
ui::SimpleMenuModel* menu_model_;
|
||||
|
||||
|
|
|
@ -132,6 +132,18 @@ LRESULT CALLBACK NotifyIconHost::WndProc(HWND hwnd,
|
|||
return TRUE;
|
||||
|
||||
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_RBUTTONDOWN:
|
||||
case WM_CONTEXTMENU:
|
||||
|
|
|
@ -52,7 +52,26 @@ Emitted when the tray icon is 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()
|
||||
|
||||
|
@ -92,6 +111,13 @@ Sets whether the tray icon is highlighted when it is clicked.
|
|||
|
||||
This is only implmented on OS X.
|
||||
|
||||
### Tray.displayBalloon(options)
|
||||
|
||||
* `options` Object
|
||||
* `icon` [Image](image.md)
|
||||
* `title` String
|
||||
* `content` String
|
||||
|
||||
### Tray.setContextMenu(menu)
|
||||
|
||||
* `menu` Menu
|
||||
|
|
Loading…
Reference in a new issue