diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2015-08-03 15:33:22 +0100 |
---|---|---|
committer | Frediano Ziglio <fziglio@redhat.com> | 2015-08-03 15:33:22 +0100 |
commit | aeaa6c6ba2611f0d133eb66d21e717558f2465df (patch) | |
tree | 9c1a24240b4ec7c412b03365fbdbbddf5a6de1ef | |
parent | c8c9be4a8ef46ae54c31cbb44ffa58734c0c90fa (diff) |
Improve record
Split record and play in 2 files.
Filter our Window for record.
Allow more verbose level.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | global.h | 3 | ||||
-rw-r--r-- | play.c | 20 | ||||
-rw-r--r-- | record.c | 211 | ||||
-rw-r--r-- | spice-replay.c | 56 |
5 files changed, 255 insertions, 37 deletions
diff --git a/Makefile.am b/Makefile.am index 0cf181c..56e1da3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,5 +26,7 @@ spice_replay_LDADD = $(REPLAY_LIBS) spice_replay_SOURCES = \ spice-replay.c \ + record.c \ + play.c \ xev.c \ test_xi2.c @@ -1,5 +1,8 @@ extern Display *dpy; +extern int verbose; +void record(const char *fn_out, Window win); +void play(const char *fn, Window win); /* standard events */ void xev_init(Window w); @@ -0,0 +1,20 @@ +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xlib.h> + +#include "global.h" + +void play(const char *fn, Window win) +{ +#if 0 + if (win == 0) { + fprintf (stderr, "play mode require a window to be specified\n"); + exit(EXIT_FAILURE); + } +#endif + + fprintf (stderr, "playback mode still not supported\n"); + exit(EXIT_FAILURE); +} diff --git a/record.c b/record.c new file mode 100644 index 0000000..0079cb7 --- /dev/null +++ b/record.c @@ -0,0 +1,211 @@ +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <signal.h> +#include <X11/Xlib.h> +#include <X11/extensions/XInput.h> +#ifdef HAVE_XI2 +#include <X11/extensions/XInput2.h> +#endif + +#include "global.h" + +static FILE *f_out = NULL; +static volatile int done = 0; +static int has_focus = 0, inside = 0; +static Window win = 0; +static int x, y, width, height; + +static void +sig_end(int sig) +{ + done = 1; +} + +static void +update_win_pos(void) +{ + int win_x, win_y; + Window child; + XWindowAttributes attr; + XGetWindowAttributes(dpy, win, &attr); + + if (!XTranslateCoordinates(dpy, win, DefaultRootWindow(dpy), attr.x, attr.y, &win_x, &win_y, &child)) { + fprintf(stderr, "Error XTranslateCoordinates\n"); + exit(EXIT_FAILURE); + } + x = win_x; + y = win_y; + width = attr.width; + height = attr.height; +} + +static void +handle_motion(XIDeviceEvent* ev) +{ + int mouse_x, mouse_y; + + mouse_x = (int) ev->root_x; + if (mouse_x < x || mouse_x - x >= width) + return; + mouse_y = (int) ev->root_y; + if (mouse_y < y || mouse_y - y >= height) + return; + if (inside) + printf("Mouse moved at (%d,%d)\n", mouse_x, mouse_y); +} + +static void +handle_xinput(XGenericEventCookie *cookie) +{ + if (verbose >= 2) + xinput_dump(dpy, cookie); + + switch (cookie->evtype) { + case XI_KeyPress: + case XI_KeyRelease: + if (has_focus) + printf("Got a key\n"); + break; + case XI_ButtonPress: + break; + case XI_ButtonRelease: + break; + case XI_Motion: + handle_motion(cookie->data); + break; + /* don't care about these */ + case XI_RawKeyPress: + case XI_RawKeyRelease: + case XI_RawButtonPress: + case XI_RawButtonRelease: + case XI_RawTouchBegin: + case XI_RawTouchUpdate: + case XI_RawTouchEnd: + case XI_RawMotion: + break; + default: + if (verbose == 1) + xinput_dump(dpy, cookie); + break; + } +} + +static void +handle_ConfigureNotify(XEvent *event) +{ + XConfigureEvent *e = &event->xconfigure; + + if (e->window == win) { + x = e->x; + y = e->y; + width = e->width; + height = e->height; + } +} + +static void +handle_xev(XEvent *ev) +{ + if (verbose >= 2) + xev_dump(ev); + + switch (ev->type) { + case FocusIn: + if (ev->xfocus.window == win) + has_focus = 1; + break; + case FocusOut: + if (ev->xfocus.window == win) + has_focus = 0; + break; + case EnterNotify: + if (ev->xcrossing.window == win) + inside = 1; + break; + case LeaveNotify: + if (ev->xcrossing.window == win) + inside = 0; + break; + case DestroyNotify: + if (ev->xdestroywindow.window == win) + done = 1; + break; + case ConfigureNotify: + handle_ConfigureNotify(ev); + break; + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case KeymapNotify: + case Expose: + case GraphicsExpose: + case NoExpose: + case VisibilityNotify: + case CreateNotify: + case UnmapNotify: + case MapNotify: + case MapRequest: + case ReparentNotify: + case ConfigureRequest: + case GravityNotify: + case ResizeRequest: + case CirculateNotify: + case CirculateRequest: + case PropertyNotify: + case SelectionClear: + case SelectionRequest: + case SelectionNotify: + case ColormapNotify: + case ClientMessage: + case MappingNotify: + if (verbose == 1) + xev_dump(ev); + break; + } +} + +void record(const char *fn_out, Window _win) +{ + if (_win == 0) { + fprintf (stderr, "record mode require a window to be specified\n"); + exit(EXIT_FAILURE); + } + win = _win; + + f_out = fopen(fn_out, "wb"); + if (!f_out) { + fprintf (stderr, "unable to open output file\n"); + exit(EXIT_FAILURE); + } + + xev_init(win); + xinput_init(dpy, win); + + update_win_pos(); + + signal(SIGINT, sig_end); + signal(SIGTERM, sig_end); + + while (!done) { + XEvent event; + + XNextEvent (dpy, &event); + + if (is_xinput_event(&event)) { + XGenericEventCookie *cookie = &event.xcookie; + if (XGetEventData(dpy, cookie)) { + handle_xinput(cookie); + XFreeEventData(dpy, cookie); + } + } else { + handle_xev(&event); + } + } + + fclose(f_out); +} diff --git a/spice-replay.c b/spice-replay.c index 151adfa..81aec0e 100644 --- a/spice-replay.c +++ b/spice-replay.c @@ -9,11 +9,17 @@ #include <stdlib.h> #include <string.h> #include <getopt.h> +#include <signal.h> #include <X11/Xlib.h> +#include <X11/extensions/XInput.h> +#ifdef HAVE_XI2 +#include <X11/extensions/XInput2.h> +#endif #include "global.h" Display *dpy = NULL; +int verbose = 0; enum { MODE_UNKNOWN, @@ -22,7 +28,6 @@ enum { }; static int mode = MODE_UNKNOWN; -static int verbose = 0; static const char short_options[] = "hVvi:"; static const struct option long_options[] = { @@ -30,7 +35,7 @@ static const struct option long_options[] = { {"version", no_argument, 0, 'V' }, {"record", no_argument, &mode, MODE_RECORD }, {"play", no_argument, &mode, MODE_PLAY }, - {"verbose", no_argument, &verbose, 1 }, + {"verbose", no_argument, 0, 'v' }, {"id", required_argument, 0, 'i'}, {"display", required_argument, 0, 'D'}, {NULL, 0, 0, 0 } @@ -60,8 +65,8 @@ version(void) int main(int argc, char **argv) { - Window w = 0; - const char *fn_out = NULL; + Window win = 0; + const char *fn = NULL; const char *display = NULL; while (1) { @@ -85,11 +90,11 @@ int main(int argc, char **argv) break; case 'v': - verbose = 1; + ++verbose; break; case 'i': - w = strtoul(optarg, NULL, 0); + win = strtoul(optarg, NULL, 0); break; case 'd': @@ -105,17 +110,7 @@ int main(int argc, char **argv) if (optind >= argc || mode == MODE_UNKNOWN) usage(stderr); - if (mode == MODE_PLAY) { - fprintf (stderr, "playback mode still not supported\n"); - return EXIT_FAILURE; - } - - if (mode == MODE_RECORD && w == 0) { - fprintf (stderr, "record mode require a window to be specified\n"); - return EXIT_FAILURE; - } - - fn_out = argv[optind]; + fn = argv[optind]; dpy = XOpenDisplay (display); if (!dpy) { @@ -123,28 +118,15 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - xev_init(w); - xinput_init(dpy, w); - - while(1) { - XEvent event; - - XNextEvent (dpy, &event); - - if (is_xinput_event(&event)) { - XGenericEventCookie *cookie = &event.xcookie; - if (XGetEventData(dpy, cookie)) { - if (verbose) - xinput_dump(dpy, cookie); - XFreeEventData(dpy, cookie); - } - } else { - if (verbose) - xev_dump(&event); - } + switch (mode) { + case MODE_RECORD: + record(fn, win); + break; + case MODE_PLAY: + play(fn, win); + break; } XCloseDisplay (dpy); - return EXIT_SUCCESS; } |