/* Copyright 2006 by Peter Hutterer */ #ifdef HAVE_DIX_CONFIG_H #include #endif #include #include #include "inputstr.h" #include "extnsionst.h" /* extension entry */ #include #include #include #include "mpxglobals.h" #include "mpxextinit.h" #include "swaprep.h" #include "getvers.h" #include "listdev.h" #include "selectev.h" #include "getevbase.h" #include "queryptr.h" static Mask lastExtEventMask = 1; int MPXEventIndex; MPXExtEventInfo EventInfo[32]; /** * MPX piggybacks on the X Input extension's event system. Each window has an * array of event masks, from 0 to MAX_DEVICES. In XI, each device can have * separate event masks. Before an event is delivered, the array at the index * of the device is checked. * * Two things: * -) core devices do not send input extension events * -) MPX events are not device specific. * * Since the mask of the core pointer (index 1) is thus not used by XI, MPX * can use it for the event mask. This also makes MPX less intrusive. */ int MPXmskidx = 1; /***************************************************************** * * Externs defined elsewhere in the X server. * */ extern MPXExtensionVersion AllExtensionVersions[]; Mask PropagateMask[MAX_DEVICES]; /***************************************************************** * * Globals referenced elsewhere in the server. * */ int MPXReqCode = 0; int MPXEventBase = 0; int MPXErrorBase = 0; int MPXButtonPress; int MPXButtonRelease; int MPXMotionNotify; int MPXLastEvent; /***************************************************************** * * Declarations of local routines. * */ static MPXExtensionVersion thisversion = { MPX_Major, MPX_Minor }; /********************************************************************** * * MPXExtensionInit - initialize the input extension. * * Called from InitExtensions in main() or from QueryExtension() if the * extension is dynamically loaded. * * This extension has several events and errors. * */ void MPXExtensionInit(void) { ExtensionEntry *extEntry; extEntry = AddExtension(MPXNAME, MPXEVENTS, MPXERRORS, ProcMPXDispatch, SProcMPXDispatch, MPXResetProc, StandardMinorOpcode); if (extEntry) { MPXReqCode = extEntry->base; MPXEventBase = extEntry->eventBase; MPXErrorBase = extEntry->errorBase; AllExtensionVersions[MPXReqCode - 128] = thisversion; MPXFixExtensionEvents(extEntry); ReplySwapVector[MPXReqCode] = (ReplySwapPtr) SReplyMPXDispatch; EventSwapVector[MPXButtonPress] = SEventMPXDispatch; EventSwapVector[MPXButtonRelease] = SEventMPXDispatch; EventSwapVector[MPXMotionNotify] = SEventMPXDispatch; } else { FatalError("MPXExtensionInit: AddExtensions failed\n"); } } /************************************************************************* * * ProcMPXDispatch - main dispatch routine for requests to this extension. * This routine is used if server and client have the same byte ordering. * */ int ProcMPXDispatch(register ClientPtr client) { REQUEST(xReq); if (stuff->data == X_MPXGetExtensionVersion) return (ProcMPXGetExtensionVersion(client)); if (stuff->data == X_MPXListDevices) return (ProcMPXListDevices(client)); if (stuff->data == X_MPXSelectEvents) return (ProcMPXSelectEvents(client)); if (stuff->data == X_MPXGetEventBase) return (ProcMPXGetEventBase(client)); if (stuff->data == X_MPXQueryPointer) return (ProcMPXQueryPointer(client)); else { SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest); } return (BadRequest); } /******************************************************************************* * * SProcMPXDispatch * * Main swapped dispatch routine for requests to this extension. * This routine is used if server and client do not have the same byte ordering. * */ int SProcMPXDispatch(register ClientPtr client) { REQUEST(xReq); if (stuff->data == X_MPXGetExtensionVersion) return (SProcMPXGetExtensionVersion(client)); if (stuff->data == X_MPXListDevices) return (SProcMPXListDevices(client)); if (stuff->data == X_MPXSelectEvents) return (SProcMPXSelectEvents(client)); if (stuff->data == X_MPXGetEventBase) return (SProcMPXGetEventBase(client)); if (stuff->data == X_MPXQueryPointer) return (SProcMPXQueryPointer(client)); else { SendErrorToClient(client, MPXReqCode, stuff->data, 0, BadRequest); } return (BadRequest); } /*********************************************************************** * * MPXResetProc. * Remove reply-swapping routine. * Remove event-swapping routine. * */ void MPXResetProc(ExtensionEntry* unused) { ReplySwapVector[MPXReqCode] = ReplyNotSwappd; EventSwapVector[MPXButtonPress] = NotImplemented; EventSwapVector[MPXButtonRelease] = NotImplemented; EventSwapVector[MPXMotionNotify] = NotImplemented; MPXRestoreExtensionEvents(); } void SReplyMPXDispatch(ClientPtr client, int len, xMPXGetExtensionVersionReply* rep) { if (rep->RepType == X_MPXGetExtensionVersion) SRepMPXGetExtensionVersion(client, len, (xMPXGetExtensionVersionReply*) rep); if (rep->RepType == X_MPXListDevices) SRepMPXListDevices(client, len, (xMPXListDevicesReply*) rep); else { FatalError("MPX confused sending swapped reply"); } } void SEventMPXDispatch(xEvent* from, xEvent* to) { int type = from->u.u.type & 0177; if (type == MPXButtonPress) { SKeyButtonPtrEvent(from, to); to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; } else if (type == MPXButtonRelease) { SKeyButtonPtrEvent(from, to); to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; } else if (type == MPXMotionNotify) { SKeyButtonPtrEvent(from, to); to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1; } else { FatalError("XInputExtension: Impossible event!\n"); } } void MPXFixExtensionEvents(ExtensionEntry* extEntry) { MPXButtonPress = extEntry->eventBase; MPXButtonRelease = MPXButtonPress + 1; MPXMotionNotify = MPXButtonRelease + 1; MPXLastEvent = MPXMotionNotify + 1; MPXSetMaskForExtEvent(MPXButtonPressMask, MPXButtonPress); MPXSetMaskForExtEvent(MPXButtonReleaseMask, MPXButtonRelease); MPXSetMaskForExtEvent(MPXPointerMotionMask, MPXMotionNotify); } /************************************************************************** * * Assign the specified mask to the specified event. * */ void MPXSetMaskForExtEvent(Mask mask, int event) { EventInfo[MPXEventIndex].mask = mask; EventInfo[MPXEventIndex++].type = event; if ((event < LASTEvent) || (event >= 128)) FatalError("MaskForExtensionEvent: bogus event number"); SetMaskForEvent(mask, event); } /************************************************************************ * * This function restores extension event types and masks to their * initial state. * */ void MPXRestoreExtensionEvents(void) { int i; MPXReqCode = 0; for (i = 0; i < MPXEventIndex - 1; i++) { if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128)) SetMaskForEvent(0, EventInfo[i].type); EventInfo[i].mask = 0; EventInfo[i].type = 0; } MPXEventIndex = 0; lastExtEventMask = 1; MPXButtonPress = 0; MPXButtonRelease = 1; MPXMotionNotify = 2; } /************************************************************************** * * Allow the specified event to have its propagation suppressed. * The default is to not allow suppression of propagation. * */ void MPXAllowPropagateSuppress(Mask mask) { int i; for (i = 0; i < MAX_DEVICES; i++) PropagateMask[i] |= mask; }