Harden pagedown-repeat test: TABBED_SYNTH_INPUT mode + stall-tolerant polling
TABBED_SYNTH_INPUT=1 makes the stdin event feed the only source of key/modifier input: host_kbd_key and host_kbd_modifiers drop real host events (kbd != NULL) while enter/leave/repeat_info still drive the clipboard bridge. A stray physical key (e.g. Alt) no longer cancels a synthesized repeat or clobbers the injected modifier state mid-test. The repeat test now polls for base+3 tab transitions with a 5s deadline instead of a fixed 1.3s sleep, so a present/frame stall no longer causes spurious failures.
This commit is contained in:
parent
198c329df7
commit
dc6f8f97c2
2 changed files with 32 additions and 6 deletions
|
|
@ -2025,10 +2025,21 @@ static void dump_host_back(void) {
|
||||||
dump_seq++;
|
dump_seq++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TABBED_SYNTH_INPUT=1: ignore the real host keyboard entirely and accept
|
||||||
|
input only from the stdin event feed (the test/driver channel). The host
|
||||||
|
keyboard listener stays attached (its enter/leave events still drive the
|
||||||
|
clipboard bridge), but key and modifier events from the real host are
|
||||||
|
dropped so a stray physical press can't cancel a synthesized repeat or
|
||||||
|
clobber the injected modifier state. */
|
||||||
|
static bool synth_input_only;
|
||||||
|
|
||||||
static void host_kbd_key(void *data, struct wl_keyboard *kbd, uint32_t serial,
|
static void host_kbd_key(void *data, struct wl_keyboard *kbd, uint32_t serial,
|
||||||
uint32_t time, uint32_t key, uint32_t state)
|
uint32_t time, uint32_t key, uint32_t state)
|
||||||
{
|
{
|
||||||
(void)data; (void)kbd;
|
(void)data;
|
||||||
|
if (synth_input_only && kbd)
|
||||||
|
return;
|
||||||
|
(void)kbd;
|
||||||
bridge.kbd_serial = serial;
|
bridge.kbd_serial = serial;
|
||||||
tabbed_log(TABBED_LOG_DEBUG,
|
tabbed_log(TABBED_LOG_DEBUG,
|
||||||
"[kbd] key=%u state=%u ctrl=%d repeat_key=%u\n", key, state,
|
"[kbd] key=%u state=%u ctrl=%d repeat_key=%u\n", key, state,
|
||||||
|
|
@ -2090,7 +2101,10 @@ static void host_kbd_modifiers(void *data, struct wl_keyboard *kbd, uint32_t ser
|
||||||
uint32_t mods_depressed, uint32_t mods_latched,
|
uint32_t mods_depressed, uint32_t mods_latched,
|
||||||
uint32_t mods_locked, uint32_t group)
|
uint32_t mods_locked, uint32_t group)
|
||||||
{
|
{
|
||||||
(void)data; (void)kbd; (void)serial;
|
(void)data; (void)serial;
|
||||||
|
if (synth_input_only && kbd)
|
||||||
|
return;
|
||||||
|
(void)kbd;
|
||||||
host.host_mods_depressed = mods_depressed;
|
host.host_mods_depressed = mods_depressed;
|
||||||
if (host.repeat_key && !(mods_depressed & (1u << 2)))
|
if (host.repeat_key && !(mods_depressed & (1u << 2)))
|
||||||
kbd_repeat_cancel();
|
kbd_repeat_cancel();
|
||||||
|
|
@ -2829,6 +2843,13 @@ int main(int argc, char *argv[]) {
|
||||||
level without touching non-async-signal-safe functions. */
|
level without touching non-async-signal-safe functions. */
|
||||||
tabbed_log_level_init();
|
tabbed_log_level_init();
|
||||||
|
|
||||||
|
/* TABBED_SYNTH_INPUT: keep real host keyboard events out of the test
|
||||||
|
channel so the stdin feed is the only source of key/modifier input. */
|
||||||
|
{
|
||||||
|
const char *v = getenv("TABBED_SYNTH_INPUT");
|
||||||
|
synth_input_only = v && v[0] && v[0] != '0';
|
||||||
|
}
|
||||||
|
|
||||||
struct sigaction crash_sa = {
|
struct sigaction crash_sa = {
|
||||||
.sa_sigaction = crash_handler,
|
.sa_sigaction = crash_handler,
|
||||||
.sa_flags = SA_SIGINFO | SA_NODEFER,
|
.sa_flags = SA_SIGINFO | SA_NODEFER,
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ def session():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
["env", "TABBED_LOG=2", "stdbuf", "-oL",
|
["env", "TABBED_LOG=2", "TABBED_SYNTH_INPUT=1", "stdbuf", "-oL",
|
||||||
BIN, f"{WL} '{RED}'", f"{WL} '{BLUE}'"],
|
BIN, f"{WL} '{RED}'", f"{WL} '{BLUE}'"],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
stdout=open(LOG, "ab"), stderr=subprocess.STDOUT,
|
stdout=open(LOG, "ab"), stderr=subprocess.STDOUT,
|
||||||
|
|
@ -399,12 +399,17 @@ def test_cycle_wraps(session):
|
||||||
def test_hold_pagedown_repeats(session):
|
def test_hold_pagedown_repeats(session):
|
||||||
start = session.wait_any_active()
|
start = session.wait_any_active()
|
||||||
assert start in (0, 1)
|
assert start in (0, 1)
|
||||||
# Press and hold Ctrl+PageDown for ~1.3s so the compositor's own
|
# Press and hold Ctrl+PageDown and wait for the compositor's own repeat
|
||||||
# repeat timer (600ms delay, then 25Hz) kicks in.
|
# timer (600ms delay, then 25Hz) to cycle several tabs. Wait for the
|
||||||
|
# transitions instead of sleeping a fixed 1.3s: a present/frame stall in
|
||||||
|
# the compositor (e.g. a swapchain allocation) can push the repeats past
|
||||||
|
# a fixed window and cause a spurious failure.
|
||||||
session.mods(CTRL)
|
session.mods(CTRL)
|
||||||
session.key(PAGE_DOWN, KEY_PRESSED)
|
session.key(PAGE_DOWN, KEY_PRESSED)
|
||||||
base = session.active_count()
|
base = session.active_count()
|
||||||
time.sleep(1.3)
|
deadline = time.monotonic() + 5.0
|
||||||
|
while time.monotonic() < deadline and session.active_count() - base < 3:
|
||||||
|
time.sleep(0.05)
|
||||||
transitions = session.active_count() - base
|
transitions = session.active_count() - base
|
||||||
# Clean release: let go of the key and the modifier.
|
# Clean release: let go of the key and the modifier.
|
||||||
session.key(PAGE_DOWN, KEY_RELEASED)
|
session.key(PAGE_DOWN, KEY_RELEASED)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue