955 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			955 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
/* $XdotOrg: xc/programs/Xserver/Xext/xtest1di.c,v 1.3 2005/04/20 12:25:12 daniels Exp $ */
 | 
						|
/* $Xorg: xtest1di.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
 | 
						|
/*
 | 
						|
 *	File:  xtest1di.c
 | 
						|
 *
 | 
						|
 *	This file contains the device independent parts of the input
 | 
						|
 *	synthesis extension.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 | 
						|
 | 
						|
Copyright 1986, 1987, 1988, 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.
 | 
						|
 | 
						|
 | 
						|
Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
 | 
						|
 | 
						|
Permission to use, copy, modify, and distribute this
 | 
						|
software and its documentation for any purpose and without
 | 
						|
fee is hereby granted, provided that the above copyright
 | 
						|
notice appear in all copies and that both that copyright
 | 
						|
notice and this permission notice appear in supporting
 | 
						|
documentation, and that the name of Hewlett-Packard not be used in
 | 
						|
advertising or publicity pertaining to distribution of the
 | 
						|
software without specific, written prior permission.
 | 
						|
 | 
						|
Hewlett-Packard makes no representations about the 
 | 
						|
suitability of this software for any purpose.  It is provided 
 | 
						|
"as is" without express or implied warranty.
 | 
						|
 | 
						|
This software is not subject to any license of the American
 | 
						|
Telephone and Telegraph Company or of the Regents of the
 | 
						|
University of California.
 | 
						|
 | 
						|
*/
 | 
						|
/* $XFree86: xc/programs/Xserver/Xext/xtest1di.c,v 3.5 2003/09/13 21:33:03 dawes Exp $ */
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 * include files
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
#define	 NEED_EVENTS
 | 
						|
#define	 NEED_REPLIES
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include "misc.h"
 | 
						|
#include "os.h"
 | 
						|
#include "gcstruct.h"   
 | 
						|
#include "extnsionst.h"
 | 
						|
#include "dixstruct.h"
 | 
						|
#include "opaque.h"
 | 
						|
#define  XTestSERVER_SIDE
 | 
						|
#include <X11/extensions/xtestext1.h>
 | 
						|
#include "modinit.h"
 | 
						|
 | 
						|
#include "xtest1dd.h"
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 * defines
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 * variables
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
/*
 | 
						|
 * Holds the request type code for this extension.  The request type code
 | 
						|
 * for this extension may vary depending on how many extensions are installed
 | 
						|
 * already, so the initial value given below will be added to the base request
 | 
						|
 * code that is aquired when this extension is installed.
 | 
						|
 */
 | 
						|
static int 		XTestReqCode = 0;
 | 
						|
/*
 | 
						|
 * Holds the two event type codes for this extension.  The event type codes
 | 
						|
 * for this extension may vary depending on how many extensions are installed
 | 
						|
 * already, so the initial values given below will be added to the base event
 | 
						|
 * code that is aquired when this extension is installed.
 | 
						|
 */
 | 
						|
int 			XTestInputActionType = 0;
 | 
						|
int 			XTestFakeAckType = 1;
 | 
						|
/*
 | 
						|
 * true => monitor stealing input
 | 
						|
 */
 | 
						|
int			on_steal_input = FALSE;
 | 
						|
/*
 | 
						|
 * true => monitor alone getting input
 | 
						|
 */
 | 
						|
int			exclusive_steal = FALSE;
 | 
						|
/*
 | 
						|
 * holds the resource type assigned to this extension
 | 
						|
 */
 | 
						|
static RESTYPE		XTestType;
 | 
						|
/*
 | 
						|
 * holds the resource ID for the client currently using XTestGetInput
 | 
						|
 */
 | 
						|
static XID		current_client_id;
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 * function declarations
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
static DISPATCH_PROC(ProcXTestDispatch);
 | 
						|
static DISPATCH_PROC(SProcXTestDispatch);
 | 
						|
static DISPATCH_PROC(ProcTestFakeInput);
 | 
						|
static DISPATCH_PROC(SProcTestFakeInput);
 | 
						|
static DISPATCH_PROC(ProcTestGetInput);
 | 
						|
static DISPATCH_PROC(SProcTestGetInput);
 | 
						|
static DISPATCH_PROC(ProcTestStopInput);
 | 
						|
static DISPATCH_PROC(SProcTestStopInput);
 | 
						|
static DISPATCH_PROC(ProcTestReset);
 | 
						|
static DISPATCH_PROC(SProcTestReset);
 | 
						|
static DISPATCH_PROC(ProcTestQueryInputSize);
 | 
						|
static DISPATCH_PROC(SProcTestQueryInputSize);
 | 
						|
 | 
						|
static void	XTestResetProc(
 | 
						|
	ExtensionEntry *	/* unused */
 | 
						|
	);
 | 
						|
static void	SReplyXTestDispatch(
 | 
						|
	ClientPtr		/* client_ptr */,
 | 
						|
	int			/* size */,
 | 
						|
	char *			/* reply_ptr */
 | 
						|
	);
 | 
						|
static void	SEventXTestDispatch(
 | 
						|
	xEvent *		/* from */,
 | 
						|
	xEvent *		/* to */
 | 
						|
	);
 | 
						|
 | 
						|
static int	XTestCurrentClientGone(
 | 
						|
	pointer			/* value */,
 | 
						|
	XID			/* id */
 | 
						|
	);
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	XTestExtension1Init
 | 
						|
 *
 | 
						|
 *	Called from InitExtensions in main() or from QueryExtension() if the
 | 
						|
 *	extension is dynamically loaded.
 | 
						|
 *
 | 
						|
 *	XTestExtension1Init has no events or errors
 | 
						|
 *	(other than the core errors).
 | 
						|
 */
 | 
						|
void
 | 
						|
XTestExtension1Init(INITARGS)
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * holds the pointer to the extension entry structure
 | 
						|
	 */
 | 
						|
	ExtensionEntry	*extEntry;
 | 
						|
 | 
						|
	extEntry = AddExtension(XTestEXTENSION_NAME,
 | 
						|
				XTestEVENT_COUNT,
 | 
						|
				0,
 | 
						|
				ProcXTestDispatch,
 | 
						|
				SProcXTestDispatch,
 | 
						|
				XTestResetProc,
 | 
						|
				StandardMinorOpcode);
 | 
						|
	if (extEntry)
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * remember the request code assigned to this extension
 | 
						|
		 */
 | 
						|
		XTestReqCode = extEntry->base;
 | 
						|
		/*
 | 
						|
		 * make an atom saying that this extension is present
 | 
						|
		 */
 | 
						|
		(void) MakeAtom(XTestEXTENSION_NAME,
 | 
						|
				strlen(XTestEXTENSION_NAME),
 | 
						|
				TRUE);
 | 
						|
		/*
 | 
						|
		 * remember the event codes assigned to this extension
 | 
						|
		 */
 | 
						|
		XTestInputActionType += extEntry->eventBase;
 | 
						|
		XTestFakeAckType += extEntry->eventBase;
 | 
						|
		/*
 | 
						|
		 * install the routine to handle byte-swapping the replies
 | 
						|
		 * for this extension in the ReplySwapVector table
 | 
						|
		 */
 | 
						|
		ReplySwapVector[XTestReqCode] = (ReplySwapPtr) SReplyXTestDispatch;
 | 
						|
		/*
 | 
						|
		 * install the routine to handle byte-swapping the events
 | 
						|
		 * for this extension in the EventSwapVector table
 | 
						|
		 */
 | 
						|
		EventSwapVector[XTestInputActionType] = SEventXTestDispatch;
 | 
						|
		EventSwapVector[XTestFakeAckType] = SEventXTestDispatch;
 | 
						|
		/*
 | 
						|
		 * get the resource type for this extension
 | 
						|
		 */
 | 
						|
		XTestType = CreateNewResourceType(XTestCurrentClientGone);
 | 
						|
		if (XTestType == 0)
 | 
						|
		{
 | 
						|
			FatalError("XTestExtension1Init: CreateNewResourceType failed\n");
 | 
						|
		}
 | 
						|
	} 
 | 
						|
	else 
 | 
						|
	{
 | 
						|
		FatalError("XTestExtension1Init: AddExtensions failed\n");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	ProcXTestDispatch
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
ProcXTestDispatch(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST(xReq);
 | 
						|
	if (stuff->data == X_TestFakeInput)
 | 
						|
	{
 | 
						|
		return(ProcTestFakeInput(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestGetInput)
 | 
						|
	{
 | 
						|
		return(ProcTestGetInput(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestStopInput)
 | 
						|
	{
 | 
						|
		return(ProcTestStopInput(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestReset)
 | 
						|
	{
 | 
						|
		return(ProcTestReset(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestQueryInputSize)
 | 
						|
	{
 | 
						|
		return(ProcTestQueryInputSize(client));
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		SendErrorToClient(client,
 | 
						|
				  XTestReqCode,
 | 
						|
				  stuff->data,
 | 
						|
				  None,
 | 
						|
				  BadRequest);
 | 
						|
		return(BadRequest);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SProcXTestDispatch
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
SProcXTestDispatch(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST(xReq);
 | 
						|
	if (stuff->data == X_TestFakeInput)
 | 
						|
	{
 | 
						|
		return(SProcTestFakeInput(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestGetInput)
 | 
						|
	{
 | 
						|
		return(SProcTestGetInput(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestStopInput)
 | 
						|
	{
 | 
						|
		return(SProcTestStopInput(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestReset)
 | 
						|
	{
 | 
						|
		return(SProcTestReset(client));
 | 
						|
	}
 | 
						|
	else if (stuff->data == X_TestQueryInputSize)
 | 
						|
	{
 | 
						|
		return(SProcTestQueryInputSize(client));
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		SendErrorToClient(client,
 | 
						|
				  XTestReqCode,
 | 
						|
				  stuff->data,
 | 
						|
				  None,
 | 
						|
				  BadRequest);
 | 
						|
		return(BadRequest);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SProcTestFakeInput
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
SProcTestFakeInput(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
	/*
 | 
						|
	 * index counter
 | 
						|
	 */
 | 
						|
	int		i;
 | 
						|
	/*
 | 
						|
	 * pointer to the next input action in the request
 | 
						|
	 */
 | 
						|
	CARD8		*input_action_ptr;
 | 
						|
	/*
 | 
						|
	 * holds the type of the next input action in the request
 | 
						|
	 */
 | 
						|
	int		input_action_type;
 | 
						|
 | 
						|
	REQUEST(xTestFakeInputReq);
 | 
						|
	/*
 | 
						|
	 * byte-swap the fields in the request
 | 
						|
	 */
 | 
						|
	swaps(&stuff->length, n);
 | 
						|
	swapl(&stuff->ack, n);
 | 
						|
	/*
 | 
						|
	 * have to parse and then byte-swap the input action list here
 | 
						|
	 */
 | 
						|
	for (i = 0; i < XTestMAX_ACTION_LIST_SIZE;)
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * point to the next input action in the request
 | 
						|
		 */
 | 
						|
		input_action_ptr = &(((xTestFakeInputReq *) stuff)->action_list[i]);
 | 
						|
		/*
 | 
						|
		 * figure out what type of input action it is
 | 
						|
		 */
 | 
						|
		input_action_type = (*input_action_ptr) & XTestACTION_TYPE_MASK;
 | 
						|
		/*
 | 
						|
		 * byte-swap the input action according to it's type
 | 
						|
		 */
 | 
						|
		switch (input_action_type)
 | 
						|
		{
 | 
						|
		case XTestKEY_ACTION:
 | 
						|
			/*
 | 
						|
			 * byte-swap the delay_time field
 | 
						|
			 */
 | 
						|
			swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n);
 | 
						|
			/*
 | 
						|
			 * advance to the next input action
 | 
						|
			 */
 | 
						|
			i += sizeof(XTestKeyInfo);
 | 
						|
			break;
 | 
						|
		case XTestMOTION_ACTION:
 | 
						|
			/*
 | 
						|
			 * byte-swap the delay_time field
 | 
						|
			 */
 | 
						|
			swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n);
 | 
						|
			/*
 | 
						|
			 * advance to the next input action
 | 
						|
			 */
 | 
						|
			i += sizeof(XTestMotionInfo);
 | 
						|
			break;
 | 
						|
		case XTestJUMP_ACTION:
 | 
						|
			/*
 | 
						|
			 * byte-swap the jumpx field
 | 
						|
			 */
 | 
						|
			swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n);
 | 
						|
			/*
 | 
						|
			 * byte-swap the jumpy field
 | 
						|
			 */
 | 
						|
			swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n);
 | 
						|
			/*
 | 
						|
			 * byte-swap the delay_time field
 | 
						|
			 */
 | 
						|
			swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n);
 | 
						|
			/*
 | 
						|
			 * advance to the next input action
 | 
						|
			 */
 | 
						|
			i += sizeof(XTestJumpInfo);
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			/*
 | 
						|
			 * if this is a delay input action, then byte-swap it,
 | 
						|
			 * otherwise we have reached the end of the input
 | 
						|
			 * actions in this request
 | 
						|
			 */
 | 
						|
			if (XTestUnpackDeviceID(*input_action_ptr) ==
 | 
						|
			    XTestDELAY_DEVICE_ID)
 | 
						|
			{
 | 
						|
				/*
 | 
						|
				 * byte-swap the delay_time field
 | 
						|
				 */
 | 
						|
				swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n);
 | 
						|
				/*
 | 
						|
				 * advance to the next input action
 | 
						|
				 */
 | 
						|
				i += sizeof(XTestDelayInfo);
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				/*
 | 
						|
				 * if the input action header byte is 0 or
 | 
						|
				 * ill-formed, then there are no more input
 | 
						|
				 * actions in this request
 | 
						|
				 */
 | 
						|
				i = XTestMAX_ACTION_LIST_SIZE;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return(ProcTestFakeInput(client));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SProcTestGetInput
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
SProcTestGetInput(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
 | 
						|
	REQUEST(xTestGetInputReq);
 | 
						|
	/*
 | 
						|
	 * byte-swap the fields in the request
 | 
						|
	 */
 | 
						|
	swaps(&stuff->length, n);
 | 
						|
	swapl(&stuff->mode, n);
 | 
						|
	return(ProcTestGetInput(client));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SProcTestStopInput
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
SProcTestStopInput(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
 | 
						|
	REQUEST(xTestStopInputReq);
 | 
						|
	/*
 | 
						|
	 * byte-swap the length field in the request
 | 
						|
	 */
 | 
						|
	swaps(&stuff->length, n);
 | 
						|
	return(ProcTestStopInput(client));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SProcTestReset
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
SProcTestReset(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
 | 
						|
	REQUEST(xTestResetReq);
 | 
						|
	/*
 | 
						|
	 * byte-swap the length field in the request
 | 
						|
	 */
 | 
						|
	swaps(&stuff->length, n);
 | 
						|
	return(ProcTestReset(client));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SProcTestQueryInputSize
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
SProcTestQueryInputSize(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
 | 
						|
	REQUEST(xTestQueryInputSizeReq);
 | 
						|
	/*
 | 
						|
	 * byte-swap the length field in the request
 | 
						|
	 */
 | 
						|
	swaps(&stuff->length, n);
 | 
						|
	return(ProcTestQueryInputSize(client));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	ProcTestFakeInput
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
ProcTestFakeInput(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST(xTestFakeInputReq);
 | 
						|
	REQUEST_SIZE_MATCH(xTestFakeInputReq);
 | 
						|
 | 
						|
	if (playback_client == NULL)
 | 
						|
	    {
 | 
						|
	    playback_client = client;
 | 
						|
	    current_client_id = FakeClientID(client->index);
 | 
						|
	    AddResource(current_client_id,
 | 
						|
		    XTestType,
 | 
						|
		    0);
 | 
						|
	    MakeClientGrabImpervious(client);
 | 
						|
	    }
 | 
						|
	if (playback_client == client)
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * This extension does not need to clean up any
 | 
						|
		 * server state when a client using this function
 | 
						|
		 * "goes away".  The server will just process any
 | 
						|
		 * input actions that have already been sent to it,
 | 
						|
		 * and will then reset its association with a client.
 | 
						|
		 */
 | 
						|
		parse_fake_input(client, (char *)stuff);
 | 
						|
		return(Success);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * this is a request by another client to send fake
 | 
						|
		 * input while the server is still being used
 | 
						|
		 */
 | 
						|
		SendErrorToClient(client,
 | 
						|
				  XTestReqCode,
 | 
						|
				  X_TestFakeInput,
 | 
						|
				  None,
 | 
						|
				  BadAccess);
 | 
						|
		return(BadAccess);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	ProcTestGetInput
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
ProcTestGetInput(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST(xTestGetInputReq);
 | 
						|
	REQUEST_SIZE_MATCH(xTestGetInputReq);
 | 
						|
	if (on_steal_input)
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * this is a request by another client to get fake input
 | 
						|
		 * while the server is still sending input to the first client
 | 
						|
		 */
 | 
						|
		SendErrorToClient(client,
 | 
						|
				  XTestReqCode,
 | 
						|
				  X_TestGetInput,
 | 
						|
				  None,
 | 
						|
				  BadAccess);
 | 
						|
		return(BadAccess);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{ 
 | 
						|
		/*
 | 
						|
		 * Set up a resource associated with the client using this
 | 
						|
		 * function so that this extension gets called when the 
 | 
						|
		 * client "goes away".  This allows this extension to
 | 
						|
		 * clean up the server state.
 | 
						|
		 */
 | 
						|
		current_client_id = FakeClientID(client->index);
 | 
						|
		AddResource(current_client_id,
 | 
						|
			    XTestType,
 | 
						|
			    0);
 | 
						|
		/*
 | 
						|
		 * indicate that a client is stealing input
 | 
						|
		 */
 | 
						|
		on_steal_input = TRUE;
 | 
						|
		if ((stuff->mode & XTestEXCLUSIVE) == 0)
 | 
						|
		{
 | 
						|
			exclusive_steal = FALSE;
 | 
						|
		}
 | 
						|
		else 
 | 
						|
		{
 | 
						|
			exclusive_steal = TRUE;
 | 
						|
		}
 | 
						|
		steal_input(client, stuff->mode);
 | 
						|
		return(Success);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	ProcTestStopInput
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
ProcTestStopInput(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST_SIZE_MATCH(xTestStopInputReq);
 | 
						|
	if (on_steal_input && (current_xtest_client == client)) 
 | 
						|
	{ 
 | 
						|
		on_steal_input = FALSE;
 | 
						|
		exclusive_steal = FALSE;
 | 
						|
		stop_stealing_input();	
 | 
						|
		/*
 | 
						|
		 * remove the resource associated with this client
 | 
						|
		 */
 | 
						|
		FreeResource(current_client_id, RT_NONE);
 | 
						|
		return(Success);
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * this is a request to stop fake input when fake input has
 | 
						|
		 * never been started or from a client that hasn't started
 | 
						|
		 * fake input
 | 
						|
		 */
 | 
						|
		SendErrorToClient(client,
 | 
						|
				  XTestReqCode,
 | 
						|
				  X_TestStopInput,
 | 
						|
				  None,
 | 
						|
				  BadAccess);
 | 
						|
		return(BadAccess);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	ProcTestReset
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
ProcTestReset(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST_SIZE_MATCH(xTestResetReq);
 | 
						|
	on_steal_input = FALSE;
 | 
						|
	exclusive_steal = FALSE;
 | 
						|
	/*
 | 
						|
	 * defined in xtest1dd.c
 | 
						|
	 */
 | 
						|
	stop_stealing_input();	
 | 
						|
	/*
 | 
						|
	 * defined in xtest1dd.c
 | 
						|
	 */
 | 
						|
	abort_play_back();
 | 
						|
	return(Success);
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	ProcTestQueryInputSize
 | 
						|
 *
 | 
						|
 *
 | 
						|
 */
 | 
						|
static int
 | 
						|
ProcTestQueryInputSize(client)
 | 
						|
	register ClientPtr	client;
 | 
						|
{
 | 
						|
	REQUEST_SIZE_MATCH(xTestQueryInputSizeReq);
 | 
						|
	/*
 | 
						|
	 * defined in xtest1dd.c
 | 
						|
	 */
 | 
						|
	return_input_array_size(client);
 | 
						|
	return(Success);
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	XTestResetProc
 | 
						|
 *
 | 
						|
 *	This function is called by the server when the server has no clients
 | 
						|
 *	connected to it.  It must put eveything back the way it was before
 | 
						|
 *	this extension was installed.
 | 
						|
 */
 | 
						|
/*ARGSUSED*/
 | 
						|
static void
 | 
						|
XTestResetProc(unused)
 | 
						|
	ExtensionEntry * unused;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * remove the routine to handle byte-swapping the replies
 | 
						|
	 * for this extension in the ReplySwapVector table
 | 
						|
	 */
 | 
						|
	ReplySwapVector[XTestReqCode] = ReplyNotSwappd;
 | 
						|
	/*
 | 
						|
	 * remove the routine to handle byte-swapping the events
 | 
						|
	 * for this extension in the EventSwapVector table
 | 
						|
	 */
 | 
						|
	EventSwapVector[XTestInputActionType] = NotImplemented;
 | 
						|
	EventSwapVector[XTestFakeAckType] = NotImplemented;
 | 
						|
	/*
 | 
						|
	 * reset the variables initialized just once at load time
 | 
						|
	 */
 | 
						|
	XTestReqCode = 0;
 | 
						|
	XTestInputActionType = 0;
 | 
						|
	XTestFakeAckType = 1;
 | 
						|
	on_steal_input = FALSE;
 | 
						|
	exclusive_steal = FALSE;
 | 
						|
	playback_client = 0;	/* Don't really need this but it looks nice */
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	PXTestCurrentClientGone
 | 
						|
 *
 | 
						|
 *	This routine is called when a client that has asked for input actions
 | 
						|
 *	to be sent to it "goes away".  This routine must clean up the 
 | 
						|
 *	server state.
 | 
						|
 */
 | 
						|
/*ARGSUSED*/
 | 
						|
static int
 | 
						|
XTestCurrentClientGone(value, id)
 | 
						|
	pointer	value;
 | 
						|
	XID	id;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * defined in xtest1dd.c
 | 
						|
	 */
 | 
						|
	on_steal_input = FALSE;
 | 
						|
	exclusive_steal = FALSE;
 | 
						|
	/*
 | 
						|
	 * defined in xtestdd.c
 | 
						|
	 */
 | 
						|
	playback_client = 0;
 | 
						|
	abort_play_back();
 | 
						|
	return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SReplyXTestDispatch
 | 
						|
 *
 | 
						|
 *	Swap any replies defined in this extension.
 | 
						|
 */
 | 
						|
static void
 | 
						|
SReplyXTestDispatch(client_ptr, size, reply_ptr)
 | 
						|
	ClientPtr	client_ptr;
 | 
						|
	int		size;
 | 
						|
	char		*reply_ptr;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
	/*
 | 
						|
	 * pointer to xTestQueryInputSizeReply
 | 
						|
	 */
 | 
						|
	xTestQueryInputSizeReply	*rep_ptr;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * there is only one reply in this extension, so byte-swap it
 | 
						|
	 */
 | 
						|
	rep_ptr = (xTestQueryInputSizeReply *) reply_ptr;
 | 
						|
	swaps(&(rep_ptr->sequenceNumber), n);
 | 
						|
	swapl(&(rep_ptr->length), n);
 | 
						|
	swapl(&(rep_ptr->size_return), n);
 | 
						|
	/*
 | 
						|
	 * now write the swapped reply to the client
 | 
						|
	 */
 | 
						|
	WriteToClient(client_ptr, size, reply_ptr);
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 *
 | 
						|
 *	SEventXTestDispatch
 | 
						|
 *
 | 
						|
 *	Swap any events defined in this extension.
 | 
						|
 */
 | 
						|
static void
 | 
						|
SEventXTestDispatch(from, to)
 | 
						|
	xEvent	*from;
 | 
						|
	xEvent	*to;
 | 
						|
{
 | 
						|
	/*
 | 
						|
	 * used in the swaps and swapl macros for temporary storage space
 | 
						|
	 */
 | 
						|
	register char	n;
 | 
						|
	/*
 | 
						|
	 * index counter
 | 
						|
	 */
 | 
						|
	int		i;
 | 
						|
	/*
 | 
						|
	 * pointer to the next input action in the event
 | 
						|
	 */
 | 
						|
	CARD8		*input_action_ptr;
 | 
						|
	/*
 | 
						|
	 * holds the type of the next input action in the event
 | 
						|
	 */
 | 
						|
	int		input_action_type;
 | 
						|
 | 
						|
 | 
						|
	/*
 | 
						|
	 * copy the type information from the "from" event to the "to" event
 | 
						|
	 */
 | 
						|
	((xTestInputActionEvent *) to)->type =
 | 
						|
	((xTestInputActionEvent *) from)->type;
 | 
						|
	/*
 | 
						|
	 * copy the sequence number information from the "from" event to the
 | 
						|
	 * "to" event
 | 
						|
	 */
 | 
						|
	((xTestInputActionEvent *) to)->sequenceNumber =
 | 
						|
	((xTestInputActionEvent *) from)->sequenceNumber;
 | 
						|
	/*
 | 
						|
	 * byte-swap the sequence number in the "to" event
 | 
						|
	 */
 | 
						|
	swaps(&(((xTestInputActionEvent *) to)->sequenceNumber), n);
 | 
						|
	/*
 | 
						|
	 * If the event is an xTestInputActionEvent, then it needs more
 | 
						|
	 * processing.  Otherwise, it is an xTestFakeAckEvent, which
 | 
						|
	 * has no other information in it.
 | 
						|
	 */
 | 
						|
	if ((((xTestInputActionEvent *) to)->type & 0x7f) ==
 | 
						|
	    XTestInputActionType)
 | 
						|
	{
 | 
						|
		/*
 | 
						|
		 * copy the input actions from the "from" event
 | 
						|
		 * to the "to" event
 | 
						|
		 */
 | 
						|
		for (i = 0; i < XTestACTIONS_SIZE; i++)
 | 
						|
		{
 | 
						|
			((xTestInputActionEvent *) to)->actions[i] =
 | 
						|
			((xTestInputActionEvent *) from)->actions[i];
 | 
						|
		}
 | 
						|
		/*
 | 
						|
		 * byte-swap the input actions in the "to" event
 | 
						|
		 */
 | 
						|
		for (i = 0; i < XTestACTIONS_SIZE; i++)
 | 
						|
		{
 | 
						|
			/*
 | 
						|
			 * point to the next input action in the event
 | 
						|
			 */
 | 
						|
			input_action_ptr = &(((xTestInputActionEvent *) to)->actions[i]);
 | 
						|
			/*
 | 
						|
			 * figure out what type of input action it is
 | 
						|
			 */
 | 
						|
			input_action_type = (*input_action_ptr) &
 | 
						|
					    XTestACTION_TYPE_MASK;
 | 
						|
			/*
 | 
						|
			 * byte-swap the input action according to it's type
 | 
						|
			 */
 | 
						|
			switch (input_action_type)
 | 
						|
			{
 | 
						|
			case XTestKEY_ACTION:
 | 
						|
				/*
 | 
						|
				 * byte-swap the delay_time field
 | 
						|
				 */
 | 
						|
				swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n);
 | 
						|
				/*
 | 
						|
				 * advance to the next input action
 | 
						|
				 */
 | 
						|
				i += sizeof(XTestKeyInfo);
 | 
						|
				break;
 | 
						|
			case XTestMOTION_ACTION:
 | 
						|
				/*
 | 
						|
				 * byte-swap the delay_time field
 | 
						|
				 */
 | 
						|
				swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n);
 | 
						|
				/*
 | 
						|
				 * advance to the next input action
 | 
						|
				 */
 | 
						|
				i += sizeof(XTestMotionInfo);
 | 
						|
				break;
 | 
						|
			case XTestJUMP_ACTION:
 | 
						|
				/*
 | 
						|
				 * byte-swap the jumpx field
 | 
						|
				 */
 | 
						|
				swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n);
 | 
						|
				/*
 | 
						|
				 * byte-swap the jumpy field
 | 
						|
				 */
 | 
						|
				swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n);
 | 
						|
				/*
 | 
						|
				 * byte-swap the delay_time field
 | 
						|
				 */
 | 
						|
				swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n);
 | 
						|
				/*
 | 
						|
				 * advance to the next input action
 | 
						|
				 */
 | 
						|
				i += sizeof(XTestJumpInfo);
 | 
						|
				break;
 | 
						|
			default:
 | 
						|
				/*
 | 
						|
				 * if this is a delay input action, then
 | 
						|
				 * byte-swap it, otherwise we have reached the
 | 
						|
				 * end of the input actions in this event
 | 
						|
				 */
 | 
						|
				if (XTestUnpackDeviceID(*input_action_ptr) ==
 | 
						|
				    XTestDELAY_DEVICE_ID)
 | 
						|
				{
 | 
						|
					/*
 | 
						|
					 * byte-swap the delay_time field
 | 
						|
					 */
 | 
						|
					swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n);
 | 
						|
					/*
 | 
						|
					 * advance to the next input action
 | 
						|
					 */
 | 
						|
					i += sizeof(XTestDelayInfo);
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					/*
 | 
						|
					 * if the input action header byte is 0
 | 
						|
					 * or ill-formed, then there are no
 | 
						|
					 * more input actions in this event
 | 
						|
					 */
 | 
						|
					i = XTestACTIONS_SIZE;
 | 
						|
				}
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |