Fix double-space period, shift double-tap; settings; letters from system keymap

- Double-space replaced the space via a Backspace keysym, which clients
  apply after the commit: use delete_surrounding_text with the commit
- Tests use a shared FakeEngine that applies ops to a simulated field
- Double-tap shift locks at a sentence start; typing between taps doesn't
- Organization name set: config lives in ~/.config/sloposk/
- Settings (auto-capitalization, double-space period) with a ⚙ panel
- Letter rows come from the compositor's XKB keymap; other letters of the
  layout become long-press alternates; globe switches the system layout
  over org.kde.keyboard
- One JSON template for non-letter layers; stretch keys even out rows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 20:28:39 +02:00
co-authored by Claude Opus 5.5
parent c6c977eb4c
commit 5277ab16ff
49 changed files with 1162 additions and 359 deletions
+49
View File
@@ -0,0 +1,49 @@
#include "SystemLayouts.h"
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusReply>
namespace {
const QString Service = QStringLiteral("org.kde.keyboard");
const QString Path = QStringLiteral("/Layouts");
const QString Interface = QStringLiteral("org.kde.KeyboardLayouts");
QDBusMessage call(const QString &method, const QVariantList &args = {})
{
QDBusMessage message = QDBusMessage::createMethodCall(Service, Path, Interface, method);
message.setArguments(args);
return message;
}
} // namespace
SystemLayouts::SystemLayouts(QObject *parent)
: QObject(parent)
{
QDBusConnection bus = QDBusConnection::sessionBus();
const QDBusReply<uint> reply = bus.call(call(QStringLiteral("getLayout")));
m_system = reply.isValid();
if (!m_system)
return;
m_current = reply.value();
bus.connect(Service, Path, Interface, QStringLiteral("layoutChanged"), this, SLOT(setCurrent(uint)));
}
void SystemLayouts::next(quint32 count)
{
if (count < 2)
return;
const quint32 index = (m_current + 1) % count;
if (m_system)
QDBusConnection::sessionBus().asyncCall(call(QStringLiteral("setLayout"), {index})); // echoes layoutChanged
else
setCurrent(index);
}
void SystemLayouts::setCurrent(uint index)
{
if (index == m_current)
return;
m_current = index;
Q_EMIT currentChanged();
}
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <QObject>
// Which of the system's keyboard layouts is active, followed and switched
// over KWin's org.kde.keyboard D-Bus interface, so the on-screen and the
// physical keyboard always agree. Without that service it switches locally.
class SystemLayouts : public QObject
{
Q_OBJECT
public:
explicit SystemLayouts(QObject *parent = nullptr);
quint32 current() const { return m_current; }
// Switches to the next of `count` layouts.
void next(quint32 count);
Q_SIGNALS:
void currentChanged();
private Q_SLOTS:
void setCurrent(uint index);
private:
bool m_system = false;
quint32 m_current = 0;
};