Linux: Improved keyboard mapping support

This commit is contained in:
Elias Naur 2005-04-11 10:00:09 +00:00
parent df4e906100
commit 96463f2ef6
1 changed files with 125 additions and 8 deletions

View File

@ -57,6 +57,10 @@
#define KEY_EVENT_BACKLOG 40 #define KEY_EVENT_BACKLOG 40
static unsigned char key_buf[KEYBOARD_SIZE]; static unsigned char key_buf[KEYBOARD_SIZE];
static int numlock_mask;
static int modeswitch_mask;
static int caps_lock_mask;
static int shift_lock_mask;
static event_queue_t event_queue; static event_queue_t event_queue;
@ -93,7 +97,7 @@ void updateKeyboardGrab(void) {
} }
} }
static void closeUnicodeStructs() { static void cleanup() {
if (iconv_descriptor != (iconv_t)-1) { if (iconv_descriptor != (iconv_t)-1) {
iconv_close(iconv_descriptor); iconv_close(iconv_descriptor);
iconv_descriptor = (iconv_t)-1; iconv_descriptor = (iconv_t)-1;
@ -126,7 +130,44 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateKeyboard
keyboard_grabbed = false; keyboard_grabbed = false;
initEventQueue(&event_queue, 3); initEventQueue(&event_queue, 3);
updateKeyboardGrab(); updateKeyboardGrab();
XModifierKeymap *modifier_map = XGetModifierMapping(getDisplay());
numlock_mask = 0;
modeswitch_mask = 0;
caps_lock_mask = 0;
shift_lock_mask = 0;
if (modifier_map != NULL) {
// Find modifier masks
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < modifier_map->max_keypermod; j++) {
KeyCode key_code = modifier_map->modifiermap[i*modifier_map->max_keypermod + j];
KeySym key_sym = XKeycodeToKeysym(getDisplay(), key_code, 0);
int mask = 1 << i;
switch (key_sym) {
case XK_Num_Lock:
numlock_mask |= mask;
break;
case XK_Mode_switch:
modeswitch_mask |= mask;
break;
case XK_Caps_Lock:
if (i == LockMapIndex) {
caps_lock_mask = mask;
shift_lock_mask = 0;
}
break;
case XK_Shift_Lock:
if (i == LockMapIndex && caps_lock_mask == 0)
shift_lock_mask = mask;
break;
default:
break;
}
}
}
XFreeModifiermap(modifier_map);
}
// Allocate unicode structures // Allocate unicode structures
iconv_descriptor = iconv_open("UCS-2", "UTF-8"); iconv_descriptor = iconv_open("UCS-2", "UTF-8");
if (iconv_descriptor != (iconv_t)-1) { if (iconv_descriptor != (iconv_t)-1) {
@ -136,17 +177,17 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nCreateKeyboard
if (xic != NULL) { if (xic != NULL) {
setupIMEventMask(); setupIMEventMask();
} else { } else {
closeUnicodeStructs(); cleanup();
} }
} else } else
closeUnicodeStructs(); cleanup();
} }
} }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyKeyboard JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nDestroyKeyboard
(JNIEnv * env, jclass clazz) (JNIEnv * env, jclass clazz)
{ {
closeUnicodeStructs(); cleanup();
ungrabKeyboard(); ungrabKeyboard();
created = false; created = false;
} }
@ -394,65 +435,142 @@ static unsigned char mapKeySymToLWJGLKeyCode(KeySym keysym) {
case XK_grave: case XK_grave:
return org_lwjgl_input_Keyboard_KEY_GRAVE; return org_lwjgl_input_Keyboard_KEY_GRAVE;
case XK_a: case XK_a:
case XK_A:
return org_lwjgl_input_Keyboard_KEY_A; return org_lwjgl_input_Keyboard_KEY_A;
case XK_b: case XK_b:
case XK_B:
return org_lwjgl_input_Keyboard_KEY_B; return org_lwjgl_input_Keyboard_KEY_B;
case XK_c: case XK_c:
case XK_C:
return org_lwjgl_input_Keyboard_KEY_C; return org_lwjgl_input_Keyboard_KEY_C;
case XK_d: case XK_d:
case XK_D:
return org_lwjgl_input_Keyboard_KEY_D; return org_lwjgl_input_Keyboard_KEY_D;
case XK_e: case XK_e:
case XK_E:
return org_lwjgl_input_Keyboard_KEY_E; return org_lwjgl_input_Keyboard_KEY_E;
case XK_f: case XK_f:
case XK_F:
return org_lwjgl_input_Keyboard_KEY_F; return org_lwjgl_input_Keyboard_KEY_F;
case XK_g: case XK_g:
case XK_G:
return org_lwjgl_input_Keyboard_KEY_G; return org_lwjgl_input_Keyboard_KEY_G;
case XK_h: case XK_h:
case XK_H:
return org_lwjgl_input_Keyboard_KEY_H; return org_lwjgl_input_Keyboard_KEY_H;
case XK_i: case XK_i:
case XK_I:
return org_lwjgl_input_Keyboard_KEY_I; return org_lwjgl_input_Keyboard_KEY_I;
case XK_j: case XK_j:
case XK_J:
return org_lwjgl_input_Keyboard_KEY_J; return org_lwjgl_input_Keyboard_KEY_J;
case XK_k: case XK_k:
case XK_K:
return org_lwjgl_input_Keyboard_KEY_K; return org_lwjgl_input_Keyboard_KEY_K;
case XK_l: case XK_l:
case XK_L:
return org_lwjgl_input_Keyboard_KEY_L; return org_lwjgl_input_Keyboard_KEY_L;
case XK_m: case XK_m:
case XK_M:
return org_lwjgl_input_Keyboard_KEY_M; return org_lwjgl_input_Keyboard_KEY_M;
case XK_n: case XK_n:
case XK_N:
return org_lwjgl_input_Keyboard_KEY_N; return org_lwjgl_input_Keyboard_KEY_N;
case XK_o: case XK_o:
case XK_O:
return org_lwjgl_input_Keyboard_KEY_O; return org_lwjgl_input_Keyboard_KEY_O;
case XK_p: case XK_p:
case XK_P:
return org_lwjgl_input_Keyboard_KEY_P; return org_lwjgl_input_Keyboard_KEY_P;
case XK_q: case XK_q:
case XK_Q:
return org_lwjgl_input_Keyboard_KEY_Q; return org_lwjgl_input_Keyboard_KEY_Q;
case XK_r: case XK_r:
case XK_R:
return org_lwjgl_input_Keyboard_KEY_R; return org_lwjgl_input_Keyboard_KEY_R;
case XK_s: case XK_s:
case XK_S:
return org_lwjgl_input_Keyboard_KEY_S; return org_lwjgl_input_Keyboard_KEY_S;
case XK_t: case XK_t:
case XK_T:
return org_lwjgl_input_Keyboard_KEY_T; return org_lwjgl_input_Keyboard_KEY_T;
case XK_u: case XK_u:
case XK_U:
return org_lwjgl_input_Keyboard_KEY_U; return org_lwjgl_input_Keyboard_KEY_U;
case XK_v: case XK_v:
case XK_V:
return org_lwjgl_input_Keyboard_KEY_V; return org_lwjgl_input_Keyboard_KEY_V;
case XK_w: case XK_w:
case XK_W:
return org_lwjgl_input_Keyboard_KEY_W; return org_lwjgl_input_Keyboard_KEY_W;
case XK_x: case XK_x:
case XK_X:
return org_lwjgl_input_Keyboard_KEY_X; return org_lwjgl_input_Keyboard_KEY_X;
case XK_y: case XK_y:
case XK_Y:
return org_lwjgl_input_Keyboard_KEY_Y; return org_lwjgl_input_Keyboard_KEY_Y;
case XK_z: case XK_z:
case XK_Z:
return org_lwjgl_input_Keyboard_KEY_Z; return org_lwjgl_input_Keyboard_KEY_Z;
default: default:
return org_lwjgl_input_Keyboard_KEY_NONE; return org_lwjgl_input_Keyboard_KEY_NONE;
} }
} }
static bool isKeypadKeysym(KeySym keysym) {
return (0xFF80 <= keysym && keysym <= 0xFFBD) ||
(0x11000000 <= keysym && keysym <= 0x1100FFFF);
}
static KeySym getKeySym(XKeyEvent *event, int group, int index) {
KeySym keysym = XLookupKeysym(event, group*2 + index);
if (keysym == NoSymbol && index == 1)
keysym = XLookupKeysym(event, group*2 + 0);
if (keysym == NoSymbol && group == 1)
keysym = getKeySym(event, 0, index);
return keysym;
}
static KeySym toUpper(KeySym keysym) {
KeySym lower_case, upper_case;
XConvertCase(keysym, &lower_case, &upper_case);
return upper_case;
}
/* Map an event to a KeySym. Use the rules described in
* http://tronche.com/gui/x/xlib/input/keyboard-encoding.html
*/
static KeySym mapEventToKeySym(XKeyEvent *event) {
int group;
KeySym keysym;
if ((event->state & modeswitch_mask) != 0)
group = 1;
else
group = 0;
if ((event->state & numlock_mask) != 0 && isKeypadKeysym(keysym = getKeySym(event, group, 1))) {
if ((event->state & (ShiftMask | shift_lock_mask)) != 0) {
return getKeySym(event, group, 0);
} else {
return keysym;
}
} else if ((event->state & (ShiftMask | LockMask)) == 0) {
return getKeySym(event, group, 0);
} else if ((event->state & ShiftMask) == 0) {
KeySym keysym = getKeySym(event, group, 0);
if ((event->state & caps_lock_mask) != 0)
keysym = toUpper(keysym);
return keysym;
} else {
KeySym keysym = getKeySym(event, group, 1);
if ((event->state & caps_lock_mask) != 0)
keysym = toUpper(keysym);
return keysym;
}
}
static unsigned char getKeycode(XKeyEvent *event) { static unsigned char getKeycode(XKeyEvent *event) {
unsigned char keycode = (unsigned char)((event->keycode - 8) & 0xff); unsigned char keycode;
KeySym keysym = XLookupKeysym(event, 0); KeySym keysym = mapEventToKeySym(event);
keycode = mapKeySymToLWJGLKeyCode(keysym); keycode = mapKeySymToLWJGLKeyCode(keysym);
return keycode; return keycode;
} }
@ -543,7 +661,6 @@ static unsigned char eventState(XKeyEvent *event) {
static void bufferEvent(XKeyEvent *key_event) { static void bufferEvent(XKeyEvent *key_event) {
unsigned char keycode = getKeycode(key_event); unsigned char keycode = getKeycode(key_event);
unsigned char state = eventState(key_event); unsigned char state = eventState(key_event);
//printf("Reading a key %d %d count %d\n", (int)keycode, (int)state, num_events);
translateEvent(key_event, keycode, state); translateEvent(key_event, keycode, state);
} }