summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-05-07 13:16:36 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2021-05-12 22:02:05 +0200
commit7feeb7c34b9fbab2593b958354dd57b4c487d5fe (patch)
tree12d10c144c587708290c0d9a15448cd518a9d230 /src
parent3224c6d7d150164241c13ccf7d47377a39c0a6bb (diff)
Rejig native interface plumbing
The initial approach for providing public access to native interfaces via T::nativeInteface<I>() was based on the template not being defined, and then having explicit instantiations of the supported types in a source file, so that the accessors were exported and available to the user. This worked fine for "simple" types such as QOpenGLContext and QOffscreenSurface, but presented a problem in the context of classes with subclasses, such as Q{Core,Gui}Application. To ensure that a native interface for QCoreApplication was accessible both from QCoreApplication and its subclasses, while at the same time preventing a native interface for QGuiApplication to be accessible for QCoreApplication, the nativeInterface() template function had to be declared in each subclass. Which in turn meant specializing each native interface once for each subclass it was available in. This quickly became tedious to manage, and the requirements for exposing a new native interface wasn't very clear with all these template specializations and explicit instantiations spread around. To improve on this situation, while also squashing a few other birds at the same time, we change the approach to use type erasure. The definition of T::nativeInteface<I>() is now inline, passing on the requested interface to a per type (T, not I) helper function, with the interface type flattened to a std::type_info. The type_info requested by the user is then compared to the available types in a single per-type (T) "switch statement", which is a lot easier to follow for someone trying to trace the logic of how a native interface is resolved. We can safely rely on type_info being stable between the user application and the Qt library as a result of exporting the type info for each native interface, by explicitly ensuring they have a key function. This is the same mechanism that ensures we can safely dynamic_cast these interfaces, even across library boundaries. The use of a free standing templated helper function instead of a member function in the type T, is to avoid shadowing issues, and to not pollute the class namespace of T with the helper function. Since we are already changing the plumbing for how a user resolves a native interface for a type T, we take the opportunity to add a few extra safeguards to the machinery. First, we add a static assert in the T::nativeInteface<I>() definition, that ensures that only compatible interfaces, as declared by the interface themselves, are allowed. This ensures a compile time error when an incompatible interface is requested, which improves on the link time errors we had prior to this patch, and also offsets the one downside of type erasure, namely that errors are only caught at runtime. Secondly, each interface meant for public consumption through T::nativeInteface<I>() is declared with a revision, which is checked when requesting the interface. This allows us to bump the revision when we make breaking changes to the interface that would have otherwise been binary incompatible. Since the user will never see this interface due to the revision check, they will not end up calling methods that have been removed or renamed. One advantage of moving to a type-erased approach for the plumbing is that we're not longer exposing the native interface types as part of the T::nativeInteface symbols. This means that if we ever want to rename a native interface, the only exported symbol that the user code relies on is the type info. Renaming is then possible by just exporting the type info for the old interface, but leaving it empty. Since no class in Qt implements the old native interface, the user will just get a nullptr back, similarly to bumping the revision of an interface. Change-Id: Ie50d8fb536aafe2836370caacb22afbcfaf1712a Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qglobal.cpp5
-rw-r--r--src/corelib/global/qnativeinterface.h97
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp7
-rw-r--r--src/corelib/kernel/qcoreapplication.h3
-rw-r--r--src/corelib/kernel/qcoreapplication_platform.h2
-rw-r--r--src/gui/kernel/qguiapplication.cpp15
-rw-r--r--src/gui/kernel/qguiapplication.h2
-rw-r--r--src/gui/kernel/qguiapplication_p.h2
-rw-r--r--src/gui/kernel/qkeymapper.cpp13
-rw-r--r--src/gui/kernel/qkeymapper_p.h2
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp17
-rw-r--r--src/gui/kernel/qoffscreensurface_platform.h2
-rw-r--r--src/gui/kernel/qopenglcontext.cpp26
-rw-r--r--src/gui/kernel/qopenglcontext_platform.h8
-rw-r--r--src/gui/kernel/qplatformoffscreensurface.h6
-rw-r--r--src/gui/kernel/qplatformopenglcontext.h6
-rw-r--r--src/gui/platform/android/qandroidnativeinterface.cpp2
-rw-r--r--src/gui/platform/macos/qcocoanativeinterface.mm2
-rw-r--r--src/gui/platform/unix/qunixnativeinterface.cpp9
-rw-r--r--src/gui/platform/windows/qwindowsnativeinterface.cpp2
-rw-r--r--src/widgets/kernel/qapplication.cpp6
-rw-r--r--src/widgets/kernel/qapplication.h2
22 files changed, 191 insertions, 45 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index f006e849af..d4a7750f98 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -50,6 +50,7 @@
# include "private/qwinregistry_p.h"
#endif // Q_OS_WIN || Q_OS_CYGWIN
#include <private/qlocale_tools_p.h>
+#include "qnativeinterface.h"
#include <qmutex.h>
#include <QtCore/private/qlocking_p.h>
@@ -4888,4 +4889,8 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
declares __CFMutableString and CFMutableStringRef.
*/
+namespace QNativeInterface::Private {
+ Q_LOGGING_CATEGORY(lcNativeInterface, "qt.nativeinterface")
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/global/qnativeinterface.h b/src/corelib/global/qnativeinterface.h
index 9e26a9ee73..e634615260 100644
--- a/src/corelib/global/qnativeinterface.h
+++ b/src/corelib/global/qnativeinterface.h
@@ -37,37 +37,104 @@
**
****************************************************************************/
-#include <QtCore/qglobal.h>
-
#ifndef QNATIVEINTERFACE_H
#define QNATIVEINTERFACE_H
+#include <QtCore/qglobal.h>
+#include <QtCore/qloggingcategory.h>
+
+#include <typeinfo>
+
+#ifndef QT_STATIC
+# define Q_NATIVE_INTERFACE_EXPORT Q_DECL_EXPORT
+# define Q_NATIVE_INTERFACE_IMPORT Q_DECL_IMPORT
+#else
+# define Q_NATIVE_INTERFACE_EXPORT
+# define Q_NATIVE_INTERFACE_IMPORT
+#endif
+
QT_BEGIN_NAMESPACE
-// Ensures that the interface's typeinfo is exported so that
-// dynamic casts work reliably, and protects the destructor
-// so that pointers to the interface can't be deleted.
-#define QT_DECLARE_NATIVE_INTERFACE(InterfaceClass) \
- protected: virtual ~InterfaceClass(); public:
+// We declare a virtual non-inline function in the form
+// of the destructor, making it the key function. This
+// ensures that the typeinfo of the class is exported.
+// By being protected, we also ensure that pointers to
+// the interface can't be deleted.
+#define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType) \
+ protected: \
+ virtual ~NativeInterface(); \
+ struct TypeInfo { \
+ using baseType = BaseType; \
+ static constexpr int revision = Revision; \
+ }; \
+ public: \
+
+// Revisioned interfaces only make sense when exposed through a base
+// type via QT_DECLARE_NATIVE_INTERFACE_ACCESSOR, as the revision
+// checks happen at that level (and not for normal dynamic_casts).
+#define QT_DECLARE_NATIVE_INTERFACE_2(NativeInterface, Revision) \
+ static_assert(false, "Must provide a base type when specifying revision");
+
+#define QT_DECLARE_NATIVE_INTERFACE_1(NativeInterface) \
+ QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, 0, void)
+
+#define QT_DECLARE_NATIVE_INTERFACE(...) \
+ QT_OVERLOADED_MACRO(QT_DECLARE_NATIVE_INTERFACE, __VA_ARGS__)
+
+namespace QNativeInterface::Private {
+ template <typename NativeInterface>
+ struct TypeInfo : private NativeInterface
+ {
+ static constexpr int revision() { return NativeInterface::TypeInfo::revision; }
+
+ template<typename BaseType>
+ static constexpr bool isCompatibleWith =
+ std::is_base_of<typename NativeInterface::TypeInfo::baseType, BaseType>::value;
+ };
+
+ template <typename T>
+ Q_NATIVE_INTERFACE_IMPORT void *resolveInterface(const T *that, const std::type_info &type, int revision);
+
+ Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcNativeInterface)
+}
// Declares an accessor for the native interface
#define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR \
- template <typename QNativeInterface> \
- QNativeInterface *nativeInterface() const;
+ template <typename I> \
+ I *nativeInterface() const \
+ { \
+ using T = std::decay_t<decltype(*this)>; \
+ using namespace QNativeInterface::Private; \
+ static_assert(TypeInfo<I>::template isCompatibleWith<T>, \
+ "T::nativeInterface<I>() requires that native interface I is compatible with T"); \
+ \
+ return static_cast<I*>(resolveInterface(this, typeid(I), TypeInfo<I>::revision())); \
+ }
// Provides a definition for the interface destructor
#define QT_DEFINE_NATIVE_INTERFACE_2(Namespace, InterfaceClass) \
QT_PREPEND_NAMESPACE(Namespace)::InterfaceClass::~InterfaceClass() = default
-// Provides a definition for the destructor, and an explicit
-// template instantiation of the native interface accessor.
-#define QT_DEFINE_NATIVE_INTERFACE_3(Namespace, InterfaceClass, PublicClass) \
- QT_DEFINE_NATIVE_INTERFACE_2(Namespace, InterfaceClass); \
- template Q_DECL_EXPORT QT_PREPEND_NAMESPACE(Namespace)::InterfaceClass *PublicClass::nativeInterface() const
-
#define QT_DEFINE_NATIVE_INTERFACE(...) QT_OVERLOADED_MACRO(QT_DEFINE_NATIVE_INTERFACE, QNativeInterface, __VA_ARGS__)
#define QT_DEFINE_PRIVATE_NATIVE_INTERFACE(...) QT_OVERLOADED_MACRO(QT_DEFINE_NATIVE_INTERFACE, QNativeInterface::Private, __VA_ARGS__)
+#define QT_NATIVE_INTERFACE_RETURN_IF(NativeInterface, baseType) \
+ using QNativeInterface::Private::lcNativeInterface; \
+ qCDebug(lcNativeInterface, "Comparing requested type id %s with available %s", \
+ type.name(), typeid(NativeInterface).name()); \
+ if (type == typeid(NativeInterface)) { \
+ qCDebug(lcNativeInterface, "Match for type id %s. Comparing revisions (requested %d / available %d)", \
+ type.name(), revision, TypeInfo<NativeInterface>::revision()); \
+ if (revision == TypeInfo<NativeInterface>::revision()) { \
+ qCDebug(lcNativeInterface) << "Full match. Returning dynamic cast of" << baseType; \
+ return dynamic_cast<NativeInterface*>(baseType); \
+ } else { \
+ qCWarning(lcNativeInterface, "Native interface revision mismatch (requested %d / available %d) for interface %s", \
+ revision, TypeInfo<NativeInterface>::revision(), type.name()); \
+ return nullptr; \
+ } \
+ }
+
QT_END_NAMESPACE
#endif // QNATIVEINTERFACE_H
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 5500d14d18..bb874569ab 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -3227,6 +3227,13 @@ QCoreApplication::checkPermission(const QString &permission)
}
#endif // future && QT_NO_QOBJECT
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QCoreApplication *that, const std::type_info &type, int revision)
+{
+ Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+ return nullptr;
+}
+
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index dd4336ea30..add9feeb40 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -53,6 +53,7 @@
#else
#include <QtCore/qscopedpointer.h>
#endif
+#include <QtCore/qnativeinterface.h>
#ifndef QT_NO_DEBUGSTREAM
#include <QtCore/qdebug.h>
#endif
@@ -159,6 +160,8 @@ public:
const char * disambiguation = nullptr,
int n = -1);
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR
+
#ifndef QT_NO_QOBJECT
#if QT_CONFIG(future)
static QFuture<QPermission::PermissionResult> requestPermission(
diff --git a/src/corelib/kernel/qcoreapplication_platform.h b/src/corelib/kernel/qcoreapplication_platform.h
index 605bfbc6a3..b246250a29 100644
--- a/src/corelib/kernel/qcoreapplication_platform.h
+++ b/src/corelib/kernel/qcoreapplication_platform.h
@@ -55,7 +55,7 @@ namespace QNativeInterface
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) || defined(Q_CLANG_QDOC)
struct Q_CORE_EXPORT QAndroidApplication
{
- QT_DECLARE_NATIVE_INTERFACE(QAndroidApplication)
+ QT_DECLARE_NATIVE_INTERFACE(QAndroidApplication, 1, QCoreApplication)
static jobject context();
static bool isActivityContext();
static int sdkVersion();
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index eed035c221..966a558304 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -4196,6 +4196,21 @@ QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
return m_inputDeviceManager;
}
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QGuiApplication *that, const std::type_info &type, int revision)
+{
+ using namespace QNativeInterface::Private;
+
+ auto *platformIntegration = QGuiApplicationPrivate::platformIntegration();
+ Q_UNUSED(platformIntegration);
+
+#if defined(Q_OS_WIN)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWindowsApplication, platformIntegration);
+#endif
+
+ return resolveInterface<QCoreApplication>(that, type, revision);
+}
+
#include "moc_qguiapplication.cpp"
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index c71ed52556..02d0376e77 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -170,6 +170,8 @@ public:
bool isSavingSession() const;
#endif
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR
+
static void sync();
Q_SIGNALS:
void fontDatabaseChanged();
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index f225bf0010..f6c8693206 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -354,7 +354,7 @@ class QWindowsMime;
struct Q_GUI_EXPORT QWindowsApplication
{
- QT_DECLARE_NATIVE_INTERFACE(QWindowsApplication)
+ QT_DECLARE_NATIVE_INTERFACE(QWindowsApplication, 1, QGuiApplication)
enum WindowActivationBehavior {
DefaultActivateWindow,
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
index 19b0e15279..3781330073 100644
--- a/src/gui/kernel/qkeymapper.cpp
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -135,4 +135,17 @@ QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
return extractKeyFromEvent(e);
}
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QKeyMapper *that, const std::type_info &type, int revision)
+{
+ Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+ using namespace QNativeInterface::Private;
+
+#if QT_CONFIG(evdev)
+ QT_NATIVE_INTERFACE_RETURN_IF(QEvdevKeyMapper, QGuiApplicationPrivate::platformIntegration());
+#endif
+
+ return nullptr;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index e0614a79a1..9f061a9eb7 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -106,7 +106,7 @@ namespace QNativeInterface::Private {
#if QT_CONFIG(evdev) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QEvdevKeyMapper
{
- QT_DECLARE_NATIVE_INTERFACE(QEvdevKeyMapper)
+ QT_DECLARE_NATIVE_INTERFACE(QEvdevKeyMapper, 1, QKeyMapper)
virtual void loadKeymap(const QString &filename) = 0;
virtual void switchLang() = 0;
};
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index d80a081105..53c60b278e 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -369,4 +369,21 @@ QPlatformSurface *QOffscreenSurface::surfaceHandle() const
return d->platformOffscreenSurface;
}
+using namespace QNativeInterface;
+
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOffscreenSurface *that, const std::type_info &type, int revision)
+{
+ Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+
+ auto *surfacePrivate = QOffscreenSurfacePrivate::get(const_cast<QOffscreenSurface*>(that));
+ Q_UNUSED(surfacePrivate);
+
+#if defined(Q_OS_ANDROID)
+ QT_NATIVE_INTERFACE_RETURN_IF(QAndroidOffscreenSurface, surfacePrivate->platformOffscreenSurface);
+#endif
+
+ return nullptr;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qoffscreensurface_platform.h b/src/gui/kernel/qoffscreensurface_platform.h
index 3eb250ea5e..b6d77491d5 100644
--- a/src/gui/kernel/qoffscreensurface_platform.h
+++ b/src/gui/kernel/qoffscreensurface_platform.h
@@ -55,7 +55,7 @@ namespace QNativeInterface {
#if defined(Q_OS_ANDROID) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QAndroidOffscreenSurface
{
- QT_DECLARE_NATIVE_INTERFACE(QAndroidOffscreenSurface)
+ QT_DECLARE_NATIVE_INTERFACE(QAndroidOffscreenSurface, 1, QOffscreenSurface)
static QOffscreenSurface *fromNative(ANativeWindow *nativeSurface);
virtual ANativeWindow *nativeSurface() const = 0;
};
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 6cc2d65a35..4a423e7ed5 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -1309,6 +1309,32 @@ QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg)
}
#endif // QT_NO_DEBUG_STREAM
+using namespace QNativeInterface;
+
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOpenGLContext *that, const std::type_info &type, int revision)
+{
+ Q_UNUSED(that); Q_UNUSED(type); Q_UNUSED(revision);
+
+ auto *platformContext = that->handle();
+ Q_UNUSED(platformContext);
+
+#if defined(Q_OS_MACOS)
+ QT_NATIVE_INTERFACE_RETURN_IF(QCocoaGLContext, platformContext);
+#endif
+#if defined(Q_OS_WIN)
+ QT_NATIVE_INTERFACE_RETURN_IF(QWGLContext, platformContext);
+#endif
+#if QT_CONFIG(xcb_glx_plugin)
+ QT_NATIVE_INTERFACE_RETURN_IF(QGLXContext, platformContext);
+#endif
+#if QT_CONFIG(egl)
+ QT_NATIVE_INTERFACE_RETURN_IF(QEGLContext, platformContext);
+#endif
+
+ return nullptr;
+}
+
#include "moc_qopenglcontext.cpp"
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qopenglcontext_platform.h b/src/gui/kernel/qopenglcontext_platform.h
index 2e475c7fe9..7627e34c20 100644
--- a/src/gui/kernel/qopenglcontext_platform.h
+++ b/src/gui/kernel/qopenglcontext_platform.h
@@ -71,7 +71,7 @@ namespace QNativeInterface {
#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QCocoaGLContext
{
- QT_DECLARE_NATIVE_INTERFACE(QCocoaGLContext)
+ QT_DECLARE_NATIVE_INTERFACE(QCocoaGLContext, 1, QOpenGLContext)
static QOpenGLContext *fromNative(QT_IGNORE_DEPRECATIONS(NSOpenGLContext) *context, QOpenGLContext *shareContext = nullptr);
virtual QT_IGNORE_DEPRECATIONS(NSOpenGLContext) *nativeContext() const = 0;
};
@@ -80,7 +80,7 @@ struct Q_GUI_EXPORT QCocoaGLContext
#if defined(Q_OS_WIN) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QWGLContext
{
- QT_DECLARE_NATIVE_INTERFACE(QWGLContext)
+ QT_DECLARE_NATIVE_INTERFACE(QWGLContext, 1, QOpenGLContext)
static HMODULE openGLModuleHandle();
static QOpenGLContext *fromNative(HGLRC context, HWND window, QOpenGLContext *shareContext = nullptr);
virtual HGLRC nativeContext() const = 0;
@@ -90,7 +90,7 @@ struct Q_GUI_EXPORT QWGLContext
#if QT_CONFIG(xcb_glx_plugin) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QGLXContext
{
- QT_DECLARE_NATIVE_INTERFACE(QGLXContext)
+ QT_DECLARE_NATIVE_INTERFACE(QGLXContext, 1, QOpenGLContext)
static QOpenGLContext *fromNative(GLXContext configBasedContext, QOpenGLContext *shareContext = nullptr);
static QOpenGLContext *fromNative(GLXContext visualBasedContext, void *visualInfo, QOpenGLContext *shareContext = nullptr);
virtual GLXContext nativeContext() const = 0;
@@ -100,7 +100,7 @@ struct Q_GUI_EXPORT QGLXContext
#if QT_CONFIG(egl) || defined(Q_CLANG_QDOC)
struct Q_GUI_EXPORT QEGLContext
{
- QT_DECLARE_NATIVE_INTERFACE(QEGLContext)
+ QT_DECLARE_NATIVE_INTERFACE(QEGLContext, 1, QOpenGLContext)
static QOpenGLContext *fromNative(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext = nullptr);
virtual EGLContext nativeContext() const = 0;
};
diff --git a/src/gui/kernel/qplatformoffscreensurface.h b/src/gui/kernel/qplatformoffscreensurface.h
index 46bc65d467..259b213f5a 100644
--- a/src/gui/kernel/qplatformoffscreensurface.h
+++ b/src/gui/kernel/qplatformoffscreensurface.h
@@ -83,12 +83,6 @@ private:
Q_DISABLE_COPY(QPlatformOffscreenSurface)
};
-template <typename NativeInterface>
-NativeInterface *QOffscreenSurface::nativeInterface() const
-{
- return dynamic_cast<NativeInterface*>(surfaceHandle());
-}
-
namespace QNativeInterface::Private {
#if defined(Q_OS_ANDROID)
diff --git a/src/gui/kernel/qplatformopenglcontext.h b/src/gui/kernel/qplatformopenglcontext.h
index d747b3b7d4..034462e5f3 100644
--- a/src/gui/kernel/qplatformopenglcontext.h
+++ b/src/gui/kernel/qplatformopenglcontext.h
@@ -104,12 +104,6 @@ private:
Q_DISABLE_COPY(QPlatformOpenGLContext)
};
-template <typename NativeInterface>
-NativeInterface *QOpenGLContext::nativeInterface() const
-{
- return dynamic_cast<NativeInterface*>(handle());
-}
-
namespace QNativeInterface::Private {
#if defined(Q_OS_MACOS)
diff --git a/src/gui/platform/android/qandroidnativeinterface.cpp b/src/gui/platform/android/qandroidnativeinterface.cpp
index b1063034a0..20c378a9e9 100644
--- a/src/gui/platform/android/qandroidnativeinterface.cpp
+++ b/src/gui/platform/android/qandroidnativeinterface.cpp
@@ -60,7 +60,7 @@ using namespace QNativeInterface::Private;
\ingroup native-interfaces-qoffscreensurface
*/
-QT_DEFINE_NATIVE_INTERFACE(QAndroidOffscreenSurface, QOffscreenSurface);
+QT_DEFINE_NATIVE_INTERFACE(QAndroidOffscreenSurface);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QAndroidOffScreenIntegration);
QOffscreenSurface *QNativeInterface::QAndroidOffscreenSurface::fromNative(ANativeWindow *nativeSurface)
diff --git a/src/gui/platform/macos/qcocoanativeinterface.mm b/src/gui/platform/macos/qcocoanativeinterface.mm
index ef8d091e47..e1f3c73e5e 100644
--- a/src/gui/platform/macos/qcocoanativeinterface.mm
+++ b/src/gui/platform/macos/qcocoanativeinterface.mm
@@ -104,7 +104,7 @@ QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QCocoaMenuBar);
\return the underlying NSOpenGLContext.
*/
-QT_DEFINE_NATIVE_INTERFACE(QCocoaGLContext, QOpenGLContext);
+QT_DEFINE_NATIVE_INTERFACE(QCocoaGLContext);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QCocoaGLIntegration);
QOpenGLContext *QNativeInterface::QCocoaGLContext::fromNative(NSOpenGLContext *nativeContext, QOpenGLContext *shareContext)
diff --git a/src/gui/platform/unix/qunixnativeinterface.cpp b/src/gui/platform/unix/qunixnativeinterface.cpp
index 0ef88b4c91..9fde98f76a 100644
--- a/src/gui/platform/unix/qunixnativeinterface.cpp
+++ b/src/gui/platform/unix/qunixnativeinterface.cpp
@@ -96,7 +96,7 @@ using namespace QNativeInterface::Private;
\return the underlying GLXContext.
*/
-QT_DEFINE_NATIVE_INTERFACE(QGLXContext, QOpenGLContext);
+QT_DEFINE_NATIVE_INTERFACE(QGLXContext);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QGLXIntegration);
QOpenGLContext *QNativeInterface::QGLXContext::fromNative(GLXContext configBasedContext, QOpenGLContext *shareContext)
@@ -143,7 +143,7 @@ QOpenGLContext *QNativeInterface::QGLXContext::fromNative(GLXContext visualBased
\return the underlying EGLContext.
*/
-QT_DEFINE_NATIVE_INTERFACE(QEGLContext, QOpenGLContext);
+QT_DEFINE_NATIVE_INTERFACE(QEGLContext);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QEGLIntegration);
QOpenGLContext *QNativeInterface::QEGLContext::fromNative(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext)
@@ -198,11 +198,6 @@ QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QVsp2Screen);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QEvdevKeyMapper);
-template <>
-QEvdevKeyMapper *QKeyMapper::nativeInterface<QEvdevKeyMapper>() const
-{
- return dynamic_cast<QEvdevKeyMapper*>(QGuiApplicationPrivate::platformIntegration());
-}
#endif // QT_CONFIG(evdev)
QT_END_NAMESPACE
diff --git a/src/gui/platform/windows/qwindowsnativeinterface.cpp b/src/gui/platform/windows/qwindowsnativeinterface.cpp
index 850713db2c..4a7d0fd2c9 100644
--- a/src/gui/platform/windows/qwindowsnativeinterface.cpp
+++ b/src/gui/platform/windows/qwindowsnativeinterface.cpp
@@ -95,7 +95,7 @@ using namespace QNativeInterface::Private;
\note This function requires that the QGuiApplication instance is already created.
*/
-QT_DEFINE_NATIVE_INTERFACE(QWGLContext, QOpenGLContext);
+QT_DEFINE_NATIVE_INTERFACE(QWGLContext);
QT_DEFINE_PRIVATE_NATIVE_INTERFACE(QWindowsGLIntegration);
HMODULE QNativeInterface::QWGLContext::openGLModuleHandle()
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 967f4177f3..8f0ce895a6 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -4100,6 +4100,12 @@ QPixmap QApplicationPrivate::applyQIconStyleHelper(QIcon::Mode mode, const QPixm
return QApplication::style()->generatedIconPixmap(mode, base, &opt);
}
+template <>
+Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QApplication *that, const std::type_info &type, int revision)
+{
+ return resolveInterface<QGuiApplication>(that, type, revision);
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/widgets/kernel/qapplication.h b/src/widgets/kernel/qapplication.h
index f5645b0a11..036526a407 100644
--- a/src/widgets/kernel/qapplication.h
+++ b/src/widgets/kernel/qapplication.h
@@ -154,6 +154,8 @@ public:
static Qt::NavigationMode navigationMode();
#endif
+ QT_DECLARE_NATIVE_INTERFACE_ACCESSOR
+
Q_SIGNALS:
void focusChanged(QWidget *old, QWidget *now);