Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/qt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,14 @@ if(WITH_DBUS)
target_link_libraries(bitcoinqt PRIVATE "Qt${WITH_QT_VERSION}::DBus")
endif()
if(WITH_TASKBAR_PROGRESS)
target_sources(bitcoinqt
PRIVATE
$<$<PLATFORM_ID:Windows>:wintaskbarprogress.cpp>
$<$<PLATFORM_ID:Windows>:wintaskbarprogress.h>
)
target_link_libraries(bitcoinqt
PRIVATE
"Qt${WITH_QT_VERSION}::WinExtras"
$<$<PLATFORM_ID:Windows>:dwmapi>
$<$<PLATFORM_ID:Windows>:ole32>
)
endif()

Expand Down
17 changes: 6 additions & 11 deletions src/qt/bitcoingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
#include <qt/macdockiconhandler.h>
#endif
#ifdef BITCOIN_QT_WIN_TASKBAR
#include <QWinTaskbarButton>
#include <QWinTaskbarProgress>
#include <qt/wintaskbarprogress.h>
#endif

#include <chain.h>
Expand Down Expand Up @@ -232,7 +231,8 @@ BitcoinGUI::BitcoinGUI(interfaces::Node& node, const PlatformStyle *_platformSty
m_app_nap_inhibitor = new CAppNapInhibitor;
#endif
#ifdef BITCOIN_QT_WIN_TASKBAR
m_taskbar_button = new QWinTaskbarButton(this);
m_taskbar_progress = new WinTaskbarProgress(this);
m_taskbar_progress->setWindow(windowHandle());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
m_taskbar_progress->setWindow(windowHandle());
m_taskbar_progress->setWindow(this);

#endif

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

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

#ifdef BITCOIN_QT_WIN_TASKBAR
m_taskbar_button->setWindow(windowHandle());
QWinTaskbarProgress* taskbar_progress = m_taskbar_button->progress();
#endif

// Set icon state: spinning if catching up, tick otherwise
if (secs < MAX_BLOCK_TIME_GAP) {
tooltip = tr("Up to date") + QString(".<br>") + tooltip;
Expand All @@ -1256,7 +1251,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
#ifdef BITCOIN_QT_WIN_TASKBAR
taskbar_progress->setVisible(false);
m_taskbar_progress->setVisible(false);
#endif
}
else
Expand All @@ -1273,8 +1268,8 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer
progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
progressBar->setVisible(true);
#ifdef BITCOIN_QT_WIN_TASKBAR
taskbar_progress->setValue(qRound(nVerificationProgress * 100.0));
taskbar_progress->setVisible(true);
m_taskbar_progress->setValue(qRound(nVerificationProgress * 100.0));
m_taskbar_progress->setVisible(true);
#endif

tooltip = tr("Catching up…") + QString("<br>") + tooltip;
Expand Down
5 changes: 3 additions & 2 deletions src/qt/bitcoingui.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ class QComboBox;
class QDateTime;
class QProgressBar;
class QProgressDialog;
class QWinTaskbarButton;
QT_END_NAMESPACE

class WinTaskbarProgress;

namespace GUIUtil {
class ClickableLabel;
class ClickableProgressBar;
Expand Down Expand Up @@ -180,7 +181,7 @@ class BitcoinGUI : public QMainWindow
RPCConsole* rpcConsole = nullptr;
HelpMessageDialog* helpMessageDialog = nullptr;
#ifdef BITCOIN_QT_WIN_TASKBAR
QWinTaskbarButton* m_taskbar_button = nullptr;
WinTaskbarProgress* m_taskbar_progress = nullptr;
#endif
ModalOverlay* modalOverlay = nullptr;
MempoolStats* mempoolStats = nullptr;
Expand Down
106 changes: 106 additions & 0 deletions src/qt/wintaskbarprogress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) 2025 The Bitcoin Knots developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qt/wintaskbarprogress.h>

#include <QWindow>

#include <cassert>
#include <windows.h>
#include <shobjidl.h>

WinTaskbarProgress::WinTaskbarProgress(QObject *parent)
: QObject(parent)
{
}

WinTaskbarProgress::~WinTaskbarProgress()
{
releaseTaskbarButton();
}

void WinTaskbarProgress::setWindow(QWindow* window)
{
assert(!m_taskbar_button);
if (m_window == window) {
return;
}

m_window = window;
initTaskbarButton();
updateProgress();
}

QWindow* WinTaskbarProgress::window() const
{
return m_window;
}

void WinTaskbarProgress::setValue(int value)
{
if (m_value == value) {
return;
}

m_value = value;
updateProgress();
}

void WinTaskbarProgress::setVisible(bool visible)
{
if (m_visible == visible) {
return;
}

m_visible = visible;
updateProgress();
}

void WinTaskbarProgress::updateProgress()
{
if (!m_taskbar_button || !m_window) {
return;
}

if (m_visible) {
// Set progress value
m_taskbar_button->SetProgressValue((HWND)m_window->winId(), m_value, 100);
// Set progress state to normal
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NORMAL);
} else {
// Hide progress bar
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
}
}

void WinTaskbarProgress::initTaskbarButton()
{
if (m_taskbar_button || !m_window) {
return;
}

HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_taskbar_button));

if (SUCCEEDED(hr)) {
hr = m_taskbar_button->HrInit();
if (!SUCCEEDED(hr)) {
m_taskbar_button->Release();
m_taskbar_button = nullptr;
}
}
}

void WinTaskbarProgress::releaseTaskbarButton()
{
if (!m_taskbar_button) {
return;
}

if (m_window) {
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
}
m_taskbar_button->Release();
m_taskbar_button = nullptr;
}
61 changes: 61 additions & 0 deletions src/qt/wintaskbarprogress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) 2025 The Bitcoin Knots developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_QT_WINTASKBARPROGRESS_H
#define BITCOIN_QT_WINTASKBARPROGRESS_H

#include <QObject>

class QWindow;
struct ITaskbarList3;

/**
* Manages Windows taskbar button progress indicator.
* Provides a platform-independent wrapper around the native Windows API
* for taskbar progress updates.
*/
class WinTaskbarProgress : public QObject
{
Q_OBJECT

public:
explicit WinTaskbarProgress(QObject *parent = nullptr);
~WinTaskbarProgress();

/**
* Set the window handle for taskbar progress updates
* @param[in] window The QWindow to update taskbar progress for
*/
void setWindow(QWindow* window);

/**
* Get the current window handle
* @return The current QWindow pointer, or nullptr if not set
*/
QWindow* window() const;

/**
* Set the progress value
* @param[in] value Progress value (0-100)
*/
void setValue(int value);

/**
* Set progress visibility
* @param[in] visible True to show progress, false to hide
*/
void setVisible(bool visible);

private:
QWindow* m_window = nullptr;
int m_value = 0;
bool m_visible = false;
ITaskbarList3* m_taskbar_button = nullptr;

void updateProgress();
void initTaskbarButton();
void releaseTaskbarButton();
};

#endif // BITCOIN_QT_WINTASKBARPROGRESS_H