Here is more code that I'm sure someone will find handy at some point in time. I know I will be using it.
This example shows an interval timer that will still accept X input.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/time.h>
Display *dis;
Window win;
int x11_fd;
fd_set in_fds;
#ifndef timeradd
# define timeradd(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
if ((result)->tv_usec >= 1000000) \
{ \
++(result)->tv_sec; \
(result)->tv_usec -= 1000000; \
} \
} while (0)
#endif
#ifndef timersub
# define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
#endif
int main() {
struct timeval tv;
struct timeval stv;
struct timeval tv_period;
XEvent ev;
dis = XOpenDisplay(NULL);
win = XCreateSimpleWindow(dis, RootWindow(dis, 0), 1, 1, 256, 256, \
0, BlackPixel (dis, 0), BlackPixel(dis, 0));
// You don't need all of these. Make the mask as you normally would.
XSelectInput(dis, win,
ExposureMask | KeyPressMask | KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask | StructureNotifyMask
);
XMapWindow(dis, win);
XFlush(dis);
// This returns the FD of the X11 connection (or something like that)
x11_fd = ConnectionNumber(dis);
// Set Timer Period (this is how you configure the frequency):
tv_period.tv_sec = 0;
tv_period.tv_usec = 500000; // 500000us = 500ms = 0.5s
tv.tv_sec = tv_period.tv_sec; // Set tv=1 sec so select() will timeout.
tv.tv_usec = tv_period.tv_usec;
gettimeofday(&stv, 0); // Get the time of day and
timeradd(&stv, &tv_period, &stv); // Trust my math for now.. :)
// Main loop
while(1) {
// Create a File Description Set containing x11_fd
FD_ZERO(&in_fds);
FD_SET(x11_fd, &in_fds);
// Wait for X Event or a Timer
if (select(x11_fd+1, &in_fds, 0, 0, &tv)) {
printf("Event Received!\n");
gettimeofday(&tv, 0);
timersub(&stv, &tv, &tv); // set tv = remaining time.
}
else {
printf("Timer Fired!\n");
// Initialize timer variables again.
tv.tv_sec = tv_period.tv_sec; // Set tv=1 sec so select() will timeout.
tv.tv_usec = tv_period.tv_usec;
gettimeofday(&stv, 0);
timeradd(&stv, &tv_period, &stv); // Trust my math for now.. :)
}
// Handle XEvents and flush the input
while(XPending(dis))
XNextEvent(dis, &ev);
}
return(0);
}
EDIT: Just a note about the last two examples. They should work fine on all POSIX variants except for OpenVMS. OpenVMS's X implementation is such that File Descriptors are not possible. For this, one can use OpenVMS's XMultiplexInput() function. You can just use a #ifdef/#else/#endif block to handle both cases.
EDIT AGAIN: Apparently the second example contains a bug. But the concept is the same.. I'll try to search it out tomorrow.
Bookmarks