| File: | XTestExt1.c |
| Location: | line 1170, column 30 |
| Description: | Assigned value is garbage or undefined |
| 1 | /* | |||
| 2 | * File: xtestext1lib.c | |||
| 3 | * | |||
| 4 | * This file contains the Xlib parts of the input synthesis extension | |||
| 5 | */ | |||
| 6 | ||||
| 7 | /* | |||
| 8 | ||||
| 9 | ||||
| 10 | Copyright 1986, 1987, 1988, 1998 The Open Group | |||
| 11 | ||||
| 12 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 13 | documentation for any purpose is hereby granted without fee, provided that | |||
| 14 | the above copyright notice appear in all copies and that both that | |||
| 15 | copyright notice and this permission notice appear in supporting | |||
| 16 | documentation. | |||
| 17 | ||||
| 18 | The above copyright notice and this permission notice shall be included in | |||
| 19 | all copies or substantial portions of the Software. | |||
| 20 | ||||
| 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| 24 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
| 25 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| 26 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| 27 | ||||
| 28 | Except as contained in this notice, the name of The Open Group shall not be | |||
| 29 | used in advertising or otherwise to promote the sale, use or other dealings | |||
| 30 | in this Software without prior written authorization from The Open Group. | |||
| 31 | ||||
| 32 | ||||
| 33 | Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation | |||
| 34 | ||||
| 35 | Permission to use, copy, modify, and distribute this | |||
| 36 | software and its documentation for any purpose and without | |||
| 37 | fee is hereby granted, provided that the above copyright | |||
| 38 | notice appear in all copies and that both that copyright | |||
| 39 | notice and this permission notice appear in supporting | |||
| 40 | documentation, and that the name of Hewlett-Packard not be used in | |||
| 41 | advertising or publicity pertaining to distribution of the | |||
| 42 | software without specific, written prior permission. | |||
| 43 | ||||
| 44 | Hewlett-Packard makes no representations about the | |||
| 45 | suitability of this software for any purpose. It is provided | |||
| 46 | "as is" without express or implied warranty. | |||
| 47 | ||||
| 48 | This software is not subject to any license of the American | |||
| 49 | Telephone and Telegraph Company or of the Regents of the | |||
| 50 | University of California. | |||
| 51 | ||||
| 52 | */ | |||
| 53 | ||||
| 54 | /****************************************************************************** | |||
| 55 | * include files | |||
| 56 | *****************************************************************************/ | |||
| 57 | ||||
| 58 | #ifdef HAVE_CONFIG_H1 | |||
| 59 | #include <config.h> | |||
| 60 | #endif | |||
| 61 | #include <stdio.h> | |||
| 62 | #include <X11/Xproto.h> | |||
| 63 | #include <X11/Xlibint.h> | |||
| 64 | #include <X11/extensions/xtestext1.h> | |||
| 65 | #include <X11/extensions/xtestext1proto.h> | |||
| 66 | ||||
| 67 | /****************************************************************************** | |||
| 68 | * variables | |||
| 69 | *****************************************************************************/ | |||
| 70 | ||||
| 71 | /* | |||
| 72 | * Holds the request type code for this extension. The request type code | |||
| 73 | * for this extension may vary depending on how many extensions are installed | |||
| 74 | * already, so the initial value given below will be added to the base request | |||
| 75 | * code that is acquired when this extension is installed. | |||
| 76 | */ | |||
| 77 | static int XTestReqCode = 0; | |||
| 78 | /* | |||
| 79 | * Holds the two event type codes for this extension. The event type codes | |||
| 80 | * for this extension may vary depending on how many extensions are installed | |||
| 81 | * already, so the initial values given below will be added to the base event | |||
| 82 | * code that is acquired when this extension is installed. | |||
| 83 | * | |||
| 84 | * These two variables must be available to programs that use this extension. | |||
| 85 | */ | |||
| 86 | int XTestInputActionType = 0; | |||
| 87 | int XTestFakeAckType = 1; | |||
| 88 | /* | |||
| 89 | * holds the current x and y coordinates for XTestMovePointer | |||
| 90 | */ | |||
| 91 | static int current_x = 0; | |||
| 92 | static int current_y = 0; | |||
| 93 | /* | |||
| 94 | * Holds input actions being accumulated until the input action buffer is | |||
| 95 | * full or until XTestFlush is called. | |||
| 96 | */ | |||
| 97 | static CARD8 action_buf[XTestMAX_ACTION_LIST_SIZE64]; | |||
| 98 | /* | |||
| 99 | * the index into the input action buffer | |||
| 100 | */ | |||
| 101 | static int action_index = 0; | |||
| 102 | /* | |||
| 103 | * the number of input actions that the server can handle at one time | |||
| 104 | */ | |||
| 105 | static unsigned long action_array_size = 0; | |||
| 106 | /* | |||
| 107 | * the current number of input actions | |||
| 108 | */ | |||
| 109 | static unsigned long action_count = 0; | |||
| 110 | ||||
| 111 | /****************************************************************************** | |||
| 112 | * function declarations | |||
| 113 | *****************************************************************************/ | |||
| 114 | ||||
| 115 | static int XTestWireToEvent(Display *dpy, XEvent *reTemp, xEvent *eventTemp); | |||
| 116 | static int XTestCheckExtInit(register Display *dpy); | |||
| 117 | static Boolint XTestIdentifyMyEvent(Display *display, XEvent *event_ptr, char *args); | |||
| 118 | static int XTestInitExtension(register Display *dpy); | |||
| 119 | static int XTestKeyOrButton(Display *display, int device_id, long unsigned int delay, unsigned int code, unsigned int action); | |||
| 120 | static int XTestCheckDelay(Display *display, long unsigned int *delay_addr); | |||
| 121 | static int XTestPackInputAction(Display *display, CARD8 *action_addr, int action_size); | |||
| 122 | static int XTestWriteInputActions(Display *display, char *action_list_addr, int action_list_size, int ack_flag); | |||
| 123 | ||||
| 124 | /****************************************************************************** | |||
| 125 | * | |||
| 126 | * XTestFakeInput | |||
| 127 | * | |||
| 128 | * Send a a request containing one or more input actions to be sent | |||
| 129 | * to the server by this extension. | |||
| 130 | */ | |||
| 131 | int | |||
| 132 | XTestFakeInput( | |||
| 133 | /* | |||
| 134 | * the connection to the X server | |||
| 135 | */ | |||
| 136 | register Display *dpy, | |||
| 137 | /* | |||
| 138 | * the address of a list of input actions to be sent to the server | |||
| 139 | */ | |||
| 140 | char *action_list_addr, | |||
| 141 | /* | |||
| 142 | * the size (in bytes) of the list of input actions | |||
| 143 | */ | |||
| 144 | int action_list_size, | |||
| 145 | /* | |||
| 146 | * specifies whether the server needs to send an event to indicate that its | |||
| 147 | * input action buffer is empty | |||
| 148 | */ | |||
| 149 | int ack_flag) | |||
| 150 | { | |||
| 151 | /* | |||
| 152 | * pointer to xTestFakeInputReq structure | |||
| 153 | */ | |||
| 154 | xTestFakeInputReq *req; | |||
| 155 | /* | |||
| 156 | * loop index | |||
| 157 | */ | |||
| 158 | int i; | |||
| 159 | ||||
| 160 | LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display )(dpy); | |||
| 161 | if ((XTestCheckExtInit(dpy) == -1) || | |||
| 162 | (action_list_size > XTestMAX_ACTION_LIST_SIZE64)) | |||
| 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)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(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)req = (xTestFakeInputReq *) _XGetRequest(dpy, 1, (64 + 8)); | |||
| 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_TestFakeInput1; | |||
| 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_SIZE64; 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)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
| 213 | SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy); | |||
| 214 | return(0); | |||
| 215 | } | |||
| 216 | } | |||
| 217 | ||||
| 218 | /****************************************************************************** | |||
| 219 | * | |||
| 220 | * XTestGetInput | |||
| 221 | * | |||
| 222 | * Request the server to begin putting user input actions into events | |||
| 223 | * to be sent to the client that called this function. | |||
| 224 | */ | |||
| 225 | int | |||
| 226 | XTestGetInput( | |||
| 227 | /* | |||
| 228 | * the connection to the X server | |||
| 229 | */ | |||
| 230 | register Display *dpy, | |||
| 231 | /* | |||
| 232 | * tells the server what to do with the user input actions | |||
| 233 | */ | |||
| 234 | int action_handling) | |||
| 235 | { | |||
| 236 | /* | |||
| 237 | * pointer to xTestGetInputReq structure | |||
| 238 | */ | |||
| 239 | xTestGetInputReq *req; | |||
| 240 | ||||
| 241 | LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display )(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)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(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)req = (xTestGetInputReq *) _XGetRequest(dpy, 2, 8); | |||
| 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_TestGetInput2; | |||
| 270 | /* | |||
| 271 | * set the action handling mode | |||
| 272 | */ | |||
| 273 | req->mode = action_handling; | |||
| 274 | UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
| 275 | SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy); | |||
| 276 | return(0); | |||
| 277 | } | |||
| 278 | } | |||
| 279 | ||||
| 280 | /****************************************************************************** | |||
| 281 | * | |||
| 282 | * XTestStopInput | |||
| 283 | * | |||
| 284 | * Tell the server to stop putting information about user input actions | |||
| 285 | * into events. | |||
| 286 | */ | |||
| 287 | int | |||
| 288 | XTestStopInput( | |||
| 289 | /* | |||
| 290 | * the connection to the X server | |||
| 291 | */ | |||
| 292 | register Display *dpy) | |||
| 293 | { | |||
| 294 | /* | |||
| 295 | * pointer to xTestStopInputReq structure | |||
| 296 | */ | |||
| 297 | xTestStopInputReq *req; | |||
| 298 | ||||
| 299 | LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display )(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)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(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)req = (xTestStopInputReq *) _XGetRequest(dpy, 3, 4); | |||
| 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_TestStopInput3; | |||
| 328 | UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
| 329 | SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy); | |||
| 330 | return(0); | |||
| 331 | } | |||
| 332 | } | |||
| 333 | ||||
| 334 | /****************************************************************************** | |||
| 335 | * | |||
| 336 | * XTestReset | |||
| 337 | * | |||
| 338 | * Tell the server to set everything having to do with this extension | |||
| 339 | * back to its initial state. | |||
| 340 | */ | |||
| 341 | int | |||
| 342 | XTestReset( | |||
| 343 | /* | |||
| 344 | * the connection to the X server | |||
| 345 | */ | |||
| 346 | register Display *dpy) | |||
| 347 | { | |||
| 348 | /* | |||
| 349 | * pointer to xTestReset structure | |||
| 350 | */ | |||
| 351 | xTestResetReq *req; | |||
| 352 | ||||
| 353 | LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display )(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)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(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)req = (xTestResetReq *) _XGetRequest(dpy, 4, 4); | |||
| 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_TestReset4; | |||
| 382 | UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
| 383 | SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy); | |||
| 384 | return(0); | |||
| 385 | } | |||
| 386 | } | |||
| 387 | ||||
| 388 | /****************************************************************************** | |||
| 389 | * | |||
| 390 | * XTestQueryInputSize | |||
| 391 | * | |||
| 392 | * Returns the number of input actions in the server's input action buffer. | |||
| 393 | */ | |||
| 394 | int | |||
| 395 | XTestQueryInputSize( | |||
| 396 | /* | |||
| 397 | * the connection to the X server | |||
| 398 | */ | |||
| 399 | register Display *dpy, | |||
| 400 | /* | |||
| 401 | * the address of the place to put the number of input actions in the | |||
| 402 | * server's input action buffer | |||
| 403 | */ | |||
| 404 | unsigned long *size_return) | |||
| 405 | { | |||
| 406 | /* | |||
| 407 | * pointer to xTestQueryInputSize structure | |||
| 408 | */ | |||
| 409 | xTestQueryInputSizeReq *req; | |||
| 410 | /* | |||
| 411 | * pointer to xTestQueryInputSize structure | |||
| 412 | */ | |||
| 413 | xTestQueryInputSizeReply rep; | |||
| 414 | ||||
| 415 | LockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->lock_display )(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)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(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)req = (xTestQueryInputSizeReq *) _XGetRequest(dpy, 5, 4); | |||
| 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_TestQueryInputSize5; | |||
| 444 | /* | |||
| 445 | * get a reply from the server | |||
| 446 | */ | |||
| 447 | (void) _XReply (dpy, (xReply *) &rep, 0, xTrue1); | |||
| 448 | /* | |||
| 449 | * put the size in the caller's variable | |||
| 450 | */ | |||
| 451 | *size_return = (unsigned long) rep.size_return; | |||
| 452 | UnlockDisplay(dpy)if ((dpy)->lock_fns) (*(dpy)->lock_fns->unlock_display )(dpy); | |||
| 453 | SyncHandle()if (dpy->synchandler) (*dpy->synchandler)(dpy); | |||
| 454 | return(0); | |||
| 455 | } | |||
| 456 | } | |||
| 457 | ||||
| 458 | /****************************************************************************** | |||
| 459 | * | |||
| 460 | * XTestCheckExtInit | |||
| 461 | * | |||
| 462 | * Check to see if the XTest extension is installed in the server. | |||
| 463 | */ | |||
| 464 | static int | |||
| 465 | XTestCheckExtInit( | |||
| 466 | /* | |||
| 467 | * the connection to the X server | |||
| 468 | */ | |||
| 469 | register Display *dpy) | |||
| 470 | { | |||
| 471 | /* | |||
| 472 | * if the extension has not been initialized, then do so | |||
| 473 | */ | |||
| 474 | if (!XTestReqCode) | |||
| 475 | { | |||
| 476 | return(XTestInitExtension(dpy)); | |||
| 477 | } | |||
| 478 | return(0); | |||
| 479 | } | |||
| 480 | ||||
| 481 | /****************************************************************************** | |||
| 482 | * | |||
| 483 | * XTestInitExtension | |||
| 484 | * | |||
| 485 | * Attempt to initialize this extension in the server. Return 0 if it | |||
| 486 | * succeeds, -1 if it does not succeed. | |||
| 487 | */ | |||
| 488 | static int | |||
| 489 | XTestInitExtension( | |||
| 490 | /* | |||
| 491 | * the connection to the X server | |||
| 492 | */ | |||
| 493 | register Display *dpy) | |||
| 494 | { | |||
| 495 | /* | |||
| 496 | * loop index | |||
| 497 | */ | |||
| 498 | int i; | |||
| 499 | /* | |||
| 500 | * return value from XInitExtension | |||
| 501 | */ | |||
| 502 | XExtCodes *ret; | |||
| 503 | ||||
| 504 | /* | |||
| 505 | * attempt to initialize the extension | |||
| 506 | */ | |||
| 507 | ret = XInitExtension(dpy, XTestEXTENSION_NAME"XTestExtension1"); | |||
| 508 | /* | |||
| 509 | * if the initialize failed, return -1 | |||
| 510 | */ | |||
| 511 | if (ret == NULL((void*)0)) | |||
| 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_COUNT2; i++) | |||
| 525 | { | |||
| 526 | XESetWireToEvent(dpy, | |||
| 527 | ret->first_event+i, | |||
| 528 | XTestWireToEvent); | |||
| 529 | } | |||
| 530 | /* | |||
| 531 | * compute the event type codes for the events | |||
| 532 | * in this extension | |||
| 533 | */ | |||
| 534 | XTestInputActionType += ret->first_event; | |||
| 535 | XTestFakeAckType += ret->first_event; | |||
| 536 | /* | |||
| 537 | * everything worked ok | |||
| 538 | */ | |||
| 539 | return(0); | |||
| 540 | } | |||
| 541 | ||||
| 542 | /****************************************************************************** | |||
| 543 | * | |||
| 544 | * XTestWireToEvent | |||
| 545 | * | |||
| 546 | * Handle XTest extension events. | |||
| 547 | * Reformat a wire event into an XEvent structure of the right type. | |||
| 548 | */ | |||
| 549 | static Boolint | |||
| 550 | XTestWireToEvent( | |||
| 551 | /* | |||
| 552 | * the connection to the X server | |||
| 553 | */ | |||
| 554 | Display *dpy, | |||
| 555 | /* | |||
| 556 | * a pointer to where a host formatted event should be stored | |||
| 557 | * with the information copied to it | |||
| 558 | */ | |||
| 559 | XEvent *reTemp, | |||
| 560 | /* | |||
| 561 | * a pointer to the wire event | |||
| 562 | */ | |||
| 563 | xEvent *eventTemp) | |||
| 564 | { | |||
| 565 | XTestInputActionEvent *re = (XTestInputActionEvent *) reTemp; | |||
| 566 | xTestInputActionEvent *event = (xTestInputActionEvent *) eventTemp; | |||
| 567 | ||||
| 568 | /* | |||
| 569 | * loop index | |||
| 570 | */ | |||
| 571 | int i; | |||
| 572 | /* | |||
| 573 | * pointer to where the input actions go in the host format event | |||
| 574 | */ | |||
| 575 | CARD8 *to; | |||
| 576 | /* | |||
| 577 | * pointer to the input actions in the wire event | |||
| 578 | */ | |||
| 579 | CARD8 *from; | |||
| 580 | ||||
| 581 | /* | |||
| 582 | * Copy the type of the wire event to the new event. | |||
| 583 | * This will work for either event type because the type, | |||
| 584 | * display, and window fields in the events have to be the same. | |||
| 585 | */ | |||
| 586 | re->type = event->type; | |||
| 587 | /* | |||
| 588 | * set the display parameter in case it is needed (by who?) | |||
| 589 | */ | |||
| 590 | re->display = dpy; | |||
| 591 | if (re->type == XTestInputActionType) | |||
| 592 | { | |||
| 593 | /* | |||
| 594 | * point at the first byte of input actions in the wire event | |||
| 595 | */ | |||
| 596 | from = &(event->actions[0]); | |||
| 597 | /* | |||
| 598 | * point at where the input action bytes go in the new event | |||
| 599 | */ | |||
| 600 | to = &(re->actions[0]); | |||
| 601 | /* | |||
| 602 | * copy the input action bytes from the wire event to | |||
| 603 | * the new event | |||
| 604 | */ | |||
| 605 | for (i = 0; i < XTestACTIONS_SIZE28; 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"XTestExtension1"); | |||
| 621 | exit (1); | |||
| 622 | } | |||
| 623 | return 1; | |||
| 624 | } | |||
| 625 | ||||
| 626 | /****************************************************************************** | |||
| 627 | * | |||
| 628 | * XTestPressKey | |||
| 629 | * | |||
| 630 | * Send input actions to the server to cause the server to think | |||
| 631 | * that the specified key on the keyboard was moved as specified. | |||
| 632 | */ | |||
| 633 | int | |||
| 634 | XTestPressKey( | |||
| 635 | Display *display, | |||
| 636 | int device_id, | |||
| 637 | unsigned long delay, | |||
| 638 | unsigned int keycode, | |||
| 639 | unsigned int key_action) | |||
| 640 | { | |||
| 641 | /* | |||
| 642 | * bounds check the key code | |||
| 643 | */ | |||
| 644 | if (keycode < 8 || keycode > 255) | |||
| 645 | { | |||
| 646 | return(-1); | |||
| 647 | } | |||
| 648 | /* | |||
| 649 | * use the commmon key/button handling routine | |||
| 650 | */ | |||
| 651 | return(XTestKeyOrButton(display, | |||
| 652 | device_id, | |||
| 653 | delay, | |||
| 654 | keycode, | |||
| 655 | key_action)); | |||
| 656 | } | |||
| 657 | ||||
| 658 | /****************************************************************************** | |||
| 659 | * | |||
| 660 | * XTestPressButton | |||
| 661 | * | |||
| 662 | * Send input actions to the server to cause the server to think | |||
| 663 | * that the specified button on the mouse was moved as specified. | |||
| 664 | */ | |||
| 665 | int | |||
| 666 | XTestPressButton( | |||
| 667 | Display *display, | |||
| 668 | int device_id, | |||
| 669 | unsigned long delay, | |||
| 670 | unsigned int button_number, | |||
| 671 | unsigned int button_action) | |||
| 672 | { | |||
| 673 | /* | |||
| 674 | * bounds check the button number | |||
| 675 | */ | |||
| 676 | if (button_number > 7) | |||
| 677 | { | |||
| 678 | return(-1); | |||
| 679 | } | |||
| 680 | /* | |||
| 681 | * use the commmon key/button handling routine | |||
| 682 | */ | |||
| 683 | return(XTestKeyOrButton(display, | |||
| 684 | device_id, | |||
| 685 | delay, | |||
| 686 | button_number, | |||
| 687 | button_action)); | |||
| 688 | } | |||
| 689 | ||||
| 690 | /****************************************************************************** | |||
| 691 | * | |||
| 692 | * XTestKeyOrButton | |||
| 693 | * | |||
| 694 | * Send input actions to the server to cause the server to think | |||
| 695 | * that the specified key/button was moved as specified. | |||
| 696 | */ | |||
| 697 | static int | |||
| 698 | XTestKeyOrButton( | |||
| 699 | Display *display, | |||
| 700 | int device_id, | |||
| 701 | unsigned long delay, | |||
| 702 | unsigned int code, | |||
| 703 | unsigned int action) | |||
| 704 | { | |||
| 705 | /* | |||
| 706 | * holds a key input action to be filled out and sent to the server | |||
| 707 | */ | |||
| 708 | XTestKeyInfo keyinfo; | |||
| 709 | ||||
| 710 | /* | |||
| 711 | * bounds check the device id | |||
| 712 | */ | |||
| 713 | if (device_id < 0 || device_id > XTestMAX_DEVICE_ID0x0f) | |||
| 714 | { | |||
| 715 | return(-1); | |||
| 716 | } | |||
| 717 | /* | |||
| 718 | * fill out the key input action(s) as appropriate | |||
| 719 | */ | |||
| 720 | switch(action) | |||
| 721 | { | |||
| 722 | case XTestPRESS1 << 0: | |||
| 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)(((device_id) & 0x0f) << 4) | | |||
| 738 | XTestKEY_ACTION1 | | |||
| 739 | XTestKEY_DOWN0x00; | |||
| 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 XTestRELEASE1 << 1: | |||
| 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)(((device_id) & 0x0f) << 4) | | |||
| 771 | XTestKEY_ACTION1 | | |||
| 772 | XTestKEY_UP0x04; | |||
| 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 XTestSTROKE1 << 2: | |||
| 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)(((device_id) & 0x0f) << 4) | | |||
| 804 | XTestKEY_ACTION1 | | |||
| 805 | XTestKEY_DOWN0x00; | |||
| 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_TIME10; | |||
| 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)(((device_id) & 0x0f) << 4) | | |||
| 846 | XTestKEY_ACTION1 | | |||
| 847 | XTestKEY_UP0x04; | |||
| 848 | /* | |||
| 849 | * set the key/button code | |||
| 850 | */ | |||
| 851 | keyinfo.keycode = code; | |||
| 852 | /* | |||
| 853 | * set the delay time | |||
| 854 | */ | |||
| 855 | keyinfo.delay_time = delay; | |||
| 856 | /* | |||
| 857 | * pack the input action into a request to be sent to the | |||
| 858 | * server when the request is full or XTestFlush is called | |||
| 859 | */ | |||
| 860 | return(XTestPackInputAction(display, | |||
| 861 | (CARD8 *) &keyinfo, | |||
| 862 | sizeof(XTestKeyInfo))); | |||
| 863 | default: | |||
| 864 | /* | |||
| 865 | * invalid action value, return -1 | |||
| 866 | */ | |||
| 867 | return(-1); | |||
| 868 | } | |||
| 869 | } | |||
| 870 | ||||
| 871 | /****************************************************************************** | |||
| 872 | * | |||
| 873 | * XTestMovePointer | |||
| 874 | * | |||
| 875 | * Send input actions to the server to cause the server to think | |||
| 876 | * that the mouse was moved as specified. | |||
| 877 | */ | |||
| 878 | int | |||
| 879 | XTestMovePointer( | |||
| 880 | Display *display, | |||
| 881 | int device_id, | |||
| 882 | unsigned long delay[], | |||
| 883 | int x[], | |||
| 884 | int y[], | |||
| 885 | unsigned int count) | |||
| 886 | { | |||
| 887 | /* | |||
| 888 | * holds a motion input action to be filled out and sent to the server | |||
| 889 | */ | |||
| 890 | XTestMotionInfo motioninfo; | |||
| 891 | /* | |||
| 892 | * holds a jump input action to be filled out and sent to the server | |||
| 893 | */ | |||
| 894 | XTestJumpInfo jumpinfo; | |||
| 895 | /* | |||
| 896 | * loop index | |||
| 897 | */ | |||
| 898 | unsigned int i; | |||
| 899 | /* | |||
| 900 | * holds the change in x and y directions from the current x and y | |||
| 901 | * coordinates | |||
| 902 | */ | |||
| 903 | int dx; | |||
| 904 | int dy; | |||
| 905 | ||||
| 906 | /* | |||
| 907 | * bounds check the device id | |||
| 908 | */ | |||
| 909 | if (device_id < 0 || device_id > XTestMAX_DEVICE_ID0x0f) | |||
| ||||
| 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_MAX15) || (dx < XTestMOTION_MIN-15) || | |||
| 954 | (dy > XTestMOTION_MAX15) || (dy < XTestMOTION_MIN-15)) | |||
| 955 | { | |||
| 956 | /* | |||
| 957 | * create a jump input action header | |||
| 958 | */ | |||
| 959 | jumpinfo.header = XTestPackDeviceID(device_id)(((device_id) & 0x0f) << 4) | | |||
| 960 | XTestJUMP_ACTION3; | |||
| 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)(((device_id) & 0x0f) << 4) | | |||
| 991 | XTestMOTION_ACTION2; | |||
| 992 | /* | |||
| 993 | * compute the motion data byte | |||
| 994 | */ | |||
| 995 | if (dx < 0) | |||
| 996 | { | |||
| 997 | motioninfo.header |= XTestX_NEGATIVE0x04; | |||
| 998 | dx = abs(dx); | |||
| 999 | } | |||
| 1000 | if (dy < 0) | |||
| 1001 | { | |||
| 1002 | motioninfo.header |= XTestY_NEGATIVE0x08; | |||
| 1003 | dy = abs(dy); | |||
| 1004 | } | |||
| 1005 | motioninfo.motion_data = XTestPackXMotionValue(dx)((dx) & 0x0f); | |||
| 1006 | motioninfo.motion_data |= XTestPackYMotionValue(dy)(((dy) << 4) & 0xf0); | |||
| 1007 | /* | |||
| 1008 | * set the delay time | |||
| 1009 | */ | |||
| 1010 | motioninfo.delay_time = delay[i]; | |||
| 1011 | /* | |||
| 1012 | * pack the motion input action into a request to be | |||
| 1013 | * sent to the server when the request is full | |||
| 1014 | * or XTestFlush is called | |||
| 1015 | */ | |||
| 1016 | if (XTestPackInputAction(display, | |||
| 1017 | (CARD8 *) &motioninfo, | |||
| 1018 | sizeof(XTestMotionInfo)) == -1) | |||
| 1019 | { | |||
| 1020 | /* | |||
| 1021 | * an error occurred, return -1 | |||
| 1022 | */ | |||
| 1023 | return(-1); | |||
| 1024 | } | |||
| 1025 | } | |||
| 1026 | } | |||
| 1027 | /* | |||
| 1028 | * if you get here, everything went ok | |||
| 1029 | */ | |||
| 1030 | return(0); | |||
| 1031 | } | |||
| 1032 | ||||
| 1033 | /****************************************************************************** | |||
| 1034 | * | |||
| 1035 | * XTestCheckDelay | |||
| 1036 | * | |||
| 1037 | * Check the delay value at the passed-in address. If it is larger than | |||
| 1038 | * will fit in a normal input action, then send a delay input action. | |||
| 1039 | */ | |||
| 1040 | static int | |||
| 1041 | XTestCheckDelay( | |||
| 1042 | Display *display, | |||
| 1043 | unsigned long *delay_addr) | |||
| 1044 | { | |||
| 1045 | /* | |||
| 1046 | * holds a delay input action to be filled out and sent to the server | |||
| 1047 | */ | |||
| 1048 | XTestDelayInfo delayinfo; | |||
| 1049 | ||||
| 1050 | /* | |||
| 1051 | * if the delay value will fit in the input action, | |||
| 1052 | * then there is no need for a delay input action | |||
| 1053 | */ | |||
| 1054 | if (*delay_addr <= XTestSHORT_DELAY_TIME0xffff) | |||
| 1055 | { | |||
| 1056 | return(0); | |||
| 1057 | } | |||
| 1058 | /* | |||
| 1059 | * fill out a delay input action | |||
| 1060 | */ | |||
| 1061 | delayinfo.header = XTestPackDeviceID(XTestDELAY_DEVICE_ID)(((0x0f) & 0x0f) << 4); | |||
| 1062 | delayinfo.delay_time = *delay_addr; | |||
| 1063 | /* | |||
| 1064 | * all of the delay time will be accounted for in the | |||
| 1065 | * delay input action, so set the original delay value to 0 | |||
| 1066 | */ | |||
| 1067 | *delay_addr = 0; | |||
| 1068 | /* | |||
| 1069 | * pack the delay input action into a request to be sent to the | |||
| 1070 | * server when the request is full or XTestFlush is called | |||
| 1071 | */ | |||
| 1072 | return(XTestPackInputAction(display, | |||
| 1073 | (CARD8 *) &delayinfo, | |||
| 1074 | sizeof(XTestDelayInfo))); | |||
| 1075 | } | |||
| 1076 | ||||
| 1077 | /****************************************************************************** | |||
| 1078 | * | |||
| 1079 | * XTestPackInputAction | |||
| 1080 | * | |||
| 1081 | * If the input action buffer is full or the number of input actions | |||
| 1082 | * has reached the maximum that the server can handle at one time, | |||
| 1083 | * then send the input actions to the server using XTestFakeInput. | |||
| 1084 | */ | |||
| 1085 | static int | |||
| 1086 | XTestPackInputAction( | |||
| 1087 | Display *display, | |||
| 1088 | CARD8 *action_addr, | |||
| 1089 | int action_size) | |||
| 1090 | { | |||
| 1091 | /* | |||
| 1092 | * loop index | |||
| 1093 | */ | |||
| 1094 | int i; | |||
| 1095 | /* | |||
| 1096 | * acknowledge flag | |||
| 1097 | */ | |||
| 1098 | int ack_flag; | |||
| 1099 | ||||
| 1100 | /* | |||
| 1101 | * if we don't already know it, find out how many input actions | |||
| 1102 | * the server can handle at one time | |||
| 1103 | */ | |||
| 1104 | if (action_array_size == 0) | |||
| 1105 | { | |||
| 1106 | if(XTestQueryInputSize(display, &action_array_size) == -1) | |||
| 1107 | { | |||
| 1108 | /* | |||
| 1109 | * if an error, return -1 | |||
| 1110 | */ | |||
| 1111 | return(-1); | |||
| 1112 | } | |||
| 1113 | } | |||
| 1114 | /* | |||
| 1115 | * if the specified input action will fit in the the input | |||
| 1116 | * action buffer and won't exceed the server's capacity, then | |||
| 1117 | * put the input action into the input buffer | |||
| 1118 | */ | |||
| 1119 | if(((action_index + action_size) <= XTestMAX_ACTION_LIST_SIZE64) && | |||
| 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_REQUEST1; | |||
| 1147 | } | |||
| 1148 | else | |||
| 1149 | { | |||
| 1150 | ack_flag = XTestFAKE_ACK_NOT_NEEDED0; | |||
| 1151 | } | |||
| 1152 | /* | |||
| 1153 | * write the input actions to the server | |||
| 1154 | */ | |||
| 1155 | if (XTestWriteInputActions(display, | |||
| 1156 | (char *) &(action_buf[0]), | |||
| 1157 | action_index, | |||
| 1158 | ack_flag) == -1) | |||
| 1159 | { | |||
| 1160 | /* | |||
| 1161 | * error, return -1 | |||
| 1162 | */ | |||
| 1163 | return(-1); | |||
| 1164 | } | |||
| 1165 | /* | |||
| 1166 | * copy the input action into the buffer | |||
| 1167 | */ | |||
| 1168 | for (i = 0; i < action_size; i++) | |||
| 1169 | { | |||
| 1170 | action_buf[action_index++] = *(action_addr++); | |||
| ||||
| 1171 | } | |||
| 1172 | /* | |||
| 1173 | * increment the action count | |||
| 1174 | */ | |||
| 1175 | action_count++; | |||
| 1176 | return(0); | |||
| 1177 | } | |||
| 1178 | ||||
| 1179 | /****************************************************************************** | |||
| 1180 | * | |||
| 1181 | * XTestWriteInputActions | |||
| 1182 | * | |||
| 1183 | * Send input actions to the server. | |||
| 1184 | */ | |||
| 1185 | static int | |||
| 1186 | XTestWriteInputActions( | |||
| 1187 | Display *display, | |||
| 1188 | char *action_list_addr, | |||
| 1189 | int action_list_size, | |||
| 1190 | int ack_flag) | |||
| 1191 | { | |||
| 1192 | /* | |||
| 1193 | * Holds an event. Used while waiting for an acknowledge event | |||
| 1194 | */ | |||
| 1195 | XEvent event; | |||
| 1196 | /* | |||
| 1197 | * points to XTestIdentifyMyEvent | |||
| 1198 | */ | |||
| 1199 | Boolint (*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_REQUEST1) | |||
| 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((void*)0)); | |||
| 1239 | /* | |||
| 1240 | * set the input action count back to 0 | |||
| 1241 | */ | |||
| 1242 | action_count = 0; | |||
| 1243 | } | |||
| 1244 | /* | |||
| 1245 | * if we got here, then everything is ok, return 0 | |||
| 1246 | */ | |||
| 1247 | return(0); | |||
| 1248 | } | |||
| 1249 | ||||
| 1250 | /****************************************************************************** | |||
| 1251 | * | |||
| 1252 | * XTestIdentifyMyEvent | |||
| 1253 | * | |||
| 1254 | * This function is called by XIfEvent to look at an event and see if | |||
| 1255 | * it is of XTestFakeAckType. | |||
| 1256 | */ | |||
| 1257 | static Boolint | |||
| 1258 | XTestIdentifyMyEvent( | |||
| 1259 | Display *display, | |||
| 1260 | /* | |||
| 1261 | * Holds the event that this routine is supposed to look at. | |||
| 1262 | */ | |||
| 1263 | XEvent *event_ptr, | |||
| 1264 | /* | |||
| 1265 | * this points to any user-specified arguments (ignored) | |||
| 1266 | */ | |||
| 1267 | char *args) | |||
| 1268 | { | |||
| 1269 | /* | |||
| 1270 | * if the event if of the correct type, return the Bool True, | |||
| 1271 | * otherwise return the Bool False. | |||
| 1272 | */ | |||
| 1273 | if (event_ptr->type == XTestFakeAckType) | |||
| 1274 | { | |||
| 1275 | return(True1); | |||
| 1276 | } | |||
| 1277 | else | |||
| 1278 | { | |||
| 1279 | return(False0); | |||
| 1280 | } | |||
| 1281 | } | |||
| 1282 | ||||
| 1283 | /****************************************************************************** | |||
| 1284 | * | |||
| 1285 | * XTestFlush | |||
| 1286 | * | |||
| 1287 | * Send any input actions in the input action buffer to the server. | |||
| 1288 | */ | |||
| 1289 | int | |||
| 1290 | XTestFlush(Display *display) | |||
| 1291 | { | |||
| 1292 | /* | |||
| 1293 | * acknowledge flag | |||
| 1294 | */ | |||
| 1295 | int ack_flag; | |||
| 1296 | ||||
| 1297 | /* | |||
| 1298 | * if there are no input actions in the input action buffer, | |||
| 1299 | * then return 0 | |||
| 1300 | */ | |||
| 1301 | if (action_index == 0) | |||
| 1302 | { | |||
| 1303 | return(0); | |||
| 1304 | } | |||
| 1305 | /* | |||
| 1306 | * We have input actions to write to the server. We will | |||
| 1307 | * wait until the server has finished processing the input actions. | |||
| 1308 | */ | |||
| 1309 | ack_flag = XTestFAKE_ACK_REQUEST1; | |||
| 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 | } |