700 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			700 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
/************************************************************
 | 
						|
 | 
						|
Copyright 2003-2005 Sun Microsystems, Inc.
 | 
						|
 | 
						|
All rights reserved.
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a
 | 
						|
copy of this software and associated documentation files (the
 | 
						|
"Software"), to deal in the Software without restriction, including
 | 
						|
without limitation the rights to use, copy, modify, merge, publish,
 | 
						|
distribute, and/or sell copies of the Software, and to permit persons
 | 
						|
to whom the Software is furnished to do so, provided that the above
 | 
						|
copyright notice(s) and this permission notice appear in all copies of
 | 
						|
the Software and that both the above copyright notice(s) and this
 | 
						|
permission notice appear in supporting documentation.
 | 
						|
 | 
						|
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
 | 
						|
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 | 
						|
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
 | 
						|
INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
 | 
						|
FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 | 
						|
NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 | 
						|
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the name of a copyright holder
 | 
						|
shall not be used in advertising or otherwise to promote the sale, use
 | 
						|
or other dealings in this Software without prior written authorization
 | 
						|
of the copyright holder.
 | 
						|
 | 
						|
************************************************************/
 | 
						|
 | 
						|
#define NEED_REPLIES
 | 
						|
#define NEED_EVENTS
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include "misc.h"
 | 
						|
#include "dixstruct.h"
 | 
						|
#include "extnsionst.h"
 | 
						|
#include "colormapst.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "servermd.h"
 | 
						|
#define  _XEVIE_SERVER_
 | 
						|
#include <X11/extensions/Xeviestr.h>
 | 
						|
#include <X11/Xfuncproto.h>
 | 
						|
#include "input.h"
 | 
						|
#include "inputstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "cursorstr.h"
 | 
						|
#include <xkbsrv.h>
 | 
						|
 | 
						|
#include "../os/osdep.h"
 | 
						|
 | 
						|
#define NoSuchEvent 0x80000000
 | 
						|
 | 
						|
#ifdef XKB
 | 
						|
extern Bool noXkbExtension;
 | 
						|
#endif
 | 
						|
extern int    xeviegrabState;
 | 
						|
 | 
						|
static int		ProcDispatch (register ClientPtr client), SProcDispatch (register ClientPtr client);
 | 
						|
static void		ResetProc (ExtensionEntry *extEntry);
 | 
						|
 | 
						|
static unsigned char	ReqCode = 0;
 | 
						|
static int		ErrorBase;
 | 
						|
 | 
						|
int			xevieFlag = 0;
 | 
						|
int	 		xevieClientIndex = 0;
 | 
						|
DeviceIntPtr		xeviekb = NULL;
 | 
						|
DeviceIntPtr		xeviemouse = NULL;
 | 
						|
Mask			xevieMask = 0;
 | 
						|
int       		xevieEventSent = 0;
 | 
						|
int			xevieKBEventSent = 0;
 | 
						|
static DevPrivateKey    xevieDevicePrivateKey = &xevieDevicePrivateKey;
 | 
						|
static Bool                     xevieModifiersOn = FALSE;
 | 
						|
 | 
						|
#define XEVIEINFO(dev)  ((xevieDeviceInfoPtr) \
 | 
						|
    dixLookupPrivate(&(dev)->devPrivates, xevieDevicePrivateKey))
 | 
						|
 | 
						|
Mask xevieFilters[128] = 
 | 
						|
{
 | 
						|
        NoSuchEvent,                   /* 0 */
 | 
						|
        NoSuchEvent,                   /* 1 */
 | 
						|
        KeyPressMask,                  /* KeyPress */
 | 
						|
        KeyReleaseMask,                /* KeyRelease */
 | 
						|
        ButtonPressMask,               /* ButtonPress */
 | 
						|
        ButtonReleaseMask,             /* ButtonRelease */
 | 
						|
        PointerMotionMask              /* MotionNotify (initial state) */
 | 
						|
};
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    ProcessInputProc processInputProc;
 | 
						|
    ProcessInputProc realInputProc;
 | 
						|
    DeviceUnwrapProc unwrapProc;
 | 
						|
} xevieDeviceInfoRec, *xevieDeviceInfoPtr;
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    CARD32 time;
 | 
						|
    KeyClassPtr keyc;
 | 
						|
} xevieKeycQueueRec, *xevieKeycQueuePtr;
 | 
						|
 | 
						|
#define KEYC_QUEUE_SIZE	    100
 | 
						|
static xevieKeycQueueRec keycq[KEYC_QUEUE_SIZE] = {{0, NULL}};
 | 
						|
static int keycqHead = 0, keycqTail = 0;
 | 
						|
 | 
						|
static int              ProcDispatch (ClientPtr), SProcDispatch (ClientPtr);
 | 
						|
static void             ResetProc (ExtensionEntry*);
 | 
						|
 | 
						|
static int              ErrorBase;
 | 
						|
 | 
						|
static Bool XevieStart(void);
 | 
						|
static void XevieEnd(int clientIndex);
 | 
						|
static void XevieClientStateCallback(CallbackListPtr *pcbl, pointer nulldata,
 | 
						|
                                    pointer calldata);
 | 
						|
static void XevieServerGrabStateCallback(CallbackListPtr *pcbl,
 | 
						|
                                         pointer nulldata,
 | 
						|
                                         pointer calldata);
 | 
						|
 | 
						|
static Bool XevieAdd(DeviceIntPtr device, pointer data);
 | 
						|
static void XevieWrap(DeviceIntPtr device, ProcessInputProc proc);
 | 
						|
static Bool XevieRemove(DeviceIntPtr device, pointer data);
 | 
						|
static void doSendEvent(xEvent *xE, DeviceIntPtr device);
 | 
						|
static void XeviePointerProcessInputProc(xEvent *xE, DeviceIntPtr dev,
 | 
						|
                                         int count);
 | 
						|
static void XevieKbdProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count);
 | 
						|
 | 
						|
void
 | 
						|
XevieExtensionInit (void)
 | 
						|
{
 | 
						|
    ExtensionEntry* extEntry;
 | 
						|
 | 
						|
    if (!AddCallback(&ServerGrabCallback,XevieServerGrabStateCallback,NULL))
 | 
						|
       return;
 | 
						|
 | 
						|
    if ((extEntry = AddExtension (XEVIENAME,
 | 
						|
				0,
 | 
						|
				XevieNumberErrors,
 | 
						|
				ProcDispatch,
 | 
						|
				SProcDispatch,
 | 
						|
				ResetProc,
 | 
						|
				StandardMinorOpcode))) {
 | 
						|
	ReqCode = (unsigned char)extEntry->base;
 | 
						|
	ErrorBase = extEntry->errorBase;
 | 
						|
    }
 | 
						|
 | 
						|
    /* PC servers initialize the desktop colors (citems) here! */
 | 
						|
}
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
static 
 | 
						|
void ResetProc (ExtensionEntry *extEntry)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
static 
 | 
						|
int ProcQueryVersion (register ClientPtr client)
 | 
						|
{
 | 
						|
    xXevieQueryVersionReply rep;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH (xXevieQueryVersionReq);
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.length = 0;
 | 
						|
    rep.sequence_number = client->sequence;
 | 
						|
    rep.server_major_version = XEVIE_MAJOR_VERSION;
 | 
						|
    rep.server_minor_version = XEVIE_MINOR_VERSION;
 | 
						|
    WriteToClient (client, sizeof (xXevieQueryVersionReply), (char *)&rep);
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int ProcStart (register ClientPtr client)
 | 
						|
{
 | 
						|
    xXevieStartReply rep;
 | 
						|
 | 
						|
    REQUEST_SIZE_MATCH (xXevieStartReq);
 | 
						|
    rep.pad1 = 0;
 | 
						|
 | 
						|
    if(!xevieFlag){
 | 
						|
        if (AddCallback(&ClientStateCallback,XevieClientStateCallback,NULL)) {
 | 
						|
           xevieFlag = 1;
 | 
						|
           rep.pad1 = 1;
 | 
						|
           xevieClientIndex = client->index;
 | 
						|
	   if(!keycq[0].time ) {
 | 
						|
		int i;
 | 
						|
		for(i=0; i<KEYC_QUEUE_SIZE; i++) {
 | 
						|
		    keycq[i].keyc = xalloc(sizeof(KeyClassRec));	
 | 
						|
		    keycq[i].keyc->xkbInfo = xalloc(sizeof(XkbSrvInfoRec));
 | 
						|
		}
 | 
						|
	   }
 | 
						|
        } else
 | 
						|
           return BadAlloc;
 | 
						|
    } else
 | 
						|
        return BadAccess;
 | 
						|
#ifdef XKB
 | 
						|
    if (!noXkbExtension) {
 | 
						|
	if (!XevieStart()) {
 | 
						|
            DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL);
 | 
						|
            return BadAlloc;
 | 
						|
        }
 | 
						|
    }
 | 
						|
#endif
 | 
						|
    
 | 
						|
    xevieModifiersOn = FALSE;
 | 
						|
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.sequence_number = client->sequence;
 | 
						|
    WriteToClient (client, sizeof (xXevieStartReply), (char *)&rep);
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int ProcEnd (register ClientPtr client)
 | 
						|
{
 | 
						|
    xXevieEndReply rep;
 | 
						|
 | 
						|
    if (xevieFlag) {
 | 
						|
        if (client->index != xevieClientIndex)
 | 
						|
            return BadAccess;
 | 
						|
 | 
						|
        DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL);
 | 
						|
        XevieEnd(xevieClientIndex);
 | 
						|
    }
 | 
						|
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.sequence_number = client->sequence;
 | 
						|
    WriteToClient (client, sizeof (xXevieEndReply), (char *)&rep);
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int ProcSend (register ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST (xXevieSendReq);
 | 
						|
    xXevieSendReply rep;
 | 
						|
    xEvent *xE;
 | 
						|
    static unsigned char lastDetail = 0, lastType = 0;
 | 
						|
 | 
						|
    if (client->index != xevieClientIndex)
 | 
						|
        return BadAccess;
 | 
						|
 | 
						|
    xE = (xEvent *)&stuff->event;
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.sequence_number = client->sequence;
 | 
						|
    WriteToClient (client, sizeof (xXevieSendReply), (char *)&rep);
 | 
						|
 | 
						|
    switch(xE->u.u.type) {
 | 
						|
	case KeyPress:
 | 
						|
        case KeyRelease:
 | 
						|
	  xevieKBEventSent = 1;
 | 
						|
#ifdef XKB
 | 
						|
          if(!noXkbExtension)
 | 
						|
	    doSendEvent(xE, inputInfo.keyboard);
 | 
						|
	  else 
 | 
						|
#endif
 | 
						|
            CoreProcessKeyboardEvent (xE, xeviekb, 1);
 | 
						|
	  break;
 | 
						|
	case ButtonPress:
 | 
						|
	case ButtonRelease:
 | 
						|
	case MotionNotify:
 | 
						|
	  xevieEventSent = 1;
 | 
						|
#ifdef XKB
 | 
						|
	  if(!noXkbExtension)
 | 
						|
	    doSendEvent(xE, inputInfo.pointer);
 | 
						|
	  else
 | 
						|
#endif
 | 
						|
	    CoreProcessPointerEvent(xE, xeviemouse, 1); 
 | 
						|
	  break; 
 | 
						|
	default:
 | 
						|
	  break;
 | 
						|
    }
 | 
						|
    lastType = xE->u.u.type;
 | 
						|
    lastDetail = xE->u.u.detail;
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int ProcSelectInput (register ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST (xXevieSelectInputReq);
 | 
						|
    xXevieSelectInputReply rep;
 | 
						|
 | 
						|
    if (client->index != xevieClientIndex)
 | 
						|
        return BadAccess;
 | 
						|
 | 
						|
    xevieMask = (long)stuff->event_mask;
 | 
						|
    rep.type = X_Reply;
 | 
						|
    rep.sequence_number = client->sequence;
 | 
						|
    WriteToClient (client, sizeof (xXevieSelectInputReply), (char *)&rep);
 | 
						|
    return client->noClientException;
 | 
						|
}
 | 
						|
 | 
						|
static 
 | 
						|
int ProcDispatch (register ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST (xReq);
 | 
						|
    switch (stuff->data)
 | 
						|
    {
 | 
						|
    case X_XevieQueryVersion:
 | 
						|
	return ProcQueryVersion (client);
 | 
						|
    case X_XevieStart:
 | 
						|
	return ProcStart (client);
 | 
						|
    case X_XevieEnd:
 | 
						|
	return ProcEnd (client);
 | 
						|
    case X_XevieSend:
 | 
						|
	return ProcSend (client);
 | 
						|
    case X_XevieSelectInput:
 | 
						|
	return ProcSelectInput(client);
 | 
						|
    default:
 | 
						|
	return BadRequest;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static 
 | 
						|
int SProcQueryVersion (register ClientPtr client)
 | 
						|
{
 | 
						|
    register int n;
 | 
						|
 | 
						|
    REQUEST(xXevieQueryVersionReq);
 | 
						|
    swaps(&stuff->length, n);
 | 
						|
    return ProcQueryVersion(client);
 | 
						|
}
 | 
						|
 | 
						|
static 
 | 
						|
int SProcStart (ClientPtr client)
 | 
						|
{
 | 
						|
    register int n;
 | 
						|
 | 
						|
    REQUEST (xXevieStartReq);
 | 
						|
    swaps (&stuff->length, n);
 | 
						|
    swapl (&stuff->screen, n);
 | 
						|
    REQUEST_AT_LEAST_SIZE (xXevieStartReq);
 | 
						|
    return ProcStart (client);
 | 
						|
}
 | 
						|
 | 
						|
static 
 | 
						|
int SProcEnd (ClientPtr client)
 | 
						|
{
 | 
						|
    register int n;
 | 
						|
 | 
						|
    REQUEST (xXevieEndReq);
 | 
						|
    swaps (&stuff->length, n);
 | 
						|
    REQUEST_AT_LEAST_SIZE (xXevieEndReq);
 | 
						|
    swapl(&stuff->cmap, n);
 | 
						|
    return ProcEnd (client);
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int SProcSend (ClientPtr client)
 | 
						|
{
 | 
						|
    register int n;
 | 
						|
 | 
						|
    REQUEST (xXevieSendReq);
 | 
						|
    swaps (&stuff->length, n);
 | 
						|
    REQUEST_AT_LEAST_SIZE (xXevieSendReq);
 | 
						|
    swapl(&stuff->event, n);
 | 
						|
    return ProcSend (client);
 | 
						|
}
 | 
						|
 | 
						|
static
 | 
						|
int SProcSelectInput (ClientPtr client)
 | 
						|
{
 | 
						|
    register int n;
 | 
						|
 | 
						|
    REQUEST (xXevieSelectInputReq);
 | 
						|
    swaps (&stuff->length, n);
 | 
						|
    REQUEST_AT_LEAST_SIZE (xXevieSelectInputReq);
 | 
						|
    swapl(&stuff->event_mask, n);
 | 
						|
    return ProcSelectInput (client);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static 
 | 
						|
int SProcDispatch (register ClientPtr client)
 | 
						|
{
 | 
						|
    REQUEST(xReq);
 | 
						|
    switch (stuff->data)
 | 
						|
    {
 | 
						|
    case X_XevieQueryVersion:
 | 
						|
	return SProcQueryVersion (client);
 | 
						|
    case X_XevieStart:
 | 
						|
	return SProcStart (client);
 | 
						|
    case X_XevieEnd:
 | 
						|
	return SProcEnd (client);
 | 
						|
    case X_XevieSend:
 | 
						|
	return SProcSend (client);
 | 
						|
    case X_XevieSelectInput:
 | 
						|
	return SProcSelectInput(client);
 | 
						|
    default:
 | 
						|
	return BadRequest;
 | 
						|
    }
 | 
						|
}
 | 
						|
/*======================================================*/
 | 
						|
 | 
						|
#define WRAP_INPUTPROC(dev,store,inputProc) \
 | 
						|
   store->processInputProc = dev->public.processInputProc; \
 | 
						|
   dev->public.processInputProc = inputProc; \
 | 
						|
   store->realInputProc = dev->public.realInputProc; \
 | 
						|
   dev->public.realInputProc = inputProc;
 | 
						|
 | 
						|
#define COND_WRAP_INPUTPROC(dev,store,inputProc) \
 | 
						|
   if (dev->public.processInputProc == dev->public.realInputProc) \
 | 
						|
          dev->public.processInputProc = inputProc; \
 | 
						|
   store->processInputProc =  \
 | 
						|
   store->realInputProc = dev->public.realInputProc; \
 | 
						|
   dev->public.realInputProc = inputProc;
 | 
						|
 | 
						|
#define UNWRAP_INPUTPROC(dev,restore) \
 | 
						|
   dev->public.processInputProc = restore->processInputProc; \
 | 
						|
   dev->public.realInputProc = restore->realInputProc;
 | 
						|
 | 
						|
#define UNWRAP_INPUTPROC(dev,restore) \
 | 
						|
   dev->public.processInputProc = restore->processInputProc; \
 | 
						|
   dev->public.realInputProc = restore->realInputProc;
 | 
						|
 | 
						|
#define XEVIE_EVENT(xE) \
 | 
						|
      (xevieFlag \
 | 
						|
       && !xeviegrabState \
 | 
						|
       && clients[xevieClientIndex] \
 | 
						|
       && (xevieMask & xevieFilters[xE->u.u.type]))
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
sendEvent(ClientPtr pClient, xEvent *xE)
 | 
						|
{
 | 
						|
    if(pClient->swapped) {
 | 
						|
        xEvent    eventTo;
 | 
						|
 | 
						|
        /* Remember to strip off the leading bit of type in case
 | 
						|
           this event was sent with "SendEvent." */
 | 
						|
        (*EventSwapVector[xE->u.u.type & 0177]) (xE, &eventTo);
 | 
						|
        (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
 | 
						|
    } else {
 | 
						|
        (void)WriteToClient(pClient, sizeof(xEvent), (char *) xE);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XevieKbdProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count)
 | 
						|
{
 | 
						|
    int             key, bit;
 | 
						|
    BYTE   *kptr;
 | 
						|
    ProcessInputProc tmp;
 | 
						|
    KeyClassPtr keyc = dev->key;
 | 
						|
    xevieDeviceInfoPtr xeviep = XEVIEINFO(dev);
 | 
						|
 | 
						|
    if(XEVIE_EVENT(xE)) {
 | 
						|
        key = xE->u.u.detail;
 | 
						|
        kptr = &keyc->down[key >> 3];
 | 
						|
        bit = 1 << (key & 7);
 | 
						|
 | 
						|
	if (dev->key->modifierMap[xE->u.u.detail])
 | 
						|
            xevieModifiersOn = TRUE;
 | 
						|
 | 
						|
        xE->u.keyButtonPointer.event = xeviewin->drawable.id;
 | 
						|
        xE->u.keyButtonPointer.root = GetCurrentRootWindow()->drawable.id;
 | 
						|
        xE->u.keyButtonPointer.child = (xeviewin->firstChild)
 | 
						|
            ? xeviewin->firstChild->drawable.id:0;
 | 
						|
        xE->u.keyButtonPointer.rootX = xeviehot.x;
 | 
						|
        xE->u.keyButtonPointer.rootY = xeviehot.y;
 | 
						|
        xE->u.keyButtonPointer.state = keyc->state | inputInfo.pointer->button->state;
 | 
						|
        /* fix bug: sequence lost in Xlib */
 | 
						|
        xE->u.u.sequenceNumber = clients[xevieClientIndex]->sequence;
 | 
						|
#ifdef XKB
 | 
						|
	/* fix for bug5092586 */
 | 
						|
	if(!noXkbExtension) {
 | 
						|
          switch(xE->u.u.type) {
 | 
						|
	    case KeyPress: *kptr |= bit; break;
 | 
						|
	    case KeyRelease: *kptr &= ~bit; break;
 | 
						|
	  }
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	keycq[keycqHead].time = xE->u.keyButtonPointer.time;
 | 
						|
	memcpy(keycq[keycqHead].keyc, keyc, sizeof(KeyClassRec) - sizeof(KeyClassPtr));
 | 
						|
	memcpy(keycq[keycqHead].keyc->xkbInfo, keyc->xkbInfo, sizeof(XkbSrvInfoRec));
 | 
						|
	if(++keycqHead >=KEYC_QUEUE_SIZE)
 | 
						|
	    keycqHead = 0;
 | 
						|
        sendEvent(clients[xevieClientIndex], xE);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    tmp = dev->public.realInputProc;
 | 
						|
    UNWRAP_INPUTPROC(dev,xeviep);
 | 
						|
    dev->public.processInputProc(xE,dev,count);
 | 
						|
    COND_WRAP_INPUTPROC(dev,xeviep,tmp);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XeviePointerProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count)
 | 
						|
{
 | 
						|
    xevieDeviceInfoPtr xeviep = XEVIEINFO(dev);
 | 
						|
    ProcessInputProc tmp;
 | 
						|
 | 
						|
    if (XEVIE_EVENT(xE)) {
 | 
						|
        /* fix bug: sequence lost in Xlib */
 | 
						|
        xE->u.u.sequenceNumber = clients[xevieClientIndex]->sequence;
 | 
						|
        sendEvent(clients[xevieClientIndex], xE);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    tmp = dev->public.realInputProc;
 | 
						|
    UNWRAP_INPUTPROC(dev,xeviep);
 | 
						|
    dev->public.processInputProc(xE,dev,count);
 | 
						|
    COND_WRAP_INPUTPROC(dev,xeviep,tmp);
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
XevieStart(void)
 | 
						|
{
 | 
						|
    ProcessInputProc prp;
 | 
						|
    prp = XevieKbdProcessInputProc;
 | 
						|
    if (!XevieAdd(inputInfo.keyboard,&prp))
 | 
						|
        return FALSE;
 | 
						|
    prp = XeviePointerProcessInputProc;
 | 
						|
    if (!XevieAdd(inputInfo.pointer,&prp))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void
 | 
						|
XevieEnd(int clientIndex)
 | 
						|
{
 | 
						|
    if (!clientIndex || clientIndex == xevieClientIndex) {
 | 
						|
 | 
						|
#ifdef XKB
 | 
						|
       if(!noXkbExtension) {
 | 
						|
 | 
						|
	   XevieRemove(inputInfo.keyboard,NULL);
 | 
						|
 | 
						|
	   inputInfo.keyboard->public.processInputProc = CoreProcessKeyboardEvent;
 | 
						|
           inputInfo.keyboard->public.realInputProc = CoreProcessKeyboardEvent;
 | 
						|
           XkbSetExtension(inputInfo.keyboard,ProcessKeyboardEvent);
 | 
						|
 | 
						|
 | 
						|
           XevieRemove(inputInfo.pointer,NULL);
 | 
						|
 | 
						|
	   inputInfo.pointer->public.processInputProc = CoreProcessPointerEvent;
 | 
						|
           inputInfo.pointer->public.realInputProc = CoreProcessPointerEvent;
 | 
						|
           XkbSetExtension(inputInfo.pointer,ProcessPointerEvent);
 | 
						|
       }
 | 
						|
#endif
 | 
						|
 | 
						|
       xevieFlag = 0;
 | 
						|
       xevieClientIndex = 0;
 | 
						|
       DeleteCallback (&ClientStateCallback, XevieClientStateCallback, NULL);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XevieClientStateCallback(CallbackListPtr *pcbl, pointer nulldata,
 | 
						|
                        pointer calldata)
 | 
						|
{
 | 
						|
    NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
 | 
						|
    ClientPtr client = pci->client;
 | 
						|
    if (client->clientState == ClientStateGone
 | 
						|
       || client->clientState == ClientStateRetained)
 | 
						|
       XevieEnd(client->index);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XevieServerGrabStateCallback(CallbackListPtr *pcbl, pointer nulldata,
 | 
						|
                            pointer calldata)
 | 
						|
{
 | 
						|
    ServerGrabInfoRec *grbinfo = (ServerGrabInfoRec *)calldata;
 | 
						|
    if (grbinfo->grabstate == SERVER_GRABBED)
 | 
						|
       xeviegrabState = TRUE;
 | 
						|
    else
 | 
						|
       xeviegrabState = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
#define UNWRAP_UNWRAPPROC(device,proc_store) \
 | 
						|
    device->unwrapProc = proc_store;
 | 
						|
 | 
						|
#define WRAP_UNWRAPPROC(device,proc_store,proc) \
 | 
						|
    proc_store = device->unwrapProc; \
 | 
						|
    device->unwrapProc = proc;
 | 
						|
 | 
						|
static void
 | 
						|
xevieUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, pointer data)
 | 
						|
{
 | 
						|
    xevieDeviceInfoPtr xeviep = XEVIEINFO(device);
 | 
						|
    ProcessInputProc tmp = device->public.processInputProc;
 | 
						|
 | 
						|
    UNWRAP_INPUTPROC(device,xeviep);
 | 
						|
    UNWRAP_UNWRAPPROC(device,xeviep->unwrapProc);
 | 
						|
    proc(device,data);
 | 
						|
    WRAP_INPUTPROC(device,xeviep,tmp);
 | 
						|
    WRAP_UNWRAPPROC(device,xeviep->unwrapProc,xevieUnwrapProc);
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
XevieUnwrapAdd(DeviceIntPtr device, void* data)
 | 
						|
{
 | 
						|
    if (device->unwrapProc)
 | 
						|
        device->unwrapProc(device,XevieUnwrapAdd,data);
 | 
						|
    else {
 | 
						|
        ProcessInputProc *ptr = data;
 | 
						|
        XevieWrap(device,*ptr);
 | 
						|
    }
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
XevieAdd(DeviceIntPtr device, void* data)
 | 
						|
{
 | 
						|
    xevieDeviceInfoPtr xeviep;
 | 
						|
 | 
						|
    xeviep = xalloc (sizeof (xevieDeviceInfoRec));
 | 
						|
    if (!xeviep)
 | 
						|
            return FALSE;
 | 
						|
 | 
						|
    dixSetPrivate(&device->devPrivates, xevieDevicePrivateKey, xeviep);
 | 
						|
    XevieUnwrapAdd(device, data);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
XevieRemove(DeviceIntPtr device,pointer data)
 | 
						|
{
 | 
						|
    xevieDeviceInfoPtr xeviep = XEVIEINFO(device);
 | 
						|
 | 
						|
    if (!xeviep) return TRUE;
 | 
						|
 | 
						|
    UNWRAP_INPUTPROC(device,xeviep);
 | 
						|
    UNWRAP_UNWRAPPROC(device,xeviep->unwrapProc);
 | 
						|
 | 
						|
    xfree(xeviep);
 | 
						|
    dixSetPrivate(&device->devPrivates, xevieDevicePrivateKey, NULL);
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
XevieWrap(DeviceIntPtr device, ProcessInputProc proc)
 | 
						|
{
 | 
						|
    xevieDeviceInfoPtr xeviep = XEVIEINFO(device);
 | 
						|
 | 
						|
    WRAP_INPUTPROC(device,xeviep,proc);
 | 
						|
    WRAP_UNWRAPPROC(device,xeviep->unwrapProc,xevieUnwrapProc);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
doSendEvent(xEvent *xE, DeviceIntPtr dev)
 | 
						|
{
 | 
						|
    xevieDeviceInfoPtr xeviep = XEVIEINFO(dev);
 | 
						|
    ProcessInputProc tmp = dev->public.realInputProc;
 | 
						|
    if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))
 | 
						|
        && !xevieModifiersOn) {
 | 
						|
	KeyClassPtr keyc =  dev->key;
 | 
						|
        CARD8 realModes = dev->key->modifierMap[xE->u.u.detail];
 | 
						|
	int notFound = 0;
 | 
						|
	/* if some events are consumed by client, move the queue tail pointer to the current 
 | 
						|
           event which just comes back from Xevie client . 
 | 
						|
	*/
 | 
						|
        if(keycq[keycqTail].time != xE->u.keyButtonPointer.time) {
 | 
						|
	    while(keycq[keycqTail].time != xE->u.keyButtonPointer.time) {
 | 
						|
		if(++keycqTail >= KEYC_QUEUE_SIZE)
 | 
						|
		    keycqTail = 0;
 | 
						|
		if(keycqTail == keycqHead) {
 | 
						|
		    notFound = 1;
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	if(!notFound) {
 | 
						|
	    dev->key = keycq[keycqTail].keyc;
 | 
						|
	    if(++keycqTail >= KEYC_QUEUE_SIZE)
 | 
						|
	        keycqTail = 0;
 | 
						|
	}
 | 
						|
        dev->key->modifierMap[xE->u.u.detail] = 0;  
 | 
						|
 | 
						|
	if(dev->key->xkbInfo->repeatKey != 0 && xE->u.u.type != KeyPress)
 | 
						|
            XkbLastRepeatEvent=     (pointer)xE;
 | 
						|
        UNWRAP_INPUTPROC(dev,xeviep);
 | 
						|
        dev->public.processInputProc(xE,dev,1);
 | 
						|
        COND_WRAP_INPUTPROC(dev,xeviep,tmp);
 | 
						|
        XkbLastRepeatEvent= NULL;
 | 
						|
 | 
						|
        dev->key->modifierMap[xE->u.u.detail] = realModes;
 | 
						|
	dev->key = keyc;
 | 
						|
	if(notFound) {
 | 
						|
	    DeleteCallback(&ClientStateCallback,XevieClientStateCallback,NULL);
 | 
						|
            XevieEnd(xevieClientIndex);
 | 
						|
	    ErrorF("Error: Xevie keyc queue size is not enough, disable Xevie\n");
 | 
						|
	}	
 | 
						|
    } else {
 | 
						|
        UNWRAP_INPUTPROC(dev,xeviep);
 | 
						|
        dev->public.processInputProc(xE,dev,1);
 | 
						|
        COND_WRAP_INPUTPROC(dev,xeviep,tmp);
 | 
						|
    }
 | 
						|
}
 | 
						|
 |