Report unavailable protocols and services; send combos as real keys
Diagnostics collects what this session doesn't allow, logs it, and lists it in the settings panel (with a dot on the gear): KWin not launching sloposk as its keyboard (detected by WAYLAND_SOCKET, since KWin offers the input-method global to every client), fake input missing or too old, org.kde.keyboard unreachable, and the D-Bus control name taken. Modifier combos go through fake input even in text fields: KWin drops the input method's modifier mask for most clients, so Ctrl+A typed "a". The desktop file is generated with an absolute Exec, which KWin needs to match it: one for the installed binary, one for the build's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#include "Checks.h"
|
||||
|
||||
#include "SystemLayouts.h"
|
||||
#include "backend/KWinInputMethod.h"
|
||||
#include "diagnostics/Diagnostics.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
namespace {
|
||||
|
||||
QString tr(const char *text)
|
||||
{
|
||||
return QCoreApplication::translate("Checks", text);
|
||||
}
|
||||
|
||||
QString fakeInputProblem(const KWinFakeInput &fakeInput)
|
||||
{
|
||||
const QString lost = tr("Hold Keys, shortcuts like Ctrl+A and typing outside text fields don't work.");
|
||||
if (!fakeInput.isActive())
|
||||
return tr("KWin doesn't let sloposk send key events (it allows the virtual keyboard it launched). ") + lost;
|
||||
return tr("KWin's fake input is too old (version %1, needs %2). ")
|
||||
.arg(fakeInput.boundVersion())
|
||||
.arg(KWinFakeInput::RequiredVersion)
|
||||
+ lost;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void watchInputMethod(Diagnostics &diagnostics, const KWinInputMethod &backend, bool launchedByKWin)
|
||||
{
|
||||
// Qt binds globals KWin already announced on construction, so the first
|
||||
// check is final unless KWin restarts.
|
||||
const auto checkInputMethod = [&] {
|
||||
diagnostics.check(QStringLiteral("input-method"), launchedByKWin && backend.isAvailable(),
|
||||
tr("Not running as KWin's virtual keyboard, so it can't type into text fields: "
|
||||
"choose sloposk in System Settings → Keyboard → Virtual Keyboard."));
|
||||
};
|
||||
const KWinFakeInput &fakeInput = backend.fakeInput();
|
||||
const auto checkFakeInput = [&] {
|
||||
diagnostics.check(QStringLiteral("fake-input"), fakeInput.canSendKeysyms(), fakeInputProblem(fakeInput));
|
||||
};
|
||||
QObject::connect(&backend, &KWinInputMethod::availableChanged, &diagnostics, checkInputMethod);
|
||||
QObject::connect(&fakeInput, &QWaylandClientExtension::activeChanged, &diagnostics, checkFakeInput);
|
||||
checkInputMethod();
|
||||
checkFakeInput();
|
||||
}
|
||||
|
||||
void watchSystemLayouts(Diagnostics &diagnostics, const SystemLayouts &layouts)
|
||||
{
|
||||
QObject::connect(&layouts, &SystemLayouts::serviceChecked, &diagnostics, [&](bool available) {
|
||||
diagnostics.check(QStringLiteral("system-layouts"), available,
|
||||
tr("KWin's keyboard layout service (org.kde.keyboard) isn't reachable: "
|
||||
"the globe key switches only the on-screen layout."));
|
||||
});
|
||||
}
|
||||
|
||||
void reportDBusControl(Diagnostics &diagnostics, bool registered)
|
||||
{
|
||||
diagnostics.check(QStringLiteral("dbus-control"), registered,
|
||||
tr("Couldn't claim org.sloposk.Keyboard on D-Bus (is another sloposk running?): "
|
||||
"show/hide commands won't reach this one."));
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
class Diagnostics;
|
||||
class KWinInputMethod;
|
||||
class SystemLayouts;
|
||||
|
||||
// Reports to `diagnostics` what this session doesn't allow, and keeps the
|
||||
// reports current as protocols and services come and go.
|
||||
// KWin offers the input-method global to every client but only activates
|
||||
// the process it launched, which it hands a connection: `launchedByKWin` is
|
||||
// whether WAYLAND_SOCKET was set at startup.
|
||||
void watchInputMethod(Diagnostics &diagnostics, const KWinInputMethod &backend, bool launchedByKWin);
|
||||
void watchSystemLayouts(Diagnostics &diagnostics, const SystemLayouts &layouts);
|
||||
void reportDBusControl(Diagnostics &diagnostics, bool registered);
|
||||
@@ -27,7 +27,7 @@ SystemLayouts::SystemLayouts(QObject *parent)
|
||||
bus.connect(Service, Path, Interface, QStringLiteral("layoutChanged"), this, SLOT(setCurrent(uint)));
|
||||
auto *watcher = new QDBusServiceWatcher(Service, bus, QDBusServiceWatcher::WatchForOwnerChange, this);
|
||||
connect(watcher, &QDBusServiceWatcher::serviceRegistered, this, &SystemLayouts::fetchCurrent);
|
||||
connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, [this] { m_system = false; });
|
||||
connect(watcher, &QDBusServiceWatcher::serviceUnregistered, this, [this] { setSystem(false); });
|
||||
fetchCurrent();
|
||||
}
|
||||
|
||||
@@ -38,10 +38,9 @@ void SystemLayouts::fetchCurrent()
|
||||
connect(watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
|
||||
watcher->deleteLater();
|
||||
const QDBusPendingReply<uint> reply = *watcher;
|
||||
if (reply.isError())
|
||||
return;
|
||||
m_system = true;
|
||||
setCurrent(reply.value());
|
||||
setSystem(!reply.isError());
|
||||
if (m_system)
|
||||
setCurrent(reply.value());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -56,6 +55,12 @@ void SystemLayouts::next(quint32 count)
|
||||
setCurrent(index);
|
||||
}
|
||||
|
||||
void SystemLayouts::setSystem(bool system)
|
||||
{
|
||||
m_system = system;
|
||||
Q_EMIT serviceChecked(system);
|
||||
}
|
||||
|
||||
void SystemLayouts::setCurrent(uint index)
|
||||
{
|
||||
if (index == m_current)
|
||||
|
||||
@@ -19,12 +19,15 @@ public:
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentChanged();
|
||||
// After each attempt to reach the service, and when it goes away.
|
||||
void serviceChecked(bool available);
|
||||
|
||||
private Q_SLOTS:
|
||||
void setCurrent(uint index);
|
||||
|
||||
private:
|
||||
void fetchCurrent();
|
||||
void setSystem(bool system);
|
||||
|
||||
bool m_system = false;
|
||||
quint32 m_current = 0;
|
||||
|
||||
Reference in New Issue
Block a user