Skip to content

Commit 6f9bf62

Browse files
committed
qt: Port Windows taskbar progress to native Windows API
1 parent 7b009f5 commit 6f9bf62

File tree

5 files changed

+185
-15
lines changed

5 files changed

+185
-15
lines changed

src/qt/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,14 @@ if(WITH_DBUS)
364364
target_link_libraries(bitcoinqt PRIVATE "Qt${WITH_QT_VERSION}::DBus")
365365
endif()
366366
if(WITH_TASKBAR_PROGRESS)
367+
target_sources(bitcoinqt
368+
PRIVATE
369+
$<$<PLATFORM_ID:Windows>:wintaskbarprogress.cpp>
370+
$<$<PLATFORM_ID:Windows>:wintaskbarprogress.h>
371+
)
367372
target_link_libraries(bitcoinqt
368373
PRIVATE
369-
"Qt${WITH_QT_VERSION}::WinExtras"
370-
$<$<PLATFORM_ID:Windows>:dwmapi>
374+
$<$<PLATFORM_ID:Windows>:ole32>
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(this);
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: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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 <QWidget>
8+
#include <QWindow>
9+
10+
#include <cassert>
11+
#include <windows.h>
12+
#include <shobjidl.h>
13+
14+
WinTaskbarProgress::WinTaskbarProgress(QObject *parent)
15+
: QObject(parent)
16+
{
17+
}
18+
19+
WinTaskbarProgress::~WinTaskbarProgress()
20+
{
21+
releaseTaskbarButton();
22+
}
23+
24+
void WinTaskbarProgress::setWindow(QWidget* widget)
25+
{
26+
assert(!m_taskbar_button);
27+
QWindow* window = widget ? widget->windowHandle() : nullptr;
28+
if (m_window == window) {
29+
return;
30+
}
31+
32+
m_window = window;
33+
initTaskbarButton();
34+
updateProgress();
35+
}
36+
37+
QWindow* WinTaskbarProgress::window() const
38+
{
39+
return m_window;
40+
}
41+
42+
void WinTaskbarProgress::setValue(int value)
43+
{
44+
if (m_value == value) {
45+
return;
46+
}
47+
48+
m_value = value;
49+
updateProgress();
50+
}
51+
52+
void WinTaskbarProgress::setVisible(bool visible)
53+
{
54+
if (m_visible == visible) {
55+
return;
56+
}
57+
58+
m_visible = visible;
59+
updateProgress();
60+
}
61+
62+
void WinTaskbarProgress::updateProgress()
63+
{
64+
if (!m_taskbar_button || !m_window) {
65+
return;
66+
}
67+
68+
if (m_visible) {
69+
// Set progress value
70+
m_taskbar_button->SetProgressValue((HWND)m_window->winId(), m_value, 100);
71+
// Set progress state to normal
72+
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NORMAL);
73+
} else {
74+
// Hide progress bar
75+
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
76+
}
77+
}
78+
79+
void WinTaskbarProgress::initTaskbarButton()
80+
{
81+
if (m_taskbar_button || !m_window) {
82+
return;
83+
}
84+
85+
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER,
86+
IID_PPV_ARGS(&m_taskbar_button));
87+
88+
if (SUCCEEDED(hr)) {
89+
hr = m_taskbar_button->HrInit();
90+
if (!SUCCEEDED(hr)) {
91+
m_taskbar_button->Release();
92+
m_taskbar_button = nullptr;
93+
}
94+
}
95+
}
96+
97+
void WinTaskbarProgress::releaseTaskbarButton()
98+
{
99+
if (!m_taskbar_button) {
100+
return;
101+
}
102+
103+
if (m_window) {
104+
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
105+
}
106+
m_taskbar_button->Release();
107+
m_taskbar_button = nullptr;
108+
}

src/qt/wintaskbarprogress.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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 QWidget;
11+
class QWindow;
12+
struct ITaskbarList3;
13+
14+
/**
15+
* Manages Windows taskbar button progress indicator.
16+
* Provides a platform-independent wrapper around the native Windows API
17+
* for taskbar progress updates.
18+
*/
19+
class WinTaskbarProgress : public QObject
20+
{
21+
Q_OBJECT
22+
23+
public:
24+
explicit WinTaskbarProgress(QObject *parent = nullptr);
25+
~WinTaskbarProgress();
26+
27+
/**
28+
* Set the window handle for taskbar progress updates
29+
* @param[in] widget The QWidget to update taskbar progress for
30+
*/
31+
void setWindow(QWidget* widget);
32+
33+
/**
34+
* Get the current window handle
35+
* @return The current QWindow pointer, or nullptr if not set
36+
*/
37+
QWindow* window() const;
38+
39+
/**
40+
* Set the progress value
41+
* @param[in] value Progress value (0-100)
42+
*/
43+
void setValue(int value);
44+
45+
/**
46+
* Set progress visibility
47+
* @param[in] visible True to show progress, false to hide
48+
*/
49+
void setVisible(bool visible);
50+
51+
private:
52+
QWindow* m_window = nullptr;
53+
int m_value = 0;
54+
bool m_visible = false;
55+
ITaskbarList3* m_taskbar_button = nullptr;
56+
57+
void updateProgress();
58+
void initTaskbarButton();
59+
void releaseTaskbarButton();
60+
};
61+
62+
#endif // BITCOIN_QT_WINTASKBARPROGRESS_H

0 commit comments

Comments
 (0)