mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-20 04:48:06 +01:00
- moved WINGs's internal handlers (timer, idle and input) to handlers.c
to avoid code duplication. - simplified wevent.c and wutil.c - renamed WMAddEternalTimerHandler() to WMAddPersistentTimerHandler()
This commit is contained in:
@@ -4,7 +4,9 @@ Changes since wmaker 0.64.0:
|
|||||||
- made programmatic scroller changes send notifications
|
- made programmatic scroller changes send notifications
|
||||||
- replaced WMSetBoxExpandsToParent with WMSetViewExpands...
|
- replaced WMSetBoxExpandsToParent with WMSetViewExpands...
|
||||||
- added WMGetLabelFont()
|
- added WMGetLabelFont()
|
||||||
- added WMAddEternalTimerHandler()
|
- added WMAddPersistentTimerHandler()
|
||||||
|
- Moved all internal handlers (timer, idle and input) to handlers.c
|
||||||
|
- simplified wevent.c and wutil.c.
|
||||||
|
|
||||||
changes since wmaker 0.63.1:
|
changes since wmaker 0.63.1:
|
||||||
............................
|
............................
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ libWINGs_a_SOURCES = \
|
|||||||
dragsource.c \
|
dragsource.c \
|
||||||
error.c \
|
error.c \
|
||||||
findfile.c \
|
findfile.c \
|
||||||
|
handlers.c \
|
||||||
hashtable.c \
|
hashtable.c \
|
||||||
host.c \
|
host.c \
|
||||||
international.c \
|
international.c \
|
||||||
@@ -81,6 +82,7 @@ libWUtil_a_SOURCES = \
|
|||||||
data.c \
|
data.c \
|
||||||
error.c \
|
error.c \
|
||||||
findfile.c \
|
findfile.c \
|
||||||
|
handlers.c \
|
||||||
hashtable.c \
|
hashtable.c \
|
||||||
host.c \
|
host.c \
|
||||||
international.c \
|
international.c \
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ void WMMaskEvent(Display *dpy, long mask, XEvent *event);
|
|||||||
WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback *callback,
|
WMHandlerID WMAddTimerHandler(int milliseconds, WMCallback *callback,
|
||||||
void *cdata);
|
void *cdata);
|
||||||
|
|
||||||
WMHandlerID WMAddEternalTimerHandler(int milliseconds, WMCallback *callback,
|
WMHandlerID WMAddPersistentTimerHandler(int milliseconds, WMCallback *callback,
|
||||||
void *cdata);
|
void *cdata);
|
||||||
|
|
||||||
void WMDeleteTimerWithClientData(void *cdata);
|
void WMDeleteTimerWithClientData(void *cdata);
|
||||||
|
|||||||
@@ -538,6 +538,14 @@ void W_BalloonHandleEnterView(WMView *view);
|
|||||||
|
|
||||||
void W_BalloonHandleLeaveView(WMView *view);
|
void W_BalloonHandleLeaveView(WMView *view);
|
||||||
|
|
||||||
|
Bool W_CheckIdleHandlers(void);
|
||||||
|
|
||||||
|
void W_CheckTimerHandlers(void);
|
||||||
|
|
||||||
|
Bool W_HaveInputHandlers(void);
|
||||||
|
|
||||||
|
Bool W_HandleInputEvents(Bool waitForInput, int inputfd);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
644
WINGs/handlers.c
Normal file
644
WINGs/handlers.c
Normal file
@@ -0,0 +1,644 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* WINGs internal handlers: timer, idle and input handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "WINGsP.h"
|
||||||
|
|
||||||
|
#include "../src/config.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <X11/Xos.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SELECT_H
|
||||||
|
# include <sys/select.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifndef X_GETTIMEOFDAY
|
||||||
|
#define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct TimerHandler {
|
||||||
|
WMCallback *callback; /* procedure to call */
|
||||||
|
struct timeval when; /* when to call the callback */
|
||||||
|
void *clientData;
|
||||||
|
struct TimerHandler *next;
|
||||||
|
int nextDelay; /* 0 if it's one-shot */
|
||||||
|
} TimerHandler;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct IdleHandler {
|
||||||
|
WMCallback *callback;
|
||||||
|
void *clientData;
|
||||||
|
} IdleHandler;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct InputHandler {
|
||||||
|
WMInputProc *callback;
|
||||||
|
void *clientData;
|
||||||
|
int fd;
|
||||||
|
int mask;
|
||||||
|
} InputHandler;
|
||||||
|
|
||||||
|
|
||||||
|
/* queue of timer event handlers */
|
||||||
|
static TimerHandler *timerHandler=NULL;
|
||||||
|
|
||||||
|
static WMBag *idleHandler=NULL;
|
||||||
|
|
||||||
|
static WMBag *inputHandler=NULL;
|
||||||
|
|
||||||
|
// this should go to wevent.c and wutil.c too
|
||||||
|
#define timerPending() (timerHandler)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
rightNow(struct timeval *tv) {
|
||||||
|
X_GETTIMEOFDAY(tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is t1 after t2 ? */
|
||||||
|
#define IS_AFTER(t1, t2) (((t1).tv_sec > (t2).tv_sec) || \
|
||||||
|
(((t1).tv_sec == (t2).tv_sec) \
|
||||||
|
&& ((t1).tv_usec > (t2).tv_usec)))
|
||||||
|
|
||||||
|
#define IS_ZERO(tv) (tv.tv_sec == 0 && tv.tv_usec == 0)
|
||||||
|
|
||||||
|
#define SET_ZERO(tv) tv.tv_sec = 0, tv.tv_usec = 0
|
||||||
|
|
||||||
|
static void
|
||||||
|
addmillisecs(struct timeval *tv, int milliseconds)
|
||||||
|
{
|
||||||
|
tv->tv_usec += milliseconds*1000;
|
||||||
|
|
||||||
|
tv->tv_sec += tv->tv_usec/1000000;
|
||||||
|
tv->tv_usec = tv->tv_usec%1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
enqueueTimerHandler(TimerHandler *handler)
|
||||||
|
{
|
||||||
|
TimerHandler *tmp;
|
||||||
|
|
||||||
|
/* insert callback in queue, sorted by time left */
|
||||||
|
if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) {
|
||||||
|
/* first in the queue */
|
||||||
|
handler->next = timerHandler;
|
||||||
|
timerHandler = handler;
|
||||||
|
} else {
|
||||||
|
tmp = timerHandler;
|
||||||
|
while (tmp->next && IS_AFTER(handler->when, tmp->next->when)) {
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
handler->next = tmp->next;
|
||||||
|
tmp->next = handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
delayUntilNextTimerEvent(struct timeval *delay)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
TimerHandler *handler;
|
||||||
|
|
||||||
|
handler = timerHandler;
|
||||||
|
while (handler && IS_ZERO(handler->when)) handler = handler->next;
|
||||||
|
|
||||||
|
if (!handler) {
|
||||||
|
/* The return value of this function is only valid if there _are_
|
||||||
|
timers active. */
|
||||||
|
delay->tv_sec = 0;
|
||||||
|
delay->tv_usec = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rightNow(&now);
|
||||||
|
if (IS_AFTER(now, handler->when)) {
|
||||||
|
delay->tv_sec = 0;
|
||||||
|
delay->tv_usec = 0;
|
||||||
|
} else {
|
||||||
|
delay->tv_sec = handler->when.tv_sec - now.tv_sec;
|
||||||
|
delay->tv_usec = handler->when.tv_usec - now.tv_usec;
|
||||||
|
if (delay->tv_usec < 0) {
|
||||||
|
delay->tv_usec += 1000000;
|
||||||
|
delay->tv_sec--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WMHandlerID
|
||||||
|
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
|
||||||
|
{
|
||||||
|
TimerHandler *handler;
|
||||||
|
|
||||||
|
handler = malloc(sizeof(TimerHandler));
|
||||||
|
if (!handler)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rightNow(&handler->when);
|
||||||
|
addmillisecs(&handler->when, milliseconds);
|
||||||
|
handler->callback = callback;
|
||||||
|
handler->clientData = cdata;
|
||||||
|
handler->nextDelay = 0;
|
||||||
|
|
||||||
|
enqueueTimerHandler(handler);
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WMHandlerID
|
||||||
|
WMAddPersistentTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
|
||||||
|
{
|
||||||
|
TimerHandler *handler = WMAddTimerHandler(milliseconds, callback, cdata);
|
||||||
|
|
||||||
|
if (handler != NULL)
|
||||||
|
handler->nextDelay = milliseconds;
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WMDeleteTimerWithClientData(void *cdata)
|
||||||
|
{
|
||||||
|
TimerHandler *handler, *tmp;
|
||||||
|
|
||||||
|
if (!cdata || !timerHandler)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp = timerHandler;
|
||||||
|
if (tmp->clientData==cdata) {
|
||||||
|
tmp->nextDelay = 0;
|
||||||
|
if (!IS_ZERO(tmp->when)) {
|
||||||
|
timerHandler = tmp->next;
|
||||||
|
wfree(tmp);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (tmp->next) {
|
||||||
|
if (tmp->next->clientData==cdata) {
|
||||||
|
handler = tmp->next;
|
||||||
|
handler->nextDelay = 0;
|
||||||
|
if (IS_ZERO(handler->when))
|
||||||
|
break;
|
||||||
|
tmp->next = handler->next;
|
||||||
|
wfree(handler);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WMDeleteTimerHandler(WMHandlerID handlerID)
|
||||||
|
{
|
||||||
|
TimerHandler *tmp, *handler=(TimerHandler*)handlerID;
|
||||||
|
|
||||||
|
if (!handler || !timerHandler)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp = timerHandler;
|
||||||
|
|
||||||
|
handler->nextDelay = 0;
|
||||||
|
|
||||||
|
if (IS_ZERO(handler->when))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (tmp==handler) {
|
||||||
|
timerHandler = handler->next;
|
||||||
|
wfree(handler);
|
||||||
|
} else {
|
||||||
|
while (tmp->next) {
|
||||||
|
if (tmp->next==handler) {
|
||||||
|
tmp->next=handler->next;
|
||||||
|
wfree(handler);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WMHandlerID
|
||||||
|
WMAddIdleHandler(WMCallback *callback, void *cdata)
|
||||||
|
{
|
||||||
|
IdleHandler *handler;
|
||||||
|
|
||||||
|
handler = malloc(sizeof(IdleHandler));
|
||||||
|
if (!handler)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
handler->callback = callback;
|
||||||
|
handler->clientData = cdata;
|
||||||
|
/* add handler at end of queue */
|
||||||
|
if (!idleHandler) {
|
||||||
|
idleHandler = WMCreateBag(16);
|
||||||
|
}
|
||||||
|
WMPutInBag(idleHandler, handler);
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WMDeleteIdleHandler(WMHandlerID handlerID)
|
||||||
|
{
|
||||||
|
IdleHandler *handler = (IdleHandler*)handlerID;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
if (!handler || !idleHandler)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos = WMGetFirstInBag(idleHandler, handler);
|
||||||
|
if (pos != WBNotFound) {
|
||||||
|
wfree(handler);
|
||||||
|
WMDeleteFromBag(idleHandler, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!inputHandler)
|
||||||
|
inputHandler = WMCreateBag(16);
|
||||||
|
WMPutInBag(inputHandler, handler);
|
||||||
|
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
WMDeleteInputHandler(WMHandlerID handlerID)
|
||||||
|
{
|
||||||
|
InputHandler *handler = (InputHandler*)handlerID;
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
if (!handler || !inputHandler)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos = WMGetFirstInBag(inputHandler, handler);
|
||||||
|
if (pos != WBNotFound) {
|
||||||
|
wfree(handler);
|
||||||
|
WMDeleteFromBag(inputHandler, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Bool
|
||||||
|
W_CheckIdleHandlers(void)
|
||||||
|
{
|
||||||
|
IdleHandler *handler;
|
||||||
|
WMBag *handlerCopy;
|
||||||
|
WMBagIterator iter;
|
||||||
|
|
||||||
|
if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
|
||||||
|
W_FlushIdleNotificationQueue();
|
||||||
|
/* make sure an observer in queue didn't added an idle handler */
|
||||||
|
return (idleHandler!=NULL && WMGetBagItemCount(idleHandler)>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
handlerCopy = WMCreateBag(WMGetBagItemCount(idleHandler));
|
||||||
|
WMAppendBag(handlerCopy, idleHandler);
|
||||||
|
|
||||||
|
for (handler = WMBagFirst(handlerCopy, &iter);
|
||||||
|
iter != NULL;
|
||||||
|
handler = WMBagNext(handlerCopy, &iter)) {
|
||||||
|
/* check if the handler still exist or was removed by a callback */
|
||||||
|
if (WMGetFirstInBag(idleHandler, handler) == WBNotFound)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
(*handler->callback)(handler->clientData);
|
||||||
|
WMDeleteIdleHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
WMFreeBag(handlerCopy);
|
||||||
|
|
||||||
|
W_FlushIdleNotificationQueue();
|
||||||
|
|
||||||
|
/* this is not necesarrily False, because one handler can re-add itself */
|
||||||
|
return (WMGetBagItemCount(idleHandler)>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
W_CheckTimerHandlers(void)
|
||||||
|
{
|
||||||
|
TimerHandler *handler;
|
||||||
|
struct timeval now;
|
||||||
|
|
||||||
|
if (!timerHandler) {
|
||||||
|
W_FlushASAPNotificationQueue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rightNow(&now);
|
||||||
|
|
||||||
|
handler = timerHandler;
|
||||||
|
while (handler && IS_AFTER(now, handler->when)) {
|
||||||
|
if (!IS_ZERO(handler->when)) {
|
||||||
|
SET_ZERO(handler->when);
|
||||||
|
(*handler->callback)(handler->clientData);
|
||||||
|
}
|
||||||
|
handler = handler->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (timerHandler && IS_ZERO(timerHandler->when)) {
|
||||||
|
handler = timerHandler;
|
||||||
|
timerHandler = timerHandler->next;
|
||||||
|
|
||||||
|
if (handler->nextDelay > 0) {
|
||||||
|
handler->when = now;
|
||||||
|
addmillisecs(&handler->when, handler->nextDelay);
|
||||||
|
enqueueTimerHandler(handler);
|
||||||
|
} else {
|
||||||
|
wfree(handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
W_FlushASAPNotificationQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Bool
|
||||||
|
W_HaveInputHandlers(void)
|
||||||
|
{
|
||||||
|
return (inputHandler && WMGetBagItemCount(inputHandler)>0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This functions will handle input events on all registered file descriptors.
|
||||||
|
* Input:
|
||||||
|
* - waitForInput - True if we want the function to wait until an event
|
||||||
|
* appears on a file descriptor we watch, False if we
|
||||||
|
* want the function to immediately return if there is
|
||||||
|
* no data available on the file descriptors we watch.
|
||||||
|
* - inputfd - Extra input file descriptor to watch for input.
|
||||||
|
* This is only used when called from wevent.c to watch
|
||||||
|
* on ConnectionNumber(dpy) to avoid blocking of X events
|
||||||
|
* if we wait for input from other file handlers.
|
||||||
|
* Output:
|
||||||
|
* if waitForInput is False, the function will return False if there are no
|
||||||
|
* input handlers registered, or if there is no data
|
||||||
|
* available on the registered ones, and will return True
|
||||||
|
* if there is at least one input handler that has data
|
||||||
|
* available.
|
||||||
|
* if waitForInput is True, the function will return False if there are no
|
||||||
|
* input handlers registered, else it will block until an
|
||||||
|
* event appears on one of the file descriptors it watches
|
||||||
|
* and then it will return True.
|
||||||
|
*
|
||||||
|
* If the retured value is True, the input handlers for the corresponding file
|
||||||
|
* descriptors are also called.
|
||||||
|
*
|
||||||
|
* Parametersshould be passed like this:
|
||||||
|
* - from wevent.c:
|
||||||
|
* waitForInput = True
|
||||||
|
* inputfd = ConnectionNumber(dpy)
|
||||||
|
* - from wutil.c:
|
||||||
|
* waitForInput - value passed from the function who calls this function
|
||||||
|
* inputfd = -1
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Bool
|
||||||
|
W_HandleInputEvents(Bool waitForInput, int inputfd)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
|
||||||
|
struct poll fd *fds;
|
||||||
|
InputHandler *handler;
|
||||||
|
int count, timeout, nfds, i, extrafd, retval;
|
||||||
|
|
||||||
|
extrafd = (inputfd < 0) ? 0 : 1;
|
||||||
|
|
||||||
|
if (inputHandler)
|
||||||
|
nfds = WMGetBagItemCount(inputHandler);
|
||||||
|
else
|
||||||
|
nfds = 0;
|
||||||
|
|
||||||
|
if (!extrafd && nfds==0) {
|
||||||
|
W_FlushASAPNotificationQueue();
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
fds = wmalloc((nfds+extrafd) * sizeof(struct pollfd));
|
||||||
|
if (extrafd) {
|
||||||
|
/* put this to the end of array to avoid using ranges from 1 to nfds+1 */
|
||||||
|
fds[nfds].fd = inputfd;
|
||||||
|
fds[nfds].events = POLLIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timeout to the estimated time until the
|
||||||
|
* next timer expires.
|
||||||
|
*/
|
||||||
|
if (!waitForInput) {
|
||||||
|
timeout = 0;
|
||||||
|
} else if (timerPending()) {
|
||||||
|
struct timeval tv;
|
||||||
|
delayUntilNextTimerEvent(&tv);
|
||||||
|
timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
|
} else {
|
||||||
|
timeout = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = poll(fds, nfds+extrafd, timeout);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
handler = WMGetFromBag(handlerCopy, i);
|
||||||
|
/* check if the handler still exist or was removed by a callback */
|
||||||
|
if (WMGetFirstInBag(inputHandler, handler) == WBNotFound)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
mask = 0;
|
||||||
|
|
||||||
|
if ((handler->mask & WIReadMask) &&
|
||||||
|
(fds[i].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI)))
|
||||||
|
mask |= WIReadMask;
|
||||||
|
|
||||||
|
if ((handler->mask & WIWriteMask) &&
|
||||||
|
(fds[i].revents & (POLLOUT | POLLWRBAND)))
|
||||||
|
mask |= WIWriteMask;
|
||||||
|
|
||||||
|
if ((handler->mask & WIExceptMask) &&
|
||||||
|
(fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
|
||||||
|
mask |= WIExceptMask;
|
||||||
|
|
||||||
|
if (mask!=0 && handler->callback) {
|
||||||
|
(*handler->callback)(handler->fd, mask,
|
||||||
|
handler->clientData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WMFreeBag(handlerCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we may only return count>0, because the returned value is not checked
|
||||||
|
* anywhere anyway. -Dan
|
||||||
|
*/
|
||||||
|
retval = ((inputfd < 0) ? (count > 0) :
|
||||||
|
fds[nfds].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI));
|
||||||
|
|
||||||
|
wfree(fds);
|
||||||
|
|
||||||
|
W_FlushASAPNotificationQueue();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SELECT
|
||||||
|
struct timeval timeout;
|
||||||
|
struct timeval *timeoutPtr;
|
||||||
|
fd_set rset, wset, eset;
|
||||||
|
int maxfd, nfds, i;
|
||||||
|
int count;
|
||||||
|
InputHandler *handler;
|
||||||
|
|
||||||
|
if (inputHandler)
|
||||||
|
nfds = WMGetBagItemCount(inputHandler);
|
||||||
|
else
|
||||||
|
nfds = 0;
|
||||||
|
|
||||||
|
if (inputfd<0 && nfds==0) {
|
||||||
|
W_FlushASAPNotificationQueue();
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_ZERO(&wset);
|
||||||
|
FD_ZERO(&eset);
|
||||||
|
|
||||||
|
if (inputfd < 0) {
|
||||||
|
maxfd = 0;
|
||||||
|
} else {
|
||||||
|
FD_SET(inputfd, &rset);
|
||||||
|
maxfd = inputfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<nfds; i++) {
|
||||||
|
handler = WMGetFromBag(inputHandler, i);
|
||||||
|
if (handler->mask & WIReadMask)
|
||||||
|
FD_SET(handler->fd, &rset);
|
||||||
|
|
||||||
|
if (handler->mask & WIWriteMask)
|
||||||
|
FD_SET(handler->fd, &wset);
|
||||||
|
|
||||||
|
if (handler->mask & WIExceptMask)
|
||||||
|
FD_SET(handler->fd, &eset);
|
||||||
|
|
||||||
|
if (maxfd < handler->fd)
|
||||||
|
maxfd = handler->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup the timeout to the estimated time until the
|
||||||
|
* next timer expires.
|
||||||
|
*/
|
||||||
|
if (!waitForInput) {
|
||||||
|
SET_ZERO(timeout);
|
||||||
|
timeoutPtr = &timeout;
|
||||||
|
} else if (timerPending()) {
|
||||||
|
delayUntilNextTimerEvent(&timeout);
|
||||||
|
timeoutPtr = &timeout;
|
||||||
|
} else {
|
||||||
|
timeoutPtr = (struct timeval*)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
handler = WMGetFromBag(handlerCopy, i);
|
||||||
|
/* check if the handler still exist or was removed by a callback */
|
||||||
|
if (WMGetFirstInBag(inputHandler, handler) == WBNotFound)
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (mask!=0 && handler->callback) {
|
||||||
|
(*handler->callback)(handler->fd, mask,
|
||||||
|
handler->clientData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WMFreeBag(handlerCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
W_FlushASAPNotificationQueue();
|
||||||
|
|
||||||
|
return ((inputfd < 0) ? (count > 0) : FD_ISSET(inputfd, &rset));
|
||||||
|
#else /* not HAVE_SELECT, not HAVE_POLL */
|
||||||
|
Neither select nor poll. You lose.
|
||||||
|
#endif /* HAVE_SELECT */
|
||||||
|
#endif /* HAVE_POLL */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
637
WINGs/wevent.c
637
WINGs/wevent.c
@@ -6,55 +6,6 @@
|
|||||||
|
|
||||||
#include "WINGsP.h"
|
#include "WINGsP.h"
|
||||||
|
|
||||||
#include "../src/config.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
#include <poll.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <X11/Xos.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
# include <sys/select.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#ifndef X_GETTIMEOFDAY
|
|
||||||
#define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct TimerHandler {
|
|
||||||
WMCallback *callback; /* procedure to call */
|
|
||||||
struct timeval when; /* when to call the callback */
|
|
||||||
void *clientData;
|
|
||||||
struct TimerHandler *next;
|
|
||||||
int nextDelay; /* 0 if it's one-shot */
|
|
||||||
} TimerHandler;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct IdleHandler {
|
|
||||||
WMCallback *callback;
|
|
||||||
void *clientData;
|
|
||||||
} IdleHandler;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct InputHandler {
|
|
||||||
WMInputProc *callback;
|
|
||||||
void *clientData;
|
|
||||||
int fd;
|
|
||||||
int mask;
|
|
||||||
} InputHandler;
|
|
||||||
|
|
||||||
|
|
||||||
/* table to map event types to event masks */
|
/* table to map event types to event masks */
|
||||||
static unsigned long eventMasks[] = {
|
static unsigned long eventMasks[] = {
|
||||||
@@ -100,353 +51,11 @@ static unsigned long eventMasks[] = {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* queue of timer event handlers */
|
|
||||||
static TimerHandler *timerHandler=NULL;
|
|
||||||
|
|
||||||
static WMBag *idleHandler=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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define timerPending() (timerHandler)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
rightNow(struct timeval *tv) {
|
|
||||||
X_GETTIMEOFDAY(tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is t1 after t2 ? */
|
|
||||||
#define IS_AFTER(t1, t2) (((t1).tv_sec > (t2).tv_sec) || \
|
|
||||||
(((t1).tv_sec == (t2).tv_sec) \
|
|
||||||
&& ((t1).tv_usec > (t2).tv_usec)))
|
|
||||||
|
|
||||||
#define IS_ZERO(tv) (tv.tv_sec == 0 && tv.tv_usec == 0)
|
|
||||||
|
|
||||||
#define SET_ZERO(tv) tv.tv_sec = 0, tv.tv_usec = 0
|
|
||||||
|
|
||||||
static void
|
|
||||||
addmillisecs(struct timeval *tv, int milliseconds)
|
|
||||||
{
|
|
||||||
tv->tv_usec += milliseconds*1000;
|
|
||||||
|
|
||||||
tv->tv_sec += tv->tv_usec/1000000;
|
|
||||||
tv->tv_usec = tv->tv_usec%1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
enqueueTimerHandler(TimerHandler *handler)
|
|
||||||
{
|
|
||||||
TimerHandler *tmp;
|
|
||||||
|
|
||||||
/* insert callback in queue, sorted by time left */
|
|
||||||
if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) {
|
|
||||||
/* first in the queue */
|
|
||||||
handler->next = timerHandler;
|
|
||||||
timerHandler = handler;
|
|
||||||
} else {
|
|
||||||
tmp = timerHandler;
|
|
||||||
while (tmp->next && IS_AFTER(handler->when, tmp->next->when)) {
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
handler->next = tmp->next;
|
|
||||||
tmp->next = handler;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WMHandlerID
|
|
||||||
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
|
|
||||||
{
|
|
||||||
TimerHandler *handler;
|
|
||||||
|
|
||||||
handler = malloc(sizeof(TimerHandler));
|
|
||||||
if (!handler)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
rightNow(&handler->when);
|
|
||||||
addmillisecs(&handler->when, milliseconds);
|
|
||||||
handler->callback = callback;
|
|
||||||
handler->clientData = cdata;
|
|
||||||
handler->nextDelay = 0;
|
|
||||||
|
|
||||||
enqueueTimerHandler(handler);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WMHandlerID
|
|
||||||
WMAddEternalTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
|
|
||||||
{
|
|
||||||
TimerHandler *handler = WMAddTimerHandler(milliseconds, callback, cdata);
|
|
||||||
|
|
||||||
if (handler != NULL)
|
|
||||||
handler->nextDelay = milliseconds;
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteTimerWithClientData(void *cdata)
|
|
||||||
{
|
|
||||||
TimerHandler *handler, *tmp;
|
|
||||||
|
|
||||||
if (!cdata || !timerHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tmp = timerHandler;
|
|
||||||
if (tmp->clientData==cdata) {
|
|
||||||
tmp->nextDelay = 0;
|
|
||||||
if (!IS_ZERO(tmp->when)) {
|
|
||||||
timerHandler = tmp->next;
|
|
||||||
wfree(tmp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (tmp->next) {
|
|
||||||
if (tmp->next->clientData==cdata) {
|
|
||||||
handler = tmp->next;
|
|
||||||
handler->nextDelay = 0;
|
|
||||||
if (IS_ZERO(handler->when))
|
|
||||||
break;
|
|
||||||
tmp->next = handler->next;
|
|
||||||
wfree(handler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteTimerHandler(WMHandlerID handlerID)
|
|
||||||
{
|
|
||||||
TimerHandler *tmp, *handler=(TimerHandler*)handlerID;
|
|
||||||
|
|
||||||
if (!handler || !timerHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tmp = timerHandler;
|
|
||||||
|
|
||||||
handler->nextDelay = 0;
|
|
||||||
|
|
||||||
if (IS_ZERO(handler->when))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (tmp==handler) {
|
|
||||||
timerHandler = handler->next;
|
|
||||||
wfree(handler);
|
|
||||||
} else {
|
|
||||||
while (tmp->next) {
|
|
||||||
if (tmp->next==handler) {
|
|
||||||
tmp->next=handler->next;
|
|
||||||
wfree(handler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WMHandlerID
|
|
||||||
WMAddIdleHandler(WMCallback *callback, void *cdata)
|
|
||||||
{
|
|
||||||
IdleHandler *handler;
|
|
||||||
|
|
||||||
handler = malloc(sizeof(IdleHandler));
|
|
||||||
if (!handler)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
handler->callback = callback;
|
|
||||||
handler->clientData = cdata;
|
|
||||||
/* add handler at end of queue */
|
|
||||||
if (!idleHandler) {
|
|
||||||
idleHandler = WMCreateBag(16);
|
|
||||||
}
|
|
||||||
WMPutInBag(idleHandler, handler);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteIdleHandler(WMHandlerID handlerID)
|
|
||||||
{
|
|
||||||
IdleHandler *handler = (IdleHandler*)handlerID;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
if (!handler || !idleHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pos = WMGetFirstInBag(idleHandler, handler);
|
|
||||||
if (pos != WBNotFound) {
|
|
||||||
wfree(handler);
|
|
||||||
WMDeleteFromBag(idleHandler, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!inputHandler)
|
|
||||||
inputHandler = WMCreateBag(16);
|
|
||||||
WMPutInBag(inputHandler, handler);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteInputHandler(WMHandlerID handlerID)
|
|
||||||
{
|
|
||||||
InputHandler *handler = (InputHandler*)handlerID;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
if (!handler || !inputHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pos = WMGetFirstInBag(inputHandler, handler);
|
|
||||||
if (pos != WBNotFound) {
|
|
||||||
wfree(handler);
|
|
||||||
WMDeleteFromBag(inputHandler, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
checkIdleHandlers()
|
|
||||||
{
|
|
||||||
IdleHandler *handler;
|
|
||||||
WMBag *handlerCopy;
|
|
||||||
WMBagIterator iter;
|
|
||||||
|
|
||||||
if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
|
|
||||||
W_FlushIdleNotificationQueue();
|
|
||||||
/* make sure an observer in queue didn't added an idle handler */
|
|
||||||
return (idleHandler!=NULL && WMGetBagItemCount(idleHandler)>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
handlerCopy = WMCreateBag(WMGetBagItemCount(idleHandler));
|
|
||||||
WMAppendBag(handlerCopy, idleHandler);
|
|
||||||
|
|
||||||
for (handler = WMBagFirst(handlerCopy, &iter);
|
|
||||||
iter != NULL;
|
|
||||||
handler = WMBagNext(handlerCopy, &iter)) {
|
|
||||||
/* check if the handler still exist or was removed by a callback */
|
|
||||||
if (WMGetFirstInBag(idleHandler, handler) == WBNotFound)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
(*handler->callback)(handler->clientData);
|
|
||||||
WMDeleteIdleHandler(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
WMFreeBag(handlerCopy);
|
|
||||||
|
|
||||||
W_FlushIdleNotificationQueue();
|
|
||||||
|
|
||||||
/* this is not necesarrily False, because one handler can re-add itself */
|
|
||||||
return (WMGetBagItemCount(idleHandler)>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
checkTimerHandlers()
|
|
||||||
{
|
|
||||||
TimerHandler *handler;
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
if (!timerHandler) {
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rightNow(&now);
|
|
||||||
|
|
||||||
handler = timerHandler;
|
|
||||||
while (handler && IS_AFTER(now, handler->when)) {
|
|
||||||
if (!IS_ZERO(handler->when)) {
|
|
||||||
SET_ZERO(handler->when);
|
|
||||||
(*handler->callback)(handler->clientData);
|
|
||||||
}
|
|
||||||
handler = handler->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (timerHandler && IS_ZERO(timerHandler->when)) {
|
|
||||||
handler = timerHandler;
|
|
||||||
timerHandler = timerHandler->next;
|
|
||||||
|
|
||||||
if (handler->nextDelay > 0) {
|
|
||||||
handler->when = now;
|
|
||||||
addmillisecs(&handler->when, handler->nextDelay);
|
|
||||||
enqueueTimerHandler(handler);
|
|
||||||
} else {
|
|
||||||
wfree(handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
delayUntilNextTimerEvent(struct timeval *delay)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
TimerHandler *handler;
|
|
||||||
|
|
||||||
handler = timerHandler;
|
|
||||||
while (handler && IS_ZERO(handler->when)) handler = handler->next;
|
|
||||||
|
|
||||||
if (!handler) {
|
|
||||||
/* The return value of this function is only valid if there _are_
|
|
||||||
timers active. */
|
|
||||||
delay->tv_sec = 0;
|
|
||||||
delay->tv_usec = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rightNow(&now);
|
|
||||||
if (IS_AFTER(now, handler->when)) {
|
|
||||||
delay->tv_sec = 0;
|
|
||||||
delay->tv_usec = 0;
|
|
||||||
} else {
|
|
||||||
delay->tv_sec = handler->when.tv_sec - now.tv_sec;
|
|
||||||
delay->tv_usec = handler->when.tv_usec - now.tv_usec;
|
|
||||||
if (delay->tv_usec < 0) {
|
|
||||||
delay->tv_usec += 1000000;
|
|
||||||
delay->tv_sec--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -775,153 +384,6 @@ WMIsDoubleClick(XEvent *event)
|
|||||||
Bool
|
Bool
|
||||||
W_WaitForEvent(Display *dpy, unsigned long xeventmask)
|
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, i, retval;
|
|
||||||
|
|
||||||
if (inputHandler)
|
|
||||||
nfds = WMGetBagItemCount(inputHandler);
|
|
||||||
else
|
|
||||||
nfds = 0;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup the select() timeout to the estimated time until the
|
|
||||||
* next timer expires.
|
|
||||||
*/
|
|
||||||
if (timerPending()) {
|
|
||||||
struct timeval tv;
|
|
||||||
delayUntilNextTimerEvent(&tv);
|
|
||||||
timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
||||||
} else {
|
|
||||||
timeout = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xeventmask==0) {
|
|
||||||
if (XPending(dpy))
|
|
||||||
return True;
|
|
||||||
} else {
|
|
||||||
XEvent ev;
|
|
||||||
if (XCheckMaskEvent(dpy, xeventmask, &ev)) {
|
|
||||||
XPutBackEvent(dpy, &ev);
|
|
||||||
return True;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
count = poll(fds, nfds, timeout);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
handler = WMGetFromBag(handlerCopy, i);
|
|
||||||
/* check if the handler still exist or was removed by a callback */
|
|
||||||
if (WMGetFirstInBag(inputHandler, handler) == WBNotFound)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mask = 0;
|
|
||||||
|
|
||||||
if ((handler->mask & WIReadMask) &&
|
|
||||||
(fds[i].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI)))
|
|
||||||
mask |= WIReadMask;
|
|
||||||
|
|
||||||
if ((handler->mask & WIWriteMask) &&
|
|
||||||
(fds[i].revents & (POLLOUT | POLLWRBAND)))
|
|
||||||
mask |= WIWriteMask;
|
|
||||||
|
|
||||||
if ((handler->mask & WIExceptMask) &&
|
|
||||||
(fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
|
|
||||||
mask |= WIExceptMask;
|
|
||||||
|
|
||||||
if (mask!=0 && handler->callback) {
|
|
||||||
(*handler->callback)(handler->fd, mask,
|
|
||||||
handler->clientData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WMFreeBag(handlerCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = fds[nfds].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI);
|
|
||||||
wfree(fds);
|
|
||||||
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
#else /* not HAVE_POLL */
|
|
||||||
#ifdef HAVE_SELECT
|
|
||||||
struct timeval timeout;
|
|
||||||
struct timeval *timeoutPtr;
|
|
||||||
fd_set rset, wset, eset;
|
|
||||||
int maxfd, nfds, i;
|
|
||||||
int count;
|
|
||||||
InputHandler *handler;
|
|
||||||
|
|
||||||
FD_ZERO(&rset);
|
|
||||||
FD_ZERO(&wset);
|
|
||||||
FD_ZERO(&eset);
|
|
||||||
|
|
||||||
FD_SET(ConnectionNumber(dpy), &rset);
|
|
||||||
maxfd = ConnectionNumber(dpy);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (handler->mask & WIWriteMask)
|
|
||||||
FD_SET(handler->fd, &wset);
|
|
||||||
|
|
||||||
if (handler->mask & WIExceptMask)
|
|
||||||
FD_SET(handler->fd, &eset);
|
|
||||||
|
|
||||||
if (maxfd < handler->fd)
|
|
||||||
maxfd = handler->fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup the select() timeout to the estimated time until the
|
|
||||||
* next timer expires.
|
|
||||||
*/
|
|
||||||
if (timerPending()) {
|
|
||||||
delayUntilNextTimerEvent(&timeout);
|
|
||||||
timeoutPtr = &timeout;
|
|
||||||
} else {
|
|
||||||
timeoutPtr = (struct timeval*)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
XSync(dpy, False);
|
XSync(dpy, False);
|
||||||
if (xeventmask==0) {
|
if (xeventmask==0) {
|
||||||
if (XPending(dpy))
|
if (XPending(dpy))
|
||||||
@@ -934,49 +396,7 @@ W_WaitForEvent(Display *dpy, unsigned long xeventmask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
|
return W_HandleInputEvents(True, ConnectionNumber(dpy));
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
handler = WMGetFromBag(handlerCopy, i);
|
|
||||||
/* check if the handler still exist or was removed by a callback */
|
|
||||||
if (WMGetFirstInBag(inputHandler, handler) == WBNotFound)
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (mask!=0 && handler->callback) {
|
|
||||||
(*handler->callback)(handler->fd, mask,
|
|
||||||
handler->clientData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WMFreeBag(handlerCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
|
|
||||||
return FD_ISSET(ConnectionNumber(dpy), &rset);
|
|
||||||
#else /* not HAVE_SELECT, not HAVE_POLL */
|
|
||||||
Neither select nor poll. You lose.
|
|
||||||
#endif /* HAVE_SELECT */
|
|
||||||
#endif /* HAVE_POLL */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -984,14 +404,14 @@ void
|
|||||||
WMNextEvent(Display *dpy, XEvent *event)
|
WMNextEvent(Display *dpy, XEvent *event)
|
||||||
{
|
{
|
||||||
/* Check any expired timers */
|
/* Check any expired timers */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
|
|
||||||
while (XPending(dpy) == 0) {
|
while (XPending(dpy) == 0) {
|
||||||
/* Do idle stuff */
|
/* Do idle stuff */
|
||||||
/* Do idle and timer stuff while there are no timer or X events */
|
/* Do idle and timer stuff while there are no timer or X events */
|
||||||
while (XPending(dpy) == 0 && checkIdleHandlers()) {
|
while (XPending(dpy) == 0 && W_CheckIdleHandlers()) {
|
||||||
/* dispatch timer events */
|
/* dispatch timer events */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1003,54 +423,12 @@ WMNextEvent(Display *dpy, XEvent *event)
|
|||||||
W_WaitForEvent(dpy, 0);
|
W_WaitForEvent(dpy, 0);
|
||||||
|
|
||||||
/* Check any expired timers */
|
/* Check any expired timers */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
XNextEvent(dpy, event);
|
XNextEvent(dpy, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
void
|
|
||||||
WMMaskEvent(Display *dpy, long mask, XEvent *event)
|
|
||||||
{
|
|
||||||
unsigned long milliseconds;
|
|
||||||
struct timeval timeout;
|
|
||||||
struct timeval *timeoutOrInfty;
|
|
||||||
fd_set readset;
|
|
||||||
|
|
||||||
while (!XCheckMaskEvent(dpy, mask, event)) {
|
|
||||||
/* Do idle stuff while there are no timer or X events */
|
|
||||||
while (checkIdleHandlers()) {
|
|
||||||
if (XCheckMaskEvent(dpy, mask, event))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup the select() timeout to the estimated time until the
|
|
||||||
* next timer expires.
|
|
||||||
*/
|
|
||||||
if (timerPending()) {
|
|
||||||
delayUntilNextTimerEvent(&timeout);
|
|
||||||
timeoutOrInfty = &timeout;
|
|
||||||
} else {
|
|
||||||
timeoutOrInfty = (struct timeval*)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XCheckMaskEvent(dpy, mask, event))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Wait for input on the X connection socket */
|
|
||||||
FD_ZERO(&readset);
|
|
||||||
FD_SET(ConnectionNumber(dpy), &readset);
|
|
||||||
select(1 + ConnectionNumber(dpy), &readset, (fd_set*)0, (fd_set*)0,
|
|
||||||
timeoutOrInfty);
|
|
||||||
|
|
||||||
/* Check any expired timers */
|
|
||||||
checkTimerHandlers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if 1
|
|
||||||
/*
|
/*
|
||||||
* Cant use this because XPending() will make W_WaitForEvent
|
* Cant use this because XPending() will make W_WaitForEvent
|
||||||
* return even if the event in the queue is not what we want,
|
* return even if the event in the queue is not what we want,
|
||||||
@@ -1063,7 +441,7 @@ WMMaskEvent(Display *dpy, long mask, XEvent *event)
|
|||||||
{
|
{
|
||||||
while (!XCheckMaskEvent(dpy, mask, event)) {
|
while (!XCheckMaskEvent(dpy, mask, event)) {
|
||||||
/* Do idle stuff while there are no timer or X events */
|
/* Do idle stuff while there are no timer or X events */
|
||||||
while (checkIdleHandlers()) {
|
while (W_CheckIdleHandlers()) {
|
||||||
if (XCheckMaskEvent(dpy, mask, event))
|
if (XCheckMaskEvent(dpy, mask, event))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1072,10 +450,9 @@ WMMaskEvent(Display *dpy, long mask, XEvent *event)
|
|||||||
W_WaitForEvent(dpy, mask);
|
W_WaitForEvent(dpy, mask);
|
||||||
|
|
||||||
/* Check any expired timers */
|
/* Check any expired timers */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
Bool
|
Bool
|
||||||
WMScreenPending(WMScreen *scr)
|
WMScreenPending(WMScreen *scr)
|
||||||
|
|||||||
566
WINGs/wutil.c
566
WINGs/wutil.c
@@ -1,586 +1,42 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This event handling stuff was based on Tk.
|
* Handle events for non-GUI based applications
|
||||||
* adapted from wevent.c
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "WINGsP.h"
|
#include "WINGsP.h"
|
||||||
|
|
||||||
#include "../src/config.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_POLL_H
|
|
||||||
#include <poll.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <X11/Xos.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SELECT_H
|
|
||||||
# include <sys/select.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#ifndef X_GETTIMEOFDAY
|
|
||||||
#define X_GETTIMEOFDAY(t) gettimeofday(t, (struct timezone*)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct TimerHandler {
|
|
||||||
WMCallback *callback; /* procedure to call */
|
|
||||||
struct timeval when; /* when to call the callback */
|
|
||||||
void *clientData;
|
|
||||||
struct TimerHandler *next;
|
|
||||||
} TimerHandler;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct IdleHandler {
|
|
||||||
WMCallback *callback;
|
|
||||||
void *clientData;
|
|
||||||
} IdleHandler;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct InputHandler {
|
|
||||||
WMInputProc *callback;
|
|
||||||
void *clientData;
|
|
||||||
int fd;
|
|
||||||
int mask;
|
|
||||||
} InputHandler;
|
|
||||||
|
|
||||||
|
|
||||||
/* queue of timer event handlers */
|
|
||||||
static TimerHandler *timerHandler=NULL;
|
|
||||||
|
|
||||||
static WMBag *idleHandler=NULL;
|
|
||||||
|
|
||||||
static WMBag *inputHandler=NULL;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define timerPending() (timerHandler)
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
rightNow(struct timeval *tv) {
|
|
||||||
X_GETTIMEOFDAY(tv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is t1 after t2 ? */
|
|
||||||
#define IS_AFTER(t1, t2) (((t1).tv_sec > (t2).tv_sec) || \
|
|
||||||
(((t1).tv_sec == (t2).tv_sec) \
|
|
||||||
&& ((t1).tv_usec > (t2).tv_usec)))
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
addmillisecs(struct timeval *tv, int milliseconds)
|
|
||||||
{
|
|
||||||
tv->tv_usec += milliseconds*1000;
|
|
||||||
|
|
||||||
tv->tv_sec += tv->tv_usec/1000000;
|
|
||||||
tv->tv_usec = tv->tv_usec%1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WMHandlerID
|
|
||||||
WMAddTimerHandler(int milliseconds, WMCallback *callback, void *cdata)
|
|
||||||
{
|
|
||||||
TimerHandler *handler, *tmp;
|
|
||||||
|
|
||||||
handler = malloc(sizeof(TimerHandler));
|
|
||||||
if (!handler)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
rightNow(&handler->when);
|
|
||||||
addmillisecs(&handler->when, milliseconds);
|
|
||||||
handler->callback = callback;
|
|
||||||
handler->clientData = cdata;
|
|
||||||
/* insert callback in queue, sorted by time left */
|
|
||||||
if (!timerHandler || !IS_AFTER(handler->when, timerHandler->when)) {
|
|
||||||
/* first in the queue */
|
|
||||||
handler->next = timerHandler;
|
|
||||||
timerHandler = handler;
|
|
||||||
} else {
|
|
||||||
tmp = timerHandler;
|
|
||||||
while (tmp->next && IS_AFTER(handler->when, tmp->next->when)) {
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
handler->next = tmp->next;
|
|
||||||
tmp->next = handler;
|
|
||||||
}
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteTimerWithClientData(void *cdata)
|
|
||||||
{
|
|
||||||
TimerHandler *handler, *tmp;
|
|
||||||
|
|
||||||
if (!cdata || !timerHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tmp = timerHandler;
|
|
||||||
if (tmp->clientData==cdata) {
|
|
||||||
timerHandler = tmp->next;
|
|
||||||
wfree(tmp);
|
|
||||||
} else {
|
|
||||||
while (tmp->next) {
|
|
||||||
if (tmp->next->clientData==cdata) {
|
|
||||||
handler = tmp->next;
|
|
||||||
tmp->next = handler->next;
|
|
||||||
wfree(handler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteTimerHandler(WMHandlerID handlerID)
|
|
||||||
{
|
|
||||||
TimerHandler *tmp, *handler=(TimerHandler*)handlerID;
|
|
||||||
|
|
||||||
if (!handler || !timerHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tmp = timerHandler;
|
|
||||||
if (tmp==handler) {
|
|
||||||
timerHandler = handler->next;
|
|
||||||
wfree(handler);
|
|
||||||
} else {
|
|
||||||
while (tmp->next) {
|
|
||||||
if (tmp->next==handler) {
|
|
||||||
tmp->next=handler->next;
|
|
||||||
wfree(handler);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tmp = tmp->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
WMHandlerID
|
|
||||||
WMAddIdleHandler(WMCallback *callback, void *cdata)
|
|
||||||
{
|
|
||||||
IdleHandler *handler;
|
|
||||||
|
|
||||||
handler = malloc(sizeof(IdleHandler));
|
|
||||||
if (!handler)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
handler->callback = callback;
|
|
||||||
handler->clientData = cdata;
|
|
||||||
/* add handler at end of queue */
|
|
||||||
if (!idleHandler) {
|
|
||||||
idleHandler = WMCreateBag(16);
|
|
||||||
}
|
|
||||||
WMPutInBag(idleHandler, handler);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteIdleHandler(WMHandlerID handlerID)
|
|
||||||
{
|
|
||||||
IdleHandler *handler = (IdleHandler*)handlerID;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
if (!handler || !idleHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pos = WMGetFirstInBag(idleHandler, handler);
|
|
||||||
if (pos >= 0) {
|
|
||||||
wfree(handler);
|
|
||||||
WMDeleteFromBag(idleHandler, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!inputHandler)
|
|
||||||
inputHandler = WMCreateBag(16);
|
|
||||||
WMPutInBag(inputHandler, handler);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
WMDeleteInputHandler(WMHandlerID handlerID)
|
|
||||||
{
|
|
||||||
InputHandler *handler = (InputHandler*)handlerID;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
if (!handler || !inputHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
pos = WMGetFirstInBag(inputHandler, handler);
|
|
||||||
if (pos >= 0) {
|
|
||||||
wfree(handler);
|
|
||||||
WMDeleteFromBag(inputHandler, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Bool
|
|
||||||
checkIdleHandlers()
|
|
||||||
{
|
|
||||||
IdleHandler *handler;
|
|
||||||
WMBag *handlerCopy;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
if (!idleHandler || WMGetBagItemCount(idleHandler)==0) {
|
|
||||||
W_FlushIdleNotificationQueue();
|
|
||||||
/* make sure an observer in queue didn't added an idle handler */
|
|
||||||
return (idleHandler!=NULL && WMGetBagItemCount(idleHandler)>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
WMDeleteIdleHandler(handler);
|
|
||||||
wfree(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
WMFreeBag(handlerCopy);
|
|
||||||
|
|
||||||
W_FlushIdleNotificationQueue();
|
|
||||||
|
|
||||||
/* this is not necesarrily False, because one handler can re-add itself */
|
|
||||||
return (WMGetBagItemCount(idleHandler)>0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
checkTimerHandlers()
|
|
||||||
{
|
|
||||||
TimerHandler *handler;
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
if (!timerHandler) {
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rightNow(&now);
|
|
||||||
|
|
||||||
while (timerHandler && IS_AFTER(now, timerHandler->when)) {
|
|
||||||
handler = timerHandler;
|
|
||||||
timerHandler = timerHandler->next;
|
|
||||||
handler->next = NULL;
|
|
||||||
(*handler->callback)(handler->clientData);
|
|
||||||
wfree(handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
delayUntilNextTimerEvent(struct timeval *delay)
|
|
||||||
{
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
if (!timerHandler) {
|
|
||||||
/* The return value of this function is only valid if there _are_
|
|
||||||
* active timers. */
|
|
||||||
delay->tv_sec = 0;
|
|
||||||
delay->tv_usec = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rightNow(&now);
|
|
||||||
if (IS_AFTER(now, timerHandler->when)) {
|
|
||||||
delay->tv_sec = 0;
|
|
||||||
delay->tv_usec = 0;
|
|
||||||
} else {
|
|
||||||
delay->tv_sec = timerHandler->when.tv_sec - now.tv_sec;
|
|
||||||
delay->tv_usec = timerHandler->when.tv_usec - now.tv_usec;
|
|
||||||
if (delay->tv_usec < 0) {
|
|
||||||
delay->tv_usec += 1000000;
|
|
||||||
delay->tv_sec--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This functions will handle input events on all registered file descriptors.
|
|
||||||
* Input:
|
|
||||||
* - waitForInput - True if we want the function to wait until an event
|
|
||||||
* appears on a file descriptor we watch, False if we
|
|
||||||
* want the function to immediately return if there is
|
|
||||||
* no data available on the file descriptors we watch.
|
|
||||||
* Output:
|
|
||||||
* if waitForInput is False, the function will return False if there are no
|
|
||||||
* input handlers registered, or if there is no data
|
|
||||||
* available on the registered ones, and will return True
|
|
||||||
* if there is at least one input handler that has data
|
|
||||||
* available.
|
|
||||||
* if waitForInput is True, the function will return False if there are no
|
|
||||||
* input handlers registered, else it will block until an
|
|
||||||
* event appears on one of the file descriptors it watches
|
|
||||||
* and then it will return True.
|
|
||||||
*
|
|
||||||
* If the retured value is True, the input handlers for the corresponding file
|
|
||||||
* descriptors are also called.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static Bool
|
|
||||||
handleInputEvents(Bool waitForInput)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_POLL) && defined(HAVE_POLL_H) && !defined(HAVE_SELECT)
|
|
||||||
struct pollfd *fds;
|
|
||||||
InputHandler *handler;
|
|
||||||
int count, timeout, nfds, i;
|
|
||||||
|
|
||||||
if (!inputHandler || (nfds=WMGetBagItemCount(inputHandler))==0) {
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
fds = wmalloc(nfds * sizeof(struct pollfd));
|
|
||||||
|
|
||||||
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);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we don't wait for input, set timeout to return immediately,
|
|
||||||
* else setup the timeout to the estimated time until the
|
|
||||||
* next timer expires or if no timer is pending to infinite.
|
|
||||||
*/
|
|
||||||
if (!waitForInput) {
|
|
||||||
timeout = 0;
|
|
||||||
} else if (timerPending()) {
|
|
||||||
struct timeval tv;
|
|
||||||
delayUntilNextTimerEvent(&tv);
|
|
||||||
timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
||||||
} else {
|
|
||||||
timeout = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
count = poll(fds, nfds, timeout);
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
WMBag *handlerCopy = WMCreateBag(nfds);
|
|
||||||
|
|
||||||
for (i=0; i<nfds, i++)
|
|
||||||
WMPutInBag(handlerCopy, WMGetFromBag(inputHandler, i));
|
|
||||||
|
|
||||||
for (i=0; i<nfds; i++) {
|
|
||||||
int mask;
|
|
||||||
|
|
||||||
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[i].revents & (POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI)))
|
|
||||||
mask |= WIReadMask;
|
|
||||||
|
|
||||||
if ((handler->mask & WIWriteMask) &&
|
|
||||||
(fds[i].revents & (POLLOUT | POLLWRBAND)))
|
|
||||||
mask |= WIWriteMask;
|
|
||||||
|
|
||||||
if ((handler->mask & WIExceptMask) &&
|
|
||||||
(fds[i].revents & (POLLHUP | POLLNVAL | POLLERR)))
|
|
||||||
mask |= WIExceptMask;
|
|
||||||
|
|
||||||
if (mask!=0 && handler->callback) {
|
|
||||||
(*handler->callback)(handler->fd, mask,
|
|
||||||
handler->clientData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WMFreeBag(handlerCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
wfree(fds);
|
|
||||||
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
|
|
||||||
return (count > 0);
|
|
||||||
#else /* not HAVE_POLL */
|
|
||||||
#ifdef HAVE_SELECT
|
|
||||||
struct timeval timeout;
|
|
||||||
struct timeval *timeoutPtr;
|
|
||||||
fd_set rset, wset, eset;
|
|
||||||
int maxfd, nfds, i;
|
|
||||||
int count;
|
|
||||||
InputHandler *handler;
|
|
||||||
|
|
||||||
if (!inputHandler || (nfds=WMGetBagItemCount(inputHandler))==0) {
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&rset);
|
|
||||||
FD_ZERO(&wset);
|
|
||||||
FD_ZERO(&eset);
|
|
||||||
|
|
||||||
maxfd = 0;
|
|
||||||
|
|
||||||
for (i=0; i<nfds; i++) {
|
|
||||||
handler = WMGetFromBag(inputHandler, i);
|
|
||||||
if (handler->mask & WIReadMask)
|
|
||||||
FD_SET(handler->fd, &rset);
|
|
||||||
|
|
||||||
if (handler->mask & WIWriteMask)
|
|
||||||
FD_SET(handler->fd, &wset);
|
|
||||||
|
|
||||||
if (handler->mask & WIExceptMask)
|
|
||||||
FD_SET(handler->fd, &eset);
|
|
||||||
|
|
||||||
if (maxfd < handler->fd)
|
|
||||||
maxfd = handler->fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we don't wait for input, set timeout to return immediately,
|
|
||||||
* else setup the timeout to the estimated time until the
|
|
||||||
* next timer expires or if no timer is pending to infinite.
|
|
||||||
*/
|
|
||||||
if (!waitForInput) {
|
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
timeoutPtr = &timeout;
|
|
||||||
} else if (timerPending()) {
|
|
||||||
delayUntilNextTimerEvent(&timeout);
|
|
||||||
timeoutPtr = &timeout;
|
|
||||||
} else {
|
|
||||||
timeoutPtr = (struct timeval*)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
count = select(1 + maxfd, &rset, &wset, &eset, timeoutPtr);
|
|
||||||
|
|
||||||
if (count > 0) {
|
|
||||||
WMBag *handlerCopy = WMCreateBag(nfds);
|
|
||||||
|
|
||||||
for (i=0; i<nfds; i++)
|
|
||||||
WMPutInBag(handlerCopy, WMGetFromBag(inputHandler, i));
|
|
||||||
|
|
||||||
for (i=0; i<nfds; i++) {
|
|
||||||
int mask;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (mask!=0 && handler->callback) {
|
|
||||||
(*handler->callback)(handler->fd, mask,
|
|
||||||
handler->clientData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WMFreeBag(handlerCopy);
|
|
||||||
}
|
|
||||||
|
|
||||||
W_FlushASAPNotificationQueue();
|
|
||||||
|
|
||||||
return (count > 0);
|
|
||||||
#else /* not HAVE_SELECT, not HAVE_POLL */
|
|
||||||
Neither select nor poll. You lose.
|
|
||||||
#endif /* HAVE_SELECT */
|
|
||||||
#endif /* HAVE_POLL */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
WHandleEvents()
|
WHandleEvents()
|
||||||
{
|
{
|
||||||
/* Check any expired timers */
|
/* Check any expired timers */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
|
|
||||||
/* We need to make sure that we have some input handler before calling
|
/* We need to make sure that we have some input handler before calling
|
||||||
* checkIdleHandlers() in a while loop, because else the while loop
|
* W_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 && WMGetBagItemCount(inputHandler)>0) {
|
if (W_HaveInputHandlers()) {
|
||||||
/* Do idle and timer stuff while there are no input events */
|
/* Do idle and timer stuff while there are no input events */
|
||||||
/* Check again if there are still input handlers, because some idle
|
/* Check again if there are still input handlers, because some idle
|
||||||
* handler could have removed them */
|
* handler could have removed them */
|
||||||
while (checkIdleHandlers() && WMGetBagItemCount(inputHandler)>0 &&
|
while (W_CheckIdleHandlers() && W_HaveInputHandlers() &&
|
||||||
!handleInputEvents(False)) {
|
!W_HandleInputEvents(False, -1)) {
|
||||||
/* dispatch timer events */
|
/* dispatch timer events */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
checkIdleHandlers();
|
W_CheckIdleHandlers();
|
||||||
/* dispatch timer events */
|
/* dispatch timer events */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInputEvents(True);
|
W_HandleInputEvents(True, -1);
|
||||||
|
|
||||||
/* Check any expired timers */
|
/* Check any expired timers */
|
||||||
checkTimerHandlers();
|
W_CheckTimerHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -800,7 +800,7 @@ StartUp(Bool defaultScreenOnly)
|
|||||||
wCursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross);
|
wCursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross);
|
||||||
|
|
||||||
/* signal handler stuff that gets called when a signal is caught */
|
/* signal handler stuff that gets called when a signal is caught */
|
||||||
WMAddEternalTimerHandler(500, delayedAction, NULL);
|
WMAddPersistentTimerHandler(500, delayedAction, NULL);
|
||||||
|
|
||||||
/* emergency exit... */
|
/* emergency exit... */
|
||||||
sig_action.sa_handler = handleSig;
|
sig_action.sa_handler = handleSig;
|
||||||
|
|||||||
Reference in New Issue
Block a user