/* * Adapted from: * https://eternallybored.org/misc/wget/src/taskbar-progress.patch */ #if !defined(__cplusplus) #define CINTERFACE #define COBJMACROS #endif #include "config.h" #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif #include #include #include #include #include "tbprogress.h" #if !defined(_SHLOBJIDL_H) && !defined(__ITaskbarList3_INTERFACE_DEFINED__) #error This file is not for you. Set ENABLE_TASKBAR=0. #endif const GUID CLSID_TaskbarList = { 0x56FDF344, 0xFD6D, 0x11d0, { 0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90 } }; const GUID IID_ITaskbarList1 = { 0x56FDF342, 0xFD6D, 0x11d0, { 0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90 } }; const GUID IID_ITaskbarList3 = { 0xea1afb91, 0x9e28, 0x4b86, { 0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf } }; #if !defined(__ITaskbarList3_INTERFACE_DEFINED__) typedef enum { TBPF_NOPROGRESS = 0, /* Normal state / no progress bar */ TBPF_INDETERMINATE = 1, /* Marquee style progress bar */ TBPF_NORMAL = 2, /* Standard progress bar */ TBPF_ERROR = 4, /* Red taskbar button to indicate an error occurred */ TBPF_PAUSED = 8 /* Yellow taskbar button to indicate user attention */ } TBPFLAG; typedef void* LPTHUMBBUTTON; /* dummy typedef! */ typedef enum { TBATF_DUMMY } TBATFLAG; #undef INTERFACE #define INTERFACE ITaskbarList3 DECLARE_INTERFACE_(ITaskbarList3,IUnknown) { STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; /* ITaskbarList(1) */ STDMETHOD(HrInit)(THIS) PURE; STDMETHOD(AddTab)(THIS, HWND hwnd) PURE; STDMETHOD(DeleteTab)(THIS, HWND hwnd) PURE; STDMETHOD(ActivateTab)(THIS, HWND hwnd) PURE; STDMETHOD(SetActiveAlt)(THIS, HWND hwnd) PURE; /* ITaskbarList2 */ STDMETHOD(MarkFullscreenWindow)(THIS, HWND hwnd, BOOL fFullscreen) PURE; /* ITaskbarList3 */ STDMETHOD(SetProgressValue)(THIS, HWND hwnd, ULONGLONG ullCompleted, ULONGLONG ullTotal) PURE; STDMETHOD(SetProgressState)(THIS, HWND hwnd, TBPFLAG tbpFlags) PURE; STDMETHOD(RegisterTab)(THIS, HWND hwndTab, HWND hwndMDI) PURE; STDMETHOD(UnregisterTab)(THIS, HWND hwndTab) PURE; STDMETHOD(SetTabOrder)(THIS, HWND hwndTab,HWND hwndInsertBefore) PURE; STDMETHOD(SetTabActive)(THIS, HWND hwndTab,HWND hwndMDI, TBATFLAG tbatFlags) PURE; STDMETHOD(ThumbBarAddButtons)(THIS, HWND hwnd,UINT cButtons, LPTHUMBBUTTON pButton) PURE; STDMETHOD(ThumbBarUpdateButtons)(THIS, HWND hwnd,UINT cButtons, LPTHUMBBUTTON pButton) PURE; STDMETHOD(ThumbBarSetImageList)(THIS, HWND hwnd, HIMAGELIST himl) PURE; STDMETHOD(SetOverlayIcon)(THIS, HWND hwnd, HICON hIcon, LPCWSTR pszDescription) PURE; STDMETHOD(SetThumbnailTooltip)(THIS, HWND hwnd, LPCWSTR pszTip); STDMETHOD(SetThumbnailClip)(THIS, HWND hwnd, RECT *prcClip); STDMETHOD(QueryContextMenu)(THIS_ HMENU,UINT,UINT,UINT,UINT) PURE; STDMETHOD(InvokeCommand)(THIS_ LPCMINVOKECOMMANDINFO) PURE; STDMETHOD(GetCommandString)(THIS_ UINT,UINT,PUINT,LPSTR,UINT) PURE; STDMETHOD(HandleMenuMsg)(THIS_ UINT,WPARAM,LPARAM) PURE; }; #undef INTERFACE #endif /* __ITaskbarList3_INTERFACE_DEFINED__ */ static ITaskbarList3 *g_pTL = NULL; static HWND g_hwndConsole = NULL; static int TB_status = 0; /* Use these macros to gets to the methods. */ #ifdef __cplusplus #define COCREATEINSTANCE(cls,iunk,ctx,iid,pv) CoCreateInstance (cls,iunk,gtx,iid,pv) #define HRINIT(iface) iface->HrInit() #define RELEASE(iface) iface->Release() #define SETPROGRESSVALUE(iface,hwnd,permille,max) iface->SetProgressValue (hwnd, permille, max) #define SETPROGRESSSTATE(iface,hwnd,state) iface->SetProgressState (hwnd, state) #else #define COCREATEINSTANCE(cls,iunk,ctx,iid,pv) CoCreateInstance ((REFCLSID)&(cls),iunk,ctx,(REFCLSID)&(iid),pv) #define HRINIT(iface) ITaskbarList3_HrInit (iface) #define RELEASE(iface) ITaskbarList3_Release (iface) #define SETPROGRESSVALUE(iface,hwnd,permille,max) ITaskbarList3_SetProgressValue (iface,hwnd,permille,max) #define SETPROGRESSSTATE(iface,hwnd,state) ITaskbarList3_SetProgressState (iface,hwnd,state) #endif void SetTBProgress (int permille) { /* Already stopped; quit */ if (g_pTL == NULL && permille < 0) return; /* Prior attempt failed; quit */ if (TB_status != 0) return; /* Clamp to max 100% */ if (permille > 1000) permille = 1000; /* 1st attempt; init */ if (g_pTL == NULL) { HRESULT hr; g_hwndConsole = GetConsoleWindow(); if (!g_hwndConsole) { TB_status = -1; return; } hr = CoInitializeEx (NULL, COINIT_APARTMENTTHREADED); if (!SUCCEEDED(hr)) { CoUninitialize(); TB_status = -1; return; } COCREATEINSTANCE (CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&g_pTL); if (g_pTL == NULL) { CoUninitialize(); TB_status = -1; return; } hr = HRINIT (g_pTL); if (!SUCCEEDED(hr)) { TB_status = -1; RELEASE (g_pTL); g_pTL = NULL; CoUninitialize(); return; } TB_status = 0; } if (permille >= 0) { SETPROGRESSVALUE (g_pTL, g_hwndConsole, permille, 1000); } else { SETPROGRESSSTATE (g_pTL, g_hwndConsole, TBPF_NOPROGRESS); RELEASE (g_pTL); g_pTL = NULL; CoUninitialize(); } }