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

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