1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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;
}
|