mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-06 01:40:22 -05:00
input: kitty: add initial unit test
Test a couple of key combos from the se and de(neo) layouts. This unit test isn't intended to test _all_ key combinations, for all kitty flag combinations, but to be more of a regression test - whenever we discover a buggy, weird combo, add it here.
This commit is contained in:
parent
786037791c
commit
09f718878f
1 changed files with 229 additions and 0 deletions
229
input.c
229
input.c
|
|
@ -1752,6 +1752,235 @@ keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
|
||||||
term_xcursor_update_for_seat(seat->kbd_focus, seat);
|
term_xcursor_update_for_seat(seat->kbd_focus, seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UNITTEST
|
||||||
|
{
|
||||||
|
int chan[2];
|
||||||
|
pipe2(chan, O_CLOEXEC);
|
||||||
|
|
||||||
|
xassert(chan[0] >= 0);
|
||||||
|
xassert(chan[1] >= 0);
|
||||||
|
|
||||||
|
struct config conf = {0};
|
||||||
|
struct grid grid = {0};
|
||||||
|
|
||||||
|
struct terminal term = {
|
||||||
|
.conf = &conf,
|
||||||
|
.grid = &grid,
|
||||||
|
.ptmx = chan[1],
|
||||||
|
.selection = {
|
||||||
|
.coords = {
|
||||||
|
.start = {-1, -1},
|
||||||
|
.end = {-1, -1},
|
||||||
|
},
|
||||||
|
.auto_scroll = {
|
||||||
|
.fd = -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
struct key_binding_manager *key_binding_manager = key_binding_manager_new();
|
||||||
|
|
||||||
|
struct wayland wayl = {
|
||||||
|
.key_binding_manager = key_binding_manager,
|
||||||
|
.terms = tll_init(),
|
||||||
|
};
|
||||||
|
|
||||||
|
struct seat seat = {
|
||||||
|
.wayl = &wayl,
|
||||||
|
.name = "unittest",
|
||||||
|
};
|
||||||
|
|
||||||
|
tll_push_back(wayl.terms, &term);
|
||||||
|
term.wl = &wayl;
|
||||||
|
|
||||||
|
seat.kbd.xkb = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||||
|
xassert(seat.kbd.xkb != NULL);
|
||||||
|
|
||||||
|
grid.kitty_kbd.flags[0] = KITTY_KBD_DISAMBIGUATE | KITTY_KBD_REPORT_ALTERNATE;
|
||||||
|
|
||||||
|
/* Swedish keymap */
|
||||||
|
{
|
||||||
|
seat.kbd.xkb_keymap = xkb_keymap_new_from_names(
|
||||||
|
seat.kbd.xkb, &(struct xkb_rule_names){.layout = "se"}, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
if (seat.kbd.xkb_keymap == NULL) {
|
||||||
|
/* Skip test */
|
||||||
|
goto no_keymap;
|
||||||
|
}
|
||||||
|
|
||||||
|
seat.kbd.xkb_state = xkb_state_new(seat.kbd.xkb_keymap);
|
||||||
|
xassert(seat.kbd.xkb_state != NULL);
|
||||||
|
|
||||||
|
seat.kbd.mod_shift = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_SHIFT);
|
||||||
|
seat.kbd.mod_alt = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_ALT) ;
|
||||||
|
seat.kbd.mod_ctrl = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_CTRL);
|
||||||
|
seat.kbd.mod_super = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_LOGO);
|
||||||
|
seat.kbd.mod_caps = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_CAPS);
|
||||||
|
seat.kbd.mod_num = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_NUM);
|
||||||
|
|
||||||
|
/* Significant modifiers in the legacy keyboard protocol */
|
||||||
|
seat.kbd.legacy_significant = 0;
|
||||||
|
if (seat.kbd.mod_shift != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_shift;
|
||||||
|
if (seat.kbd.mod_alt != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_alt;
|
||||||
|
if (seat.kbd.mod_ctrl != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_ctrl;
|
||||||
|
if (seat.kbd.mod_super != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_super;
|
||||||
|
|
||||||
|
/* Significant modifiers in the kitty keyboard protocol */
|
||||||
|
seat.kbd.kitty_significant = seat.kbd.legacy_significant;
|
||||||
|
if (seat.kbd.mod_caps != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.kitty_significant |= 1 << seat.kbd.mod_caps;
|
||||||
|
if (seat.kbd.mod_num != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.kitty_significant |= 1 << seat.kbd.mod_num;
|
||||||
|
|
||||||
|
key_binding_new_for_seat(key_binding_manager, &seat);
|
||||||
|
key_binding_load_keymap(key_binding_manager, &seat);
|
||||||
|
|
||||||
|
{
|
||||||
|
xkb_mod_mask_t mods = 1u << seat.kbd.mod_shift | 1u << seat.kbd.mod_ctrl;
|
||||||
|
keyboard_modifiers(&seat, NULL, 1337, mods, 0, 0, 0);
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_A + 8, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
|
||||||
|
char escape[64] = {0};
|
||||||
|
ssize_t count = read(chan[0], escape, sizeof(escape));
|
||||||
|
|
||||||
|
/* key: 97 = 'a', alternate: 65 = 'A', base: N/A, mods: 6 = ctrl+shift */
|
||||||
|
const char expected_ctrl_shift_a[] = "\033[97:65;6u";
|
||||||
|
xassert(count == strlen(expected_ctrl_shift_a));
|
||||||
|
xassert(streq(escape, expected_ctrl_shift_a));
|
||||||
|
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_A + 8, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
xkb_mod_mask_t mods = 1u << seat.kbd.mod_shift | 1u << seat.kbd.mod_alt;
|
||||||
|
keyboard_modifiers(&seat, NULL, 1337, mods, 0, 0, 0);
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_2 + 8, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
|
||||||
|
char escape[64] = {0};
|
||||||
|
ssize_t count = read(chan[0], escape, sizeof(escape));
|
||||||
|
|
||||||
|
/* key;. 50 = '2', alternate: 34 = '"', base: N/A, 4 = alt+shift */
|
||||||
|
const char expected_alt_shift_2[] = "\033[50:34;4u";
|
||||||
|
xassert(count == strlen(expected_alt_shift_2));
|
||||||
|
xassert(streq(escape, expected_alt_shift_2));
|
||||||
|
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_2 + 8, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
xkb_mod_index_t alt_gr = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, "Mod5");
|
||||||
|
xassert(alt_gr != XKB_MOD_INVALID);
|
||||||
|
|
||||||
|
xkb_mod_mask_t mods = 1u << seat.kbd.mod_shift | 1u << seat.kbd.mod_alt | 1u << alt_gr;
|
||||||
|
keyboard_modifiers(&seat, NULL, 1337, mods, 0, 0, 0);
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_2 + 8, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
|
||||||
|
char escape[64] = {0};
|
||||||
|
ssize_t count = read(chan[0], escape, sizeof(escape));
|
||||||
|
|
||||||
|
/* key; 178 = '²', alternate: N/A, base: 50 = '2', 4 = alt+shift (AltGr not part of the protocol) */
|
||||||
|
const char expected_altgr_alt_shift_2[] = "\033[178::50;4u";
|
||||||
|
xassert(count == strlen(expected_altgr_alt_shift_2));
|
||||||
|
xassert(streq(escape, expected_altgr_alt_shift_2));
|
||||||
|
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_2 + 8, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
key_binding_unload_keymap(key_binding_manager, &seat);
|
||||||
|
key_binding_remove_seat(key_binding_manager, &seat);
|
||||||
|
|
||||||
|
xkb_state_unref(seat.kbd.xkb_state);
|
||||||
|
xkb_keymap_unref(seat.kbd.xkb_keymap);
|
||||||
|
|
||||||
|
seat.kbd.xkb_state = NULL;
|
||||||
|
seat.kbd.xkb_keymap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* de(neo) keymap */
|
||||||
|
{
|
||||||
|
seat.kbd.xkb_keymap = xkb_keymap_new_from_names(
|
||||||
|
seat.kbd.xkb, &(struct xkb_rule_names){.layout = "us,de(neo)"},
|
||||||
|
XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||||
|
|
||||||
|
if (seat.kbd.xkb_keymap == NULL) {
|
||||||
|
/* Skip test */
|
||||||
|
goto no_keymap;
|
||||||
|
}
|
||||||
|
|
||||||
|
seat.kbd.xkb_state = xkb_state_new(seat.kbd.xkb_keymap);
|
||||||
|
xassert(seat.kbd.xkb_state != NULL);
|
||||||
|
|
||||||
|
seat.kbd.mod_shift = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_SHIFT);
|
||||||
|
seat.kbd.mod_alt = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_ALT) ;
|
||||||
|
seat.kbd.mod_ctrl = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_CTRL);
|
||||||
|
seat.kbd.mod_super = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_LOGO);
|
||||||
|
seat.kbd.mod_caps = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_CAPS);
|
||||||
|
seat.kbd.mod_num = xkb_keymap_mod_get_index(seat.kbd.xkb_keymap, XKB_MOD_NAME_NUM);
|
||||||
|
|
||||||
|
/* Significant modifiers in the legacy keyboard protocol */
|
||||||
|
seat.kbd.legacy_significant = 0;
|
||||||
|
if (seat.kbd.mod_shift != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_shift;
|
||||||
|
if (seat.kbd.mod_alt != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_alt;
|
||||||
|
if (seat.kbd.mod_ctrl != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_ctrl;
|
||||||
|
if (seat.kbd.mod_super != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.legacy_significant |= 1 << seat.kbd.mod_super;
|
||||||
|
|
||||||
|
/* Significant modifiers in the kitty keyboard protocol */
|
||||||
|
seat.kbd.kitty_significant = seat.kbd.legacy_significant;
|
||||||
|
if (seat.kbd.mod_caps != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.kitty_significant |= 1 << seat.kbd.mod_caps;
|
||||||
|
if (seat.kbd.mod_num != XKB_MOD_INVALID)
|
||||||
|
seat.kbd.kitty_significant |= 1 << seat.kbd.mod_num;
|
||||||
|
|
||||||
|
key_binding_new_for_seat(key_binding_manager, &seat);
|
||||||
|
key_binding_load_keymap(key_binding_manager, &seat);
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* In the de(neo) layout, the Y key generates 'k'. This
|
||||||
|
* means we should get a key+alternate that indiciates
|
||||||
|
* 'k', but a base key that is 'y'.
|
||||||
|
*/
|
||||||
|
xkb_mod_mask_t mods = 1u << seat.kbd.mod_shift | 1u << seat.kbd.mod_alt;
|
||||||
|
keyboard_modifiers(&seat, NULL, 1337, mods, 0, 0, 1);
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_Y + 8, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||||
|
|
||||||
|
char escape[64] = {0};
|
||||||
|
ssize_t count = read(chan[0], escape, sizeof(escape));
|
||||||
|
|
||||||
|
/* key: 107 = 'k', alternate: 75 = 'K', base: 121 = 'y', mods: 4 = alt+shift */
|
||||||
|
const char expected_alt_shift_y[] = "\033[107:75:121;4u";
|
||||||
|
xassert(count == strlen(expected_alt_shift_y));
|
||||||
|
xassert(streq(escape, expected_alt_shift_y));
|
||||||
|
|
||||||
|
key_press_release(&seat, &term, 1337, KEY_Y + 8, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||||
|
}
|
||||||
|
|
||||||
|
key_binding_unload_keymap(key_binding_manager, &seat);
|
||||||
|
key_binding_remove_seat(key_binding_manager, &seat);
|
||||||
|
|
||||||
|
xkb_state_unref(seat.kbd.xkb_state);
|
||||||
|
xkb_keymap_unref(seat.kbd.xkb_keymap);
|
||||||
|
|
||||||
|
seat.kbd.xkb_state = NULL;
|
||||||
|
seat.kbd.xkb_keymap = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
no_keymap:
|
||||||
|
xkb_context_unref(seat.kbd.xkb);
|
||||||
|
key_binding_manager_destroy(key_binding_manager);
|
||||||
|
|
||||||
|
tll_free(wayl.terms);
|
||||||
|
close(chan[0]);
|
||||||
|
close(chan[1]);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
|
keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
|
||||||
int32_t rate, int32_t delay)
|
int32_t rate, int32_t delay)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue