From 3b4c508ee36ac74c37e77fcaa14d106397ad2994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Thu, 28 May 2015 10:17:41 +0200 Subject: [PATCH] [wayland] Pass xkb keymap to Wayland server When creating a new xkb keymap we need to pass it to the Wayland server's seat. As the Wayland protocol expects the keymap as a file descriptor, a temporary file is created, mmapped and the keymap written into it. As the Wayland protocol doesn't restrict how long the file descriptor needs to be valid we keep any created temporary file around till the InputRedirection gets destroyed. --- input.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- input.h | 4 +++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/input.cpp b/input.cpp index 65542b77a6..57ba3c1035 100644 --- a/input.cpp +++ b/input.cpp @@ -41,6 +41,7 @@ along with this program. If not, see . // Qt #include #include +#include // KDE #include #if HAVE_XKB @@ -50,13 +51,15 @@ along with this program. If not, see . // system #include #include +#include namespace KWin { #if HAVE_XKB -Xkb::Xkb() - : m_context(xkb_context_new(static_cast(0))) +Xkb::Xkb(InputRedirection *input) + : m_input(input) + , m_context(xkb_context_new(static_cast(0))) , m_keymap(NULL) , m_state(NULL) , m_shiftModifier(0) @@ -123,6 +126,47 @@ void Xkb::updateKeymap(xkb_keymap *keymap) m_controlModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL); m_altModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT); m_metaModifier = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO); + + createKeymapFile(); +} + +void Xkb::createKeymapFile() +{ +#if HAVE_WAYLAND + if (!waylandServer()) { + return; + } + // TODO: uninstall keymap on server? + if (!m_keymap) { + return; + } + + ScopedCPointer keymapString(xkb_keymap_get_as_string(m_keymap, XKB_KEYMAP_FORMAT_TEXT_V1)); + if (keymapString.isNull()) { + return; + } + const uint size = qstrlen(keymapString.data()) + 1; + + QTemporaryFile *tmp = new QTemporaryFile(m_input); + if (!tmp->open()) { + delete tmp; + return; + } + unlink(tmp->fileName().toUtf8().constData()); + if (!tmp->resize(size)) { + delete tmp; + return; + } + uchar *address = tmp->map(0, size); + if (!address) { + return; + } + if (qstrncpy(reinterpret_cast(address), keymapString.data(), size) == nullptr) { + delete tmp; + return; + } + waylandServer()->seat()->setKeymap(tmp->handle(), size); +#endif } void Xkb::updateModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group) @@ -195,7 +239,7 @@ KWIN_SINGLETON_FACTORY(InputRedirection) InputRedirection::InputRedirection(QObject *parent) : QObject(parent) #if HAVE_XKB - , m_xkb(new Xkb()) + , m_xkb(new Xkb(this)) #endif , m_pointerWindow() , m_shortcuts(new GlobalShortcutsManager(this)) diff --git a/input.h b/input.h index 81da6465e2..a29d2d9d17 100644 --- a/input.h +++ b/input.h @@ -213,7 +213,7 @@ private: class Xkb { public: - Xkb(); + Xkb(InputRedirection *input); ~Xkb(); void installKeymap(int fd, uint32_t size); void updateModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t modsLocked, uint32_t group); @@ -224,7 +224,9 @@ public: Qt::KeyboardModifiers modifiers() const; private: void updateKeymap(xkb_keymap *keymap); + void createKeymapFile(); void updateModifiers(); + InputRedirection *m_input; xkb_context *m_context; xkb_keymap *m_keymap; xkb_state *m_state;