Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / handlers.c
Commit [+]AuthorDateLineData
f5dcab06 dan2001-03-20 23:46:57 +00001
2/*
3 * WINGs internal handlers: timer, idle and input handlers
4 */
5
558615a8 dan2004-10-30 05:46:37 +00006#include "wconfig.h"
f5dcab06 dan2001-03-20 23:46:57 +00007#include "WINGsP.h"
8
f5dcab06 dan2001-03-20 23:46:57 +00009#include <sys/types.h>
10#include <unistd.h>
11
12#include <X11/Xos.h>
13
14#ifdef HAVE_SYS_SELECT_H
15# include <sys/select.h>
16#endif
17
18#include <time.h>
19
20#ifndef X_GETTIMEOFDAY
21#define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0)
22#endif
23
f5dcab06 dan2001-03-20 23:46:57 +000024typedef struct TimerHandler {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020025 WMCallback *callback; /* procedure to call */
26 struct timeval when; /* when to call the callback */
27 void *clientData;
28 struct TimerHandler *next;
29 int nextDelay; /* 0 if it's one-shot */
f5dcab06 dan2001-03-20 23:46:57 +000030} TimerHandler;
31
f5dcab06 dan2001-03-20 23:46:57 +000032typedef struct IdleHandler {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020033 WMCallback *callback;
34 void *clientData;
f5dcab06 dan2001-03-20 23:46:57 +000035} IdleHandler;
36
f5dcab06 dan2001-03-20 23:46:57 +000037typedef struct InputHandler {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020038 WMInputProc *callback;
39 void *clientData;
40 int fd;
41 int mask;
f5dcab06 dan2001-03-20 23:46:57 +000042} InputHandler;
43
f5dcab06 dan2001-03-20 23:46:57 +000044/* queue of timer event handlers */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020045static TimerHandler *timerHandler = NULL;
f5dcab06 dan2001-03-20 23:46:57 +000046
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020047static WMArray *idleHandler = NULL;
f5dcab06 dan2001-03-20 23:46:57 +000048
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020049static WMArray *inputHandler = NULL;
f5dcab06 dan2001-03-20 23:46:57 +000050
f5dcab06 dan2001-03-20 23:46:57 +000051#define timerPending() (timerHandler)
52
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020053static void rightNow(struct timeval *tv)
6830b057 dan2004-10-12 21:28:27 +000054{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020055 X_GETTIMEOFDAY(tv);
f5dcab06 dan2001-03-20 23:46:57 +000056}
57
58/* is t1 after t2 ? */
59#define IS_AFTER(t1, t2) (((t1).tv_sec > (t2).tv_sec) || \
6830b057 dan2004-10-12 21:28:27 +000060 (((t1).tv_sec == (t2).tv_sec) \
61 && ((t1).tv_usec > (t2).tv_usec)))
f5dcab06 dan2001-03-20 23:46:57 +000062
63#define IS_ZERO(tv) (tv.tv_sec == 0 && tv.tv_usec == 0)
64
65#define SET_ZERO(tv) tv.tv_sec = 0, tv.tv_usec = 0
66
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020067static void addmillisecs(struct timeval *tv, int milliseconds)
f5dcab06 dan2001-03-20 23:46:57 +000068{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020069 tv->tv_usec += milliseconds * 1000;
f5dcab06 dan2001-03-20 23:46:57 +000070
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020071 tv->tv_sec += tv->tv_usec / 1000000;
72 tv->tv_usec = tv->tv_usec % 1000000;
f5dcab06 dan2001-03-20 23:46:57 +000073}
74
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020075static void enqueueTimerHandler(TimerHandler * handler)
f5dcab06 dan2001-03-20 23:46:57 +000076{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020077 TimerHandler *tmp;
78
79 /* insert callback in queue, sorted by time left */
80 if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) {
81 /* first in the queue */
82 handler->next = timerHandler;
83 timerHandler = handler;
84 } else {
85 tmp = timerHandler;
86 while (tmp->next && IS_AFTER(handler->when, tmp->next->when)) {
87 tmp = tmp->next;
88 }
89 handler->next = tmp->next;
90 tmp->next = handler;
91 }
f5dcab06 dan2001-03-20 23:46:57 +000092}
93
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020094static void delayUntilNextTimerEvent(struct timeval *delay)
f5dcab06 dan2001-03-20 23:46:57 +000095{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020096 struct timeval now;
97 TimerHandler *handler;
98
99 handler = timerHandler;
100 while (handler && IS_ZERO(handler->when))
101 handler = handler->next;
102
103 if (!handler) {
104 /* The return value of this function is only valid if there _are_
105 timers active. */
106 delay->tv_sec = 0;
107 delay->tv_usec = 0;
108 return;
109 }
110
111 rightNow(&now);
112 if (IS_AFTER(now, handler->when)) {
113 delay->tv_sec = 0;
114 delay->tv_usec = 0;
115 } else {
116 delay->tv_sec = handler->when.tv_sec - now.tv_sec;
117 delay->tv_usec = handler->when.tv_usec - now.tv_usec;
118 if (delay->tv_usec < 0) {
119 delay->tv_usec += 1000000;
120 delay->tv_sec--;
121 }
122 }
f5dcab06 dan2001-03-20 23:46:57 +0000123}
124
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200125WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback * callback, void *cdata)
f5dcab06 dan2001-03-20 23:46:57 +0000126{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200127 TimerHandler *handler;
f5dcab06 dan2001-03-20 23:46:57 +0000128
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200129 handler = malloc(sizeof(TimerHandler));
130 if (!handler)
131 return NULL;
f5dcab06 dan2001-03-20 23:46:57 +0000132
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200133 rightNow(&handler->when);
134 addmillisecs(&handler->when, milliseconds);
135 handler->callback = callback;
136 handler->clientData = cdata;
137 handler->nextDelay = 0;
f5dcab06 dan2001-03-20 23:46:57 +0000138
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200139 enqueueTimerHandler(handler);
f5dcab06 dan2001-03-20 23:46:57 +0000140
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200141 return handler;
f5dcab06 dan2001-03-20 23:46:57 +0000142}
143
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200144WMHandlerID WMAddPersistentTimerHandler(int milliseconds, WMCallback * callback, void *cdata)
f5dcab06 dan2001-03-20 23:46:57 +0000145{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200146 TimerHandler *handler = WMAddTimerHandler(milliseconds, callback, cdata);
f5dcab06 dan2001-03-20 23:46:57 +0000147
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200148 if (handler != NULL)
149 handler->nextDelay = milliseconds;
f5dcab06 dan2001-03-20 23:46:57 +0000150
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200151 return handler;
f5dcab06 dan2001-03-20 23:46:57 +0000152}
153
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200154void WMDeleteTimerWithClientData(void *cdata)
f5dcab06 dan2001-03-20 23:46:57 +0000155{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200156 TimerHandler *handler, *tmp;
157
158 if (!cdata || !timerHandler)
159 return;
160
161 tmp = timerHandler;
162 if (tmp->clientData == cdata) {
163 tmp->nextDelay = 0;
164 if (!IS_ZERO(tmp->when)) {
165 timerHandler = tmp->next;
166 wfree(tmp);
167 }
168 } else {
169 while (tmp->next) {
170 if (tmp->next->clientData == cdata) {
171 handler = tmp->next;
172 handler->nextDelay = 0;
173 if (IS_ZERO(handler->when))
174 break;
175 tmp->next = handler->next;
176 wfree(handler);
177 break;
178 }
179 tmp = tmp->next;
180 }
181 }
f5dcab06 dan2001-03-20 23:46:57 +0000182}
183
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200184void WMDeleteTimerHandler(WMHandlerID handlerID)
f5dcab06 dan2001-03-20 23:46:57 +0000185{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200186 TimerHandler *tmp, *handler = (TimerHandler *) handlerID;
187
188 if (!handler || !timerHandler)
189 return;
190
191 tmp = timerHandler;
192
193 handler->nextDelay = 0;
194
195 if (IS_ZERO(handler->when))
196 return;
197
198 if (tmp == handler) {
199 timerHandler = handler->next;
200 wfree(handler);
201 } else {
202 while (tmp->next) {
203 if (tmp->next == handler) {
204 tmp->next = handler->next;
205 wfree(handler);
206 break;
207 }
208 tmp = tmp->next;
209 }
210 }
f5dcab06 dan2001-03-20 23:46:57 +0000211}
212
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200213WMHandlerID WMAddIdleHandler(WMCallback * callback, void *cdata)
f5dcab06 dan2001-03-20 23:46:57 +0000214{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200215 IdleHandler *handler;
f5dcab06 dan2001-03-20 23:46:57 +0000216
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200217 handler = malloc(sizeof(IdleHandler));
218 if (!handler)
219 return NULL;
f5dcab06 dan2001-03-20 23:46:57 +0000220
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200221 handler->callback = callback;
222 handler->clientData = cdata;
223 /* add handler at end of queue */
224 if (!idleHandler) {
225 idleHandler = WMCreateArrayWithDestructor(16, wfree);
226 }
227 WMAddToArray(idleHandler, handler);
f5dcab06 dan2001-03-20 23:46:57 +0000228
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200229 return handler;
f5dcab06 dan2001-03-20 23:46:57 +0000230}
231
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200232void WMDeleteIdleHandler(WMHandlerID handlerID)
f5dcab06 dan2001-03-20 23:46:57 +0000233{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200234 IdleHandler *handler = (IdleHandler *) handlerID;
f5dcab06 dan2001-03-20 23:46:57 +0000235
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200236 if (!handler || !idleHandler)
237 return;
f5dcab06 dan2001-03-20 23:46:57 +0000238
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200239 WMRemoveFromArray(idleHandler, handler);
f5dcab06 dan2001-03-20 23:46:57 +0000240}
241
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200242WMHandlerID WMAddInputHandler(int fd, int condition, WMInputProc * proc, void *clientData)
f5dcab06 dan2001-03-20 23:46:57 +0000243{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200244 InputHandler *handler;
f5dcab06 dan2001-03-20 23:46:57 +0000245
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200246 handler = wmalloc(sizeof(InputHandler));
f5dcab06 dan2001-03-20 23:46:57 +0000247
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200248 handler->fd = fd;
249 handler->mask = condition;
250 handler->callback = proc;
251 handler->clientData = clientData;
f5dcab06 dan2001-03-20 23:46:57 +0000252
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200253 if (!inputHandler)
254 inputHandler = WMCreateArrayWithDestructor(16, wfree);
255 WMAddToArray(inputHandler, handler);
f5dcab06 dan2001-03-20 23:46:57 +0000256
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200257 return handler;
f5dcab06 dan2001-03-20 23:46:57 +0000258}
259
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200260void WMDeleteInputHandler(WMHandlerID handlerID)
f5dcab06 dan2001-03-20 23:46:57 +0000261{
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200262 InputHandler *handler = (InputHandler *) handlerID;
f5dcab06 dan2001-03-20 23:46:57 +0000263
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200264 if (!handler || !inputHandler)
265 return;
f5dcab06 dan2001-03-20 23:46:57 +0000266
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200267 WMRemoveFromArray(inputHandler, handler);
f5dcab06 dan2001-03-20 23:46:57 +0000268}
269
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200270Bool W_CheckIdleHandlers(void)
f5dcab06 dan2001-03-20 23:46:57 +0000271{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200272 IdleHandler *handler;
273 WMArray *handlerCopy;
274 WMArrayIterator iter;
f5dcab06 dan2001-03-20 23:46:57 +0000275
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200276 if (!idleHandler || WMGetArrayItemCount(idleHandler) == 0) {
277 W_FlushIdleNotificationQueue();
278 /* make sure an observer in queue didn't added an idle handler */
279 return (idleHandler != NULL && WMGetArrayItemCount(idleHandler) > 0);
280 }
f5dcab06 dan2001-03-20 23:46:57 +0000281
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200282 handlerCopy = WMDuplicateArray(idleHandler);
f5dcab06 dan2001-03-20 23:46:57 +0000283
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200284 WM_ITERATE_ARRAY(handlerCopy, handler, iter) {
285 /* check if the handler still exist or was removed by a callback */
286 if (WMGetFirstInArray(idleHandler, handler) == WANotFound)
287 continue;
f5dcab06 dan2001-03-20 23:46:57 +0000288
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200289 (*handler->callback) (handler->clientData);
290 WMDeleteIdleHandler(handler);
291 }
f5dcab06 dan2001-03-20 23:46:57 +0000292
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200293 WMFreeArray(handlerCopy);
f5dcab06 dan2001-03-20 23:46:57 +0000294
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200295 W_FlushIdleNotificationQueue();
f5dcab06 dan2001-03-20 23:46:57 +0000296
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200297 /* this is not necesarrily False, because one handler can re-add itself */
298 return (WMGetArrayItemCount(idleHandler) > 0);
f5dcab06 dan2001-03-20 23:46:57 +0000299}
300
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200301void W_CheckTimerHandlers(void)
f5dcab06 dan2001-03-20 23:46:57 +0000302{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200303 TimerHandler *handler;
304 struct timeval now;
305
306 if (!timerHandler) {
307 W_FlushASAPNotificationQueue();
308 return;
309 }
310
311 rightNow(&now);
312
313 handler = timerHandler;
314 while (handler && IS_AFTER(now, handler->when)) {
315 if (!IS_ZERO(handler->when)) {
316 SET_ZERO(handler->when);
317 (*handler->callback) (handler->clientData);
318 }
319 handler = handler->next;
320 }
321
322 while (timerHandler && IS_ZERO(timerHandler->when)) {
323 handler = timerHandler;
324 timerHandler = timerHandler->next;
325
326 if (handler->nextDelay > 0) {
327 handler->when = now;
328 addmillisecs(&handler->when, handler->nextDelay);
329 enqueueTimerHandler(handler);
330 } else {
331 wfree(handler);
332 }
333 }
334
335 W_FlushASAPNotificationQueue();
f5dcab06 dan2001-03-20 23:46:57 +0000336}
337
f5dcab06 dan2001-03-20 23:46:57 +0000338/*
339 * This functions will handle input events on all registered file descriptors.
340 * Input:
341 * - waitForInput - True if we want the function to wait until an event
342 * appears on a file descriptor we watch, False if we
343 * want the function to immediately return if there is
344 * no data available on the file descriptors we watch.
345 * - inputfd - Extra input file descriptor to watch for input.
346 * This is only used when called from wevent.c to watch
347 * on ConnectionNumber(dpy) to avoid blocking of X events
348 * if we wait for input from other file handlers.
349 * Output:
350 * if waitForInput is False, the function will return False if there are no
351 * input handlers registered, or if there is no data
352 * available on the registered ones, and will return True
353 * if there is at least one input handler that has data
354 * available.
355 * if waitForInput is True, the function will return False if there are no
356 * input handlers registered, else it will block until an
357 * event appears on one of the file descriptors it watches
358 * and then it will return True.
359 *
360 * If the retured value is True, the input handlers for the corresponding file
361 * descriptors are also called.
362 *
363 * Parametersshould be passed like this:
364 * - from wevent.c:
bc3b44ac dan2001-03-21 01:29:22 +0000365 * waitForInput - apropriate value passed by the function who called us
f5dcab06 dan2001-03-20 23:46:57 +0000366 * inputfd = ConnectionNumber(dpy)
367 * - from wutil.c:
bc3b44ac dan2001-03-21 01:29:22 +0000368 * waitForInput - apropriate value passed by the function who called us
f5dcab06 dan2001-03-20 23:46:57 +0000369 * inputfd = -1
370 *
371 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200372Bool W_HandleInputEvents(Bool waitForInput, int inputfd)
f5dcab06 dan2001-03-20 23:46:57 +0000373{
374#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200375 struct poll fd *fds;
376 InputHandler *handler;
377 int count, timeout, nfds, i, extrafd;
378
379 extrafd = (inputfd < 0) ? 0 : 1;
380
381 if (inputHandler)
382 nfds = WMGetArrayItemCount(inputHandler);
383 else
384 nfds = 0;
385
386 if (!extrafd && nfds == 0) {
387 W_FlushASAPNotificationQueue();
388 return False;
389 }
390
391 fds = wmalloc((nfds + extrafd) * sizeof(struct pollfd));
392 if (extrafd) {
393 /* put this to the end of array to avoid using ranges from 1 to nfds+1 */
394 fds[nfds].fd = inputfd;
395 fds[nfds].events = POLLIN;
396 }
397
398 /* use WM_ITERATE_ARRAY() here */
399 for (i = 0; i < nfds; i++) {
400 handler = WMGetFromArray(inputHandler, i);
401 fds[i].fd = handler->fd;
402 fds[i].events = 0;
403 if (handler->mask & WIReadMask)
404 fds[i].events |= POLLIN;
405
406 if (handler->mask & WIWriteMask)
407 fds[i].events |= POLLOUT;
408
409#if 0 /* FIXME */
410 if (handler->mask & WIExceptMask)
411 FD_SET(handler->fd, &eset);
f5dcab06 dan2001-03-20 23:46:57 +0000412#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200413 }
414
415 /*
416 * Setup the timeout to the estimated time until the
417 * next timer expires.
418 */
419 if (!waitForInput) {
420 timeout = 0;
421 } else if (timerPending()) {
422 struct timeval tv;
423 delayUntilNextTimerEvent(&tv);
424 timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
425 } else {
426 timeout = -1;
427 }
428
429 count = poll(fds, nfds + extrafd, timeout);
430
431 if (count > 0 && nfds > 0) {
432 WMArray *handlerCopy = WMDuplicateArray(inputHandler);
433 int mask;
434
435 /* use WM_ITERATE_ARRAY() here */
436 for (i = 0; i < nfds; i++) {
437 handler = WMGetFromArray(handlerCopy, i);
438 /* check if the handler still exist or was removed by a callback */
439 if (WMGetFirstInArray(inputHandler, handler) == WANotFound)
440 continue;
441
442 mask = 0;
443
444 if ((handler->mask & WIReadMask) &&
445 (fds[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)))
446 mask |= WIReadMask;
447
448 if ((handler->mask & WIWriteMask) && (fds[i].revents & (POLLOUT | POLLWRBAND)))
449 mask |= WIWriteMask;
450
451 if ((handler->mask & WIExceptMask) && (fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
452 mask |= WIExceptMask;
453
454 if (mask != 0 && handler->callback) {
455 (*handler->callback) (handler->fd, mask, handler->clientData);
456 }
457 }
458
459 WMFreeArray(handlerCopy);
460 }
461
462 wfree(fds);
463
464 W_FlushASAPNotificationQueue();
465
466 return (count > 0);
f5dcab06 dan2001-03-20 23:46:57 +0000467#else
468#ifdef HAVE_SELECT
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200469 struct timeval timeout;
470 struct timeval *timeoutPtr;
471 fd_set rset, wset, eset;
472 int maxfd, nfds, i;
473 int count;
474 InputHandler *handler;
475
476 if (inputHandler)
477 nfds = WMGetArrayItemCount(inputHandler);
478 else
479 nfds = 0;
480
481 if (inputfd < 0 && nfds == 0) {
482 W_FlushASAPNotificationQueue();
483 return False;
484 }
485
486 FD_ZERO(&rset);
487 FD_ZERO(&wset);
488 FD_ZERO(&eset);
489
490 if (inputfd < 0) {
491 maxfd = 0;
492 } else {
493 FD_SET(inputfd, &rset);
494 maxfd = inputfd;
495 }
496
497 /* use WM_ITERATE_ARRAY() here */
498 for (i = 0; i < nfds; i++) {
499 handler = WMGetFromArray(inputHandler, i);
500 if (handler->mask & WIReadMask)
501 FD_SET(handler->fd, &rset);
502
503 if (handler->mask & WIWriteMask)
504 FD_SET(handler->fd, &wset);
505
506 if (handler->mask & WIExceptMask)
507 FD_SET(handler->fd, &eset);
508
509 if (maxfd < handler->fd)
510 maxfd = handler->fd;
511 }
512
513 /*
514 * Setup the timeout to the estimated time until the
515 * next timer expires.
516 */
517 if (!waitForInput) {
518 SET_ZERO(timeout);
519 timeoutPtr = &timeout;
520 } else if (timerPending()) {
521 delayUntilNextTimerEvent(&timeout);
522 timeoutPtr = &timeout;
523 } else {
524 timeoutPtr = (struct timeval *)0;
525 }
526
527 count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
528
529 if (count > 0 && nfds > 0) {
530 WMArray *handlerCopy = WMDuplicateArray(inputHandler);
531 int mask;
532
533 /* use WM_ITERATE_ARRAY() here */
534 for (i = 0; i < nfds; i++) {
535 handler = WMGetFromArray(handlerCopy, i);
536 /* check if the handler still exist or was removed by a callback */
537 if (WMGetFirstInArray(inputHandler, handler) == WANotFound)
538 continue;
539
540 mask = 0;
541
542 if ((handler->mask & WIReadMask) && FD_ISSET(handler->fd, &rset))
543 mask |= WIReadMask;
544
545 if ((handler->mask & WIWriteMask) && FD_ISSET(handler->fd, &wset))
546 mask |= WIWriteMask;
547
548 if ((handler->mask & WIExceptMask) && FD_ISSET(handler->fd, &eset))
549 mask |= WIExceptMask;
550
551 if (mask != 0 && handler->callback) {
552 (*handler->callback) (handler->fd, mask, handler->clientData);
553 }
554 }
555
556 WMFreeArray(handlerCopy);
557 }
558
559 W_FlushASAPNotificationQueue();
560
561 return (count > 0);
562#else /* not HAVE_SELECT, not HAVE_POLL */
08225948 dan2003-08-14 01:39:27 +0000563# error Neither select nor poll. You lose.
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200564#endif /* HAVE_SELECT */
565#endif /* HAVE_POLL */
f5dcab06 dan2001-03-20 23:46:57 +0000566}