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 <Friedemann.Kleint@digia.com>
bb10
Miikka Heikkinen 2012-10-23 16:25:47 +03:00 committed by The Qt Project
parent 52ccbd8911
commit c4109fe103
4 changed files with 31 additions and 3 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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;