test: the xkb modifier mask and the forwarded key bitmap

The two pure things in the Wayland frontend, in the shape the XIM adapter
test already uses: wl.c included behind one define that makes the virtual
keyboard inert, and a keymap built from a string, so no compositor and no
xkb data files are wanted.  The mask test holds Caps Lock apart from
Shift, which is what a Korean key turns on; the bitmap test holds a
release of a key we never passed on, a code the bitmap cannot hold, and
the release of everything still down when the context goes.

wayland-scanner's output is the parent Makefile's to write, as ../strans
already is.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 19:51:37 +09:00
parent 2e1e0b9645
commit ad2f2fc5eb
4 changed files with 121 additions and 3 deletions

View File

@@ -20,7 +20,9 @@ X11_CFLAGS = $(shell $(PKG_CONFIG) --cflags x11)
X11_LIBS = $(shell $(PKG_CONFIG) --libs x11) X11_LIBS = $(shell $(PKG_CONFIG) --libs x11)
XIM_CFLAGS = $(shell $(PKG_CONFIG) --cflags xcb-imdkit xcb-aux xcb-xkb xkbcommon-x11) XIM_CFLAGS = $(shell $(PKG_CONFIG) --cflags xcb-imdkit xcb-aux xcb-xkb xkbcommon-x11)
XIM_LIBS = $(shell $(PKG_CONFIG) --libs xcb-imdkit xcb-aux xcb-xkb xkbcommon-x11) XIM_LIBS = $(shell $(PKG_CONFIG) --libs xcb-imdkit xcb-aux xcb-xkb xkbcommon-x11)
UNIT_LDLIBS = -lthread -lbio $(TEXT_LIBS) $(IBUS_LIBS) $(XIM_LIBS) WL_CFLAGS = $(shell $(PKG_CONFIG) --cflags wayland-client xkbcommon)
WL_LIBS = $(shell $(PKG_CONFIG) --libs wayland-client xkbcommon)
UNIT_LDLIBS = -lthread -lbio $(TEXT_LIBS) $(IBUS_LIBS) $(XIM_LIBS) $(WL_LIBS)
PROG = unit_test PROG = unit_test
STRESS = stress_test STRESS = stress_test
@@ -33,10 +35,11 @@ LIVE = $(SMOKE) $(FAULT)
TESTSRC = test_util.c str_test.c trie_test.c \ TESTSRC = test_util.c str_test.c trie_test.c \
ko_test.c vi_test.c engine_test.c dict_test.c ipc_test.c \ ko_test.c vi_test.c engine_test.c dict_test.c ipc_test.c \
popup_test.c font_test.c ibus_test.c server_test.c compose_test.c \ popup_test.c font_test.c ibus_test.c server_test.c compose_test.c \
xim_adapter_test.c xim_adapter_test.c wl_adapter_test.c
TESTOBJ = $(TESTSRC:.c=.o) TESTOBJ = $(TESTSRC:.c=.o)
# imv2.c and vkv1.c are wayland-scanner's; the parent Makefile writes them.
PARENTSRC = str.c trie.c dict.c ko.c vi.c ipc.c popup_layout.c \ PARENTSRC = str.c trie.c dict.c ko.c vi.c ipc.c popup_layout.c \
font.c compose.c font.c compose.c imv2.c vkv1.c
PARENTOBJ = $(PARENTSRC:%.c=unit_%.o) PARENTOBJ = $(PARENTSRC:%.c=unit_%.o)
COMMONOBJ = $(TESTOBJ) $(PARENTOBJ) COMMONOBJ = $(TESTOBJ) $(PARENTOBJ)
OBJS = unit_test.o stress_test.o $(COMMONOBJ) OBJS = unit_test.o stress_test.o $(COMMONOBJ)
@@ -92,6 +95,9 @@ gtk_live_test: gtk_live_test.c $(LIVESRC) ../ipc.c ../ipc.h
../strans: ../strans:
$(MAKE) -C .. strans $(MAKE) -C .. strans
../imv2.c ../imv2.h ../vkv1.c ../vkv1.h:
$(MAKE) -C .. $(@F)
xim_live_test: xim_live_test.c $(LIVESRC) ../ipc.c ../ipc.h xim_live_test: xim_live_test.c $(LIVESRC) ../ipc.c ../ipc.h
$(HOSTCC) $(CPPFLAGS) -I.. $(X11_CFLAGS) $(HOST_CFLAGS) $(CFLAGS) \ $(HOSTCC) $(CPPFLAGS) -I.. $(X11_CFLAGS) $(HOST_CFLAGS) $(CFLAGS) \
$(LDFLAGS) -o $@ xim_live_test.c live.c ../ipc.c $(X11_LIBS) \ $(LDFLAGS) -o $@ xim_live_test.c live.c ../ipc.c $(X11_LIBS) \
@@ -124,6 +130,8 @@ ibus_test.o: UNIT_CPPFLAGS += $(IBUS_CFLAGS)
ibus_test.o: ../ibus.c ibus_test.o: ../ibus.c
xim_adapter_test.o: UNIT_CPPFLAGS += $(XIM_CFLAGS) xim_adapter_test.o: UNIT_CPPFLAGS += $(XIM_CFLAGS)
xim_adapter_test.o: ../xim.c xim_adapter_test.o: ../xim.c
wl_adapter_test.o unit_imv2.o unit_vkv1.o: UNIT_CPPFLAGS += $(WL_CFLAGS)
wl_adapter_test.o: ../wl.c ../imv2.h ../vkv1.h
server_test.o: ../srv.c server_test.o: ../srv.c
unit_font.o: UNIT_CPPFLAGS += $(TEXT_CFLAGS) unit_font.o: UNIT_CPPFLAGS += $(TEXT_CFLAGS)
unit_compose.o compose_test.o: UNIT_CPPFLAGS += $(IBUS_CFLAGS) unit_compose.o compose_test.o: UNIT_CPPFLAGS += $(IBUS_CFLAGS)

View File

@@ -125,3 +125,5 @@ void xim_adapter_callback_cleanup(struct ct*);
void xim_adapter_callback_transfer(struct ct*); void xim_adapter_callback_transfer(struct ct*);
void xim_adapter_callback_owner_loss(struct ct*); void xim_adapter_callback_owner_loss(struct ct*);
void xim_adapter_commit_encoding(struct ct*); void xim_adapter_commit_encoding(struct ct*);
void wl_modifier_mask(struct ct*);
void wl_forwarded_keys(struct ct*);

View File

@@ -145,6 +145,8 @@ static const struct ct_test tests[] = {
{ "xim/callback-transfer", xim_adapter_callback_transfer }, { "xim/callback-transfer", xim_adapter_callback_transfer },
{ "xim/callback-owner-loss", xim_adapter_callback_owner_loss }, { "xim/callback-owner-loss", xim_adapter_callback_owner_loss },
{ "xim/commit-encoding", xim_adapter_commit_encoding }, { "xim/commit-encoding", xim_adapter_commit_encoding },
{ "wl/modifier-mask", wl_modifier_mask },
{ "wl/forwarded-keys", wl_forwarded_keys },
}; };
#else #else
static const struct ct_test tests[] = { static const struct ct_test tests[] = {

106
tests/wl_adapter_test.c Normal file
View File

@@ -0,0 +1,106 @@
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include "vkv1.h"
/* The virtual keyboard is the only wire call the tested code makes. */
static int nkeysent;
static void wirekey(struct zwp_virtual_keyboard_v1*, uint32_t, uint32_t,
uint32_t);
#define zwp_virtual_keyboard_v1_key wirekey
#include "wl.c"
#include "test.h"
static void
wirekey(struct zwp_virtual_keyboard_v1 *vkb, uint32_t time, uint32_t code,
uint32_t state)
{
USED(vkb);
USED(time);
USED(code);
USED(state);
nkeysent++;
}
/* Only the modifiers are read from it, so nothing else need be here. */
static char keymaptext[] =
"xkb_keymap {\n"
"xkb_keycodes { <AD01> = 24; };\n"
"xkb_types { type \"ONE_LEVEL\" {\n"
" modifiers = none; map[none] = 1; level_name[1] = \"Any\"; }; };\n"
"xkb_compatibility { };\n"
"xkb_symbols { key <AD01> { [ q ] }; };\n"
"};\n";
void
wl_modifier_mask(struct ct *t)
{
struct xkb_context *ctx;
struct xkb_keymap *km;
xkb_mod_mask_t caps, ctrl, shift;
kstate = nil;
CT_EQ_UINT(t, 0, modmask()); /* before any keymap arrives */
ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
km = xkb_keymap_new_from_string(ctx, keymaptext,
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
CT_CHECK(t, km != nil);
if(km != nil){
kstate = xkb_state_new(km);
shift = (xkb_mod_mask_t)1 <<
xkb_keymap_mod_get_index(km, XKB_MOD_NAME_SHIFT);
ctrl = (xkb_mod_mask_t)1 <<
xkb_keymap_mod_get_index(km, XKB_MOD_NAME_CTRL);
caps = (xkb_mod_mask_t)1 <<
xkb_keymap_mod_get_index(km, XKB_MOD_NAME_CAPS);
xkb_state_update_mask(kstate, shift, 0, 0, 0, 0, 0);
CT_EQ_UINT(t, Mshift, modmask());
xkb_state_update_mask(kstate, shift|ctrl, 0, 0, 0, 0, 0);
CT_EQ_UINT(t, Mshift|Mctrl, modmask());
/* Caps Lock is not Shift; a Korean key must not shift under it. */
xkb_state_update_mask(kstate, 0, 0, caps, 0, 0, 0);
CT_EQ_UINT(t, 0, modmask());
xkb_state_unref(kstate);
kstate = nil;
xkb_keymap_unref(km);
}
xkb_context_unref(ctx);
}
void
wl_forwarded_keys(struct ct *t)
{
haskeymap = 1;
memset(sent, 0, sizeof sent);
nkeysent = 0;
forward(30, WL_KEYBOARD_KEY_STATE_PRESSED);
CT_CHECK(t, issent(30));
forward(30, WL_KEYBOARD_KEY_STATE_RELEASED);
CT_CHECK(t, !issent(30));
CT_EQ_INT(t, 2, nkeysent);
/* A code the bitmap cannot hold is not passed on at all. */
nkeysent = 0;
forward(Maxcode, WL_KEYBOARD_KEY_STATE_PRESSED);
CT_EQ_INT(t, 0, nkeysent);
/* Whatever is still down is released, once each and no more. */
forward(1, WL_KEYBOARD_KEY_STATE_PRESSED);
forward(200, WL_KEYBOARD_KEY_STATE_PRESSED);
nkeysent = 0;
releasekeys();
CT_EQ_INT(t, 2, nkeysent);
CT_CHECK(t, !issent(1));
CT_CHECK(t, !issent(200));
releasekeys();
CT_EQ_INT(t, 2, nkeysent);
/* Before a keymap the virtual keyboard must not be touched. */
haskeymap = 0;
nkeysent = 0;
forward(30, WL_KEYBOARD_KEY_STATE_PRESSED);
CT_EQ_INT(t, 0, nkeysent);
CT_CHECK(t, !issent(30));
}