emul: don't hardcode X11 keycodes in key handling routines
I thought it wasn't possible with XCB to transform keycodes into symbols for the current keyboard mapping, but I hadn't looked hard enough.
This commit is contained in:
parent
473d04d7d9
commit
cc8068f8ab
@ -4,6 +4,8 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#define XK_MISCELLANY
|
||||
#include <X11/keysymdef.h>
|
||||
|
||||
#include "../../emul.h"
|
||||
#include "vdp.h"
|
||||
@ -153,6 +155,48 @@ void draw_pixels()
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
||||
// Returns true to exist event loop
|
||||
static bool _handle_keypress(xcb_generic_event_t *e)
|
||||
{
|
||||
xcb_key_press_event_t *ev = (xcb_key_press_event_t *)e;
|
||||
bool ispressed = e->response_type == XCB_KEY_PRESS;
|
||||
// change keycode into symbol
|
||||
xcb_get_keyboard_mapping_reply_t* km = xcb_get_keyboard_mapping_reply(
|
||||
conn, xcb_get_keyboard_mapping(conn, ev->detail, 1), NULL);
|
||||
if (km->length) {
|
||||
xcb_keysym_t* keysyms = (xcb_keysym_t*)(km + 1);
|
||||
switch (keysyms[0]) {
|
||||
case XK_Escape: free(km); return true;
|
||||
case 'w':
|
||||
pad_setbtn(&pad, PAD_BTN_UP, ispressed);
|
||||
break;
|
||||
case 'a':
|
||||
pad_setbtn(&pad, PAD_BTN_LEFT, ispressed);
|
||||
break;
|
||||
case 's':
|
||||
pad_setbtn(&pad, PAD_BTN_DOWN, ispressed);
|
||||
break;
|
||||
case 'd':
|
||||
pad_setbtn(&pad, PAD_BTN_RIGHT, ispressed);
|
||||
break;
|
||||
case 'h':
|
||||
pad_setbtn(&pad, PAD_BTN_A, ispressed);
|
||||
break;
|
||||
case 'j':
|
||||
pad_setbtn(&pad, PAD_BTN_B, ispressed);
|
||||
break;
|
||||
case 'k':
|
||||
pad_setbtn(&pad, PAD_BTN_C, ispressed);
|
||||
break;
|
||||
case 'l':
|
||||
pad_setbtn(&pad, PAD_BTN_START, ispressed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(km);
|
||||
return false;
|
||||
}
|
||||
|
||||
void event_loop()
|
||||
{
|
||||
while (1) {
|
||||
@ -183,38 +227,9 @@ void event_loop()
|
||||
switch (e->response_type & ~0x80) {
|
||||
/* ESC to exit */
|
||||
case XCB_KEY_RELEASE:
|
||||
case XCB_KEY_PRESS: {
|
||||
xcb_key_press_event_t *ev = (xcb_key_press_event_t *)e;
|
||||
bool ispressed = e->response_type == XCB_KEY_PRESS;
|
||||
switch (ev->detail) {
|
||||
case 0x09: return; // ESC
|
||||
case 0x19: // W
|
||||
pad_setbtn(&pad, PAD_BTN_UP, ispressed);
|
||||
break;
|
||||
case 0x26: // A
|
||||
pad_setbtn(&pad, PAD_BTN_LEFT, ispressed);
|
||||
break;
|
||||
case 0x27: // S
|
||||
pad_setbtn(&pad, PAD_BTN_DOWN, ispressed);
|
||||
break;
|
||||
case 0x28: // D
|
||||
pad_setbtn(&pad, PAD_BTN_RIGHT, ispressed);
|
||||
break;
|
||||
case 0x2b: // H
|
||||
pad_setbtn(&pad, PAD_BTN_A, ispressed);
|
||||
break;
|
||||
case 0x2c: // J
|
||||
pad_setbtn(&pad, PAD_BTN_B, ispressed);
|
||||
break;
|
||||
case 0x2d: // K
|
||||
pad_setbtn(&pad, PAD_BTN_C, ispressed);
|
||||
break;
|
||||
case 0x2e: // L
|
||||
pad_setbtn(&pad, PAD_BTN_START, ispressed);
|
||||
break;
|
||||
}
|
||||
case XCB_KEY_PRESS:
|
||||
if (_handle_keypress(e)) return;
|
||||
break;
|
||||
}
|
||||
case XCB_EXPOSE: {
|
||||
draw_pixels();
|
||||
break;
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#define XK_MISCELLANY
|
||||
#include <X11/keysymdef.h>
|
||||
|
||||
#include "../../emul.h"
|
||||
#include "t6a04.h"
|
||||
@ -83,64 +85,72 @@ static void iowr_interrupt(uint8_t val)
|
||||
}
|
||||
}
|
||||
|
||||
// TIL: XCB doesn't have a builtin way to translate a keycode to an ASCII char.
|
||||
// Using Xlib looks complicated. This will probably not work in many cases (non
|
||||
// query keyboards and all...), but for now, let's go with this.
|
||||
static uint8_t keycode_to_tikbd(xcb_keycode_t kc)
|
||||
{
|
||||
switch (kc) {
|
||||
case 0x0a: return 0x41; // 1
|
||||
case 0x0b: return 0x31; // 2
|
||||
case 0x0c: return 0x21; // 3
|
||||
case 0x0d: return 0x42; // 4
|
||||
case 0x0e: return 0x32; // 5
|
||||
case 0x0f: return 0x22; // 6
|
||||
case 0x10: return 0x43; // 7
|
||||
case 0x11: return 0x33; // 8
|
||||
case 0x12: return 0x23; // 9
|
||||
case 0x13: return 0x40; // 0
|
||||
case 0x14: return 0x12; // -
|
||||
case 0x15: return 0x11; // +
|
||||
case 0x16: return 0x67; // DEL
|
||||
case 0x18: return 0x23; // Q
|
||||
case 0x19: return 0x12; // W
|
||||
case 0x1a: return 0x45; // E
|
||||
case 0x1b: return 0x13; // R
|
||||
case 0x1c: return 0x42; // T
|
||||
case 0x1d: return 0x41; // Y
|
||||
case 0x1e: return 0x32; // U
|
||||
case 0x1f: return 0x54; // I
|
||||
case 0x20: return 0x43; // O
|
||||
case 0x21: return 0x33; // P
|
||||
case 0x22: return 0x34; // (
|
||||
case 0x23: return 0x24; // )
|
||||
case 0x24: return 0x10; // Return
|
||||
case 0x25: return KBD_ALPHA; // LCTRL
|
||||
case 0x26: return 0x56; // A
|
||||
case 0x27: return 0x52; // S
|
||||
case 0x28: return 0x55; // D
|
||||
case 0x29: return 0x35; // F
|
||||
case 0x2a: return 0x25; // G
|
||||
case 0x2b: return 0x15; // H
|
||||
case 0x2c: return 0x44; // J
|
||||
case 0x2d: return 0x34; // K
|
||||
case 0x2e: return 0x24; // L
|
||||
case 0x2f: return 0x30; // :
|
||||
case 0x30: return 0x11; // "
|
||||
case 0x32: return KBD_2ND; // Lshift
|
||||
case 0x34: return 0x31; // Z
|
||||
case 0x35: return 0x51; // X
|
||||
case 0x36: return 0x36; // C
|
||||
case 0x37: return 0x22; // V
|
||||
case 0x38: return 0x46; // B
|
||||
case 0x39: return 0x53; // N
|
||||
case 0x3a: return 0x14; // M
|
||||
case 0x3b: return 0x44; // ,
|
||||
case 0x3c: return 0x30; // .
|
||||
case 0x3d: return 0x20; // ?
|
||||
case 0x41: return 0x40; // Space
|
||||
default: return 0;
|
||||
// First, change keycode into symbol
|
||||
xcb_get_keyboard_mapping_reply_t* km = xcb_get_keyboard_mapping_reply(
|
||||
conn, xcb_get_keyboard_mapping(conn, kc, 1), NULL);
|
||||
xcb_keysym_t* keysyms = (xcb_keysym_t*)(km + 1);
|
||||
uint8_t res = 0;
|
||||
for (int i=0; i<km->length; i++) {
|
||||
switch (keysyms[0]) {
|
||||
case XK_Shift_L: res = KBD_2ND; break;
|
||||
case XK_Control_L: res = KBD_ALPHA; break;
|
||||
case XK_Return: res = 0x10; break;
|
||||
case XK_Delete: res = 0x67; break;
|
||||
case ' ': res = 0x40; break;
|
||||
case '1': res = 0x41; break;
|
||||
case '2': res = 0x31; break;
|
||||
case '3': res = 0x21; break;
|
||||
case '4': res = 0x42; break;
|
||||
case '5': res = 0x32; break;
|
||||
case '6': res = 0x22; break;
|
||||
case '7': res = 0x43; break;
|
||||
case '8': res = 0x33; break;
|
||||
case '9': res = 0x23; break;
|
||||
case '0': res = 0x40; break;
|
||||
case '-': res = 0x12; break;
|
||||
case '+': res = 0x11; break;
|
||||
case 'q': res = 0x23; break;
|
||||
case 'w': res = 0x12; break;
|
||||
case 'e': res = 0x45; break;
|
||||
case 'r': res = 0x13; break;
|
||||
case 't': res = 0x42; break;
|
||||
case 'y': res = 0x41; break;
|
||||
case 'u': res = 0x32; break;
|
||||
case 'i': res = 0x54; break;
|
||||
case 'o': res = 0x43; break;
|
||||
case 'p': res = 0x33; break;
|
||||
case '(': res = 0x34; break;
|
||||
case ')': res = 0x24; break;
|
||||
case 'a': res = 0x56; break;
|
||||
case 's': res = 0x52; break;
|
||||
case 'd': res = 0x55; break;
|
||||
case 'f': res = 0x35; break;
|
||||
case 'g': res = 0x25; break;
|
||||
case 'h': res = 0x15; break;
|
||||
case 'j': res = 0x44; break;
|
||||
case 'k': res = 0x34; break;
|
||||
case 'l': res = 0x24; break;
|
||||
case ':': res = 0x30; break;
|
||||
case '"': res = 0x11; break;
|
||||
case 'z': res = 0x31; break;
|
||||
case 'x': res = 0x51; break;
|
||||
case 'c': res = 0x36; break;
|
||||
case 'v': res = 0x22; break;
|
||||
case 'b': res = 0x46; break;
|
||||
case 'n': res = 0x53; break;
|
||||
case 'm': res = 0x14; break;
|
||||
case ',': res = 0x44; break;
|
||||
case '.': res = 0x30; break;
|
||||
case '?': res = 0x20; break;
|
||||
}
|
||||
if (res) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(km);
|
||||
return res;
|
||||
}
|
||||
|
||||
void create_window()
|
||||
|
Loading…
Reference in New Issue
Block a user