From c4109fe10370b7b27b22ddc9db4286db34ea9c4e Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Tue, 23 Oct 2012 16:25:47 +0300 Subject: Fix crash when handling WM_PAINT during COM operations Synchronous expose corrupts painter state if it is done during existing paint operation, which can happen e.g. when requesting some value from dumpcpp generated wrapper inside a slot. Fixed by implementing support for setting asynchronous expose and doing expose according to the setting in handleWmPaint(). Task-number: QTBUG-27209 Change-Id: I89b5aa823fda947d26b1a4757f129e7c31ea408b Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowscontext.cpp | 13 ++++++++++++- src/plugins/platforms/windows/qwindowscontext.h | 2 ++ src/plugins/platforms/windows/qwindowsintegration.cpp | 13 +++++++++++++ src/plugins/platforms/windows/qwindowswindow.cpp | 6 ++++-- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 42db58ae6c..a0749388f9 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -259,6 +259,7 @@ struct QWindowsContextPrivate { const HRESULT m_oleInitializeResult; const QByteArray m_eventType; QWindow *m_lastActiveWindow; + bool m_asyncExpose; }; QWindowsContextPrivate::QWindowsContextPrivate() : @@ -267,7 +268,7 @@ QWindowsContextPrivate::QWindowsContextPrivate() : m_defaultDPI(GetDeviceCaps(m_displayContext,LOGPIXELSY)), m_oleInitializeResult(OleInitialize(NULL)), m_eventType(QByteArrayLiteral("windows_generic_MSG")), - m_lastActiveWindow(0) + m_lastActiveWindow(0), m_asyncExpose(0) { #ifndef Q_OS_WINCE QWindowsContext::user32dll.init(); @@ -923,6 +924,16 @@ void QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) } #endif +bool QWindowsContext::asyncExpose() const +{ + return d->m_asyncExpose; +} + +void QWindowsContext::setAsyncExpose(bool value) +{ + d->m_asyncExpose = value; +} + /*! \brief Windows functions for actual windows. diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index ef48a52e07..21a846ef97 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -184,6 +184,8 @@ public: #endif static QByteArray comErrorString(HRESULT hr); + bool asyncExpose() const; + void setAsyncExpose(bool value); private: void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index f95fbf4b34..b7309c3f7c 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -96,6 +96,7 @@ QT_BEGIN_NAMESPACE class QWindowsNativeInterface : public QPlatformNativeInterface { Q_OBJECT + Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose) public: #ifndef QT_NO_OPENGL virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context); @@ -106,6 +107,8 @@ public: Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate, const QString &windowName, void *eventProc) const; + bool asyncExpose() const; + void setAsyncExpose(bool value); }; void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window) @@ -183,6 +186,16 @@ void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTempl return hwnd; } +bool QWindowsNativeInterface::asyncExpose() const +{ + return QWindowsContext::instance()->asyncExpose(); +} + +void QWindowsNativeInterface::setAsyncExpose(bool value) +{ + QWindowsContext::instance()->setAsyncExpose(value); +} + /*! \class QWindowsIntegration \brief QPlatformIntegration implementation for Windows. diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 99b8922768..9aada91e73 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1158,7 +1158,8 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, InvalidateRect(hwnd, 0, false); BeginPaint(hwnd, &ps); QWindowSystemInterface::handleExposeEvent(window(), QRegion(qrectFromRECT(ps.rcPaint))); - QWindowSystemInterface::flushWindowSystemEvents(); + if (!QWindowsContext::instance()->asyncExpose()) + QWindowSystemInterface::flushWindowSystemEvents(); EndPaint(hwnd, &ps); } else { @@ -1169,7 +1170,8 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, qDebug() << __FUNCTION__ << this << window() << updateRect; QWindowSystemInterface::handleExposeEvent(window(), QRegion(updateRect)); - QWindowSystemInterface::flushWindowSystemEvents(); + if (!QWindowsContext::instance()->asyncExpose()) + QWindowSystemInterface::flushWindowSystemEvents(); EndPaint(hwnd, &ps); } return true; -- cgit v1.2.3