summaryrefslogtreecommitdiffstats
path: root/src/corelib/platform/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/platform/windows')
-rw-r--r--src/corelib/platform/windows/qcomobject_p.h127
-rw-r--r--src/corelib/platform/windows/qfactorycacheregistration.cpp53
-rw-r--r--src/corelib/platform/windows/qfactorycacheregistration_p.h52
-rw-r--r--src/corelib/platform/windows/qt_winrtbase_p.h34
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(&registrationMutex);
+
+ // 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(&registrationMutex);
+
+ *m_prevNext = m_next;
+
+ if (m_next)
+ m_next->m_prevNext = m_prevNext;
+}
+
+void detail::QWinRTFactoryCacheRegistration::clearAllCaches()
+{
+ QMutexLocker lock(&registrationMutex);
+
+ 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