KDEAmbi/wayland_poc.cpp

148 lines
5.1 KiB
C++

#include <QCoreApplication>
#include <QUuid>
#include <QDebug>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusMessage>
#include <QDBusPendingCall>
#include <QDBusPendingCallWatcher>
#include <QDBusObjectPath>
#include <QVariantMap>
#include <QThread>
// Global variable to store the session handle
static QDBusObjectPath sessionHandle;
// QDBus callback for xdg-desktop-portal SelectSources response
void handleSelectSourcesResponse(QDBusPendingCallWatcher *watcher) {
QDBusPendingCall reply = *watcher;
watcher->deleteLater();
if (reply.isError()) {
qCritical() << "D-Bus call to SelectSources failed:" << reply.error().message(); fflush(stderr);
QCoreApplication::quit();
return;
}
QList<QVariant> arguments = reply.reply().arguments();
if (arguments.isEmpty()) {
qCritical() << "SelectSources response has no arguments."; fflush(stderr);
QCoreApplication::quit();
return;
}
bool success = arguments.at(0).toBool();
if (!success) {
qCritical() << "SelectSources request denied or failed."; fflush(stderr);
QCoreApplication::quit();
return;
}
QVariantList sources = arguments.at(1).toList();
if (sources.isEmpty()) {
qCritical() << "No sources selected."; fflush(stderr);
QCoreApplication::quit();
return;
}
// For POC, just take the first source
QVariantMap sourceMap = sources.at(0).toMap();
if (!sourceMap.contains("pipewire_node_id")) {
qCritical() << "Selected source missing pipewire_node_id."; fflush(stderr);
QCoreApplication::quit();
return;
}
quint32 node_id = sourceMap.value("pipewire_node_id").toUInt();
qDebug() << "xdg-desktop-portal granted screen capture. PipeWire node ID:" << node_id;
QCoreApplication::quit(); // Quit after getting the node ID for POC
}
// QDBus callback for xdg-desktop-portal CreateSession response
// QDBus callback for xdg-desktop-portal CreateSession response
void handleCreateSessionFinished(QDBusPendingCallWatcher *watcher) {
QDBusPendingCall reply = *watcher;
watcher->deleteLater();
if (reply.isError()) {
qCritical() << "D-Bus call to CreateSession failed:" << reply.error().message(); fflush(stderr);
QCoreApplication::quit();
return;
}
QList<QVariant> arguments = reply.reply().arguments();
if (arguments.isEmpty()) {
qCritical() << "CreateSession response has no arguments."; fflush(stderr);
QCoreApplication::quit();
return;
}
QVariant firstArg = arguments.at(0);
if (!firstArg.canConvert<QDBusObjectPath>()) {
qCritical() << "CreateSession response first argument is not an object path."; fflush(stderr);
QCoreApplication::quit();
return;
}
sessionHandle = qvariant_cast<QDBusObjectPath>(firstArg);
qDebug() << "Session created with handle:" << sessionHandle.path();
// Now call SelectSources
QDBusConnection sessionBus = QDBusConnection::sessionBus();
QDBusMessage message = QDBusMessage::createMethodCall(
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.ScreenCast",
"SelectSources"
);
QVariantMap options;
options.insert("multiple", false); // Request single source
options.insert("types", (uint)3); // Monitor and Window
options.insert("cursor_mode", (uint)4); // Metadata
options.insert("persist_mode", (uint)2); // Persist for session (OBS value)
options.insert("handle_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Use QUuid without braces
options.insert("restore_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Add restore_token (OBS value)
message << options;
QDBusPendingCall pendingCall = sessionBus.asyncCall(message);
QDBusPendingCallWatcher *selectSourcesWatcher = new QDBusPendingCallWatcher(pendingCall); // Use a new watcher
QObject::connect(selectSourcesWatcher, &QDBusPendingCallWatcher::finished, handleSelectSourcesResponse);
}
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
qDebug() << "Requesting screen capture via xdg-desktop-portal...";
QDBusConnection sessionBus = QDBusConnection::sessionBus();
if (!sessionBus.isConnected()) {
qCritical() << "Failed to connect to D-Bus session bus."; fflush(stderr);
return -1;
}
// Call CreateSession first
QDBusMessage message = QDBusMessage::createMethodCall(
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.ScreenCast",
"CreateSession"
);
QVariantMap options;
options.insert("handle_token", QUuid::createUuid().toString(QUuid::WithoutBraces)); // Add handle_token
message << options;
QDBusPendingCall pendingCall = sessionBus.asyncCall(message);
QDBusPendingCallWatcher *mainWatcher = new QDBusPendingCallWatcher(pendingCall);
QObject::connect(mainWatcher, &QDBusPendingCallWatcher::finished, handleCreateSessionFinished);
return app.exec();
}