diff options
Diffstat (limited to 'tools/guest-diag/xtest_move.c')
| -rw-r--r-- | tools/guest-diag/xtest_move.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/tools/guest-diag/xtest_move.c b/tools/guest-diag/xtest_move.c new file mode 100644 index 0000000..a156bf8 --- /dev/null +++ b/tools/guest-diag/xtest_move.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: BSD-3-Clause +// xtest_move.c - drive the game with XTEST: hold forward + fire and tap +// left/right periodically so the captured footage has constant motion. +// Usage: xtest_move <display> <seconds> +#include <X11/Xlib.h> +#include <X11/keysym.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +extern int XTestFakeKeyEvent(Display *, unsigned int, int, unsigned long); + +int main(int argc, char **argv) +{ + Display *d = XOpenDisplay(argc > 1 ? argv[1] : ":1"); + int secs = argc > 2 ? atoi(argv[2]) : 12; + KeyCode kFwd, kFire, kLeft, kRight; + int t; + + if (!d) { + fprintf(stderr, "xtest_move: no display\n"); + return 1; + } + /* No WM on Xvfb: give the game window input focus ourselves. */ + { + Window r, parent, *kids = NULL; + unsigned int nk = 0; + + if (XQueryTree(d, DefaultRootWindow(d), &r, &parent, &kids, &nk)) { + unsigned int i; + + for (i = 0; i < nk; i++) { + char *nm = NULL; + + if (XFetchName(d, kids[i], &nm) && nm) { + int hit = strstr(nm, "Freedoom") || strstr(nm, "Doom") || + strstr(nm, "gzdoom") || strstr(nm, "Outer"); + + XFree(nm); + if (hit) { + XSetInputFocus(d, kids[i], RevertToParent, CurrentTime); + fprintf(stderr, "xtest_move: focused 0x%lx\n", + (unsigned long)kids[i]); + break; + } + } + } + if (kids) + XFree(kids); + } + } + kFwd = XKeysymToKeycode(d, XK_Up); + kFire = XKeysymToKeycode(d, XK_space); + kLeft = XKeysymToKeycode(d, XK_Left); + kRight = XKeysymToKeycode(d, XK_Right); + fprintf(stderr, "xtest_move: fwd=%d fire=%d left=%d right=%d\n", + kFwd, kFire, kLeft, kRight); + XTestFakeKeyEvent(d, kFwd, 1, 0); + XTestFakeKeyEvent(d, kFire, 1, 0); + XFlush(d); + /* Continuous motion: rotate steadily (hold a turn key ~0.8 s, then + * the other) while forward+fire stay held - every frame changes. */ + for (t = 0; t < secs * 10; t++) { + KeyCode turn = (t & 8) ? kLeft : kRight; + Window wr, wpar, *wk = NULL; + unsigned int wnk = 0; + + /* Re-assert focus every tick: Xvfb has no WM, and any new X client + * (the capture tool) can leave the game unfocused - GZDoom pauses + * the game the moment SDL reports focus loss. */ + if (XQueryTree(d, DefaultRootWindow(d), &wr, &wpar, &wk, &wnk)) { + unsigned int i; + + for (i = 0; i < wnk; i++) { + char *nm = NULL; + + if (XFetchName(d, wk[i], &nm) && nm) { + int hit = strstr(nm, "Freedoom") || strstr(nm, "Outer") || + strstr(nm, "Doom"); + + XFree(nm); + if (hit) { + XSetInputFocus(d, wk[i], RevertToParent, + CurrentTime); + break; + } + } + } + if (wk) + XFree(wk); + } + XTestFakeKeyEvent(d, kLeft, 0, 0); + XTestFakeKeyEvent(d, kRight, 0, 0); + XTestFakeKeyEvent(d, turn, 1, 0); + XFlush(d); + usleep(100000); + } + XTestFakeKeyEvent(d, kLeft, 0, 0); + XTestFakeKeyEvent(d, kRight, 0, 0); + XTestFakeKeyEvent(d, kFwd, 0, 0); + XTestFakeKeyEvent(d, kFire, 0, 0); + XFlush(d); + XCloseDisplay(d); + fprintf(stderr, "xtest_move: done\n"); + return 0; +} |
