/* Measuring X round-trip time.
 * Copyright (c) 2008 Jim Huang <jserv.tw@gmail.com>, MIT X License
 *
 * Build:
 *   gcc -o xttl xttl.c -Wall `pkg-config --cflags --libs x11`
 */
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <X11/Xlib.h>
#include <sys/time.h>

#define TRY_TIMES (10)
#define INTERVAL (1)
int main()
{
	Display *disp;
	struct timeval start = { 0UL, 0UL }, end = { 0UL, 0UL };
	char *disp_name;
	int ret = 0;
	int count = 0;

	disp_name = XDisplayName(NULL);
	if ((disp = XOpenDisplay(NULL)) == NULL) {
		errx(1, "cannot open display %s", disp_name);
	}

	printf("X server version is %i.%i\n", 
	       ProtocolVersion(disp), ProtocolRevision(disp));
	printf("X Vendor string: %s\n", ServerVendor(disp));
	printf("X Vendor release number: %i\n", XVendorRelease(disp));

	while (count++ < TRY_TIMES) {
		ret = gettimeofday(&start, NULL);
		if (ret < 0) {
			err(1, "gettimeofday");
		}

		/* The XNoOp function sends a NoOperation protocol request
		 * to the X server, thereby exercising the connection. */
		if (XNoOp(disp)) {
			struct timeval diff = { 0UL, 0UL };
			if ((ret = gettimeofday(&end, NULL)) < 0)
				err(1, "gettimeofday");

			if (end.tv_sec < start.tv_sec &&
			    end.tv_usec < start.tv_usec) {
				break;
			}

			diff.tv_sec = end.tv_sec - start.tv_sec;
			diff.tv_usec = end.tv_usec - start.tv_usec;

			printf(" reply from display %s: XNoOP_seq=%i time=%lu.%lu ms\n",
			       disp_name, count,
			       (diff.tv_sec * 1000 * INTERVAL), diff.tv_usec);
		}
		sleep(INTERVAL);
	}
	XCloseDisplay(disp);

	return 0;
}
