Skip to content

Commit c527b35

Browse files
committed
qt: Port Windows taskbar progress to native Windows API
1 parent eeb9cc1 commit c527b35

File tree

5 files changed

+185
-13
lines changed

5 files changed

+185
-13
lines changed

src/qt/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ add_library(bitcoinqt STATIC EXCLUDE_FROM_ALL
257257
utilitydialog.h
258258
$<$<PLATFORM_ID:Windows>:winshutdownmonitor.cpp>
259259
$<$<PLATFORM_ID:Windows>:winshutdownmonitor.h>
260+
$<$<AND:$<PLATFORM_ID:Windows>,$<BOOL:${BITCOIN_QT_WIN_TASKBAR}>>:wintaskbarprogress.cpp>
261+
$<$<AND:$<PLATFORM_ID:Windows>,$<BOOL:${BITCOIN_QT_WIN_TASKBAR}>>:wintaskbarprogress.h>
260262
bitcoin.qrc
261263
${CMAKE_CURRENT_BINARY_DIR}/bitcoin_locale.qrc
262264
${CMAKE_CURRENT_BINARY_DIR}/bitcoin_rendered.qrc
@@ -368,6 +370,8 @@ if(WITH_TASKBAR_PROGRESS)
368370
PRIVATE
369371
"Qt${WITH_QT_VERSION}::WinExtras"
370372
$<$<PLATFORM_ID:Windows>:dwmapi>
373+
$<$<PLATFORM_ID:Windows>:ole32>
374+
$<$<PLATFORM_ID:Windows>:shell32>
371375
)
372376
endif()
373377

src/qt/bitcoingui.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@
3535
#include <qt/macdockiconhandler.h>
3636
#endif
3737
#ifdef BITCOIN_QT_WIN_TASKBAR
38-
#include <QWinTaskbarButton>
39-
#include <QWinTaskbarProgress>
38+
#include <qt/wintaskbarprogress.h>
4039
#endif
4140

4241
#include <chain.h>
@@ -232,7 +231,8 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
232231
m_app_nap_inhibitor = new CAppNapInhibitor;
233232
#endif
234233
#ifdef BITCOIN_QT_WIN_TASKBAR
235-
m_taskbar_button = new QWinTaskbarButton(this);
234+
m_taskbar_progress = new WinTaskbarProgress(this);
235+
m_taskbar_progress->setWindow(windowHandle());
236236
#endif
237237

238238
GUIUtil::handleCloseWindowShortcut(this);
@@ -1235,11 +1235,6 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
12351235

12361236
tooltip = tr("Processed %n block(s) of transaction history.", "", count);
12371237

1238-
#ifdef BITCOIN_QT_WIN_TASKBAR
1239-
m_taskbar_button->setWindow(windowHandle());
1240-
QWinTaskbarProgress* taskbar_progress = m_taskbar_button->progress();
1241-
#endif
1242-
12431238
// Set icon state: spinning if catching up, tick otherwise
12441239
if (secs < MAX_BLOCK_TIME_GAP) {
12451240
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
@@ -1256,7 +1251,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
12561251
progressBarLabel->setVisible(false);
12571252
progressBar->setVisible(false);
12581253
#ifdef BITCOIN_QT_WIN_TASKBAR
1259-
taskbar_progress->setVisible(false);
1254+
m_taskbar_progress->setVisible(false);
12601255
#endif
12611256
}
12621257
else
@@ -1273,8 +1268,8 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
12731268
progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
12741269
progressBar->setVisible(true);
12751270
#ifdef BITCOIN_QT_WIN_TASKBAR
1276-
taskbar_progress->setValue(qRound(nVerificationProgress * 100.0));
1277-
taskbar_progress->setVisible(true);
1271+
m_taskbar_progress->setValue(qRound(nVerificationProgress * 100.0));
1272+
m_taskbar_progress->setVisible(true);
12781273
#endif
12791274

12801275
tooltip = tr("Catching up…") + QString("<br>") + tooltip;

src/qt/bitcoingui.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ class QComboBox;
5555
class QDateTime;
5656
class QProgressBar;
5757
class QProgressDialog;
58-
class QWinTaskbarButton;
5958
QT_END_NAMESPACE
6059

60+
class WinTaskbarProgress;
61+
6162
namespace GUIUtil {
6263
class ClickableLabel;
6364
class ClickableProgressBar;
@@ -180,7 +181,7 @@ class BitcoinGUI : public QMainWindow
180181
RPCConsole* rpcConsole = nullptr;
181182
HelpMessageDialog* helpMessageDialog = nullptr;
182183
#ifdef BITCOIN_QT_WIN_TASKBAR
183-
QWinTaskbarButton* m_taskbar_button = nullptr;
184+
WinTaskbarProgress* m_taskbar_progress = nullptr;
184185
#endif
185186
ModalOverlay* modalOverlay = nullptr;
186187
MempoolStats* mempoolStats = nullptr;

src/qt/wintaskbarprogress.cpp

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Copyright (c) 2025 The Bitcoin Knots developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include <qt/wintaskbarprogress.h>
6+
7+
#include <QWindow>
8+
9+
#include <windows.h>
10+
#include <shobjidl.h>
11+
12+
#pragma comment(lib, "ole32.lib")
13+
#pragma comment(lib, "shell32.lib")
14+
15+
WinTaskbarProgress::WinTaskbarProgress(QObject *parent)
16+
: QObject(parent)
17+
{
18+
}
19+
20+
WinTaskbarProgress::~WinTaskbarProgress()
21+
{
22+
releaseTaskbarButton();
23+
}
24+
25+
void WinTaskbarProgress::setWindow(QWindow* window)
26+
{
27+
if (m_window == window) {
28+
return;
29+
}
30+
31+
m_window = window;
32+
initTaskbarButton();
33+
updateProgress();
34+
}
35+
36+
QWindow* WinTaskbarProgress::window() const
37+
{
38+
return m_window;
39+
}
40+
41+
void WinTaskbarProgress::setValue(int value)
42+
{
43+
if (m_value == value) {
44+
return;
45+
}
46+
47+
m_value = value;
48+
updateProgress();
49+
}
50+
51+
void WinTaskbarProgress::setVisible(bool visible)
52+
{
53+
if (m_visible == visible) {
54+
return;
55+
}
56+
57+
m_visible = visible;
58+
updateProgress();
59+
}
60+
61+
void WinTaskbarProgress::updateProgress()
62+
{
63+
if (!m_taskbar_button || !m_window) {
64+
return;
65+
}
66+
67+
ITaskbarList3* pTaskbarList = (ITaskbarList3*)m_taskbar_button;
68+
69+
if (m_visible) {
70+
// Set progress value
71+
pTaskbarList->SetProgressValue((HWND)m_window->winId(), m_value, 100);
72+
// Set progress state to normal
73+
pTaskbarList->SetProgressState((HWND)m_window->winId(), TBPF_NORMAL);
74+
} else {
75+
// Hide progress bar
76+
pTaskbarList->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
77+
}
78+
}
79+
80+
void WinTaskbarProgress::initTaskbarButton()
81+
{
82+
if (m_taskbar_button || !m_window) {
83+
return;
84+
}
85+
86+
ITaskbarList3* pTaskbarList = nullptr;
87+
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER,
88+
IID_PPV_ARGS(&pTaskbarList));
89+
90+
if (SUCCEEDED(hr)) {
91+
hr = pTaskbarList->HrInit();
92+
if (SUCCEEDED(hr)) {
93+
m_taskbar_button = pTaskbarList;
94+
} else {
95+
pTaskbarList->Release();
96+
}
97+
}
98+
}
99+
100+
void WinTaskbarProgress::releaseTaskbarButton()
101+
{
102+
if (!m_taskbar_button) {
103+
return;
104+
}
105+
106+
ITaskbarList3* pTaskbarList = (ITaskbarList3*)m_taskbar_button;
107+
if (m_window) {
108+
pTaskbarList->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
109+
}
110+
pTaskbarList->Release();
111+
m_taskbar_button = nullptr;
112+
}

src/qt/wintaskbarprogress.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) 2025 The Bitcoin Knots developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_QT_WINTASKBARPROGRESS_H
6+
#define BITCOIN_QT_WINTASKBARPROGRESS_H
7+
8+
#include <QObject>
9+
10+
class QWindow;
11+
12+
/**
13+
* Manages Windows taskbar button progress indicator.
14+
* Provides a platform-independent wrapper around the native Windows API
15+
* for taskbar progress updates.
16+
*/
17+
class WinTaskbarProgress : public QObject
18+
{
19+
Q_OBJECT
20+
21+
public:
22+
explicit WinTaskbarProgress(QObject *parent = nullptr);
23+
~WinTaskbarProgress();
24+
25+
/**
26+
* Set the window handle for taskbar progress updates
27+
* @param[in] window The QWindow to update taskbar progress for
28+
*/
29+
void setWindow(QWindow* window);
30+
31+
/**
32+
* Get the current window handle
33+
* @return The current QWindow pointer, or nullptr if not set
34+
*/
35+
QWindow* window() const;
36+
37+
/**
38+
* Set the progress value
39+
* @param[in] value Progress value (0-100)
40+
*/
41+
void setValue(int value);
42+
43+
/**
44+
* Set progress visibility
45+
* @param[in] visible True to show progress, false to hide
46+
*/
47+
void setVisible(bool visible);
48+
49+
private:
50+
QWindow* m_window = nullptr;
51+
int m_value = 0;
52+
bool m_visible = false;
53+
void* m_taskbar_button = nullptr; // ITaskbarList3*
54+
55+
void updateProgress();
56+
void initTaskbarButton();
57+
void releaseTaskbarButton();
58+
};
59+
60+
#endif // BITCOIN_QT_WINTASKBARPROGRESS_H

0 commit comments

Comments
 (0)