1 // Copyright 2014 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 #ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_ 6 #define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_ 7 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/string16.h" 10 #include "base/threading/non_thread_safe.h" 11 #include "base/win/iunknown_impl.h" 12 #include "base/win/scoped_comptr.h" 13 14 // The known values for NOTIFYITEM's dwPreference member. 15 enum NOTIFYITEM_PREFERENCE { 16 // In Windows UI: "Only show notifications." 17 PREFERENCE_SHOW_WHEN_ACTIVE = 0, 18 // In Windows UI: "Hide icon and notifications." 19 PREFERENCE_SHOW_NEVER = 1, 20 // In Windows UI: "Show icon and notifications." 21 PREFERENCE_SHOW_ALWAYS = 2 22 }; 23 24 // NOTIFYITEM describes an entry in Explorer's registry of status icons. 25 // Explorer keeps entries around for a process even after it exits. 26 struct NOTIFYITEM { 27 PWSTR exe_name; // The file name of the creating executable. 28 PWSTR tip; // The last hover-text value associated with this status 29 // item. 30 HICON icon; // The icon associated with this status item. 31 HWND hwnd; // The HWND associated with the status item. 32 DWORD preference; // Determines the behavior of the icon with respect to 33 // the taskbar. Values taken from NOTIFYITEM_PREFERENCE. 34 UINT id; // The ID specified by the application. (hWnd, uID) is 35 // unique. 36 GUID guid; // The GUID specified by the application, alternative to 37 // uID. 38 }; 39 40 // INotificationCB is an interface that applications can implement in order to 41 // receive notifications about the state of the notification area manager. 42 class __declspec(uuid("D782CCBA-AFB0-43F1-94DB-FDA3779EACCB")) INotificationCB 43 : public IUnknown { 44 public: 45 virtual HRESULT STDMETHODCALLTYPE 46 Notify(ULONG event, NOTIFYITEM* notify_item) = 0; 47 }; 48 49 // A class that is capable of reading and writing the state of the notification 50 // area in the Windows taskbar. It is used to promote a tray icon from the 51 // overflow area to the taskbar, and refuses to do anything if the user has 52 // explicitly marked an icon to be always hidden. 53 class StatusTrayStateChangerWin : public INotificationCB, 54 public base::win::IUnknownImpl, 55 public base::NonThreadSafe { 56 public: 57 StatusTrayStateChangerWin(UINT icon_id, HWND window); 58 59 // Call this method to move the icon matching |icon_id| and |window| to the 60 // taskbar from the overflow area. This will not make any changes if the 61 // icon has been set to |PREFERENCE_SHOW_NEVER|, in order to comply with 62 // the explicit wishes/configuration of the user. 63 void EnsureTrayIconVisible(); 64 65 // IUnknown. 66 virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE; 67 virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE; 68 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, PVOID*) OVERRIDE; 69 70 // INotificationCB. 71 // Notify is called in response to RegisterCallback for each current 72 // entry in Explorer's list of notification area icons, and ever time 73 // one of them changes, until UnregisterCallback is called or |this| 74 // is destroyed. 75 virtual HRESULT STDMETHODCALLTYPE Notify(ULONG, NOTIFYITEM*); 76 77 protected: 78 virtual ~StatusTrayStateChangerWin(); 79 80 private: 81 friend class StatusTrayStateChangerWinTest; 82 83 enum InterfaceVersion { 84 INTERFACE_VERSION_LEGACY = 0, 85 INTERFACE_VERSION_WIN8, 86 INTERFACE_VERSION_UNKNOWN 87 }; 88 89 // Creates an instance of TrayNotify, and ensures that it supports either 90 // ITrayNotify or ITrayNotifyWin8. Returns true on success. 91 bool CreateTrayNotify(); 92 93 // Returns the NOTIFYITEM that corresponds to this executable and the 94 // HWND/ID pair that were used to create the StatusTrayStateChangerWin. 95 // Internally it calls the appropriate RegisterCallback{Win8,Legacy}. 96 scoped_ptr<NOTIFYITEM> RegisterCallback(); 97 98 // Calls RegisterCallback with the appropriate interface required by 99 // different versions of Windows. This will result in |notify_item_| being 100 // updated when a matching item is passed into 101 // StatusTrayStateChangerWin::Notify. 102 bool RegisterCallbackWin8(); 103 bool RegisterCallbackLegacy(); 104 105 // Sends an update to Explorer with the passed NOTIFYITEM. 106 void SendNotifyItemUpdate(scoped_ptr<NOTIFYITEM> notify_item); 107 108 // Storing IUnknown since we will need to use different interfaces 109 // for different versions of Windows. 110 base::win::ScopedComPtr<IUnknown> tray_notify_; 111 InterfaceVersion interface_version_; 112 113 // The ID assigned to the notification area icon that we want to manipulate. 114 const UINT icon_id_; 115 // The HWND associated with the notification area icon that we want to 116 // manipulate. This is an unretained pointer, do not dereference. 117 const HWND window_; 118 // Executable name of the current program. Along with |icon_id_| and 119 // |window_|, this uniquely identifies a notification area entry to Explorer. 120 base::string16 file_name_; 121 122 // Temporary storage for the matched NOTIFYITEM. This is necessary because 123 // Notify doesn't return anything. The call flow looks like this: 124 // TrayNotify->RegisterCallback() 125 // ... other COM stack frames .. 126 // StatusTrayStateChangerWin->Notify(NOTIFYITEM); 127 // so we can't just return the notifyitem we're looking for. 128 scoped_ptr<NOTIFYITEM> notify_item_; 129 130 DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerWin); 131 }; 132 133 #endif // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_ 134