以下代码将打印整个 keycode-to-keysym 映射。它相当于xmodmap -pk 或xmodmap -pke。也就是说,给定任何键码,它都会为您提供与该键码关联的键符。
(除了它只显示keysym values,不显示keysym names,你可以在/usr/include/X11/keysymdef.h或使用Xlib的XKeysymToString()找到,我没有认为存在该功能的 XCB 端口,但您可以根据 keysymdef.h 编写自己的端口。)(在我的 X 服务器上,每个键码有 7 个键符,我想知道 X 服务器是否可以支持超过那……)
/*
gcc keymap.c -o keymap -lxcb && ./keymap
*/
#include <stdlib.h>
#include <stdio.h>
#include <xcb/xcb.h>
void xcb_show_keyboard_mapping(xcb_connection_t* connection, const xcb_setup_t* setup){
xcb_get_keyboard_mapping_reply_t* keyboard_mapping =
xcb_get_keyboard_mapping_reply(
connection,
xcb_get_keyboard_mapping(
connection,
setup->min_keycode,
setup->max_keycode - setup->min_keycode + 1),
NULL);
int nkeycodes = keyboard_mapping->length / keyboard_mapping->keysyms_per_keycode;
int nkeysyms = keyboard_mapping->length;
xcb_keysym_t* keysyms = (xcb_keysym_t*)(keyboard_mapping + 1); // `xcb_keycode_t` is just a `typedef u8`, and `xcb_keysym_t` is just a `typedef u32`
printf("nkeycodes %u nkeysyms %u keysyms_per_keycode %u\n\n", nkeycodes, nkeysyms, keyboard_mapping->keysyms_per_keycode);
for(int keycode_idx=0; keycode_idx < nkeycodes; ++keycode_idx){
printf("keycode %3u ", setup->min_keycode + keycode_idx);
for(int keysym_idx=0; keysym_idx < keyboard_mapping->keysyms_per_keycode; ++keysym_idx){
printf(" %8x", keysyms[keysym_idx + keycode_idx * keyboard_mapping->keysyms_per_keycode]);
}
putchar('\n');
}
free(keyboard_mapping);
}
int main(){
xcb_connection_t* connection = xcb_connect(NULL, NULL);
const xcb_setup_t* setup = xcb_get_setup(connection);
xcb_show_keyboard_mapping(connection, setup);
xcb_disconnect(connection);
}
如果你想要相反的映射(keysyms-to-keycodes),你可能想要xcb_key_symbols_get_keycode(),我不知道。
不,你不需要 XKB 来处理键盘的东西。您可能想要的大部分内容都可以使用核心 X 协议完成,包括但不限于修改上述键码到键符号的映射、抓取键盘、抓取鼠标、发送键盘/鼠标输入,使用所有 8 个修饰符,并写入“伪 Unicode”(即您在 keysymdef.h 中找到的所有符号,我认为这不是官方的 Unicode,但确实包含很多东西)。