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