Get modifier mapping using standard X, no need for libxkbcommon here.

Reviewed-by: Samuel Rødal
This commit is contained in:
Laszlo Agocs 2011-06-09 10:39:08 +02:00
parent bd781231b2
commit 06c56cb464
2 changed files with 52 additions and 33 deletions

View File

@ -41,19 +41,10 @@
#include "qxcbkeyboard.h" #include "qxcbkeyboard.h"
#include "qxcbwindow.h" #include "qxcbwindow.h"
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#ifndef QT_NO_XCB_XKB
typedef unsigned char KeyCode;
#include <X11/extensions/XKBcommon.h>
#endif
#include <QtGui/QWindowSystemInterface> #include <QtGui/QWindowSystemInterface>
#include <QtCore/QTextCodec> #include <QtCore/QTextCodec>
#include <stdio.h> #include <stdio.h>
#ifndef XK_ISO_Left_Tab #ifndef XK_ISO_Left_Tab
@ -904,13 +895,9 @@ QString QXcbKeyboard::translateKeySym(xcb_keysym_t keysym, uint xmodifiers,
QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
: QXcbObject(connection) : QXcbObject(connection)
, m_alt_mask(0)
, m_super_mask(0)
, m_hyper_mask(0)
, m_meta_mask(0)
{ {
m_key_symbols = xcb_key_symbols_alloc(xcb_connection()); m_key_symbols = xcb_key_symbols_alloc(xcb_connection());
initXkb(); setupModifiers();
} }
QXcbKeyboard::~QXcbKeyboard() QXcbKeyboard::~QXcbKeyboard()
@ -918,27 +905,58 @@ QXcbKeyboard::~QXcbKeyboard()
xcb_key_symbols_free(m_key_symbols); xcb_key_symbols_free(m_key_symbols);
} }
void QXcbKeyboard::initXkb() void QXcbKeyboard::setupModifiers()
{ {
#ifndef QT_NO_XCB_XKB m_alt_mask = 0;
struct xkb_rule_names names; m_super_mask = 0;
names.rules = "evdev"; m_hyper_mask = 0;
names.model = "pc105"; m_meta_mask = 0;
names.layout = "us"; m_mode_switch_mask = 0;
names.variant = ""; m_num_lock_mask = 0;
names.options = "";
m_xkb = xkb_compile_keymap_from_rules(&names); xcb_generic_error_t *error = 0;
for (int i = m_xkb->min_key_code; i < m_xkb->max_key_code; ++i) { xcb_connection_t *conn = xcb_connection();
const uint mask = m_xkb->map->modmap ? m_xkb->map->modmap[i] : 0; xcb_get_modifier_mapping_cookie_t modMapCookie = xcb_get_modifier_mapping(conn);
if (!mask) xcb_get_modifier_mapping_reply_t *modMapReply =
continue; xcb_get_modifier_mapping_reply(conn, modMapCookie, &error);
for (int j = 0; j < XkbKeyGroupsWidth(m_xkb, i); ++j) { if (error) {
uint32_t keySym = XkbKeySym(m_xkb, i, j); qWarning("xcb keyboard: failed to get modifier mapping");
if (keySym) free(error);
setMask(keySym, mask); return;
}
// Figure out the modifier mapping, ICCCM 6.6
typedef QPair<uint, xcb_keycode_t *> SymCodes;
QList<SymCodes> modKeyCodes;
// for Alt and Meta L and R are the same
modKeyCodes << SymCodes(XK_Alt_L, xcb_key_symbols_get_keycode(m_key_symbols, XK_Alt_L));
modKeyCodes << SymCodes(XK_Meta_L, xcb_key_symbols_get_keycode(m_key_symbols, XK_Meta_L));
modKeyCodes << SymCodes(XK_Super_L, xcb_key_symbols_get_keycode(m_key_symbols, XK_Super_L));
modKeyCodes << SymCodes(XK_Super_R, xcb_key_symbols_get_keycode(m_key_symbols, XK_Super_R));
modKeyCodes << SymCodes(XK_Hyper_L, xcb_key_symbols_get_keycode(m_key_symbols, XK_Hyper_L));
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));
xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply);
const int w = modMapReply->keycodes_per_modifier;
for (int i = 0; i < modKeyCodes.count(); ++i) {
for (int bit = 0; bit < 8; ++bit) {
uint mask = 1 << bit;
for (int x = 0; x < w; ++x) {
xcb_keycode_t keyCode = modMap[x + bit * w];
xcb_keycode_t *itk = modKeyCodes.at(i).second;
while (itk && *itk != XCB_NO_SYMBOL)
if (*itk++ == keyCode)
setMask(modKeyCodes.at(i).first, mask);
}
} }
} }
#endif
for (int i = 0; i < modKeyCodes.count(); ++i)
free(modKeyCodes.at(i).second);
free(modMapReply);
} }
void QXcbKeyboard::setMask(uint sym, uint mask) void QXcbKeyboard::setMask(uint sym, uint mask)
@ -1045,4 +1063,5 @@ void QXcbKeyboard::handleKeyReleaseEvent(QXcbWindow *window, const xcb_key_relea
void QXcbKeyboard::handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event) void QXcbKeyboard::handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event)
{ {
xcb_refresh_keyboard_mapping(m_key_symbols, const_cast<xcb_mapping_notify_event_t *>(event)); xcb_refresh_keyboard_mapping(m_key_symbols, const_cast<xcb_mapping_notify_event_t *>(event));
setupModifiers();
} }

View File

@ -70,7 +70,7 @@ private:
QString translateKeySym(xcb_keysym_t keysym, uint xmodifiers, QString translateKeySym(xcb_keysym_t keysym, uint xmodifiers,
int &code, Qt::KeyboardModifiers &modifiers, int &code, Qt::KeyboardModifiers &modifiers,
QByteArray &chars, int &count); QByteArray &chars, int &count);
void initXkb(); void setupModifiers();
void setMask(uint sym, uint mask); void setMask(uint sym, uint mask);
uint m_alt_mask; uint m_alt_mask;