Skip to content
Open
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
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,6 @@ if(BUILD_GUI)
set(USE_DBUS TRUE)
endif()
if(WITH_TASKBAR_PROGRESS)
list(APPEND qt_components WinExtras)
set(BITCOIN_QT_WIN_TASKBAR TRUE)
endif()
if(BUILD_GUI_TESTS)
Expand Down
9 changes: 0 additions & 9 deletions depends/packages/qt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ $(package)_qttools_sha256_hash=433006eb6732bb7f546f63e0d1890477a9dd2f889228f30aa
$(package)_extra_sources = $($(package)_qttranslations_file_name)
$(package)_extra_sources += $($(package)_qttools_file_name)

$(package)_qtwinextras_file_name=qtwinextras-$($(package)_suffix)
$(package)_qtwinextras_sha256_hash=5e0e0e583b03f831ae02bf63a25a01e3bb511100ea6ca695fbc617b5c7f87bdc
$(package)_extra_sources += $($(package)_qtwinextras_file_name)

define $(package)_set_vars
$(package)_config_env = QT_MAC_SDK_NO_VERSION_CHECK=1
Expand Down Expand Up @@ -194,7 +191,6 @@ endef
define $(package)_fetch_cmds
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_download_file),$($(package)_file_name),$($(package)_sha256_hash)) && \
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttranslations_file_name),$($(package)_qttranslations_file_name),$($(package)_qttranslations_sha256_hash)) && \
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qtwinextras_file_name),$($(package)_qtwinextras_file_name),$($(package)_qtwinextras_sha256_hash)) && \
$(call fetch_file,$(package),$($(package)_download_path),$($(package)_qttools_file_name),$($(package)_qttools_file_name),$($(package)_qttools_sha256_hash))
endef

Expand All @@ -203,14 +199,11 @@ define $(package)_extract_cmds
echo "$($(package)_sha256_hash) $($(package)_source)" > $($(package)_extract_dir)/.$($(package)_file_name).hash && \
echo "$($(package)_qttranslations_sha256_hash) $($(package)_source_dir)/$($(package)_qttranslations_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
echo "$($(package)_qttools_sha256_hash) $($(package)_source_dir)/$($(package)_qttools_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
echo "$($(package)_qtwinextras_sha256_hash) $($(package)_source_dir)/$($(package)_qtwinextras_file_name)" >> $($(package)_extract_dir)/.$($(package)_file_name).hash && \
$(build_SHA256SUM) -c $($(package)_extract_dir)/.$($(package)_file_name).hash && \
mkdir qtbase && \
$(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source) -C qtbase && \
mkdir qttranslations && \
$(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttranslations_file_name) -C qttranslations && \
mkdir qtwinextras && \
$(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qtwinextras_file_name) -C qtwinextras && \
mkdir qttools && \
$(build_TAR) --no-same-owner --strip-components=1 -xf $($(package)_source_dir)/$($(package)_qttools_file_name) -C qttools
endef
Expand Down Expand Up @@ -242,7 +235,6 @@ define $(package)_preprocess_cmds
patch -p1 -i $($(package)_patch_dir)/guix_cross_lib_path.patch && \
patch -p1 -i $($(package)_patch_dir)/windows_lto.patch && \
patch -p1 -i $($(package)_patch_dir)/darwin_no_libm.patch && \
sed -i.old -e '/qwinjumplist/d' qtwinextras/src/winextras/winextras.pro && \
mkdir -p qtbase/mkspecs/macx-clang-linux &&\
cp -f qtbase/mkspecs/macx-clang/qplatformdefs.h qtbase/mkspecs/macx-clang-linux/ &&\
cp -f $($(package)_patch_dir)/mac-qmake.conf qtbase/mkspecs/macx-clang-linux/qmake.conf && \
Expand Down Expand Up @@ -273,7 +265,6 @@ endef
define $(package)_stage_cmds
$(MAKE) -C qtbase INSTALL_ROOT=$($(package)_staging_dir) install && \
$(MAKE) -C qttools INSTALL_ROOT=$($(package)_staging_dir) install && \
$(MAKE) -C qtwinextras INSTALL_ROOT=$($(package)_staging_dir) install_subtargets && \
$(MAKE) -C qttranslations INSTALL_ROOT=$($(package)_staging_dir) install_subtargets
endef

Expand Down
3 changes: 1 addition & 2 deletions depends/patches/qt/qt.pro
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ cache(, super)
!QTDIR_build: cache(CONFIG, add, $$list(QTDIR_build))

TEMPLATE = subdirs
SUBDIRS = qtbase qttools qttranslations qtwinextras
SUBDIRS = qtbase qttools qttranslations

qttools.depends = qtbase
qttranslations.depends = qttools
qtwinextras.depends = qtbase

load(qt_configure)
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
21 changes: 10 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);
QApplication::instance()->installNativeEventFilter(m_taskbar_progress);
#endif

GUIUtil::handleCloseWindowShortcut(this);
Expand All @@ -251,6 +251,9 @@ BitcoinGUI::~BitcoinGUI()
delete m_app_nap_inhibitor;
MacDockIconHandler::cleanup();
#endif
#ifdef BITCOIN_QT_WIN_TASKBAR
QApplication::instance()->removeNativeEventFilter(m_taskbar_progress);
#endif

delete NetWatch;
delete rpcConsole;
Expand Down Expand Up @@ -1235,11 +1238,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 +1254,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 +1271,9 @@ 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->setWindow(this);
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
127 changes: 127 additions & 0 deletions src/qt/wintaskbarprogress.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// 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 <QWidget>
#include <QWindow>

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

WinTaskbarProgress::WinTaskbarProgress(QObject *parent)
: QObject(parent)
{
m_taskbar_button_created_msg = RegisterWindowMessage(L"TaskbarButtonCreated");
}

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

void WinTaskbarProgress::setWindow(QWidget* widget)
{
QWindow* window = widget ? widget->windowHandle() : nullptr;
if (!window) {
return;
}
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) {
m_taskbar_button->SetProgressValue((HWND)m_window->winId(), m_value, 100);
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NORMAL);
} else {
m_taskbar_button->SetProgressState((HWND)m_window->winId(), TBPF_NOPROGRESS);
}
}

void WinTaskbarProgress::initTaskbarButton()
{
if (m_taskbar_button || !m_window || !m_taskbar_ready) {
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;
}

#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool WinTaskbarProgress::nativeEventFilter(const QByteArray &eventType, void *pMessage, qintptr *pnResult)
#else
bool WinTaskbarProgress::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
#endif
{
Q_UNUSED(eventType);
Q_UNUSED(pnResult);

MSG *msg = static_cast<MSG *>(pMessage);

if (msg->message == m_taskbar_button_created_msg && m_window) {
m_taskbar_ready = true;
initTaskbarButton();
updateProgress();
}

return false;
}
49 changes: 49 additions & 0 deletions src/qt/wintaskbarprogress.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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 <QAbstractNativeEventFilter>
#include <QObject>

#include <windows.h>

class QWidget;
class QWindow;
struct ITaskbarList3;

class WinTaskbarProgress : public QObject, public QAbstractNativeEventFilter
{
Q_OBJECT

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

void setWindow(QWidget* widget);
QWindow* window() const;
void setValue(int value);
void setVisible(bool visible);

#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
bool nativeEventFilter(const QByteArray &eventType, void *pMessage, qintptr *pnResult) override;
#else
bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) override;
#endif

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

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

#endif // BITCOIN_QT_WINTASKBARPROGRESS_H