summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/xkbcommon/main.cpp29
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.cpp141
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputdevice.h14
3 files changed, 112 insertions, 72 deletions
diff --git a/config.tests/xkbcommon/main.cpp b/config.tests/xkbcommon/main.cpp
index 27422bf2d..9eb8506db 100644
--- a/config.tests/xkbcommon/main.cpp
+++ b/config.tests/xkbcommon/main.cpp
@@ -42,17 +42,28 @@
#include <X11/keysym.h>
#include <QtCore/qnamespace.h>
+#include <string.h>
-int main(int argc, char **argv)
+int main()
{
- struct xkb_rule_names names;
- names.rules = "evdev";
- names.model = "pc105";
- names.layout = "us";
- names.variant = "";
- names.options = "";
+ xkb_rule_names names;
+ names.rules = strdup("evdev");
+ names.model = strdup("pc105");
+ names.layout = strdup("us");
+ names.variant = strdup("");
+ names.options = strdup("");
+
+ xkb_context *context = xkb_context_new();
+ if (context) {
+ xkb_keymap * keymap = xkb_map_new_from_names(context, &names);
+ if (keymap) {
+ xkb_state *state = xkb_state_new(keymap);
+ if (state)
+ xkb_state_unref(state);
+ xkb_map_unref(keymap);
+ }
+ xkb_context_unref(context);
+ }
- struct xkb_desc *xkb = xkb_compile_keymap_from_rules(&names);
- Q_UNUSED(xkb);
return 0;
}
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
index c590cdc83..357cffa01 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp
@@ -70,6 +70,11 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
, mKeyboardFocus(0)
, mTouchFocus(0)
, mButtons(0)
+#ifndef QT_NO_WAYLAND_XKB
+ , mXkbContext(0)
+ , mXkbMap(0)
+ , mXkbState(0)
+#endif
{
mInputDevice = static_cast<struct wl_input_device *>
(wl_display_bind(mDisplay,id,&wl_input_device_interface));
@@ -79,17 +84,23 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
wl_input_device_set_user_data(mInputDevice, this);
#ifndef QT_NO_WAYLAND_XKB
- struct xkb_rule_names names;
- names.rules = "evdev";
- names.model = "pc105";
- names.layout = "us";
- names.variant = "";
- names.options = "";
-
- mXkb = xkb_compile_keymap_from_rules(&names);
+ xkb_rule_names names;
+ names.rules = strdup("evdev");
+ names.model = strdup("pc105");
+ names.layout = strdup("us");
+ names.variant = strdup("");
+ names.options = strdup("");
+
+ xkb_context *mXkbContext = xkb_context_new();
+ if (mXkbContext) {
+ mXkbMap = xkb_map_new_from_names(mXkbContext, &names);
+ if (mXkbMap) {
+ mXkbState = xkb_state_new(mXkbMap);
+ }
+ }
- if (!mXkb)
- qWarning() << "xkb_compile_keymap_from_rules failed, no key input";
+ if (!mXkbContext || !mXkbMap || !mXkbState)
+ qWarning() << "xkb_map_new_from_names failed, no key input";
#endif
if (mQDisplay->dndSelectionHandler()) {
@@ -102,6 +113,18 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display,
QWindowSystemInterface::registerTouchDevice(mTouchDevice);
}
+QWaylandInputDevice::~QWaylandInputDevice()
+{
+#ifndef QT_NO_WAYLAND_XKB
+ if (mXkbState)
+ xkb_state_unref(mXkbState);
+ if (mXkbMap)
+ xkb_map_unref(mXkbMap);
+ if (mXkbContext)
+ xkb_context_unref(mXkbContext);
+#endif
+}
+
void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window)
{
if (window == mPointerFocus)
@@ -227,20 +250,21 @@ void QWaylandInputDevice::inputHandleAxis(void *data,
Q_UNUSED(value);
}
#ifndef QT_NO_WAYLAND_XKB
-static Qt::KeyboardModifiers translateModifiers(int s)
+static Qt::KeyboardModifiers translateModifiers(xkb_state *state)
{
- const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK;
- const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK;
-
- Qt::KeyboardModifiers ret = 0;
- if (s & XKB_COMMON_SHIFT_MASK)
- ret |= Qt::ShiftModifier;
- if (s & XKB_COMMON_CONTROL_MASK)
- ret |= Qt::ControlModifier;
- if (s & qt_alt_mask)
- ret |= Qt::AltModifier;
- if (s & qt_meta_mask)
- ret |= Qt::MetaModifier;
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
+ xkb_state_component cstate = xkb_state_component(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
+
+ if (xkb_state_mod_name_is_active(state, "Shift", cstate))
+ ret |= Qt::ShiftModifier;
+ if (xkb_state_mod_name_is_active(state, "Control", cstate))
+ ret |= Qt::ControlModifier;
+ if (xkb_state_mod_name_is_active(state, "Alt", cstate))
+ ret |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(state, "Mod1", cstate))
+ ret |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(state, "Mod4", cstate))
+ ret |= Qt::MetaModifier;
return ret;
}
@@ -296,7 +320,7 @@ static uint32_t translateKey(uint32_t sym, char *string, size_t size)
#endif
void QWaylandInputDevice::inputHandleKey(void *data,
- struct wl_input_device *input_device,
+ struct wl_input_device *input_device,
uint32_t serial, uint32_t time,
uint32_t key, uint32_t state)
{
@@ -305,44 +329,46 @@ void QWaylandInputDevice::inputHandleKey(void *data,
QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data;
QWaylandWindow *window = inputDevice->mKeyboardFocus;
#ifndef QT_NO_WAYLAND_XKB
- uint32_t code, sym, level;
+ uint32_t numSyms, code;
+ const xkb_keysym_t *syms;
Qt::KeyboardModifiers modifiers;
QEvent::Type type;
char s[2];
- if (window == NULL || !inputDevice->mXkb) {
- /* We destroyed the keyboard focus surface, but the server
- * didn't get the message yet. */
- return;
+ if (window == NULL || !inputDevice->mXkbMap) {
+ // We destroyed the keyboard focus surface, but the server
+ // didn't get the message yet.
+ return;
}
- code = key + inputDevice->mXkb->min_key_code;
-
- level = 0;
- if (inputDevice->mModifiers & Qt::ShiftModifier &&
- XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1)
- level = 1;
+ code = key + 8;
+ bool isDown = state != 0;
+ numSyms = xkb_key_get_syms(inputDevice->mXkbState, code, &syms);
+ xkb_state_update_key(inputDevice->mXkbState, code,
+ isDown ? XKB_KEY_DOWN : XKB_KEY_UP);
- sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0);
+ xkb_keysym_t sym;
+ if (numSyms == 1) {
+ sym = syms[0];
- modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]);
+ modifiers = translateModifiers(inputDevice->mXkbState);
- if (state) {
- inputDevice->mModifiers |= modifiers;
- type = QEvent::KeyPress;
- } else {
- inputDevice->mModifiers &= ~modifiers;
- type = QEvent::KeyRelease;
- }
+ if (isDown) {
+ inputDevice->mModifiers |= modifiers;
+ type = QEvent::KeyPress;
+ } else {
+ inputDevice->mModifiers &= ~modifiers;
+ type = QEvent::KeyRelease;
+ }
- sym = translateKey(sym, s, sizeof s);
+ sym = translateKey(sym, s, sizeof s);
- if (window) {
- QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
- time, type, sym,
- inputDevice->mModifiers,
- code, 0, 0,
- QString::fromLatin1(s));
+ if (window)
+ QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
+ time, type, sym,
+ inputDevice->mModifiers,
+ code, 0, 0,
+ QString::fromLatin1(s));
}
#else
// Generic fallback for single hard keys: Assume 'key' is a Qt key code.
@@ -409,18 +435,9 @@ void QWaylandInputDevice::inputHandleKeyboardEnter(void *data,
inputDevice->mModifiers = 0;
-#ifndef QT_NO_WAYLAND_XKB
- uint32_t *k, *end;
- uint32_t code;
-
- end = (uint32_t *) ((char *) keys->data + keys->size);
- for (k = (uint32_t *) keys->data; k < end; k++) {
- code = *k + inputDevice->mXkb->min_key_code;
- inputDevice->mModifiers |=
- translateModifiers(inputDevice->mXkb->map->modmap[code]);
- }
-#else
Q_UNUSED(keys);
+#ifndef QT_NO_WAYLAND_XKB
+ inputDevice->mModifiers |= translateModifiers(inputDevice->mXkbState);
#endif
// shouldn't get keyboard enter with no surface
diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h
index a9d3d6183..d29723fad 100644
--- a/src/plugins/platforms/wayland/qwaylandinputdevice.h
+++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h
@@ -52,6 +52,12 @@
#include <wayland-client.h>
+#ifndef QT_NO_WAYLAND_XKB
+struct xkb_context;
+struct xkb_keymap;
+struct xkb_state;
+#endif
+
QT_BEGIN_NAMESPACE
class QWaylandWindow;
@@ -60,6 +66,7 @@ class QWaylandDisplay;
class QWaylandInputDevice {
public:
QWaylandInputDevice(QWaylandDisplay *display, uint32_t id);
+ ~QWaylandInputDevice();
void attach(QWaylandBuffer *buffer, int x, int y);
void handleWindowDestroyed(QWaylandWindow *window);
struct wl_input_device *wl_input_device() const { return mInputDevice; }
@@ -82,7 +89,6 @@ private:
Qt::MouseButtons mButtons;
QPoint mSurfacePos;
QPoint mGlobalPos;
- struct xkb_desc *mXkb;
Qt::KeyboardModifiers mModifiers;
uint32_t mTime;
@@ -149,6 +155,12 @@ private:
QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
QTouchDevice *mTouchDevice;
+#ifndef QT_NO_WAYLAND_XKB
+ xkb_context *mXkbContext;
+ xkb_keymap *mXkbMap;
+ xkb_state *mXkbState;
+#endif
+
friend class QWaylandTouchExtension;
friend class QWaylandQtKeyExtension;
};