GHOST/X11: support accessing physical keycodes
This means we can check keys such as tilde in a generic way.
This commit is contained in:
parent
5165d62931
commit
f3427cbc98
@ -95,7 +95,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;
|
||||
@ -111,6 +116,7 @@ GHOST_SystemX11::
|
||||
GHOST_SystemX11(
|
||||
)
|
||||
: GHOST_System(),
|
||||
m_xkb_descr(NULL),
|
||||
m_start_time(0)
|
||||
{
|
||||
m_display = XOpenDisplay(NULL);
|
||||
@ -185,6 +191,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
|
||||
@ -242,6 +253,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);
|
||||
}
|
||||
|
||||
@ -626,7 +641,7 @@ processEvents(
|
||||
getMilliSeconds(),
|
||||
GHOST_kEventKeyDown,
|
||||
window,
|
||||
convertXKey(modifiers[i]),
|
||||
ghost_key_from_keysym(modifiers[i]),
|
||||
'\0',
|
||||
NULL));
|
||||
}
|
||||
@ -883,7 +898,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:
|
||||
*
|
||||
@ -921,7 +936,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:
|
||||
@ -958,10 +973,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,
|
||||
@ -983,7 +1000,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';
|
||||
@ -1632,10 +1649,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;
|
||||
|
||||
@ -1743,11 +1772,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_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);
|
||||
@ -1762,6 +1786,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 */
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define __GHOST_SYSTEMX11_H__
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/XKBlib.h> /* allow detectable autorepeate */
|
||||
|
||||
#include "GHOST_System.h"
|
||||
#include "../GHOST_Types.h"
|
||||
@ -353,6 +354,10 @@ public:
|
||||
private:
|
||||
|
||||
Display *m_display;
|
||||
|
||||
/* Use for scancode lookups. */
|
||||
XkbDescRec *m_xkb_descr;
|
||||
|
||||
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
|
||||
XIM m_xim;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user