Use member function instead of template function to resolve native interface

The use of a freestanding function is not needed now that the name
doesn't alias the nativeInterface accessor function, and was just
adding complexity to the machinery.

People not familiar with the code will have an easier time following
the flow through the helper member function, and we no longer need
to declare our own export macros.

Pick-to: 6.2
Change-Id: I17530b7e89939cfc19ab8ffaa076b7129ae02dcf
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Tor Arne Vestbø 2021-07-14 00:50:29 +02:00
parent 8ebd4a1da8
commit 0e7212460b
10 changed files with 53 additions and 66 deletions

View File

@ -43,14 +43,6 @@
#include <QtCore/qglobal.h>
#include <QtCore/qloggingcategory.h>
#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
// We declare a virtual non-inline function in the form
@ -166,9 +158,6 @@ namespace QNativeInterface::Private {
template <typename I>
struct NativeInterface : TypeInfo<I> {};
template <typename T>
Q_NATIVE_INTERFACE_IMPORT void *resolveInterface(const T *that, const char *name, int revision);
Q_CORE_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcNativeInterface)
} // QNativeInterface::Private
@ -179,10 +168,12 @@ namespace QNativeInterface::Private {
typename BaseType = T, std::enable_if_t<TypeInfo::template isCompatibleWith<T>, bool> = true> \
NativeInterface *nativeInterface() const \
{ \
return static_cast<NativeInterface*>( \
QNativeInterface::Private::resolveInterface(this, \
TypeInfo::name(), TypeInfo::revision())); \
}
return static_cast<NativeInterface*>(resolveInterface( \
TypeInfo::name(), TypeInfo::revision())); \
} \
protected: \
void *resolveInterface(const char *name, int revision) const; \
public:
// Provides a definition for the interface destructor
#define QT_DEFINE_NATIVE_INTERFACE_2(Namespace, InterfaceClass) \
@ -192,22 +183,25 @@ namespace QNativeInterface::Private {
#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 interface name %s with available %s", \
name, TypeInfo<NativeInterface>::name()); \
if (qstrcmp(name, TypeInfo<NativeInterface>::name()) == 0) { \
qCDebug(lcNativeInterface, "Match for interface %s. Comparing revisions (requested %d / available %d)", \
name, revision, TypeInfo<NativeInterface>::revision()); \
if (revision == TypeInfo<NativeInterface>::revision()) { \
qCDebug(lcNativeInterface) << "Full match. Returning dynamic cast of" << baseType; \
return dynamic_cast<NativeInterface*>(baseType); \
{ \
using QNativeInterface::Private::lcNativeInterface; \
using QNativeInterface::Private::TypeInfo; \
qCDebug(lcNativeInterface, "Comparing requested interface name %s with available %s", \
name, TypeInfo<NativeInterface>::name()); \
if (qstrcmp(name, TypeInfo<NativeInterface>::name()) == 0) { \
qCDebug(lcNativeInterface, "Match for interface %s. Comparing revisions (requested %d / available %d)", \
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(), name); \
return nullptr; \
} \
} else { \
qCWarning(lcNativeInterface, "Native interface revision mismatch (requested %d / available %d) for interface %s", \
revision, TypeInfo<NativeInterface>::revision(), name); \
return nullptr; \
qCDebug(lcNativeInterface, "No match for requested interface name %s", name); \
} \
} else { \
qCDebug(lcNativeInterface, "No match for requested interface name %s", name); \
}
QT_END_NAMESPACE

View File

@ -3246,10 +3246,9 @@ QCoreApplication::checkPermission(const QString &permission)
}
#endif // future && QT_NO_QOBJECT
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QCoreApplication *that, const char *name, int revision)
void *QCoreApplication::resolveInterface(const char *name, int revision) const
{
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
Q_UNUSED(name); Q_UNUSED(revision);
return nullptr;
}

View File

@ -4203,8 +4203,7 @@ QInputDeviceManager *QGuiApplicationPrivate::inputDeviceManager()
return m_inputDeviceManager;
}
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QGuiApplication *that, const char *name, int revision)
void *QGuiApplication::resolveInterface(const char *name, int revision) const
{
using namespace QNativeInterface::Private;
@ -4215,7 +4214,7 @@ Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(cons
QT_NATIVE_INTERFACE_RETURN_IF(QWindowsApplication, platformIntegration);
#endif
return resolveInterface<QCoreApplication>(that, name, revision);
return QCoreApplication::resolveInterface(name, revision);
}
#include "moc_qguiapplication.cpp"

View File

@ -135,10 +135,9 @@ QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
return extractKeyFromEvent(e);
}
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QKeyMapper *that, const char *name, int revision)
void *QKeyMapper::resolveInterface(const char *name, int revision) const
{
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
Q_UNUSED(name); Q_UNUSED(revision);
using namespace QNativeInterface::Private;
#if QT_CONFIG(evdev)

View File

@ -371,16 +371,15 @@ QPlatformSurface *QOffscreenSurface::surfaceHandle() const
using namespace QNativeInterface;
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOffscreenSurface *that, const char *name, int revision)
void *QOffscreenSurface::resolveInterface(const char *name, int revision) const
{
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
Q_UNUSED(name); Q_UNUSED(revision);
auto *surfacePrivate = QOffscreenSurfacePrivate::get(const_cast<QOffscreenSurface*>(that));
Q_UNUSED(surfacePrivate);
Q_D(const QOffscreenSurface);
Q_UNUSED(d);
#if defined(Q_OS_ANDROID)
QT_NATIVE_INTERFACE_RETURN_IF(QAndroidOffscreenSurface, surfacePrivate->platformOffscreenSurface);
QT_NATIVE_INTERFACE_RETURN_IF(QAndroidOffscreenSurface, d->platformOffscreenSurface);
#endif
return nullptr;

View File

@ -1312,12 +1312,11 @@ QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg)
using namespace QNativeInterface;
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QOpenGLContext *that, const char *name, int revision)
void *QOpenGLContext::resolveInterface(const char *name, int revision) const
{
Q_UNUSED(that); Q_UNUSED(name); Q_UNUSED(revision);
Q_UNUSED(name); Q_UNUSED(revision);
auto *platformContext = that->handle();
auto *platformContext = handle();
Q_UNUSED(platformContext);
#if defined(Q_OS_MACOS)

View File

@ -785,13 +785,11 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height)
result.setDevicePixelRatio(result.devicePixelRatio() * factor);
return result;
}
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QScreen *that, const char *name, int revision)
void *QScreen::resolveInterface(const char *name, int revision) const
{
using namespace QNativeInterface::Private;
auto *platformScreen = that->handle();
auto *platformScreen = handle();
Q_UNUSED(platformScreen);
Q_UNUSED(name);
Q_UNUSED(revision);

View File

@ -3004,12 +3004,11 @@ bool QWindowPrivate::applyCursor()
}
#endif // QT_NO_CURSOR
template <>
Q_NATIVE_INTERFACE_EXPORT void *QNativeInterface::Private::resolveInterface(const QWindow *that, const char *name, int revision)
void *QWindow::resolveInterface(const char *name, int revision) const
{
using namespace QNativeInterface::Private;
auto *platformWindow = that->handle();
auto *platformWindow = handle();
Q_UNUSED(platformWindow);
Q_UNUSED(name);
Q_UNUSED(revision);

View File

@ -4101,10 +4101,9 @@ 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 char *name, int revision)
void *QApplication::resolveInterface(const char *name, int revision) const
{
return resolveInterface<QGuiApplication>(that, name, revision);
return QGuiApplication::resolveInterface(name, revision);
}
QT_END_NAMESPACE

View File

@ -37,6 +37,8 @@ private slots:
void typeInfo() const;
void resolve() const;
void accessor() const;
friend struct PublicClass;
};
struct InterfaceImplementation;
@ -46,6 +48,8 @@ struct PublicClass
PublicClass();
QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(PublicClass)
std::unique_ptr<InterfaceImplementation> m_implementation;
friend void tst_QNativeInterface::resolve() const;
};
QT_BEGIN_NAMESPACE
@ -84,11 +88,9 @@ struct InterfaceImplementation : public Interface
PublicClass::PublicClass() : m_implementation(new InterfaceImplementation) {}
template <>
void* QNativeInterface::Private::resolveInterface<PublicClass>(
PublicClass const* that, char const* name, int revision)
void* PublicClass::resolveInterface(char const* name, int revision) const
{
auto *implementation = that->m_implementation.get();
auto *implementation = m_implementation.get();
QT_NATIVE_INTERFACE_RETURN_IF(Interface, implementation);
QT_NATIVE_INTERFACE_RETURN_IF(OtherInterface, implementation);
return nullptr;
@ -116,14 +118,14 @@ void tst_QNativeInterface::resolve() const
PublicClass foo;
QVERIFY(resolveInterface(&foo, "Interface", 10));
QVERIFY(foo.resolveInterface("Interface", 10));
QTest::ignoreMessage(QtWarningMsg, "Native interface revision mismatch "
"(requested 5 / available 10) for interface Interface");
QCOMPARE(resolveInterface(&foo, "Interface", 5), nullptr);
QCOMPARE(resolveInterface(&foo, "NotInterface", 10), nullptr);
QCOMPARE(resolveInterface(&foo, "OtherInterface", 10), nullptr);
QCOMPARE(foo.resolveInterface("Interface", 5), nullptr);
QCOMPARE(foo.resolveInterface("NotInterface", 10), nullptr);
QCOMPARE(foo.resolveInterface("OtherInterface", 10), nullptr);
}
void tst_QNativeInterface::accessor() const