1
0
Fork 0

Fix stale taskbar preview thumbnails after closing child windows.

This commit is contained in:
Duncan Ogilvie 2025-12-01 03:03:44 +01:00
parent e11f5b7eaa
commit 8b7a6d38b9
6 changed files with 37 additions and 6 deletions

1
CMakeLists.txt generated
View File

@ -853,6 +853,7 @@ target_link_libraries(gui PRIVATE
md4c-html
winmm
wininet
dwmapi
)
if(CMAKE_SIZEOF_VOID_P EQUAL 4) # x86

View File

@ -148,6 +148,7 @@ private-link-libraries = [
"::md4c-html",
"winmm",
"wininet",
"dwmapi"
]
x86.private-link-libraries = [
"src/gui/Src/ThirdPartyLibs/ldconvert/ldconvert_x86.lib",

View File

@ -1400,10 +1400,10 @@ bool MainWindow::event(QEvent* event)
return QMainWindow::event(event);
}
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
bool MainWindow::nativeEvent(const QByteArray & eventType, void* message, long* result)
{
const auto msg = (MSG*)message;
if (msg->message == WM_SYSCOMMAND && (msg->wParam & 0xFFF0) == SC_CLOSE)
if(msg->message == WM_SYSCOMMAND && (msg->wParam & 0xFFF0) == SC_CLOSE)
{
// When a modal dialog is open (QDialog::exec), the main window is disabled.
// DefWindowProc ignores WM_SYSCOMMAND/SC_CLOSE for disabled windows,

View File

@ -276,7 +276,7 @@ protected:
void dragEnterEvent(QDragEnterEvent* pEvent) override;
void dropEvent(QDropEvent* pEvent) override;
bool event(QEvent* event) override;
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
bool nativeEvent(const QByteArray & eventType, void* message, long* result) override;
private slots:
void setupLanguagesMenu2();

View File

@ -10,6 +10,7 @@
#include <QDebug>
#include <QDir>
#include "MiscUtil.h"
#include <dwmapi.h>
MyApplication::MyApplication(int & argc, char** argv)
: QApplication(argc, argv)
@ -28,6 +29,21 @@ bool MyApplication::globalEventFilter(void* message)
}
#endif
static void invalidateParentThumbnail(QDialog* dialog)
{
// Find the top-level parent window
auto parent = dialog->parentWidget();
while(parent && parent->parentWidget())
{
parent = parent->parentWidget();
}
if(parent && parent->windowHandle())
{
DwmInvalidateIconicBitmaps((HWND)parent->winId());
}
}
bool MyApplication::notify(QObject* receiver, QEvent* event)
{
bool done = true;
@ -41,7 +57,20 @@ bool MyApplication::notify(QObject* receiver, QEvent* event)
MainWindow::updateDarkTitleBar(widget);
}
}
done = QApplication::notify(receiver, event);
// Fix stale taskbar preview thumbnails after closing child windows.
// Windows DWM caches the preview bitmap while hovering the taskbar, but Qt
// doesn't notify DWM when modal dialogs close, leaving the cached thumbnail
// showing the now-closed dialog. Force DWM to refresh by invalidating it.
if(event->type() == QEvent::Hide)
{
if(auto dialog = qobject_cast<QDialog*>(receiver))
{
invalidateParentThumbnail(dialog);
}
}
}
catch(const std::exception & ex)
{

View File

@ -33,12 +33,12 @@ extern thread_local TranslatedStringStorage TLS_TranslatedString;
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
class MyEventFilter : public QAbstractNativeEventFilter
{
public:
virtual bool nativeEventFilter(const QByteArray & eventType, void* message, long* result) Q_DECL_OVERRIDE
protected:
bool nativeEventFilter(const QByteArray & eventType, void* message, long* result) override
{
if(eventType == "windows_dispatcher_MSG")
return DbgWinEventGlobal((MSG*)message);
else if(eventType == "windows_generic_MSG")
if(eventType == "windows_generic_MSG")
return DbgWinEvent((MSG*)message, result);
return false;
}