summaryrefslogtreecommitdiffstats
path: root/src/gui/platform
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/gui/platform
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/gui/platform')
-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
4 files changed, 5 insertions, 10 deletions
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()