diff options
-rw-r--r-- | config.tests/xkbcommon/main.cpp | 29 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 141 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandinputdevice.h | 14 |
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; }; |