#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#define DMX_EQ_DEBUG 0
#include "dmx.h"
#include "dmxeq.h"
#include "dmxinput.h"
#include "dmxlog.h"
#include "dmxdpms.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include <X11/extensions/XIproto.h>
#define EXTENSION_PROC_ARGS void *
#if DMX_EQ_DEBUG
#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
#else
#define DMXDBG2(f,a,b)
#define DMXDBG5(f,a,b,c,d,e)
#endif
#define QUEUE_SIZE 256
typedef struct _Event {
xEvent event;
ScreenPtr pScreen;
deviceValuator valuator;
DeviceIntPtr pDev;
} EventRec, *EventPtr;
typedef struct _EventQueue {
HWEventQueueType head;
HWEventQueueType tail;
CARD32 lastEventTime;
Bool lastMotion;
EventRec events[QUEUE_SIZE];
DevicePtr pKbd, pPtr;
ScreenPtr pEnqueueScreen;
ScreenPtr pDequeueScreen;
} EventQueueRec, *EventQueuePtr;
static EventQueueRec dmxEventQueue;
static Bool dmxeqInitializedFlag = FALSE;
Bool dmxeqInitialized(void)
{
return dmxeqInitializedFlag;
}
Bool dmxeqInit(DevicePtr pKbd, DevicePtr pPtr)
{
static unsigned long dmxGeneration = 0;
if (dmxGeneration == serverGeneration && dmxeqInitializedFlag)
return FALSE;
dmxGeneration = serverGeneration;
dmxeqInitializedFlag = TRUE;
dmxEventQueue.head = 0;
dmxEventQueue.tail = 0;
dmxEventQueue.lastEventTime = GetTimeInMillis();
dmxEventQueue.pKbd = pKbd;
dmxEventQueue.pPtr = pPtr;
dmxEventQueue.lastMotion = FALSE;
dmxEventQueue.pEnqueueScreen = screenInfo.screens[0];
dmxEventQueue.pDequeueScreen = dmxEventQueue.pEnqueueScreen;
SetInputCheck(&dmxEventQueue.head, &dmxEventQueue.tail);
return TRUE;
}
void dmxeqEnqueue(DeviceIntPtr pDev, xEvent *e)
{
HWEventQueueType oldtail, newtail;
Bool isMotion;
oldtail = dmxEventQueue.tail;
isMotion = e->u.u.type == MotionNotify;
if (isMotion
&& dmxEventQueue.lastMotion
&& oldtail != dmxEventQueue.head) {
if (oldtail == 0) oldtail = QUEUE_SIZE;
oldtail = oldtail - 1;
} else {
newtail = oldtail + 1;
if (newtail == QUEUE_SIZE) newtail = 0;
if (newtail == dmxEventQueue.head) return;
dmxEventQueue.tail = newtail;
}
DMXDBG2("dmxeqEnqueue %d %d\n", dmxEventQueue.head, dmxEventQueue.tail);
dmxEventQueue.lastMotion = isMotion;
dmxEventQueue.events[oldtail].pScreen = dmxEventQueue.pEnqueueScreen;
dmxEventQueue.events[oldtail].event = *e;
dmxEventQueue.events[oldtail].pDev = pDev;
deviceKeyButtonPointer *ev = (deviceKeyButtonPointer *)e;
if (e->u.u.type >= LASTEvent && (ev->deviceid & MORE_EVENTS))
dmxEventQueue.events[oldtail].valuator = *(deviceValuator *)(ev+1);
if (e->u.keyButtonPointer.time < dmxEventQueue.lastEventTime
&& dmxEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000) {
dmxEventQueue.events[oldtail].event.u.keyButtonPointer.time =
dmxEventQueue.lastEventTime;
}
}
void dmxeqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
{
dmxEventQueue.pEnqueueScreen = pScreen;
if (fromDIX) dmxEventQueue.pDequeueScreen = pScreen;
}
static void dmxeqProcessXInputEvent(xEvent *xe, EventRec *e)
{
deviceKeyButtonPointer *ev = (deviceKeyButtonPointer *)xe;
int id = ev->deviceid & DEVICE_BITS;
DeviceIntPtr pDevice;
dixLookupDevice(&pDevice, id, serverClient, DixUnknownAccess);
if (!pDevice) {
dmxLog(dmxError, "dmxeqProcessInputEvents: id %d not found\n", id);
return;
}
if (!pDevice->public.processInputProc) {
dmxLog(dmxError,
"dmxeqProcessInputEvents: no processInputProc for"
" device id %d (%s)\n", id, pDevice->name);
return;
}
if (ev->deviceid & MORE_EVENTS) {
xe[1] = *(xEvent *)(&e->valuator);
pDevice->public.processInputProc(xe, pDevice, 2);
} else {
pDevice->public.processInputProc(xe, pDevice, 1);
}
}
void dmxeqProcessInputEvents(void)
{
EventRec *e;
int x, y;
xEvent xe[2];
while (dmxEventQueue.head != dmxEventQueue.tail) {
dmxDPMSWakeup();
e = &dmxEventQueue.events[dmxEventQueue.head];
DMXDBG5("dmxeqProcessInputEvents: type=%d screen=%p,%p root=%d,%d\n",
e->event.u.u.type,
e->pScreen, dmxEventQueue.pDequeueScreen,
e->event.u.keyButtonPointer.rootX,
e->event.u.keyButtonPointer.rootY);
if (e->event.u.u.type == MotionNotify
&& e->pScreen != dmxEventQueue.pDequeueScreen) {
dmxEventQueue.pDequeueScreen = e->pScreen;
x = e->event.u.keyButtonPointer.rootX;
y = e->event.u.keyButtonPointer.rootY;
if (dmxEventQueue.head == QUEUE_SIZE - 1) dmxEventQueue.head = 0;
else ++dmxEventQueue.head;
NewCurrentScreen(e->pDev, dmxEventQueue.pDequeueScreen, x, y);
} else {
xe[0] = e->event;
if (dmxEventQueue.head == QUEUE_SIZE - 1) dmxEventQueue.head = 0;
else ++dmxEventQueue.head;
switch (xe[0].u.u.type) {
case KeyPress:
case KeyRelease:
if (!dmxEventQueue.pKbd) {
dmxLog(dmxError, "dmxeqProcessInputEvents: No keyboard\n");
return;
}
dmxEventQueue.pKbd
->processInputProc(xe,
(DeviceIntPtr)dmxEventQueue.pKbd, 1);
break;
default:
dmxeqProcessXInputEvent(xe, e);
break;
case ButtonPress:
case ButtonRelease:
case MotionNotify:
if (!dmxEventQueue.pPtr) {
dmxLog(dmxError, "dmxeqProcessInputEvents: No mouse\n");
return;
}
dmxEventQueue.pPtr
->processInputProc(xe,
(DeviceIntPtr)dmxEventQueue.pPtr, 1);
break;
}
}
}
}