147 lines
5.1 KiB
C++
147 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();
|
|
} |