summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2015-08-03 15:33:22 +0100
committerFrediano Ziglio <fziglio@redhat.com>2015-08-03 15:33:22 +0100
commitaeaa6c6ba2611f0d133eb66d21e717558f2465df (patch)
tree9c1a24240b4ec7c412b03365fbdbbddf5a6de1ef
parentc8c9be4a8ef46ae54c31cbb44ffa58734c0c90fa (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.am2
-rw-r--r--global.h3
-rw-r--r--play.c20
-rw-r--r--record.c211
-rw-r--r--spice-replay.c56
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
diff --git a/global.h b/global.h
index 92fbb00..14edb58 100644
--- a/global.h
+++ b/global.h
@@ -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);
diff --git a/play.c b/play.c
new file mode 100644
index 0000000..119aa00
--- /dev/null
+++ b/play.c
@@ -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;
}