diff options
Diffstat (limited to 'src/corelib/platform/windows')
-rw-r--r-- | src/corelib/platform/windows/qcomobject_p.h | 127 | ||||
-rw-r--r-- | src/corelib/platform/windows/qfactorycacheregistration.cpp | 53 | ||||
-rw-r--r-- | src/corelib/platform/windows/qfactorycacheregistration_p.h | 52 | ||||
-rw-r--r-- | src/corelib/platform/windows/qt_winrtbase_p.h | 34 |
4 files changed, 266 insertions, 0 deletions
diff --git a/src/corelib/platform/windows/qcomobject_p.h b/src/corelib/platform/windows/qcomobject_p.h new file mode 100644 index 0000000000..8f27a18ff6 --- /dev/null +++ b/src/corelib/platform/windows/qcomobject_p.h @@ -0,0 +1,127 @@ +// Copyright (C) 2023 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 QCOMOBJECT_P_H +#define QCOMOBJECT_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/private/qglobal_p.h> + +#if defined(Q_OS_WIN) || defined(Q_QDOC) + +# include <QtCore/qt_windows.h> + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { + +template <typename... TInterfaces> +struct QComObjectTraits +{ + static constexpr bool isGuidOf(REFIID riid) noexcept + { + return ((riid == __uuidof(TInterfaces)) || ...); + } +}; + +} // namespace QtPrivate + +// NOTE: In order to be able to query the intermediate interface, i.e. the one you do not specify in +// QComObject interface list (TFirstInterface, TInterfaces) but that is a base for any of them +// (except IUnknown) you need to provide an explicit specialization of function +// QComObjectTraits<...>::isGuidOf for that type. For example, if you want to inherit interface +// IMFSampleGrabberSinkCallback which inherits IMFClockStateSink and you want to be able to query +// the latter one you need to provide this explicit specialization: +// +// class SinkCallback : public QComObject<IMFSampleGrabberSinkCallback> +// { +// ... +// }; +// +// namespace QtPrivate { +// +// template <> +// struct QComObjectTraits<IMFSampleGrabberSinkCallback> +// { +// static constexpr bool isGuidOf(REFIID riid) noexcept +// { +// return QComObjectTraits<IMFSampleGrabberSinkCallback, IMFClockStateSink>::isGuidOf(riid); +// } +// }; +// +// } + +template <typename TFirstInterface, typename... TAdditionalInterfaces> +class QComObject : public TFirstInterface, public TAdditionalInterfaces... +{ +public: + STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override + { + if (!ppvObject) + return E_POINTER; + + if (riid == __uuidof(IUnknown)) { + *ppvObject = static_cast<IUnknown *>(static_cast<TFirstInterface *>(this)); + AddRef(); + + return S_OK; + } + + return tryQueryInterface<TFirstInterface, TAdditionalInterfaces...>(riid, ppvObject); + } + + STDMETHODIMP_(ULONG) AddRef() override { return ++m_referenceCount; } + + STDMETHODIMP_(ULONG) Release() override + { + const LONG referenceCount = --m_referenceCount; + if (referenceCount == 0) + delete this; + + return referenceCount; + } + +protected: + QComObject() = default; + + // Destructor is not public. Caller should call Release. + // Derived class should make its destructor private to force this behavior. + virtual ~QComObject() = default; + +private: + template <typename TInterface, typename... TRest> + HRESULT tryQueryInterface(REFIID riid, void **ppvObject) + { + if (QtPrivate::QComObjectTraits<TInterface>::isGuidOf(riid)) { + *ppvObject = static_cast<TInterface *>(this); + AddRef(); + + return S_OK; + } + + if constexpr (sizeof...(TRest) > 0) + return tryQueryInterface<TRest...>(riid, ppvObject); + + *ppvObject = nullptr; + + return E_NOINTERFACE; + } + + std::atomic<LONG> m_referenceCount = 1; +}; + +QT_END_NAMESPACE + +#endif // Q_OS_WIN + +#endif // QCOMOBJECT_P_H 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..d0b19b995b --- /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) && QT_CONFIG(cpp_winrt) +# define QT_USE_FACTORY_CACHE_REGISTRATION +#endif + +#ifdef QT_USE_FACTORY_CACHE_REGISTRATION + +#include "qt_winrtbase_p.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/platform/windows/qt_winrtbase_p.h b/src/corelib/platform/windows/qt_winrtbase_p.h new file mode 100644 index 0000000000..fb7366f93d --- /dev/null +++ b/src/corelib/platform/windows/qt_winrtbase_p.h @@ -0,0 +1,34 @@ +// 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 QT_WINRTBASE_P_H +#define QT_WINRTBASE_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 QT_CONFIG(cpp_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 +{ + template <typename Async> + auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout); +} +// See https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/faq#how-do-i-resolve-ambiguities-with-getcurrenttime-and-or-try- +// for more workarounds. +#endif // QT_CONFIG(cpp/winrt) + +#endif // QT_WINRTBASE_P_H |