2003-11-14 16:54:54 +01:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
Copyright 1990, 1998 The Open Group
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
|
|
in this Software without prior written authorization from The Open Group.
|
|
|
|
*
|
|
|
|
* Author: Keith Packard, MIT X Consortium
|
|
|
|
*/
|
2006-11-16 11:13:27 +01:00
|
|
|
/*
|
|
|
|
* MPX additions:
|
|
|
|
* Copyright © 2006 Peter Hutterer
|
|
|
|
* License see above.
|
|
|
|
* Author: Peter Hutterer <peter@cs.unisa.edu.au>
|
|
|
|
*
|
|
|
|
*/
|
2003-11-14 16:54:54 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* mieq.c
|
|
|
|
*
|
|
|
|
* Machine independent event queue
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2006-09-06 15:20:55 +02:00
|
|
|
#if HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
# define NEED_EVENTS
|
2005-04-20 14:25:48 +02:00
|
|
|
# include <X11/X.h>
|
|
|
|
# include <X11/Xmd.h>
|
|
|
|
# include <X11/Xproto.h>
|
2003-11-14 16:54:54 +01:00
|
|
|
# include "misc.h"
|
|
|
|
# include "windowstr.h"
|
|
|
|
# include "pixmapstr.h"
|
|
|
|
# include "inputstr.h"
|
|
|
|
# include "mi.h"
|
2006-07-20 22:39:54 +02:00
|
|
|
# include "mipointer.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
# include "scrnintstr.h"
|
2006-07-20 22:39:54 +02:00
|
|
|
# include <X11/extensions/XI.h>
|
|
|
|
# include <X11/extensions/XIproto.h>
|
2007-05-02 06:20:09 +02:00
|
|
|
# include <X11/extensions/geproto.h>
|
2006-07-20 22:39:54 +02:00
|
|
|
# include "extinit.h"
|
|
|
|
# include "exglobals.h"
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2007-01-03 21:05:35 +01:00
|
|
|
#ifdef DPMSExtension
|
|
|
|
# include "dpmsproc.h"
|
|
|
|
# define DPMS_SERVER
|
|
|
|
# include <X11/extensions/dpms.h>
|
|
|
|
#endif
|
|
|
|
|
2007-04-08 12:56:41 +02:00
|
|
|
#define QUEUE_SIZE 512
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2007-04-26 08:28:50 +02:00
|
|
|
#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
|
|
|
|
#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
typedef struct _Event {
|
2007-05-02 06:20:09 +02:00
|
|
|
EventListPtr events;
|
2006-07-20 22:39:54 +02:00
|
|
|
int nevents;
|
|
|
|
ScreenPtr pScreen;
|
2006-11-04 20:20:45 +01:00
|
|
|
DeviceIntPtr pDev; /* device this event _originated_ from */
|
2003-11-14 16:54:54 +01:00
|
|
|
} EventRec, *EventPtr;
|
|
|
|
|
|
|
|
typedef struct _EventQueue {
|
2006-07-20 22:39:54 +02:00
|
|
|
HWEventQueueType head, tail; /* long for SetInputCheck */
|
|
|
|
CARD32 lastEventTime; /* to avoid time running backwards */
|
|
|
|
int lastMotion; /* device ID if last event motion? */
|
|
|
|
EventRec events[QUEUE_SIZE]; /* static allocation for signals */
|
2007-03-20 23:10:38 +01:00
|
|
|
mieqHandler handlers[128]; /* custom event handler */
|
2003-11-14 16:54:54 +01:00
|
|
|
} EventQueueRec, *EventQueuePtr;
|
|
|
|
|
|
|
|
static EventQueueRec miEventQueue;
|
|
|
|
|
|
|
|
Bool
|
2007-04-09 23:33:15 +02:00
|
|
|
mieqInit(void)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-03-20 23:10:38 +01:00
|
|
|
int i;
|
|
|
|
|
2003-11-14 16:54:54 +01:00
|
|
|
miEventQueue.head = miEventQueue.tail = 0;
|
|
|
|
miEventQueue.lastEventTime = GetTimeInMillis ();
|
|
|
|
miEventQueue.lastMotion = FALSE;
|
2007-03-20 23:10:38 +01:00
|
|
|
for (i = 0; i < 128; i++)
|
|
|
|
miEventQueue.handlers[i] = NULL;
|
2007-05-02 06:20:09 +02:00
|
|
|
for (i = 0; i < QUEUE_SIZE; i++)
|
|
|
|
{
|
|
|
|
EventListPtr evlist = InitEventList(7); /* 1 + MAX_VALUATOR_EVENTS */
|
|
|
|
if (!evlist)
|
|
|
|
FatalError("Could not allocate event queue.\n");
|
|
|
|
miEventQueue.events[i].events = evlist;
|
|
|
|
}
|
2006-10-19 23:30:28 +02:00
|
|
|
SetInputCheck(&miEventQueue.head, &miEventQueue.tail);
|
2003-11-14 16:54:54 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
|
|
|
|
* will never be interrupted. If this is called from both signal
|
|
|
|
* handlers and regular code, make sure the signal is suspended when
|
|
|
|
* called from regular code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
2006-10-19 23:30:28 +02:00
|
|
|
mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-06-26 12:13:54 +02:00
|
|
|
unsigned int oldtail = miEventQueue.tail, newtail;
|
2007-05-02 06:20:09 +02:00
|
|
|
EventListPtr evt;
|
2006-07-20 22:39:54 +02:00
|
|
|
int isMotion = 0;
|
2007-06-19 09:50:52 +02:00
|
|
|
int evlen;
|
|
|
|
|
2006-07-20 22:39:54 +02:00
|
|
|
|
2006-11-16 05:41:14 +01:00
|
|
|
/* avoid merging events from different devices */
|
2007-03-25 07:30:03 +02:00
|
|
|
if (e->u.u.type == MotionNotify)
|
2006-11-16 05:41:14 +01:00
|
|
|
isMotion = pDev->id;
|
2006-10-19 23:30:28 +02:00
|
|
|
else if (e->u.u.type == DeviceMotionNotify)
|
2006-11-28 05:04:36 +01:00
|
|
|
isMotion = pDev->id | (1 << 8); /* flag to indicate DeviceMotion */
|
2006-10-19 23:30:28 +02:00
|
|
|
|
|
|
|
/* We silently steal valuator events: just tack them on to the last
|
|
|
|
* motion event they need to be attached to. Sigh. */
|
|
|
|
if (e->u.u.type == DeviceValuator) {
|
2007-05-02 06:20:09 +02:00
|
|
|
deviceValuator *v = (deviceValuator *) e;
|
|
|
|
EventPtr laste;
|
|
|
|
deviceKeyButtonPointer *lastkbp;
|
|
|
|
|
2007-06-26 12:13:54 +02:00
|
|
|
laste = &miEventQueue.events[(oldtail - 1) % QUEUE_SIZE];
|
2007-05-02 06:20:09 +02:00
|
|
|
lastkbp = (deviceKeyButtonPointer *) laste->events->event;
|
|
|
|
|
2006-10-19 23:30:28 +02:00
|
|
|
if (laste->nevents > 6) {
|
|
|
|
ErrorF("mieqEnqueue: more than six valuator events; dropping.\n");
|
2006-07-20 22:39:54 +02:00
|
|
|
return;
|
|
|
|
}
|
2006-10-19 23:44:46 +02:00
|
|
|
if (oldtail == miEventQueue.head ||
|
2006-10-19 23:30:28 +02:00
|
|
|
!(lastkbp->type == DeviceMotionNotify ||
|
|
|
|
lastkbp->type == DeviceButtonPress ||
|
|
|
|
lastkbp->type == DeviceButtonRelease) ||
|
2006-10-27 00:25:21 +02:00
|
|
|
((lastkbp->deviceid & DEVICE_BITS) !=
|
|
|
|
(v->deviceid & DEVICE_BITS))) {
|
2006-10-19 23:30:28 +02:00
|
|
|
ErrorF("mieqEnequeue: out-of-order valuator event; dropping.\n");
|
|
|
|
return;
|
2006-07-20 22:39:54 +02:00
|
|
|
}
|
2007-05-02 06:20:09 +02:00
|
|
|
|
|
|
|
memcpy((laste->events[laste->nevents++].event), e, sizeof(xEvent));
|
2006-10-19 23:30:28 +02:00
|
|
|
return;
|
2006-07-20 22:39:54 +02:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
|
2006-07-20 22:39:54 +02:00
|
|
|
if (isMotion && isMotion == miEventQueue.lastMotion &&
|
|
|
|
oldtail != miEventQueue.head) {
|
2007-06-26 12:13:54 +02:00
|
|
|
oldtail = (oldtail - 1) % QUEUE_SIZE;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
2006-07-20 22:39:54 +02:00
|
|
|
else {
|
2007-06-11 09:23:18 +02:00
|
|
|
newtail = (oldtail + 1) % QUEUE_SIZE;
|
2006-11-04 20:20:45 +01:00
|
|
|
/* Toss events which come in late. Usually this means your server's
|
|
|
|
* stuck in an infinite loop somewhere, but SIGIO is still getting
|
|
|
|
* handled. */
|
2006-07-20 22:39:54 +02:00
|
|
|
if (newtail == miEventQueue.head) {
|
|
|
|
ErrorF("tossed event which came in late\n");
|
2003-11-14 16:54:54 +01:00
|
|
|
return;
|
2006-07-20 22:39:54 +02:00
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
miEventQueue.tail = newtail;
|
|
|
|
}
|
2006-07-20 22:39:54 +02:00
|
|
|
|
2007-05-02 06:20:09 +02:00
|
|
|
evlen = sizeof(xEvent);
|
|
|
|
if (e->u.u.type == GenericEvent)
|
|
|
|
evlen += ((xGenericEvent*)e)->length * 4;
|
|
|
|
|
|
|
|
evt = miEventQueue.events[oldtail].events;
|
|
|
|
if (evt->evlen < evlen)
|
|
|
|
{
|
|
|
|
evt->evlen = evlen;
|
|
|
|
evt->event = xrealloc(evt->event, evt->evlen);
|
2007-07-16 10:31:00 +02:00
|
|
|
if (!evt->event)
|
|
|
|
{
|
|
|
|
ErrorF("Running out of memory. Tossing event.\n");
|
|
|
|
return;
|
|
|
|
}
|
2007-05-02 06:20:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(evt->event, e, evlen);
|
2006-07-20 22:39:54 +02:00
|
|
|
miEventQueue.events[oldtail].nevents = 1;
|
|
|
|
|
2006-10-19 23:30:28 +02:00
|
|
|
/* Make sure that event times don't go backwards - this
|
|
|
|
* is "unnecessary", but very useful. */
|
2007-07-16 10:31:00 +02:00
|
|
|
if (e->u.u.type != GenericEvent &&
|
|
|
|
e->u.keyButtonPointer.time < miEventQueue.lastEventTime &&
|
|
|
|
miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
|
2007-05-02 06:20:09 +02:00
|
|
|
evt->event->u.keyButtonPointer.time = miEventQueue.lastEventTime;
|
2006-09-30 16:05:46 +02:00
|
|
|
|
2007-05-02 06:20:09 +02:00
|
|
|
miEventQueue.lastEventTime = evt->event->u.keyButtonPointer.time;
|
2007-04-26 08:28:50 +02:00
|
|
|
miEventQueue.events[oldtail].pScreen = EnqueueScreen(pDev);
|
2006-07-20 22:39:54 +02:00
|
|
|
miEventQueue.events[oldtail].pDev = pDev;
|
|
|
|
|
|
|
|
miEventQueue.lastMotion = isMotion;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-04-26 08:28:50 +02:00
|
|
|
mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2007-04-26 08:28:50 +02:00
|
|
|
EnqueueScreen(pDev) = pScreen;
|
2003-11-14 16:54:54 +01:00
|
|
|
if (fromDIX)
|
2007-04-26 08:28:50 +02:00
|
|
|
DequeueScreen(pDev) = pScreen;
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
|
2007-03-20 23:10:38 +01:00
|
|
|
void
|
|
|
|
mieqSetHandler(int event, mieqHandler handler)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-10-19 23:30:28 +02:00
|
|
|
/* Call this from ProcessInputEvents(). */
|
|
|
|
void
|
2007-04-09 23:33:15 +02:00
|
|
|
mieqProcessInputEvents(void)
|
2003-11-14 16:54:54 +01:00
|
|
|
{
|
2006-10-19 23:30:28 +02:00
|
|
|
EventRec *e = NULL;
|
|
|
|
int x = 0, y = 0;
|
2007-05-02 06:20:09 +02:00
|
|
|
xEvent* event;
|
2006-10-19 23:30:28 +02:00
|
|
|
|
|
|
|
while (miEventQueue.head != miEventQueue.tail) {
|
|
|
|
if (screenIsSaved == SCREEN_SAVER_ON)
|
|
|
|
SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
|
2007-01-03 21:05:35 +01:00
|
|
|
#ifdef DPMSExtension
|
|
|
|
else if (DPMSPowerLevel != DPMSModeOn)
|
|
|
|
SetScreenSaverTimer();
|
|
|
|
|
|
|
|
if (DPMSPowerLevel != DPMSModeOn)
|
|
|
|
DPMSSet(DPMSModeOn);
|
|
|
|
#endif
|
2006-10-19 23:30:28 +02:00
|
|
|
|
|
|
|
e = &miEventQueue.events[miEventQueue.head];
|
|
|
|
/* Assumption - screen switching can only occur on motion events. */
|
2007-06-11 09:23:18 +02:00
|
|
|
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
|
|
|
|
|
2007-04-26 08:28:50 +02:00
|
|
|
if (e->pScreen != DequeueScreen(e->pDev)) {
|
|
|
|
DequeueScreen(e->pDev) = e->pScreen;
|
2007-05-02 06:20:09 +02:00
|
|
|
x = e->events[0].event->u.keyButtonPointer.rootX;
|
|
|
|
y = e->events[0].event->u.keyButtonPointer.rootY;
|
2007-04-26 08:28:50 +02:00
|
|
|
NewCurrentScreen (e->pDev, DequeueScreen(e->pDev), x, y);
|
2006-10-19 23:30:28 +02:00
|
|
|
}
|
|
|
|
else {
|
2007-03-20 23:10:38 +01:00
|
|
|
/* If someone's registered a custom event handler, let them
|
|
|
|
* steal it. */
|
2007-05-02 06:20:09 +02:00
|
|
|
if (miEventQueue.handlers[e->events->event->u.u.type]) {
|
|
|
|
miEventQueue.handlers[e->events->event->u.u.type](
|
|
|
|
DequeueScreen(e->pDev)->myNum,
|
2007-09-26 07:42:49 +02:00
|
|
|
e->events->event,
|
|
|
|
e->pDev,
|
2007-05-02 06:20:09 +02:00
|
|
|
e->nevents);
|
2007-03-20 23:10:38 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-10-02 05:58:40 +02:00
|
|
|
/* Make sure our keymap, et al, is changed to suit. */
|
|
|
|
if ((e->events->event[0].u.u.type == DeviceKeyPress ||
|
|
|
|
e->events->event[0].u.u.type == DeviceKeyRelease ||
|
|
|
|
e->events->event[0].u.u.type == KeyPress ||
|
|
|
|
e->events->event[0].u.u.type == KeyRelease) &&
|
|
|
|
e->pDev->coreEvents) {
|
2006-10-19 23:30:28 +02:00
|
|
|
SwitchCoreKeyboard(e->pDev);
|
|
|
|
}
|
2007-05-02 06:20:09 +02:00
|
|
|
|
|
|
|
/* FIXME: Bad hack. The only event where we actually get multiple
|
|
|
|
* events at once is a DeviceMotionNotify followed by
|
|
|
|
* DeviceValuators. For now it's save enough to just take the
|
|
|
|
* event directly or copy the bunch of events and pass in the
|
|
|
|
* copy. Eventually the interface for the processInputProc needs
|
|
|
|
* to be changed. (whot)
|
|
|
|
*/
|
|
|
|
if (e->nevents > 1)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
event = xcalloc(e->nevents, sizeof(xEvent));
|
|
|
|
for (i = 0; i < e->nevents; i++)
|
|
|
|
memcpy(&event[i], e->events[i].event, sizeof(xEvent));
|
|
|
|
}
|
|
|
|
else
|
2007-07-16 10:31:00 +02:00
|
|
|
{
|
2007-05-02 06:20:09 +02:00
|
|
|
event = e->events->event;
|
2007-07-16 10:31:00 +02:00
|
|
|
}
|
2007-05-02 06:20:09 +02:00
|
|
|
|
2007-09-26 07:42:49 +02:00
|
|
|
e->pDev->public.processInputProc(event, e->pDev, e->nevents);
|
2007-05-02 06:20:09 +02:00
|
|
|
|
|
|
|
if (e->nevents > 1)
|
|
|
|
xfree(event);
|
2006-10-19 23:30:28 +02:00
|
|
|
}
|
2006-12-18 06:03:54 +01:00
|
|
|
|
|
|
|
/* Update the sprite now. Next event may be from different device. */
|
2007-09-28 11:16:41 +02:00
|
|
|
if (e->events->event[0].u.u.type == DeviceMotionNotify
|
|
|
|
&& e->pDev->coreEvents)
|
2006-11-17 08:33:43 +01:00
|
|
|
{
|
|
|
|
miPointerUpdateSprite(e->pDev);
|
|
|
|
}
|
2003-11-14 16:54:54 +01:00
|
|
|
}
|
|
|
|
}
|