diff options
Diffstat (limited to 'Xext/xtest1di.c')
-rw-r--r-- | Xext/xtest1di.c | 966 |
1 files changed, 966 insertions, 0 deletions
diff --git a/Xext/xtest1di.c b/Xext/xtest1di.c new file mode 100644 index 000000000..cd8f5e727 --- /dev/null +++ b/Xext/xtest1di.c @@ -0,0 +1,966 @@ +/* $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. + +*/ + +/***************************************************************************** + * include files + ****************************************************************************/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#include <stdio.h> +#include "X.h" +#include "Xproto.h" +#include "misc.h" +#include "os.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "opaque.h" +#define XTestSERVER_SIDE +#include "xtestext1.h" + +/***************************************************************************** + * defines + ****************************************************************************/ + +/***************************************************************************** + * externals + ****************************************************************************/ + +/* + * holds the addresses of the routines that handle byte-swapping of replys + */ +extern void (* ReplySwapVector[256]) (); +/* + * id of client using XTestGetInput + * + * defined in xtest1dd.c + */ +extern ClientPtr current_xtest_client; +/* + * id of client using XTestFakeInput + * + * defined in xtest1dd.c + */ +extern ClientPtr playback_client; + +/***************************************************************************** + * 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 int ProcXTestDispatch(); +static int SProcXTestDispatch(); +static void XTestResetProc(); +static int ProcTestFakeInput(); +static int SProcTestFakeInput(); +static int ProcTestGetInput(); +static int SProcTestGetInput(); +static int ProcTestStopInput(); +static int SProcTestStopInput(); +static int ProcTestReset(); +static int SProcTestReset(); +static int ProcTestQueryInputSize(); +static int SProcTestQueryInputSize(); +static void SReplyXTestDispatch(); +static void SEventXTestDispatch(); +void NotImplemented(); + +void abort_play_back(); +void return_input_array_size(); +void steal_input(); +void stop_stealing_input(); +void flush_input_actions(); +void parse_fake_input(); + +static int XTestCurrentClientGone(); + +/***************************************************************************** + * + * 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() +{ + /* + * holds the pointer to the extension entry structure + */ + ExtensionEntry *extEntry; + /* + * This routine adds the extension to the server extension table. + */ + ExtensionEntry *AddExtension(); + + 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] = 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(xTestStopInputReq); + 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(xTestResetReq); + 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(xTestQueryInputSizeReq); + 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. + */ +static void +XTestResetProc() +{ + /* + * remove the routine to handle byte-swapping the replies + * for this extension in the ReplySwapVector table + */ + ReplySwapVector[XTestReqCode] = NotImplemented; + /* + * 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 */ +} + +/***************************************************************************** + * + * ProcTestQueryInputSize + * + * 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; + } + } + } +} |