[devel] looking for xkbcommon experts
Alexey Gladkov
legion на altlinux.ru
Ср Дек 29 19:18:09 MSK 2021
On Wed, Dec 29, 2021 at 06:23:14PM +0400, Igor Chudov wrote:
> Добрый день.
>
> А можно ли получить больше информации о том, какую задачу планируется решать? Это позволит понять, корректно ли
> задан вопрос и чем можно помочь.
Oк.
Я исследую возможность дампа keymap при заданной конфигурации. Например, у
меня есть конфигурация:
struct xkb_rule_names names = {
.rules = "evdev",
.model = "pc105",
.layout = "us,ru",
.variant = NULL,
.options = "grp:lctrl_toggle"
};
Я могу сделать дамп (см. аттач), но я не могу понять как получить какой
модификатор используется для переключения layout. Переключатель есть
только в options и там много чего ещё есть. Более того, как-то странно
парсить руками эти опции.
Возможно я слаб в этой библиотеке и не нашёл как получить
XKB_KEY_Control_L для указанной конфигруации. Поэтому и решил спросить
тут.
--
Rgrds, legion
----------- следующая часть -----------
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <xkbcommon/xkbcommon.h>
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
/* Offset between evdev keycodes (where KEY_ESCAPE is 1), and the evdev XKB
* keycode set (where ESC is 9). */
#define EVDEV_OFFSET 8
int main(int argc, char **argv)
{
struct xkb_context *ctx;
ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!ctx)
errx(EXIT_FAILURE, "xkb_context_new failed");
struct xkb_rule_names names = {
.rules = "evdev",
.model = "pc105",
.layout = "us,ru",
.variant = NULL,
.options = "grp:lctrl_toggle"
};
struct xkb_keymap *keymap;
keymap = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!keymap)
errx(EXIT_FAILURE, "xkb_keymap_new_from_names failed");
xkb_mod_index_t num_mods = xkb_keymap_num_mods(keymap);
for (xkb_keycode_t keycode = 1; keycode < 255; keycode++) {
xkb_keycode_t evdev_keycode = keycode + EVDEV_OFFSET;
xkb_layout_index_t num_layouts = xkb_keymap_num_layouts_for_key(keymap, evdev_keycode);
printf("keycode %3d =", keycode);
for (xkb_layout_index_t layout = 0; layout < num_layouts; layout++) {
xkb_level_index_t num_levels = xkb_keymap_num_levels_for_key(keymap, evdev_keycode, layout);
printf(" | {%s}", xkb_keymap_layout_get_name(keymap, layout));
for (xkb_level_index_t level = 0; level < num_levels; level++) {
xkb_mod_mask_t masks[100];
size_t num_masks;
const xkb_keysym_t *syms;
int num_syms;
memset(masks, 0, sizeof(masks));
num_masks = xkb_keymap_key_get_mods_for_level(keymap, evdev_keycode, layout, level, masks, ARRAY_SIZE(masks));
num_syms = xkb_keymap_key_get_syms_by_level(keymap, evdev_keycode, layout, level, &syms);
for (int i = 0; i < num_syms; i++) {
xkb_keysym_t sym = syms[i];
for (size_t m = 0; m < num_masks; m++) {
xkb_mod_mask_t mask = masks[m];
char s[255];
int ret;
ret = xkb_keysym_get_name(sym, s, sizeof(s));
if (ret < 0 || (size_t) ret >= sizeof(s))
errx(EXIT_FAILURE, "Failed to get name of keysym");
xkb_mod_index_t num_mods = xkb_keymap_num_mods(keymap);
printf(" (");
if (!mask)
printf("Plain");
int delim = 0;
for (xkb_mod_index_t mod = 0; mod < num_mods; mod++) {
if ((mask & (1 << mod)) == 0)
continue;
printf("%s%s",
(delim ? " " : ""),
xkb_keymap_mod_get_name(keymap, mod));
delim = 1;
}
printf(") %s,", s);
}
}
}
}
printf("\n");
}
return EXIT_SUCCESS;
}
Подробная информация о списке рассылки Devel