1 /*
2  *	File:  xtestext1lib.c
3  *
4  *	This file contains the Xlib parts of the input synthesis extension
5  */
6 
7 /*
8 
9 
10 Copyright 1986, 1987, 1988, 1998   The Open Group
11 
12 Permission to use, copy, modify, distribute, and sell this software and its
13 documentation for any purpose is hereby granted without fee, provided that
14 the above copyright notice appear in all copies and that both that
15 copyright notice and this permission notice appear in supporting
16 documentation.
17 
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20 
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 Except as contained in this notice, the name of The Open Group shall not be
29 used in advertising or otherwise to promote the sale, use or other dealings
30 in this Software without prior written authorization from The Open Group.
31 
32 
33 Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
34 
35 Permission to use, copy, modify, and distribute this
36 software and its documentation for any purpose and without
37 fee is hereby granted, provided that the above copyright
38 notice appear in all copies and that both that copyright
39 notice and this permission notice appear in supporting
40 documentation, and that the name of Hewlett-Packard not be used in
41 advertising or publicity pertaining to distribution of the
42 software without specific, written prior permission.
43 
44 Hewlett-Packard makes no representations about the
45 suitability of this software for any purpose.  It is provided
46 "as is" without express or implied warranty.
47 
48 This software is not subject to any license of the American
49 Telephone and Telegraph Company or of the Regents of the
50 University 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  */
77 static 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  */
86 int			XTestInputActionType = 0;
87 int			XTestFakeAckType   = 1;
88 /*
89  * holds the current x and y coordinates for XTestMovePointer
90  */
91 static int	current_x = 0;
92 static 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  */
97 static CARD8		action_buf[XTestMAX_ACTION_LIST_SIZE];
98 /*
99  * the index into the input action buffer
100  */
101 static int		action_index = 0;
102 /*
103  * the number of input actions that the server can handle at one time
104  */
105 static unsigned long	action_array_size = 0;
106 /*
107  * the current number of input actions
108  */
109 static unsigned long	action_count = 0;
110 
111 /******************************************************************************
112  * function declarations
113  *****************************************************************************/
114 
115 static int	XTestWireToEvent(Display *dpy, XEvent *reTemp, xEvent *eventTemp);
116 static int	XTestCheckExtInit(register Display *dpy);
117 static Bool	XTestIdentifyMyEvent(Display *display, XEvent *event_ptr, char *args);
118 static int	XTestInitExtension(register Display *dpy);
119 static int	XTestKeyOrButton(Display *display, int device_id, long unsigned int delay, unsigned int code, unsigned int action);
120 static int	XTestCheckDelay(Display *display, long unsigned int *delay_addr);
121 static int	XTestPackInputAction(Display *display, CARD8 *action_addr, int action_size);
122 static 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  */
131 int
XTestFakeInput(register Display * dpy,char * action_list_addr,int action_list_size,int ack_flag)132 XTestFakeInput(
133 /*
134  * the connection to the X server
135  */
136 register Display	*dpy,
137 /*
138  * the address of a list of input actions to be sent to the server
139  */
140 char			*action_list_addr,
141 /*
142  * the size (in bytes) of the list of input actions
143  */
144 int			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  */
149 int			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  */
225 int
XTestGetInput(register Display * dpy,int action_handling)226 XTestGetInput(
227 /*
228  * the connection to the X server
229  */
230 register Display	*dpy,
231 /*
232  * tells the server what to do with the user input actions
233  */
234 int			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  */
287 int
XTestStopInput(register Display * dpy)288 XTestStopInput(
289 /*
290  * the connection to the X server
291  */
292 register 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  */
341 int
XTestReset(register Display * dpy)342 XTestReset(
343 /*
344  * the connection to the X server
345  */
346 register 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  */
394 int
XTestQueryInputSize(register Display * dpy,unsigned long * size_return)395 XTestQueryInputSize(
396 /*
397  * the connection to the X server
398  */
399 register 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  */
404 unsigned 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  */
464 static int
XTestCheckExtInit(register Display * dpy)465 XTestCheckExtInit(
466 /*
467  * the connection to the X server
468  */
469 register 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  */
488 static int
XTestInitExtension(register Display * dpy)489 XTestInitExtension(
490 /*
491  * the connection to the X server
492  */
493 register 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  */
549 static Bool
XTestWireToEvent(Display * dpy,XEvent * reTemp,xEvent * eventTemp)550 XTestWireToEvent(
551 /*
552  * the connection to the X server
553  */
554 Display	*dpy,
555 /*
556  * a pointer to where a host formatted event should be stored
557  * with the information copied to it
558  */
559 XEvent	*reTemp,
560 /*
561  * a pointer to the wire event
562  */
563 xEvent	*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  */
633 int
XTestPressKey(Display * display,int device_id,unsigned long delay,unsigned int keycode,unsigned int key_action)634 XTestPressKey(
635 Display		*display,
636 int		device_id,
637 unsigned long	delay,
638 unsigned int	keycode,
639 unsigned 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 commmon 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  */
665 int
XTestPressButton(Display * display,int device_id,unsigned long delay,unsigned int button_number,unsigned int button_action)666 XTestPressButton(
667 Display		*display,
668 int		device_id,
669 unsigned long	delay,
670 unsigned int	button_number,
671 unsigned 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 commmon 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  */
697 static int
XTestKeyOrButton(Display * display,int device_id,unsigned long delay,unsigned int code,unsigned int action)698 XTestKeyOrButton(
699 Display		*display,
700 int		device_id,
701 unsigned long	delay,
702 unsigned int	code,
703 unsigned 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  */
878 int
XTestMovePointer(Display * display,int device_id,unsigned long delay[],int x[],int y[],unsigned int count)879 XTestMovePointer(
880 Display		*display,
881 int		device_id,
882 unsigned long	delay[],
883 int		x[],
884 int		y[],
885 unsigned 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  */
1040 static int
XTestCheckDelay(Display * display,unsigned long * delay_addr)1041 XTestCheckDelay(
1042 Display		*display,
1043 unsigned 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  */
1085 static int
XTestPackInputAction(Display * display,CARD8 * action_addr,int action_size)1086 XTestPackInputAction(
1087 Display	*display,
1088 CARD8	*action_addr,
1089 int	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  */
1185 static int
XTestWriteInputActions(Display * display,char * action_list_addr,int action_list_size,int ack_flag)1186 XTestWriteInputActions(
1187 Display	*display,
1188 char	*action_list_addr,
1189 int	action_list_size,
1190 int	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  */
1257 static	Bool
XTestIdentifyMyEvent(Display * display,XEvent * event_ptr,char * args)1258 XTestIdentifyMyEvent(
1259 Display	*display,
1260 /*
1261  * Holds the event that this routine is supposed to look at.
1262  */
1263 XEvent	*event_ptr,
1264 /*
1265  * this points to any user-specified arguments (ignored)
1266  */
1267 char	*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  */
1289 int
XTestFlush(Display * display)1290 XTestFlush(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