diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f7d8cce9fe61..42608ea3eef9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/depends/packages/qt.mk b/depends/packages/qt.mk index 2500c24d96b3a..dd8234b1227fd 100644 --- a/depends/packages/qt.mk +++ b/depends/packages/qt.mk @@ -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 @@ -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 @@ -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 @@ -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 && \ @@ -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 diff --git a/depends/patches/qt/qt.pro b/depends/patches/qt/qt.pro index f0dbf3dc2d31d..6d8b7fdb6a2ca 100644 --- a/depends/patches/qt/qt.pro +++ b/depends/patches/qt/qt.pro @@ -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) diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index eeba0fbd7c90a..087d10cdefc83 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -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 + $<$:wintaskbarprogress.cpp> + $<$:wintaskbarprogress.h> + ) target_link_libraries(bitcoinqt PRIVATE - "Qt${WITH_QT_VERSION}::WinExtras" - $<$:dwmapi> + $<$:ole32> ) endif() diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index fb2922afc4b9b..79f91748ea6c0 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -35,8 +35,7 @@ #include #endif #ifdef BITCOIN_QT_WIN_TASKBAR -#include -#include +#include #endif #include @@ -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); @@ -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; @@ -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(".
") + tooltip; @@ -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 @@ -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("
") + tooltip; diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index f7ac119a019e9..c05f6e4b5d1aa 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -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; @@ -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; diff --git a/src/qt/wintaskbarprogress.cpp b/src/qt/wintaskbarprogress.cpp new file mode 100644 index 0000000000000..38fcb22f2d4e6 --- /dev/null +++ b/src/qt/wintaskbarprogress.cpp @@ -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 + +#include +#include + +#include +#include + +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(pMessage); + + if (msg->message == m_taskbar_button_created_msg && m_window) { + m_taskbar_ready = true; + initTaskbarButton(); + updateProgress(); + } + + return false; +} diff --git a/src/qt/wintaskbarprogress.h b/src/qt/wintaskbarprogress.h new file mode 100644 index 0000000000000..abb6f539fa2c8 --- /dev/null +++ b/src/qt/wintaskbarprogress.h @@ -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 +#include + +#include + +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