diff options
9 files changed, 136 insertions, 2 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index cf408ad28e..3dd7d47394 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -973,6 +973,12 @@ qt_internal_extend_target(Core CONDITION ANDROID platform/android/qandroidnativeinterface.cpp ) +qt_internal_extend_target(Core CONDITION WIN32 + SOURCES + platform/windows/qfactorycacheregistration_p.h + platform/windows/qfactorycacheregistration.cpp +) + qt_internal_extend_target(Core CONDITION HAIKU AND NOT ANDROID SOURCES io/qstandardpaths_haiku.cpp diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake index 183decb530..1ce685170a 100644 --- a/src/corelib/configure.cmake +++ b/src/corelib/configure.cmake @@ -743,7 +743,7 @@ qt_feature("xmlstream" PUBLIC LABEL "XML Streaming APIs" PURPOSE "Provides a simple streaming API for XML." ) -qt_feature("cpp-winrt" PRIVATE +qt_feature("cpp-winrt" PRIVATE PUBLIC LABEL "cpp/winrt base" PURPOSE "basic cpp/winrt language projection support" CONDITION WIN32 AND TEST_cpp_winrt diff --git a/src/corelib/platform/windows/qfactorycacheregistration.cpp b/src/corelib/platform/windows/qfactorycacheregistration.cpp new file mode 100644 index 0000000000..6bd69c66d1 --- /dev/null +++ b/src/corelib/platform/windows/qfactorycacheregistration.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qfactorycacheregistration_p.h" + +#include <QtCore/QMutex> + +QT_BEGIN_NAMESPACE + +#ifdef QT_USE_FACTORY_CACHE_REGISTRATION + +static QBasicMutex registrationMutex; +static detail::QWinRTFactoryCacheRegistration *firstElement; + +detail::QWinRTFactoryCacheRegistration::QWinRTFactoryCacheRegistration( + QFunctionPointer clearFunction) + : m_clearFunction(clearFunction) +{ + QMutexLocker lock(®istrationMutex); + + // forward pointers + m_next = std::exchange(firstElement, this); + + // backward pointers + m_prevNext = &firstElement; + if (m_next) + m_next->m_prevNext = &m_next; +} + +detail::QWinRTFactoryCacheRegistration::~QWinRTFactoryCacheRegistration() +{ + QMutexLocker lock(®istrationMutex); + + *m_prevNext = m_next; + + if (m_next) + m_next->m_prevNext = m_prevNext; +} + +void detail::QWinRTFactoryCacheRegistration::clearAllCaches() +{ + QMutexLocker lock(®istrationMutex); + + detail::QWinRTFactoryCacheRegistration *element; + + for (element = firstElement; element != nullptr; element = element->m_next) { + element->m_clearFunction(); + } +} + +#endif + +QT_END_NAMESPACE diff --git a/src/corelib/platform/windows/qfactorycacheregistration_p.h b/src/corelib/platform/windows/qfactorycacheregistration_p.h new file mode 100644 index 0000000000..db1582e94b --- /dev/null +++ b/src/corelib/platform/windows/qfactorycacheregistration_p.h @@ -0,0 +1,52 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QFACTORYCACHEREGISTRATION_P_H +#define QFACTORYCACHEREGISTRATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +#if !defined(QT_BOOTSTRAPPED) && defined(Q_OS_WIN) && !defined(Q_CC_CLANG) && QT_CONFIG(cpp_winrt) +# define QT_USE_FACTORY_CACHE_REGISTRATION +#endif + +#ifdef QT_USE_FACTORY_CACHE_REGISTRATION + +#include <winrt/base.h> + +QT_BEGIN_NAMESPACE + +namespace detail { + +class QWinRTFactoryCacheRegistration +{ +public: + Q_CORE_EXPORT explicit QWinRTFactoryCacheRegistration(QFunctionPointer clearFunction); + Q_CORE_EXPORT ~QWinRTFactoryCacheRegistration(); + Q_CORE_EXPORT static void clearAllCaches(); + + Q_DISABLE_COPY_MOVE(QWinRTFactoryCacheRegistration) +private: + QWinRTFactoryCacheRegistration **m_prevNext = nullptr; + QWinRTFactoryCacheRegistration *m_next = nullptr; + QFunctionPointer m_clearFunction; +}; + +inline QWinRTFactoryCacheRegistration reg([]() noexcept { winrt::clear_factory_cache(); }); +} + +QT_END_NAMESPACE + +#endif +#endif // QFACTORYCACHEREGISTRATION_P_H diff --git a/src/corelib/text/qlocale_win.cpp b/src/corelib/text/qlocale_win.cpp index d395b1f0cd..cb7131667c 100644 --- a/src/corelib/text/qlocale_win.cpp +++ b/src/corelib/text/qlocale_win.cpp @@ -19,6 +19,7 @@ #if QT_CONFIG(cpp_winrt) && !defined(Q_CC_CLANG) # include <winrt/base.h> +# include <QtCore/private/qfactorycacheregistration_p.h> // Workaround for Windows SDK bug. // See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 namespace winrt::impl diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp index 72023c6628..5af75a89d5 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp @@ -5,6 +5,7 @@ #ifdef SUPPORTS_WINRT #include <winrt/base.h> +#include <QtCore/private/qfactorycacheregistration_p.h> // Workaround for Windows SDK bug. // See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 namespace winrt::impl diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h index cf9a08ca84..b82d123fa4 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.h @@ -21,6 +21,7 @@ #ifdef SUPPORTS_WINRT #include <winrt/base.h> +#include <QtCore/private/qfactorycacheregistration_p.h> #endif using namespace Microsoft::WRL; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index b52d624a76..2be6625833 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -45,6 +45,7 @@ #include <QtCore/qscopedpointer.h> #include <QtCore/quuid.h> #include <QtCore/private/qwinregistry_p.h> +#include <QtCore/private/qfactorycacheregistration_p.h> #include <QtGui/private/qwindowsguieventdispatcher_p.h> @@ -221,8 +222,12 @@ QWindowsContext::~QWindowsContext() DestroyWindow(d->m_powerDummyWindow); unregisterWindowClasses(); - if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) + if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) { +#ifdef QT_USE_FACTORY_CACHE_REGISTRATION + detail::QWinRTFactoryCacheRegistration::clearAllCaches(); +#endif OleUninitialize(); + } d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows. if (d->m_displayContext) diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index ee8f03d1af..afcecd4637 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -128,6 +128,7 @@ private slots: void wheelEventPropagation(); void qtbug_12673(); + void qtbug_103611(); void noQuitOnHide(); void globalStaticObjectDestruction(); // run this last @@ -2513,6 +2514,20 @@ void tst_QApplication::qtbug_12673() #endif } +void tst_QApplication::qtbug_103611() +{ + { + int argc = 0; + QApplication app(argc, nullptr); + auto ll = QLocale().uiLanguages(); + } + { + int argc = 0; + QApplication app(argc, nullptr); + auto ll = QLocale().uiLanguages(); + } +} + class NoQuitOnHideWidget : public QWidget { Q_OBJECT |