#if HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# define NEED_EVENTS
# include <X11/X.h>
# include <X11/Xmd.h>
# include <X11/Xproto.h>
# include "misc.h"
# include "windowstr.h"
# include "pixmapstr.h"
# include "inputstr.h"
# include "mi.h"
# include "mipointer.h"
# include "scrnintstr.h"
# include <X11/extensions/XI.h>
# include <X11/extensions/XIproto.h>
# include "extinit.h"
# include "exglobals.h"
#ifdef DPMSExtension
# include "dpmsproc.h"
# define DPMS_SERVER
# include <X11/extensions/dpms.h>
#endif
#define QUEUE_SIZE 512
typedef struct _Event {
xEvent event[7];
int nevents;
ScreenPtr pScreen;
DeviceIntPtr pDev;
} EventRec, *EventPtr;
typedef struct _EventQueue {
HWEventQueueType head, tail;
CARD32 lastEventTime;
int lastMotion;
EventRec events[QUEUE_SIZE];
ScreenPtr pEnqueueScreen;
ScreenPtr pDequeueScreen;
mieqHandler handlers[128];
} EventQueueRec, *EventQueuePtr;
static EventQueueRec miEventQueue;
#ifdef XQUARTZ
#include <pthread.h>
static pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
extern BOOL serverInitComplete;
extern pthread_mutex_t serverInitCompleteMutex;
extern pthread_cond_t serverInitCompleteCond;
static inline void wait_for_server_init(void) {
if(!serverInitComplete) {
pthread_mutex_lock(&serverInitCompleteMutex);
while(!serverInitComplete)
pthread_cond_wait(&serverInitCompleteCond, &serverInitCompleteMutex);
pthread_mutex_unlock(&serverInitCompleteMutex);
}
}
#endif
Bool
mieqInit(void)
{
int i;
miEventQueue.head = miEventQueue.tail = 0;
miEventQueue.lastEventTime = GetTimeInMillis ();
miEventQueue.lastMotion = FALSE;
miEventQueue.pEnqueueScreen = screenInfo.screens[0];
miEventQueue.pDequeueScreen = miEventQueue.pEnqueueScreen;
for (i = 0; i < 128; i++)
miEventQueue.handlers[i] = NULL;
SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
return TRUE;
}
void
mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
{
#ifdef XQUARTZ
wait_for_server_init();
pthread_mutex_lock(&miEventQueueMutex);
#endif
unsigned int oldtail = miEventQueue.tail;
int isMotion = 0;
deviceValuator *v = (deviceValuator *) e;
EventPtr laste = &miEventQueue.events[(oldtail - 1) %
QUEUE_SIZE];
deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *)
&laste->event[0];
if (e->u.u.type == MotionNotify)
isMotion = inputInfo.pointer->id;
else if (e->u.u.type == DeviceMotionNotify)
isMotion = pDev->id;
if (e->u.u.type == DeviceValuator) {
if (laste->nevents > 6) {
ErrorF("mieqEnqueue: more than six valuator events; dropping.\n");
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
return;
}
if (oldtail == miEventQueue.head ||
!(lastkbp->type == DeviceMotionNotify ||
lastkbp->type == DeviceButtonPress ||
lastkbp->type == DeviceButtonRelease ||
lastkbp->type == ProximityIn ||
lastkbp->type == ProximityOut) ||
((lastkbp->deviceid & DEVICE_BITS) !=
(v->deviceid & DEVICE_BITS))) {
ErrorF("mieqEnequeue: out-of-order valuator event; dropping.\n");
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
return;
}
memcpy(&(laste->event[laste->nevents++]), e, sizeof(xEvent));
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
return;
}
if (isMotion && isMotion == miEventQueue.lastMotion &&
oldtail != miEventQueue.head) {
oldtail = (oldtail - 1) % QUEUE_SIZE;
}
else if ((oldtail + 1) % QUEUE_SIZE == miEventQueue.head) {
ErrorF("tossed event which came in late\n");
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
return;
}
memcpy(&(miEventQueue.events[oldtail].event[0]), e, sizeof(xEvent));
miEventQueue.events[oldtail].nevents = 1;
if (e->u.keyButtonPointer.time < miEventQueue.lastEventTime &&
miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time =
miEventQueue.lastEventTime;
miEventQueue.lastEventTime =
miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time;
miEventQueue.events[oldtail].pScreen = miEventQueue.pEnqueueScreen;
miEventQueue.events[oldtail].pDev = pDev;
miEventQueue.lastMotion = isMotion;
miEventQueue.tail = (oldtail + 1) % QUEUE_SIZE;
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
}
void
mieqSwitchScreen(ScreenPtr pScreen, Bool fromDIX)
{
#ifdef XQUARTZ
pthread_mutex_lock(&miEventQueueMutex);
#endif
miEventQueue.pEnqueueScreen = pScreen;
if (fromDIX)
miEventQueue.pDequeueScreen = pScreen;
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
}
void
mieqSetHandler(int event, mieqHandler handler)
{
#ifdef XQUARTZ
pthread_mutex_lock(&miEventQueueMutex);
#endif
if (handler && miEventQueue.handlers[event])
ErrorF("mieq: warning: overriding existing handler %p with %p for "
"event %d\n", miEventQueue.handlers[event], handler, event);
miEventQueue.handlers[event] = handler;
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
}
void
mieqProcessInputEvents(void)
{
mieqHandler handler;
EventRec e;
int x = 0, y = 0;
DeviceIntPtr dev = NULL;
#ifdef XQUARTZ
pthread_mutex_lock(&miEventQueueMutex);
#endif
while (miEventQueue.head != miEventQueue.tail) {
memcpy(&e, &miEventQueue.events[miEventQueue.head], sizeof(EventRec));
handler = miEventQueue.handlers[e.event[0].u.u.type];
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
if (screenIsSaved == SCREEN_SAVER_ON)
SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
#ifdef DPMSExtension
else if (DPMSPowerLevel != DPMSModeOn)
SetScreenSaverTimer();
if (DPMSPowerLevel != DPMSModeOn)
DPMSSet(DPMSModeOn);
#endif
if (handler) {
handler(e.pScreen->myNum, e.event, e.pDev, e.nevents);
}
else if (e.pScreen != miEventQueue.pDequeueScreen) {
miEventQueue.pDequeueScreen = e.pScreen;
x = e.event[0].u.keyButtonPointer.rootX;
y = e.event[0].u.keyButtonPointer.rootY;
NewCurrentScreen(e.pScreen, x, y);
}
else {
if (e.event[0].u.u.type == KeyPress ||
e.event[0].u.u.type == KeyRelease) {
SwitchCoreKeyboard(e.pDev);
dev = inputInfo.keyboard;
}
else if (e.event[0].u.u.type == MotionNotify ||
e.event[0].u.u.type == ButtonPress ||
e.event[0].u.u.type == ButtonRelease) {
SwitchCorePointer(e.pDev);
dev = inputInfo.pointer;
}
else {
dev = e.pDev;
}
dev->public.processInputProc(e.event, dev, e.nevents);
}
#ifdef XQUARTZ
pthread_mutex_lock(&miEventQueueMutex);
#endif
}
#ifdef XQUARTZ
pthread_mutex_unlock(&miEventQueueMutex);
#endif
}