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