1/* 2 * Copyright © 2009 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25/** 26 * @file eventconvert.c 27 * This file contains event conversion routines from InternalEvent to the 28 * matching protocol events. 29 */ 30 31#ifdef HAVE_DIX_CONFIG_H 32#include <dix-config.h> 33#endif 34 35#include <stdint.h> 36#include <X11/X.h> 37#include <X11/extensions/XIproto.h> 38#include <X11/extensions/XI2proto.h> 39#include <X11/extensions/XI.h> 40#include <X11/extensions/XI2.h> 41 42#include "dix.h" 43#include "inputstr.h" 44#include "misc.h" 45#include "eventstr.h" 46#include "exglobals.h" 47#include "eventconvert.h" 48#include "xiquerydevice.h" 49#include "xkbsrv.h" 50 51 52static int countValuators(DeviceEvent *ev, int *first); 53static int getValuatorEvents(DeviceEvent *ev, deviceValuator *xv); 54static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count); 55static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce); 56static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi); 57static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi); 58 59/* Do not use, read comments below */ 60BOOL EventIsKeyRepeat(xEvent *event); 61 62/** 63 * Hack to allow detectable autorepeat for core and XI1 events. 64 * The sequence number is unused until we send to the client and can be 65 * misused to store data. More or less, anyway. 66 * 67 * Do not use this. It may change any time without warning, eat your babies 68 * and piss on your cat. 69 */ 70static void 71EventSetKeyRepeatFlag(xEvent *event, BOOL on) 72{ 73 event->u.u.sequenceNumber = on; 74} 75 76/** 77 * Check if the event was marked as a repeat event before. 78 * NOTE: This is a nasty hack and should NOT be used by anyone else but 79 * TryClientEvents. 80 */ 81BOOL 82EventIsKeyRepeat(xEvent *event) 83{ 84 return !!event->u.u.sequenceNumber; 85} 86 87/** 88 * Convert the given event to the respective core event. 89 * 90 * Return values: 91 * Success ... core contains the matching core event. 92 * BadValue .. One or more values in the internal event are invalid. 93 * BadMatch .. The event has no core equivalent. 94 * 95 * @param[in] event The event to convert into a core event. 96 * @param[in] core The memory location to store the core event at. 97 * @return Success or the matching error code. 98 */ 99int 100EventToCore(InternalEvent *event, xEvent *core) 101{ 102 switch(event->any.type) 103 { 104 case ET_Motion: 105 { 106 DeviceEvent *e = &event->device_event; 107 /* Don't create core motion event if neither x nor y are 108 * present */ 109 if (!BitIsOn(e->valuators.mask, 0) && 110 !BitIsOn(e->valuators.mask, 1)) 111 return BadMatch; 112 } 113 /* fallthrough */ 114 case ET_ButtonPress: 115 case ET_ButtonRelease: 116 case ET_KeyPress: 117 case ET_KeyRelease: 118 { 119 DeviceEvent *e = &event->device_event; 120 121 if (e->detail.key > 0xFF) 122 return BadMatch; 123 124 memset(core, 0, sizeof(xEvent)); 125 core->u.u.type = e->type - ET_KeyPress + KeyPress; 126 core->u.u.detail = e->detail.key & 0xFF; 127 core->u.keyButtonPointer.time = e->time; 128 core->u.keyButtonPointer.rootX = e->root_x; 129 core->u.keyButtonPointer.rootY = e->root_y; 130 core->u.keyButtonPointer.state = e->corestate; 131 core->u.keyButtonPointer.root = e->root; 132 EventSetKeyRepeatFlag(core, (e->type == ET_KeyPress && e->key_repeat)); 133 } 134 break; 135 case ET_ProximityIn: 136 case ET_ProximityOut: 137 case ET_RawKeyPress: 138 case ET_RawKeyRelease: 139 case ET_RawButtonPress: 140 case ET_RawButtonRelease: 141 case ET_RawMotion: 142 return BadMatch; 143 default: 144 /* XXX: */ 145 ErrorF("[dix] EventToCore: Not implemented yet \n"); 146 return BadImplementation; 147 } 148 return Success; 149} 150 151/** 152 * Convert the given event to the respective XI 1.x event and store it in 153 * xi. xi is allocated on demand and must be freed by the caller. 154 * count returns the number of events in xi. If count is 1, and the type of 155 * xi is GenericEvent, then xi may be larger than 32 bytes. 156 * 157 * Return values: 158 * Success ... core contains the matching core event. 159 * BadValue .. One or more values in the internal event are invalid. 160 * BadMatch .. The event has no XI equivalent. 161 * 162 * @param[in] ev The event to convert into an XI 1 event. 163 * @param[out] xi Future memory location for the XI event. 164 * @param[out] count Number of elements in xi. 165 * 166 * @return Success or the error code. 167 */ 168int 169EventToXI(InternalEvent *ev, xEvent **xi, int *count) 170{ 171 switch (ev->any.type) 172 { 173 case ET_Motion: 174 case ET_ButtonPress: 175 case ET_ButtonRelease: 176 case ET_KeyPress: 177 case ET_KeyRelease: 178 case ET_ProximityIn: 179 case ET_ProximityOut: 180 return eventToKeyButtonPointer(&ev->device_event, xi, count); 181 case ET_DeviceChanged: 182 case ET_RawKeyPress: 183 case ET_RawKeyRelease: 184 case ET_RawButtonPress: 185 case ET_RawButtonRelease: 186 case ET_RawMotion: 187 *count = 0; 188 *xi = NULL; 189 return BadMatch; 190 default: 191 break; 192 } 193 194 ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->any.type); 195 return BadImplementation; 196} 197 198/** 199 * Convert the given event to the respective XI 2.x event and store it in xi. 200 * xi is allocated on demand and must be freed by the caller. 201 * 202 * Return values: 203 * Success ... core contains the matching core event. 204 * BadValue .. One or more values in the internal event are invalid. 205 * BadMatch .. The event has no XI2 equivalent. 206 * 207 * @param[in] ev The event to convert into an XI2 event 208 * @param[out] xi Future memory location for the XI2 event. 209 * 210 * @return Success or the error code. 211 */ 212int 213EventToXI2(InternalEvent *ev, xEvent **xi) 214{ 215 switch (ev->any.type) 216 { 217 /* Enter/FocusIn are for grabs. We don't need an actual event, since 218 * the real events delivered are triggered elsewhere */ 219 case ET_Enter: 220 case ET_FocusIn: 221 *xi = NULL; 222 return Success; 223 case ET_Motion: 224 case ET_ButtonPress: 225 case ET_ButtonRelease: 226 case ET_KeyPress: 227 case ET_KeyRelease: 228 return eventToDeviceEvent(&ev->device_event, xi); 229 case ET_ProximityIn: 230 case ET_ProximityOut: 231 *xi = NULL; 232 return BadMatch; 233 case ET_DeviceChanged: 234 return eventToDeviceChanged(&ev->changed_event, xi); 235 case ET_RawKeyPress: 236 case ET_RawKeyRelease: 237 case ET_RawButtonPress: 238 case ET_RawButtonRelease: 239 case ET_RawMotion: 240 return eventToRawEvent(&ev->raw_event, xi); 241 default: 242 break; 243 } 244 245 ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->any.type); 246 return BadImplementation; 247} 248 249static int 250eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count) 251{ 252 int num_events; 253 int first; /* dummy */ 254 deviceKeyButtonPointer *kbp; 255 256 /* Sorry, XI 1.x protocol restrictions. */ 257 if (ev->detail.button > 0xFF || ev->deviceid >= 0x80) 258 { 259 *count = 0; 260 return Success; 261 } 262 263 num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */ 264 if (num_events <= 0) 265 { 266 switch (ev->type) 267 { 268 case ET_KeyPress: 269 case ET_KeyRelease: 270 case ET_ButtonPress: 271 case ET_ButtonRelease: 272 /* no axes is ok */ 273 break; 274 case ET_Motion: 275 case ET_ProximityIn: 276 case ET_ProximityOut: 277 *count = 0; 278 return BadMatch; 279 } 280 } 281 282 num_events++; /* the actual event event */ 283 284 *xi = calloc(num_events, sizeof(xEvent)); 285 if (!(*xi)) 286 { 287 return BadAlloc; 288 } 289 290 kbp = (deviceKeyButtonPointer*)(*xi); 291 kbp->detail = ev->detail.button; 292 kbp->time = ev->time; 293 kbp->root = ev->root; 294 kbp->root_x = ev->root_x; 295 kbp->root_y = ev->root_y; 296 kbp->deviceid = ev->deviceid; 297 kbp->state = ev->corestate; 298 EventSetKeyRepeatFlag((xEvent*)kbp, 299 (ev->type == ET_KeyPress && ev->key_repeat)); 300 301 if (num_events > 1) 302 kbp->deviceid |= MORE_EVENTS; 303 304 switch(ev->type) 305 { 306 case ET_Motion: kbp->type = DeviceMotionNotify; break; 307 case ET_ButtonPress: kbp->type = DeviceButtonPress; break; 308 case ET_ButtonRelease: kbp->type = DeviceButtonRelease; break; 309 case ET_KeyPress: kbp->type = DeviceKeyPress; break; 310 case ET_KeyRelease: kbp->type = DeviceKeyRelease; break; 311 case ET_ProximityIn: kbp->type = ProximityIn; break; 312 case ET_ProximityOut: kbp->type = ProximityOut; break; 313 default: 314 break; 315 } 316 317 if (num_events > 1) 318 { 319 getValuatorEvents(ev, (deviceValuator*)(kbp + 1)); 320 } 321 322 *count = num_events; 323 return Success; 324} 325 326 327/** 328 * Set first to the first valuator in the event ev and return the number of 329 * valuators from first to the last set valuator. 330 */ 331static int 332countValuators(DeviceEvent *ev, int *first) 333{ 334 int first_valuator = -1, last_valuator = -1, num_valuators = 0; 335 int i; 336 337 for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) 338 { 339 if (BitIsOn(ev->valuators.mask, i)) 340 { 341 if (first_valuator == -1) 342 first_valuator = i; 343 last_valuator = i; 344 } 345 } 346 347 if (first_valuator != -1) 348 { 349 num_valuators = last_valuator - first_valuator + 1; 350 *first = first_valuator; 351 } 352 353 return num_valuators; 354} 355 356static int 357getValuatorEvents(DeviceEvent *ev, deviceValuator *xv) 358{ 359 int i; 360 int state = 0; 361 int first_valuator, num_valuators; 362 363 364 num_valuators = countValuators(ev, &first_valuator); 365 if (num_valuators > 0) 366 { 367 DeviceIntPtr dev = NULL; 368 dixLookupDevice(&dev, ev->deviceid, serverClient, DixUseAccess); 369 /* State needs to be assembled BEFORE the device is updated. */ 370 state = (dev && dev->key) ? XkbStateFieldFromRec(&dev->key->xkbInfo->state) : 0; 371 state |= (dev && dev->button) ? (dev->button->state) : 0; 372 } 373 374 for (i = 0; i < num_valuators; i += 6, xv++) { 375 INT32 *valuators = &xv->valuator0; // Treat all 6 vals as an array 376 int j; 377 378 xv->type = DeviceValuator; 379 xv->first_valuator = first_valuator + i; 380 xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); 381 xv->deviceid = ev->deviceid; 382 xv->device_state = state; 383 384 /* Unset valuators in masked valuator events have the proper data values 385 * in the case of an absolute axis in between two set valuators. */ 386 for (j = 0; j < xv->num_valuators; j++) 387 valuators[j] = ev->valuators.data[xv->first_valuator + j]; 388 389 if (i + 6 < num_valuators) 390 xv->deviceid |= MORE_EVENTS; 391 } 392 393 return (num_valuators + 5) / 6; 394} 395 396 397static int 398appendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo* info) 399{ 400 uint32_t *kc; 401 int i; 402 403 info->type = XIKeyClass; 404 info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1; 405 info->length = sizeof(xXIKeyInfo)/4 + info->num_keycodes; 406 info->sourceid = dce->sourceid; 407 408 kc = (uint32_t*)&info[1]; 409 for (i = 0; i < info->num_keycodes; i++) 410 *kc++ = i + dce->keys.min_keycode; 411 412 return info->length * 4; 413} 414 415static int 416appendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo *info) 417{ 418 unsigned char *bits; 419 int mask_len; 420 421 mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons)); 422 423 info->type = XIButtonClass; 424 info->num_buttons = dce->buttons.num_buttons; 425 info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + 426 info->num_buttons + mask_len; 427 info->sourceid = dce->sourceid; 428 429 bits = (unsigned char*)&info[1]; 430 memset(bits, 0, mask_len * 4); 431 /* FIXME: is_down? */ 432 433 bits += mask_len * 4; 434 memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom)); 435 436 return info->length * 4; 437} 438 439static int 440appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumber) 441{ 442 info->type = XIValuatorClass; 443 info->length = sizeof(xXIValuatorInfo)/4; 444 info->label = dce->valuators[axisnumber].name; 445 info->min.integral = dce->valuators[axisnumber].min; 446 info->min.frac = 0; 447 info->max.integral = dce->valuators[axisnumber].max; 448 info->max.frac = 0; 449 /* FIXME: value */ 450 info->value.integral = 0; 451 info->value.frac = 0; 452 info->resolution = dce->valuators[axisnumber].resolution; 453 info->number = axisnumber; 454 info->mode = dce->valuators[axisnumber].mode; 455 info->sourceid = dce->sourceid; 456 457 return info->length * 4; 458} 459 460static int 461eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) 462{ 463 xXIDeviceChangedEvent *dcce; 464 int len = sizeof(xXIDeviceChangedEvent); 465 int nkeys; 466 char *ptr; 467 468 if (dce->buttons.num_buttons) 469 { 470 len += sizeof(xXIButtonInfo); 471 len += dce->buttons.num_buttons * sizeof(Atom); /* button names */ 472 len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons)); 473 } 474 if (dce->num_valuators) 475 len += sizeof(xXIValuatorInfo) * dce->num_valuators; 476 477 nkeys = (dce->keys.max_keycode > 0) ? 478 dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0; 479 if (nkeys > 0) 480 { 481 len += sizeof(xXIKeyInfo); 482 len += sizeof(CARD32) * nkeys; /* keycodes */ 483 } 484 485 dcce = calloc(1, len); 486 if (!dcce) 487 { 488 ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n"); 489 return BadAlloc; 490 } 491 492 dcce->type = GenericEvent; 493 dcce->extension = IReqCode; 494 dcce->evtype = XI_DeviceChanged; 495 dcce->time = dce->time; 496 dcce->deviceid = dce->deviceid; 497 dcce->sourceid = dce->sourceid; 498 dcce->reason = (dce->flags & DEVCHANGE_DEVICE_CHANGE) ? XIDeviceChange : XISlaveSwitch; 499 dcce->num_classes = 0; 500 dcce->length = bytes_to_int32(len - sizeof(xEvent)); 501 502 ptr = (char*)&dcce[1]; 503 if (dce->buttons.num_buttons) 504 { 505 dcce->num_classes++; 506 ptr += appendButtonInfo(dce, (xXIButtonInfo*)ptr); 507 } 508 509 if (nkeys) 510 { 511 dcce->num_classes++; 512 ptr += appendKeyInfo(dce, (xXIKeyInfo*)ptr); 513 } 514 515 if (dce->num_valuators) 516 { 517 int i; 518 519 dcce->num_classes += dce->num_valuators; 520 for (i = 0; i < dce->num_valuators; i++) 521 ptr += appendValuatorInfo(dce, (xXIValuatorInfo*)ptr, i); 522 } 523 524 *xi = (xEvent*)dcce; 525 526 return Success; 527} 528 529static int count_bits(unsigned char* ptr, int len) 530{ 531 int bits = 0; 532 unsigned int i; 533 unsigned char x; 534 535 for (i = 0; i < len; i++) 536 { 537 x = ptr[i]; 538 while(x > 0) 539 { 540 bits += (x & 0x1); 541 x >>= 1; 542 } 543 } 544 return bits; 545} 546 547static int 548eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) 549{ 550 int len = sizeof(xXIDeviceEvent); 551 xXIDeviceEvent *xde; 552 int i, btlen, vallen; 553 char *ptr; 554 FP3232 *axisval; 555 556 /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same 557 * with MAX_VALUATORS below */ 558 /* btlen is in 4 byte units */ 559 btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS)); 560 len += btlen * 4; /* buttonmask len */ 561 562 563 vallen = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)/sizeof(ev->valuators.mask[0])); 564 len += vallen * 2 * sizeof(uint32_t); /* axisvalues */ 565 vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); 566 len += vallen * 4; /* valuators mask */ 567 568 *xi = calloc(1, len); 569 xde = (xXIDeviceEvent*)*xi; 570 xde->type = GenericEvent; 571 xde->extension = IReqCode; 572 xde->evtype = GetXI2Type((InternalEvent*)ev); 573 xde->time = ev->time; 574 xde->length = bytes_to_int32(len - sizeof(xEvent)); 575 xde->detail = ev->detail.button; 576 xde->root = ev->root; 577 xde->buttons_len = btlen; 578 xde->valuators_len = vallen; 579 xde->deviceid = ev->deviceid; 580 xde->sourceid = ev->sourceid; 581 xde->root_x = FP1616(ev->root_x, ev->root_x_frac); 582 xde->root_y = FP1616(ev->root_y, ev->root_y_frac); 583 584 if (ev->key_repeat) 585 xde->flags |= XIKeyRepeat; 586 587 xde->mods.base_mods = ev->mods.base; 588 xde->mods.latched_mods = ev->mods.latched; 589 xde->mods.locked_mods = ev->mods.locked; 590 xde->mods.effective_mods = ev->mods.effective; 591 592 xde->group.base_group = ev->group.base; 593 xde->group.latched_group = ev->group.latched; 594 xde->group.locked_group = ev->group.locked; 595 xde->group.effective_group = ev->group.effective; 596 597 ptr = (char*)&xde[1]; 598 for (i = 0; i < sizeof(ev->buttons) * 8; i++) 599 { 600 if (BitIsOn(ev->buttons, i)) 601 SetBit(ptr, i); 602 } 603 604 ptr += xde->buttons_len * 4; 605 axisval = (FP3232*)(ptr + xde->valuators_len * 4); 606 for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) 607 { 608 if (BitIsOn(ev->valuators.mask, i)) 609 { 610 SetBit(ptr, i); 611 axisval->integral = ev->valuators.data[i]; 612 axisval->frac = ev->valuators.data_frac[i]; 613 axisval++; 614 } 615 } 616 617 return Success; 618} 619 620static int 621eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) 622{ 623 xXIRawEvent* raw; 624 int vallen, nvals; 625 int i, len = sizeof(xXIRawEvent); 626 char *ptr; 627 FP3232 *axisval; 628 629 nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)); 630 len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once 631 raw, once processed */ 632 vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); 633 len += vallen * 4; /* valuators mask */ 634 635 *xi = calloc(1, len); 636 raw = (xXIRawEvent*)*xi; 637 raw->type = GenericEvent; 638 raw->extension = IReqCode; 639 raw->evtype = GetXI2Type((InternalEvent*)ev); 640 raw->time = ev->time; 641 raw->length = bytes_to_int32(len - sizeof(xEvent)); 642 raw->detail = ev->detail.button; 643 raw->deviceid = ev->deviceid; 644 raw->valuators_len = vallen; 645 646 ptr = (char*)&raw[1]; 647 axisval = (FP3232*)(ptr + raw->valuators_len * 4); 648 for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) 649 { 650 if (BitIsOn(ev->valuators.mask, i)) 651 { 652 SetBit(ptr, i); 653 axisval->integral = ev->valuators.data[i]; 654 axisval->frac = ev->valuators.data_frac[i]; 655 (axisval + nvals)->integral = ev->valuators.data_raw[i]; 656 (axisval + nvals)->frac = ev->valuators.data_raw_frac[i]; 657 axisval++; 658 } 659 } 660 661 return Success; 662} 663 664/** 665 * Return the corresponding core type for the given event or 0 if no core 666 * equivalent exists. 667 */ 668int 669GetCoreType(InternalEvent *event) 670{ 671 int coretype = 0; 672 switch(event->any.type) 673 { 674 case ET_Motion: coretype = MotionNotify; break; 675 case ET_ButtonPress: coretype = ButtonPress; break; 676 case ET_ButtonRelease: coretype = ButtonRelease; break; 677 case ET_KeyPress: coretype = KeyPress; break; 678 case ET_KeyRelease: coretype = KeyRelease; break; 679 default: 680 break; 681 } 682 return coretype; 683} 684 685/** 686 * Return the corresponding XI 1.x type for the given event or 0 if no 687 * equivalent exists. 688 */ 689int 690GetXIType(InternalEvent *event) 691{ 692 int xitype = 0; 693 switch(event->any.type) 694 { 695 case ET_Motion: xitype = DeviceMotionNotify; break; 696 case ET_ButtonPress: xitype = DeviceButtonPress; break; 697 case ET_ButtonRelease: xitype = DeviceButtonRelease; break; 698 case ET_KeyPress: xitype = DeviceKeyPress; break; 699 case ET_KeyRelease: xitype = DeviceKeyRelease; break; 700 case ET_ProximityIn: xitype = ProximityIn; break; 701 case ET_ProximityOut: xitype = ProximityOut; break; 702 default: 703 break; 704 } 705 return xitype; 706} 707 708/** 709 * Return the corresponding XI 2.x type for the given event or 0 if no 710 * equivalent exists. 711 */ 712int 713GetXI2Type(InternalEvent *event) 714{ 715 int xi2type = 0; 716 717 switch(event->any.type) 718 { 719 case ET_Motion: xi2type = XI_Motion; break; 720 case ET_ButtonPress: xi2type = XI_ButtonPress; break; 721 case ET_ButtonRelease: xi2type = XI_ButtonRelease; break; 722 case ET_KeyPress: xi2type = XI_KeyPress; break; 723 case ET_KeyRelease: xi2type = XI_KeyRelease; break; 724 case ET_Enter: xi2type = XI_Enter; break; 725 case ET_Leave: xi2type = XI_Leave; break; 726 case ET_Hierarchy: xi2type = XI_HierarchyChanged; break; 727 case ET_DeviceChanged: xi2type = XI_DeviceChanged; break; 728 case ET_RawKeyPress: xi2type = XI_RawKeyPress; break; 729 case ET_RawKeyRelease: xi2type = XI_RawKeyRelease; break; 730 case ET_RawButtonPress: xi2type = XI_RawButtonPress; break; 731 case ET_RawButtonRelease: xi2type = XI_RawButtonRelease; break; 732 case ET_RawMotion: xi2type = XI_RawMotion; break; 733 case ET_FocusIn: xi2type = XI_FocusIn; break; 734 case ET_FocusOut: xi2type = XI_FocusOut; break; 735 default: 736 break; 737 } 738 return xi2type; 739} 740