Skip to content

Commit 9757d00

Browse files
committed
qt: Port Windows taskbar progress to Qt6
Replace QtWinExtras (removed in Qt6) with native Windows ITaskbarList3 COM API. The new WinTaskbarProgress class uses Windows ITaskbarList3 directly, maintaining full feature parity with the Qt5 implementation while working with both Qt5 and Qt6. Changes: - Replace QtWinExtras with direct ITaskbarList3 COM interface - Use consistent Q_OS_WIN macro for Windows platform detection - Update copyright to Bitcoin Knots
1 parent 32ad8cd commit 9757d00

File tree

3 files changed

+78
-35
lines changed

3 files changed

+78
-35
lines changed

src/qt/bitcoingui.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
232232
#endif
233233
#ifdef BITCOIN_QT_WIN_TASKBAR
234234
m_taskbar_progress = new WinTaskbarProgress();
235+
if (windowHandle()) {
236+
m_taskbar_progress->setWindow(windowHandle());
237+
}
235238
#endif
236239

237240
GUIUtil::handleCloseWindowShortcut(this);
@@ -250,6 +253,9 @@ BitcoinGUI::~BitcoinGUI()
250253
delete m_app_nap_inhibitor;
251254
MacDockIconHandler::cleanup();
252255
#endif
256+
#ifdef BITCOIN_QT_WIN_TASKBAR
257+
delete m_taskbar_progress;
258+
#endif
253259

254260
delete NetWatch;
255261
delete rpcConsole;
@@ -1234,10 +1240,6 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
12341240

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

1237-
#ifdef BITCOIN_QT_WIN_TASKBAR
1238-
m_taskbar_progress->setWindow(this);
1239-
#endif
1240-
12411243
// Set icon state: spinning if catching up, tick otherwise
12421244
if (secs < MAX_BLOCK_TIME_GAP) {
12431245
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
@@ -1443,6 +1445,13 @@ void BitcoinGUI::showEvent(QShowEvent *event)
14431445
showMempoolStatsAction->setEnabled(true);
14441446
aboutAction->setEnabled(true);
14451447
optionsAction->setEnabled(true);
1448+
1449+
#ifdef BITCOIN_QT_WIN_TASKBAR
1450+
// If window handle wasn't available during construction, set it now
1451+
if (m_taskbar_progress && !m_taskbar_progress->window() && windowHandle()) {
1452+
m_taskbar_progress->setWindow(windowHandle());
1453+
}
1454+
#endif
14461455
}
14471456

14481457
#ifdef ENABLE_WALLET

src/qt/wintaskbarprogress.cpp

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,41 @@
1-
// Copyright (c) 2025 The Bitcoin Core developers
1+
// Copyright (c) 2025 The Bitcoin Knots developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#include <qt/wintaskbarprogress.h>
66

77
#if defined(Q_OS_WIN)
88

9-
#include <QWidget>
109
#include <QWindow>
1110

1211
#include <windows.h>
1312
#include <shobjidl.h>
1413

1514
WinTaskbarProgress::WinTaskbarProgress()
1615
{
17-
// COM will be initialized by Qt or the application
1816
}
1917

2018
WinTaskbarProgress::~WinTaskbarProgress()
2119
{
2220
releaseTaskbar();
2321
}
2422

25-
void WinTaskbarProgress::setWindow(QWidget* window)
23+
void WinTaskbarProgress::setWindow(QWindow* window)
2624
{
27-
if (!window) {
28-
return;
29-
}
30-
31-
// Get the native window handle
32-
QWindow* qwindow = window->windowHandle();
33-
if (qwindow) {
34-
m_winId = reinterpret_cast<HWND>(qwindow->winId());
35-
initializeTaskbar();
36-
}
25+
m_window = window;
3726
}
3827

3928
void WinTaskbarProgress::initializeTaskbar()
4029
{
41-
if (m_initialized || !m_winId) {
30+
if (m_initialized || !m_window) {
31+
return;
32+
}
33+
34+
HWND winId = reinterpret_cast<HWND>(m_window->winId());
35+
if (!winId) {
4236
return;
4337
}
4438

45-
// Create ITaskbarList3 instance
4639
HRESULT hr = CoCreateInstance(
4740
CLSID_TaskbarList,
4841
nullptr,
@@ -66,41 +59,76 @@ void WinTaskbarProgress::releaseTaskbar()
6659
{
6760
if (m_taskbarList) {
6861
// Clear progress state before releasing
69-
if (m_winId) {
70-
m_taskbarList->SetProgressState(m_winId, TBPF_NOPROGRESS);
62+
if (m_window) {
63+
HWND winId = reinterpret_cast<HWND>(m_window->winId());
64+
if (winId) {
65+
m_taskbarList->SetProgressState(winId, TBPF_NOPROGRESS);
66+
}
7167
}
7268
m_taskbarList->Release();
7369
m_taskbarList = nullptr;
7470
}
7571
m_initialized = false;
72+
m_visible = false;
7673
}
7774

7875
void WinTaskbarProgress::setValue(int value)
7976
{
80-
if (!m_initialized || !m_taskbarList || !m_winId) {
77+
// Lazy initialization on first use
78+
if (!m_initialized) {
79+
initializeTaskbar();
80+
}
81+
82+
if (!m_initialized || !m_taskbarList || !m_window) {
83+
return;
84+
}
85+
86+
HWND winId = reinterpret_cast<HWND>(m_window->winId());
87+
if (!winId) {
8188
return;
8289
}
8390

8491
// Clamp value to 0-100
8592
if (value < 0) value = 0;
8693
if (value > 100) value = 100;
8794

95+
// Use indeterminate mode for very low progress (< 1%) to show activity
96+
// Otherwise progress of 0 is invisible on the taskbar
97+
if (value < 1) {
98+
m_taskbarList->SetProgressState(winId, TBPF_INDETERMINATE);
99+
m_visible = true;
100+
return;
101+
}
102+
103+
// Switch to normal mode if not already visible
104+
if (!m_visible) {
105+
m_taskbarList->SetProgressState(winId, TBPF_NORMAL);
106+
m_visible = true;
107+
}
108+
88109
// Set progress value (current, maximum)
89-
m_taskbarList->SetProgressValue(m_winId, value, 100);
110+
m_taskbarList->SetProgressValue(winId, value, 100);
90111
}
91112

92113
void WinTaskbarProgress::setVisible(bool visible)
93114
{
94-
if (!m_initialized || !m_taskbarList || !m_winId) {
115+
if (!m_initialized || !m_taskbarList || !m_window) {
116+
return;
117+
}
118+
119+
HWND winId = reinterpret_cast<HWND>(m_window->winId());
120+
if (!winId) {
95121
return;
96122
}
97123

98-
if (visible) {
124+
if (visible && !m_visible) {
99125
// Show normal progress
100-
m_taskbarList->SetProgressState(m_winId, TBPF_NORMAL);
101-
} else {
126+
m_taskbarList->SetProgressState(winId, TBPF_NORMAL);
127+
m_visible = true;
128+
} else if (!visible && m_visible) {
102129
// Hide progress
103-
m_taskbarList->SetProgressState(m_winId, TBPF_NOPROGRESS);
130+
m_taskbarList->SetProgressState(winId, TBPF_NOPROGRESS);
131+
m_visible = false;
104132
}
105133
}
106134

src/qt/wintaskbarprogress.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
// Copyright (c) 2025 The Bitcoin Core developers
1+
// Copyright (c) 2025 The Bitcoin Knots developers
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

55
#ifndef BITCOIN_QT_WINTASKBARPROGRESS_H
66
#define BITCOIN_QT_WINTASKBARPROGRESS_H
77

8-
#ifdef WIN32
9-
#include <QWidget>
8+
#ifdef Q_OS_WIN
9+
#include <QWindow>
10+
11+
#include <windows.h>
1012

1113
// Forward declarations for COM interfaces
1214
struct ITaskbarList3;
@@ -23,7 +25,10 @@ class WinTaskbarProgress
2325
~WinTaskbarProgress();
2426

2527
/** Set the window handle to attach progress to */
26-
void setWindow(QWidget* window);
28+
void setWindow(QWindow* window);
29+
30+
/** Get the window handle */
31+
QWindow* window() const { return m_window; }
2732

2833
/** Set progress value (0-100) */
2934
void setValue(int value);
@@ -35,14 +40,15 @@ class WinTaskbarProgress
3540
void reset();
3641

3742
private:
43+
QWindow* m_window{nullptr};
3844
ITaskbarList3* m_taskbarList{nullptr};
39-
HWND m_winId{nullptr};
4045
bool m_initialized{false};
46+
bool m_visible{false};
4147

4248
void initializeTaskbar();
4349
void releaseTaskbar();
4450
};
4551

46-
#endif // WIN32
52+
#endif // Q_OS_WIN
4753

4854
#endif // BITCOIN_QT_WINTASKBARPROGRESS_H

0 commit comments

Comments
 (0)