c12c22306350c0f35e248e1e95ec36bc70f0ccad
[framework/uifw/xorg/lib/libxext.git] / src / XTestExt1.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }