diff --git a/CMakeLists.txt b/CMakeLists.txt
index 06aa83c88a..69daa8ec01 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -158,7 +158,7 @@ if(Wayland_Egl_FOUND)
set(HAVE_WAYLAND_EGL TRUE)
endif()
-find_package(XKB 0.4.1)
+find_package(XKB 0.5.0)
set_package_properties(XKB PROPERTIES
TYPE REQUIRED
PURPOSE "Required for building KWin with Wayland support"
diff --git a/keyboard_input.cpp b/keyboard_input.cpp
index cf4dc00ea6..25ee022d30 100644
--- a/keyboard_input.cpp
+++ b/keyboard_input.cpp
@@ -42,6 +42,7 @@ along with this program. If not, see .
#include
// xkbcommon
#include
+#include
#include
// system
#include
@@ -90,12 +91,31 @@ Xkb::Xkb(InputRedirection *input)
, m_altModifier(0)
, m_metaModifier(0)
, m_modifiers(Qt::NoModifier)
+ , m_keysym(XKB_KEY_NoSymbol)
{
if (!m_context) {
qCDebug(KWIN_XKB) << "Could not create xkb context";
} else {
xkb_context_set_log_level(m_context, XKB_LOG_LEVEL_DEBUG);
xkb_context_set_log_fn(m_context, &xkbLogHandler);
+
+ // get locale as described in xkbcommon doc
+ // cannot use QLocale as it drops the modifier part
+ QByteArray locale = qgetenv("LC_ALL");
+ if (locale.isEmpty()) {
+ locale = qgetenv("LC_CTYPE");
+ }
+ if (locale.isEmpty()) {
+ locale = qgetenv("LANG");
+ }
+ if (locale.isEmpty()) {
+ locale = QByteArrayLiteral("C");
+ }
+
+ m_compose.table = xkb_compose_table_new_from_locale(m_context, locale.constData(), XKB_COMPOSE_COMPILE_NO_FLAGS);
+ if (m_compose.table) {
+ m_compose.state = xkb_compose_state_new(m_compose.table, XKB_COMPOSE_STATE_NO_FLAGS);
+ }
}
auto resetModOnlyShortcut = [this] {
@@ -108,6 +128,8 @@ Xkb::Xkb(InputRedirection *input)
Xkb::~Xkb()
{
+ xkb_compose_state_unref(m_compose.state);
+ xkb_compose_table_unref(m_compose.table);
xkb_state_unref(m_state);
xkb_keymap_unref(m_keymap);
xkb_context_unref(m_context);
@@ -254,6 +276,24 @@ void Xkb::updateKey(uint32_t key, InputRedirection::KeyboardKeyState state)
}
const auto oldMods = m_modifiers;
xkb_state_update_key(m_state, key + 8, static_cast(state));
+ if (state == InputRedirection::KeyboardKeyPressed) {
+ const auto sym = toKeysym(key);
+ if (m_compose.state && xkb_compose_state_feed(m_compose.state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
+ switch (xkb_compose_state_get_status(m_compose.state)) {
+ case XKB_COMPOSE_NOTHING:
+ m_keysym = sym;
+ break;
+ case XKB_COMPOSE_COMPOSED:
+ m_keysym = xkb_compose_state_get_one_sym(m_compose.state);
+ break;
+ default:
+ m_keysym = XKB_KEY_NoSymbol;
+ break;
+ }
+ } else {
+ m_keysym = sym;
+ }
+ }
updateModifiers();
if (state == InputRedirection::KeyboardKeyPressed) {
m_modOnlyShortcut.pressCount++;
@@ -525,13 +565,13 @@ void KeyboardInputRedirection::processKey(uint32_t key, InputRedirection::Keyboa
}
}
- const xkb_keysym_t keySym = m_xkb->toKeysym(key);
+ const xkb_keysym_t keySym = m_xkb->currentKeysym();
KeyEvent event(type,
m_xkb->toQtKey(keySym),
m_xkb->modifiers(),
key,
keySym,
- m_xkb->toString(m_xkb->toKeysym(key)),
+ m_xkb->toString(keySym),
autoRepeat,
time,
device);
diff --git a/keyboard_input.h b/keyboard_input.h
index e47f06dceb..da0785985a 100644
--- a/keyboard_input.h
+++ b/keyboard_input.h
@@ -33,6 +33,8 @@ class QWindow;
struct xkb_context;
struct xkb_keymap;
struct xkb_state;
+struct xkb_compose_table;
+struct xkb_compose_state;
typedef uint32_t xkb_mod_index_t;
typedef uint32_t xkb_keysym_t;
@@ -58,6 +60,9 @@ public:
void updateModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group);
void updateKey(uint32_t key, InputRedirection::KeyboardKeyState state);
xkb_keysym_t toKeysym(uint32_t key);
+ xkb_keysym_t currentKeysym() const {
+ return m_keysym;
+ }
QString toString(xkb_keysym_t keysym);
Qt::Key toQtKey(xkb_keysym_t keysym);
Qt::KeyboardModifiers modifiers() const;
@@ -81,11 +86,17 @@ private:
xkb_mod_index_t m_altModifier;
xkb_mod_index_t m_metaModifier;
Qt::KeyboardModifiers m_modifiers;
+ xkb_keysym_t m_keysym;
struct {
uint pressCount = 0;
Qt::KeyboardModifier modifier = Qt::NoModifier;
} m_modOnlyShortcut;
quint32 m_currentLayout = 0;
+
+ struct {
+ xkb_compose_table *table = nullptr;
+ xkb_compose_state *state = nullptr;
+ } m_compose;
};
class KeyboardInputRedirection : public QObject