Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discover X keycodes at runtime, as they are server dependent. #8

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion os.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
#include "os_sound_linux.c"
#include "os_thread_linux.c"
#include "os_window_x11.c"
#include "os_x11_keys_linux.c"
/* #include "os_x11_keys_linux.c" */
#include "os_x11_keys_generic.c"

#else
#error Not yet ported to Windows, Mac, etc.
Expand Down
2 changes: 1 addition & 1 deletion os_window_x11.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ os_window_create(uint32_t width, uint32_t height) {
errx(1, "XFlush failed");
}

p_window->p_key_map = os_x11_keys_get_mapping();
p_window->p_key_map = os_x11_keys_get_mapping(p_window->d);

return p_window;
}
Expand Down
2 changes: 1 addition & 1 deletion os_x11_keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
#define OS_X11_KEYS_H

/* Must return a 256 array mapping to keyboard.h values. */
uint8_t* os_x11_keys_get_mapping();
uint8_t* os_x11_keys_get_mapping(void* display);
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved

#endif /* OS_X11_KEYS_H */
170 changes: 170 additions & 0 deletions os_x11_keys_generic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
#include "os_x11_keys.h"

#include <X11/Xlib.h>

struct mapping_struct {
const char *x_key_name;
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
uint8_t key;
};

static const struct mapping_struct s_x_keys_mapping[] = {
{"Escape", k_keyboard_key_escape},
{"0", '0'},
{"1", '1'},
{"2", '2'},
{"3", '3'},
{"4", '4'},
{"5", '5'},
{"6", '6'},
{"7", '7'},
{"8", '8'},
{"9", '9'},
{"minus", '-'},
{"equal", '='},
{"BackSpace", k_keyboard_key_backspace},

{"Tab", k_keyboard_key_tab},
{"Q", 'Q'},
{"W", 'W'},
{"E", 'E'},
{"R", 'R'},
{"T", 'T'},
{"Y", 'Y'},
{"U", 'U'},
{"I", 'I'},
{"O", 'O'},
{"P", 'P'},
{"bracketleft", '['},
{"bracketright", ']'},
{"backslash", '\\'},

{"Caps_Lock", k_keyboard_key_caps_lock},
{"A", 'A'},
{"S", 'S'},
{"D", 'D'},
{"F", 'F'},
{"G", 'G'},
{"H", 'H'},
{"J", 'J'},
{"K", 'K'},
{"L", 'L'},
{"semicolon", ';'},
{"apostrophe", '\''},
{"Return", k_keyboard_key_enter},

{"Shift_L", k_keyboard_key_shift_left},
{"Z", 'Z'},
{"X", 'X'},
{"C", 'C'},
{"V", 'V'},
{"B", 'B'},
{"N", 'N'},
{"M", 'M'},
{"comma", ','},
{"period", '.'},
{"slash", '/'},
{"Shift_R", k_keyboard_key_shift_right},

{"Control_L", k_keyboard_key_ctrl_left},
{"Meta_L", k_keyboard_key_alt_left},
{"space", ' '},

{"F1", k_keyboard_key_f1},
{"F2", k_keyboard_key_f2},
{"F3", k_keyboard_key_f3},
{"F4", k_keyboard_key_f4},
{"F5", k_keyboard_key_f5},
{"F6", k_keyboard_key_f6},
{"F7", k_keyboard_key_f7},
{"F8", k_keyboard_key_f8},
{"F9", k_keyboard_key_f9},
{"F10", k_keyboard_key_f0},
{"F11", k_keyboard_key_f11},
{"F12", k_keyboard_key_f12},

{"Up", k_keyboard_key_arrow_up},
{"Down", k_keyboard_key_arrow_down},
{"Left", k_keyboard_key_arrow_left},
{"Right", k_keyboard_key_arrow_right},

{"End", k_keyboard_key_end},

{NULL},
};

static int s_keys_mapping_built;
static uint8_t s_keys_mapping[256];

/* XKeysymToKeycode only returns one keycode - but a keysym can map to multiple
* keycodes. So this code does an exhaustive search to find everything.
*
* There's probably a better way of doing this.
*/
static void
init_mapping(Display* display) {
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
const struct mapping_struct* p_mapping;
int keycode;
int min_keycode, max_keycode;
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
/* X keycodes are byte values, so 256 entries is sufficient. */
KeySym *keysyms[256];
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
int num_keysyms[256];

XDisplayKeycodes(display,&min_keycode,&max_keycode);
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved

tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
/* XGetKeyboardMapping took long enough on my Mac that it seems to be worth
* calling it for each keycode outside the loop. (The endless calls to
* XKeysymToString in the inner loop below, on the other hand, aren't
* obviously causing a problem.)
*/
for (keycode = min_keycode; keycode <= max_keycode; ++keycode) {
keysyms[keycode] = XGetKeyboardMapping(display,
keycode,
1,
&num_keysyms[keycode]);
}

for (p_mapping = s_x_keys_mapping; p_mapping->x_key_name != NULL; ++p_mapping) {
int found_x_key = 0;

for (keycode = min_keycode; keycode <= max_keycode; ++keycode) {
for (int i = 0; i < num_keysyms[keycode]; ++i) {
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
char *keysym_name = XKeysymToString(keysyms[keycode][i]);
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
if (keysym_name != NULL) {
if (strcmp(keysym_name, p_mapping->x_key_name) == 0) {
/* Can multiple keysyms map to the same keycode? Should probably
* print a warning if that happens. */
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
s_keys_mapping[keycode] = p_mapping->key;

found_x_key = 1;

/* Continue checking key codes. The same X key name might map to
* multiple physical keys. */
break;
}
}
}
}

if (!found_x_key) {
/* Not an error... right? This key presumably just isn't on the
* keyboard. */
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
log_do_log(k_log_misc, k_log_info, "X key not available: %s", p_mapping->x_key_name);
}
}

for (keycode = min_keycode; keycode <= max_keycode; ++keycode) {
XFree(keysyms[keycode]);
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
keysyms[keycode] = NULL;
}
}

uint8_t*
os_x11_keys_get_mapping(void* display) {
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
if(!s_keys_mapping_built) {
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
init_mapping(display);

s_keys_mapping_built=1;
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
}

return s_keys_mapping;
}
4 changes: 3 additions & 1 deletion os_x11_keys_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,9 @@ os_x11_keys_build_mapping() {
}

uint8_t*
os_x11_keys_get_mapping() {
os_x11_keys_get_mapping(void* display) {
tom-seddon marked this conversation as resolved.
Show resolved Hide resolved
(void) display;

if (!g_keys_mapping_built) {
os_x11_keys_build_mapping();
g_keys_mapping_built = 1;
Expand Down