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