XTestExt1.c revision caade7cc
1/* $Xorg: XTestExt1.c,v 1.4 2001/02/09 02:03:49 xorgcvs Exp $ */
2/*
3 *	File:  xtestext1lib.c
4 *
5 *	This file contains the Xlib parts of the input synthesis extension
6 */
7
8/*
9
10
11Copyright 1986, 1987, 1988, 1998   The Open Group
12
13Permission to use, copy, modify, distribute, and sell this software and its
14documentation for any purpose is hereby granted without fee, provided that
15the above copyright notice appear in all copies and that both that
16copyright notice and this permission notice appear in supporting
17documentation.
18
19The above copyright notice and this permission notice shall be included in
20all copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29Except as contained in this notice, the name of The Open Group shall not be
30used in advertising or otherwise to promote the sale, use or other dealings
31in this Software without prior written authorization from The Open Group.
32
33
34Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
35
36Permission to use, copy, modify, and distribute this
37software and its documentation for any purpose and without
38fee is hereby granted, provided that the above copyright
39notice appear in all copies and that both that copyright
40notice and this permission notice appear in supporting
41documentation, and that the name of Hewlett-Packard not be used in
42advertising or publicity pertaining to distribution of the
43software without specific, written prior permission.
44
45Hewlett-Packard makes no representations about the
46suitability of this software for any purpose.  It is provided
47"as is" without express or implied warranty.
48
49This software is not subject to any license of the American
50Telephone and Telegraph Company or of the Regents of the
51University of California.
52
53*/
54/* $XFree86: xc/lib/Xext/XTestExt1.c,v 1.3 2001/01/17 19:42:46 dawes Exp $ */
55
56/******************************************************************************
57 * include files
58 *****************************************************************************/
59
60#define NEED_REPLIES
61#define NEED_EVENTS
62
63#ifdef HAVE_CONFIG_H
64#include <config.h>
65#endif
66#include <stdio.h>
67#include <X11/Xproto.h>
68#include <X11/Xlibint.h>
69#include <X11/extensions/xtestext1.h>
70
71/******************************************************************************
72 * variables
73 *****************************************************************************/
74
75/*
76 * Holds the request type code for this extension.  The request type code
77 * for this extension may vary depending on how many extensions are installed
78 * already, so the initial value given below will be added to the base request
79 * code that is acquired when this extension is installed.
80 */
81static int		XTestReqCode = 0;
82/*
83 * Holds the two event type codes for this extension.  The event type codes
84 * for this extension may vary depending on how many extensions are installed
85 * already, so the initial values given below will be added to the base event
86 * code that is acquired when this extension is installed.
87 *
88 * These two variables must be available to programs that use this extension.
89 */
90int			XTestInputActionType = 0;
91int			XTestFakeAckType   = 1;
92/*
93 * holds the current x and y coordinates for XTestMovePointer
94 */
95static int	current_x = 0;
96static int	current_y = 0;
97/*
98 * Holds input actions being accumulated until the input action buffer is
99 * full or until XTestFlush is called.
100 */
101static CARD8		action_buf[XTestMAX_ACTION_LIST_SIZE];
102/*
103 * the index into the input action buffer
104 */
105static int		action_index = 0;
106/*
107 * the number of input actions that the server can handle at one time
108 */
109static unsigned long	action_array_size = 0;
110/*
111 * the current number of input actions
112 */
113static unsigned long	action_count = 0;
114
115/******************************************************************************
116 * function declarations
117 *****************************************************************************/
118
119static int	XTestWireToEvent(Display *dpy, XEvent *reTemp, xEvent *eventTemp);
120static int	XTestCheckExtInit(register Display *dpy);
121static Bool	XTestIdentifyMyEvent(Display *display, XEvent *event_ptr, char *args);
122static int	XTestInitExtension(register Display *dpy);
123static int	XTestKeyOrButton(Display *display, int device_id, long unsigned int delay, unsigned int code, unsigned int action);
124static int	XTestCheckDelay(Display *display, long unsigned int *delay_addr);
125static int	XTestPackInputAction(Display *display, CARD8 *action_addr, int action_size);
126static int	XTestWriteInputActions(Display *display, char *action_list_addr, int action_list_size, int ack_flag);
127
128/******************************************************************************
129 *
130 *	XTestFakeInput
131 *
132 *	Send a a request containing one or more input actions to be sent
133 *	to the server by this extension.
134 */
135int
136XTestFakeInput(
137/*
138 * the connection to the X server
139 */
140register Display	*dpy,
141/*
142 * the address of a list of input actions to be sent to the server
143 */
144char			*action_list_addr,
145/*
146 * the size (in bytes) of the list of input actions
147 */
148int			action_list_size,
149/*
150 * specifies whether the server needs to send an event to indicate that its
151 * input action buffer is empty
152 */
153int			ack_flag)
154{
155	/*
156	 * pointer to xTestFakeInputReq structure
157	 */
158	xTestFakeInputReq	*req;
159	/*
160	 * loop index
161	 */
162	int			i;
163
164	LockDisplay(dpy);
165	if ((XTestCheckExtInit(dpy) == -1) ||
166	    (action_list_size > XTestMAX_ACTION_LIST_SIZE))
167	{
168		/*
169		 * if the extension is not installed in the server or the
170		 * action list will not fit in the request, then unlock
171		 * the display and return -1.
172		 */
173		UnlockDisplay(dpy);
174		return(-1);
175	}
176	else
177	{
178		/*
179		 * Get the next available X request packet in the buffer.
180		 * It sets the `length' field to the size (in 32-bit words)
181		 * of the request.  It also sets the `reqType' field in the
182		 * request to X_TestFakeInput, which is not what is needed.
183		 *
184		 * GetReq is a macro defined in Xlibint.h.
185		 */
186		GetReq(TestFakeInput, req);
187		/*
188		 * fix up the request type code to what is needed
189		 */
190		req->reqType = XTestReqCode;
191		/*
192		 * set the minor request type code to X_TestFakeInput
193		 */
194		req->XTestReqType = X_TestFakeInput;
195		/*
196		 * set the ack code
197		 */
198		req->ack = ack_flag;
199		/*
200		 * Set the action_list area to all 0's. An input action header
201		 * value of 0 is interpreted as a flag to the input action
202		 * list handling code in the server part of this extension
203		 * that there are no more input actions in this request.
204		 */
205		for (i = 0; i < XTestMAX_ACTION_LIST_SIZE; i++)
206		{
207			req->action_list[i] = 0;
208		}
209		/*
210		 * copy the input actions into the request
211		 */
212		for (i = 0; i < action_list_size; i++)
213		{
214			req->action_list[i] = *(action_list_addr++);
215		}
216		UnlockDisplay(dpy);
217		SyncHandle();
218		return(0);
219	}
220}
221
222/******************************************************************************
223 *
224 *	XTestGetInput
225 *
226 *	Request the server to begin putting user input actions into events
227 *	to be sent to the client that called this function.
228 */
229int
230XTestGetInput(
231/*
232 * the connection to the X server
233 */
234register Display	*dpy,
235/*
236 * tells the server what to do with the user input actions
237 */
238int			action_handling)
239{
240	/*
241	 * pointer to xTestGetInputReq structure
242	 */
243	xTestGetInputReq 	*req;
244
245	LockDisplay(dpy);
246	if (XTestCheckExtInit(dpy) == -1)
247	{
248		/*
249		 * if the extension is not installed in the server
250		 * then unlock the display and return -1.
251		 */
252		UnlockDisplay(dpy);
253		return(-1);
254	}
255	else
256	{
257		/*
258		 * Get the next available X request packet in the buffer.
259		 * It sets the `length' field to the size (in 32-bit words)
260		 * of the request.  It also sets the `reqType' field in the
261		 * request to X_TestGetInput, which is not what is needed.
262		 *
263		 * GetReq is a macro defined in Xlibint.h.
264		 */
265		GetReq(TestGetInput, req);
266		/*
267		 * fix up the request type code to what is needed
268		 */
269		req->reqType = XTestReqCode;
270		/*
271		 * set the minor request type code to X_TestGetInput
272		 */
273		req->XTestReqType = X_TestGetInput;
274		/*
275		 * set the action handling mode
276		 */
277		req->mode = action_handling;
278		UnlockDisplay(dpy);
279		SyncHandle();
280		return(0);
281	}
282}
283
284/******************************************************************************
285 *
286 *	XTestStopInput
287 *
288 *	Tell the server to stop putting information about user input actions
289 *	into events.
290 */
291int
292XTestStopInput(
293/*
294 * the connection to the X server
295 */
296register Display	*dpy)
297{
298	/*
299	 * pointer to xTestStopInputReq structure
300	 */
301	xTestStopInputReq 	*req;
302
303	LockDisplay(dpy);
304	if (XTestCheckExtInit(dpy) == -1)
305	{
306		/*
307		 * if the extension is not installed in the server
308		 * then unlock the display and return -1.
309		 */
310		UnlockDisplay(dpy);
311		return(-1);
312	}
313	else
314	{
315		/*
316		 * Get the next available X request packet in the buffer.
317		 * It sets the `length' field to the size (in 32-bit words)
318		 * of the request.  It also sets the `reqType' field in the
319		 * request to X_TestStopInput, which is not what is needed.
320		 *
321		 * GetReq is a macro defined in Xlibint.h.
322		 */
323		GetReq(TestStopInput, req);
324		/*
325		 * fix up the request type code to what is needed
326		 */
327		req->reqType = XTestReqCode;
328		/*
329		 * set the minor request type code to X_TestStopInput
330		 */
331		req->XTestReqType = X_TestStopInput;
332		UnlockDisplay(dpy);
333		SyncHandle();
334		return(0);
335	}
336}
337
338/******************************************************************************
339 *
340 *	XTestReset
341 *
342 *	Tell the server to set everything having to do with this extension
343 *	back to its initial state.
344 */
345int
346XTestReset(
347/*
348 * the connection to the X server
349 */
350register Display	*dpy)
351{
352	/*
353	 * pointer to xTestReset structure
354	 */
355	xTestResetReq 	*req;
356
357	LockDisplay(dpy);
358	if (XTestCheckExtInit(dpy) == -1)
359	{
360		/*
361		 * if the extension is not installed in the server
362		 * then unlock the display and return -1.
363		 */
364		UnlockDisplay(dpy);
365		return(-1);
366	}
367	else
368	{
369		/*
370		 * Get the next available X request packet in the buffer.
371		 * It sets the `length' field to the size (in 32-bit words)
372		 * of the request.  It also sets the `reqType' field in the
373		 * request to X_TestReset, which is not what is needed.
374		 *
375		 * GetReq is a macro defined in Xlibint.h.
376		 */
377		GetReq(TestReset, req);
378		/*
379		 * fix up the request type code to what is needed
380		 */
381		req->reqType = XTestReqCode;
382		/*
383		 * set the minor request type code to X_TestReset
384		 */
385		req->XTestReqType = X_TestReset;
386		UnlockDisplay(dpy);
387		SyncHandle();
388		return(0);
389	}
390}
391
392/******************************************************************************
393 *
394 *	XTestQueryInputSize
395 *
396 *	Returns the number of input actions in the server's input action buffer.
397 */
398int
399XTestQueryInputSize(
400/*
401 * the connection to the X server
402 */
403register Display	*dpy,
404/*
405 * the address of the place to put the number of input actions in the
406 * server's input action buffer
407 */
408unsigned long		*size_return)
409{
410	/*
411	 * pointer to xTestQueryInputSize structure
412	 */
413	xTestQueryInputSizeReq 		*req;
414	/*
415	 * pointer to xTestQueryInputSize structure
416	 */
417	xTestQueryInputSizeReply 	rep;
418
419	LockDisplay(dpy);
420	if (XTestCheckExtInit(dpy) == -1)
421	{
422		/*
423		 * if the extension is not installed in the server
424		 * then unlock the display and return -1.
425		 */
426		UnlockDisplay(dpy);
427		return(-1);
428	}
429	else
430	{
431		/*
432		 * Get the next available X request packet in the buffer.
433		 * It sets the `length' field to the size (in 32-bit words)
434		 * of the request.  It also sets the `reqType' field in the
435		 * request to X_TestQueryInputSize, which is not what is needed.
436		 *
437		 * GetReq is a macro defined in Xlibint.h.
438		 */
439		GetReq(TestQueryInputSize, req);
440		/*
441		 * fix up the request type code to what is needed
442		 */
443		req->reqType = XTestReqCode;
444		/*
445		 * set the minor request type code to X_TestQueryInputSize
446		 */
447		req->XTestReqType = X_TestQueryInputSize;
448		/*
449		 * get a reply from the server
450		 */
451		(void) _XReply (dpy, (xReply *) &rep, 0, xTrue);
452		/*
453		 * put the size in the caller's variable
454		 */
455		*size_return = (unsigned long) rep.size_return;
456		UnlockDisplay(dpy);
457		SyncHandle();
458		return(0);
459	}
460}
461
462/******************************************************************************
463 *
464 *	XTestCheckExtInit
465 *
466 *	Check to see if the XTest extension is installed in the server.
467 */
468static int
469XTestCheckExtInit(
470/*
471 * the connection to the X server
472 */
473register Display	*dpy)
474{
475	/*
476	 * if the extension has not been initialized, then do so
477	 */
478	if (!XTestReqCode)
479	{
480		return(XTestInitExtension(dpy));
481	}
482	return(0);
483}
484
485/******************************************************************************
486 *
487 *	XTestInitExtension
488 *
489 *	Attempt to initialize this extension in the server.  Return 0 if it
490 *	succeeds, -1 if it does not succeed.
491 */
492static int
493XTestInitExtension(
494/*
495 * the connection to the X server
496 */
497register Display	*dpy)
498{
499	/*
500	 * loop index
501	 */
502	int			i;
503	/*
504	 * return value from XInitExtension
505	 */
506	XExtCodes		*ret;
507
508	/*
509	 * attempt to initialize the extension
510	 */
511	ret = XInitExtension(dpy, XTestEXTENSION_NAME);
512	/*
513	 * if the initialize failed, return -1
514	 */
515	if (ret == NULL)
516	{
517		return (-1);
518	}
519	/*
520	 * the initialize succeeded, remember the major opcode
521	 * for this extension
522	 */
523	XTestReqCode = ret->major_opcode;
524	/*
525	 * set up the event handler for any events from
526	 * this extension
527	 */
528	for (i = 0; i < XTestEVENT_COUNT; i++)
529	{
530		XESetWireToEvent(dpy,
531				 ret->first_event+i,
532				 XTestWireToEvent);
533	}
534	/*
535	 * compute the event type codes for the events
536	 * in this extension
537	 */
538	XTestInputActionType += ret->first_event;
539	XTestFakeAckType += ret->first_event;
540	/*
541	 * everything worked ok
542	 */
543	return(0);
544}
545
546/******************************************************************************
547 *
548 *	XTestWireToEvent
549 *
550 *	Handle XTest extension events.
551 *	Reformat a wire event into an XEvent structure of the right type.
552 */
553static Bool
554XTestWireToEvent(
555/*
556 * the connection to the X server
557 */
558Display	*dpy,
559/*
560 * a pointer to where a host formatted event should be stored
561 * with the information copied to it
562 */
563XEvent	*reTemp,
564/*
565 * a pointer to the wire event
566 */
567xEvent	*eventTemp)
568{
569	XTestInputActionEvent *re    = (XTestInputActionEvent *) reTemp;
570	xTestInputActionEvent *event = (xTestInputActionEvent *) eventTemp;
571
572	/*
573	 * loop index
574	 */
575	int	i;
576	/*
577	 * pointer to where the input actions go in the host format event
578	 */
579	CARD8	*to;
580	/*
581	 * pointer to the input actions in the wire event
582	 */
583	CARD8	*from;
584
585	/*
586	 * Copy the type of the wire event to the new event.
587	 * This will work for either event type because the type,
588	 * display, and window fields in the events have to be the same.
589	 */
590	re->type = event->type;
591	/*
592	 * set the display parameter in case it is needed (by who?)
593	 */
594	re->display = dpy;
595	if (re->type == XTestInputActionType)
596	{
597		/*
598		 * point at the first byte of input actions in the wire event
599		 */
600		from = &(event->actions[0]);
601		/*
602		 * point at where the input action bytes go in the new event
603		 */
604		to = &(re->actions[0]);
605		/*
606		 * copy the input action bytes from the wire event to
607		 * the new event
608		 */
609		for (i = 0; i < XTestACTIONS_SIZE; i++)
610		{
611			*(to++) = *(from++);
612		}
613	}
614	else if (re->type == XTestFakeAckType)
615	{
616		/*
617		 * nothing else needs to be done
618		 */
619	}
620	else
621	{
622		printf("XTestWireToEvent: UNKNOWN WIRE EVENT! type=%d\n",
623			(int) event->type);
624		printf("%s is giving up.\n", XTestEXTENSION_NAME);
625		exit (1);
626	}
627	return 1;
628}
629
630/******************************************************************************
631 *
632 *	XTestPressKey
633 *
634 *	Send input actions to the server to cause the server to think
635 *	that the specified key on the keyboard was moved as specified.
636 */
637int
638XTestPressKey(
639Display		*display,
640int		device_id,
641unsigned long	delay,
642unsigned int	keycode,
643unsigned int	key_action)
644{
645	/*
646	 * bounds check the key code
647	 */
648	if (keycode < 8 || keycode > 255)
649	{
650		return(-1);
651	}
652	/*
653	 * use the commmon key/button handling routine
654	 */
655	return(XTestKeyOrButton(display,
656				device_id,
657				delay,
658				keycode,
659				key_action));
660}
661
662/******************************************************************************
663 *
664 *	XTestPressButton
665 *
666 *	Send input actions to the server to cause the server to think
667 *	that the specified button on the mouse was moved as specified.
668 */
669int
670XTestPressButton(
671Display		*display,
672int		device_id,
673unsigned long	delay,
674unsigned int	button_number,
675unsigned int	button_action)
676{
677	/*
678	 * bounds check the button number
679	 */
680	if (button_number > 7)
681	{
682		return(-1);
683	}
684	/*
685	 * use the commmon key/button handling routine
686	 */
687	return(XTestKeyOrButton(display,
688				device_id,
689				delay,
690				button_number,
691				button_action));
692}
693
694/******************************************************************************
695 *
696 *	XTestKeyOrButton
697 *
698 *	Send input actions to the server to cause the server to think
699 *	that the specified key/button was moved as specified.
700 */
701static int
702XTestKeyOrButton(
703Display		*display,
704int		device_id,
705unsigned long	delay,
706unsigned int	code,
707unsigned int	action)
708{
709	/*
710	 * holds a key input action to be filled out and sent to the server
711	 */
712	XTestKeyInfo	keyinfo;
713
714	/*
715	 * bounds check the device id
716	 */
717	if (device_id < 0 || device_id > XTestMAX_DEVICE_ID)
718	{
719		return(-1);
720	}
721	/*
722	 * fill out the key input action(s) as appropriate
723	 */
724	switch(action)
725	{
726	case XTestPRESS:
727		/*
728		 * Check the delay.  If it is larger than will fit in the
729		 * key input action, send a delay input action.
730		 */
731		if(XTestCheckDelay(display, &delay) == -1)
732		{
733			/*
734			 * an error occurred, return -1
735			 */
736			return(-1);
737		}
738		/*
739		 * create the header
740		 */
741		keyinfo.header = XTestPackDeviceID(device_id) |
742				 XTestKEY_ACTION |
743				 XTestKEY_DOWN;
744		/*
745		 * set the key/button code
746		 */
747		keyinfo.keycode = code;
748		/*
749		 * set the delay time
750		 */
751		keyinfo.delay_time = delay;
752		/*
753		 * pack the input action into a request to be sent to the
754		 * server when the request is full or XTestFlush is called
755		 */
756		return(XTestPackInputAction(display,
757					    (CARD8 *) &keyinfo,
758					    sizeof(XTestKeyInfo)));
759	case XTestRELEASE:
760		/*
761		 * Check the delay.  If it is larger than will fit in the
762		 * key input action, send a delay input action.
763		 */
764		if(XTestCheckDelay(display, &delay) == -1)
765		{
766			/*
767			 * an error occurred, return -1
768			 */
769			return(-1);
770		}
771		/*
772		 * create the header
773		 */
774		keyinfo.header = XTestPackDeviceID(device_id) |
775				 XTestKEY_ACTION |
776				 XTestKEY_UP;
777		/*
778		 * set the key/button code
779		 */
780		keyinfo.keycode = code;
781		/*
782		 * set the delay time
783		 */
784		keyinfo.delay_time = delay;
785		/*
786		 * pack the input action into a request to be sent to the
787		 * server when the request is full or XTestFlush is called
788		 */
789		return(XTestPackInputAction(display,
790					    (CARD8 *) &keyinfo,
791					    sizeof(XTestKeyInfo)));
792	case XTestSTROKE:
793		/*
794		 * Check the delay.  If it is larger than will fit in the
795		 * key input action, send a delay input action.
796		 */
797		if(XTestCheckDelay(display, &delay) == -1)
798		{
799			/*
800			 * an error occurred, return -1
801			 */
802			return(-1);
803		}
804		/*
805		 * create a key/button-down input action header
806		 */
807		keyinfo.header = XTestPackDeviceID(device_id) |
808				 XTestKEY_ACTION |
809				 XTestKEY_DOWN;
810		/*
811		 * set the key/button code
812		 */
813		keyinfo.keycode = code;
814		/*
815		 * set the delay time
816		 */
817		keyinfo.delay_time = delay;
818		/*
819		 * pack the input action into a request to be sent to the
820		 * server when the request is full or XTestFlush is called
821		 */
822		if (XTestPackInputAction(display,
823					 (CARD8 *) &keyinfo,
824					 sizeof(XTestKeyInfo)) == -1)
825		{
826			/*
827			 * an error occurred, return -1
828			 */
829			return(-1);
830		}
831		/*
832		 * set the delay to XTestSTROKE_DELAY_TIME
833		 */
834		delay = XTestSTROKE_DELAY_TIME;
835		/*
836		 * Check the delay.  If it is larger than will fit in the
837		 * key input action, send a delay input action.
838		 */
839		if(XTestCheckDelay(display, &delay) == -1)
840		{
841			/*
842			 * an error occurred, return -1
843			 */
844			return(-1);
845		}
846		/*
847		 * create a key/button-up input action header
848		 */
849		keyinfo.header = XTestPackDeviceID(device_id) |
850				 XTestKEY_ACTION |
851				 XTestKEY_UP;
852		/*
853		 * set the key/button code
854		 */
855		keyinfo.keycode = code;
856		/*
857		 * set the delay time
858		 */
859		keyinfo.delay_time = delay;
860		/*
861		 * pack the input action into a request to be sent to the
862		 * server when the request is full or XTestFlush is called
863		 */
864		return(XTestPackInputAction(display,
865					    (CARD8 *) &keyinfo,
866					    sizeof(XTestKeyInfo)));
867	default:
868		/*
869		 * invalid action value, return -1
870		 */
871		 return(-1);
872	}
873}
874
875/******************************************************************************
876 *
877 *	XTestMovePointer
878 *
879 *	Send input actions to the server to cause the server to think
880 *	that the mouse was moved as specified.
881 */
882int
883XTestMovePointer(
884Display		*display,
885int		device_id,
886unsigned long	delay[],
887int		x[],
888int		y[],
889unsigned int	count)
890{
891	/*
892	 * holds a motion input action to be filled out and sent to the server
893	 */
894	XTestMotionInfo	motioninfo;
895	/*
896	 * holds a jump input action to be filled out and sent to the server
897	 */
898	XTestJumpInfo	jumpinfo;
899	/*
900	 * loop index
901	 */
902	unsigned int	i;
903	/*
904	 * holds the change in x and y directions from the current x and y
905	 * coordinates
906	 */
907	int	dx;
908	int	dy;
909
910	/*
911	 * bounds check the device id
912	 */
913	if (device_id < 0 || device_id > XTestMAX_DEVICE_ID)
914	{
915		return(-1);
916	}
917	/*
918	 * if the count is 0, there is nothing to do.  return 0
919	 */
920	if (count == 0)
921	{
922		return(0);
923	}
924	/*
925	 * loop through the pointer motions, creating the appropriate
926	 * input actions for each motion
927	 */
928	for (i = 0; i < count; i++)
929	{
930		/*
931		 * Check the delay.  If it is larger than will fit in the
932		 * input action, send a delay input action.
933		 */
934		if(XTestCheckDelay(display, &(delay[i])) == -1)
935		{
936			/*
937			 * an error occurred, return -1
938			 */
939			return(-1);
940		}
941		/*
942		 * compute the change from the current x and y coordinates
943		 * to the new x and y coordinates
944		 */
945		dx = x[i] - current_x;
946		dy = y[i] - current_y;
947		/*
948		 * update the current x and y coordinates
949		 */
950		current_x = x[i];
951		current_y = y[i];
952		/*
953		 * If the pointer motion range is too large to fit into
954		 * a motion input action, then use a jump input action.
955		 * Otherwise, use a motion input action.
956		 */
957		 if ((dx > XTestMOTION_MAX) || (dx < XTestMOTION_MIN) ||
958		     (dy > XTestMOTION_MAX) || (dy < XTestMOTION_MIN))
959		{
960			/*
961			 * create a jump input action header
962			 */
963			jumpinfo.header = XTestPackDeviceID(device_id) |
964					  XTestJUMP_ACTION;
965			/*
966			 * set the x and y coordinates to jump to
967			 */
968			jumpinfo.jumpx = x[i];
969			jumpinfo.jumpy = y[i];
970			/*
971			 * set the delay time
972			 */
973			jumpinfo.delay_time = delay[i];
974			/*
975			 * pack the jump input action into a request to be
976			 * sent to the server when the request is full
977			 * or XTestFlush is called
978			 */
979			if (XTestPackInputAction(display,
980						 (CARD8 *) &jumpinfo,
981						 sizeof(XTestJumpInfo)) == -1)
982			{
983				/*
984				 * an error occurred, return -1
985				 */
986				return(-1);
987			}
988		}
989		else
990		{
991			/*
992			 * create a motion input action header
993			 */
994			motioninfo.header = XTestPackDeviceID(device_id) |
995					    XTestMOTION_ACTION;
996			/*
997			 * compute the motion data byte
998			 */
999			if (dx < 0)
1000			{
1001				motioninfo.header |= XTestX_NEGATIVE;
1002				dx = abs(dx);
1003			}
1004			if (dy < 0)
1005			{
1006				motioninfo.header |= XTestY_NEGATIVE;
1007				dy = abs(dy);
1008			}
1009			motioninfo.motion_data = XTestPackXMotionValue(dx);
1010			motioninfo.motion_data |= XTestPackYMotionValue(dy);
1011			/*
1012			 * set the delay time
1013			 */
1014			motioninfo.delay_time = delay[i];
1015			/*
1016			 * pack the motion input action into a request to be
1017			 * sent to the server when the request is full
1018			 * or XTestFlush is called
1019			 */
1020			if (XTestPackInputAction(display,
1021						 (CARD8 *) &motioninfo,
1022						 sizeof(XTestMotionInfo)) == -1)
1023			{
1024				/*
1025				 * an error occurred, return -1
1026				 */
1027				return(-1);
1028			}
1029		}
1030	}
1031	/*
1032	 * if you get here, everything went ok
1033	 */
1034	return(0);
1035}
1036
1037/******************************************************************************
1038 *
1039 *	XTestCheckDelay
1040 *
1041 *	Check the delay value at the passed-in address.  If it is larger than
1042 *	will fit in a normal input action, then send a delay input action.
1043 */
1044static int
1045XTestCheckDelay(
1046Display		*display,
1047unsigned long	*delay_addr)
1048{
1049	/*
1050	 * holds a delay input action to be filled out and sent to the server
1051	 */
1052	XTestDelayInfo	delayinfo;
1053
1054	/*
1055	 * if the delay value will fit in the input action,
1056	 * then there is no need for a delay input action
1057	 */
1058	if (*delay_addr <= XTestSHORT_DELAY_TIME)
1059	{
1060		return(0);
1061	}
1062	/*
1063	 * fill out a delay input action
1064	 */
1065	delayinfo.header = XTestPackDeviceID(XTestDELAY_DEVICE_ID);
1066	delayinfo.delay_time = *delay_addr;
1067	/*
1068	 * all of the delay time will be accounted for in the
1069	 * delay input action, so set the original delay value to 0
1070	 */
1071	*delay_addr = 0;
1072	/*
1073	 * pack the delay input action into a request to be sent to the
1074	 * server when the request is full or XTestFlush is called
1075	 */
1076	return(XTestPackInputAction(display,
1077				    (CARD8 *) &delayinfo,
1078				    sizeof(XTestDelayInfo)));
1079}
1080
1081/******************************************************************************
1082 *
1083 *	XTestPackInputAction
1084 *
1085 *	If the input action buffer is full or the number of input actions
1086 *	has reached the maximum that the server can handle at one time,
1087 *	then send the input actions to the server using XTestFakeInput.
1088 */
1089static int
1090XTestPackInputAction(
1091Display	*display,
1092CARD8	*action_addr,
1093int	action_size)
1094{
1095	/*
1096	 * loop index
1097	 */
1098	int	i;
1099	/*
1100	 * acknowledge flag
1101	 */
1102	int	ack_flag;
1103
1104	/*
1105	 * if we don't already know it, find out how many input actions
1106	 * the server can handle at one time
1107	 */
1108	if (action_array_size == 0)
1109	{
1110		if(XTestQueryInputSize(display, &action_array_size) == -1)
1111		{
1112			/*
1113			 * if an error, return -1
1114			 */
1115			return(-1);
1116		}
1117	}
1118	/*
1119	 * if the specified input action will fit in the the input
1120	 * action buffer and won't exceed the server's capacity, then
1121	 * put the input action into the input buffer
1122	 */
1123	if(((action_index + action_size) <= XTestMAX_ACTION_LIST_SIZE) &&
1124	   ((action_count + 1) < action_array_size))
1125	{
1126		/*
1127		 * copy the input action into the buffer
1128		 */
1129		for (i = 0; i < action_size; i++)
1130		{
1131			action_buf[action_index++] = *(action_addr++);
1132		}
1133		/*
1134		 * increment the action count
1135		 */
1136		action_count++;
1137		/*
1138		 * everything went ok, return 0
1139		 */
1140		return(0);
1141	}
1142	/*
1143	 * We have to write input actions to the server.  If the server's
1144	 * input action capacity will be reached, then ask for an
1145	 * acknowledge event when the server has processed all of the
1146	 * input actions.  Otherwise, an acknowledge event is not needed.
1147	 */
1148	if (action_count >= action_array_size)
1149	{
1150		ack_flag = XTestFAKE_ACK_REQUEST;
1151	}
1152	else
1153	{
1154		ack_flag = XTestFAKE_ACK_NOT_NEEDED;
1155	}
1156	/*
1157	 * write the input actions to the server
1158	 */
1159	if (XTestWriteInputActions(display,
1160				   (char *) &(action_buf[0]),
1161				   action_index,
1162				   ack_flag) == -1)
1163	{
1164		/*
1165		 * error, return -1
1166		 */
1167		return(-1);
1168	}
1169	/*
1170	 * copy the input action into the buffer
1171	 */
1172	for (i = 0; i < action_size; i++)
1173	{
1174		action_buf[action_index++] = *(action_addr++);
1175	}
1176	/*
1177	 * increment the action count
1178	 */
1179	action_count++;
1180	return(0);
1181}
1182
1183/******************************************************************************
1184 *
1185 *	XTestWriteInputActions
1186 *
1187 *	Send input actions to the server.
1188 */
1189static int
1190XTestWriteInputActions(
1191Display	*display,
1192char	*action_list_addr,
1193int	action_list_size,
1194int	ack_flag)
1195{
1196	/*
1197	 * Holds an event.  Used while waiting for an acknowledge event
1198	 */
1199	XEvent	event;
1200	/*
1201	 * points to XTestIdentifyMyEvent
1202	 */
1203	Bool	(*func_ptr)(Display *, XEvent *, XPointer);
1204
1205	/*
1206	 * write the input actions to the server
1207	 */
1208	if (XTestFakeInput(display,
1209			   action_list_addr,
1210			   action_list_size,
1211			   ack_flag) == -1)
1212	{
1213		/*
1214		 * if an error, return -1
1215		 */
1216		return(-1);
1217	}
1218	/*
1219	 * flush X's buffers to make sure that the server really gets
1220	 * the input actions
1221	 */
1222	XFlush(display);
1223	/*
1224	 * mark the input action buffer as empty
1225	 */
1226	action_index = 0;
1227	/*
1228	 * if we asked for an acknowledge event, then wait for it
1229	 */
1230	if (ack_flag == XTestFAKE_ACK_REQUEST)
1231	{
1232		/*
1233		 * point func_ptr at XTestIdentifyMyEvent
1234		 */
1235		func_ptr = XTestIdentifyMyEvent;
1236		/*
1237		 * Wait until the acknowledge event comes.  When the
1238		 * acknowledge event comes, it is removed from the event
1239		 * queue without disturbing any other events that might
1240		 * be in the queue.
1241		 */
1242		XIfEvent(display, &event, func_ptr, NULL);
1243		/*
1244		 * set the input action count back to 0
1245		 */
1246		action_count = 0;
1247	}
1248	/*
1249	 * if we got here, then everything is ok, return 0
1250	 */
1251	return(0);
1252}
1253
1254/******************************************************************************
1255 *
1256 *	XTestIdentifyMyEvent
1257 *
1258 *	This function is called by XIfEvent to look at an event and see if
1259 *	it is of XTestFakeAckType.
1260 */
1261static	Bool
1262XTestIdentifyMyEvent(
1263Display	*display,
1264/*
1265 * Holds the event that this routine is supposed to look at.
1266 */
1267XEvent	*event_ptr,
1268/*
1269 * this points to any user-specified arguments (ignored)
1270 */
1271char	*args)
1272{
1273	/*
1274	 * if the event if of the correct type, return the Bool True,
1275	 * otherwise return the Bool False.
1276	 */
1277	if (event_ptr->type == XTestFakeAckType)
1278	{
1279		return(True);
1280	}
1281	else
1282	{
1283		return(False);
1284	}
1285}
1286
1287/******************************************************************************
1288 *
1289 *	XTestFlush
1290 *
1291 *	Send any input actions in the input action buffer to the server.
1292 */
1293int
1294XTestFlush(Display *display)
1295{
1296	/*
1297	 * acknowledge flag
1298	 */
1299	int	ack_flag;
1300
1301	/*
1302	 * if there are no input actions in the input action buffer,
1303	 * then return 0
1304	 */
1305	if (action_index == 0)
1306	{
1307		return(0);
1308	}
1309	/*
1310	 * We have input actions to write to the server.  We will
1311	 * wait until the server has finished processing the input actions.
1312	 */
1313	ack_flag = XTestFAKE_ACK_REQUEST;
1314	/*
1315	 * write the input actions to the server
1316	 */
1317	return(XTestWriteInputActions(display,
1318				      (char *) &(action_buf[0]),
1319				      action_index,
1320				      ack_flag));
1321}
1322