wintaskbarprogress.cpp raw
1 // Copyright (c) 2025 The Limenka Knots developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include <qt/wintaskbarprogress.h>
6
7 #include <QWidget>
8 #include <QWindow>
9
10 #include <windows.h>
11 #include <shobjidl.h>
12
13 WinTaskbarProgress::WinTaskbarProgress(QObject *parent)
14 : QObject(parent),
15 m_taskbar_button_created_msg(RegisterWindowMessageW(L"TaskbarButtonCreated"))
16 {
17 }
18
19 WinTaskbarProgress::~WinTaskbarProgress()
20 {
21 releaseTaskbarButton();
22 }
23
24 void WinTaskbarProgress::setWindow(QWidget* widget)
25 {
26 QWindow* window = widget ? widget->windowHandle() : nullptr;
27 if (!window) {
28 return;
29 }
30 if (m_window == window) {
31 return;
32 }
33
34 m_window = window;
35 initTaskbarButton();
36 updateProgress();
37 }
38
39 void WinTaskbarProgress::setValue(int value)
40 {
41 if (m_value == value) {
42 return;
43 }
44
45 m_value = value;
46 updateProgress();
47 }
48
49 void WinTaskbarProgress::setVisible(bool visible)
50 {
51 if (m_visible == visible) {
52 return;
53 }
54
55 m_visible = visible;
56 updateProgress();
57 }
58
59 void WinTaskbarProgress::updateProgress()
60 {
61 if (!m_taskbar_button || !m_window) {
62 return;
63 }
64
65 HWND hwnd = reinterpret_cast<HWND>(m_window->winId());
66 if (m_visible) {
67 m_taskbar_button->SetProgressValue(hwnd, m_value, 100);
68 m_taskbar_button->SetProgressState(hwnd, TBPF_NORMAL);
69 } else {
70 m_taskbar_button->SetProgressState(hwnd, TBPF_NOPROGRESS);
71 }
72 }
73
74 void WinTaskbarProgress::initTaskbarButton()
75 {
76 if (m_taskbar_button || !m_window || !m_taskbar_ready) {
77 return;
78 }
79
80 HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER,
81 IID_PPV_ARGS(&m_taskbar_button));
82
83 if (SUCCEEDED(hr)) {
84 hr = m_taskbar_button->HrInit();
85 if (FAILED(hr)) {
86 m_taskbar_button->Release();
87 m_taskbar_button = nullptr;
88 }
89 }
90 }
91
92 void WinTaskbarProgress::releaseTaskbarButton()
93 {
94 if (m_taskbar_button) {
95 m_taskbar_button->Release();
96 m_taskbar_button = nullptr;
97 }
98 }
99
100 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
101 bool WinTaskbarProgress::nativeEventFilter(const QByteArray &eventType, void *pMessage, qintptr *pnResult)
102 #else
103 bool WinTaskbarProgress::nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pnResult)
104 #endif
105 {
106 Q_UNUSED(pnResult);
107
108 if (eventType != "windows_generic_MSG" && eventType != "windows_dispatcher_MSG") {
109 return false;
110 }
111
112 MSG *msg = static_cast<MSG *>(pMessage);
113
114 if (m_taskbar_button_created_msg != 0 && msg->message == m_taskbar_button_created_msg) {
115 m_taskbar_ready = true;
116 if (m_window) {
117 initTaskbarButton();
118 updateProgress();
119 }
120 }
121
122 return false;
123 }
124