1 /* $XConsortium: xtest1di.c,v 1.13 94/04/17 20:33:01 rws Exp $ */
2 /* $XFree86: xc/programs/Xserver/Xext/xtest1di.c,v 3.0 1996/05/06 05:55:45 dawes Exp $ */
6 * This file contains the device independent parts of the input
13 Copyright (c) 1986, 1987, 1988 X Consortium
15 Permission is hereby granted, free of charge, to any person obtaining a copy
16 of this software and associated documentation files (the "Software"), to deal
17 in the Software without restriction, including without limitation the rights
18 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19 copies of the Software, and to permit persons to whom the Software is
20 furnished to do so, subject to the following conditions:
22 The above copyright notice and this permission notice shall be included in
23 all copies or substantial portions of the Software.
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
29 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 Except as contained in this notice, the name of the X Consortium shall not be
33 used in advertising or otherwise to promote the sale, use or other dealings
34 in this Software without prior written authorization from the X Consortium.
37 Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
39 Permission to use, copy, modify, and distribute this
40 software and its documentation for any purpose and without
41 fee is hereby granted, provided that the above copyright
42 notice appear in all copies and that both that copyright
43 notice and this permission notice appear in supporting
44 documentation, and that the name of Hewlett-Packard not be used in
45 advertising or publicity pertaining to distribution of the
46 software without specific, written prior permission.
48 Hewlett-Packard makes no representations about the
49 suitability of this software for any purpose. It is provided
50 "as is" without express or implied warranty.
52 This software is not subject to any license of the American
53 Telephone and Telegraph Company or of the Regents of the
54 University of California.
58 /*****************************************************************************
60 ****************************************************************************/
71 #include "extnsionst.h"
72 #include "dixstruct.h"
74 #define XTestSERVER_SIDE
75 #include "xtestext1.h"
79 /*****************************************************************************
81 ****************************************************************************/
83 /*****************************************************************************
85 ****************************************************************************/
88 * id of client using XTestGetInput
90 * defined in xtest1dd.c
92 extern ClientPtr current_xtest_client;
94 * id of client using XTestFakeInput
96 * defined in xtest1dd.c
98 extern ClientPtr playback_client;
100 /*****************************************************************************
102 ****************************************************************************/
105 * Holds the request type code for this extension. The request type code
106 * for this extension may vary depending on how many extensions are installed
107 * already, so the initial value given below will be added to the base request
108 * code that is aquired when this extension is installed.
110 static int XTestReqCode = 0;
112 * Holds the two event type codes for this extension. The event type codes
113 * for this extension may vary depending on how many extensions are installed
114 * already, so the initial values given below will be added to the base event
115 * code that is aquired when this extension is installed.
117 int XTestInputActionType = 0;
118 int XTestFakeAckType = 1;
120 * true => monitor stealing input
122 int on_steal_input = FALSE;
124 * true => monitor alone getting input
126 int exclusive_steal = FALSE;
128 * holds the resource type assigned to this extension
130 static RESTYPE XTestType;
132 * holds the resource ID for the client currently using XTestGetInput
134 static XID current_client_id;
136 /*****************************************************************************
137 * function declarations
138 ****************************************************************************/
140 static DISPATCH_PROC(ProcXTestDispatch);
141 static DISPATCH_PROC(SProcXTestDispatch);
142 static DISPATCH_PROC(ProcTestFakeInput);
143 static DISPATCH_PROC(SProcTestFakeInput);
144 static DISPATCH_PROC(ProcTestGetInput);
145 static DISPATCH_PROC(SProcTestGetInput);
146 static DISPATCH_PROC(ProcTestStopInput);
147 static DISPATCH_PROC(SProcTestStopInput);
148 static DISPATCH_PROC(ProcTestReset);
149 static DISPATCH_PROC(SProcTestReset);
150 static DISPATCH_PROC(ProcTestQueryInputSize);
151 static DISPATCH_PROC(SProcTestQueryInputSize);
153 static void XTestResetProc(
154 #if NeedFunctionPrototypes
155 ExtensionEntry * /* unused */
158 static void SReplyXTestDispatch(
159 #if NeedFunctionPrototypes
160 ClientPtr /* client_ptr */,
162 char * /* reply_ptr */
165 static void SEventXTestDispatch(
166 #if NeedFunctionPrototypes
172 static int XTestCurrentClientGone(
173 #if NeedFunctionPrototypes
179 /*****************************************************************************
181 * XTestExtension1Init
183 * Called from InitExtensions in main() or from QueryExtension() if the
184 * extension is dynamically loaded.
186 * XTestExtension1Init has no events or errors
187 * (other than the core errors).
190 XTestExtension1Init()
193 * holds the pointer to the extension entry structure
195 ExtensionEntry *extEntry;
197 extEntry = AddExtension(XTestEXTENSION_NAME,
203 StandardMinorOpcode);
207 * remember the request code assigned to this extension
209 XTestReqCode = extEntry->base;
211 * make an atom saying that this extension is present
213 (void) MakeAtom(XTestEXTENSION_NAME,
214 strlen(XTestEXTENSION_NAME),
217 * remember the event codes assigned to this extension
219 XTestInputActionType += extEntry->eventBase;
220 XTestFakeAckType += extEntry->eventBase;
222 * install the routine to handle byte-swapping the replies
223 * for this extension in the ReplySwapVector table
225 ReplySwapVector[XTestReqCode] = (ReplySwapPtr) SReplyXTestDispatch;
227 * install the routine to handle byte-swapping the events
228 * for this extension in the EventSwapVector table
230 EventSwapVector[XTestInputActionType] = SEventXTestDispatch;
231 EventSwapVector[XTestFakeAckType] = SEventXTestDispatch;
233 * get the resource type for this extension
235 XTestType = CreateNewResourceType(XTestCurrentClientGone);
238 FatalError("XTestExtension1Init: CreateNewResourceType failed\n");
243 FatalError("XTestExtension1Init: AddExtensions failed\n");
247 /*****************************************************************************
254 ProcXTestDispatch(client)
255 register ClientPtr client;
258 if (stuff->data == X_TestFakeInput)
260 return(ProcTestFakeInput(client));
262 else if (stuff->data == X_TestGetInput)
264 return(ProcTestGetInput(client));
266 else if (stuff->data == X_TestStopInput)
268 return(ProcTestStopInput(client));
270 else if (stuff->data == X_TestReset)
272 return(ProcTestReset(client));
274 else if (stuff->data == X_TestQueryInputSize)
276 return(ProcTestQueryInputSize(client));
280 SendErrorToClient(client,
289 /*****************************************************************************
296 SProcXTestDispatch(client)
297 register ClientPtr client;
300 if (stuff->data == X_TestFakeInput)
302 return(SProcTestFakeInput(client));
304 else if (stuff->data == X_TestGetInput)
306 return(SProcTestGetInput(client));
308 else if (stuff->data == X_TestStopInput)
310 return(SProcTestStopInput(client));
312 else if (stuff->data == X_TestReset)
314 return(SProcTestReset(client));
316 else if (stuff->data == X_TestQueryInputSize)
318 return(SProcTestQueryInputSize(client));
322 SendErrorToClient(client,
331 /*****************************************************************************
338 SProcTestFakeInput(client)
339 register ClientPtr client;
342 * used in the swaps and swapl macros for temporary storage space
350 * pointer to the next input action in the request
352 CARD8 *input_action_ptr;
354 * holds the type of the next input action in the request
356 int input_action_type;
358 REQUEST(xTestFakeInputReq);
360 * byte-swap the fields in the request
362 swaps(&stuff->length, n);
363 swapl(&stuff->ack, n);
365 * have to parse and then byte-swap the input action list here
367 for (i = 0; i < XTestMAX_ACTION_LIST_SIZE;)
370 * point to the next input action in the request
372 input_action_ptr = &(((xTestFakeInputReq *) stuff)->action_list[i]);
374 * figure out what type of input action it is
376 input_action_type = (*input_action_ptr) & XTestACTION_TYPE_MASK;
378 * byte-swap the input action according to it's type
380 switch (input_action_type)
382 case XTestKEY_ACTION:
384 * byte-swap the delay_time field
386 swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n);
388 * advance to the next input action
390 i += sizeof(XTestKeyInfo);
392 case XTestMOTION_ACTION:
394 * byte-swap the delay_time field
396 swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n);
398 * advance to the next input action
400 i += sizeof(XTestMotionInfo);
402 case XTestJUMP_ACTION:
404 * byte-swap the jumpx field
406 swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n);
408 * byte-swap the jumpy field
410 swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n);
412 * byte-swap the delay_time field
414 swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n);
416 * advance to the next input action
418 i += sizeof(XTestJumpInfo);
422 * if this is a delay input action, then byte-swap it,
423 * otherwise we have reached the end of the input
424 * actions in this request
426 if (XTestUnpackDeviceID(*input_action_ptr) ==
427 XTestDELAY_DEVICE_ID)
430 * byte-swap the delay_time field
432 swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n);
434 * advance to the next input action
436 i += sizeof(XTestDelayInfo);
441 * if the input action header byte is 0 or
442 * ill-formed, then there are no more input
443 * actions in this request
445 i = XTestMAX_ACTION_LIST_SIZE;
450 return(ProcTestFakeInput(client));
453 /*****************************************************************************
460 SProcTestGetInput(client)
461 register ClientPtr client;
464 * used in the swaps and swapl macros for temporary storage space
468 REQUEST(xTestGetInputReq);
470 * byte-swap the fields in the request
472 swaps(&stuff->length, n);
473 swapl(&stuff->mode, n);
474 return(ProcTestGetInput(client));
477 /*****************************************************************************
484 SProcTestStopInput(client)
485 register ClientPtr client;
488 * used in the swaps and swapl macros for temporary storage space
492 REQUEST(xTestStopInputReq);
494 * byte-swap the length field in the request
496 swaps(&stuff->length, n);
497 return(ProcTestStopInput(client));
500 /*****************************************************************************
507 SProcTestReset(client)
508 register ClientPtr client;
511 * used in the swaps and swapl macros for temporary storage space
515 REQUEST(xTestResetReq);
517 * byte-swap the length field in the request
519 swaps(&stuff->length, n);
520 return(ProcTestReset(client));
523 /*****************************************************************************
525 * SProcTestQueryInputSize
530 SProcTestQueryInputSize(client)
531 register ClientPtr client;
534 * used in the swaps and swapl macros for temporary storage space
538 REQUEST(xTestQueryInputSizeReq);
540 * byte-swap the length field in the request
542 swaps(&stuff->length, n);
543 return(ProcTestQueryInputSize(client));
546 /*****************************************************************************
553 ProcTestFakeInput(client)
554 register ClientPtr client;
556 REQUEST(xTestFakeInputReq);
557 REQUEST_SIZE_MATCH(xTestFakeInputReq);
559 if (playback_client == NULL)
561 playback_client = client;
562 current_client_id = FakeClientID(client->index);
563 AddResource(current_client_id,
566 MakeClientGrabImpervious(client);
568 if (playback_client == client)
571 * This extension does not need to clean up any
572 * server state when a client using this function
573 * "goes away". The server will just process any
574 * input actions that have already been sent to it,
575 * and will then reset its association with a client.
577 parse_fake_input(client, (char *)stuff);
583 * this is a request by another client to send fake
584 * input while the server is still being used
586 SendErrorToClient(client,
595 /*****************************************************************************
602 ProcTestGetInput(client)
603 register ClientPtr client;
605 REQUEST(xTestGetInputReq);
606 REQUEST_SIZE_MATCH(xTestGetInputReq);
610 * this is a request by another client to get fake input
611 * while the server is still sending input to the first client
613 SendErrorToClient(client,
623 * Set up a resource associated with the client using this
624 * function so that this extension gets called when the
625 * client "goes away". This allows this extension to
626 * clean up the server state.
628 current_client_id = FakeClientID(client->index);
629 AddResource(current_client_id,
633 * indicate that a client is stealing input
635 on_steal_input = TRUE;
636 if ((stuff->mode & XTestEXCLUSIVE) == 0)
638 exclusive_steal = FALSE;
642 exclusive_steal = TRUE;
644 steal_input(client, stuff->mode);
649 /*****************************************************************************
656 ProcTestStopInput(client)
657 register ClientPtr client;
659 REQUEST_SIZE_MATCH(xTestStopInputReq);
660 if (on_steal_input && (current_xtest_client == client))
662 on_steal_input = FALSE;
663 exclusive_steal = FALSE;
664 stop_stealing_input();
666 * remove the resource associated with this client
668 FreeResource(current_client_id, RT_NONE);
674 * this is a request to stop fake input when fake input has
675 * never been started or from a client that hasn't started
678 SendErrorToClient(client,
687 /*****************************************************************************
694 ProcTestReset(client)
695 register ClientPtr client;
697 REQUEST_SIZE_MATCH(xTestResetReq);
698 on_steal_input = FALSE;
699 exclusive_steal = FALSE;
701 * defined in xtest1dd.c
703 stop_stealing_input();
705 * defined in xtest1dd.c
711 /*****************************************************************************
713 * ProcTestQueryInputSize
718 ProcTestQueryInputSize(client)
719 register ClientPtr client;
721 REQUEST_SIZE_MATCH(xTestQueryInputSizeReq);
723 * defined in xtest1dd.c
725 return_input_array_size(client);
729 /*****************************************************************************
733 * This function is called by the server when the server has no clients
734 * connected to it. It must put eveything back the way it was before
735 * this extension was installed.
739 XTestResetProc(unused)
740 ExtensionEntry * unused;
743 * remove the routine to handle byte-swapping the replies
744 * for this extension in the ReplySwapVector table
746 ReplySwapVector[XTestReqCode] = ReplyNotSwappd;
748 * remove the routine to handle byte-swapping the events
749 * for this extension in the EventSwapVector table
751 EventSwapVector[XTestInputActionType] = NotImplemented;
752 EventSwapVector[XTestFakeAckType] = NotImplemented;
754 * reset the variables initialized just once at load time
757 XTestInputActionType = 0;
758 XTestFakeAckType = 1;
759 on_steal_input = FALSE;
760 exclusive_steal = FALSE;
761 playback_client = 0; /* Don't really need this but it looks nice */
764 /*****************************************************************************
766 * PXTestCurrentClientGone
768 * This routine is called when a client that has asked for input actions
769 * to be sent to it "goes away". This routine must clean up the
774 XTestCurrentClientGone(value, id)
779 * defined in xtest1dd.c
781 on_steal_input = FALSE;
782 exclusive_steal = FALSE;
784 * defined in xtestdd.c
791 /*****************************************************************************
793 * SReplyXTestDispatch
795 * Swap any replies defined in this extension.
798 SReplyXTestDispatch(client_ptr, size, reply_ptr)
799 ClientPtr client_ptr;
804 * used in the swaps and swapl macros for temporary storage space
808 * pointer to xTestQueryInputSizeReply
810 xTestQueryInputSizeReply *rep_ptr;
813 * there is only one reply in this extension, so byte-swap it
815 rep_ptr = (xTestQueryInputSizeReply *) reply_ptr;
816 swaps(&(rep_ptr->sequenceNumber), n);
817 swapl(&(rep_ptr->length), n);
818 swapl(&(rep_ptr->size_return), n);
820 * now write the swapped reply to the client
822 WriteToClient(client_ptr, size, reply_ptr);
825 /*****************************************************************************
827 * SEventXTestDispatch
829 * Swap any events defined in this extension.
832 SEventXTestDispatch(from, to)
837 * used in the swaps and swapl macros for temporary storage space
845 * pointer to the next input action in the event
847 CARD8 *input_action_ptr;
849 * holds the type of the next input action in the event
851 int input_action_type;
855 * copy the type information from the "from" event to the "to" event
857 ((xTestInputActionEvent *) to)->type =
858 ((xTestInputActionEvent *) from)->type;
860 * copy the sequence number information from the "from" event to the
863 ((xTestInputActionEvent *) to)->sequenceNumber =
864 ((xTestInputActionEvent *) from)->sequenceNumber;
866 * byte-swap the sequence number in the "to" event
868 swaps(&(((xTestInputActionEvent *) to)->sequenceNumber), n);
870 * If the event is an xTestInputActionEvent, then it needs more
871 * processing. Otherwise, it is an xTestFakeAckEvent, which
872 * has no other information in it.
874 if ((((xTestInputActionEvent *) to)->type & 0x7f) ==
875 XTestInputActionType)
878 * copy the input actions from the "from" event
881 for (i = 0; i < XTestACTIONS_SIZE; i++)
883 ((xTestInputActionEvent *) to)->actions[i] =
884 ((xTestInputActionEvent *) from)->actions[i];
887 * byte-swap the input actions in the "to" event
889 for (i = 0; i < XTestACTIONS_SIZE; i++)
892 * point to the next input action in the event
894 input_action_ptr = &(((xTestInputActionEvent *) to)->actions[i]);
896 * figure out what type of input action it is
898 input_action_type = (*input_action_ptr) &
899 XTestACTION_TYPE_MASK;
901 * byte-swap the input action according to it's type
903 switch (input_action_type)
905 case XTestKEY_ACTION:
907 * byte-swap the delay_time field
909 swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n);
911 * advance to the next input action
913 i += sizeof(XTestKeyInfo);
915 case XTestMOTION_ACTION:
917 * byte-swap the delay_time field
919 swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n);
921 * advance to the next input action
923 i += sizeof(XTestMotionInfo);
925 case XTestJUMP_ACTION:
927 * byte-swap the jumpx field
929 swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n);
931 * byte-swap the jumpy field
933 swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n);
935 * byte-swap the delay_time field
937 swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n);
939 * advance to the next input action
941 i += sizeof(XTestJumpInfo);
945 * if this is a delay input action, then
946 * byte-swap it, otherwise we have reached the
947 * end of the input actions in this event
949 if (XTestUnpackDeviceID(*input_action_ptr) ==
950 XTestDELAY_DEVICE_ID)
953 * byte-swap the delay_time field
955 swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n);
957 * advance to the next input action
959 i += sizeof(XTestDelayInfo);
964 * if the input action header byte is 0
965 * or ill-formed, then there are no
966 * more input actions in this event
968 i = XTestACTIONS_SIZE;