Получение раскладки клавиатуры и клавиш с помощью XCB

Я создаю экранную клавиатуру для Linux, интегрированную в простой диспетчер окон. В настоящее время я использую XCB, и теперь я хочу сделать ложные нажатия клавиш. Все работает нормально, используя расширение xtest, за исключением деталей, которые я не могу получить истинные коды клавиш из ключей, которые я хочу поставить.

В настоящее время я использую xcb_key_symbols_get_keycode, а затем я использую xcb_key_symbols_get_keysym, чтобы узнать, какой модификатор мне нужен, чтобы получить этот символ. Это прекрасно работает, когда настроенная клавиатура является США. Но у меня есть испанская клавиатура, и этот вызов возвращает только настройки США. В испанских клавиатурах несколько символов получаются с правым alt (altgr), но предыдущие вызовы, кажется, не поддерживают это.

Итак, как я могу получить коды клавиш, необходимые для получения любых ключей? Я предполагаю, что мне нужны расширения XKB, но я не смог найти их для XCB, и я не хочу переписывать весь оконный менеджер для XLib.

Благодарю.

2 ответа

Вероятно, это устаревшая проблема, но я считаю, что она по-прежнему актуальна.

Вы можете включить расширения xkb через xcb, а затем получить раскладку, ее раскладку и соответствующий симсит для этой раскладки через API xcb (или, более конкретно, из состояния раскладки xkb).

Ссылки:

  • libxkbcommon Быстрый старт
  • Поддержка X11 для настройки расширения xkb и получения идентификатора устройства (см. Предыдущую ссылку: необходимо создать расширение, прежде чем пытаться получить доступ к любому xcb_x11 звонки). (с идентификатором устройства вы можете позвонить xkb_x11_keymap_new_from_device вернуть xkb_keymap указатель).
  • xkb_keymap struct
  • Состояние клавиатуры (и что более важно xkb_state_key_get_sym()) здесь вы можете использовать xkb_state, чтобы получить sym для соответствующего ключа.

Я должен признать, что на самом деле я еще не сделал это полностью (только до раскладки / раскладки / состояния). Но этого должно быть достаточно, чтобы вы начали.:)

Следующий код распечатает полное сопоставление кода ключа с ключом. Это эквивалентно xmodmap -pk или же xmodmap -pke, То есть, учитывая любой код ключа, он дает вам ключевые символы, связанные с этим кодом ключа.

(За исключением того, что он показывает только значения keysym, а не имена keysym, которые вы можете найти в /usr/include/X11/keysymdef.h или используя Xlib's 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);
}

Если вы хотите обратное сопоставление (коды-коды-ключи), вы можете захотеть xcb_key_symbols_get_keycode(), Я не знаю.


И нет, вам не нужен XKB для работы с клавиатурой. Большинство вещей, которые вы, возможно, захотите, могут быть выполнены с помощью основного протокола X, включая, но не ограничиваясь, модификацию вышеупомянутого сопоставления код-ключ-клавиатура, захват клавиатуры, захват мыши, отправка ввода с клавиатуры / мыши, используя все 8 модификаторов. и писать "псевдо Юникод" (т.е. все символы, которые вы найдете в keysymdef.h, который я не думаю, что официально Unicode, но содержит много вещей).

Другие вопросы по тегам