Files
sloposk/src/input/DeadKeys.cpp
T
ericek111andClaude Opus 5.5 23e957660f Reword code comments in plain technical language
Comments only, no code changes. Replaces vague or personified phrasing
with explicit statements of what the code does and why, uses bullet
lists for multi-case behavior, and fixes the settings path in
WindowSettings.h (~/.config/sloposk/sloposk.conf).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:58:59 +01:00

92 lines
2.6 KiB
C++

#include "DeadKeys.h"
#include "layout/KeymapKeys.h"
#include <xkbcommon/xkbcommon-compose.h>
#include <xkbcommon/xkbcommon.h>
namespace {
QByteArray systemLocale()
{
for (const char *name : {"LC_ALL", "LC_CTYPE", "LANG"}) {
if (const QByteArray value = qgetenv(name); !value.isEmpty())
return value;
}
return "C";
}
} // namespace
DeadKeys::DeadKeys(const QString &locale)
: m_context(xkb_context_new(XKB_CONTEXT_NO_FLAGS), xkb_context_unref)
, m_table(nullptr, xkb_compose_table_unref)
, m_state(nullptr, xkb_compose_state_unref)
{
// The C locale has no compose table; en_US.UTF-8's is the common base of all.
const QByteArray name = locale.isEmpty() ? systemLocale() : locale.toUtf8();
for (const QByteArray &candidate : {name, QByteArrayLiteral("en_US.UTF-8")}) {
m_table.reset(xkb_compose_table_new_from_locale(m_context.get(), candidate.constData(),
XKB_COMPOSE_COMPILE_NO_FLAGS));
if (m_table)
break;
}
if (m_table)
m_state.reset(xkb_compose_state_new(m_table.get(), XKB_COMPOSE_STATE_NO_FLAGS));
}
DeadKeys::~DeadKeys() = default;
QString DeadKeys::press(quint32 deadKeysym)
{
if (!m_state) {
m_pending += deadKeyText(deadKeysym);
return {};
}
xkb_compose_state_feed(m_state.get(), deadKeysym);
switch (xkb_compose_state_get_status(m_state.get())) {
case XKB_COMPOSE_COMPOSED: {
const QString composed = composedText();
cancel();
return composed;
}
case XKB_COMPOSE_CANCELLED: {
// No compose sequence continues with this key: flush the pending accents
// and start a new sequence.
const QString accents = m_pending;
cancel();
return accents + press(deadKeysym);
}
default:
m_pending += deadKeyText(deadKeysym);
return {};
}
}
QString DeadKeys::composedText() const
{
char utf8[64];
xkb_compose_state_get_utf8(m_state.get(), utf8, sizeof utf8);
return QString::fromUtf8(utf8);
}
QString DeadKeys::compose(const QString &text)
{
QString result = m_pending + text;
if (m_state && !text.isEmpty()) {
const char32_t ucs = text.toUcs4().first();
xkb_compose_state_feed(m_state.get(), xkb_utf32_to_keysym(ucs));
if (xkb_compose_state_get_status(m_state.get()) == XKB_COMPOSE_COMPOSED)
result = composedText() + text.mid(QString::fromUcs4(&ucs, 1).size());
}
cancel();
return result;
}
void DeadKeys::cancel()
{
m_pending.clear();
if (m_state)
xkb_compose_state_reset(m_state.get());
}