XTest.c revision 25b89263
1/* 2Copyright 1990, 1991 by UniSoft Group Limited 3*/ 4 5/* 6 7Copyright 1992, 1993, 1998 The Open Group 8 9Permission to use, copy, modify, distribute, and sell this software and its 10documentation for any purpose is hereby granted without fee, provided that 11the above copyright notice appear in all copies and that both that 12copyright notice and this permission notice appear in supporting 13documentation. 14 15The above copyright notice and this permission notice shall be included 16in all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 22OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24OTHER DEALINGS IN THE SOFTWARE. 25 26Except as contained in this notice, the name of The Open Group shall 27not be used in advertising or otherwise to promote the sale, use or 28other dealings in this Software without prior written authorization 29from The Open Group. 30 31*/ 32 33#include <X11/Xlibint.h> 34#include <X11/extensions/XTest.h> 35#include <X11/extensions/xtestproto.h> 36#include <X11/extensions/Xext.h> 37#include <X11/extensions/extutil.h> 38#include <X11/extensions/XInput.h> 39#include <X11/extensions/XIproto.h> 40 41static XExtensionInfo _xtest_info_data; 42static XExtensionInfo *xtest_info = &_xtest_info_data; 43static /* const */ char *xtest_extension_name = XTestExtensionName; 44 45#define XTestCheckExtension(dpy,i,val) \ 46 XextCheckExtension (dpy, i, xtest_extension_name, val) 47 48#define XTestICheckExtension(dpy,i,val) \ 49 XextCheckExtension (dpy, i, xtest_extension_name, val); \ 50 if (!i->data) return val 51 52/***************************************************************************** 53 * * 54 * private utility routines * 55 * * 56 *****************************************************************************/ 57 58static int close_display(Display *dpy, XExtCodes *codes); 59static /* const */ XExtensionHooks xtest_extension_hooks = { 60 NULL, /* create_gc */ 61 NULL, /* copy_gc */ 62 NULL, /* flush_gc */ 63 NULL, /* free_gc */ 64 NULL, /* create_font */ 65 NULL, /* free_font */ 66 close_display, /* close_display */ 67 NULL, /* wire_to_event */ 68 NULL, /* event_to_wire */ 69 NULL, /* error */ 70 NULL /* error_string */ 71}; 72 73static XPointer 74get_xinput_base(Display *dpy) 75{ 76 int major_opcode, first_event, first_error; 77 first_event = 0; 78 79 XQueryExtension(dpy, INAME, &major_opcode, &first_event, &first_error); 80 return (XPointer)(long)first_event; 81} 82 83static XEXT_GENERATE_FIND_DISPLAY (find_display, xtest_info, 84 xtest_extension_name, 85 &xtest_extension_hooks, XTestNumberEvents, 86 get_xinput_base(dpy)) 87 88static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xtest_info) 89 90/***************************************************************************** 91 * * 92 * public routines * 93 * * 94 *****************************************************************************/ 95 96Bool 97XTestQueryExtension (Display *dpy, 98 int *event_base_return, int *error_base_return, 99 int *major_return, int *minor_return) 100{ 101 XExtDisplayInfo *info = find_display (dpy); 102 register xXTestGetVersionReq *req; 103 xXTestGetVersionReply rep; 104 105 if (XextHasExtension(info)) { 106 LockDisplay(dpy); 107 GetReq(XTestGetVersion, req); 108 req->reqType = info->codes->major_opcode; 109 req->xtReqType = X_XTestGetVersion; 110 req->majorVersion = XTestMajorVersion; 111 req->minorVersion = XTestMinorVersion; 112 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 113 UnlockDisplay(dpy); 114 SyncHandle(); 115 return False; 116 } 117 UnlockDisplay(dpy); 118 SyncHandle(); 119 *event_base_return = info->codes->first_event; 120 *error_base_return = info->codes->first_error; 121 *major_return = rep.majorVersion; 122 *minor_return = rep.minorVersion; 123 return True; 124 } else { 125 return False; 126 } 127} 128 129Bool 130XTestCompareCursorWithWindow(Display *dpy, Window window, Cursor cursor) 131{ 132 XExtDisplayInfo *info = find_display (dpy); 133 register xXTestCompareCursorReq *req; 134 xXTestCompareCursorReply rep; 135 136 XTestCheckExtension (dpy, info, 0); 137 138 LockDisplay(dpy); 139 GetReq(XTestCompareCursor, req); 140 req->reqType = info->codes->major_opcode; 141 req->xtReqType = X_XTestCompareCursor; 142 req->window = window; 143 req->cursor = cursor; 144 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 145 UnlockDisplay(dpy); 146 SyncHandle(); 147 return False; 148 } 149 UnlockDisplay(dpy); 150 SyncHandle(); 151 return rep.same; 152} 153 154Bool 155XTestCompareCurrentCursorWithWindow(Display *dpy, Window window) 156{ 157 return XTestCompareCursorWithWindow(dpy, window, XTestCurrentCursor); 158} 159 160int 161XTestFakeKeyEvent(Display *dpy, unsigned int keycode, 162 Bool is_press, unsigned long delay) 163{ 164 XExtDisplayInfo *info = find_display (dpy); 165 register xXTestFakeInputReq *req; 166 167 XTestCheckExtension (dpy, info, 0); 168 169 LockDisplay(dpy); 170 GetReq(XTestFakeInput, req); 171 req->reqType = info->codes->major_opcode; 172 req->xtReqType = X_XTestFakeInput; 173 req->type = is_press ? KeyPress : KeyRelease; 174 req->detail = keycode; 175 req->time = delay; 176 UnlockDisplay(dpy); 177 SyncHandle(); 178 return 1; 179} 180 181int 182XTestFakeButtonEvent(Display *dpy, unsigned int button, 183 Bool is_press, unsigned long delay) 184{ 185 XExtDisplayInfo *info = find_display (dpy); 186 register xXTestFakeInputReq *req; 187 188 XTestCheckExtension (dpy, info, 0); 189 190 LockDisplay(dpy); 191 GetReq(XTestFakeInput, req); 192 req->reqType = info->codes->major_opcode; 193 req->xtReqType = X_XTestFakeInput; 194 req->type = is_press ? ButtonPress : ButtonRelease; 195 req->detail = button; 196 req->time = delay; 197 UnlockDisplay(dpy); 198 SyncHandle(); 199 return 1; 200} 201 202int 203XTestFakeMotionEvent(Display *dpy, int screen, int x, int y, unsigned long delay) 204{ 205 XExtDisplayInfo *info = find_display (dpy); 206 register xXTestFakeInputReq *req; 207 208 XTestCheckExtension (dpy, info, 0); 209 210 LockDisplay(dpy); 211 GetReq(XTestFakeInput, req); 212 req->reqType = info->codes->major_opcode; 213 req->xtReqType = X_XTestFakeInput; 214 req->type = MotionNotify; 215 req->detail = False; 216 if (screen == -1) 217 req->root = None; 218 else 219 req->root = RootWindow(dpy, screen); 220 req->rootX = x; 221 req->rootY = y; 222 req->time = delay; 223 UnlockDisplay(dpy); 224 SyncHandle(); 225 return 1; 226} 227 228int 229XTestFakeRelativeMotionEvent(Display *dpy, int dx, int dy, unsigned long delay) 230{ 231 XExtDisplayInfo *info = find_display (dpy); 232 register xXTestFakeInputReq *req; 233 234 XTestCheckExtension (dpy, info, 0); 235 236 LockDisplay(dpy); 237 GetReq(XTestFakeInput, req); 238 req->reqType = info->codes->major_opcode; 239 req->xtReqType = X_XTestFakeInput; 240 req->type = MotionNotify; 241 req->detail = True; 242 req->root = None; 243 req->rootX = dx; 244 req->rootY = dy; 245 req->time = delay; 246 UnlockDisplay(dpy); 247 SyncHandle(); 248 return 1; 249} 250 251static void 252send_axes( 253 Display *dpy, 254 XExtDisplayInfo *info, 255 xXTestFakeInputReq *req, 256 XDevice *dev, 257 int first_axis, 258 int *axes, 259 int n_axes) 260{ 261 deviceValuator ev; 262 int n; 263 264 req->deviceid |= MORE_EVENTS; 265 req->length += ((n_axes + 5) / 6) * (SIZEOF(xEvent) >> 2); 266 ev.type = XI_DeviceValuator + (long)info->data; 267 ev.deviceid = dev->device_id; 268 ev.first_valuator = first_axis; 269 while (n_axes > 0) { 270 n = n_axes > 6 ? 6 : n_axes; 271 ev.num_valuators = n; 272 switch (n) { 273 case 6: 274 ev.valuator5 = *(axes+5); 275 case 5: 276 ev.valuator4 = *(axes+4); 277 case 4: 278 ev.valuator3 = *(axes+3); 279 case 3: 280 ev.valuator2 = *(axes+2); 281 case 2: 282 ev.valuator1 = *(axes+1); 283 case 1: 284 ev.valuator0 = *axes; 285 } 286 Data(dpy, (char *)&ev, SIZEOF(xEvent)); 287 axes += n; 288 n_axes -= n; 289 ev.first_valuator += n; 290 } 291} 292 293int 294XTestFakeDeviceKeyEvent(Display *dpy, XDevice *dev, 295 unsigned int keycode, Bool is_press, 296 int *axes, int n_axes, unsigned long delay) 297{ 298 XExtDisplayInfo *info = find_display (dpy); 299 register xXTestFakeInputReq *req; 300 301 XTestICheckExtension (dpy, info, 0); 302 303 LockDisplay(dpy); 304 GetReq(XTestFakeInput, req); 305 req->reqType = info->codes->major_opcode; 306 req->xtReqType = X_XTestFakeInput; 307 req->type = is_press ? XI_DeviceKeyPress : XI_DeviceKeyRelease; 308 req->type += (int)(long)info->data; 309 req->detail = keycode; 310 req->time = delay; 311 req->deviceid = dev->device_id; 312 if (n_axes) 313 send_axes(dpy, info, req, dev, 0, axes, n_axes); 314 UnlockDisplay(dpy); 315 SyncHandle(); 316 return 1; 317} 318 319int 320XTestFakeDeviceButtonEvent(Display *dpy, XDevice *dev, 321 unsigned int button, Bool is_press, 322 int *axes, int n_axes, unsigned long delay) 323{ 324 XExtDisplayInfo *info = find_display (dpy); 325 register xXTestFakeInputReq *req; 326 327 XTestICheckExtension (dpy, info, 0); 328 329 LockDisplay(dpy); 330 GetReq(XTestFakeInput, req); 331 req->reqType = info->codes->major_opcode; 332 req->xtReqType = X_XTestFakeInput; 333 req->type = is_press ? XI_DeviceButtonPress : XI_DeviceButtonRelease; 334 req->type += (int)(long)info->data; 335 req->detail = button; 336 req->time = delay; 337 req->deviceid = dev->device_id; 338 if (n_axes) 339 send_axes(dpy, info, req, dev, 0, axes, n_axes); 340 UnlockDisplay(dpy); 341 SyncHandle(); 342 return 1; 343} 344 345int 346XTestFakeProximityEvent(Display *dpy, XDevice *dev, Bool in_prox, 347 int *axes, int n_axes, unsigned long delay) 348{ 349 XExtDisplayInfo *info = find_display (dpy); 350 register xXTestFakeInputReq *req; 351 352 XTestICheckExtension (dpy, info, 0); 353 354 LockDisplay(dpy); 355 GetReq(XTestFakeInput, req); 356 req->reqType = info->codes->major_opcode; 357 req->xtReqType = X_XTestFakeInput; 358 req->type = in_prox ? XI_ProximityIn : XI_ProximityOut; 359 req->type += (int)(long)info->data; 360 req->time = delay; 361 req->deviceid = dev->device_id; 362 if (n_axes) 363 send_axes(dpy, info, req, dev, 0, axes, n_axes); 364 UnlockDisplay(dpy); 365 SyncHandle(); 366 return 1; 367} 368 369int 370XTestFakeDeviceMotionEvent(Display *dpy, XDevice *dev, 371 Bool is_relative, int first_axis, 372 int *axes, int n_axes, unsigned long delay) 373{ 374 XExtDisplayInfo *info = find_display (dpy); 375 register xXTestFakeInputReq *req; 376 377 XTestICheckExtension (dpy, info, 0); 378 379 LockDisplay(dpy); 380 GetReq(XTestFakeInput, req); 381 req->reqType = info->codes->major_opcode; 382 req->xtReqType = X_XTestFakeInput; 383 req->type = XI_DeviceMotionNotify + (int)(long)info->data; 384 req->detail = is_relative; 385 req->time = delay; 386 req->deviceid = dev->device_id; 387 send_axes(dpy, info, req, dev, first_axis, axes, n_axes); 388 UnlockDisplay(dpy); 389 SyncHandle(); 390 return 1; 391} 392 393int 394XTestGrabControl(Display *dpy, Bool impervious) 395{ 396 XExtDisplayInfo *info = find_display (dpy); 397 register xXTestGrabControlReq *req; 398 399 XTestCheckExtension (dpy, info, 0); 400 401 LockDisplay(dpy); 402 GetReq(XTestGrabControl, req); 403 req->reqType = info->codes->major_opcode; 404 req->xtReqType = X_XTestGrabControl; 405 req->impervious = impervious; 406 UnlockDisplay(dpy); 407 SyncHandle(); 408 return 1; 409} 410 411void 412XTestSetGContextOfGC(GC gc, GContext gid) 413{ 414 gc->gid = gid; 415} 416 417void 418XTestSetVisualIDOfVisual(Visual *visual, VisualID visualid) 419{ 420 visual->visualid = visualid; 421} 422 423static xReq _dummy_request = { 424 0, 0, 0 425}; 426 427Status 428XTestDiscard(Display *dpy) 429{ 430 Bool something; 431 register char *ptr; 432 433 LockDisplay(dpy); 434 if ((something = (dpy->bufptr != dpy->buffer))) { 435 for (ptr = dpy->buffer; 436 ptr < dpy->bufptr; 437 ptr += (((xReq *)ptr)->length << 2)) 438 dpy->request--; 439 dpy->bufptr = dpy->buffer; 440 dpy->last_req = (char *)&_dummy_request; 441 } 442 UnlockDisplay(dpy); 443 SyncHandle(); 444 return something; 445} 446