diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-06-06 14:26:26 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-06-19 17:23:16 +0200 |
commit | feda990ae8fa3bc25ad5b5b7f7cc4733137519d6 (patch) | |
tree | e3fee4bb8c8db1722c9f06ed5dc644d6e239e159 | |
parent | 54a2206bba699687c4218bde2d9b295c2cf5a549 (diff) |
QEventDispatcherWin32: Use a shared class name for the message window.
Introduce a global-static struct storing atom and class name for
the message window to be shared between threads. This prevents
RegisterWindow()/UnregisterWindow() of different threads (using exec())
from interfering and silently failing.
Task-number: QTBUG-39471
Change-Id: I9bc1106a41f64749c55825a96973921bb831458f
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 64ad2ff0d3..db2d30f2f5 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -325,8 +325,6 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private() { if (internalHwnd) DestroyWindow(internalHwnd); - QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); - UnregisterClass((wchar_t*)className.utf16(), qWinAppInst()); } void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen) @@ -486,10 +484,26 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) #endif } -static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) +// Provide class name and atom for the message window used by +// QEventDispatcherWin32Private via Q_GLOBAL_STATIC shared between threads. +struct QWindowsMessageWindowClassContext +{ + QWindowsMessageWindowClassContext(); + ~QWindowsMessageWindowClassContext(); + + ATOM atom; + wchar_t *className; +}; + +QWindowsMessageWindowClassContext::QWindowsMessageWindowClassContext() + : atom(0), className(0) { // make sure that multiple Qt's can coexist in the same process - QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + const QString qClassName = QStringLiteral("QEventDispatcherWin32_Internal_Widget") + + QString::number(quintptr(qt_internal_proc)); + className = new wchar_t[qClassName.size() + 1]; + qClassName.toWCharArray(className); + className[qClassName.size()] = 0; WNDCLASS wc; wc.style = 0; @@ -501,16 +515,37 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = NULL; - wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16()); + wc.lpszClassName = className; + atom = RegisterClass(&wc); + if (!atom) { + qErrnoWarning("%s: RegisterClass() failed", Q_FUNC_INFO, qPrintable(qClassName)); + delete [] className; + className = 0; + } +} + +QWindowsMessageWindowClassContext::~QWindowsMessageWindowClassContext() +{ + if (className) { + UnregisterClass(className, qWinAppInst()); + delete [] className; + } +} + +Q_GLOBAL_STATIC(QWindowsMessageWindowClassContext, qWindowsMessageWindowClassContext) - RegisterClass(&wc); +static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) +{ + QWindowsMessageWindowClassContext *ctx = qWindowsMessageWindowClassContext(); + if (!ctx->atom) + return 0; #ifdef Q_OS_WINCE HWND parent = 0; #else HWND parent = HWND_MESSAGE; #endif - HWND wnd = CreateWindow(wc.lpszClassName, // classname - wc.lpszClassName, // window name + HWND wnd = CreateWindow(ctx->className, // classname + ctx->className, // window name 0, // style 0, 0, 0, 0, // geometry parent, // parent @@ -519,7 +554,8 @@ static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatch 0); // windows creation data. if (!wnd) { - qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError()); + qErrnoWarning("%s: CreateWindow() for QEventDispatcherWin32 internal window failed", Q_FUNC_INFO); + return 0; } #ifdef GWLP_USERDATA |