15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#ifndef CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_ 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#define CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_ 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_ptr.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/strings/string16.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/threading/non_thread_safe.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/win/iunknown_impl.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/win/scoped_comptr.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// The known values for NOTIFYITEM's dwPreference member. 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuenum NOTIFYITEM_PREFERENCE { 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // In Windows UI: "Only show notifications." 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PREFERENCE_SHOW_WHEN_ACTIVE = 0, 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // In Windows UI: "Hide icon and notifications." 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PREFERENCE_SHOW_NEVER = 1, 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // In Windows UI: "Show icon and notifications." 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PREFERENCE_SHOW_ALWAYS = 2 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// NOTIFYITEM describes an entry in Explorer's registry of status icons. 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Explorer keeps entries around for a process even after it exits. 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct NOTIFYITEM { 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PWSTR exe_name; // The file name of the creating executable. 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PWSTR tip; // The last hover-text value associated with this status 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // item. 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HICON icon; // The icon associated with this status item. 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HWND hwnd; // The HWND associated with the status item. 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DWORD preference; // Determines the behavior of the icon with respect to 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // the taskbar. Values taken from NOTIFYITEM_PREFERENCE. 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu UINT id; // The ID specified by the application. (hWnd, uID) is 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // unique. 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GUID guid; // The GUID specified by the application, alternative to 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // uID. 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// INotificationCB is an interface that applications can implement in order to 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// receive notifications about the state of the notification area manager. 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass __declspec(uuid("D782CCBA-AFB0-43F1-94DB-FDA3779EACCB")) INotificationCB 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : public IUnknown { 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public: 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual HRESULT STDMETHODCALLTYPE 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu Notify(ULONG event, NOTIFYITEM* notify_item) = 0; 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A class that is capable of reading and writing the state of the notification 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// area in the Windows taskbar. It is used to promote a tray icon from the 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// overflow area to the taskbar, and refuses to do anything if the user has 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// explicitly marked an icon to be always hidden. 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass StatusTrayStateChangerWin : public INotificationCB, 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public base::win::IUnknownImpl, 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public base::NonThreadSafe { 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public: 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu StatusTrayStateChangerWin(UINT icon_id, HWND window); 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Call this method to move the icon matching |icon_id| and |window| to the 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // taskbar from the overflow area. This will not make any changes if the 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // icon has been set to |PREFERENCE_SHOW_NEVER|, in order to comply with 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // the explicit wishes/configuration of the user. 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu void EnsureTrayIconVisible(); 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // IUnknown. 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual ULONG STDMETHODCALLTYPE AddRef() OVERRIDE; 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual ULONG STDMETHODCALLTYPE Release() OVERRIDE; 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, PVOID*) OVERRIDE; 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // INotificationCB. 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Notify is called in response to RegisterCallback for each current 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // entry in Explorer's list of notification area icons, and ever time 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // one of them changes, until UnregisterCallback is called or |this| 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // is destroyed. 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual HRESULT STDMETHODCALLTYPE Notify(ULONG, NOTIFYITEM*); 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected: 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual ~StatusTrayStateChangerWin(); 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu friend class StatusTrayStateChangerWinTest; 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu enum InterfaceVersion { 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu INTERFACE_VERSION_LEGACY = 0, 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu INTERFACE_VERSION_WIN8, 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu INTERFACE_VERSION_UNKNOWN 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu }; 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Creates an instance of TrayNotify, and ensures that it supports either 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // ITrayNotify or ITrayNotifyWin8. Returns true on success. 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool CreateTrayNotify(); 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Returns the NOTIFYITEM that corresponds to this executable and the 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // HWND/ID pair that were used to create the StatusTrayStateChangerWin. 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Internally it calls the appropriate RegisterCallback{Win8,Legacy}. 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<NOTIFYITEM> RegisterCallback(); 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Calls RegisterCallback with the appropriate interface required by 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // different versions of Windows. This will result in |notify_item_| being 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // updated when a matching item is passed into 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // StatusTrayStateChangerWin::Notify. 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool RegisterCallbackWin8(); 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bool RegisterCallbackLegacy(); 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Sends an update to Explorer with the passed NOTIFYITEM. 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu void SendNotifyItemUpdate(scoped_ptr<NOTIFYITEM> notify_item); 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Storing IUnknown since we will need to use different interfaces 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // for different versions of Windows. 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::win::ScopedComPtr<IUnknown> tray_notify_; 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu InterfaceVersion interface_version_; 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The ID assigned to the notification area icon that we want to manipulate. 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const UINT icon_id_; 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // The HWND associated with the notification area icon that we want to 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // manipulate. This is an unretained pointer, do not dereference. 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const HWND window_; 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Executable name of the current program. Along with |icon_id_| and 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // |window_|, this uniquely identifies a notification area entry to Explorer. 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::string16 file_name_; 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Temporary storage for the matched NOTIFYITEM. This is necessary because 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Notify doesn't return anything. The call flow looks like this: 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // TrayNotify->RegisterCallback() 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // ... other COM stack frames .. 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // StatusTrayStateChangerWin->Notify(NOTIFYITEM); 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // so we can't just return the notifyitem we're looking for. 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<NOTIFYITEM> notify_item_; 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISALLOW_COPY_AND_ASSIGN(StatusTrayStateChangerWin); 1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif // CHROME_BROWSER_UI_VIEWS_STATUS_ICONS_STATUS_TRAY_STATE_CHANGER_WIN_H_ 134