Merge pull request #872 from atom/tray-balloon

Add Tray.displayBalloon API on Windows
This commit is contained in:
Cheng Zhao 2014-11-28 20:01:08 +08:00
commit 29b8cd8df7
11 changed files with 141 additions and 45 deletions

View file

@ -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]

View file

@ -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);
}

View file

@ -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:

View file

@ -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

View file

@ -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();

View file

@ -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() {}

View file

@ -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_

View file

@ -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_;
}

View file

@ -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_;

View file

@ -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:

View file

@ -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