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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
#ifdef HAVE_XI2
#include <X11/extensions/XInput2.h>
#endif
#include <X11/XKBlib.h>
#define class _class
extern "C" {
#include <xdo.h>
};
#undef class
#include "global.h"
#include "rec.h"
Rect get_win_pos(Window win)
{
Rect r;
Window child;
XWindowAttributes attr;
XGetWindowAttributes(dpy, win, &attr);
if (!XTranslateCoordinates(dpy, win, attr.root, 0, 0, &r.x, &r.y, &child)) {
fprintf(stderr, "Error XTranslateCoordinates\n");
exit(EXIT_FAILURE);
}
r.width = attr.width;
r.height = attr.height;
return r;
}
void play(const char *fn, Window win)
{
Window target_win = 0;
if (win == 0) {
fprintf (stderr, "play mode require a window to be specified\n");
exit(EXIT_FAILURE);
}
xdo_t *xdo = xdo_new_with_opened_display(dpy, NULL, False);
Rect rc = get_win_pos(win);
ReadRecordsFile file(fn);
unsigned prev_time = 0;
while (!file.at_eof()) {
const Record rec = file.get();
unsigned tm = rec.get_time();
if (prev_time) {
unsigned diff = tm - prev_time;
struct timespec ts = { diff / 1000u, diff % 1000u * 1000000u };
nanosleep(&ts, NULL);
}
prev_time = tm;
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xkey.display = dpy;
ev.xkey.window = win;
ev.xkey.time = CurrentTime;
ev.xkey.root = DefaultRootWindow(dpy);
switch (rec.get_type()) {
case Record::KeyDown:
ev.type = KeyPress;
goto keyboard;
case Record::KeyUp:
ev.type = KeyRelease;
keyboard:
if (rec.get_field(Record::Window, 0) != target_win)
break;
ev.xkey.x = rec.get_field(Record::X);
ev.xkey.y = rec.get_field(Record::Y);
ev.xkey.x_root = ev.xkey.x + rc.x;
ev.xkey.y_root = ev.xkey.y + rc.y;
ev.xkey.state = rec.get_field(Record::State);
ev.xkey.keycode = rec.get_field(Record::Detail);
ev.xkey.same_screen = True;
// XSendEvent(dpy, win, True, KeyPressMask, &ev);
XSendEvent(dpy, win, False, 0, &ev);
XFlush(dpy);
break;
case Record::ButtonDown:
if (rec.get_field(Record::Window, 0) != target_win)
break;
xdo_mousedown(xdo, 0, rec.get_field(Record::Detail));
break;
case Record::ButtonUp:
if (rec.get_field(Record::Window, 0) != target_win)
break;
xdo_mouseup(xdo, 0, rec.get_field(Record::Detail));
break;
case Record::MouseMotion:
if (rec.get_field(Record::Window, 0) != target_win)
break;
xdo_mousemove_relative_to_window(xdo, win, rec.get_field(Record::X), rec.get_field(Record::Y));
break;
case Record::TargetWindow:
target_win = rec.get_field(Record::Window);
break;
case Record::WindowMove:
xdo_window_move(xdo, win, rec.get_field(Record::X), rec.get_field(Record::Y));
break;
default:
fprintf (stderr, "unknown type %u\n", rec.get_type());
exit(EXIT_FAILURE);
}
XFlush(dpy);
}
xdo_free(xdo);
}
|