Fix: D-Bus CreateSession signature mismatch (revisited)\n\nRemoved the unexpected parent_window argument from the CreateSession call in wayland_poc.cpp, as the xdg-desktop-portal API expects only the options dictionary. Updated lessons_learned.md.

This commit is contained in:
Tobias J. Endres 2025-08-14 07:43:30 +02:00
parent 536e264590
commit 4b1d8116bd
2 changed files with 16 additions and 22 deletions

View File

@ -113,6 +113,11 @@ This document summarizes the key challenges, debugging steps, and solutions enco
* **Diagnosis:** The `CreateSession` method, while expecting a single dictionary of options, also requires a `handle_token` within that dictionary. * **Diagnosis:** The `CreateSession` method, while expecting a single dictionary of options, also requires a `handle_token` within that dictionary.
* **Fix:** Added a `handle_token` to the `QVariantMap` passed to the `CreateSession` call in `wayland_poc.cpp`. * **Fix:** Added a `handle_token` to the `QVariantMap` passed to the `CreateSession` call in `wayland_poc.cpp`.
* **D-Bus `CreateSession` Signature Mismatch (Revisited):**
* **Problem:** The `CreateSession` call was failing with "Type of message, “(oa{sv})”, does not match expected type “(a{sv})”". This indicated that `CreateSession` expects only a single dictionary of options (`a{sv}`), and the previously added `parent_window` object path argument was unexpected.
* **Diagnosis:** The `xdg-desktop-portal` API for `CreateSession` does not expect a `parent_window` argument.
* **Fix:** Removed the `QDBusObjectPath("/")` argument from the `CreateSession` call in `wayland_poc.cpp`.
* **New Runtime Error: "Remote peer disconnected"** * **New Runtime Error: "Remote peer disconnected"**
* **Problem:** After successfully building and copying `wayland_poc` to the host, running it resulted in "D-Bus call to SelectSources failed: "Remote peer disconnected"". * **Problem:** After successfully building and copying `wayland_poc` to the host, running it resulted in "D-Bus call to SelectSources failed: "Remote peer disconnected"".
* **Diagnosis:** This indicates a problem with the D-Bus connection itself, rather than a rejection from the portal. Possible causes include incorrect D-Bus environment variables on the host, `xdg-desktop-portal` not running, or permission issues. * **Diagnosis:** This indicates a problem with the D-Bus connection itself, rather than a rejection from the portal. Possible causes include incorrect D-Bus environment variables on the host, `xdg-desktop-portal` not running, or permission issues.

View File

@ -19,28 +19,28 @@ void handleSelectSourcesResponse(QDBusPendingCallWatcher *watcher) {
watcher->deleteLater(); watcher->deleteLater();
if (reply.isError()) { if (reply.isError()) {
qCritical() << "D-Bus call to SelectSources failed:" << reply.error().message(); qCritical() << "D-Bus call to SelectSources failed:" << reply.error().message(); fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
QList<QVariant> arguments = reply.reply().arguments(); QList<QVariant> arguments = reply.reply().arguments();
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
qCritical() << "SelectSources response has no arguments."; qCritical() << "SelectSources response has no arguments."; fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
bool success = arguments.at(0).toBool(); bool success = arguments.at(0).toBool();
if (!success) { if (!success) {
qCritical() << "SelectSources request denied or failed."; qCritical() << "SelectSources request denied or failed."; fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
QVariantList sources = arguments.at(1).toList(); QVariantList sources = arguments.at(1).toList();
if (sources.isEmpty()) { if (sources.isEmpty()) {
qCritical() << "No sources selected."; qCritical() << "No sources selected."; fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
@ -48,7 +48,7 @@ void handleSelectSourcesResponse(QDBusPendingCallWatcher *watcher) {
// For POC, just take the first source // For POC, just take the first source
QVariantMap sourceMap = sources.at(0).toMap(); QVariantMap sourceMap = sources.at(0).toMap();
if (!sourceMap.contains("pipewire_node_id")) { if (!sourceMap.contains("pipewire_node_id")) {
qCritical() << "Selected source missing pipewire_node_id."; qCritical() << "Selected source missing pipewire_node_id."; fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
@ -66,21 +66,21 @@ void handleCreateSessionFinished(QDBusPendingCallWatcher *watcher) {
watcher->deleteLater(); watcher->deleteLater();
if (reply.isError()) { if (reply.isError()) {
qCritical() << "D-Bus call to CreateSession failed:" << reply.error().message(); qCritical() << "D-Bus call to CreateSession failed:" << reply.error().message(); fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
QList<QVariant> arguments = reply.reply().arguments(); QList<QVariant> arguments = reply.reply().arguments();
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
qCritical() << "CreateSession response has no arguments."; qCritical() << "CreateSession response has no arguments."; fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
QVariant firstArg = arguments.at(0); QVariant firstArg = arguments.at(0);
if (!firstArg.canConvert<QDBusObjectPath>()) { if (!firstArg.canConvert<QDBusObjectPath>()) {
qCritical() << "CreateSession response first argument is not an object path."; qCritical() << "CreateSession response first argument is not an object path."; fflush(stderr);
QCoreApplication::quit(); QCoreApplication::quit();
return; return;
} }
@ -122,13 +122,7 @@ int main(int argc, char *argv[]) {
QDBusConnection sessionBus = QDBusConnection::sessionBus(); QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) { if (!sessionBus.isConnected()) {
qCritical() << "Failed to connect to D-Bus session bus."; qCritical() << "Failed to connect to D-Bus session bus."; fflush(stderr);
return -1;
}
QThread::msleep(100); // Add a small delay
if (!sessionBus.interface()->isServiceRegistered("org.freedesktop.portal.Desktop")) {
qCritical() << "xdg-desktop-portal service not found. Please ensure it is installed and running.";
return -1; return -1;
} }
@ -140,14 +134,9 @@ int main(int argc, char *argv[]) {
"CreateSession" "CreateSession"
); );
// Generate unique object paths for handle and session_handle
QDBusObjectPath handlePath("/org/freedesktop/portal/request/12345/screencast_req_1");
QDBusObjectPath sessionPath("/org/freedesktop/portal/session/12345/screencast_sess_1");
// Add arguments: handle, session_handle, app_id, options
QVariantMap options; QVariantMap options;
options.insert("handle_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Add handle_token options.insert("handle_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Add handle_token
message << options; // Empty options map message << options;
QDBusPendingCall pendingCall = sessionBus.asyncCall(message); QDBusPendingCall pendingCall = sessionBus.asyncCall(message);
QDBusPendingCallWatcher *mainWatcher = new QDBusPendingCallWatcher(pendingCall); QDBusPendingCallWatcher *mainWatcher = new QDBusPendingCallWatcher(pendingCall);