1/************************************************************ 2Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_CONFIG_H 28#include <config.h> 29#endif 30#include <stdio.h> 31#define NEED_MAP_READERS 32#include "Xlibint.h" 33#include <X11/extensions/XKBproto.h> 34#include "XKBlibint.h" 35#include <X11/extensions/XI.h> 36 37/***====================================================================***/ 38 39void 40XkbNoteDeviceChanges(XkbDeviceChangesPtr old, 41 XkbExtensionDeviceNotifyEvent *new, 42 unsigned int wanted) 43{ 44 if ((!old) || (!new) || (!wanted) || ((new->reason & wanted) == 0)) 45 return; 46 if ((wanted & new->reason) & XkbXI_ButtonActionsMask) { 47 if (old->changed & XkbXI_ButtonActionsMask) { 48 int first, last, newLast; 49 50 if (new->first_btn < old->first_btn) 51 first = new->first_btn; 52 else 53 first = old->first_btn; 54 last = old->first_btn + old->num_btns - 1; 55 newLast = new->first_btn + new->num_btns - 1; 56 if (newLast > last) 57 last = newLast; 58 old->first_btn = first; 59 old->num_btns = (last - first) + 1; 60 } 61 else { 62 old->changed |= XkbXI_ButtonActionsMask; 63 old->first_btn = new->first_btn; 64 old->num_btns = new->num_btns; 65 } 66 } 67 if ((wanted & new->reason) & XkbXI_IndicatorsMask) { 68 XkbDeviceLedChangesPtr this; 69 70 if (old->changed & XkbXI_IndicatorsMask) { 71 XkbDeviceLedChangesPtr found = NULL; 72 73 for (this = &old->leds; this && (!found); this = this->next) { 74 if ((this->led_class == new->led_class) && 75 (this->led_id == new->led_id)) { 76 found = this; 77 } 78 } 79 if (!found) { 80 found = _XkbTypedCalloc(1, XkbDeviceLedChangesRec); 81 if (!found) 82 return; 83 found->next = old->leds.next; 84 found->led_class = new->led_class; 85 found->led_id = new->led_id; 86 old->leds.next = found; 87 } 88 if ((wanted & new->reason) & XkbXI_IndicatorNamesMask) 89 found->defined = new->leds_defined; 90 } 91 else { 92 old->changed |= ((wanted & new->reason) & XkbXI_IndicatorsMask); 93 old->leds.led_class = new->led_class; 94 old->leds.led_id = new->led_id; 95 old->leds.defined = new->leds_defined; 96 if (old->leds.next) { 97 XkbDeviceLedChangesPtr next; 98 99 for (this = old->leds.next; this; this = next) { 100 next = this->next; 101 _XkbFree(this); 102 } 103 old->leds.next = NULL; 104 } 105 } 106 } 107 return; 108} 109 110/***====================================================================***/ 111 112static Status 113_XkbReadDeviceLedInfo(XkbReadBufferPtr buf, 114 unsigned present, 115 XkbDeviceInfoPtr devi) 116{ 117 register unsigned i, bit; 118 XkbDeviceLedInfoPtr devli; 119 xkbDeviceLedsWireDesc *wireli; 120 121 wireli = _XkbGetTypedRdBufPtr(buf, 1, xkbDeviceLedsWireDesc); 122 if (!wireli) 123 return BadLength; 124 devli = XkbAddDeviceLedInfo(devi, wireli->ledClass, wireli->ledID); 125 if (!devli) 126 return BadAlloc; 127 devli->phys_indicators = wireli->physIndicators; 128 129 if (present & XkbXI_IndicatorStateMask) 130 devli->state = wireli->state; 131 132 if (present & XkbXI_IndicatorNamesMask) { 133 devli->names_present = wireli->namesPresent; 134 if (devli->names_present) { 135 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 136 if (wireli->namesPresent & bit) { 137 if (!_XkbCopyFromReadBuffer(buf, 138 (char *) &devli->names[i], 4)) 139 return BadLength; 140 } 141 } 142 } 143 } 144 145 if (present & XkbXI_IndicatorMapsMask) { 146 devli->maps_present = wireli->mapsPresent; 147 if (devli->maps_present) { 148 XkbIndicatorMapPtr im; 149 xkbIndicatorMapWireDesc *wireim; 150 151 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 152 if (wireli->mapsPresent & bit) { 153 wireim = 154 _XkbGetTypedRdBufPtr(buf, 1, xkbIndicatorMapWireDesc); 155 if (!wireim) 156 return BadAlloc; 157 im = &devli->maps[i]; 158 im->flags = wireim->flags; 159 im->which_groups = wireim->whichGroups; 160 im->groups = wireim->groups; 161 im->which_mods = wireim->whichMods; 162 im->mods.mask = wireim->mods; 163 im->mods.real_mods = wireim->realMods; 164 im->mods.vmods = wireim->virtualMods; 165 im->ctrls = wireim->ctrls; 166 } 167 } 168 } 169 } 170 return Success; 171} 172 173static Status 174_XkbReadGetDeviceInfoReply(Display *dpy, 175 xkbGetDeviceInfoReply *rep, 176 XkbDeviceInfoPtr devi) 177{ 178 XkbReadBufferRec buf; 179 XkbAction *act; 180 int tmp; 181 182 if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4)) 183 return BadAlloc; 184 185 if ((rep->totalBtns > 0) && (rep->totalBtns != devi->num_btns)) { 186 tmp = XkbResizeDeviceButtonActions(devi, rep->totalBtns); 187 if (tmp != Success) 188 return tmp; 189 } 190 if (rep->nBtnsWanted > 0) { 191 if (((unsigned short) rep->firstBtnWanted + rep->nBtnsWanted) > devi->num_btns) 192 goto BAILOUT; 193 act = &devi->btn_acts[rep->firstBtnWanted]; 194 bzero((char *) act, (rep->nBtnsWanted * sizeof(XkbAction))); 195 } 196 197 _XkbFree(devi->name); 198 if (!_XkbGetReadBufferCountedString(&buf, &devi->name)) 199 goto BAILOUT; 200 if (rep->nBtnsRtrn > 0) { 201 int size; 202 203 if (((unsigned short) rep->firstBtnRtrn + rep->nBtnsRtrn) > devi->num_btns) 204 goto BAILOUT; 205 act = &devi->btn_acts[rep->firstBtnRtrn]; 206 size = rep->nBtnsRtrn * SIZEOF(xkbActionWireDesc); 207 if (!_XkbCopyFromReadBuffer(&buf, (char *) act, size)) 208 goto BAILOUT; 209 } 210 if (rep->nDeviceLedFBs > 0) { 211 register int i; 212 213 for (i = 0; i < rep->nDeviceLedFBs; i++) { 214 if ((tmp = _XkbReadDeviceLedInfo(&buf, rep->present, devi)) 215 != Success) 216 return tmp; 217 } 218 } 219 tmp = _XkbFreeReadBuffer(&buf); 220 if (tmp) 221 fprintf(stderr, "GetDeviceInfo! Bad length (%d extra bytes)\n", tmp); 222 if (tmp || buf.error) 223 return BadLength; 224 return Success; 225 BAILOUT: 226 _XkbFreeReadBuffer(&buf); 227 return BadLength; 228} 229 230XkbDeviceInfoPtr 231XkbGetDeviceInfo(Display *dpy, 232 unsigned which, 233 unsigned deviceSpec, 234 unsigned class, 235 unsigned id) 236{ 237 register xkbGetDeviceInfoReq *req; 238 xkbGetDeviceInfoReply rep; 239 Status status; 240 XkbDeviceInfoPtr devi; 241 242 if ((dpy->flags & XlibDisplayNoXkb) || 243 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 244 return NULL; 245 LockDisplay(dpy); 246 GetReq(kbGetDeviceInfo, req); 247 req->reqType = dpy->xkb_info->codes->major_opcode; 248 req->xkbReqType = X_kbGetDeviceInfo; 249 req->deviceSpec = deviceSpec; 250 req->wanted = which; 251 req->allBtns = ((which & XkbXI_ButtonActionsMask) != 0); 252 req->firstBtn = req->nBtns = 0; 253 req->ledClass = class; 254 req->ledID = id; 255 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 256 UnlockDisplay(dpy); 257 SyncHandle(); 258 return NULL; 259 } 260 devi = XkbAllocDeviceInfo(rep.deviceID, rep.totalBtns, rep.nDeviceLedFBs); 261 if (devi) { 262 devi->supported = rep.supported; 263 devi->unsupported = rep.unsupported; 264 devi->type = rep.devType; 265 devi->has_own_state = rep.hasOwnState; 266 devi->dflt_kbd_fb = rep.dfltKbdFB; 267 devi->dflt_led_fb = rep.dfltLedFB; 268 status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 269 if (status != Success) { 270 XkbFreeDeviceInfo(devi, XkbXI_AllDeviceFeaturesMask, True); 271 devi = NULL; 272 } 273 } 274 UnlockDisplay(dpy); 275 SyncHandle(); 276 return devi; 277} 278 279Status 280XkbGetDeviceInfoChanges(Display *dpy, 281 XkbDeviceInfoPtr devi, 282 XkbDeviceChangesPtr changes) 283{ 284 register xkbGetDeviceInfoReq *req; 285 xkbGetDeviceInfoReply rep; 286 Status status; 287 288 if ((dpy->flags & XlibDisplayNoXkb) || 289 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 290 return BadMatch; 291 if ((changes->changed & XkbXI_AllDeviceFeaturesMask) == 0) 292 return Success; 293 changes->changed &= ~XkbXI_AllDeviceFeaturesMask; 294 status = Success; 295 LockDisplay(dpy); 296 while ((changes->changed) && (status == Success)) { 297 GetReq(kbGetDeviceInfo, req); 298 req->reqType = dpy->xkb_info->codes->major_opcode; 299 req->xkbReqType = X_kbGetDeviceInfo; 300 req->deviceSpec = devi->device_spec; 301 req->wanted = changes->changed; 302 req->allBtns = False; 303 if (changes->changed & XkbXI_ButtonActionsMask) { 304 req->firstBtn = changes->first_btn; 305 req->nBtns = changes->num_btns; 306 changes->changed &= ~XkbXI_ButtonActionsMask; 307 } 308 else 309 req->firstBtn = req->nBtns = 0; 310 if (changes->changed & XkbXI_IndicatorsMask) { 311 req->ledClass = changes->leds.led_class; 312 req->ledID = changes->leds.led_id; 313 if (changes->leds.next == NULL) 314 changes->changed &= ~XkbXI_IndicatorsMask; 315 else { 316 XkbDeviceLedChangesPtr next; 317 318 next = changes->leds.next; 319 changes->leds = *next; 320 _XkbFree(next); 321 } 322 } 323 else { 324 req->ledClass = XkbDfltXIClass; 325 req->ledID = XkbDfltXIId; 326 } 327 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 328 status = BadLength; 329 break; 330 } 331 devi->supported |= rep.supported; 332 devi->unsupported |= rep.unsupported; 333 devi->type = rep.devType; 334 status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 335 } 336 UnlockDisplay(dpy); 337 SyncHandle(); 338 return status; 339} 340 341Status 342XkbGetDeviceButtonActions(Display *dpy, 343 XkbDeviceInfoPtr devi, 344 Bool all, 345 unsigned int first, 346 unsigned int num) 347{ 348 register xkbGetDeviceInfoReq *req; 349 xkbGetDeviceInfoReply rep; 350 Status status; 351 352 if ((dpy->flags & XlibDisplayNoXkb) || 353 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 354 return BadMatch; 355 if (!devi) 356 return BadValue; 357 LockDisplay(dpy); 358 GetReq(kbGetDeviceInfo, req); 359 req->reqType = dpy->xkb_info->codes->major_opcode; 360 req->xkbReqType = X_kbGetDeviceInfo; 361 req->deviceSpec = devi->device_spec; 362 req->wanted = XkbXI_ButtonActionsMask; 363 req->allBtns = all; 364 req->firstBtn = first; 365 req->nBtns = num; 366 req->ledClass = XkbDfltXIClass; 367 req->ledID = XkbDfltXIId; 368 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 369 UnlockDisplay(dpy); 370 SyncHandle(); 371 return BadLength; 372 } 373 devi->type = rep.devType; 374 devi->supported = rep.supported; 375 devi->unsupported = rep.unsupported; 376 status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 377 UnlockDisplay(dpy); 378 SyncHandle(); 379 return status; 380} 381 382Status 383XkbGetDeviceLedInfo(Display *dpy, 384 XkbDeviceInfoPtr devi, 385 unsigned int ledClass, 386 unsigned int ledId, 387 unsigned int which) 388{ 389 register xkbGetDeviceInfoReq *req; 390 xkbGetDeviceInfoReply rep; 391 Status status; 392 393 if ((dpy->flags & XlibDisplayNoXkb) || 394 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 395 return BadMatch; 396 if (((which & XkbXI_IndicatorsMask) == 0) || 397 (which & (~XkbXI_IndicatorsMask))) 398 return BadMatch; 399 if (!devi) 400 return BadValue; 401 LockDisplay(dpy); 402 GetReq(kbGetDeviceInfo, req); 403 req->reqType = dpy->xkb_info->codes->major_opcode; 404 req->xkbReqType = X_kbGetDeviceInfo; 405 req->deviceSpec = devi->device_spec; 406 req->wanted = which; 407 req->allBtns = False; 408 req->firstBtn = req->nBtns = 0; 409 req->ledClass = ledClass; 410 req->ledID = ledId; 411 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 412 UnlockDisplay(dpy); 413 SyncHandle(); 414 return BadLength; 415 } 416 devi->type = rep.devType; 417 devi->supported = rep.supported; 418 devi->unsupported = rep.unsupported; 419 status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 420 UnlockDisplay(dpy); 421 SyncHandle(); 422 return status; 423} 424 425/***====================================================================***/ 426 427typedef struct _LedInfoStuff { 428 Bool used; 429 XkbDeviceLedInfoPtr devli; 430} LedInfoStuff; 431 432typedef struct _SetLedStuff { 433 unsigned wanted; 434 int num_info; 435 int dflt_class; 436 LedInfoStuff *dflt_kbd_fb; 437 LedInfoStuff *dflt_led_fb; 438 LedInfoStuff *info; 439} SetLedStuff; 440 441static void 442_InitLedStuff(SetLedStuff *stuff, unsigned wanted, XkbDeviceInfoPtr devi) 443{ 444 int i; 445 register XkbDeviceLedInfoPtr devli; 446 447 bzero(stuff, sizeof(SetLedStuff)); 448 stuff->wanted = wanted; 449 stuff->dflt_class = XkbXINone; 450 if ((devi->num_leds < 1) || ((wanted & XkbXI_IndicatorsMask) == 0)) 451 return; 452 stuff->info = _XkbTypedCalloc(devi->num_leds, LedInfoStuff); 453 if (!stuff->info) 454 return; 455 stuff->num_info = devi->num_leds; 456 for (devli = &devi->leds[0], i = 0; i < devi->num_leds; i++, devli++) { 457 stuff->info[i].devli = devli; 458 if (devli->led_class == KbdFeedbackClass) { 459 stuff->dflt_class = KbdFeedbackClass; 460 if (stuff->dflt_kbd_fb == NULL) 461 stuff->dflt_kbd_fb = &stuff->info[i]; 462 } 463 else if (devli->led_class == LedFeedbackClass) { 464 if (stuff->dflt_class == XkbXINone) 465 stuff->dflt_class = LedFeedbackClass; 466 if (stuff->dflt_led_fb == NULL) 467 stuff->dflt_led_fb = &stuff->info[i]; 468 } 469 } 470 return; 471} 472 473static void 474_FreeLedStuff(SetLedStuff * stuff) 475{ 476 if (stuff->num_info > 0) 477 _XkbFree(stuff->info); 478 bzero(stuff, sizeof(SetLedStuff)); 479 return; 480} 481 482static int 483_XkbSizeLedInfo(unsigned changed, XkbDeviceLedInfoPtr devli) 484{ 485 register int i, size; 486 register unsigned bit, namesNeeded, mapsNeeded; 487 488 size = SIZEOF(xkbDeviceLedsWireDesc); 489 namesNeeded = mapsNeeded = 0; 490 if (changed & XkbXI_IndicatorNamesMask) 491 namesNeeded = devli->names_present; 492 if (changed & XkbXI_IndicatorMapsMask) 493 mapsNeeded = devli->maps_present; 494 if ((namesNeeded) || (mapsNeeded)) { 495 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 496 if (namesNeeded & bit) 497 size += 4; /* atoms are 4 bytes on the wire */ 498 if (mapsNeeded & bit) 499 size += SIZEOF(xkbIndicatorMapWireDesc); 500 } 501 } 502 return size; 503} 504 505static Bool 506_SizeMatches(SetLedStuff *stuff, 507 XkbDeviceLedChangesPtr changes, 508 int *sz_rtrn, 509 int *nleds_rtrn) 510{ 511 int i, nMatch, class, id; 512 LedInfoStuff *linfo; 513 Bool match; 514 515 nMatch = 0; 516 class = changes->led_class; 517 id = changes->led_id; 518 if (class == XkbDfltXIClass) 519 class = stuff->dflt_class; 520 for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) { 521 XkbDeviceLedInfoPtr devli; 522 LedInfoStuff *dflt; 523 524 devli = linfo->devli; 525 match = ((class == devli->led_class) || (class == XkbAllXIClasses)); 526 if (devli->led_class == KbdFeedbackClass) 527 dflt = stuff->dflt_kbd_fb; 528 else 529 dflt = stuff->dflt_led_fb; 530 match = (match && (id == devli->led_id)) || 531 (id == XkbAllXIIds) || 532 ((id == XkbDfltXIId) && (linfo == dflt)); 533 if (match) { 534 if (!linfo->used) { 535 *sz_rtrn += _XkbSizeLedInfo(stuff->wanted, devli); 536 *nleds_rtrn += 1; 537 linfo->used = True; 538 if ((class != XkbAllXIClasses) && (id != XkbAllXIIds)) 539 return True; 540 } 541 nMatch++; 542 linfo->used = True; 543 } 544 } 545 return (nMatch > 0); 546} 547 548/***====================================================================***/ 549 550 551static Status 552_XkbSetDeviceInfoSize(XkbDeviceInfoPtr devi, 553 XkbDeviceChangesPtr changes, 554 SetLedStuff *stuff, 555 int *sz_rtrn, 556 int *num_leds_rtrn) 557{ 558 *sz_rtrn = 0; 559 if ((changes->changed & XkbXI_ButtonActionsMask) && (changes->num_btns > 0)) { 560 if (!XkbXI_LegalDevBtn 561 (devi, (changes->first_btn + changes->num_btns - 1))) 562 return BadMatch; 563 *sz_rtrn += changes->num_btns * SIZEOF(xkbActionWireDesc); 564 } 565 else { 566 changes->changed &= ~XkbXI_ButtonActionsMask; 567 changes->first_btn = changes->num_btns = 0; 568 } 569 if ((changes->changed & XkbXI_IndicatorsMask) && 570 XkbLegalXILedClass(changes->leds.led_class)) { 571 XkbDeviceLedChangesPtr leds; 572 573 for (leds = &changes->leds; leds != NULL; leds = leds->next) { 574 if (!_SizeMatches(stuff, leds, sz_rtrn, num_leds_rtrn)) 575 return BadMatch; 576 } 577 } 578 else { 579 changes->changed &= ~XkbXI_IndicatorsMask; 580 *num_leds_rtrn = 0; 581 } 582 return Success; 583} 584 585static char * 586_XkbWriteLedInfo(char *wire, unsigned changed, XkbDeviceLedInfoPtr devli) 587{ 588 register int i; 589 register unsigned bit, namesNeeded, mapsNeeded; 590 xkbDeviceLedsWireDesc *lwire; 591 592 namesNeeded = mapsNeeded = 0; 593 if (changed & XkbXI_IndicatorNamesMask) 594 namesNeeded = devli->names_present; 595 if (changed & XkbXI_IndicatorMapsMask) 596 mapsNeeded = devli->maps_present; 597 598 lwire = (xkbDeviceLedsWireDesc *) wire; 599 lwire->ledClass = devli->led_class; 600 lwire->ledID = devli->led_id; 601 lwire->namesPresent = namesNeeded; 602 lwire->mapsPresent = mapsNeeded; 603 lwire->physIndicators = devli->phys_indicators; 604 lwire->state = devli->state; 605 wire = (char *) &lwire[1]; 606 if (namesNeeded) { 607 CARD32 *awire = (CARD32 *) wire; 608 609 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 610 if (namesNeeded & bit) { 611 *awire = (CARD32) devli->names[i]; 612 awire++; 613 } 614 } 615 wire = (char *) awire; 616 } 617 if (mapsNeeded) { 618 xkbIndicatorMapWireDesc *mwire = (xkbIndicatorMapWireDesc *) wire; 619 620 for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 621 if (mapsNeeded & bit) { 622 XkbIndicatorMapPtr map = &devli->maps[i]; 623 624 mwire->flags = map->flags; 625 mwire->whichGroups = map->which_groups; 626 mwire->groups = map->groups; 627 mwire->whichMods = map->which_mods; 628 mwire->mods = map->mods.mask; 629 mwire->realMods = map->mods.real_mods; 630 mwire->virtualMods = map->mods.vmods; 631 mwire->ctrls = map->ctrls; 632 mwire++; 633 } 634 } 635 wire = (char *) mwire; 636 } 637 return wire; 638} 639 640 641static int 642_XkbWriteSetDeviceInfo(char *wire, 643 XkbDeviceChangesPtr changes, 644 SetLedStuff *stuff, 645 XkbDeviceInfoPtr devi) 646{ 647 char *start = wire; 648 649 if (changes->changed & XkbXI_ButtonActionsMask) { 650 int size = changes->num_btns * SIZEOF(xkbActionWireDesc); 651 652 memcpy(wire, (char *) &devi->btn_acts[changes->first_btn], (size_t) size); 653 wire += size; 654 } 655 if (changes->changed & XkbXI_IndicatorsMask) { 656 register int i; 657 register LedInfoStuff *linfo; 658 659 for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) { 660 if (linfo->used) { 661 register char *new_wire; 662 663 new_wire = _XkbWriteLedInfo(wire, stuff->wanted, linfo->devli); 664 if (!new_wire) 665 return wire - start; 666 wire = new_wire; 667 } 668 } 669 } 670 return wire - start; 671} 672 673Bool 674XkbSetDeviceInfo(Display *dpy, unsigned which, XkbDeviceInfoPtr devi) 675{ 676 register xkbSetDeviceInfoReq *req; 677 Status ok = 0; 678 int size, nLeds; 679 XkbInfoPtr xkbi; 680 XkbDeviceChangesRec changes; 681 SetLedStuff lstuff; 682 683 if ((dpy->flags & XlibDisplayNoXkb) || 684 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 685 return False; 686 if ((!devi) || (which & (~XkbXI_AllDeviceFeaturesMask)) || 687 ((which & XkbXI_ButtonActionsMask) && (!XkbXI_DevHasBtnActs(devi))) || 688 ((which & XkbXI_IndicatorsMask) && (!XkbXI_DevHasLeds(devi)))) 689 return False; 690 691 bzero((char *) &changes, sizeof(XkbDeviceChangesRec)); 692 changes.changed = which; 693 changes.first_btn = 0; 694 changes.num_btns = devi->num_btns; 695 changes.leds.led_class = XkbAllXIClasses; 696 changes.leds.led_id = XkbAllXIIds; 697 changes.leds.defined = 0; 698 size = nLeds = 0; 699 _InitLedStuff(&lstuff, changes.changed, devi); 700 if (_XkbSetDeviceInfoSize(devi, &changes, &lstuff, &size, &nLeds) != 701 Success) 702 return False; 703 LockDisplay(dpy); 704 xkbi = dpy->xkb_info; 705 GetReq(kbSetDeviceInfo, req); 706 req->length += size / 4; 707 req->reqType = xkbi->codes->major_opcode; 708 req->xkbReqType = X_kbSetDeviceInfo; 709 req->deviceSpec = devi->device_spec; 710 req->firstBtn = changes.first_btn; 711 req->nBtns = changes.num_btns; 712 req->change = changes.changed; 713 req->nDeviceLedFBs = nLeds; 714 if (size > 0) { 715 char *wire; 716 717 BufAlloc(char *, wire, size); 718 ok = (wire != NULL) && 719 (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size); 720 } 721 UnlockDisplay(dpy); 722 SyncHandle(); 723 _FreeLedStuff(&lstuff); 724 /* 12/11/95 (ef) -- XXX!! should clear changes here */ 725 return ok; 726} 727 728Bool 729XkbChangeDeviceInfo(Display *dpy, 730 XkbDeviceInfoPtr devi, 731 XkbDeviceChangesPtr changes) 732{ 733 register xkbSetDeviceInfoReq *req; 734 Status ok = 0; 735 int size, nLeds; 736 XkbInfoPtr xkbi; 737 SetLedStuff lstuff; 738 739 if ((dpy->flags & XlibDisplayNoXkb) || 740 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 741 return False; 742 if ((!devi) || (changes->changed & (~XkbXI_AllDeviceFeaturesMask)) || 743 ((changes->changed & XkbXI_ButtonActionsMask) && 744 (!XkbXI_DevHasBtnActs(devi))) || 745 ((changes->changed & XkbXI_IndicatorsMask) && 746 (!XkbXI_DevHasLeds(devi)))) 747 return False; 748 749 size = nLeds = 0; 750 _InitLedStuff(&lstuff, changes->changed, devi); 751 if (_XkbSetDeviceInfoSize(devi, changes, &lstuff, &size, &nLeds) != Success) 752 return False; 753 LockDisplay(dpy); 754 xkbi = dpy->xkb_info; 755 GetReq(kbSetDeviceInfo, req); 756 req->length += size / 4; 757 req->reqType = xkbi->codes->major_opcode; 758 req->xkbReqType = X_kbSetDeviceInfo; 759 req->deviceSpec = devi->device_spec; 760 req->firstBtn = changes->first_btn; 761 req->nBtns = changes->num_btns; 762 req->change = changes->changed; 763 req->nDeviceLedFBs = nLeds; 764 if (size > 0) { 765 char *wire; 766 767 BufAlloc(char *, wire, size); 768 ok = (wire != NULL) && 769 (_XkbWriteSetDeviceInfo(wire, changes, &lstuff, devi) == size); 770 } 771 UnlockDisplay(dpy); 772 SyncHandle(); 773 _FreeLedStuff(&lstuff); 774 /* 12/11/95 (ef) -- XXX!! should clear changes here */ 775 return ok; 776} 777 778Bool 779XkbSetDeviceLedInfo(Display *dpy, 780 XkbDeviceInfoPtr devi, 781 unsigned ledClass, 782 unsigned ledID, 783 unsigned which) 784{ 785 return False; 786} 787 788Bool 789XkbSetDeviceButtonActions(Display *dpy, 790 XkbDeviceInfoPtr devi, 791 unsigned int first, 792 unsigned int nBtns) 793{ 794 register xkbSetDeviceInfoReq *req; 795 Status ok = 0; 796 int size, nLeds; 797 XkbInfoPtr xkbi; 798 XkbDeviceChangesRec changes; 799 SetLedStuff lstuff; 800 801 if ((dpy->flags & XlibDisplayNoXkb) || 802 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 803 return False; 804 if ((!devi) || (!XkbXI_DevHasBtnActs(devi)) || 805 (first + nBtns > devi->num_btns)) 806 return False; 807 if (nBtns == 0) 808 return True; 809 810 bzero((char *) &changes, sizeof(XkbDeviceChangesRec)); 811 changes.changed = XkbXI_ButtonActionsMask; 812 changes.first_btn = first; 813 changes.num_btns = nBtns; 814 changes.leds.led_class = XkbXINone; 815 changes.leds.led_id = XkbXINone; 816 changes.leds.defined = 0; 817 size = nLeds = 0; 818 if (_XkbSetDeviceInfoSize(devi, &changes, NULL, &size, &nLeds) != Success) 819 return False; 820 LockDisplay(dpy); 821 xkbi = dpy->xkb_info; 822 GetReq(kbSetDeviceInfo, req); 823 req->length += size / 4; 824 req->reqType = xkbi->codes->major_opcode; 825 req->xkbReqType = X_kbSetDeviceInfo; 826 req->deviceSpec = devi->device_spec; 827 req->firstBtn = changes.first_btn; 828 req->nBtns = changes.num_btns; 829 req->change = changes.changed; 830 req->nDeviceLedFBs = nLeds; 831 if (size > 0) { 832 char *wire; 833 834 BufAlloc(char *, wire, size); 835 ok = (wire != NULL) && 836 (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size); 837 } 838 UnlockDisplay(dpy); 839 SyncHandle(); 840 return ok; 841} 842