Use XLookupString for translating key events.
There seems to be no easy equivalent in the XCB world and the fallback we currently have is really incomplete. Hence we will call XLookupString with a fake XKeyEvent if XCB_USE_XLIB is enabled. Reviewed-by: Samuel Rødal
This commit is contained in:
parent
e3410908a2
commit
4d10e64f2a
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user