mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-29 07:03:08 +00:00
Improve Waydroid app management
Handle unavailable Waydroid sessions more cleanly and add KCM controls for launching apps, Game Shell visibility, and compatibility overrides.
This commit is contained in:
parent
eb177e0394
commit
a8e76002f4
10 changed files with 792 additions and 48 deletions
|
|
@ -35,6 +35,17 @@ void WaydroidApplicationListModel::initializeApplications(const QList<QDBusObjec
|
|||
endResetModel();
|
||||
}
|
||||
|
||||
void WaydroidApplicationListModel::clearApplications()
|
||||
{
|
||||
if (m_applications.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
m_applications.clear();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void WaydroidApplicationListModel::addApplication(const QDBusObjectPath &objectPath)
|
||||
{
|
||||
beginInsertRows({}, m_applications.size(), m_applications.size());
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public:
|
|||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
void initializeApplications(const QList<QDBusObjectPath> &applicationObjectPaths);
|
||||
void clearApplications();
|
||||
|
||||
public Q_SLOTS:
|
||||
void addApplication(const QDBusObjectPath &objectPath);
|
||||
|
|
|
|||
|
|
@ -6,24 +6,38 @@
|
|||
|
||||
#include "waydroiddbusclient.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QCoroDBusPendingReply>
|
||||
#include <QDBusMessage>
|
||||
#include <QGuiApplication>
|
||||
#include <QTimer>
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
|
||||
static const QString s_waydroidGamingGroup = QStringLiteral("WaydroidGaming");
|
||||
static const QString s_gameShellPackagesKey = QStringLiteral("gameShellPackages");
|
||||
|
||||
WaydroidDBusClient::WaydroidDBusClient(QObject *parent)
|
||||
: QObject{parent}
|
||||
, m_interface{new OrgKdePlasmashellWaydroidInterface{u"org.kde.plasmashell"_s, u"/Waydroid"_s, QDBusConnection::sessionBus(), this}}
|
||||
, m_watcher{new QDBusServiceWatcher{u"org.kde.plasmashell"_s, QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this}}
|
||||
, m_applicationListModel{new WaydroidApplicationListModel{this}}
|
||||
, m_config{KSharedConfig::openConfig(QStringLiteral("plasmamobilerc"))}
|
||||
{
|
||||
m_configWatcher = KConfigWatcher::create(m_config);
|
||||
connect(m_configWatcher.data(), &KConfigWatcher::configChanged, this, [this](const KConfigGroup &group) {
|
||||
if (group.name() == s_waydroidGamingGroup) {
|
||||
m_config->reparseConfiguration();
|
||||
reloadGameShellPackages();
|
||||
}
|
||||
});
|
||||
reloadGameShellPackages();
|
||||
|
||||
// Check if the service is already running
|
||||
if (QDBusConnection::sessionBus().interface()->isServiceRegistered(u"org.kde.plasmashell"_s)) {
|
||||
m_connected = true;
|
||||
if (m_interface->isValid()) {
|
||||
connectSignals();
|
||||
}
|
||||
checkWaydroidObject();
|
||||
}
|
||||
|
||||
connect(m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, [this](const QString &service, const QString &oldOwner, const QString &newOwner) {
|
||||
|
|
@ -31,12 +45,11 @@ WaydroidDBusClient::WaydroidDBusClient(QObject *parent)
|
|||
if (newOwner.isEmpty()) {
|
||||
// Service stopped
|
||||
m_connected = false;
|
||||
m_connectionCheckPending = false;
|
||||
resetState();
|
||||
} else if (oldOwner.isEmpty()) {
|
||||
// Service started
|
||||
m_connected = true;
|
||||
if (m_interface->isValid()) {
|
||||
connectSignals();
|
||||
}
|
||||
checkWaydroidObject();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -44,26 +57,32 @@ WaydroidDBusClient::WaydroidDBusClient(QObject *parent)
|
|||
|
||||
void WaydroidDBusClient::connectSignals()
|
||||
{
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::statusChanged, this, &WaydroidDBusClient::updateStatus);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::downloadStatusChanged, this, [this](double downloaded, double total, double speed) {
|
||||
Q_EMIT downloadStatusChanged(downloaded, total, speed);
|
||||
});
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::sessionStatusChanged, this, &WaydroidDBusClient::updateSessionStatus);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::systemTypeChanged, this, &WaydroidDBusClient::updateSystemType);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::ipAddressChanged, this, &WaydroidDBusClient::updateIpAddress);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::androidIdChanged, this, &WaydroidDBusClient::updateAndroidId);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::multiWindowsChanged, this, &WaydroidDBusClient::updateMultiWindows);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::suspendChanged, this, &WaydroidDBusClient::updateSuspend);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::ueventChanged, this, &WaydroidDBusClient::updateUevent);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::actionFinished, this, [this](const QString message) {
|
||||
Q_EMIT actionFinished(message);
|
||||
});
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::actionFailed, this, [this](const QString message) {
|
||||
Q_EMIT actionFailed(message);
|
||||
});
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::errorOccurred, this, [this](const QString title, const QString message) {
|
||||
Q_EMIT errorOccurred(title, message);
|
||||
});
|
||||
if (!m_signalsConnected) {
|
||||
m_signalsConnected = true;
|
||||
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::statusChanged, this, &WaydroidDBusClient::updateStatus);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::downloadStatusChanged, this, [this](double downloaded, double total, double speed) {
|
||||
Q_EMIT downloadStatusChanged(downloaded, total, speed);
|
||||
});
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::sessionStatusChanged, this, &WaydroidDBusClient::updateSessionStatus);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::systemTypeChanged, this, &WaydroidDBusClient::updateSystemType);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::ipAddressChanged, this, &WaydroidDBusClient::updateIpAddress);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::androidIdChanged, this, &WaydroidDBusClient::updateAndroidId);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::multiWindowsChanged, this, &WaydroidDBusClient::updateMultiWindows);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::suspendChanged, this, &WaydroidDBusClient::updateSuspend);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::ueventChanged, this, &WaydroidDBusClient::updateUevent);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::fakeTouchChanged, this, &WaydroidDBusClient::updateFakeTouch);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::fakeWifiChanged, this, &WaydroidDBusClient::updateFakeWifi);
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::actionFinished, this, [this](const QString message) {
|
||||
Q_EMIT actionFinished(message);
|
||||
});
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::actionFailed, this, [this](const QString message) {
|
||||
Q_EMIT actionFailed(message);
|
||||
});
|
||||
connect(m_interface, &OrgKdePlasmashellWaydroidInterface::errorOccurred, this, [this](const QString title, const QString message) {
|
||||
Q_EMIT errorOccurred(title, message);
|
||||
});
|
||||
}
|
||||
|
||||
initializeApplicationListModel();
|
||||
updateStatus();
|
||||
|
|
@ -74,6 +93,118 @@ void WaydroidDBusClient::connectSignals()
|
|||
updateMultiWindows();
|
||||
updateSuspend();
|
||||
updateUevent();
|
||||
updateFakeTouch();
|
||||
updateFakeWifi();
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::checkWaydroidObject()
|
||||
{
|
||||
if (m_connectionCheckPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_connectionCheckPending = true;
|
||||
|
||||
const QDBusMessage message =
|
||||
QDBusMessage::createMethodCall(u"org.kde.plasmashell"_s, u"/Waydroid"_s, u"org.freedesktop.DBus.Introspectable"_s, u"Introspect"_s);
|
||||
auto *watcher = new QDBusPendingCallWatcher(QDBusConnection::sessionBus().asyncCall(message), this);
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, &WaydroidDBusClient::onWaydroidObjectCheckFinished);
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::onWaydroidObjectCheckFinished(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
m_connectionCheckPending = false;
|
||||
|
||||
QDBusPendingReply<QString> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
m_connected = false;
|
||||
watcher->deleteLater();
|
||||
resetState();
|
||||
scheduleWaydroidObjectCheck();
|
||||
return;
|
||||
}
|
||||
|
||||
m_connected = true;
|
||||
watcher->deleteLater();
|
||||
|
||||
if (m_interface->isValid()) {
|
||||
connectSignals();
|
||||
}
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::handleUnavailableReply()
|
||||
{
|
||||
if (!m_connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_connected = false;
|
||||
resetState();
|
||||
scheduleWaydroidObjectCheck();
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::resetState()
|
||||
{
|
||||
if (m_status != NotSupported) {
|
||||
m_status = NotSupported;
|
||||
Q_EMIT statusChanged();
|
||||
}
|
||||
|
||||
if (m_sessionStatus != SessionStopped) {
|
||||
m_sessionStatus = SessionStopped;
|
||||
Q_EMIT sessionStatusChanged();
|
||||
}
|
||||
|
||||
if (m_systemType != UnknownSystemType) {
|
||||
m_systemType = UnknownSystemType;
|
||||
Q_EMIT systemTypeChanged();
|
||||
}
|
||||
|
||||
if (!m_ipAddress.isEmpty()) {
|
||||
m_ipAddress.clear();
|
||||
Q_EMIT ipAddressChanged();
|
||||
}
|
||||
|
||||
if (!m_androidId.isEmpty()) {
|
||||
m_androidId.clear();
|
||||
Q_EMIT androidIdChanged();
|
||||
}
|
||||
|
||||
if (m_multiWindows) {
|
||||
m_multiWindows = false;
|
||||
Q_EMIT multiWindowsChanged();
|
||||
}
|
||||
|
||||
if (m_suspend) {
|
||||
m_suspend = false;
|
||||
Q_EMIT suspendChanged();
|
||||
}
|
||||
|
||||
if (m_uevent) {
|
||||
m_uevent = false;
|
||||
Q_EMIT ueventChanged();
|
||||
}
|
||||
|
||||
if (!m_fakeTouch.isEmpty()) {
|
||||
m_fakeTouch.clear();
|
||||
Q_EMIT fakeTouchChanged();
|
||||
}
|
||||
|
||||
if (!m_fakeWifi.isEmpty()) {
|
||||
m_fakeWifi.clear();
|
||||
Q_EMIT fakeWifiChanged();
|
||||
}
|
||||
|
||||
m_applicationListModel->clearApplications();
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::scheduleWaydroidObjectCheck()
|
||||
{
|
||||
if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(u"org.kde.plasmashell"_s)) {
|
||||
return;
|
||||
}
|
||||
|
||||
QTimer::singleShot(1000, this, &WaydroidDBusClient::checkWaydroidObject);
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::initializeApplicationListModel()
|
||||
|
|
@ -85,6 +216,7 @@ void WaydroidDBusClient::initializeApplicationListModel()
|
|||
QDBusPendingReply<QList<QDBusObjectPath>> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch applications:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -133,6 +265,10 @@ WaydroidApplicationListModel *WaydroidDBusClient::applicationListModel() const
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::setMultiWindowsTask(const bool multiWindows)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->setMultiWindows(multiWindows);
|
||||
}
|
||||
|
||||
|
|
@ -148,6 +284,10 @@ bool WaydroidDBusClient::multiWindows() const
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::setSuspendTask(const bool suspend)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->setSuspend(suspend);
|
||||
}
|
||||
|
||||
|
|
@ -163,6 +303,10 @@ bool WaydroidDBusClient::suspend() const
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::setUeventTask(const bool uevent)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->setUevent(uevent);
|
||||
}
|
||||
|
||||
|
|
@ -173,6 +317,10 @@ QCoro::QmlTask WaydroidDBusClient::setUevent(const bool uevent)
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::refreshSessionInfoTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->refreshSessionInfo();
|
||||
}
|
||||
|
||||
|
|
@ -183,6 +331,10 @@ QCoro::QmlTask WaydroidDBusClient::refreshSessionInfo()
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::refreshAndroidIdTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->refreshAndroidId();
|
||||
}
|
||||
|
||||
|
|
@ -193,6 +345,10 @@ QCoro::QmlTask WaydroidDBusClient::refreshAndroidId()
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::refreshApplicationsTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->refreshApplications();
|
||||
}
|
||||
|
||||
|
|
@ -201,13 +357,87 @@ QCoro::QmlTask WaydroidDBusClient::refreshApplications()
|
|||
return refreshApplicationsTask();
|
||||
}
|
||||
|
||||
bool WaydroidDBusClient::gameShellEnabledForPackage(const QString &packageName) const
|
||||
{
|
||||
return m_gameShellPackages.contains(packageName);
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::setGameShellEnabledForPackage(const QString &packageName, bool enabled)
|
||||
{
|
||||
QStringList packages = m_gameShellPackages;
|
||||
packages.removeAll(packageName);
|
||||
if (enabled) {
|
||||
packages.append(packageName);
|
||||
}
|
||||
packages.removeDuplicates();
|
||||
packages.sort();
|
||||
|
||||
if (packages == m_gameShellPackages) {
|
||||
return;
|
||||
}
|
||||
|
||||
KConfigGroup group(m_config, s_waydroidGamingGroup);
|
||||
group.writeEntry(s_gameShellPackagesKey, packages, KConfigGroup::Notify);
|
||||
m_config->sync();
|
||||
|
||||
m_gameShellPackages = packages;
|
||||
Q_EMIT gameShellPackagesChanged();
|
||||
}
|
||||
|
||||
bool WaydroidDBusClient::uevent() const
|
||||
{
|
||||
return m_uevent;
|
||||
}
|
||||
|
||||
QCoro::Task<void> WaydroidDBusClient::setFakeTouchTask(const QString &fakeTouch)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->setFakeTouch(fakeTouch);
|
||||
}
|
||||
|
||||
QCoro::QmlTask WaydroidDBusClient::setFakeTouch(const QString &fakeTouch)
|
||||
{
|
||||
return setFakeTouchTask(fakeTouch);
|
||||
}
|
||||
|
||||
QString WaydroidDBusClient::fakeTouch() const
|
||||
{
|
||||
return m_fakeTouch;
|
||||
}
|
||||
|
||||
QCoro::Task<void> WaydroidDBusClient::setFakeWifiTask(const QString &fakeWifi)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->setFakeWifi(fakeWifi);
|
||||
}
|
||||
|
||||
QCoro::QmlTask WaydroidDBusClient::setFakeWifi(const QString &fakeWifi)
|
||||
{
|
||||
return setFakeWifiTask(fakeWifi);
|
||||
}
|
||||
|
||||
QString WaydroidDBusClient::fakeWifi() const
|
||||
{
|
||||
return m_fakeWifi;
|
||||
}
|
||||
|
||||
QStringList WaydroidDBusClient::gameShellPackages() const
|
||||
{
|
||||
return m_gameShellPackages;
|
||||
}
|
||||
|
||||
QCoro::Task<void> WaydroidDBusClient::initializeTask(const SystemType systemType, const RomType romType, const bool forced)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->initialize(systemType, romType, forced);
|
||||
}
|
||||
|
||||
|
|
@ -218,6 +448,10 @@ QCoro::QmlTask WaydroidDBusClient::initialize(const SystemType systemType, const
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::startSessionTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->startSession();
|
||||
}
|
||||
|
||||
|
|
@ -228,6 +462,10 @@ QCoro::QmlTask WaydroidDBusClient::startSession()
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::stopSessionTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->stopSession();
|
||||
}
|
||||
|
||||
|
|
@ -238,6 +476,10 @@ QCoro::QmlTask WaydroidDBusClient::stopSession()
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::resetWaydroidTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->resetWaydroid();
|
||||
}
|
||||
|
||||
|
|
@ -248,6 +490,10 @@ QCoro::QmlTask WaydroidDBusClient::resetWaydroid()
|
|||
|
||||
QCoro::Task<void> WaydroidDBusClient::installApkTask(const QString apkFile)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->installApk(apkFile);
|
||||
}
|
||||
|
||||
|
|
@ -256,8 +502,26 @@ QCoro::QmlTask WaydroidDBusClient::installApk(const QString apkFile)
|
|||
return installApkTask(apkFile);
|
||||
}
|
||||
|
||||
QCoro::Task<void> WaydroidDBusClient::launchApplicationTask(const QString appId)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->launchApplication(appId);
|
||||
}
|
||||
|
||||
QCoro::QmlTask WaydroidDBusClient::launchApplication(const QString appId)
|
||||
{
|
||||
return launchApplicationTask(appId);
|
||||
}
|
||||
|
||||
QCoro::Task<void> WaydroidDBusClient::deleteApplicationTask(const QString appId)
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->deleteApplication(appId);
|
||||
}
|
||||
|
||||
|
|
@ -266,6 +530,20 @@ QCoro::QmlTask WaydroidDBusClient::deleteApplication(const QString appId)
|
|||
return deleteApplicationTask(appId);
|
||||
}
|
||||
|
||||
QCoro::Task<void> WaydroidDBusClient::refreshSupportsInfoTask()
|
||||
{
|
||||
if (!m_connected) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
co_await m_interface->refreshSupportsInfo();
|
||||
}
|
||||
|
||||
QCoro::QmlTask WaydroidDBusClient::refreshSupportsInfo()
|
||||
{
|
||||
return refreshSupportsInfoTask();
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::updateStatus()
|
||||
{
|
||||
auto reply = m_interface->status();
|
||||
|
|
@ -275,6 +553,7 @@ void WaydroidDBusClient::updateStatus()
|
|||
QDBusPendingReply<int> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch status:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -299,6 +578,7 @@ void WaydroidDBusClient::updateSessionStatus()
|
|||
QDBusPendingReply<int> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch sessionStatus:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -323,6 +603,7 @@ void WaydroidDBusClient::updateSystemType()
|
|||
QDBusPendingReply<int> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch systemType:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -347,6 +628,7 @@ void WaydroidDBusClient::updateIpAddress()
|
|||
QDBusPendingReply<QString> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch ipAddress:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -371,6 +653,7 @@ void WaydroidDBusClient::updateAndroidId()
|
|||
QDBusPendingReply<QString> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch androidId:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -395,6 +678,7 @@ void WaydroidDBusClient::updateMultiWindows()
|
|||
QDBusPendingReply<bool> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch multiWindows:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -419,6 +703,7 @@ void WaydroidDBusClient::updateSuspend()
|
|||
QDBusPendingReply<bool> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch suspend:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -443,6 +728,7 @@ void WaydroidDBusClient::updateUevent()
|
|||
QDBusPendingReply<bool> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch uevent:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
|
@ -458,7 +744,72 @@ void WaydroidDBusClient::updateUevent()
|
|||
});
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::updateFakeTouch()
|
||||
{
|
||||
auto reply = m_interface->fakeTouch();
|
||||
auto watcher = new QDBusPendingCallWatcher(reply, this);
|
||||
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](auto watcher) {
|
||||
QDBusPendingReply<QString> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch fakeTouch:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
const QString fakeTouch = reply.argumentAt<0>();
|
||||
|
||||
if (m_fakeTouch != fakeTouch) {
|
||||
m_fakeTouch = fakeTouch;
|
||||
Q_EMIT fakeTouchChanged();
|
||||
}
|
||||
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::updateFakeWifi()
|
||||
{
|
||||
auto reply = m_interface->fakeWifi();
|
||||
auto watcher = new QDBusPendingCallWatcher(reply, this);
|
||||
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](auto watcher) {
|
||||
QDBusPendingReply<QString> reply = *watcher;
|
||||
if (!reply.isValid()) {
|
||||
qDebug() << "WaydroidDBusClient: Failed to fetch fakeWifi:" << reply.error().message();
|
||||
handleUnavailableReply();
|
||||
watcher->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
const QString fakeWifi = reply.argumentAt<0>();
|
||||
|
||||
if (m_fakeWifi != fakeWifi) {
|
||||
m_fakeWifi = fakeWifi;
|
||||
Q_EMIT fakeWifiChanged();
|
||||
}
|
||||
|
||||
watcher->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::copyToClipboard(const QString text)
|
||||
{
|
||||
qGuiApp->clipboard()->setText(text);
|
||||
}
|
||||
|
||||
void WaydroidDBusClient::reloadGameShellPackages()
|
||||
{
|
||||
const KConfigGroup group(m_config, s_waydroidGamingGroup);
|
||||
QStringList packages = group.readEntry(s_gameShellPackagesKey, QStringList{});
|
||||
packages.removeDuplicates();
|
||||
packages.sort();
|
||||
|
||||
if (m_gameShellPackages == packages) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_gameShellPackages = packages;
|
||||
Q_EMIT gameShellPackagesChanged();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,12 @@
|
|||
#include "waydroidapplicationlistmodel.h"
|
||||
#include "waydroiddbusobject.h"
|
||||
|
||||
#include <KConfigWatcher>
|
||||
#include <KSharedConfig>
|
||||
|
||||
#include <QCoroCore>
|
||||
#include <QCoroQmlTask>
|
||||
#include <QDBusPendingCallWatcher>
|
||||
#include <QDBusServiceWatcher>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
|
@ -32,6 +36,9 @@ class WaydroidDBusClient : public QObject
|
|||
Q_PROPERTY(bool multiWindows READ multiWindows WRITE setMultiWindows NOTIFY multiWindowsChanged)
|
||||
Q_PROPERTY(bool suspend READ suspend WRITE setSuspend NOTIFY suspendChanged)
|
||||
Q_PROPERTY(bool uevent READ uevent WRITE setUevent NOTIFY ueventChanged)
|
||||
Q_PROPERTY(QString fakeTouch READ fakeTouch WRITE setFakeTouch NOTIFY fakeTouchChanged)
|
||||
Q_PROPERTY(QString fakeWifi READ fakeWifi WRITE setFakeWifi NOTIFY fakeWifiChanged)
|
||||
Q_PROPERTY(QStringList gameShellPackages READ gameShellPackages NOTIFY gameShellPackagesChanged)
|
||||
Q_PROPERTY(WaydroidApplicationListModel *applicationListModel READ applicationListModel CONSTANT)
|
||||
|
||||
public:
|
||||
|
|
@ -98,16 +105,25 @@ public:
|
|||
QCoro::QmlTask setSuspend(const bool suspend);
|
||||
[[nodiscard]] bool uevent() const;
|
||||
QCoro::QmlTask setUevent(const bool uevent);
|
||||
[[nodiscard]] QString fakeTouch() const;
|
||||
QCoro::QmlTask setFakeTouch(const QString &fakeTouch);
|
||||
[[nodiscard]] QString fakeWifi() const;
|
||||
QCoro::QmlTask setFakeWifi(const QString &fakeWifi);
|
||||
[[nodiscard]] QStringList gameShellPackages() const;
|
||||
|
||||
Q_INVOKABLE QCoro::QmlTask initialize(const SystemType systemType, const RomType romType, const bool forced = false);
|
||||
Q_INVOKABLE QCoro::QmlTask startSession();
|
||||
Q_INVOKABLE QCoro::QmlTask stopSession();
|
||||
Q_INVOKABLE QCoro::QmlTask resetWaydroid();
|
||||
Q_INVOKABLE QCoro::QmlTask installApk(const QString apkFile);
|
||||
Q_INVOKABLE QCoro::QmlTask launchApplication(const QString appId);
|
||||
Q_INVOKABLE QCoro::QmlTask deleteApplication(const QString appId);
|
||||
Q_INVOKABLE QCoro::QmlTask refreshSupportsInfo();
|
||||
Q_INVOKABLE QCoro::QmlTask refreshSessionInfo();
|
||||
Q_INVOKABLE QCoro::QmlTask refreshAndroidId();
|
||||
Q_INVOKABLE QCoro::QmlTask refreshApplications();
|
||||
Q_INVOKABLE bool gameShellEnabledForPackage(const QString &packageName) const;
|
||||
Q_INVOKABLE void setGameShellEnabledForPackage(const QString &packageName, bool enabled);
|
||||
|
||||
Q_INVOKABLE void copyToClipboard(const QString text);
|
||||
|
||||
|
|
@ -122,6 +138,9 @@ Q_SIGNALS:
|
|||
void multiWindowsChanged();
|
||||
void suspendChanged();
|
||||
void ueventChanged();
|
||||
void fakeTouchChanged();
|
||||
void fakeWifiChanged();
|
||||
void gameShellPackagesChanged();
|
||||
|
||||
void actionFinished(const QString message);
|
||||
void actionFailed(const QString message);
|
||||
|
|
@ -136,12 +155,14 @@ private Q_SLOTS:
|
|||
void updateMultiWindows();
|
||||
void updateSuspend();
|
||||
void updateUevent();
|
||||
void updateFakeTouch();
|
||||
void updateFakeWifi();
|
||||
|
||||
private:
|
||||
OrgKdePlasmashellWaydroidInterface *m_interface;
|
||||
QDBusServiceWatcher *m_watcher;
|
||||
|
||||
Status m_status{NotInitialized};
|
||||
Status m_status{NotSupported};
|
||||
SessionStatus m_sessionStatus{SessionStopped};
|
||||
SystemType m_systemType{UnknownSystemType};
|
||||
QString m_ipAddress{""};
|
||||
|
|
@ -152,22 +173,40 @@ private:
|
|||
bool m_multiWindows{false};
|
||||
bool m_suspend{false};
|
||||
bool m_uevent{false};
|
||||
QString m_fakeTouch;
|
||||
QString m_fakeWifi;
|
||||
KSharedConfig::Ptr m_config;
|
||||
KConfigWatcher::Ptr m_configWatcher;
|
||||
QStringList m_gameShellPackages;
|
||||
|
||||
bool m_connected{false};
|
||||
bool m_signalsConnected{false};
|
||||
bool m_connectionCheckPending{false};
|
||||
|
||||
void connectSignals();
|
||||
void initializeApplicationListModel();
|
||||
void checkWaydroidObject();
|
||||
void handleUnavailableReply();
|
||||
void onWaydroidObjectCheckFinished(QDBusPendingCallWatcher *watcher);
|
||||
void resetState();
|
||||
void scheduleWaydroidObjectCheck();
|
||||
|
||||
QCoro::Task<void> initializeTask(const SystemType systemType, const RomType romType, const bool forced = false);
|
||||
QCoro::Task<void> startSessionTask();
|
||||
QCoro::Task<void> stopSessionTask();
|
||||
QCoro::Task<void> resetWaydroidTask();
|
||||
QCoro::Task<void> installApkTask(const QString apkFile);
|
||||
QCoro::Task<void> launchApplicationTask(const QString appId);
|
||||
QCoro::Task<void> deleteApplicationTask(const QString appId);
|
||||
QCoro::Task<void> refreshSupportsInfoTask();
|
||||
QCoro::Task<void> setMultiWindowsTask(const bool multiWindows);
|
||||
QCoro::Task<void> setSuspendTask(const bool suspend);
|
||||
QCoro::Task<void> setUeventTask(const bool uevent);
|
||||
QCoro::Task<void> setFakeTouchTask(const QString &fakeTouch);
|
||||
QCoro::Task<void> setFakeWifiTask(const QString &fakeWifi);
|
||||
QCoro::Task<void> refreshSessionInfoTask();
|
||||
QCoro::Task<void> refreshAndroidIdTask();
|
||||
QCoro::Task<void> refreshApplicationsTask();
|
||||
|
||||
void reloadGameShellPackages();
|
||||
};
|
||||
|
|
@ -31,6 +31,8 @@ using namespace Qt::StringLiterals;
|
|||
#define MULTI_WINDOWS_PROP_KEY "persist.waydroid.multi_windows"
|
||||
#define SUSPEND_PROP_KEY "persist.waydroid.suspend"
|
||||
#define UEVENT_PROP_KEY "persist.waydroid.uevent"
|
||||
#define FAKE_TOUCH_PROP_KEY "persist.waydroid.fake_touch"
|
||||
#define FAKE_WIFI_PROP_KEY "persist.waydroid.fake_wifi"
|
||||
|
||||
static const QRegularExpression sessionRegExp(u"Session:\\s*(\\w+)"_s);
|
||||
static const QRegularExpression ipAddressRegExp(u"IP address:\\s*(\\d+\\.\\d+\\.\\d+\\.\\d+)"_s);
|
||||
|
|
@ -179,10 +181,12 @@ void WaydroidDBusObject::stopSession()
|
|||
|
||||
connect(process, &QProcess::finished, this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
Q_UNUSED(exitStatus);
|
||||
const QByteArray errorLog = process->readAllStandardError();
|
||||
process->deleteLater();
|
||||
|
||||
if (exitCode == 0) {
|
||||
qCWarning(WAYDROIDINTEGRATIONPLUGIN) << "Failed to stop the Waydroid session: " << process->readAllStandardError();
|
||||
if (exitCode != 0) {
|
||||
Q_EMIT errorOccurred(i18n("Failed to stop the Waydroid session."), QString::fromUtf8(errorLog));
|
||||
qCWarning(WAYDROIDINTEGRATIONPLUGIN) << "Failed to stop the Waydroid session: " << errorLog;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +254,27 @@ void WaydroidDBusObject::installApk(const QString apkFile)
|
|||
process->start(WAYDROID_COMMAND, arguments);
|
||||
}
|
||||
|
||||
void WaydroidDBusObject::launchApplication(const QString appId)
|
||||
{
|
||||
const QStringList arguments{u"app"_s, u"launch"_s, appId};
|
||||
|
||||
QProcess *process = new QProcess(this);
|
||||
|
||||
connect(process, &QProcess::finished, this, [this, appId, process](int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
const QByteArray errorLog = process->readAllStandardError();
|
||||
process->deleteLater();
|
||||
|
||||
if (exitCode == 0 && exitStatus == QProcess::NormalExit) {
|
||||
Q_EMIT actionFinished(i18n("Application has been launched"));
|
||||
} else {
|
||||
Q_EMIT actionFailed(i18n("Application launch failed"));
|
||||
qCWarning(WAYDROIDINTEGRATIONPLUGIN) << "Error occurred while launching " << appId << ": " << errorLog;
|
||||
}
|
||||
});
|
||||
|
||||
process->start(WAYDROID_COMMAND, arguments);
|
||||
}
|
||||
|
||||
void WaydroidDBusObject::deleteApplication(const QString appId)
|
||||
{
|
||||
const QStringList arguments{u"app"_s, u"remove"_s, appId};
|
||||
|
|
@ -375,6 +400,52 @@ void WaydroidDBusObject::setUevent(const bool uevent)
|
|||
coro(this, value, uevent);
|
||||
}
|
||||
|
||||
QString WaydroidDBusObject::fakeTouch() const
|
||||
{
|
||||
return m_fakeTouch;
|
||||
}
|
||||
|
||||
void WaydroidDBusObject::setFakeTouch(const QString &fakeTouch)
|
||||
{
|
||||
if (m_fakeTouch == fakeTouch) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto coro = [](WaydroidDBusObject *self, QString fakeTouch) -> QCoro::Task<void> {
|
||||
QPointer<WaydroidDBusObject> guard(self);
|
||||
if (co_await self->writePropValue(FAKE_TOUCH_PROP_KEY, fakeTouch)) {
|
||||
if (guard) {
|
||||
self->m_fakeTouch = fakeTouch;
|
||||
Q_EMIT self->fakeTouchChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
coro(this, fakeTouch);
|
||||
}
|
||||
|
||||
QString WaydroidDBusObject::fakeWifi() const
|
||||
{
|
||||
return m_fakeWifi;
|
||||
}
|
||||
|
||||
void WaydroidDBusObject::setFakeWifi(const QString &fakeWifi)
|
||||
{
|
||||
if (m_fakeWifi == fakeWifi) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto coro = [](WaydroidDBusObject *self, QString fakeWifi) -> QCoro::Task<void> {
|
||||
QPointer<WaydroidDBusObject> guard(self);
|
||||
if (co_await self->writePropValue(FAKE_WIFI_PROP_KEY, fakeWifi)) {
|
||||
if (guard) {
|
||||
self->m_fakeWifi = fakeWifi;
|
||||
Q_EMIT self->fakeWifiChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
coro(this, fakeWifi);
|
||||
}
|
||||
|
||||
QList<QDBusObjectPath> WaydroidDBusObject::applications() const
|
||||
{
|
||||
QList<QDBusObjectPath> paths;
|
||||
|
|
@ -513,6 +584,7 @@ void WaydroidDBusObject::refreshAndroidId()
|
|||
}
|
||||
} else {
|
||||
m_androidId = "";
|
||||
Q_EMIT actionFailed(i18n("Failed to fetch Android ID"));
|
||||
qCWarning(WAYDROIDINTEGRATIONPLUGIN) << "KAuth returned an error code:" << executeJob->error();
|
||||
}
|
||||
|
||||
|
|
@ -539,6 +611,12 @@ QCoro::Task<void> WaydroidDBusObject::refreshPropsInfo()
|
|||
const QString ueventPropValue = co_await fetchPropValue(UEVENT_PROP_KEY, "false");
|
||||
m_uevent = ueventPropValue == "true";
|
||||
Q_EMIT ueventChanged();
|
||||
|
||||
m_fakeTouch = co_await fetchPropValue(FAKE_TOUCH_PROP_KEY, QString{});
|
||||
Q_EMIT fakeTouchChanged();
|
||||
|
||||
m_fakeWifi = co_await fetchPropValue(FAKE_WIFI_PROP_KEY, QString{});
|
||||
Q_EMIT fakeWifiChanged();
|
||||
}
|
||||
|
||||
QCoro::Task<QString> WaydroidDBusObject::fetchPropValue(const QString key, const QString defaultValue)
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ Q_SIGNALS:
|
|||
Q_SCRIPTABLE void multiWindowsChanged();
|
||||
Q_SCRIPTABLE void suspendChanged();
|
||||
Q_SCRIPTABLE void ueventChanged();
|
||||
Q_SCRIPTABLE void fakeTouchChanged();
|
||||
Q_SCRIPTABLE void fakeWifiChanged();
|
||||
|
||||
Q_SCRIPTABLE void applicationAdded(QDBusObjectPath path);
|
||||
Q_SCRIPTABLE void applicationRemoved(QDBusObjectPath path);
|
||||
|
|
@ -119,6 +121,10 @@ public Q_SLOTS:
|
|||
Q_SCRIPTABLE void setSuspend(const bool suspend);
|
||||
Q_SCRIPTABLE bool uevent() const;
|
||||
Q_SCRIPTABLE void setUevent(const bool uevent);
|
||||
Q_SCRIPTABLE QString fakeTouch() const;
|
||||
Q_SCRIPTABLE void setFakeTouch(const QString &fakeTouch);
|
||||
Q_SCRIPTABLE QString fakeWifi() const;
|
||||
Q_SCRIPTABLE void setFakeWifi(const QString &fakeWifi);
|
||||
Q_SCRIPTABLE QList<QDBusObjectPath> applications() const;
|
||||
|
||||
Q_SCRIPTABLE void initialize(const int systemType, const int romType, const bool forced = false);
|
||||
|
|
@ -126,7 +132,9 @@ public Q_SLOTS:
|
|||
Q_SCRIPTABLE void stopSession();
|
||||
Q_SCRIPTABLE void resetWaydroid();
|
||||
Q_SCRIPTABLE void installApk(const QString apkFile);
|
||||
Q_SCRIPTABLE void launchApplication(const QString appId);
|
||||
Q_SCRIPTABLE void deleteApplication(const QString appId);
|
||||
Q_SCRIPTABLE void refreshSupportsInfo();
|
||||
Q_SCRIPTABLE void refreshSessionInfo();
|
||||
Q_SCRIPTABLE void refreshAndroidId();
|
||||
Q_SCRIPTABLE void refreshApplications();
|
||||
|
|
@ -143,8 +151,9 @@ private:
|
|||
bool m_multiWindows{false};
|
||||
bool m_suspend{false};
|
||||
bool m_uevent{false};
|
||||
QString m_fakeTouch;
|
||||
QString m_fakeWifi;
|
||||
|
||||
void refreshSupportsInfo();
|
||||
void refreshInstallationInfo();
|
||||
QCoro::Task<void> refreshPropsInfo();
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,45 @@ import org.kde.plasma.private.mobileshell.waydroidintegrationplugin as AIP
|
|||
KCM.SimpleKCM {
|
||||
id: root
|
||||
|
||||
function packagePatterns(value: string): var {
|
||||
if (value === "") {
|
||||
return []
|
||||
}
|
||||
|
||||
return value.split(",")
|
||||
.map(pattern => pattern.trim())
|
||||
.filter(pattern => pattern !== "")
|
||||
}
|
||||
|
||||
function wildcardRegExp(pattern: string): RegExp {
|
||||
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&")
|
||||
return new RegExp("^" + escaped.replace(/\*/g, ".*") + "$")
|
||||
}
|
||||
|
||||
function hasExactPackage(value: string, packageName: string): bool {
|
||||
return packagePatterns(value).includes(packageName)
|
||||
}
|
||||
|
||||
function hasWildcardPackage(value: string, packageName: string): bool {
|
||||
return packagePatterns(value)
|
||||
.filter(pattern => pattern.includes("*"))
|
||||
.some(pattern => wildcardRegExp(pattern).test(packageName))
|
||||
}
|
||||
|
||||
function hasEffectivePackage(value: string, packageName: string): bool {
|
||||
return hasExactPackage(value, packageName) || hasWildcardPackage(value, packageName)
|
||||
}
|
||||
|
||||
function updateExactPackage(value: string, packageName: string, enabled: bool): string {
|
||||
const updatedPatterns = packagePatterns(value).filter(pattern => pattern !== packageName)
|
||||
|
||||
if (enabled) {
|
||||
updatedPatterns.push(packageName)
|
||||
}
|
||||
|
||||
return updatedPatterns.join(",")
|
||||
}
|
||||
|
||||
topPadding: Kirigami.Units.largeSpacing
|
||||
bottomPadding: Kirigami.Units.largeSpacing
|
||||
leftPadding: 0
|
||||
|
|
@ -74,6 +113,7 @@ KCM.SimpleKCM {
|
|||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: AIP.WaydroidDBusClient.status === AIP.WaydroidDBusClient.Initialized
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
Kirigami.InlineMessage {
|
||||
|
|
@ -85,6 +125,11 @@ KCM.SimpleKCM {
|
|||
showCloseButton: true
|
||||
}
|
||||
|
||||
Kirigami.PlaceholderMessage {
|
||||
Layout.fillWidth: true
|
||||
explanation: i18n("This page manages the launchers exported by Waydroid. Enable Show in Game Shell for Android apps you want listed in Game Center's Waydroid tab. Touch and Wi-Fi toggles add or remove exact package names from Waydroid's documented compatibility property lists. Wildcard rules remain in the main Waydroid properties page.")
|
||||
}
|
||||
|
||||
FormCard.FormCard {
|
||||
Repeater {
|
||||
model: AIP.WaydroidDBusClient.applicationListModel
|
||||
|
|
@ -95,23 +140,105 @@ KCM.SimpleKCM {
|
|||
width: ListView.view.width
|
||||
|
||||
background: null
|
||||
contentItem: RowLayout {
|
||||
QQC2.Label {
|
||||
contentItem: ColumnLayout {
|
||||
spacing: Kirigami.Units.smallSpacing
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
text: model.name
|
||||
elide: Text.ElideRight
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.name
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
text: i18nc("@action:button", "Launch the application")
|
||||
icon.name: "media-playback-start"
|
||||
|
||||
onClicked: AIP.WaydroidDBusClient.launchApplication(model.id)
|
||||
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
text: i18nc("@action:button", "Delete the application")
|
||||
icon.name: "usermenu-delete"
|
||||
|
||||
onClicked: AIP.WaydroidDBusClient.deleteApplication(model.id)
|
||||
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.ToolButton {
|
||||
display: QQC2.AbstractButton.IconOnly
|
||||
text: i18nc("@action:button", "Delete the application")
|
||||
icon.name: "usermenu-delete"
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
onClicked: AIP.WaydroidDBusClient.deleteApplication(model.id)
|
||||
QQC2.CheckBox {
|
||||
text: i18n("Show in Game Shell")
|
||||
checked: AIP.WaydroidDBusClient.gameShellPackages.indexOf(model.id) !== -1
|
||||
|
||||
QQC2.ToolTip.visible: hovered
|
||||
QQC2.ToolTip.text: text
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
onClicked: AIP.WaydroidDBusClient.setGameShellEnabledForPackage(model.id, checked)
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: i18n("Adds this app to the Game Shell allowlist so it appears in Game Center under Waydroid.")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
QQC2.CheckBox {
|
||||
id: fakeTouchToggle
|
||||
text: i18n("Touch")
|
||||
checked: root.hasEffectivePackage(AIP.WaydroidDBusClient.fakeTouch, model.id)
|
||||
enabled: !root.hasWildcardPackage(AIP.WaydroidDBusClient.fakeTouch, model.id)
|
||||
|
||||
onClicked: {
|
||||
AIP.WaydroidDBusClient.fakeTouch = root.updateExactPackage(AIP.WaydroidDBusClient.fakeTouch, model.id, checked)
|
||||
}
|
||||
|
||||
QQC2.ToolTip.visible: hovered && !enabled
|
||||
QQC2.ToolTip.text: i18n("Managed by a wildcard pattern in Waydroid properties")
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
|
||||
QQC2.CheckBox {
|
||||
id: fakeWifiToggle
|
||||
text: i18n("Wi-Fi")
|
||||
checked: root.hasEffectivePackage(AIP.WaydroidDBusClient.fakeWifi, model.id)
|
||||
enabled: !root.hasWildcardPackage(AIP.WaydroidDBusClient.fakeWifi, model.id)
|
||||
|
||||
onClicked: {
|
||||
AIP.WaydroidDBusClient.fakeWifi = root.updateExactPackage(AIP.WaydroidDBusClient.fakeWifi, model.id, checked)
|
||||
}
|
||||
|
||||
QQC2.ToolTip.visible: hovered && !enabled
|
||||
QQC2.ToolTip.text: i18n("Managed by a wildcard pattern in Waydroid properties")
|
||||
QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
|
||||
}
|
||||
}
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
visible: !fakeTouchToggle.enabled || !fakeWifiToggle.enabled
|
||||
wrapMode: Text.WordWrap
|
||||
color: Kirigami.Theme.disabledTextColor
|
||||
text: i18n("One or more compatibility settings for this app come from a wildcard rule. Edit the global Waydroid property to change that rule.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -121,4 +248,22 @@ KCM.SimpleKCM {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: AIP.WaydroidDBusClient.status !== AIP.WaydroidDBusClient.Initialized
|
||||
anchors.centerIn: parent
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
QQC2.Label {
|
||||
text: i18n("Waydroid is unavailable")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
PC3.Button {
|
||||
text: i18n("Check again")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: AIP.WaydroidDBusClient.refreshSupportsInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ import org.kde.plasma.private.mobileshell.waydroidintegrationplugin as AIP
|
|||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
visible: AIP.WaydroidDBusClient.status === AIP.WaydroidDBusClient.Initialized
|
||||
&& AIP.WaydroidDBusClient.sessionStatus === AIP.WaydroidDBusClient.SessionRunning
|
||||
|
||||
function packagePatternSummary(value: string): string {
|
||||
return value === "" ? i18n("Not set") : value
|
||||
}
|
||||
|
||||
FormCard.FormHeader {
|
||||
title: i18n("General information")
|
||||
}
|
||||
|
|
@ -66,6 +73,64 @@ ColumnLayout {
|
|||
onAccepted: AIP.WaydroidDBusClient.resetWaydroid()
|
||||
}
|
||||
|
||||
Kirigami.PromptDialog {
|
||||
id: fakeTouchDialog
|
||||
title: i18n("Touch input override")
|
||||
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
|
||||
|
||||
onOpened: {
|
||||
fakeTouchField.text = AIP.WaydroidDBusClient.fakeTouch
|
||||
fakeTouchField.forceActiveFocus()
|
||||
}
|
||||
|
||||
onAccepted: AIP.WaydroidDBusClient.fakeTouch = fakeTouchField.text.trim()
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: i18n("Comma-separated package names for apps where mouse input should be interpreted as touch. Supports * wildcards. Leave empty to clear the override.")
|
||||
}
|
||||
|
||||
QQC2.TextField {
|
||||
id: fakeTouchField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: "com.rovio.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kirigami.PromptDialog {
|
||||
id: fakeWifiDialog
|
||||
title: i18n("Wi-Fi override")
|
||||
standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel
|
||||
|
||||
onOpened: {
|
||||
fakeWifiField.text = AIP.WaydroidDBusClient.fakeWifi
|
||||
fakeWifiField.forceActiveFocus()
|
||||
}
|
||||
|
||||
onAccepted: AIP.WaydroidDBusClient.fakeWifi = fakeWifiField.text.trim()
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
QQC2.Label {
|
||||
Layout.fillWidth: true
|
||||
wrapMode: Text.WordWrap
|
||||
text: i18n("Comma-separated package names for apps that should always appear to be on Wi-Fi. Supports * wildcards. Leave empty to clear the override.")
|
||||
}
|
||||
|
||||
QQC2.TextField {
|
||||
id: fakeWifiField
|
||||
Layout.fillWidth: true
|
||||
placeholderText: "com.gameloft.*"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Some information such as IP address can take time to be set by Waydroid
|
||||
|
|
@ -140,5 +205,29 @@ ColumnLayout {
|
|||
infoMessage.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator { above: uevent; below: fakeTouch }
|
||||
|
||||
FormCard.FormTextDelegate {
|
||||
id: fakeTouch
|
||||
text: i18n("Touch input override")
|
||||
description: root.packagePatternSummary(AIP.WaydroidDBusClient.fakeTouch)
|
||||
trailing: PC3.Button {
|
||||
text: i18n("Edit")
|
||||
onClicked: fakeTouchDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
FormCard.FormDelegateSeparator { above: fakeTouch; below: fakeWifi }
|
||||
|
||||
FormCard.FormTextDelegate {
|
||||
id: fakeWifi
|
||||
text: i18n("Wi-Fi override")
|
||||
description: root.packagePatternSummary(AIP.WaydroidDBusClient.fakeWifi)
|
||||
trailing: PC3.Button {
|
||||
text: i18n("Edit")
|
||||
onClicked: fakeWifiDialog.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ KCM.SimpleKCM {
|
|||
}
|
||||
|
||||
WaydroidLoader {
|
||||
visible: AIP.WaydroidDBusClient.androidId === ""
|
||||
visible: AIP.WaydroidDBusClient.status === AIP.WaydroidDBusClient.Initialized
|
||||
&& AIP.WaydroidDBusClient.androidId === ""
|
||||
&& !inlineMessage.visible
|
||||
text: i18n("Fetching your Android ID.\nIt can take a few seconds.")
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +55,8 @@ KCM.SimpleKCM {
|
|||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: AIP.WaydroidDBusClient.androidId !== ""
|
||||
visible: AIP.WaydroidDBusClient.status === AIP.WaydroidDBusClient.Initialized
|
||||
&& AIP.WaydroidDBusClient.androidId !== ""
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent
|
||||
anchors.leftMargin: Kirigami.Units.largeSpacing
|
||||
|
|
@ -76,4 +79,22 @@ KCM.SimpleKCM {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: AIP.WaydroidDBusClient.status !== AIP.WaydroidDBusClient.Initialized
|
||||
anchors.centerIn: parent
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
QQC2.Label {
|
||||
text: i18n("Waydroid is unavailable")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
}
|
||||
|
||||
QQC2.Button {
|
||||
text: i18n("Check again")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: AIP.WaydroidDBusClient.refreshSupportsInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ KCM.SimpleKCM {
|
|||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
QQC2.Label {
|
||||
text: i18n("Waydroid is not installed")
|
||||
text: i18n("Waydroid is unavailable")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
}
|
||||
|
||||
PC3.Button {
|
||||
text: i18n("Check installation")
|
||||
text: i18n("Check again")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
onClicked: AIP.WaydroidDBusClient.refreshSupportsInfo()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue