XExtInt.c revision b789ec8a
1/************************************************************ 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Hewlett-Packard not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45********************************************************/ 46 47/*********************************************************************** 48 * 49 * Input Extension library internal functions. 50 * 51 */ 52 53#include <stdio.h> 54#include <stdint.h> 55#include <X11/extensions/XI.h> 56#include <X11/extensions/XI2.h> 57#include <X11/extensions/XIproto.h> 58#include <X11/extensions/XI2proto.h> 59#include <X11/Xlibint.h> 60#include <X11/extensions/XInput.h> 61#include <X11/extensions/XInput2.h> 62#include <X11/extensions/extutil.h> 63#include <X11/extensions/geproto.h> 64#include <X11/extensions/ge.h> 65#include <X11/extensions/Xge.h> 66#include "XIint.h" 67 68#define ENQUEUE_EVENT True 69#define DONT_ENQUEUE False 70#define FP1616toDBL(x) ((x) * 1.0 / (1 << 16)) 71 72extern void _xibaddevice( 73 Display * /* dpy */, 74 int * /* error */ 75); 76 77extern void _xibadclass( 78 Display * /* dpy */, 79 int * /* error */ 80); 81 82extern void _xibadevent( 83 Display * /* dpy */, 84 int * /* error */ 85); 86 87extern void _xibadmode( 88 Display * /* dpy */, 89 int * /* error */ 90); 91 92extern void _xidevicebusy( 93 Display * /* dpy */, 94 int * /* error */ 95); 96 97extern int _XiGetDevicePresenceNotifyEvent( 98 Display * /* dpy */ 99); 100 101int copy_classes(XIDeviceInfo *to, xXIAnyInfo* from, int nclasses); 102int size_classes(xXIAnyInfo* from, int nclasses); 103 104static XExtensionInfo *xinput_info; 105static /* const */ char *xinput_extension_name = INAME; 106 107static int XInputClose( 108 Display * /* dpy */, 109 XExtCodes * /* codes */ 110); 111 112static char *XInputError( 113 Display * /* dpy */, 114 int /* code */, 115 XExtCodes * /* codes */, 116 char * /* buf */, 117 int /* n */ 118); 119 120static Bool XInputWireToEvent( 121 Display * /* dpy */, 122 XEvent * /* re */, 123 xEvent * /* event */ 124); 125static Bool XInputWireToCookie( 126 Display* /* display */, 127 XGenericEventCookie* /* re */, 128 xEvent* /* event */ 129); 130 131static Bool XInputCopyCookie( 132 Display* /* display */, 133 XGenericEventCookie* /* in */, 134 XGenericEventCookie* /* out */ 135); 136 137static int 138wireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* out); 139static int 140wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie); 141static int 142wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie); 143static int 144wireToRawEvent(xXIRawEvent *in, XGenericEventCookie *cookie); 145static int 146wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie); 147static int 148wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie); 149 150static /* const */ XEvent emptyevent; 151 152static /* const */ XExtensionHooks xinput_extension_hooks = { 153 NULL, /* create_gc */ 154 NULL, /* copy_gc */ 155 NULL, /* flush_gc */ 156 NULL, /* free_gc */ 157 NULL, /* create_font */ 158 NULL, /* free_font */ 159 XInputClose, /* close_display */ 160 XInputWireToEvent, /* wire_to_event */ 161 _XiEventToWire, /* event_to_wire */ 162 NULL, /* error */ 163 XInputError, /* error_string */ 164}; 165 166static char *XInputErrorList[] = { 167 "BadDevice, invalid or uninitialized input device", /* BadDevice */ 168 "BadEvent, invalid event type", /* BadEvent */ 169 "BadMode, invalid mode parameter", /* BadMode */ 170 "DeviceBusy, device is busy", /* DeviceBusy */ 171 "BadClass, invalid event class", /* BadClass */ 172}; 173 174/* Get the version supported by the server to know which number of 175* events are support. Otherwise, a wrong number of events may smash 176* the Xlib-internal event processing vector. 177* 178* Since the extension hasn't been initialized yet, we need to 179* manually get the opcode, then the version. 180*/ 181static int 182_XiFindEventsSupported(Display *dpy) 183{ 184 XExtCodes codes; 185 XExtensionVersion *extversion = NULL; 186 int nevents = 0; 187 188 if (!XQueryExtension(dpy, INAME, &codes.major_opcode, 189 &codes.first_event, &codes.first_error)) 190 goto out; 191 192 LockDisplay(dpy); 193 extversion = _XiGetExtensionVersionRequest(dpy, INAME, codes.major_opcode); 194 UnlockDisplay(dpy); 195 SyncHandle(); 196 197 if (!extversion || !extversion->present) 198 goto out; 199 200 if (extversion->major_version >= 2) 201 nevents = IEVENTS; /* number is fixed, XI2 adds GenericEvents only */ 202 else if (extversion->major_version <= 0) 203 { 204 printf("XInput_find_display: invalid extension version %d.%d\n", 205 extversion->major_version, extversion->minor_version); 206 goto out; 207 } 208 else 209 { 210 switch(extversion->minor_version) 211 { 212 case XI_Add_DeviceProperties_Minor: 213 nevents = XI_DevicePropertyNotify + 1; 214 break; 215 case XI_Add_DevicePresenceNotify_Minor: 216 nevents = XI_DevicePresenceNotify + 1; 217 break; 218 default: 219 nevents = XI_DeviceButtonstateNotify + 1; 220 break; 221 } 222 } 223 224out: 225 if (extversion) 226 XFree(extversion); 227 return nevents; 228} 229 230 231_X_HIDDEN 232XExtDisplayInfo *XInput_find_display (Display *dpy) 233{ 234 XExtDisplayInfo *dpyinfo; 235 if (!xinput_info) { if (!(xinput_info = XextCreateExtension())) return NULL; } 236 if (!(dpyinfo = XextFindDisplay (xinput_info, dpy))) 237 { 238 int nevents = _XiFindEventsSupported(dpy); 239 240 dpyinfo = XextAddDisplay (xinput_info, dpy, 241 xinput_extension_name, 242 &xinput_extension_hooks, 243 nevents, NULL); 244 if (dpyinfo->codes) /* NULL if XI doesn't exist on the server */ 245 { 246 XESetWireToEventCookie(dpy, dpyinfo->codes->major_opcode, XInputWireToCookie); 247 XESetCopyEventCookie(dpy, dpyinfo->codes->major_opcode, XInputCopyCookie); 248 } 249 } 250 return dpyinfo; 251} 252 253static XEXT_GENERATE_ERROR_STRING(XInputError, xinput_extension_name, 254 IERRORS, XInputErrorList) 255/******************************************************************* 256* 257* Input extension versions. 258* 259*/ 260static XExtensionVersion versions[] = { {XI_Absent, 0, 0}, 261{XI_Present, XI_Initial_Release_Major, XI_Initial_Release_Minor}, 262{XI_Present, XI_Add_XDeviceBell_Major, XI_Add_XDeviceBell_Minor}, 263{XI_Present, XI_Add_XSetDeviceValuators_Major, 264 XI_Add_XSetDeviceValuators_Minor}, 265{XI_Present, XI_Add_XChangeDeviceControl_Major, 266 XI_Add_XChangeDeviceControl_Minor}, 267{XI_Present, XI_Add_DevicePresenceNotify_Major, 268 XI_Add_DevicePresenceNotify_Minor}, 269{XI_Present, XI_Add_DeviceProperties_Major, 270 XI_Add_DeviceProperties_Minor}, 271{XI_Present, XI_2_Major, XI_2_Minor} 272}; 273 274/*********************************************************************** 275 * 276 * Return errors reported by this extension. 277 * 278 */ 279 280void 281_xibaddevice( 282 Display *dpy, 283 int *error) 284{ 285 XExtDisplayInfo *info = XInput_find_display(dpy); 286 287 *error = info->codes->first_error + XI_BadDevice; 288} 289 290void 291_xibadclass( 292 Display *dpy, 293 int *error) 294{ 295 XExtDisplayInfo *info = XInput_find_display(dpy); 296 297 *error = info->codes->first_error + XI_BadClass; 298} 299 300void 301_xibadevent( 302 Display *dpy, 303 int *error) 304{ 305 XExtDisplayInfo *info = XInput_find_display(dpy); 306 307 *error = info->codes->first_error + XI_BadEvent; 308} 309 310void 311_xibadmode( 312 Display *dpy, 313 int *error) 314{ 315 XExtDisplayInfo *info = XInput_find_display(dpy); 316 317 *error = info->codes->first_error + XI_BadMode; 318} 319 320void 321_xidevicebusy( 322 Display *dpy, 323 int *error) 324{ 325 XExtDisplayInfo *info = XInput_find_display(dpy); 326 327 *error = info->codes->first_error + XI_DeviceBusy; 328} 329 330static int XInputCheckExtension(Display *dpy, XExtDisplayInfo *info) 331{ 332 XextCheckExtension (dpy, info, xinput_extension_name, 0); 333 return 1; 334} 335 336/*********************************************************************** 337 * 338 * Check to see if the input extension is installed in the server. 339 * Also check to see if the version is >= the requested version. 340 * 341 */ 342 343_X_HIDDEN int 344_XiCheckExtInit( 345 register Display *dpy, 346 register int version_index, 347 XExtDisplayInfo *info) 348{ 349 XExtensionVersion *ext; 350 351 if (!XInputCheckExtension(dpy, info)) { 352 UnlockDisplay(dpy); 353 return (-1); 354 } 355 356 if (info->data == NULL) { 357 info->data = (XPointer) Xmalloc(sizeof(XInputData)); 358 if (!info->data) { 359 UnlockDisplay(dpy); 360 return (-1); 361 } 362 ((XInputData *) info->data)->vers = 363 _XiGetExtensionVersion(dpy, "XInputExtension", info); 364 } 365 366 if (versions[version_index].major_version > Dont_Check) { 367 ext = ((XInputData *) info->data)->vers; 368 if ((ext->major_version < versions[version_index].major_version) || 369 ((ext->major_version == versions[version_index].major_version) && 370 (ext->minor_version < versions[version_index].minor_version))) { 371 UnlockDisplay(dpy); 372 return (-1); 373 } 374 } 375 return (0); 376} 377 378/*********************************************************************** 379 * 380 * Close display routine. 381 * 382 */ 383 384static int 385XInputClose( 386 Display *dpy, 387 XExtCodes *codes) 388{ 389 XExtDisplayInfo *info = XInput_find_display(dpy); 390 391 if (info->data != NULL) { 392 XFree((char *)((XInputData *) info->data)->vers); 393 XFree((char *)info->data); 394 } 395 return XextRemoveDisplay(xinput_info, dpy); 396} 397 398static int 399Ones(Mask mask) 400{ 401 register Mask y; 402 403 y = (mask >> 1) & 033333333333; 404 y = mask - y - ((y >> 1) & 033333333333); 405 return (((y + (y >> 3)) & 030707070707) % 077); 406} 407 408static int count_bits(unsigned char* ptr, int len) 409{ 410 int bits = 0; 411 unsigned int i; 412 unsigned char x; 413 414 for (i = 0; i < len; i++) 415 { 416 x = ptr[i]; 417 while(x > 0) 418 { 419 bits += (x & 0x1); 420 x >>= 1; 421 } 422 } 423 return bits; 424} 425 426int 427_XiGetDevicePresenceNotifyEvent(Display * dpy) 428{ 429 XExtDisplayInfo *info = XInput_find_display(dpy); 430 431 return info->codes->first_event + XI_DevicePresenceNotify; 432} 433 434/*********************************************************************** 435 * 436 * Handle Input extension events. 437 * Reformat a wire event into an XEvent structure of the right type. 438 * 439 */ 440 441static Bool 442XInputWireToEvent( 443 Display *dpy, 444 XEvent *re, 445 xEvent *event) 446{ 447 unsigned int type, reltype; 448 unsigned int i, j; 449 XExtDisplayInfo *info = XInput_find_display(dpy); 450 XEvent *save = (XEvent *) info->data; 451 452 type = event->u.u.type & 0x7f; 453 reltype = (type - info->codes->first_event); 454 455 if (type == GenericEvent || 456 (reltype != XI_DeviceValuator && 457 reltype != XI_DeviceKeystateNotify && 458 reltype != XI_DeviceButtonstateNotify)) { 459 *save = emptyevent; 460 save->type = type; 461 ((XAnyEvent *) save)->serial = _XSetLastRequestRead(dpy, 462 (xGenericReply *) 463 event); 464 ((XAnyEvent *) save)->send_event = ((event->u.u.type & 0x80) != 0); 465 ((XAnyEvent *) save)->display = dpy; 466 } 467 468 /* Process traditional events */ 469 if (type != GenericEvent) 470 { 471 switch (reltype) { 472 case XI_DeviceMotionNotify: 473 { 474 register XDeviceMotionEvent *ev = (XDeviceMotionEvent *) save; 475 deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 476 477 ev->root = ev2->root; 478 ev->window = ev2->event; 479 ev->subwindow = ev2->child; 480 ev->time = ev2->time; 481 ev->x_root = ev2->root_x; 482 ev->y_root = ev2->root_y; 483 ev->x = ev2->event_x; 484 ev->y = ev2->event_y; 485 ev->state = ev2->state; 486 ev->same_screen = ev2->same_screen; 487 ev->is_hint = ev2->detail; 488 ev->deviceid = ev2->deviceid & DEVICE_BITS; 489 return (DONT_ENQUEUE); 490 } 491 break; 492 case XI_DeviceKeyPress: 493 case XI_DeviceKeyRelease: 494 { 495 register XDeviceKeyEvent *ev = (XDeviceKeyEvent *) save; 496 deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 497 498 ev->root = ev2->root; 499 ev->window = ev2->event; 500 ev->subwindow = ev2->child; 501 ev->time = ev2->time; 502 ev->x_root = ev2->root_x; 503 ev->y_root = ev2->root_y; 504 ev->x = ev2->event_x; 505 ev->y = ev2->event_y; 506 ev->state = ev2->state; 507 ev->same_screen = ev2->same_screen; 508 ev->keycode = ev2->detail; 509 ev->deviceid = ev2->deviceid & DEVICE_BITS; 510 if (ev2->deviceid & MORE_EVENTS) 511 return (DONT_ENQUEUE); 512 else { 513 *re = *save; 514 return (ENQUEUE_EVENT); 515 } 516 } 517 break; 518 case XI_DeviceButtonPress: 519 case XI_DeviceButtonRelease: 520 { 521 register XDeviceButtonEvent *ev = (XDeviceButtonEvent *) save; 522 deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 523 524 ev->root = ev2->root; 525 ev->window = ev2->event; 526 ev->subwindow = ev2->child; 527 ev->time = ev2->time; 528 ev->x_root = ev2->root_x; 529 ev->y_root = ev2->root_y; 530 ev->x = ev2->event_x; 531 ev->y = ev2->event_y; 532 ev->state = ev2->state; 533 ev->same_screen = ev2->same_screen; 534 ev->button = ev2->detail; 535 ev->deviceid = ev2->deviceid & DEVICE_BITS; 536 if (ev2->deviceid & MORE_EVENTS) 537 return (DONT_ENQUEUE); 538 else { 539 *re = *save; 540 return (ENQUEUE_EVENT); 541 } 542 } 543 break; 544 case XI_ProximityIn: 545 case XI_ProximityOut: 546 { 547 register XProximityNotifyEvent *ev = (XProximityNotifyEvent *) save; 548 deviceKeyButtonPointer *ev2 = (deviceKeyButtonPointer *) event; 549 550 ev->root = ev2->root; 551 ev->window = ev2->event; 552 ev->subwindow = ev2->child; 553 ev->time = ev2->time; 554 ev->x_root = ev2->root_x; 555 ev->y_root = ev2->root_y; 556 ev->x = ev2->event_x; 557 ev->y = ev2->event_y; 558 ev->state = ev2->state; 559 ev->same_screen = ev2->same_screen; 560 ev->deviceid = ev2->deviceid & DEVICE_BITS; 561 if (ev2->deviceid & MORE_EVENTS) 562 return (DONT_ENQUEUE); 563 else { 564 *re = *save; 565 return (ENQUEUE_EVENT); 566 } 567 } 568 break; 569 case XI_DeviceValuator: 570 { 571 deviceValuator *xev = (deviceValuator *) event; 572 int save_type = save->type - info->codes->first_event; 573 574 if (save_type == XI_DeviceKeyPress || save_type == XI_DeviceKeyRelease) { 575 XDeviceKeyEvent *kev = (XDeviceKeyEvent *) save; 576 577 kev->device_state = xev->device_state; 578 kev->axes_count = xev->num_valuators; 579 kev->first_axis = xev->first_valuator; 580 i = xev->num_valuators; 581 if (i > 6) 582 i = 6; 583 switch (i) { 584 case 6: 585 kev->axis_data[5] = xev->valuator5; 586 case 5: 587 kev->axis_data[4] = xev->valuator4; 588 case 4: 589 kev->axis_data[3] = xev->valuator3; 590 case 3: 591 kev->axis_data[2] = xev->valuator2; 592 case 2: 593 kev->axis_data[1] = xev->valuator1; 594 case 1: 595 kev->axis_data[0] = xev->valuator0; 596 } 597 } else if (save_type == XI_DeviceButtonPress || 598 save_type == XI_DeviceButtonRelease) { 599 XDeviceButtonEvent *bev = (XDeviceButtonEvent *) save; 600 601 bev->device_state = xev->device_state; 602 bev->axes_count = xev->num_valuators; 603 bev->first_axis = xev->first_valuator; 604 i = xev->num_valuators; 605 if (i > 6) 606 i = 6; 607 switch (i) { 608 case 6: 609 bev->axis_data[5] = xev->valuator5; 610 case 5: 611 bev->axis_data[4] = xev->valuator4; 612 case 4: 613 bev->axis_data[3] = xev->valuator3; 614 case 3: 615 bev->axis_data[2] = xev->valuator2; 616 case 2: 617 bev->axis_data[1] = xev->valuator1; 618 case 1: 619 bev->axis_data[0] = xev->valuator0; 620 } 621 } else if (save_type == XI_DeviceMotionNotify) { 622 XDeviceMotionEvent *mev = (XDeviceMotionEvent *) save; 623 624 mev->device_state = xev->device_state; 625 mev->axes_count = xev->num_valuators; 626 mev->first_axis = xev->first_valuator; 627 i = xev->num_valuators; 628 if (i > 6) 629 i = 6; 630 switch (i) { 631 case 6: 632 mev->axis_data[5] = xev->valuator5; 633 case 5: 634 mev->axis_data[4] = xev->valuator4; 635 case 4: 636 mev->axis_data[3] = xev->valuator3; 637 case 3: 638 mev->axis_data[2] = xev->valuator2; 639 case 2: 640 mev->axis_data[1] = xev->valuator1; 641 case 1: 642 mev->axis_data[0] = xev->valuator0; 643 } 644 } else if (save_type == XI_ProximityIn || save_type == XI_ProximityOut) { 645 XProximityNotifyEvent *pev = (XProximityNotifyEvent *) save; 646 647 pev->device_state = xev->device_state; 648 pev->axes_count = xev->num_valuators; 649 pev->first_axis = xev->first_valuator; 650 i = xev->num_valuators; 651 if (i > 6) 652 i = 6; 653 switch (i) { 654 case 6: 655 pev->axis_data[5] = xev->valuator5; 656 case 5: 657 pev->axis_data[4] = xev->valuator4; 658 case 4: 659 pev->axis_data[3] = xev->valuator3; 660 case 3: 661 pev->axis_data[2] = xev->valuator2; 662 case 2: 663 pev->axis_data[1] = xev->valuator1; 664 case 1: 665 pev->axis_data[0] = xev->valuator0; 666 } 667 } else if (save_type == XI_DeviceStateNotify) { 668 XDeviceStateNotifyEvent *sev = (XDeviceStateNotifyEvent *) save; 669 XInputClass *any = (XInputClass *) & sev->data[0]; 670 XValuatorStatus *v; 671 672 for (i = 0; i < sev->num_classes; i++) 673 if (any->class != ValuatorClass) 674 any = (XInputClass *) ((char *)any + any->length); 675 v = (XValuatorStatus *) any; 676 i = v->num_valuators; 677 j = xev->num_valuators; 678 if (j > 3) 679 j = 3; 680 switch (j) { 681 case 3: 682 v->valuators[i + 2] = xev->valuator2; 683 case 2: 684 v->valuators[i + 1] = xev->valuator1; 685 case 1: 686 v->valuators[i + 0] = xev->valuator0; 687 } 688 v->num_valuators += j; 689 690 } 691 *re = *save; 692 return (ENQUEUE_EVENT); 693 } 694 break; 695 case XI_DeviceFocusIn: 696 case XI_DeviceFocusOut: 697 { 698 register XDeviceFocusChangeEvent *ev = (XDeviceFocusChangeEvent *) re; 699 deviceFocus *fev = (deviceFocus *) event; 700 701 *ev = *((XDeviceFocusChangeEvent *) save); 702 ev->window = fev->window; 703 ev->time = fev->time; 704 ev->mode = fev->mode; 705 ev->detail = fev->detail; 706 ev->deviceid = fev->deviceid & DEVICE_BITS; 707 return (ENQUEUE_EVENT); 708 } 709 break; 710 case XI_DeviceStateNotify: 711 { 712 XDeviceStateNotifyEvent *stev = (XDeviceStateNotifyEvent *) save; 713 deviceStateNotify *sev = (deviceStateNotify *) event; 714 char *data; 715 716 stev->window = None; 717 stev->deviceid = sev->deviceid & DEVICE_BITS; 718 stev->time = sev->time; 719 stev->num_classes = Ones((Mask) sev->classes_reported & InputClassBits); 720 data = (char *)&stev->data[0]; 721 if (sev->classes_reported & (1 << KeyClass)) { 722 register XKeyStatus *kstev = (XKeyStatus *) data; 723 724 kstev->class = KeyClass; 725 kstev->length = sizeof(XKeyStatus); 726 kstev->num_keys = sev->num_keys; 727 memcpy((char *)&kstev->keys[0], (char *)&sev->keys[0], 4); 728 data += sizeof(XKeyStatus); 729 } 730 if (sev->classes_reported & (1 << ButtonClass)) { 731 register XButtonStatus *bev = (XButtonStatus *) data; 732 733 bev->class = ButtonClass; 734 bev->length = sizeof(XButtonStatus); 735 bev->num_buttons = sev->num_buttons; 736 memcpy((char *)bev->buttons, (char *)sev->buttons, 4); 737 data += sizeof(XButtonStatus); 738 } 739 if (sev->classes_reported & (1 << ValuatorClass)) { 740 register XValuatorStatus *vev = (XValuatorStatus *) data; 741 742 vev->class = ValuatorClass; 743 vev->length = sizeof(XValuatorStatus); 744 vev->num_valuators = sev->num_valuators; 745 vev->mode = sev->classes_reported >> ModeBitsShift; 746 j = sev->num_valuators; 747 if (j > 3) 748 j = 3; 749 switch (j) { 750 case 3: 751 vev->valuators[2] = sev->valuator2; 752 case 2: 753 vev->valuators[1] = sev->valuator1; 754 case 1: 755 vev->valuators[0] = sev->valuator0; 756 } 757 data += sizeof(XValuatorStatus); 758 } 759 if (sev->deviceid & MORE_EVENTS) 760 return (DONT_ENQUEUE); 761 else { 762 *re = *save; 763 stev = (XDeviceStateNotifyEvent *) re; 764 return (ENQUEUE_EVENT); 765 } 766 } 767 break; 768 case XI_DeviceKeystateNotify: 769 { 770 int i; 771 XInputClass *anyclass; 772 register XKeyStatus *kv; 773 deviceKeyStateNotify *ksev = (deviceKeyStateNotify *) event; 774 XDeviceStateNotifyEvent *kstev = (XDeviceStateNotifyEvent *) save; 775 776 anyclass = (XInputClass *) & kstev->data[0]; 777 for (i = 0; i < kstev->num_classes; i++) 778 if (anyclass->class == KeyClass) 779 break; 780 else 781 anyclass = (XInputClass *) ((char *)anyclass + 782 anyclass->length); 783 784 kv = (XKeyStatus *) anyclass; 785 kv->num_keys = 256; 786 memcpy((char *)&kv->keys[4], (char *)ksev->keys, 28); 787 if (ksev->deviceid & MORE_EVENTS) 788 return (DONT_ENQUEUE); 789 else { 790 *re = *save; 791 kstev = (XDeviceStateNotifyEvent *) re; 792 return (ENQUEUE_EVENT); 793 } 794 } 795 break; 796 case XI_DeviceButtonstateNotify: 797 { 798 int i; 799 XInputClass *anyclass; 800 register XButtonStatus *bv; 801 deviceButtonStateNotify *bsev = (deviceButtonStateNotify *) event; 802 XDeviceStateNotifyEvent *bstev = (XDeviceStateNotifyEvent *) save; 803 804 anyclass = (XInputClass *) & bstev->data[0]; 805 for (i = 0; i < bstev->num_classes; i++) 806 if (anyclass->class == ButtonClass) 807 break; 808 else 809 anyclass = (XInputClass *) ((char *)anyclass + 810 anyclass->length); 811 812 bv = (XButtonStatus *) anyclass; 813 bv->num_buttons = 256; 814 memcpy((char *)&bv->buttons[4], (char *)bsev->buttons, 28); 815 if (bsev->deviceid & MORE_EVENTS) 816 return (DONT_ENQUEUE); 817 else { 818 *re = *save; 819 bstev = (XDeviceStateNotifyEvent *) re; 820 return (ENQUEUE_EVENT); 821 } 822 } 823 break; 824 case XI_DeviceMappingNotify: 825 { 826 register XDeviceMappingEvent *ev = (XDeviceMappingEvent *) re; 827 deviceMappingNotify *ev2 = (deviceMappingNotify *) event; 828 829 *ev = *((XDeviceMappingEvent *) save); 830 ev->window = 0; 831 ev->first_keycode = ev2->firstKeyCode; 832 ev->request = ev2->request; 833 ev->count = ev2->count; 834 ev->time = ev2->time; 835 ev->deviceid = ev2->deviceid & DEVICE_BITS; 836 return (ENQUEUE_EVENT); 837 } 838 break; 839 case XI_ChangeDeviceNotify: 840 { 841 register XChangeDeviceNotifyEvent *ev = (XChangeDeviceNotifyEvent *) re; 842 changeDeviceNotify *ev2 = (changeDeviceNotify *) event; 843 844 *ev = *((XChangeDeviceNotifyEvent *) save); 845 ev->window = 0; 846 ev->request = ev2->request; 847 ev->time = ev2->time; 848 ev->deviceid = ev2->deviceid & DEVICE_BITS; 849 return (ENQUEUE_EVENT); 850 } 851 break; 852 853 case XI_DevicePresenceNotify: 854 { 855 XDevicePresenceNotifyEvent *ev = (XDevicePresenceNotifyEvent *) re; 856 devicePresenceNotify *ev2 = (devicePresenceNotify *) event; 857 858 *ev = *(XDevicePresenceNotifyEvent *) save; 859 ev->window = 0; 860 ev->time = ev2->time; 861 ev->devchange = ev2->devchange; 862 ev->deviceid = ev2->deviceid; 863 ev->control = ev2->control; 864 return (ENQUEUE_EVENT); 865 } 866 break; 867 case XI_DevicePropertyNotify: 868 { 869 XDevicePropertyNotifyEvent* ev = (XDevicePropertyNotifyEvent*)re; 870 devicePropertyNotify *ev2 = (devicePropertyNotify*)event; 871 872 *ev = *(XDevicePropertyNotifyEvent*)save; 873 ev->time = ev2->time; 874 ev->deviceid = ev2->deviceid; 875 ev->atom = ev2->atom; 876 ev->state = ev2->state; 877 return ENQUEUE_EVENT; 878 } 879 break; 880 default: 881 printf("XInputWireToEvent: UNKNOWN WIRE EVENT! type=%d\n", type); 882 break; 883 } 884 } 885 return (DONT_ENQUEUE); 886} 887 888static void xge_copy_to_cookie(xGenericEvent* ev, 889 XGenericEventCookie *cookie) 890{ 891 cookie->type = ev->type; 892 cookie->evtype = ev->evtype; 893 cookie->extension = ev->extension; 894} 895 896static Bool 897XInputWireToCookie( 898 Display *dpy, 899 XGenericEventCookie *cookie, 900 xEvent *event) 901{ 902 XExtDisplayInfo *info = XInput_find_display(dpy); 903 XEvent *save = (XEvent *) info->data; 904 xGenericEvent* ge = (xGenericEvent*)event; 905 906 if (ge->extension != info->codes->major_opcode) 907 { 908 printf("XInputWireToCookie: wrong extension opcode %d\n", 909 ge->extension); 910 return DONT_ENQUEUE; 911 } 912 913 *save = emptyevent; 914 save->type = event->u.u.type; 915 ((XAnyEvent*)save)->serial = _XSetLastRequestRead(dpy, (xGenericReply *) event); 916 ((XAnyEvent*)save)->send_event = ((event->u.u.type & 0x80) != 0); 917 ((XAnyEvent*)save)->display = dpy; 918 919 xge_copy_to_cookie((xGenericEvent*)event, (XGenericEventCookie*)save); 920 switch(ge->evtype) 921 { 922 case XI_Motion: 923 case XI_ButtonPress: 924 case XI_ButtonRelease: 925 case XI_KeyPress: 926 case XI_KeyRelease: 927 *cookie = *(XGenericEventCookie*)save; 928 if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie)) 929 { 930 printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 931 ge->evtype); 932 break; 933 } 934 return ENQUEUE_EVENT; 935 case XI_DeviceChanged: 936 *cookie = *(XGenericEventCookie*)save; 937 if (!wireToDeviceChangedEvent((xXIDeviceChangedEvent*)event, cookie)) 938 { 939 printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 940 ge->evtype); 941 break; 942 } 943 return ENQUEUE_EVENT; 944 case XI_HierarchyChanged: 945 *cookie = *(XGenericEventCookie*)save; 946 if (!wireToHierarchyChangedEvent((xXIHierarchyEvent*)event, cookie)) 947 { 948 printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 949 ge->evtype); 950 break; 951 } 952 return ENQUEUE_EVENT; 953 954 case XI_RawKeyPress: 955 case XI_RawKeyRelease: 956 case XI_RawButtonPress: 957 case XI_RawButtonRelease: 958 case XI_RawMotion: 959 *cookie = *(XGenericEventCookie*)save; 960 if (!wireToRawEvent((xXIRawEvent*)event, cookie)) 961 { 962 printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 963 ge->evtype); 964 break; 965 } 966 return ENQUEUE_EVENT; 967 case XI_Enter: 968 case XI_Leave: 969 case XI_FocusIn: 970 case XI_FocusOut: 971 *cookie = *(XGenericEventCookie*)save; 972 if (!wireToEnterLeave((xXIEnterEvent*)event, cookie)) 973 { 974 printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 975 ge->evtype); 976 break; 977 } 978 return ENQUEUE_EVENT; 979 case XI_PropertyEvent: 980 *cookie = *(XGenericEventCookie*)save; 981 if (!wireToPropertyEvent((xXIPropertyEvent*)event, cookie)) 982 { 983 printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", 984 ge->evtype); 985 break; 986 } 987 return ENQUEUE_EVENT; 988 default: 989 printf("XInputWireToCookie: Unknown generic event. type %d\n", ge->evtype); 990 991 } 992 return DONT_ENQUEUE; 993} 994 995/** 996 * Calculate length in bytes needed for the device event with the given 997 * button mask length, valuator mask length + valuator mask. All parameters 998 * in bytes. 999 */ 1000static inline int 1001sizeDeviceEvent(int buttons_len, int valuators_len, 1002 unsigned char *valuators_mask) 1003{ 1004 int len; 1005 1006 len = sizeof(XIDeviceEvent); 1007 len += sizeof(XIButtonState) + buttons_len; 1008 len += sizeof(XIValuatorState) + valuators_len; 1009 len += count_bits(valuators_mask, valuators_len) * sizeof(double); 1010 len += sizeof(XIModifierState) + sizeof(XIGroupState); 1011 1012 return len; 1013} 1014 1015/** 1016 * Return the size in bytes required to store the matching class type 1017 * num_elements is num_buttons for XIButtonClass or num_keycodes for 1018 * XIKeyClass. 1019 * 1020 * Also used from copy_classes in XIQueryDevice.c 1021 */ 1022static int 1023sizeDeviceClassType(int type, int num_elements) 1024{ 1025 int l = 0; 1026 switch(type) 1027 { 1028 case XIButtonClass: 1029 l = sizeof(XIButtonClassInfo); 1030 l += num_elements * sizeof(Atom); 1031 /* Force mask alignment with longs to avoid 1032 * unaligned access when accessing the atoms. */ 1033 l += ((((num_elements + 7)/8) + 3)/4) * sizeof(Atom); 1034 break; 1035 case XIKeyClass: 1036 l = sizeof(XIKeyClassInfo); 1037 l += num_elements * sizeof(int); 1038 break; 1039 case XIValuatorClass: 1040 l = sizeof(XIValuatorClassInfo); 1041 break; 1042 default: 1043 printf("sizeDeviceClassType: unknown type %d\n", type); 1044 break; 1045 } 1046 return l; 1047} 1048 1049static Bool 1050copyHierarchyEvent(XGenericEventCookie *cookie_in, 1051 XGenericEventCookie *cookie_out) 1052{ 1053 XIHierarchyEvent *in, *out; 1054 void *ptr; 1055 1056 in = cookie_in->data; 1057 1058 ptr = cookie_out->data = malloc(sizeof(XIHierarchyEvent) + 1059 in->num_info * sizeof(XIHierarchyInfo)); 1060 if (!ptr) 1061 return False; 1062 1063 out = next_block(&ptr, sizeof(XIHierarchyEvent)); 1064 *out = *in; 1065 out->info = next_block(&ptr, in->num_info * sizeof(XIHierarchyInfo)); 1066 memcpy(out->info, in->info, in->num_info * sizeof(XIHierarchyInfo)); 1067 1068 return True; 1069} 1070 1071static Bool 1072copyDeviceChangedEvent(XGenericEventCookie *in_cookie, 1073 XGenericEventCookie *out_cookie) 1074{ 1075 int len, i; 1076 XIDeviceChangedEvent *in, *out; 1077 XIAnyClassInfo *any; 1078 void *ptr; 1079 1080 in = in_cookie->data; 1081 1082 len = sizeof(XIDeviceChangedEvent); 1083 len += in->num_classes * sizeof(XIAnyClassInfo*); 1084 1085 for (i = 0; i < in->num_classes; i++) 1086 { 1087 any = in->classes[i]; 1088 switch(any->type) 1089 { 1090 case XIButtonClass: 1091 len += sizeDeviceClassType(XIButtonClass, 1092 ((XIButtonClassInfo*)any)->num_buttons); 1093 break; 1094 case XIKeyClass: 1095 len += sizeDeviceClassType(XIKeyClass, 1096 ((XIKeyClassInfo*)any)->num_keycodes); 1097 break; 1098 case XIValuatorClass: 1099 len += sizeDeviceClassType(XIValuatorClass, 0); 1100 break; 1101 default: 1102 printf("copyDeviceChangedEvent: unknown type %d\n", 1103 any->type); 1104 break; 1105 } 1106 1107 } 1108 1109 ptr = out_cookie->data = malloc(len); 1110 if (!ptr) 1111 return False; 1112 out = next_block(&ptr, sizeof(XIDeviceChangedEvent)); 1113 *out = *in; 1114 1115 out->classes = next_block(&ptr, 1116 out->num_classes * sizeof(XIAnyClassInfo*)); 1117 1118 for (i = 0; i < in->num_classes; i++) 1119 { 1120 any = in->classes[i]; 1121 1122 switch(any->type) 1123 { 1124 case XIButtonClass: 1125 { 1126 int size; 1127 XIButtonClassInfo *bin, *bout; 1128 bin = (XIButtonClassInfo*)any; 1129 bout = next_block(&ptr, sizeof(XIButtonClass)); 1130 1131 *bout = *bin; 1132 /* Force mask alignment with longs to avoid unaligned 1133 * access when accessing the atoms. */ 1134 size = bout->state.mask_len/4 * sizeof(Atom); 1135 bout->state.mask = next_block(&ptr, size); 1136 memcpy(bout->state.mask, bin->state.mask, 1137 bout->state.mask_len); 1138 1139 bout->labels = next_block(&ptr, bout->num_buttons * sizeof(Atom)); 1140 memcpy(bout->labels, bin->labels, bout->num_buttons * sizeof(Atom)); 1141 out->classes[i] = (XIAnyClassInfo*)bout; 1142 break; 1143 } 1144 case XIKeyClass: 1145 { 1146 XIKeyClassInfo *kin, *kout; 1147 kin = (XIKeyClassInfo*)any; 1148 1149 kout = next_block(&ptr, sizeof(XIKeyClass)); 1150 *kout = *kin; 1151 kout->keycodes = next_block(&ptr, kout->num_keycodes * sizeof(int)); 1152 memcpy(kout->keycodes, kin->keycodes, kout->num_keycodes * sizeof(int)); 1153 out->classes[i] = (XIAnyClassInfo*)kout; 1154 break; 1155 } 1156 case XIValuatorClass: 1157 { 1158 XIValuatorClassInfo *vin, *vout; 1159 vin = (XIValuatorClassInfo*)any; 1160 vout = next_block(&ptr, sizeof(XIValuatorClass)); 1161 *vout = *vin; 1162 out->classes[i] = (XIAnyClassInfo*)vout; 1163 break; 1164 } 1165 } 1166 } 1167 1168 return True; 1169} 1170 1171static Bool 1172copyDeviceEvent(XGenericEventCookie *cookie_in, 1173 XGenericEventCookie *cookie_out) 1174{ 1175 int len; 1176 XIDeviceEvent *in, *out; 1177 int bits; /* valuator bits */ 1178 void *ptr; 1179 1180 in = cookie_in->data; 1181 bits = count_bits(in->valuators.mask, in->valuators.mask_len); 1182 1183 len = sizeDeviceEvent(in->buttons.mask_len, in->valuators.mask_len, 1184 in->valuators.mask); 1185 1186 ptr = cookie_out->data = malloc(len); 1187 if (!ptr) 1188 return False; 1189 1190 out = next_block(&ptr, sizeof(XIDeviceEvent)); 1191 *out = *in; 1192 1193 out->buttons.mask = next_block(&ptr, in->buttons.mask_len); 1194 memcpy(out->buttons.mask, in->buttons.mask, 1195 out->buttons.mask_len); 1196 out->valuators.mask = next_block(&ptr, in->valuators.mask_len); 1197 memcpy(out->valuators.mask, in->valuators.mask, 1198 out->valuators.mask_len); 1199 out->valuators.values = next_block(&ptr, bits * sizeof(double)); 1200 memcpy(out->valuators.values, in->valuators.values, 1201 bits * sizeof(double)); 1202 1203 return True; 1204} 1205 1206static Bool 1207copyEnterEvent(XGenericEventCookie *cookie_in, 1208 XGenericEventCookie *cookie_out) 1209{ 1210 int len; 1211 XIEnterEvent *in, *out; 1212 void *ptr; 1213 1214 in = cookie_in->data; 1215 1216 len = sizeof(XIEnterEvent) + in->buttons.mask_len; 1217 1218 ptr = cookie_out->data = malloc(len); 1219 if (!ptr) 1220 return False; 1221 1222 out = next_block(&ptr, sizeof(XIEnterEvent)); 1223 *out = *in; 1224 1225 out->buttons.mask = next_block(&ptr, in->buttons.mask_len); 1226 memcpy(out->buttons.mask, in->buttons.mask, out->buttons.mask_len); 1227 1228 return True; 1229} 1230 1231static Bool 1232copyPropertyEvent(XGenericEventCookie *cookie_in, 1233 XGenericEventCookie *cookie_out) 1234{ 1235 XIPropertyEvent *in, *out; 1236 1237 in = cookie_in->data; 1238 1239 out = cookie_out->data = malloc(sizeof(XIPropertyEvent)); 1240 if (!out) 1241 return False; 1242 1243 *out = *in; 1244 return True; 1245} 1246 1247static Bool 1248copyRawEvent(XGenericEventCookie *cookie_in, 1249 XGenericEventCookie *cookie_out) 1250{ 1251 XIRawEvent *in, *out; 1252 void *ptr; 1253 int len; 1254 int bits; 1255 1256 in = cookie_in->data; 1257 1258 bits = count_bits(in->valuators.mask, in->valuators.mask_len); 1259 len = sizeof(XIRawEvent) + in->valuators.mask_len; 1260 len += bits * sizeof(double) * 2; 1261 1262 ptr = cookie_out->data = malloc(len); 1263 if (!ptr) 1264 return False; 1265 1266 out = next_block(&ptr, sizeof(XIRawEvent)); 1267 *out = *in; 1268 out->valuators.mask = next_block(&ptr, out->valuators.mask_len); 1269 memcpy(out->valuators.mask, in->valuators.mask, out->valuators.mask_len); 1270 1271 out->valuators.values = next_block(&ptr, bits * sizeof(double)); 1272 memcpy(out->valuators.values, in->valuators.values, bits * sizeof(double)); 1273 1274 out->raw_values = next_block(&ptr, bits * sizeof(double)); 1275 memcpy(out->raw_values, in->raw_values, bits * sizeof(double)); 1276 1277 return True; 1278} 1279 1280 1281 1282static Bool 1283XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out) 1284{ 1285 int ret = True; 1286 1287 XExtDisplayInfo *info = XInput_find_display(dpy); 1288 1289 if (in->extension != info->codes->major_opcode) 1290 { 1291 printf("XInputCopyCookie: wrong extension opcode %d\n", 1292 in->extension); 1293 return False; 1294 } 1295 1296 *out = *in; 1297 out->data = NULL; 1298 out->cookie = 0; 1299 1300 switch(in->evtype) { 1301 case XI_Motion: 1302 case XI_ButtonPress: 1303 case XI_ButtonRelease: 1304 case XI_KeyPress: 1305 case XI_KeyRelease: 1306 ret = copyDeviceEvent(in, out); 1307 break; 1308 case XI_DeviceChanged: 1309 ret = copyDeviceChangedEvent(in, out); 1310 break; 1311 case XI_HierarchyChanged: 1312 ret = copyHierarchyEvent(in, out); 1313 break; 1314 case XI_Enter: 1315 case XI_Leave: 1316 case XI_FocusIn: 1317 case XI_FocusOut: 1318 ret = copyEnterEvent(in, out); 1319 break; 1320 case XI_PropertyEvent: 1321 ret = copyPropertyEvent(in, out); 1322 break; 1323 case XI_RawKeyPress: 1324 case XI_RawKeyRelease: 1325 case XI_RawButtonPress: 1326 case XI_RawButtonRelease: 1327 case XI_RawMotion: 1328 ret = copyRawEvent(in, out); 1329 break; 1330 default: 1331 printf("XInputCopyCookie: unknown evtype %d\n", in->evtype); 1332 ret = False; 1333 } 1334 1335 if (!ret) 1336 printf("XInputCopyCookie: Failed to copy evtype %d", in->evtype); 1337 return ret; 1338} 1339 1340static int 1341wireToDeviceEvent(xXIDeviceEvent *in, XGenericEventCookie* cookie) 1342{ 1343 int len, i; 1344 unsigned char *ptr; 1345 void *ptr_lib; 1346 FP3232 *values; 1347 XIDeviceEvent *out; 1348 1349 ptr = (unsigned char*)&in[1] + in->buttons_len * 4; 1350 1351 len = sizeDeviceEvent(in->buttons_len * 4, in->valuators_len * 4, ptr); 1352 1353 cookie->data = ptr_lib = malloc(len); 1354 1355 out = next_block(&ptr_lib, sizeof(XIDeviceEvent)); 1356 out->display = cookie->display; 1357 out->type = in->type; 1358 out->extension = in->extension; 1359 out->evtype = in->evtype; 1360 out->send_event = ((in->type & 0x80) != 0); 1361 out->time = in->time; 1362 out->deviceid = in->deviceid; 1363 out->sourceid = in->sourceid; 1364 out->detail = in->detail; 1365 out->root = in->root; 1366 out->event = in->event; 1367 out->child = in->child; 1368 out->root_x = FP1616toDBL(in->root_x); 1369 out->root_y = FP1616toDBL(in->root_y); 1370 out->event_x = FP1616toDBL(in->event_x); 1371 out->event_y = FP1616toDBL(in->event_y); 1372 out->flags = in->flags; 1373 out->mods.base = in->mods.base_mods; 1374 out->mods.locked = in->mods.locked_mods; 1375 out->mods.latched = in->mods.latched_mods; 1376 out->mods.effective = in->mods.effective_mods; 1377 out->group.base = in->group.base_group; 1378 out->group.locked = in->group.locked_group; 1379 out->group.latched = in->group.latched_group; 1380 out->group.effective = in->group.effective_group; 1381 out->buttons.mask_len = in->buttons_len * 4; 1382 out->valuators.mask_len = in->valuators_len * 4; 1383 1384 out->buttons.mask = next_block(&ptr_lib, out->buttons.mask_len); 1385 1386 /* buttons */ 1387 ptr = (unsigned char*)&in[1]; 1388 memcpy(out->buttons.mask, ptr, out->buttons.mask_len); 1389 ptr += in->buttons_len * 4; 1390 1391 /* valuators */ 1392 out->valuators.mask = next_block(&ptr_lib, out->valuators.mask_len); 1393 memcpy(out->valuators.mask, ptr, out->valuators.mask_len); 1394 ptr += in->valuators_len * 4; 1395 1396 len = count_bits(out->valuators.mask, out->valuators.mask_len); 1397 out->valuators.values = next_block(&ptr_lib, len * sizeof(double)); 1398 1399 values = (FP3232*)ptr; 1400 for (i = 0; i < len; i++, values++) 1401 { 1402 out->valuators.values[i] = values->integral; 1403 out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16)); 1404 } 1405 1406 1407 return 1; 1408} 1409 1410_X_HIDDEN int 1411size_classes(xXIAnyInfo* from, int nclasses) 1412{ 1413 int len, i; 1414 xXIAnyInfo *any_wire; 1415 char *ptr_wire; 1416 1417 len = nclasses * sizeof(XIAnyClassInfo*); /* len for to->classes */ 1418 ptr_wire = (char*)from; 1419 for (i = 0; i < nclasses; i++) 1420 { 1421 int l = 0; 1422 any_wire = (xXIAnyInfo*)ptr_wire; 1423 switch(any_wire->type) 1424 { 1425 case XIButtonClass: 1426 l = sizeDeviceClassType(XIButtonClass, 1427 ((xXIButtonInfo*)any_wire)->num_buttons); 1428 break; 1429 case XIKeyClass: 1430 l = sizeDeviceClassType(XIKeyClass, 1431 ((xXIKeyInfo*)any_wire)->num_keycodes); 1432 break; 1433 case XIValuatorClass: 1434 l = sizeDeviceClassType(XIValuatorClass, 0); 1435 break; 1436 } 1437 1438 len += l; 1439 ptr_wire += any_wire->length * 4; 1440 } 1441 1442 return len; 1443} 1444 1445/* Copy classes from any into to->classes and return the number of bytes 1446 * copied. Memory layout of to->classes is 1447 * [clsptr][clsptr][clsptr][classinfo][classinfo]... 1448 * |________|___________^ 1449 * |______________________^ 1450 */ 1451_X_HIDDEN int 1452copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses) 1453{ 1454 XIAnyClassInfo *any_lib; 1455 xXIAnyInfo *any_wire; 1456 void *ptr_lib; 1457 char *ptr_wire; 1458 int i, len; 1459 1460 if (!to->classes) 1461 return -1; 1462 1463 ptr_wire = (char*)from; 1464 ptr_lib = to->classes; 1465 to->classes = next_block(&ptr_lib, nclasses * sizeof(XIAnyClassInfo*)); 1466 len = 0; /* count wire length */ 1467 1468 for (i = 0; i < nclasses; i++) 1469 { 1470 any_lib = (XIAnyClassInfo*)ptr_lib; 1471 any_wire = (xXIAnyInfo*)ptr_wire; 1472 1473 to->classes[i] = any_lib; 1474 any_lib->type = any_wire->type; 1475 any_lib->sourceid = any_wire->sourceid; 1476 switch(any_wire->type) 1477 { 1478 case XIButtonClass: 1479 { 1480 XIButtonClassInfo *cls_lib; 1481 xXIButtonInfo *cls_wire; 1482 uint32_t *atoms; 1483 int size; 1484 int j; 1485 1486 cls_lib = next_block(&ptr_lib, sizeof(XIButtonClassInfo)); 1487 cls_wire = (xXIButtonInfo*)any_wire; 1488 1489 cls_lib->num_buttons = cls_wire->num_buttons; 1490 size = ((((cls_wire->num_buttons + 7)/8) + 3)/4); 1491 cls_lib->state.mask_len = size * 4; 1492 /* Force mask alignment with longs to avoid unaligned 1493 * access when accessing the atoms. */ 1494 cls_lib->state.mask = next_block(&ptr_lib, size * sizeof(Atom)); 1495 memcpy(cls_lib->state.mask, &cls_wire[1], 1496 cls_lib->state.mask_len); 1497 1498 cls_lib->labels = next_block(&ptr_lib, cls_lib->num_buttons * sizeof(Atom)); 1499 atoms =(uint32_t*)((char*)&cls_wire[1] + cls_lib->state.mask_len); 1500 for (j = 0; j < cls_lib->num_buttons; j++) 1501 cls_lib->labels[j] = *atoms++; 1502 1503 break; 1504 } 1505 case XIKeyClass: 1506 { 1507 XIKeyClassInfo *cls_lib; 1508 xXIKeyInfo *cls_wire; 1509 1510 cls_lib = next_block(&ptr_lib, sizeof(XIKeyClassInfo)); 1511 cls_wire = (xXIKeyInfo*)any_wire; 1512 1513 cls_lib->num_keycodes = cls_wire->num_keycodes; 1514 cls_lib->keycodes = next_block(&ptr_lib, 1515 cls_lib->num_keycodes * sizeof(int)); 1516 memcpy(cls_lib->keycodes, &cls_wire[1], 1517 cls_lib->num_keycodes); 1518 1519 break; 1520 } 1521 case XIValuatorClass: 1522 { 1523 XIValuatorClassInfo *cls_lib; 1524 xXIValuatorInfo *cls_wire; 1525 1526 cls_lib = next_block(&ptr_lib, sizeof(XIValuatorClassInfo)); 1527 cls_wire = (xXIValuatorInfo*)any_wire; 1528 1529 cls_lib->number = cls_wire->number; 1530 cls_lib->label = cls_wire->label; 1531 cls_lib->resolution = cls_wire->resolution; 1532 cls_lib->min = cls_wire->min.integral; 1533 cls_lib->max = cls_wire->max.integral; 1534 cls_lib->value = cls_wire->value.integral; 1535 /* FIXME: fractional parts */ 1536 cls_lib->mode = cls_wire->mode; 1537 1538 } 1539 break; 1540 } 1541 len += any_wire->length * 4; 1542 ptr_wire += any_wire->length * 4; 1543 } 1544 return len; 1545} 1546 1547 1548static int 1549wireToDeviceChangedEvent(xXIDeviceChangedEvent *in, XGenericEventCookie *cookie) 1550{ 1551 XIDeviceChangedEvent *out; 1552 XIDeviceInfo info; 1553 int len; 1554 1555 len = size_classes((xXIAnyInfo*)&in[1], in->num_classes); 1556 1557 cookie->data = out = malloc(sizeof(XIDeviceChangedEvent) + len); 1558 1559 out->type = in->type; 1560 out->display = cookie->display; 1561 out->extension = in->extension; 1562 out->evtype = in->evtype; 1563 out->send_event = ((in->type & 0x80) != 0); 1564 out->time = in->time; 1565 out->deviceid = in->deviceid; 1566 out->sourceid = in->sourceid; 1567 out->reason = in->reason; 1568 out->num_classes = in->num_classes; 1569 1570 out->classes = (XIAnyClassInfo**)&out[1]; 1571 1572 info.classes = out->classes; 1573 1574 copy_classes(&info, (xXIAnyInfo*)&in[1], in->num_classes); 1575 1576 return 1; 1577} 1578 1579static int 1580wireToHierarchyChangedEvent(xXIHierarchyEvent *in, XGenericEventCookie *cookie) 1581{ 1582 int i; 1583 XIHierarchyInfo *info_out; 1584 xXIHierarchyInfo *info_in; 1585 XIHierarchyEvent *out; 1586 1587 cookie->data = out = malloc(sizeof(XIHierarchyEvent) + in->num_info * sizeof(XIHierarchyInfo));; 1588 1589 out->info = (XIHierarchyInfo*)&out[1]; 1590 out->display = cookie->display; 1591 out->type = in->type; 1592 out->extension = in->extension; 1593 out->evtype = in->evtype; 1594 out->send_event = ((in->type & 0x80) != 0); 1595 out->time = in->time; 1596 out->flags = in->flags; 1597 out->num_info = in->num_info; 1598 1599 info_out = out->info; 1600 info_in = (xXIHierarchyInfo*)&in[1]; 1601 1602 for (i = 0; i < out->num_info; i++, info_out++, info_in++) 1603 { 1604 info_out->deviceid = info_in->deviceid; 1605 info_out->attachment = info_in->attachment; 1606 info_out->use = info_in->use; 1607 info_out->enabled = info_in->enabled; 1608 info_out->flags = info_in->flags; 1609 } 1610 1611 return 1; 1612} 1613 1614static int 1615wireToRawEvent(xXIRawEvent *in, XGenericEventCookie *cookie) 1616{ 1617 int len, i, bits; 1618 FP3232 *values; 1619 XIRawEvent *out; 1620 void *ptr; 1621 1622 1623 len = sizeof(XIRawEvent) + in->valuators_len * 4; 1624 bits = count_bits((unsigned char*)&in[1], in->valuators_len * 4); 1625 len += bits * sizeof(double) * 2; /* raw + normal */ 1626 1627 cookie->data = ptr = calloc(1, len); 1628 if (!ptr) 1629 return 0; 1630 1631 out = next_block(&ptr, sizeof(XIRawEvent)); 1632 out->type = in->type; 1633 out->display = cookie->display; 1634 out->extension = in->extension; 1635 out->evtype = in->evtype; 1636 out->send_event = ((in->type & 0x80) != 0); 1637 out->time = in->time; 1638 out->detail = in->detail; 1639 out->deviceid = in->deviceid; 1640 out->sourceid = 0; /* https://bugs.freedesktop.org/show_bug.cgi?id=34240 */ 1641 out->flags = in->flags; 1642 1643 out->valuators.mask_len = in->valuators_len * 4; 1644 out->valuators.mask = next_block(&ptr, out->valuators.mask_len); 1645 memcpy(out->valuators.mask, &in[1], out->valuators.mask_len); 1646 1647 out->valuators.values = next_block(&ptr, bits * sizeof(double)); 1648 out->raw_values = next_block(&ptr, bits * sizeof(double)); 1649 1650 values = (FP3232*)(((char*)&in[1]) + in->valuators_len * 4); 1651 for (i = 0; i < bits; i++) 1652 { 1653 out->valuators.values[i] = values->integral; 1654 out->valuators.values[i] += ((double)values->frac / (1 << 16) / (1 << 16)); 1655 out->raw_values[i] = (values + bits)->integral; 1656 out->raw_values[i] += ((double)(values + bits)->frac / (1 << 16) / (1 << 16)); 1657 values++; 1658 } 1659 1660 return 1; 1661} 1662 1663/* Memory layout of XIEnterEvents: 1664 [event][modifiers][group][button] 1665 */ 1666static int 1667wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie) 1668{ 1669 int len; 1670 XIEnterEvent *out; 1671 1672 len = sizeof(XIEnterEvent) + in->buttons_len * 4; 1673 1674 cookie->data = out = malloc(len); 1675 out->buttons.mask = (unsigned char*)&out[1]; 1676 1677 out->type = in->type; 1678 out->display = cookie->display; 1679 out->extension = in->extension; 1680 out->evtype = in->evtype; 1681 out->send_event = ((in->type & 0x80) != 0); 1682 out->time = in->time; 1683 out->detail = in->detail; 1684 out->deviceid = in->deviceid; 1685 out->root = in->root; 1686 out->event = in->event; 1687 out->child = in->child; 1688 out->sourceid = in->sourceid; 1689 out->root_x = FP1616toDBL(in->root_x); 1690 out->root_y = FP1616toDBL(in->root_y); 1691 out->event_x = FP1616toDBL(in->event_x); 1692 out->event_y = FP1616toDBL(in->event_y); 1693 out->mode = in->mode; 1694 out->focus = in->focus; 1695 out->same_screen = in->same_screen; 1696 1697 out->mods.base = in->mods.base_mods; 1698 out->mods.locked = in->mods.locked_mods; 1699 out->mods.latched = in->mods.latched_mods; 1700 out->mods.effective = in->mods.effective_mods; 1701 out->group.base = in->group.base_group; 1702 out->group.locked = in->group.locked_group; 1703 out->group.latched = in->group.latched_group; 1704 out->group.effective = in->group.effective_group; 1705 1706 out->buttons.mask_len = in->buttons_len * 4; 1707 memcpy(out->buttons.mask, &in[1], out->buttons.mask_len); 1708 1709 return 1; 1710} 1711 1712static int 1713wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie) 1714{ 1715 XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent)); 1716 1717 cookie->data = out; 1718 1719 out->type = in->type; 1720 out->extension = in->extension; 1721 out->evtype = in->evtype; 1722 out->send_event = ((in->type & 0x80) != 0); 1723 out->time = in->time; 1724 out->property = in->property; 1725 out->what = in->what; 1726 out->deviceid = in->deviceid; 1727 1728 return 1; 1729} 1730