diff --git a/build/guest-tests/gui-check.sh b/build/guest-tests/gui-check.sh index 823833dc..fa3a2785 100755 --- a/build/guest-tests/gui-check.sh +++ b/build/guest-tests/gui-check.sh @@ -6,7 +6,7 @@ # GT KEY-FOCUS-ZONE, GT KEY-FOCUS-OVERSIZE, # GT KEY-FOCUS-FORGED, GT KEY-FOCUS-PERSONAL press Alt+j (explicit focus) # GT KEY-FULLSCREEN, GT KEY-FULLSCREEN-AGAIN press Alt+e (fullscreen, then back) -# GT KEY-FOCUS-CHILD, GT KEY-FOCUS-PARENT, +# GT KEY-FOCUS-AWAY, GT KEY-FOCUS-CHILD, GT KEY-FOCUS-PARENT, # GT KEY-FOCUS-BELOW, GT KEY-FOCUS-LATE press Alt+j # GT KEY-ZOOM-BELOW, GT KEY-ZOOM-AGAIN press Alt+Return (zoom) # GT KEY-PARENT-FULLSCREEN, GT KEY-LATE-FULLSCREEN press Alt+e @@ -117,6 +117,19 @@ grep -q 'not advertised' "$RT/kryptik/untrusted/proxy.log" 2>/dev/null && pass " # zone 0's request is granted, which shows the probe would see a grant. as_user "/usr/libexec/kryptik/wlprobe fullscreen 4" > "$LOG/fullscreen-zone0.out" 2>&1 grep -q 'configure (fullscreen)' "$LOG/fullscreen-zone0.out" && pass "zone0-fullscreen-granted" || fail "zone0-fullscreen-granted" "$(tr '\n' ' ' < "$LOG/fullscreen-zone0.out")" +# Granted only while that window has the focus: the probe asks once the +# keyboard has left it, after Alt+j moved the focus to the launcher, and the +# request gets no fullscreen configure. +as_user "/usr/libexec/kryptik/wlprobe fullscreen 7 late" > "$LOG/fullscreen-zone0-late.out" 2>&1 & +late0_pid=$! +wait_for 10 grep -q 'keyboard entered the window' "$LOG/fullscreen-zone0-late.out" +echo "GT KEY-FOCUS-AWAY" +wait "$late0_pid" 2>/dev/null +if grep -q 'asked for fullscreen' "$LOG/fullscreen-zone0-late.out" && ! grep -q 'configure (fullscreen)' "$LOG/fullscreen-zone0-late.out"; then + pass "zone0-fullscreen-needs-focus" "an unfocused zone 0 window asked and was not made fullscreen" +else + fail "zone0-fullscreen-needs-focus" "$(grep -E 'asked|committed|keyboard' "$LOG/fullscreen-zone0-late.out" | tail -4 | tr '\n' ' ')" +fi mark fs untrusted launch_plain untrusted "/usr/libexec/kryptik/wlprobe fullscreen 6" > "$LOG/launch-fullscreen.out" 2>&1 fs_answered() { since_mark fs untrusted | sed -n '/asked for fullscreen/,$p' | grep -q committed; } diff --git a/tools/desktop/wlprobe.c b/tools/desktop/wlprobe.c index 18ecfd09..ea780a17 100644 --- a/tools/desktop/wlprobe.c +++ b/tools/desktop/wlprobe.c @@ -11,9 +11,10 @@ * buffer EXTRA px wider and taller than asked, in a * colour no zone has; stay SECONDS, titled TITLE * ("oversize" by default, at most 255 bytes) - * wlprobe fullscreen SECONDS + * wlprobe fullscreen SECONDS [late] * as oversize 0, and once drawn ask for fullscreen; - * a commit says when its configure was fullscreen + * a commit says when its configure was fullscreen; + * with late, ask once the keyboard has left the window * wlprobe child SECONDS [late] * as oversize 0, and once drawn map a second window * that is a child of the first; with late, only @@ -123,6 +124,7 @@ static int errored; enum { COMPOSITOR = 4, SHM, WM_BASE, SURFACE, XDG_SURFACE, TOPLEVEL }; static int oversize, charge, drawn, draw_failed, extra, conf_w, conf_h, closed; static int askfs, conf_fs; +static int late, kb_left; /* fullscreen late: ask once the keyboard has left */ /* child: 1 wanted once drawn, 2 wanted once fullscreen, 3 mapped; its objects. */ static int child, cconf_w, cconf_h; static uint32_t csurface, cxdg, ctoplevel; @@ -328,6 +330,7 @@ static int handle_one(void) fflush(stdout); } else if (keyboard_id && object == keyboard_id && (opcode == 1 || opcode == 2)) { uint32_t s = get32(body + 4); /* wl_keyboard.enter|leave(serial, surface, ...) */ + if (opcode == 2 && s == SURFACE) kb_left = 1; printf("keyboard %s %s\n", opcode == 1 ? "entered" : "left", s == SURFACE ? "the window" : (csurface && s == csurface) ? "the child" : "another surface"); fflush(stdout); @@ -409,7 +412,7 @@ static int hold_oversize(int more, int seconds, const char *title) time_t end = time(NULL) + seconds; while (time(NULL) < end && !closed) { if (drain(500) < 0) { puts(errored ? "refused" : "connection closed"); return 3; } - if (askfs == 1 && drawn) { + if (askfs == 1 && drawn && (!late || kb_left)) { put32(b, 0); /* no output: the compositor's choice */ send_msg(TOPLEVEL, 11, b, 4); /* xdg_toplevel.set_fullscreen */ askfs = 2; @@ -429,11 +432,11 @@ int main(int argc, char **argv) && strcmp(argv[1], "cursor")) || (!strcmp(argv[1], "bind") && argc < 3) || (!strcmp(argv[1], "oversize") && argc < 4) || (!strcmp(argv[1], "oversize") && argc > 4 && strlen(argv[4]) > 255) - || (!strcmp(argv[1], "fullscreen") && argc != 3) + || (!strcmp(argv[1], "fullscreen") && (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "late")))) || (!strcmp(argv[1], "child") && (argc < 3 || argc > 4 || (argc == 4 && strcmp(argv[3], "late")))) || (!strcmp(argv[1], "charge") && argc != 2) || (!strcmp(argv[1], "cursor") && argc != 3)) { - fprintf(stderr, "usage: wlprobe list | bind INTERFACE | oversize EXTRA SECONDS [TITLE] | fullscreen SECONDS | child SECONDS [late] | charge | cursor SECONDS\n"); + fprintf(stderr, "usage: wlprobe list | bind INTERFACE | oversize EXTRA SECONDS [TITLE] | fullscreen SECONDS [late] | child SECONDS [late] | charge | cursor SECONDS\n"); return 2; } const char *disp = getenv("WAYLAND_DISPLAY"); @@ -461,7 +464,7 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "list")) return errored ? 3 : 0; if (!strcmp(argv[1], "oversize")) return hold_oversize(atoi(argv[2]), atoi(argv[3]), argc > 4 ? argv[4] : "oversize"); - if (!strcmp(argv[1], "fullscreen")) { askfs = 1; return hold_oversize(0, atoi(argv[2]), "fullscreen"); } + if (!strcmp(argv[1], "fullscreen")) { askfs = 1; late = argc == 4; return hold_oversize(0, atoi(argv[2]), "fullscreen"); } if (!strcmp(argv[1], "child")) { child = argc == 4 ? 2 : 1; return hold_oversize(0, atoi(argv[2]), "child-parent"); } if (!strcmp(argv[1], "charge")) { charge = 1; return hold_oversize(0, 10, "shm-charge"); } if (!strcmp(argv[1], "cursor")) { cursor = 1; return hold_oversize(0, atoi(argv[2]), "cursor"); } diff --git a/tools/image/gui-test.sh b/tools/image/gui-test.sh index 58b29435..fafeac81 100755 --- a/tools/image/gui-test.sh +++ b/tools/image/gui-test.sh @@ -64,6 +64,7 @@ python3 "$DRV" --serial "$SER" --qmp "$QMP" --timeout 600 \ "expect:KRYPTIK_SMOKE: END" "seen:kryptik-firstboot: created user '${TUSER}'" "login:${TUSER}:${TPASS}" \ "send:su - root -c 'bash /usr/lib/kryptik/guest-tests/gui-check.sh ${TUSER} 2>&1 | tee /var/log/kryptik/gui-check.log; echo GCHECK-DONE'" \ "expect:Password: ?" "send:${RPASS}" \ + "expect:GT KEY-FOCUS-AWAY" "key:alt+j" \ "expect:GT KEY-FOCUS-CHILD" "key:alt+j" \ "expect:GT KEY-FOCUS-PARENT" "key:alt+j" \ "expect:GT KEY-PARENT-FULLSCREEN" "key:alt+e" \ @@ -108,7 +109,7 @@ for name in session-socket compositor-running chrome-focus-record chrome-window- transfer-policy no-question-for-policy-refusal consent-code-shown transfer-approved transfer-landed plain-y-refused denied-file-absent \ second-head-appears chrome-follows-head second-head-zone-window second-head-names-zone second-head-gone compositor-survives-unplug zone-survives-unplug chrome-back-on-first-head \ zone0-cursor-set zone0-cursor-shown zone-cursor-asked zone-hears-of-outputs zone-cursor-not-shown \ - zone0-fullscreen-granted fullscreen-by-key zone-child-mapped child-focused parent-focused parent-fullscreen fullscreen-keeps-focus keyboard-stays-on-fullscreen zoom-keeps-keyboard zoom-twice-keeps-keyboard zone0-over-fullscreen-gets-keyboard zone0-window-ends-fullscreen child-ends-fullscreen; do + zone0-fullscreen-granted zone0-fullscreen-needs-focus fullscreen-by-key zone-child-mapped child-focused parent-focused parent-fullscreen fullscreen-keeps-focus keyboard-stays-on-fullscreen zoom-keeps-keyboard zoom-twice-keeps-keyboard zone0-over-fullscreen-gets-keyboard zone0-window-ends-fullscreen child-ends-fullscreen; do grep -q "GT PASS ${name}" <<<"$T" && green "guest: ${name}" || red "guest: ${name} (not passed)" done