summaryrefslogtreecommitdiffstats
path: root/tools/guest-diag/xtest_move.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/guest-diag/xtest_move.c')
-rw-r--r--tools/guest-diag/xtest_move.c107
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;
+}