Skip to content

Conversation

@kwsantiago
Copy link

@kwsantiago kwsantiago commented Oct 12, 2025

Replace QtWinExtras (removed in Qt6) with native Windows ITaskbarList3 COM API, making the Windows taskbar progress feature compatible with both Qt5 and Qt6.

Closes #191

Changes

  • Replace QtWinExtras with direct ITaskbarList3 COM interface
  • Create new WinTaskbarProgress class using Windows COM API
  • Use consistent Q_OS_WIN macro for Windows platform detection
  • Update CMakeLists.txt to link ole32 instead of Qt WinExtras

Implementation

The new WinTaskbarProgress class uses Windows ITaskbarList3 directly, maintaining full feature parity with the Qt5 implementation while working with both Qt5 and Qt6.

@luke-jr
Copy link
Collaborator

luke-jr commented Nov 4, 2025

I think this would be easier to review if the Qt6 depends changes were split to a separate PR, and the fixups squashed.

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 3c0a6ca to 9757d00 Compare November 4, 2025 21:53
@kwsantiago
Copy link
Author

I've split this PR as requested:

@luke-jr
Copy link
Collaborator

luke-jr commented Nov 5, 2025

My thought was more of having this PR just port win_taskbar_progress to native Windows, and have the Qt6 PR independently change depends builds, neither depending on each other.

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 9757d00 to 8986737 Compare November 6, 2025 21:16
@kwsantiago
Copy link
Author

Gotcha @luke-jr I've updated both PRs to reflect.

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch 2 times, most recently from bdc4742 to 52502ef Compare November 7, 2025 16:53
@kwsantiago kwsantiago requested a review from luke-jr November 7, 2025 16:55
@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 52502ef to 0dc86b2 Compare November 7, 2025 17:26
@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 0dc86b2 to b895717 Compare November 7, 2025 19:18
@kwsantiago kwsantiago requested a review from luke-jr November 7, 2025 19:27
@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from b895717 to c527b35 Compare November 7, 2025 19:36
@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from c527b35 to c8fe155 Compare November 9, 2025 01:00
@kwsantiago kwsantiago requested a review from luke-jr November 9, 2025 01:00
Copy link
Collaborator

@luke-jr luke-jr left a comment

Choose a reason for hiding this comment

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

Not sure if windowHandle() can return null, but it should only ever return itself anyway, so might as well just pass this?

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch 3 times, most recently from d132c1b to 6f9bf62 Compare November 16, 2025 01:32
@kwsantiago kwsantiago requested a review from luke-jr November 16, 2025 01:32
@kwsantiago kwsantiago marked this pull request as ready for review November 16, 2025 01:32
Copy link

@bigshiny90 bigshiny90 left a comment

Choose a reason for hiding this comment

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

Testing this a little today but ran into some unexpected difficulties.

  1. built as is, the progress bar never shows/initiates for me. I ended up moving the m_taskbar_progress->setWindow out of the constructor (line 235) back down closer to its original position inside of setNumBlocks. Something like:
    Line 1270
#ifdef BITCOIN_QT_WIN_TASKBAR
           if (!m_taskbar_progress->window()) {
               m_taskbar_progress->setWindow(this);
           }
           m_taskbar_progress->setValue(qRound(nVerificationProgress * 100.0));
           m_taskbar_progress->setVisible(true);
#endif

This fixed the issue but with a caveat (see #2)

  1. with it now working, the progress bar will still take 1 to 3 minutes to actually show up. (variable)

Not sure what the issue is - I'm wondering if having setWindow in the constructor is problematic (windowhandle still null?)

Copy link

@bigshiny90 bigshiny90 left a comment

Choose a reason for hiding this comment

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

Since this PR replaces Qt5 WinExtras, do you want to remove the old dependencies?

  • CMakeLists.txt, line 242 - remove list(APPEND qt_components WinExtras)
  • depends/packages/qt.mk - has references to qtwinextras

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 6f9bf62 to 527b8f9 Compare December 3, 2025 23:57
@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 527b8f9 to 972972c Compare December 3, 2025 23:57
@kwsantiago
Copy link
Author

@bigshiny90 should be resolved in 972972c

@bigshiny90
Copy link

bigshiny90 commented Dec 4, 2025

@bigshiny90 should be resolved in [972972c]

Running the new code. New Taskbar progress is now loading. But, i'm still having the issue where the actual taskbar progress takes over a minute (1.5 minutes in my last test) before it switches from normal taskbar style to actually showing progress.

Screenshots showing INITIAL STATE / POST 1.5 minutes:

Screenshot 2025-12-04 110225 Screenshot 2025-12-04 110624

Running normal QtWinExtras taskbar progress will show progress indicator immediately.

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from 972972c to eee7c82 Compare December 4, 2025 16:17
@kwsantiago
Copy link
Author

@bigshiny90 thank you for testing, I pushed up some fixes in eee7c82, let me know if that helped.

@bigshiny90
Copy link

@bigshiny90 thank you for testing, I pushed up some fixes in [eee7c82]

So i don't think these changes are addressing the real issue. i did some quick research and came up with the idea that it is missing the proper QT NativeEventFilter. Made some changes and tested and everything now works correctly - instant taskbar progress. (Note - not sure it matters - but i'm building using the windows msvc method and QT5. Not sure if the same issue exists with QT6).

(I hope you don't mind me hacking away at this!)

My guess:

Windows needs us to wait for a TaskbarButtonCreated message before calling ITaskbarList3 methods. Looks like Qt5 WinExtras handled this behind the scenes (from somequick research), but since we're going native we need to do it ourselves.

The fix?

I followed the same pattern already used in winshutdownmonitor.cpp - hook into Qt's native event filter and wait for that message.

Here are the changes that worked for me, all pretty boilerplate stuff:


wintaskbarprogress.h

#include <QAbstractNativeEventFilter>
#include <QObject>

#include <windows.h>

// ...

class WinTaskbarProgress : public QObject, public QAbstractNativeEventFilter
{
    Q_OBJECT

public:
    // ... existing methods ...

    /** Implements QAbstractNativeEventFilter interface for processing Windows messages */
    bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult) override;

private:
    // ... existing members ...
    UINT m_taskbar_button_created_msg = 0;
    bool m_taskbar_ready = false;
};

wintaskbarprogress.cpp

Constructor - register the message:

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

Add native event filter:

bool WinTaskbarProgress::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
{
    Q_UNUSED(eventType);
    Q_UNUSED(pnResult);

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

    if (msg->message == m_taskbar_button_created_msg && m_window) {
        // Taskbar button is now ready - safe to initialize ITaskbarList3
        m_taskbar_ready = true;
        initTaskbarButton();
        updateProgress();
    }

    return false; // Allow normal processing
}

Update initTaskbarButton() guard:

void WinTaskbarProgress::initTaskbarButton()
{
    if (m_taskbar_button || !m_window || !m_taskbar_ready) {
        return;
    }
    // ... rest unchanged ...
}

bitcoingui.cpp

Constructor - install filter:

#ifdef BITCOIN_QT_WIN_TASKBAR
    m_taskbar_progress = new WinTaskbarProgress(this);
    QApplication::instance()->installNativeEventFilter(m_taskbar_progress);
#endif

Destructor - remove filter:

#ifdef BITCOIN_QT_WIN_TASKBAR
    QApplication::instance()->removeNativeEventFilter(m_taskbar_progress);
#endif

Tested and confirmed working - progress shows up immediately now

@kwsantiago kwsantiago force-pushed the kwsantiago/191-win-taskbar-progress-qt6 branch from eee7c82 to 23b4023 Compare December 4, 2025 17:35
@kwsantiago
Copy link
Author

@bigshiny90 thank you, that's helpful. Reflected in 23b4023

@kwsantiago kwsantiago requested a review from bigshiny90 December 4, 2025 17:37
@bigshiny90
Copy link

bigshiny90 commented Dec 4, 2025

Working great. Everything has been addressed as far as what i can see.

I will run it through the day during IBD just to confirm end-to-end that everything works. I will let you know if any surprises...

Copy link

@bigshiny90 bigshiny90 left a comment

Choose a reason for hiding this comment

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

Tested and working. Ran thru a full IBD to watch progress bar and visibility.

Big ACK from me as this is necessary for moving forward with QT6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Port win_taskbar_progress (#14137) to Qt6

3 participants