1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 04:20:27 +01:00

Rewrote idle and input handlers using WMBag to avoid a functional problem of

them, regarding removal of other input/idle handlers next to the called one,
from the called handler.
This commit is contained in:
dan
1999-12-03 07:07:14 +00:00
parent 8800cd0b67
commit 34c926186c
5 changed files with 208 additions and 219 deletions

View File

@@ -25,6 +25,10 @@ changes since wmaker 0.61.1:
- fixed a bug in how input events were posted. Establishing 2 or more input - fixed a bug in how input events were posted. Establishing 2 or more input
handlers for the same file descriptor, handling different (read/write/except) handlers for the same file descriptor, handling different (read/write/except)
events, caused wrong handlers to be called. events, caused wrong handlers to be called.
- Reimplemented the input and idle handlers with WMBag to avoid a functional
problem with them: inability to remove handlers next to the called one, from
the called handler itself. Trying to do this with the old version caused the
program to crash.
changes since wmaker 0.61.0: changes since wmaker 0.61.0:
............................ ............................

View File

@@ -44,7 +44,6 @@ typedef struct TimerHandler {
typedef struct IdleHandler { typedef struct IdleHandler {
WMCallback *callback; WMCallback *callback;
void *clientData; void *clientData;
struct IdleHandler *next;
} IdleHandler; } IdleHandler;
@@ -53,7 +52,6 @@ typedef struct InputHandler {
void *clientData; void *clientData;
int fd; int fd;
int mask; int mask;
struct InputHandler *next;
} InputHandler; } InputHandler;
@@ -104,9 +102,9 @@ static unsigned long eventMasks[] = {
/* queue of timer event handlers */ /* queue of timer event handlers */
static TimerHandler *timerHandler=NULL; static TimerHandler *timerHandler=NULL;
static IdleHandler *idleHandler=NULL; static WMBag *idleHandler=NULL;
static InputHandler *inputHandler=NULL; static WMBag *inputHandler=NULL;
/* hook for other toolkits or wmaker process their events */ /* hook for other toolkits or wmaker process their events */
static WMEventHook *extraEventHandler=NULL; static WMEventHook *extraEventHandler=NULL;
@@ -225,7 +223,7 @@ WMDeleteTimerHandler(WMHandlerID handlerID)
WMHandlerID WMHandlerID
WMAddIdleHandler(WMCallback *callback, void *cdata) WMAddIdleHandler(WMCallback *callback, void *cdata)
{ {
IdleHandler *handler, *tmp; IdleHandler *handler;
handler = malloc(sizeof(IdleHandler)); handler = malloc(sizeof(IdleHandler));
if (!handler) if (!handler)
@@ -233,17 +231,11 @@ WMAddIdleHandler(WMCallback *callback, void *cdata)
handler->callback = callback; handler->callback = callback;
handler->clientData = cdata; handler->clientData = cdata;
handler->next = NULL; /* add handler at end of queue */
/* add callback at end of queue */
if (!idleHandler) { if (!idleHandler) {
idleHandler = handler; idleHandler = WMCreateBag(16);
} else {
tmp = idleHandler;
while (tmp->next) {
tmp = tmp->next;
}
tmp->next = handler;
} }
WMPutInBag(idleHandler, handler);
return handler; return handler;
} }
@@ -253,24 +245,16 @@ WMAddIdleHandler(WMCallback *callback, void *cdata)
void void
WMDeleteIdleHandler(WMHandlerID handlerID) WMDeleteIdleHandler(WMHandlerID handlerID)
{ {
IdleHandler *tmp, *handler = (IdleHandler*)handlerID; IdleHandler *handler = (IdleHandler*)handlerID;
int pos;
if (!handler || !idleHandler) if (!handler || !idleHandler)
return; return;
tmp = idleHandler; pos = WMGetFirstInBag(idleHandler, handler);
if (tmp == handler) { if (pos >= 0) {
idleHandler = handler->next;
wfree(handler); wfree(handler);
} else { WMDeleteFromBag(idleHandler, pos);
while (tmp->next) {
if (tmp->next == handler) {
tmp->next = handler->next;
wfree(handler);
break;
}
tmp = tmp->next;
}
} }
} }
@@ -288,68 +272,67 @@ WMAddInputHandler(int fd, int condition, WMInputProc *proc, void *clientData)
handler->callback = proc; handler->callback = proc;
handler->clientData = clientData; handler->clientData = clientData;
handler->next = inputHandler; if (!inputHandler)
inputHandler = WMCreateBag(16);
inputHandler = handler; WMPutInBag(inputHandler, handler);
return handler; return handler;
} }
void void
WMDeleteInputHandler(WMHandlerID handlerID) WMDeleteInputHandler(WMHandlerID handlerID)
{ {
InputHandler *tmp, *handler = (InputHandler*)handlerID; InputHandler *handler = (InputHandler*)handlerID;
int pos;
if (!handler || !inputHandler) if (!handler || !inputHandler)
return; return;
tmp = inputHandler; pos = WMGetFirstInBag(inputHandler, handler);
if (tmp == handler) { if (pos >= 0) {
inputHandler = handler->next;
wfree(handler); wfree(handler);
} else { WMDeleteFromBag(inputHandler, pos);
while (tmp->next) {
if (tmp->next == handler) {
tmp->next = handler->next;
wfree(handler);
break;
}
tmp = tmp->next;
}
} }
} }
static Bool static Bool
checkIdleHandlers() checkIdleHandlers()
{ {
IdleHandler *handler, *tmp; IdleHandler *handler;
WMBag *handlerCopy;
int i, n;
if (!idleHandler) { if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
W_FlushIdleNotificationQueue(); W_FlushIdleNotificationQueue();
/* make sure an observer in queue didn't added an idle handler */ /* make sure an observer in queue didn't added an idle handler */
return (idleHandler!=NULL); return (idleHandler!=NULL && WMGetBagItemCount(idleHandler)>0);
} }
handler = idleHandler; n = WMGetBagItemCount(idleHandler);
handlerCopy = WMCreateBag(n);
for (i=0; i<n; i++)
WMPutInBag(handlerCopy, WMGetFromBag(idleHandler, i));
/* we will process all idleHandlers so, empty the handler list */ for (i=0; i<n; i++) {
idleHandler = NULL; handler = WMGetFromBag(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInBag(idleHandler, handler)<0)
continue;
while (handler) {
tmp = handler->next;
(*handler->callback)(handler->clientData); (*handler->callback)(handler->clientData);
/* remove the handler */ WMDeleteIdleHandler(handler);
wfree(handler);
handler = tmp;
} }
WMFreeBag(handlerCopy);
W_FlushIdleNotificationQueue(); W_FlushIdleNotificationQueue();
/* this is not necesarrily False, because one handler can re-add itself */ /* this is not necesarrily False, because one handler can re-add itself */
return (idleHandler!=NULL); return (WMGetBagItemCount(idleHandler)>0);
} }
@@ -736,25 +719,27 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT) #if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
struct pollfd *fds; struct pollfd *fds;
InputHandler *handler; InputHandler *handler;
int count, timeout, nfds, k, retval; int count, timeout, nfds, i, retval;
for (nfds = 1, handler = inputHandler; if (inputHandler)
handler != 0; handler = handler->next) nfds++; nfds = WMGetBagItemCount(inputHandler);
else
nfds = 0;
fds = wmalloc(nfds * sizeof(struct pollfd)); fds = wmalloc(nfds+1 * sizeof(struct pollfd));
fds[0].fd = ConnectionNumber(dpy); /* put this to the end of array to avoid using ranges from 1 to nfds+1 */
fds[0].events = POLLIN; fds[nfds].fd = ConnectionNumber(dpy);
fds[nfds].events = POLLIN;
for (k = 1, handler = inputHandler; for (i = 0; i<nfds; i++) {
handler; handler = WMGetFromBag(inputHandler, i);
handler = handler->next, k++) { fds[i].fd = handler->fd;
fds[k].fd = handler->fd; fds[i].events = 0;
fds[k].events = 0;
if (handler->mask & WIReadMask) if (handler->mask & WIReadMask)
fds[k].events |= POLLIN; fds[i].events |= POLLIN;
if (handler->mask & WIWriteMask) if (handler->mask & WIWriteMask)
fds[k].events |= POLLOUT; fds[i].events |= POLLOUT;
#if 0 /* FIXME */ #if 0 /* FIXME */
if (handler->mask & WIExceptMask) if (handler->mask & WIExceptMask)
@@ -787,40 +772,44 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
count = poll(fds, nfds, timeout); count = poll(fds, nfds, timeout);
if (count > 0) { if (count>0 && nfds>0) {
handler = inputHandler; WMBag *handlerCopy = WMCreateBag(nfds);
k = 1;
while (handler) { for (i=0; i<nfds; i++)
WMPutInBag(handlerCopy, WMGetFromBag(inputHandler, i));
for (i=0; i<nfds; i++) {
int mask; int mask;
InputHandler *next;
handler = WMGetFromBag(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInBag(inputHandler, handler)<0)
continue;
mask = 0; mask = 0;
if ((handler->mask & WIReadMask) && if ((handler->mask & WIReadMask) &&
(fds[k].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI))) (fds[i].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI)))
mask |= WIReadMask; mask |= WIReadMask;
if ((handler->mask & WIWriteMask) && if ((handler->mask & WIWriteMask) &&
(fds[k].revents & (POLLOUT | POLLWRBAND))) (fds[i].revents & (POLLOUT | POLLWRBAND)))
mask |= WIWriteMask; mask |= WIWriteMask;
if ((handler->mask & WIExceptMask) && if ((handler->mask & WIExceptMask) &&
(fds[k].revents & (POLLHUP | POLLNVAL | POLLERR))) (fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
mask |= WIExceptMask; mask |= WIExceptMask;
next = handler->next;
if (mask!=0 && handler->callback) { if (mask!=0 && handler->callback) {
(*handler->callback)(handler->fd, mask, (*handler->callback)(handler->fd, mask,
handler->clientData); handler->clientData);
} }
handler = next;
k++;
}
} }
retval = fds[0].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI); WMFreeBag(handlerCopy);
}
retval = fds[nfds].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI);
wfree(fds); wfree(fds);
W_FlushASAPNotificationQueue(); W_FlushASAPNotificationQueue();
@@ -831,9 +820,9 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
struct timeval timeout; struct timeval timeout;
struct timeval *timeoutPtr; struct timeval *timeoutPtr;
fd_set rset, wset, eset; fd_set rset, wset, eset;
int maxfd; int maxfd, nfds, i;
int count; int count;
InputHandler *handler = inputHandler; InputHandler *handler;
FD_ZERO(&rset); FD_ZERO(&rset);
FD_ZERO(&wset); FD_ZERO(&wset);
@@ -842,7 +831,13 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
FD_SET(ConnectionNumber(dpy), &rset); FD_SET(ConnectionNumber(dpy), &rset);
maxfd = ConnectionNumber(dpy); maxfd = ConnectionNumber(dpy);
while (handler) { if (inputHandler)
nfds = WMGetBagItemCount(inputHandler);
else
nfds = 0;
for (i=0; i<nfds; i++) {
handler = WMGetFromBag(inputHandler, i);
if (handler->mask & WIReadMask) if (handler->mask & WIReadMask)
FD_SET(handler->fd, &rset); FD_SET(handler->fd, &rset);
@@ -854,8 +849,6 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
if (maxfd < handler->fd) if (maxfd < handler->fd)
maxfd = handler->fd; maxfd = handler->fd;
handler = handler->next;
} }
@@ -884,12 +877,19 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr); count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
if (count > 0) { if (count>0 && nfds>0) {
handler = inputHandler; WMBag *handlerCopy = WMCreateBag(nfds);
while (handler) { for (i=0; i<nfds; i++)
WMPutInBag(handlerCopy, WMGetFromBag(inputHandler, i));
for (i=0; i<nfds; i++) {
int mask; int mask;
InputHandler *next;
handler = WMGetFromBag(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInBag(inputHandler, handler)<0)
continue;
mask = 0; mask = 0;
@@ -902,16 +902,13 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
if ((handler->mask & WIExceptMask) && FD_ISSET(handler->fd, &eset)) if ((handler->mask & WIExceptMask) && FD_ISSET(handler->fd, &eset))
mask |= WIExceptMask; mask |= WIExceptMask;
/* save it because the handler may remove itself! */
next = handler->next;
if (mask!=0 && handler->callback) { if (mask!=0 && handler->callback) {
(*handler->callback)(handler->fd, mask, (*handler->callback)(handler->fd, mask,
handler->clientData); handler->clientData);
} }
handler = next;
} }
WMFreeBag(handlerCopy);
} }
W_FlushASAPNotificationQueue(); W_FlushASAPNotificationQueue();

View File

@@ -856,7 +856,7 @@ familyClick(WMWidget *w, void *data)
for (i = 0; i < WMGetBagItemCount(family->typefaces); i++) { for (i = 0; i < WMGetBagItemCount(family->typefaces); i++) {
char buffer[256]; char buffer[256];
int top; int top=0;
WMListItem *fitem; WMListItem *fitem;
face = WMGetFromBag(family->typefaces, i); face = WMGetFromBag(family->typefaces, i);

View File

@@ -976,7 +976,7 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
char buffer[64]; char buffer[64];
KeySym ksym; KeySym ksym;
char *textEvent = NULL; char *textEvent = NULL;
void *data; void *data = NULL;
int count, refresh = 0; int count, refresh = 0;
int control_pressed = 0; int control_pressed = 0;
int cancelSelection = 1; int cancelSelection = 1;

View File

@@ -43,7 +43,6 @@ typedef struct TimerHandler {
typedef struct IdleHandler { typedef struct IdleHandler {
WMCallback *callback; WMCallback *callback;
void *clientData; void *clientData;
struct IdleHandler *next;
} IdleHandler; } IdleHandler;
@@ -52,16 +51,15 @@ typedef struct InputHandler {
void *clientData; void *clientData;
int fd; int fd;
int mask; int mask;
struct InputHandler *next;
} InputHandler; } InputHandler;
/* queue of timer event handlers */ /* queue of timer event handlers */
static TimerHandler *timerHandler=NULL; static TimerHandler *timerHandler=NULL;
static IdleHandler *idleHandler=NULL; static WMBag *idleHandler=NULL;
static InputHandler *inputHandler=NULL; static WMBag *inputHandler=NULL;
@@ -176,7 +174,7 @@ WMDeleteTimerHandler(WMHandlerID handlerID)
WMHandlerID WMHandlerID
WMAddIdleHandler(WMCallback *callback, void *cdata) WMAddIdleHandler(WMCallback *callback, void *cdata)
{ {
IdleHandler *handler, *tmp; IdleHandler *handler;
handler = malloc(sizeof(IdleHandler)); handler = malloc(sizeof(IdleHandler));
if (!handler) if (!handler)
@@ -184,17 +182,11 @@ WMAddIdleHandler(WMCallback *callback, void *cdata)
handler->callback = callback; handler->callback = callback;
handler->clientData = cdata; handler->clientData = cdata;
handler->next = NULL; /* add handler at end of queue */
/* add callback at end of queue */
if (!idleHandler) { if (!idleHandler) {
idleHandler = handler; idleHandler = WMCreateBag(16);
} else {
tmp = idleHandler;
while (tmp->next) {
tmp = tmp->next;
}
tmp->next = handler;
} }
WMPutInBag(idleHandler, handler);
return handler; return handler;
} }
@@ -204,24 +196,16 @@ WMAddIdleHandler(WMCallback *callback, void *cdata)
void void
WMDeleteIdleHandler(WMHandlerID handlerID) WMDeleteIdleHandler(WMHandlerID handlerID)
{ {
IdleHandler *tmp, *handler = (IdleHandler*)handlerID; IdleHandler *handler = (IdleHandler*)handlerID;
int pos;
if (!handler || !idleHandler) if (!handler || !idleHandler)
return; return;
tmp = idleHandler; pos = WMGetFirstInBag(idleHandler, handler);
if (tmp == handler) { if (pos >= 0) {
idleHandler = handler->next;
wfree(handler); wfree(handler);
} else { WMDeleteFromBag(idleHandler, pos);
while (tmp->next) {
if (tmp->next == handler) {
tmp->next = handler->next;
wfree(handler);
break;
}
tmp = tmp->next;
}
} }
} }
@@ -239,68 +223,68 @@ WMAddInputHandler(int fd, int condition, WMInputProc *proc, void *clientData)
handler->callback = proc; handler->callback = proc;
handler->clientData = clientData; handler->clientData = clientData;
handler->next = inputHandler; if (!inputHandler)
inputHandler = WMCreateBag(16);
inputHandler = handler; WMPutInBag(inputHandler, handler);
return handler; return handler;
} }
void void
WMDeleteInputHandler(WMHandlerID handlerID) WMDeleteInputHandler(WMHandlerID handlerID)
{ {
InputHandler *tmp, *handler = (InputHandler*)handlerID; InputHandler *handler = (InputHandler*)handlerID;
int pos;
if (!handler || !inputHandler) if (!handler || !inputHandler)
return; return;
tmp = inputHandler; pos = WMGetFirstInBag(inputHandler, handler);
if (tmp == handler) { if (pos >= 0) {
inputHandler = handler->next;
wfree(handler); wfree(handler);
} else { WMDeleteFromBag(inputHandler, pos);
while (tmp->next) {
if (tmp->next == handler) {
tmp->next = handler->next;
wfree(handler);
break;
}
tmp = tmp->next;
}
} }
} }
static Bool static Bool
checkIdleHandlers() checkIdleHandlers()
{ {
IdleHandler *handler, *tmp; IdleHandler *handler;
WMBag *handlerCopy;
int i, n;
if (!idleHandler) { if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
W_FlushIdleNotificationQueue(); W_FlushIdleNotificationQueue();
/* make sure an observer in queue didn't added an idle handler */ /* make sure an observer in queue didn't added an idle handler */
return (idleHandler!=NULL); return (idleHandler!=NULL && WMGetBagItemCount(idleHandler)>0);
} }
handler = idleHandler; n = WMGetBagItemCount(idleHandler);
handlerCopy = WMCreateBag(n);
for (i=0; i<n; i++)
WMPutInBag(handlerCopy, WMGetFromBag(idleHandler, i));
/* we will process all idleHandlers so, empty the handler list */ for (i=0; i<n; i++) {
idleHandler = NULL; handler = WMGetFromBag(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInBag(idleHandler, handler)<0)
continue;
while (handler) {
tmp = handler->next;
(*handler->callback)(handler->clientData); (*handler->callback)(handler->clientData);
/* remove the handler */ WMDeleteIdleHandler(handler);
wfree(handler); wfree(handler);
handler = tmp;
} }
WMFreeBag(handlerCopy);
W_FlushIdleNotificationQueue(); W_FlushIdleNotificationQueue();
/* this is not necesarrily False, because one handler can re-add itself */ /* this is not necesarrily False, because one handler can re-add itself */
return (idleHandler!=NULL); return (WMGetBagItemCount(idleHandler)>0);
} }
@@ -387,28 +371,24 @@ handleInputEvents(Bool waitForInput)
#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT) #if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
struct pollfd *fds; struct pollfd *fds;
InputHandler *handler; InputHandler *handler;
int count, timeout, nfds, k; int count, timeout, nfds, i;
if (!inputHandler) { if (!inputHandler || (nfds=WMGetBagItemCount(inputHandler))==0) {
W_FlushASAPNotificationQueue(); W_FlushASAPNotificationQueue();
return False; return False;
} }
for (nfds = 0, handler = inputHandler;
handler != 0; handler = handler->next) nfds++;
fds = wmalloc(nfds * sizeof(struct pollfd)); fds = wmalloc(nfds * sizeof(struct pollfd));
for (k = 0, handler = inputHandler; for (i = 0; i<nfds; i++) {
handler; handler = WMGetFromBag(inputHandler, i);
handler = handler->next, k++) { fds[i].fd = handler->fd;
fds[k].fd = handler->fd; fds[i].events = 0;
fds[k].events = 0;
if (handler->mask & WIReadMask) if (handler->mask & WIReadMask)
fds[k].events |= POLLIN; fds[i].events |= POLLIN;
if (handler->mask & WIWriteMask) if (handler->mask & WIWriteMask)
fds[k].events |= POLLOUT; fds[i].events |= POLLOUT;
#if 0 /* FIXME */ #if 0 /* FIXME */
if (handler->mask & WIExceptMask) if (handler->mask & WIExceptMask)
@@ -434,36 +414,40 @@ handleInputEvents(Bool waitForInput)
count = poll(fds, nfds, timeout); count = poll(fds, nfds, timeout);
if (count > 0) { if (count > 0) {
handler = inputHandler; WMBag *handlerCopy = WMCreateBag(nfds);
k = 0;
while (handler) { for (i=0; i<nfds, i++)
WMPutInBag(handlerCopy, WMGetFromBag(inputHandler, i));
for (i=0; i<nfds; i++) {
int mask; int mask;
InputHandler *next;
handler = WMGetFromBag(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInBag(inputHandler, handler)<0)
continue;
mask = 0; mask = 0;
if ((handler->mask & WIReadMask) && if ((handler->mask & WIReadMask) &&
(fds[k].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI))) (fds[i].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI)))
mask |= WIReadMask; mask |= WIReadMask;
if ((handler->mask & WIWriteMask) && if ((handler->mask & WIWriteMask) &&
(fds[k].revents & (POLLOUT | POLLWRBAND))) (fds[i].revents & (POLLOUT | POLLWRBAND)))
mask |= WIWriteMask; mask |= WIWriteMask;
if ((handler->mask & WIExceptMask) && if ((handler->mask & WIExceptMask) &&
(fds[k].revents & (POLLHUP | POLLNVAL | POLLERR))) (fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
mask |= WIExceptMask; mask |= WIExceptMask;
next = handler->next;
if (mask!=0 && handler->callback) { if (mask!=0 && handler->callback) {
(*handler->callback)(handler->fd, mask, (*handler->callback)(handler->fd, mask,
handler->clientData); handler->clientData);
} }
handler = next;
k++;
} }
WMFreeBag(handlerCopy);
} }
wfree(fds); wfree(fds);
@@ -476,11 +460,11 @@ handleInputEvents(Bool waitForInput)
struct timeval timeout; struct timeval timeout;
struct timeval *timeoutPtr; struct timeval *timeoutPtr;
fd_set rset, wset, eset; fd_set rset, wset, eset;
int maxfd; int maxfd, nfds, i;
int count; int count;
InputHandler *handler = inputHandler; InputHandler *handler;
if (!inputHandler) { if (!inputHandler || (nfds=WMGetBagItemCount(inputHandler))==0) {
W_FlushASAPNotificationQueue(); W_FlushASAPNotificationQueue();
return False; return False;
} }
@@ -491,7 +475,8 @@ handleInputEvents(Bool waitForInput)
maxfd = 0; maxfd = 0;
while (handler) { for (i=0; i<nfds; i++) {
handler = WMGetFromBag(inputHandler, i);
if (handler->mask & WIReadMask) if (handler->mask & WIReadMask)
FD_SET(handler->fd, &rset); FD_SET(handler->fd, &rset);
@@ -503,8 +488,6 @@ handleInputEvents(Bool waitForInput)
if (maxfd < handler->fd) if (maxfd < handler->fd)
maxfd = handler->fd; maxfd = handler->fd;
handler = handler->next;
} }
/* /*
@@ -526,11 +509,18 @@ handleInputEvents(Bool waitForInput)
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr); count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
if (count > 0) { if (count > 0) {
handler = inputHandler; WMBag *handlerCopy = WMCreateBag(nfds);
while (handler) { for (i=0; i<nfds; i++)
WMPutInBag(handlerCopy, WMGetFromBag(inputHandler, i));
for (i=0; i<nfds; i++) {
int mask; int mask;
InputHandler *next;
handler = WMGetFromBag(handlerCopy, i);
/* check if the handler still exist or was removed by a callback */
if (WMGetFirstInBag(inputHandler, handler)<0)
continue;
mask = 0; mask = 0;
@@ -543,16 +533,13 @@ handleInputEvents(Bool waitForInput)
if ((handler->mask & WIExceptMask) && FD_ISSET(handler->fd, &eset)) if ((handler->mask & WIExceptMask) && FD_ISSET(handler->fd, &eset))
mask |= WIExceptMask; mask |= WIExceptMask;
/* save it because the handler may remove itself! */
next = handler->next;
if (mask!=0 && handler->callback) { if (mask!=0 && handler->callback) {
(*handler->callback)(handler->fd, mask, (*handler->callback)(handler->fd, mask,
handler->clientData); handler->clientData);
} }
handler = next;
} }
WMFreeBag(handlerCopy);
} }
W_FlushASAPNotificationQueue(); W_FlushASAPNotificationQueue();
@@ -575,11 +562,12 @@ WHandleEvents()
* checkIdleHandlers() in a while loop, because else the while loop * checkIdleHandlers() in a while loop, because else the while loop
* can run forever (if some idle handler reinitiates itself). * can run forever (if some idle handler reinitiates itself).
*/ */
if (inputHandler) { if (inputHandler && WMGetBagItemCount(inputHandler)>0) {
/* Do idle and timer stuff while there are no input events */ /* Do idle and timer stuff while there are no input events */
/* We check InputHandler again because some idle handler could have /* Check again if there are still input handlers, because some idle
* removed them */ * handler could have removed them */
while (checkIdleHandlers() && inputHandler && !handleInputEvents(False)) { while (checkIdleHandlers() && WMGetBagItemCount(inputHandler)>0 &&
!handleInputEvents(False)) {
/* dispatch timer events */ /* dispatch timer events */
checkTimerHandlers(); checkTimerHandlers();
} }