diff options
Diffstat (limited to 'intern/ghost/intern/GHOST_SystemX11.cpp')
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.cpp | 72 |
1 files changed, 59 insertions, 13 deletions
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index ebfa3013ec8..e50df358cb2 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -101,7 +101,12 @@ * See T47228 and D1746 */ #define USE_NON_LATIN_KB_WORKAROUND -static GHOST_TKey convertXKey(KeySym key); +static GHOST_TKey ghost_key_from_keysym( + const KeySym key); +static GHOST_TKey ghost_key_from_keycode( + const XkbDescPtr xkb_descr, const KeyCode keycode); +static GHOST_TKey ghost_key_from_keysym_or_keycode( + const KeySym key, const XkbDescPtr xkb_descr, const KeyCode keycode); /* these are for copy and select copy */ static char *txt_cut_buffer = NULL; @@ -117,6 +122,7 @@ GHOST_SystemX11:: GHOST_SystemX11( ) : GHOST_System(), + m_xkb_descr(NULL), m_start_time(0) { XInitThreads(); @@ -192,6 +198,11 @@ GHOST_SystemX11( use_xkb = XkbQueryExtension(m_display, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor); if (use_xkb) { XkbSetDetectableAutoRepeat(m_display, true, NULL); + + m_xkb_descr = XkbGetMap(m_display, 0, XkbUseCoreKbd); + if (m_xkb_descr) { + XkbGetNames(m_display, XkbKeyNamesMask, m_xkb_descr); + } } #ifdef WITH_XWAYLAND_HACK @@ -249,6 +260,10 @@ GHOST_SystemX11:: XCloseDevice(m_display, m_xtablet.EraserDevice); #endif /* WITH_X11_XINPUT */ + if (m_xkb_descr) { + XkbFreeNames(m_xkb_descr, XkbKeyNamesMask, false); + } + XCloseDisplay(m_display); } @@ -724,7 +739,7 @@ processEvents( getMilliSeconds(), GHOST_kEventKeyDown, window, - convertXKey(modifiers[i]), + ghost_key_from_keysym(modifiers[i]), '\0', NULL)); } @@ -981,7 +996,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) * is unmodified (or anyone swapping the keys with xmodmap). * * - XLookupKeysym seems to always use first defined keymap (see T47228), which generates - * keycodes unusable by convertXKey for non-latin-compatible keymaps. + * keycodes unusable by ghost_key_from_keysym for non-latin-compatible keymaps. * * To address this, we: * @@ -1019,7 +1034,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) /* Only allow a limited set of keys from XLookupKeysym, all others we take from XLookupString, * unless it gives unknown key... */ - gkey = convertXKey(key_sym); + gkey = ghost_key_from_keysym_or_keycode(key_sym, m_xkb_descr, xke->keycode); switch (gkey) { case GHOST_kKeyRightAlt: case GHOST_kKeyLeftAlt: @@ -1056,10 +1071,12 @@ GHOST_SystemX11::processEvent(XEvent *xe) case GHOST_kKeyNumpadSlash: break; default: - GHOST_TKey gkey_str = convertXKey(key_sym_str); + { + GHOST_TKey gkey_str = ghost_key_from_keysym(key_sym_str); if (gkey_str != GHOST_kKeyUnknown) { gkey = gkey_str; } + } } #else /* In keyboards like latin ones, @@ -1081,7 +1098,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) key_sym = XLookupKeysym(xke, 0); } - gkey = convertXKey(key_sym); + gkey = ghost_key_from_keysym(key_sym); if (!XLookupString(xke, &ascii, 1, NULL, NULL)) { ascii = '\0'; @@ -1730,10 +1747,22 @@ generateWindowExposeEvents() return anyProcessed; } +static GHOST_TKey +ghost_key_from_keysym_or_keycode(const KeySym keysym, XkbDescPtr xkb_descr, const KeyCode keycode) +{ + GHOST_TKey type = ghost_key_from_keysym(keysym); + if (type == GHOST_kKeyUnknown) { + if (xkb_descr) { + type = ghost_key_from_keycode(xkb_descr, keycode); + } + } + return type; +} + #define GXMAP(k, x, y) case x: k = y; break static GHOST_TKey -convertXKey(KeySym key) +ghost_key_from_keysym(const KeySym key) { GHOST_TKey type; @@ -1841,12 +1870,6 @@ convertXKey(KeySym key) GXMAP(type, XF86XK_AudioForward, GHOST_kKeyMediaLast); #endif #endif - /* Non US keyboard layouts: avoid 'UnknownKey' - TODO(campbell): lookup scan-codes. */ - GXMAP(type, XK_dead_circumflex, GHOST_kKeyAccentGrave); /* 'de' */ - GXMAP(type, XK_dead_grave, GHOST_kKeyAccentGrave); /* 'us' (intl) */ - GXMAP(type, XK_masculine, GHOST_kKeyAccentGrave); /* 'es' */ - GXMAP(type, XK_onehalf, GHOST_kKeyAccentGrave); /* 'dk' */ - GXMAP(type, XK_twosuperior, GHOST_kKeyAccentGrave); /* 'fr' */ default: #ifdef GHOST_DEBUG printf("%s: unknown key: %lu / 0x%lx\n", __func__, key, key); @@ -1861,6 +1884,29 @@ convertXKey(KeySym key) #undef GXMAP +#define MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a)) + +static GHOST_TKey +ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCode keycode) +{ + GHOST_ASSERT(XkbKeyNameLength == 4, "Name length is invalid!"); + if (keycode >= xkb_descr->min_key_code && keycode <= xkb_descr->max_key_code) { + const char *id_str = xkb_descr->names->keys[keycode].name; + const uint32_t id = MAKE_ID(id_str[0], id_str[1], id_str[2], id_str[3]); + // printf("scancode is: %.*s\n", XkbKeyNameLength, id_str); + switch (id) { + case MAKE_ID('T', 'L', 'D', 'E'): + return GHOST_kKeyAccentGrave; + } + } + else { + GHOST_ASSERT(false, "KeyCode out of range!"); + } + return GHOST_kKeyUnknown; +} + +#undef MAKE_ID + /* from xclip.c xcout() v0.11 */ #define XCLIB_XCOUT_NONE 0 /* no context */ |