From c9684054553f6dd8c4ff478653d20cd7a4adba9e Mon Sep 17 00:00:00 2001 From: Ievgenii Meshcheriakov Date: Tue, 23 May 2023 15:03:09 +0200 Subject: [PATCH] QDBusAbstractAdaptor: Send signals using correct interface When forwarding a signal, associate this signal with its enclosing metaobject instead of its sender's metaobject. Those two may be different if the signal is declared in a base class. Add a regression test into tst_qdbusconnection. Fixes: QTBUG-33142 Pick-to: 6.5 Change-Id: I532ab3bb6c0671a480568f46d63fceff0c82c097 Reviewed-by: Thiago Macieira Reviewed-by: Qt CI Bot --- src/dbus/qdbusabstractadaptor.cpp | 4 +-- .../qdbusconnection/tst_qdbusconnection.cpp | 28 +++++++++++++++++++ .../qdbusconnection/tst_qdbusconnection.h | 8 ++++++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/dbus/qdbusabstractadaptor.cpp b/src/dbus/qdbusabstractadaptor.cpp index 77e86ed949f..9da2fd38866 100644 --- a/src/dbus/qdbusabstractadaptor.cpp +++ b/src/dbus/qdbusabstractadaptor.cpp @@ -255,8 +255,8 @@ void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void ** // QObject signal (destroyed(QObject *)) -- ignore return; - const QMetaObject *senderMetaObject = senderObj->metaObject(); - QMetaMethod mm = senderMetaObject->method(lastSignalIdx); + QMetaMethod mm = senderObj->metaObject()->method(lastSignalIdx); + const QMetaObject *senderMetaObject = mm.enclosingMetaObject(); QObject *realObject = senderObj; if (qobject_cast(senderObj)) diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 42e898eda7b..dc39cadc95e 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -1417,6 +1417,34 @@ void tst_QDBusConnection::emptyServerAddress() QDBusServer server({}, nullptr); } +void tst_QDBusConnection::parentClassSignal() +{ + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + + const QString path = "/path"; + + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + // register one object at root: + MyObject obj; + QVERIFY(con.registerObject(path, &obj, QDBusConnection::ExportAllContents)); + QCOMPARE(con.objectRegisteredAt(path), static_cast(&obj)); + + SignalReceiver recv; + QVERIFY(con.connect(con.baseService(), path, "local.BaseObject", "baseObjectSignal", &recv, + SLOT(oneSlot()))); + QVERIFY(con.connect(con.baseService(), path, "local.MyObject", "myObjectSignal", &recv, + SLOT(oneSlot()))); + + emit obj.baseObjectSignal(); + QTRY_COMPARE(recv.signalsReceived, 1); + + emit obj.myObjectSignal(); + QTRY_COMPARE(recv.signalsReceived, 2); +} + QString MyObject::path; QString MyObjectWithoutInterface::path; QString MyObjectWithoutInterface::interface; diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h index 0aec2aa0bdf..46e53dad9b2 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h @@ -21,11 +21,14 @@ public: BaseObject(QObject *parent = nullptr) : QObject(parent) { } public slots: void anotherMethod() { } +signals: + void baseObjectSignal(); }; class MyObject: public BaseObject { Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "local.MyObject") public slots: void method(const QDBusMessage &msg); @@ -33,6 +36,9 @@ public: static QString path; int callCount; MyObject(QObject *parent = nullptr) : BaseObject(parent), callCount(0) {} + +signals: + void myObjectSignal(); }; class MyObjectWithoutInterface: public QObject @@ -117,6 +123,8 @@ private slots: void emptyServerAddress(); + void parentClassSignal(); + public: QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; } bool callMethod(const QDBusConnection &conn, const QString &path);