Home | History | Annotate | Download | only in status_icons
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/views/status_icons/status_icon_win.h"
      6 
      7 #include "base/sys_string_conversions.h"
      8 #include "third_party/skia/include/core/SkBitmap.h"
      9 #include "ui/gfx/icon_util.h"
     10 #include "ui/gfx/point.h"
     11 #include "views/controls/menu/menu_2.h"
     12 
     13 StatusIconWin::StatusIconWin(UINT id, HWND window, UINT message)
     14     : icon_id_(id),
     15       window_(window),
     16       message_id_(message) {
     17   NOTIFYICONDATA icon_data;
     18   InitIconData(&icon_data);
     19   icon_data.uFlags = NIF_MESSAGE;
     20   icon_data.uCallbackMessage = message_id_;
     21   BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
     22   // This can happen if the explorer process isn't running when we try to
     23   // create the icon for some reason (for example, at startup).
     24   if (!result)
     25     LOG(WARNING) << "Unable to create status tray icon.";
     26 }
     27 
     28 StatusIconWin::~StatusIconWin() {
     29   // Remove our icon.
     30   NOTIFYICONDATA icon_data;
     31   InitIconData(&icon_data);
     32   Shell_NotifyIcon(NIM_DELETE, &icon_data);
     33 }
     34 
     35 void StatusIconWin::SetImage(const SkBitmap& image) {
     36   // Create the icon.
     37   NOTIFYICONDATA icon_data;
     38   InitIconData(&icon_data);
     39   icon_data.uFlags = NIF_ICON;
     40   icon_.Set(IconUtil::CreateHICONFromSkBitmap(image));
     41   icon_data.hIcon = icon_.Get();
     42   BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
     43   if (!result)
     44     LOG(WARNING) << "Error setting status tray icon image";
     45 }
     46 
     47 void StatusIconWin::ResetIcon() {
     48   NOTIFYICONDATA icon_data;
     49   InitIconData(&icon_data);
     50   // Delete any previously existing icon.
     51   Shell_NotifyIcon(NIM_DELETE, &icon_data);
     52   InitIconData(&icon_data);
     53   icon_data.uFlags = NIF_MESSAGE;
     54   icon_data.uCallbackMessage = message_id_;
     55   icon_data.hIcon = icon_.Get();
     56   // If we have an image, then set the NIF_ICON flag, which tells
     57   // Shell_NotifyIcon() to set the image for the status icon it creates.
     58   if (icon_data.hIcon)
     59     icon_data.uFlags |= NIF_ICON;
     60   // Re-add our icon.
     61   BOOL result = Shell_NotifyIcon(NIM_ADD, &icon_data);
     62   if (!result)
     63     LOG(WARNING) << "Unable to re-create status tray icon.";
     64 }
     65 
     66 void StatusIconWin::SetPressedImage(const SkBitmap& image) {
     67   // Ignore pressed images, since the standard on Windows is to not highlight
     68   // pressed status icons.
     69 }
     70 
     71 void StatusIconWin::SetToolTip(const string16& tool_tip) {
     72   // Create the icon.
     73   NOTIFYICONDATA icon_data;
     74   InitIconData(&icon_data);
     75   icon_data.uFlags = NIF_TIP;
     76   wcscpy_s(icon_data.szTip, tool_tip.c_str());
     77   BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
     78   if (!result)
     79     LOG(WARNING) << "Unable to set tooltip for status tray icon";
     80 }
     81 
     82 void StatusIconWin::DisplayBalloon(const string16& title,
     83                                    const string16& contents) {
     84   NOTIFYICONDATA icon_data;
     85   InitIconData(&icon_data);
     86   icon_data.uFlags = NIF_INFO;
     87   icon_data.dwInfoFlags = NIIF_INFO;
     88   wcscpy_s(icon_data.szInfoTitle, title.c_str());
     89   wcscpy_s(icon_data.szInfo, contents.c_str());
     90   icon_data.uTimeout = 0;
     91   BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
     92   if (!result)
     93     LOG(WARNING) << "Unable to create status tray balloon.";
     94 }
     95 
     96 void StatusIconWin::UpdatePlatformContextMenu(ui::MenuModel* menu) {
     97   // If no items are passed, blow away our context menu.
     98   if (!menu) {
     99     context_menu_.reset();
    100     return;
    101   }
    102 
    103   // Create context menu with the new contents.
    104   context_menu_.reset(new views::Menu2(menu));
    105 }
    106 
    107 void StatusIconWin::HandleClickEvent(int x, int y, bool left_mouse_click) {
    108   // Pass to the observer if appropriate.
    109   if (left_mouse_click && HasObservers()) {
    110     DispatchClickEvent();
    111     return;
    112   }
    113 
    114   // Event not sent to the observer, so display the context menu if one exists.
    115   if (context_menu_.get()) {
    116     // Set our window as the foreground window, so the context menu closes when
    117     // we click away from it.
    118     SetForegroundWindow(window_);
    119     context_menu_->RunContextMenuAt(gfx::Point(x, y));
    120   }
    121 }
    122 
    123 void StatusIconWin::InitIconData(NOTIFYICONDATA* icon_data) {
    124   icon_data->cbSize = sizeof(NOTIFYICONDATA);
    125   icon_data->hWnd = window_;
    126   icon_data->uID = icon_id_;
    127 }
    128