#include "config.h" #include #include #include #include #include #include #include #ifdef HAVE_XI2 #include #endif #include #define class _class extern "C" { #include }; #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); }