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