summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp112
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h3
-rw-r--r--src/plugins/platforms/xcb/xcb.pro2
3 files changed, 82 insertions, 35 deletions
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 30481cc11a..5c034252d3 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -41,6 +41,7 @@
#include "qxcbkeyboard.h"
#include "qxcbwindow.h"
+#include "qxcbscreen.h"
#include <xcb/xcb_keysyms.h>
#include <X11/keysym.h>
#include <QtGui/QWindowSystemInterface>
@@ -913,6 +914,7 @@ void QXcbKeyboard::setupModifiers()
m_meta_mask = 0;
m_mode_switch_mask = 0;
m_num_lock_mask = 0;
+ m_caps_lock_mask = 0;
xcb_generic_error_t *error = 0;
xcb_connection_t *conn = xcb_connection();
@@ -938,6 +940,7 @@ void QXcbKeyboard::setupModifiers()
modKeyCodes << SymCodes(XK_Hyper_R, xcb_key_symbols_get_keycode(m_key_symbols, XK_Hyper_R));
modKeyCodes << SymCodes(XK_Num_Lock, xcb_key_symbols_get_keycode(m_key_symbols, XK_Num_Lock));
modKeyCodes << SymCodes(XK_Mode_switch, xcb_key_symbols_get_keycode(m_key_symbols, XK_Mode_switch));
+ modKeyCodes << SymCodes(XK_Caps_Lock, xcb_key_symbols_get_keycode(m_key_symbols, XK_Caps_Lock));
xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply);
const int w = modMapReply->keycodes_per_modifier;
@@ -965,56 +968,51 @@ void QXcbKeyboard::setMask(uint sym, uint mask)
&& m_meta_mask != mask
&& m_super_mask != mask
&& m_hyper_mask != mask
- && (sym == XK_Alt_L || sym == XK_Alt_R)) {
+ && (sym == XK_Alt_L || sym == XK_Alt_R))
m_alt_mask = mask;
- }
+
if (m_meta_mask == 0
&& m_alt_mask != mask
&& m_super_mask != mask
&& m_hyper_mask != mask
- && (sym == XK_Meta_L || sym == XK_Meta_R)) {
+ && (sym == XK_Meta_L || sym == XK_Meta_R))
m_meta_mask = mask;
- }
+
if (m_super_mask == 0
&& m_alt_mask != mask
&& m_meta_mask != mask
&& m_hyper_mask != mask
- && (sym == XK_Super_L || sym == XK_Super_R)) {
+ && (sym == XK_Super_L || sym == XK_Super_R))
m_super_mask = mask;
- }
+
if (m_hyper_mask == 0
&& m_alt_mask != mask
&& m_meta_mask != mask
&& m_super_mask != mask
- && (sym == XK_Hyper_L || sym == XK_Hyper_R)) {
+ && (sym == XK_Hyper_L || sym == XK_Hyper_R))
m_hyper_mask = mask;
- }
+
if (m_mode_switch_mask == 0
&& m_alt_mask != mask
&& m_meta_mask != mask
&& m_super_mask != mask
&& m_hyper_mask != mask
- && sym == XK_Mode_switch) {
+ && sym == XK_Mode_switch)
m_mode_switch_mask = mask;
- }
- if (m_num_lock_mask == 0
- && sym == XK_Num_Lock) {
+
+ if (m_num_lock_mask == 0 && sym == XK_Num_Lock)
m_num_lock_mask = mask;
- }
+
+ if (m_caps_lock_mask == 0 && sym == XK_Caps_Lock)
+ m_caps_lock_mask = mask;
}
// #define XCB_KEYBOARD_DEBUG
-void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time)
+void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code,
+ quint16 state, xcb_timestamp_t time)
{
- int col = state & XCB_MOD_MASK_SHIFT ? 1 : 0;
-
- const int altGrOffset = 4;
- if (state & 128)
- col += altGrOffset;
-
Q_XCB_NOOP(connection());
-
#ifdef XCB_KEYBOARD_DEBUG
printf("key code: %d, state: %d, syms: ", code, state);
for (int i = 0; i <= 5; ++i) {
@@ -1023,30 +1021,76 @@ void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycod
printf("\n");
#endif
- Q_XCB_NOOP(connection());
+ QByteArray chars;
+ xcb_keysym_t sym = lookupString(window, state, code, type, &chars);
+ Qt::KeyboardModifiers modifiers;
+ int qtcode = 0;
+ int count = chars.count();
+ QString string = translateKeySym(sym, state, qtcode, modifiers, chars, count);
+ QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
+ code, 0, state, string.left(count));
+}
+
+#ifdef XCB_USE_XLIB
+extern "C" {
+ int XLookupString(void *event, char *buf, int count, void *keysym, void *comp);
+}
+typedef struct { // must match XKeyEvent in Xlib.h
+ int type;
+ unsigned long serial;
+ int send_event;
+ void *display;
+ unsigned long window;
+ unsigned long root;
+ unsigned long subwindow;
+ unsigned long time;
+ int x, y;
+ int x_root, y_root;
+ unsigned int state;
+ unsigned int keycode;
+ int same_screen;
+} FakeXKeyEvent;
+#endif
+xcb_keysym_t QXcbKeyboard::lookupString(QWindow *window, uint state, xcb_keycode_t code,
+ QEvent::Type type, QByteArray *chars)
+{
+#ifdef XCB_USE_XLIB
+
+ xcb_keysym_t sym = XCB_NO_SYMBOL;
+ chars->resize(512);
+ FakeXKeyEvent event;
+ memset(&event, 0, sizeof(event));
+ event.type = (type == QEvent::KeyRelease ? 3 : 2);
+ event.display = connection()->xlib_display();
+ event.window = static_cast<QXcbWindow *>(window->handle())->xcb_window();
+ event.root = connection()->screens().at(0)->root();
+ event.state = state;
+ event.keycode = code;
+ int count = XLookupString(&event, chars->data(), chars->size(), &sym, 0);
+ chars->resize(count);
+ return sym;
+
+#else
+
+ // No XLookupString available. The following is really incomplete...
+
+ int col = state & XCB_MOD_MASK_SHIFT ? 1 : 0;
+ const int altGrOffset = 4;
+ if (state & 128)
+ col += altGrOffset;
xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col);
if (sym == XCB_NO_SYMBOL)
sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1);
-
if (state & XCB_MOD_MASK_LOCK && sym <= 0x7f && isprint(sym)) {
if (isupper(sym))
sym = tolower(sym);
else
sym = toupper(sym);
}
+ return sym;
- Q_XCB_NOOP(connection());
-
- QByteArray chars;
-
- Qt::KeyboardModifiers modifiers;
- int qtcode = 0;
- int count = 0;
-
- QString string = translateKeySym(sym, state, qtcode, modifiers, chars, count);
-
- QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers, code, 0, state, string.left(count));
+#endif
}
void QXcbKeyboard::handleKeyPressEvent(QXcbWindow *window, const xcb_key_press_event_t *event)
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index a4da07417d..d85698d936 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -72,6 +72,8 @@ private:
QByteArray &chars, int &count);
void setupModifiers();
void setMask(uint sym, uint mask);
+ xcb_keysym_t lookupString(QWindow *window, uint state, xcb_keycode_t code,
+ QEvent::Type type, QByteArray *chars);
uint m_alt_mask;
uint m_super_mask;
@@ -79,6 +81,7 @@ private:
uint m_meta_mask;
uint m_mode_switch_mask;
uint m_num_lock_mask;
+ uint m_caps_lock_mask;
xcb_key_symbols_t *m_key_symbols;
#ifndef QT_NO_XCB_XKB
diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro
index c5ce6fa57b..2b545f9b1d 100644
--- a/src/plugins/platforms/xcb/xcb.pro
+++ b/src/plugins/platforms/xcb/xcb.pro
@@ -39,7 +39,7 @@ HEADERS = \
QT += gui-private core-private
-# needed by GLX, Xcursor, ...
+# needed by GLX, Xcursor, XLookupString, ...
DEFINES += XCB_USE_XLIB
# to support custom cursors with depth > 1