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