Results 1 to 1 of 1
I wanted something that would block for a specific amount of time without consuming processor time and without getting in the way of Xevents
I found a neat solution on ...
- 03-19-2008 #1Just Joined!
- Join Date
- Mar 2008
- Posts
- 34
useful timer without blocking Xevents
I wanted something that would block for a specific amount of time without consuming processor time and without getting in the way of Xevents
I found a neat solution on a forum (see link in code) and I thought it was worth posting here as its rather useful!
I've encapsulated it into a class which keeps the event loop from looking too untidy and it uses a user specified function pointer every "tick" which has a user defined period.
oh and the example shows enabling and disabling as its minimised and restored
Code:// g++ xlibtimertest.cpp -lX11 // based on code from http://www.linuxquestions.org/questions/programming-9/xnextevent-select-409355/ #include <stdio.h> #include <stdlib.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <sys/time.h> #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 static char *event_names[] = { "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", "ClientMessage", "MappingNotify" }; struct timeval tv; struct timeval stv; struct timeval tv_period; Display *dis; Window win; void timerFired(); class xtimer { int dis; int x11_fd; fd_set in_fds; void (*tickFunc)(); public: // display, period in seconds 0.25 etc, // and void function() pointer thats called each "tick" xtimer(Display *d,float p,void (*fp)()) { tickFunc=fp; dis=0; x11_fd=ConnectionNumber(d); tv_period.tv_sec = 0; tv_period.tv_usec = (int)(p*1000000); // 1000000us = 1000ms = 1.0s 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.. :) } void check() { // 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, so you can only have 1 timer at a time... if (select(x11_fd+1, &in_fds, 0, 0, &tv)) { gettimeofday(&tv, 0); timersub(&stv, &tv, &tv); // set tv = remaining time. } else { if (!dis) { tickFunc(); // 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.. :) } } } void disable() { dis=1; tv.tv_sec =1; } void enable() { dis=0; tv.tv_sec =0; } int running() { return 1-dis; } }; xtimer *t; int main() { 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); t=new xtimer(dis,0.5,timerFired); // Main loop while(1) { t->check(); // this blocks till time runs out or Xevent comes // Handle XEvents and flush the input, if timers stopped block for next event (probably map!) while(XPending(dis) || t->running()==0) { XNextEvent(dis, &ev); printf("event.type %s\n",event_names[ev.type]); if (ev.type==UnmapNotify) { t->disable(); } if (ev.type==MapNotify) { t->enable(); } } } return(0); } void timerFired() { printf("Timer Fired!\n"); }


Reply With Quote