SPDX-FileCopyrightText: 2013 Alexander Mezin <mezin.alexander@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "kded.h"
#include <KConfigGroup>
#include <KPluginFactory>
#include <KSharedConfig>
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QDBusMessage>
#include <QDebug>
using namespace Qt::Literals::StringLiterals;
K_PLUGIN_CLASS_WITH_JSON(TouchpadDisabler, "kded_touchpad.json")
void migrateConfig(TouchpadBackend *backend)
{
if (!backend->isTouchpadAvailable()) {
return;
}
#if BUILD_KCM_TOUCHPAD_X11
if (backend->getMode() != TouchpadInputBackendMode::XLibinput) {
return;
}
#else
return;
#endif
KSharedConfig::Ptr oldConfig = KSharedConfig::openConfig(u"touchpadrc"_s);
const KConfigGroup oldGroup = oldConfig->group(u"autodisable"_s);
if (!oldGroup.exists()) {
return;
}
bool disableWhenMousePluggedIn = oldGroup.readEntry("DisableWhenMousePluggedIn", false);
bool disableOnKeyboardActivity = oldGroup.readEntry("DisableOnKeyboardActivity", true);
backend->load();
for (LibinputCommon *device : backend->inputDevices()) {
if (device->supportsDisableEventsOnExternalMouse()) {
device->setDisableEventsOnExternalMouse(disableWhenMousePluggedIn);
}
if (!disableOnKeyboardActivity && device->supportsDisableWhileTyping()) {
device->setDisableWhileTyping(false);
}
}
backend->save();
oldConfig->deleteGroup(u"autodisable"_s);
oldConfig->sync();
}
void TouchpadDisabler::serviceRegistered(const QString &service)
{
if (!m_dependencies.removeWatchedService(service)) {
return;
}
if (m_dependencies.watchedServices().isEmpty()) {
lateInit();
}
}
TouchpadDisabler::TouchpadDisabler(QObject *parent, const QVariantList &)
: KDEDModule(parent)
, m_backend(TouchpadBackend::implementation())
{
if (!m_backend) {
return;
}
migrateConfig(m_backend);
QDBusConnection::sessionBus().registerService(u"org.kde.touchpad"_s);
m_dependencies.addWatchedService("org.kde.plasmashell");
connect(&m_dependencies, &QDBusServiceWatcher::serviceRegistered, this, &TouchpadDisabler::serviceRegistered);
connect(m_backend, &TouchpadBackend::touchpadStateChanged, this, &TouchpadDisabler::updateCurrentState);
connect(m_backend, &TouchpadBackend::touchpadReset, this, &TouchpadDisabler::handleReset);
updateCurrentState();
m_userRequestedSuspend = m_touchpadSuspended;
m_dependencies.setWatchMode(QDBusServiceWatcher::WatchForRegistration);
m_dependencies.setConnection(QDBusConnection::sessionBus());
QDBusPendingCall async = QDBusConnection::sessionBus().interface()->asyncCall(QLatin1String("ListNames"));
QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(async, this);
connect(callWatcher, &QDBusPendingCallWatcher::finished, this, &TouchpadDisabler::serviceNameFetchFinished);
QDBusConnection::systemBus().connect(QStringLiteral("org.freedesktop.login1"),
QStringLiteral("/org/freedesktop/login1"),
QStringLiteral("org.freedesktop.login1.Manager"),
QStringLiteral("PrepareForSleep"),
this,
SLOT(onPrepareForSleep(bool)));
}
void TouchpadDisabler::serviceNameFetchFinished(QDBusPendingCallWatcher *callWatcher)
{
QDBusPendingReply<QStringList> reply = *callWatcher;
callWatcher->deleteLater();
if (reply.isError() || reply.value().isEmpty()) {
qWarning() << "Error: Couldn't get registered services list from session bus";
return;
}
const QStringList allServices = reply.value();
const QStringList watchedList = m_dependencies.watchedServices();
for (const QString &service : watchedList) {
if (allServices.contains(service)) {
serviceRegistered(service);
}
}
}
void TouchpadDisabler::updateCurrentState()
{
if (!m_backend->isTouchpadAvailable()) {
return;
}
m_touchpadSuspended = m_backend->isTouchpadSuspended();
}
void TouchpadDisabler::toggle()
{
m_userRequestedSuspend = !m_touchpadSuspended;
m_backend->setTouchpadSuspended(m_userRequestedSuspend);
showOsd();
}
void TouchpadDisabler::disable()
{
m_userRequestedSuspend = true;
m_backend->setTouchpadSuspended(true);
showOsd();
}
void TouchpadDisabler::enable()
{
m_userRequestedSuspend = false;
m_backend->setTouchpadSuspended(false);
showOsd();
}
void TouchpadDisabler::lateInit()
{
updateCurrentState();
}
void TouchpadDisabler::handleReset()
{
updateCurrentState();
if (!m_backend->isTouchpadAvailable()) {
return;
}
m_backend->setTouchpadSuspended(m_userRequestedSuspend);
}
void TouchpadDisabler::onPrepareForSleep(bool sleep)
{
m_preparingForSleep = sleep;
}
void TouchpadDisabler::showOsd()
{
if (m_preparingForSleep) {
return;
}
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.plasmashell"),
QStringLiteral("/org/kde/osdService"),
QStringLiteral("org.kde.osdService"),
QStringLiteral("touchpadEnabledChanged"));
msg.setArguments({!m_backend->isTouchpadSuspended()});
QDBusConnection::sessionBus().asyncCall(msg);
}
#include "kded.moc"
#include "moc_kded.cpp"