[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.
This commit is contained in:
parent
988ce28943
commit
3b4c508ee3
2 changed files with 50 additions and 4 deletions
50
input.cpp
50
input.cpp
|
@ -41,6 +41,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// Qt
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QTemporaryFile>
|
||||
// KDE
|
||||
#include <kkeyserver.h>
|
||||
#if HAVE_XKB
|
||||
|
@ -50,13 +51,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// system
|
||||
#include <linux/input.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
#if HAVE_XKB
|
||||
Xkb::Xkb()
|
||||
: m_context(xkb_context_new(static_cast<xkb_context_flags>(0)))
|
||||
Xkb::Xkb(InputRedirection *input)
|
||||
: m_input(input)
|
||||
, m_context(xkb_context_new(static_cast<xkb_context_flags>(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<char> 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<char*>(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))
|
||||
|
|
4
input.h
4
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;
|
||||
|
|
Loading…
Reference in a new issue