Commit a17c85a9 authored by Martin Flöser's avatar Martin Flöser

Support mapping QKeyEvent to xkb_keysym_t

Summary:
This is needed in virtual keyboard and also used KKeyServer so far. With
this change it is moved to new API provided in Xkb. The new translation
map is now also used for the direction from Qt::Key +
Qt::KeyboardModifier to xkb_keysym_t.

New implementation is supported by a new test case covering the same
combinations as in the existing direction.

Reviewers: #kwin, #plasma

Subscribers: plasma-devel, kwin

Tags: #kwin

Differential Revision: https://phabricator.kde.org/D7356
parent 0eba3f3c
This diff is collapsed.
......@@ -19,16 +19,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "virtualkeyboard.h"
#include "input.h"
#include "keyboard_input.h"
#include "utils.h"
#include "screens.h"
#include "wayland_server.h"
#include "workspace.h"
#include "xkb.h"
#include <KWayland/Server/display.h>
#include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/textinput_interface.h>
#include <KKeyServer>
#include <KStatusNotifierItem>
#include <KLocalizedString>
......@@ -409,12 +410,7 @@ bool VirtualKeyboard::eventFilter(QObject *o, QEvent *e)
QKeyEvent *event = static_cast<QKeyEvent*>(e);
if (event->nativeScanCode() == 0) {
// this is a key composed by the virtual keyboard - we need to send it to the client
// TODO: proper xkb support in KWindowSystem needed
int sym = xkb_keysym_from_name(event->text().toUtf8().constData(), XKB_KEYSYM_NO_FLAGS);
if (sym == XKB_KEY_NoSymbol) {
// mapping from text failed, try mapping through KKeyServer
KKeyServer::keyQtToSymX(event->key(), &sym);
}
const auto sym = input()->keyboard()->xkb()->fromKeyEvent(event);
if (sym != 0) {
if (waylandServer()) {
auto t = waylandServer()->seat()->focusedTextInput();
......
......@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KWayland/Server/seat_interface.h>
// Qt
#include <QTemporaryFile>
#include <QKeyEvent>
// xkbcommon
#include <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-compose.h>
......@@ -445,6 +446,21 @@ Qt::Key Xkb::toQtKey(xkb_keysym_t keysym) const
return xkbToQtKey(keysym);
}
xkb_keysym_t Xkb::fromQtKey(Qt::Key key, Qt::KeyboardModifiers mods) const
{
return qtKeyToXkb(key, mods);
}
xkb_keysym_t Xkb::fromKeyEvent(QKeyEvent *event) const
{
xkb_keysym_t sym = xkb_keysym_from_name(event->text().toUtf8().constData(), XKB_KEYSYM_NO_FLAGS);
if (sym == XKB_KEY_NoSymbol) {
// mapping from text failed, try mapping through KKeyServer
sym = fromQtKey(Qt::Key(event->key() & ~Qt::KeyboardModifierMask), event->modifiers());
}
return sym;
}
bool Xkb::shouldKeyRepeat(quint32 key) const
{
if (!m_keymap) {
......
......@@ -69,6 +69,8 @@ public:
}
QString toString(xkb_keysym_t keysym);
Qt::Key toQtKey(xkb_keysym_t keysym) const;
xkb_keysym_t fromQtKey(Qt::Key key, Qt::KeyboardModifiers mods) const;
xkb_keysym_t fromKeyEvent(QKeyEvent *event) const;
Qt::KeyboardModifiers modifiers() const;
Qt::KeyboardModifiers modifiersRelevantForGlobalShortcuts() const;
bool shouldKeyRepeat(quint32 key) const;
......
......@@ -273,6 +273,45 @@ static inline Qt::Key xkbToQtKey(xkb_keysym_t keySym)
return key;
}
static inline xkb_keysym_t qtKeyToXkb(Qt::Key qtKey, Qt::KeyboardModifiers modifiers)
{
xkb_keysym_t sym = XKB_KEY_NoSymbol;
if (modifiers.testFlag(Qt::KeypadModifier) && qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9) {
sym = XKB_KEY_KP_0 + qtKey - Qt::Key_0;
} else if (qtKey < 0x1000 && !modifiers.testFlag(Qt::KeypadModifier)) {
QChar character(qtKey);
if (!modifiers.testFlag(Qt::ShiftModifier)) {
character = character.toLower();
}
sym = character.unicode();
}
if (sym == XKB_KEY_NoSymbol) {
std::vector<xkb_keysym_t> possibleMatches;
for (auto pair : s_mapping) {
if (pair.second == qtKey) {
possibleMatches.emplace_back(pair.first);
}
}
if (!possibleMatches.empty()) {
sym = possibleMatches.front();
for (auto match : possibleMatches) {
// is the current match better than existing?
if (modifiers.testFlag(Qt::KeypadModifier)) {
if (match >= XKB_KEY_KP_Space && match <= XKB_KEY_KP_9) {
sym = match;
}
} else {
if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9) {
sym = match;
}
}
}
}
}
return sym;
}
}
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment