Windows: Prevent event processing during QDesktopServices::openUrl()
The platform implementation uses the Win32 API ShellExecute(), which may spin an event loop to do COM processing, causing things like QMetaCallEvent being processed. Run it in a thread to suppress this. Pick-to: 5.15 Fixes: QTBUG-85676 Change-Id: I240ca78b41b39ded22e466662ffce8e9b03c10a2 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
parent
44d4bc6d90
commit
ed114b728d
@ -44,6 +44,8 @@
|
||||
#include <QtCore/qurl.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qdir.h>
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#include <QtCore/qthread.h>
|
||||
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
|
||||
@ -54,15 +56,33 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
static quintptr runShellExecute(const wchar_t *path)
|
||||
{
|
||||
HINSTANCE result = nullptr;
|
||||
if (SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) {
|
||||
result = ShellExecute(nullptr, nullptr, path, nullptr, nullptr, SW_SHOWNORMAL);
|
||||
CoUninitialize();
|
||||
}
|
||||
return reinterpret_cast<quintptr>(result);
|
||||
}
|
||||
|
||||
static inline bool shellExecute(const QUrl &url)
|
||||
{
|
||||
const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery()
|
||||
? QDir::toNativeSeparators(url.toLocalFile())
|
||||
: url.toString(QUrl::FullyEncoded);
|
||||
const auto result =
|
||||
reinterpret_cast<quintptr>(ShellExecute(nullptr, nullptr,
|
||||
reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
|
||||
nullptr, nullptr, SW_SHOWNORMAL));
|
||||
|
||||
|
||||
// Run ShellExecute() in a thread since it may spin the event loop.
|
||||
// Prevent it from interfering with processing of posted events (QTBUG-85676).
|
||||
quintptr result = 0;
|
||||
quintptr *resultPtr = &result;
|
||||
const auto path = reinterpret_cast<const wchar_t *>(nativeFilePath.utf16());
|
||||
QScopedPointer<QThread> thread(QThread::create([path, resultPtr]
|
||||
() { *resultPtr = runShellExecute(path); }));
|
||||
thread->start();
|
||||
thread->wait();
|
||||
|
||||
// ShellExecute returns a value greater than 32 if successful
|
||||
if (result <= 32) {
|
||||
qWarning("ShellExecute '%ls' failed (error %zu).", qUtf16Printable(url.toString()), result);
|
||||
|
Loading…
Reference in New Issue
Block a user