breezy-desktop/kwin/src/xrdriveripc/xrdriveripc.cpp

112 lines
4.3 KiB
C++

// New implementation using QProcess to call python
#include "xrdriveripc.h"
#include <iostream>
#include <cmath>
#include <QFileInfo>
#include <QProcess>
#include <QProcessEnvironment>
#include <QStandardPaths>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
XRDriverIPC &XRDriverIPC::instance() {
static XRDriverIPC inst;
if (!inst.m_initialized) {
QString installedFile = QStandardPaths::locate(
QStandardPaths::GenericDataLocation,
QStringLiteral("kwin/effects/breezy_desktop/xrdriveripc.py"),
QStandardPaths::LocateFile);
if (installedFile.isEmpty()) {
throw std::runtime_error("Cannot locate kwin/effects/breezy_desktop/xrdriveripc.py");
}
inst.m_pythonDir = QFileInfo(installedFile).path();
inst.m_initialized = true;
}
return inst;
}
std::string XRDriverIPC::configHome() const {
QString configHome = QString::fromUtf8(qgetenv("XDG_CONFIG_HOME"));
if (configHome.isEmpty()) {
QString homeDir = QString::fromUtf8(qgetenv("HOME"));
configHome = homeDir + QStringLiteral("/.config");
}
return configHome.toStdString();
}
QByteArray XRDriverIPC::invokePython(const QString &method,
const QByteArray &payloadJson,
const QString &singleArg) const {
QProcess proc;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert(QStringLiteral("BREEZY_METHOD"), method);
env.insert(QStringLiteral("BREEZY_CONFIG_HOME"), QString::fromStdString(configHome()));
if (!singleArg.isEmpty()) env.insert(QStringLiteral("BREEZY_ARG"), singleArg);
if (!payloadJson.isEmpty()) env.insert(QStringLiteral("BREEZY_PAYLOAD"), QString::fromUtf8(payloadJson));
proc.setProcessEnvironment(env);
// Expect xrdriveripc_runner.py to reside in the same directory as xrdriveripc.py (m_pythonDir)
QString wrapperPath = m_pythonDir + QStringLiteral("/xrdriveripc_runner.py");
proc.start(QStringLiteral("python3"), QStringList() << wrapperPath);
if (!proc.waitForStarted(5000)) {
std::cerr << "Failed to start python process" << std::endl;
return {};
}
proc.closeWriteChannel();
if (!proc.waitForFinished(15000)) {
proc.kill();
std::cerr << "Python process timeout" << std::endl;
return {};
}
if (proc.exitStatus() != QProcess::NormalExit || proc.exitCode() != 0) {
std::cerr << "Python process failed (" << proc.exitCode() << "):\n"
<< proc.readAllStandardError().toStdString() << std::endl;
return {};
}
return proc.readAllStandardOutput().trimmed();
}
std::optional<QJsonObject> XRDriverIPC::retrieveConfig() {
QByteArray out = invokePython(QStringLiteral("retrieve_config"), {}, QStringLiteral("0"));
if (out.isEmpty()) return std::nullopt;
QJsonParseError err; auto doc = QJsonDocument::fromJson(out, &err);
if (err.error != QJsonParseError::NoError || !doc.isObject()) return std::nullopt;
return doc.object();
}
std::optional<QJsonObject> XRDriverIPC::retrieveDriverState() {
QByteArray out = invokePython(QStringLiteral("retrieve_driver_state"), {}, {});
if (out.isEmpty()) return std::nullopt;
QJsonParseError err; auto doc = QJsonDocument::fromJson(out, &err);
if (err.error != QJsonParseError::NoError || !doc.isObject()) return std::nullopt;
return doc.object();
}
bool XRDriverIPC::writeConfig(const QJsonObject &configUpdate) {
QByteArray payload = QJsonDocument(configUpdate).toJson(QJsonDocument::Compact);
QByteArray out = invokePython(QStringLiteral("write_config"), payload, {});
return !out.isEmpty();
}
bool XRDriverIPC::writeControlFlags(const std::map<std::string, bool> &flags) {
QJsonObject obj; for (const auto &kv : flags) obj.insert(QString::fromStdString(kv.first), kv.second);
QByteArray payload = QJsonDocument(obj).toJson(QJsonDocument::Compact);
QByteArray out = invokePython(QStringLiteral("write_control_flags"), payload, {});
return !out.isEmpty();
}
bool XRDriverIPC::requestToken(const std::string &email) {
QByteArray out = invokePython(QStringLiteral("request_token"), {}, QString::fromStdString(email));
if (out.isEmpty()) return false;
QString result = QString::fromUtf8(out).trimmed().toLower();
return result == QStringLiteral("true");
}
bool XRDriverIPC::verifyToken(const std::string &token) {
QByteArray out = invokePython(QStringLiteral("verify_token"), {}, QString::fromStdString(token));
if (out.isEmpty()) return false;
QString result = QString::fromUtf8(out).trimmed().toLower();
return result == QStringLiteral("true");
}