11ab64890Smrg/************************************************************ 21ab64890SmrgCopyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 31ab64890Smrg 41ab64890SmrgPermission to use, copy, modify, and distribute this 51ab64890Smrgsoftware and its documentation for any purpose and without 61ab64890Smrgfee is hereby granted, provided that the above copyright 71ab64890Smrgnotice appear in all copies and that both that copyright 81ab64890Smrgnotice and this permission notice appear in supporting 961b2299dSmrgdocumentation, and that the name of Silicon Graphics not be 1061b2299dSmrgused in advertising or publicity pertaining to distribution 111ab64890Smrgof the software without specific prior written permission. 1261b2299dSmrgSilicon Graphics makes no representation about the suitability 131ab64890Smrgof this software for any purpose. It is provided "as is" 141ab64890Smrgwithout any express or implied warranty. 151ab64890Smrg 1661b2299dSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1761b2299dSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 181ab64890SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1961b2299dSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2061b2299dSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2161b2299dSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 221ab64890SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 231ab64890SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 241ab64890Smrg 251ab64890Smrg********************************************************/ 261ab64890Smrg 271ab64890Smrg#ifdef HAVE_CONFIG_H 281ab64890Smrg#include <config.h> 291ab64890Smrg#endif 301ab64890Smrg#include <stdio.h> 311ab64890Smrg#define NEED_MAP_READERS 321ab64890Smrg#include "Xlibint.h" 331ab64890Smrg#include <X11/extensions/XKBproto.h> 341ab64890Smrg#include "XKBlibint.h" 351ab64890Smrg#include <X11/extensions/XI.h> 361ab64890Smrg 371ab64890Smrg/***====================================================================***/ 381ab64890Smrg 393233502eSmrgvoid 40818534a1SmrgXkbNoteDeviceChanges(XkbDeviceChangesPtr old, 41818534a1Smrg XkbExtensionDeviceNotifyEvent *new, 42818534a1Smrg unsigned int wanted) 431ab64890Smrg{ 44818534a1Smrg if ((!old) || (!new) || (!wanted) || ((new->reason & wanted) == 0)) 45818534a1Smrg return; 46818534a1Smrg if ((wanted & new->reason) & XkbXI_ButtonActionsMask) { 47818534a1Smrg if (old->changed & XkbXI_ButtonActionsMask) { 48818534a1Smrg int first, last, newLast; 49818534a1Smrg 50818534a1Smrg if (new->first_btn < old->first_btn) 51818534a1Smrg first = new->first_btn; 52818534a1Smrg else 53818534a1Smrg first = old->first_btn; 54818534a1Smrg last = old->first_btn + old->num_btns - 1; 55818534a1Smrg newLast = new->first_btn + new->num_btns - 1; 56818534a1Smrg if (newLast > last) 57818534a1Smrg last = newLast; 58818534a1Smrg old->first_btn = first; 59818534a1Smrg old->num_btns = (last - first) + 1; 60818534a1Smrg } 61818534a1Smrg else { 62818534a1Smrg old->changed |= XkbXI_ButtonActionsMask; 63818534a1Smrg old->first_btn = new->first_btn; 64818534a1Smrg old->num_btns = new->num_btns; 65818534a1Smrg } 661ab64890Smrg } 67818534a1Smrg if ((wanted & new->reason) & XkbXI_IndicatorsMask) { 68818534a1Smrg XkbDeviceLedChangesPtr this; 69818534a1Smrg 70818534a1Smrg if (old->changed & XkbXI_IndicatorsMask) { 71818534a1Smrg XkbDeviceLedChangesPtr found = NULL; 72818534a1Smrg 73818534a1Smrg for (this = &old->leds; this && (!found); this = this->next) { 74818534a1Smrg if ((this->led_class == new->led_class) && 75818534a1Smrg (this->led_id == new->led_id)) { 76818534a1Smrg found = this; 77818534a1Smrg } 78818534a1Smrg } 79818534a1Smrg if (!found) { 80818534a1Smrg found = _XkbTypedCalloc(1, XkbDeviceLedChangesRec); 81818534a1Smrg if (!found) 82818534a1Smrg return; 83818534a1Smrg found->next = old->leds.next; 84818534a1Smrg found->led_class = new->led_class; 85818534a1Smrg found->led_id = new->led_id; 86818534a1Smrg old->leds.next = found; 87818534a1Smrg } 88818534a1Smrg if ((wanted & new->reason) & XkbXI_IndicatorNamesMask) 89818534a1Smrg found->defined = new->leds_defined; 90818534a1Smrg } 91818534a1Smrg else { 92818534a1Smrg old->changed |= ((wanted & new->reason) & XkbXI_IndicatorsMask); 93818534a1Smrg old->leds.led_class = new->led_class; 94818534a1Smrg old->leds.led_id = new->led_id; 95818534a1Smrg old->leds.defined = new->leds_defined; 96818534a1Smrg if (old->leds.next) { 97818534a1Smrg XkbDeviceLedChangesPtr next; 98818534a1Smrg 99818534a1Smrg for (this = old->leds.next; this; this = next) { 100818534a1Smrg next = this->next; 101818534a1Smrg _XkbFree(this); 102818534a1Smrg } 103818534a1Smrg old->leds.next = NULL; 104818534a1Smrg } 105818534a1Smrg } 1061ab64890Smrg } 1071ab64890Smrg return; 1081ab64890Smrg} 1091ab64890Smrg 1101ab64890Smrg/***====================================================================***/ 1111ab64890Smrg 1121ab64890Smrgstatic Status 113818534a1Smrg_XkbReadDeviceLedInfo(XkbReadBufferPtr buf, 114818534a1Smrg unsigned present, 115818534a1Smrg XkbDeviceInfoPtr devi) 1161ab64890Smrg{ 117818534a1Smrg register unsigned i, bit; 118818534a1Smrg XkbDeviceLedInfoPtr devli; 119818534a1Smrg xkbDeviceLedsWireDesc *wireli; 1201ab64890Smrg 121818534a1Smrg wireli = _XkbGetTypedRdBufPtr(buf, 1, xkbDeviceLedsWireDesc); 1221ab64890Smrg if (!wireli) 123818534a1Smrg return BadLength; 124818534a1Smrg devli = XkbAddDeviceLedInfo(devi, wireli->ledClass, wireli->ledID); 1251ab64890Smrg if (!devli) 126818534a1Smrg return BadAlloc; 127818534a1Smrg devli->phys_indicators = wireli->physIndicators; 128818534a1Smrg 129818534a1Smrg if (present & XkbXI_IndicatorStateMask) 130818534a1Smrg devli->state = wireli->state; 131818534a1Smrg 132818534a1Smrg if (present & XkbXI_IndicatorNamesMask) { 133818534a1Smrg devli->names_present = wireli->namesPresent; 134818534a1Smrg if (devli->names_present) { 135818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 136818534a1Smrg if (wireli->namesPresent & bit) { 137818534a1Smrg if (!_XkbCopyFromReadBuffer(buf, 138818534a1Smrg (char *) &devli->names[i], 4)) 139818534a1Smrg return BadLength; 140818534a1Smrg } 141818534a1Smrg } 142818534a1Smrg } 1431ab64890Smrg } 1441ab64890Smrg 145818534a1Smrg if (present & XkbXI_IndicatorMapsMask) { 146818534a1Smrg devli->maps_present = wireli->mapsPresent; 147818534a1Smrg if (devli->maps_present) { 148818534a1Smrg XkbIndicatorMapPtr im; 149818534a1Smrg xkbIndicatorMapWireDesc *wireim; 150818534a1Smrg 151818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 152818534a1Smrg if (wireli->mapsPresent & bit) { 153818534a1Smrg wireim = 154818534a1Smrg _XkbGetTypedRdBufPtr(buf, 1, xkbIndicatorMapWireDesc); 155818534a1Smrg if (!wireim) 156818534a1Smrg return BadAlloc; 157818534a1Smrg im = &devli->maps[i]; 158818534a1Smrg im->flags = wireim->flags; 159818534a1Smrg im->which_groups = wireim->whichGroups; 160818534a1Smrg im->groups = wireim->groups; 161818534a1Smrg im->which_mods = wireim->whichMods; 162818534a1Smrg im->mods.mask = wireim->mods; 163818534a1Smrg im->mods.real_mods = wireim->realMods; 164818534a1Smrg im->mods.vmods = wireim->virtualMods; 165818534a1Smrg im->ctrls = wireim->ctrls; 166818534a1Smrg } 167818534a1Smrg } 168818534a1Smrg } 1691ab64890Smrg } 1701ab64890Smrg return Success; 1711ab64890Smrg} 1721ab64890Smrg 1731ab64890Smrgstatic Status 174818534a1Smrg_XkbReadGetDeviceInfoReply(Display *dpy, 175818534a1Smrg xkbGetDeviceInfoReply *rep, 176818534a1Smrg XkbDeviceInfoPtr devi) 1771ab64890Smrg{ 178818534a1Smrg XkbReadBufferRec buf; 179818534a1Smrg XkbAction *act; 180818534a1Smrg int tmp; 1811ab64890Smrg 182818534a1Smrg if (!_XkbInitReadBuffer(dpy, &buf, (int) rep->length * 4)) 183818534a1Smrg return BadAlloc; 1841ab64890Smrg 185818534a1Smrg if ((rep->totalBtns > 0) && (rep->totalBtns != devi->num_btns)) { 186818534a1Smrg tmp = XkbResizeDeviceButtonActions(devi, rep->totalBtns); 187818534a1Smrg if (tmp != Success) 188818534a1Smrg return tmp; 1891ab64890Smrg } 190818534a1Smrg if (rep->nBtnsWanted > 0) { 191ebe525bcSmrg if (((unsigned short) rep->firstBtnWanted + rep->nBtnsWanted) > devi->num_btns) 192818534a1Smrg goto BAILOUT; 193818534a1Smrg act = &devi->btn_acts[rep->firstBtnWanted]; 194818534a1Smrg bzero((char *) act, (rep->nBtnsWanted * sizeof(XkbAction))); 1951ab64890Smrg } 1960f8248bfSmrg 1970f8248bfSmrg _XkbFree(devi->name); 198818534a1Smrg if (!_XkbGetReadBufferCountedString(&buf, &devi->name)) 199818534a1Smrg goto BAILOUT; 200818534a1Smrg if (rep->nBtnsRtrn > 0) { 201818534a1Smrg int size; 202818534a1Smrg 203ebe525bcSmrg if (((unsigned short) rep->firstBtnRtrn + rep->nBtnsRtrn) > devi->num_btns) 204818534a1Smrg goto BAILOUT; 205818534a1Smrg act = &devi->btn_acts[rep->firstBtnRtrn]; 206818534a1Smrg size = rep->nBtnsRtrn * SIZEOF(xkbActionWireDesc); 207818534a1Smrg if (!_XkbCopyFromReadBuffer(&buf, (char *) act, size)) 208818534a1Smrg goto BAILOUT; 2091ab64890Smrg } 210818534a1Smrg if (rep->nDeviceLedFBs > 0) { 211818534a1Smrg register int i; 212818534a1Smrg 213818534a1Smrg for (i = 0; i < rep->nDeviceLedFBs; i++) { 214818534a1Smrg if ((tmp = _XkbReadDeviceLedInfo(&buf, rep->present, devi)) 215818534a1Smrg != Success) 216818534a1Smrg return tmp; 217818534a1Smrg } 2181ab64890Smrg } 219818534a1Smrg tmp = _XkbFreeReadBuffer(&buf); 22061b2299dSmrg if (tmp) 221818534a1Smrg fprintf(stderr, "GetDeviceInfo! Bad length (%d extra bytes)\n", tmp); 2221ab64890Smrg if (tmp || buf.error) 223818534a1Smrg return BadLength; 2241ab64890Smrg return Success; 225818534a1Smrg BAILOUT: 2261ab64890Smrg _XkbFreeReadBuffer(&buf); 2271ab64890Smrg return BadLength; 2281ab64890Smrg} 2291ab64890Smrg 2301ab64890SmrgXkbDeviceInfoPtr 231818534a1SmrgXkbGetDeviceInfo(Display *dpy, 232818534a1Smrg unsigned which, 233818534a1Smrg unsigned deviceSpec, 234818534a1Smrg unsigned class, 235818534a1Smrg unsigned id) 2361ab64890Smrg{ 237818534a1Smrg register xkbGetDeviceInfoReq *req; 238818534a1Smrg xkbGetDeviceInfoReply rep; 239818534a1Smrg Status status; 240818534a1Smrg XkbDeviceInfoPtr devi; 2411ab64890Smrg 2421ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 243818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 244818534a1Smrg return NULL; 2451ab64890Smrg LockDisplay(dpy); 2461ab64890Smrg GetReq(kbGetDeviceInfo, req); 2471ab64890Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 2481ab64890Smrg req->xkbReqType = X_kbGetDeviceInfo; 2491ab64890Smrg req->deviceSpec = deviceSpec; 250818534a1Smrg req->wanted = which; 251818534a1Smrg req->allBtns = ((which & XkbXI_ButtonActionsMask) != 0); 252818534a1Smrg req->firstBtn = req->nBtns = 0; 253818534a1Smrg req->ledClass = class; 254818534a1Smrg req->ledID = id; 255818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 256818534a1Smrg UnlockDisplay(dpy); 257818534a1Smrg SyncHandle(); 258818534a1Smrg return NULL; 2591ab64890Smrg } 260818534a1Smrg devi = XkbAllocDeviceInfo(rep.deviceID, rep.totalBtns, rep.nDeviceLedFBs); 2611ab64890Smrg if (devi) { 262818534a1Smrg devi->supported = rep.supported; 263818534a1Smrg devi->unsupported = rep.unsupported; 264818534a1Smrg devi->type = rep.devType; 265818534a1Smrg devi->has_own_state = rep.hasOwnState; 266818534a1Smrg devi->dflt_kbd_fb = rep.dfltKbdFB; 267818534a1Smrg devi->dflt_led_fb = rep.dfltLedFB; 268818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 269818534a1Smrg if (status != Success) { 270818534a1Smrg XkbFreeDeviceInfo(devi, XkbXI_AllDeviceFeaturesMask, True); 271818534a1Smrg devi = NULL; 272818534a1Smrg } 2731ab64890Smrg } 2741ab64890Smrg UnlockDisplay(dpy); 2751ab64890Smrg SyncHandle(); 2761ab64890Smrg return devi; 2771ab64890Smrg} 2781ab64890Smrg 2791ab64890SmrgStatus 280818534a1SmrgXkbGetDeviceInfoChanges(Display *dpy, 281818534a1Smrg XkbDeviceInfoPtr devi, 282818534a1Smrg XkbDeviceChangesPtr changes) 2831ab64890Smrg{ 284818534a1Smrg register xkbGetDeviceInfoReq *req; 285818534a1Smrg xkbGetDeviceInfoReply rep; 286818534a1Smrg Status status; 2871ab64890Smrg 2881ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 289818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 290818534a1Smrg return BadMatch; 291818534a1Smrg if ((changes->changed & XkbXI_AllDeviceFeaturesMask) == 0) 292818534a1Smrg return Success; 293818534a1Smrg changes->changed &= ~XkbXI_AllDeviceFeaturesMask; 294818534a1Smrg status = Success; 2951ab64890Smrg LockDisplay(dpy); 296818534a1Smrg while ((changes->changed) && (status == Success)) { 297818534a1Smrg GetReq(kbGetDeviceInfo, req); 298818534a1Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 299818534a1Smrg req->xkbReqType = X_kbGetDeviceInfo; 300818534a1Smrg req->deviceSpec = devi->device_spec; 301818534a1Smrg req->wanted = changes->changed; 302818534a1Smrg req->allBtns = False; 303818534a1Smrg if (changes->changed & XkbXI_ButtonActionsMask) { 304818534a1Smrg req->firstBtn = changes->first_btn; 305818534a1Smrg req->nBtns = changes->num_btns; 306818534a1Smrg changes->changed &= ~XkbXI_ButtonActionsMask; 307818534a1Smrg } 308818534a1Smrg else 309818534a1Smrg req->firstBtn = req->nBtns = 0; 310818534a1Smrg if (changes->changed & XkbXI_IndicatorsMask) { 311818534a1Smrg req->ledClass = changes->leds.led_class; 312818534a1Smrg req->ledID = changes->leds.led_id; 313818534a1Smrg if (changes->leds.next == NULL) 314818534a1Smrg changes->changed &= ~XkbXI_IndicatorsMask; 315818534a1Smrg else { 316818534a1Smrg XkbDeviceLedChangesPtr next; 317818534a1Smrg 318818534a1Smrg next = changes->leds.next; 319818534a1Smrg changes->leds = *next; 320818534a1Smrg _XkbFree(next); 321818534a1Smrg } 322818534a1Smrg } 323818534a1Smrg else { 324818534a1Smrg req->ledClass = XkbDfltXIClass; 325818534a1Smrg req->ledID = XkbDfltXIId; 326818534a1Smrg } 327818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 328818534a1Smrg status = BadLength; 329818534a1Smrg break; 330818534a1Smrg } 331818534a1Smrg devi->supported |= rep.supported; 332818534a1Smrg devi->unsupported |= rep.unsupported; 333818534a1Smrg devi->type = rep.devType; 334818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 3351ab64890Smrg } 3361ab64890Smrg UnlockDisplay(dpy); 3371ab64890Smrg SyncHandle(); 3381ab64890Smrg return status; 3391ab64890Smrg} 3401ab64890Smrg 3411ab64890SmrgStatus 342818534a1SmrgXkbGetDeviceButtonActions(Display *dpy, 343818534a1Smrg XkbDeviceInfoPtr devi, 344818534a1Smrg Bool all, 345818534a1Smrg unsigned int first, 346818534a1Smrg unsigned int num) 3471ab64890Smrg{ 348818534a1Smrg register xkbGetDeviceInfoReq *req; 349818534a1Smrg xkbGetDeviceInfoReply rep; 350818534a1Smrg Status status; 3511ab64890Smrg 35261b2299dSmrg if ((dpy->flags & XlibDisplayNoXkb) || 353818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 354818534a1Smrg return BadMatch; 3551ab64890Smrg if (!devi) 356818534a1Smrg return BadValue; 3571ab64890Smrg LockDisplay(dpy); 3581ab64890Smrg GetReq(kbGetDeviceInfo, req); 3591ab64890Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 3601ab64890Smrg req->xkbReqType = X_kbGetDeviceInfo; 3611ab64890Smrg req->deviceSpec = devi->device_spec; 362818534a1Smrg req->wanted = XkbXI_ButtonActionsMask; 363818534a1Smrg req->allBtns = all; 364818534a1Smrg req->firstBtn = first; 365818534a1Smrg req->nBtns = num; 366818534a1Smrg req->ledClass = XkbDfltXIClass; 367818534a1Smrg req->ledID = XkbDfltXIId; 368818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 369818534a1Smrg UnlockDisplay(dpy); 370818534a1Smrg SyncHandle(); 371818534a1Smrg return BadLength; 3721ab64890Smrg } 373818534a1Smrg devi->type = rep.devType; 374818534a1Smrg devi->supported = rep.supported; 375818534a1Smrg devi->unsupported = rep.unsupported; 376818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 3771ab64890Smrg UnlockDisplay(dpy); 3781ab64890Smrg SyncHandle(); 3791ab64890Smrg return status; 3801ab64890Smrg} 3811ab64890Smrg 3821ab64890SmrgStatus 383818534a1SmrgXkbGetDeviceLedInfo(Display *dpy, 384818534a1Smrg XkbDeviceInfoPtr devi, 385818534a1Smrg unsigned int ledClass, 386818534a1Smrg unsigned int ledId, 387818534a1Smrg unsigned int which) 3881ab64890Smrg{ 389818534a1Smrg register xkbGetDeviceInfoReq *req; 390818534a1Smrg xkbGetDeviceInfoReply rep; 391818534a1Smrg Status status; 3921ab64890Smrg 39361b2299dSmrg if ((dpy->flags & XlibDisplayNoXkb) || 394818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 395818534a1Smrg return BadMatch; 396818534a1Smrg if (((which & XkbXI_IndicatorsMask) == 0) || 397818534a1Smrg (which & (~XkbXI_IndicatorsMask))) 398818534a1Smrg return BadMatch; 3991ab64890Smrg if (!devi) 400818534a1Smrg return BadValue; 4011ab64890Smrg LockDisplay(dpy); 4021ab64890Smrg GetReq(kbGetDeviceInfo, req); 4031ab64890Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 4041ab64890Smrg req->xkbReqType = X_kbGetDeviceInfo; 4051ab64890Smrg req->deviceSpec = devi->device_spec; 406818534a1Smrg req->wanted = which; 407818534a1Smrg req->allBtns = False; 408818534a1Smrg req->firstBtn = req->nBtns = 0; 409818534a1Smrg req->ledClass = ledClass; 410818534a1Smrg req->ledID = ledId; 411818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 412818534a1Smrg UnlockDisplay(dpy); 413818534a1Smrg SyncHandle(); 414818534a1Smrg return BadLength; 41561b2299dSmrg } 416818534a1Smrg devi->type = rep.devType; 417818534a1Smrg devi->supported = rep.supported; 418818534a1Smrg devi->unsupported = rep.unsupported; 419818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 4201ab64890Smrg UnlockDisplay(dpy); 4211ab64890Smrg SyncHandle(); 4221ab64890Smrg return status; 4231ab64890Smrg} 4241ab64890Smrg 4251ab64890Smrg/***====================================================================***/ 4261ab64890Smrg 4271ab64890Smrgtypedef struct _LedInfoStuff { 428818534a1Smrg Bool used; 429818534a1Smrg XkbDeviceLedInfoPtr devli; 4301ab64890Smrg} LedInfoStuff; 4311ab64890Smrg 4321ab64890Smrgtypedef struct _SetLedStuff { 433818534a1Smrg unsigned wanted; 434818534a1Smrg int num_info; 435818534a1Smrg int dflt_class; 436818534a1Smrg LedInfoStuff *dflt_kbd_fb; 437818534a1Smrg LedInfoStuff *dflt_led_fb; 438818534a1Smrg LedInfoStuff *info; 4391ab64890Smrg} SetLedStuff; 4401ab64890Smrg 4411ab64890Smrgstatic void 442818534a1Smrg_InitLedStuff(SetLedStuff *stuff, unsigned wanted, XkbDeviceInfoPtr devi) 4431ab64890Smrg{ 444818534a1Smrg int i; 445818534a1Smrg register XkbDeviceLedInfoPtr devli; 446818534a1Smrg 447818534a1Smrg bzero(stuff, sizeof(SetLedStuff)); 448818534a1Smrg stuff->wanted = wanted; 449818534a1Smrg stuff->dflt_class = XkbXINone; 450818534a1Smrg if ((devi->num_leds < 1) || ((wanted & XkbXI_IndicatorsMask) == 0)) 451818534a1Smrg return; 452818534a1Smrg stuff->info = _XkbTypedCalloc(devi->num_leds, LedInfoStuff); 4531ab64890Smrg if (!stuff->info) 454818534a1Smrg return; 455818534a1Smrg stuff->num_info = devi->num_leds; 456818534a1Smrg for (devli = &devi->leds[0], i = 0; i < devi->num_leds; i++, devli++) { 457818534a1Smrg stuff->info[i].devli = devli; 458818534a1Smrg if (devli->led_class == KbdFeedbackClass) { 459818534a1Smrg stuff->dflt_class = KbdFeedbackClass; 460818534a1Smrg if (stuff->dflt_kbd_fb == NULL) 461818534a1Smrg stuff->dflt_kbd_fb = &stuff->info[i]; 462818534a1Smrg } 463818534a1Smrg else if (devli->led_class == LedFeedbackClass) { 464818534a1Smrg if (stuff->dflt_class == XkbXINone) 465818534a1Smrg stuff->dflt_class = LedFeedbackClass; 466818534a1Smrg if (stuff->dflt_led_fb == NULL) 467818534a1Smrg stuff->dflt_led_fb = &stuff->info[i]; 468818534a1Smrg } 4691ab64890Smrg } 4701ab64890Smrg return; 4711ab64890Smrg} 4721ab64890Smrg 4731ab64890Smrgstatic void 474818534a1Smrg_FreeLedStuff(SetLedStuff * stuff) 4751ab64890Smrg{ 4760f8248bfSmrg if (stuff->num_info > 0) 477818534a1Smrg _XkbFree(stuff->info); 478818534a1Smrg bzero(stuff, sizeof(SetLedStuff)); 4791ab64890Smrg return; 4801ab64890Smrg} 4811ab64890Smrg 4821ab64890Smrgstatic int 483818534a1Smrg_XkbSizeLedInfo(unsigned changed, XkbDeviceLedInfoPtr devli) 4841ab64890Smrg{ 485818534a1Smrg register int i, size; 486818534a1Smrg register unsigned bit, namesNeeded, mapsNeeded; 487818534a1Smrg 488818534a1Smrg size = SIZEOF(xkbDeviceLedsWireDesc); 489818534a1Smrg namesNeeded = mapsNeeded = 0; 490818534a1Smrg if (changed & XkbXI_IndicatorNamesMask) 491818534a1Smrg namesNeeded = devli->names_present; 492818534a1Smrg if (changed & XkbXI_IndicatorMapsMask) 493818534a1Smrg mapsNeeded = devli->maps_present; 494818534a1Smrg if ((namesNeeded) || (mapsNeeded)) { 495818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 496818534a1Smrg if (namesNeeded & bit) 497818534a1Smrg size += 4; /* atoms are 4 bytes on the wire */ 498818534a1Smrg if (mapsNeeded & bit) 499818534a1Smrg size += SIZEOF(xkbIndicatorMapWireDesc); 500818534a1Smrg } 5011ab64890Smrg } 5021ab64890Smrg return size; 5031ab64890Smrg} 5041ab64890Smrg 5051ab64890Smrgstatic Bool 506818534a1Smrg_SizeMatches(SetLedStuff *stuff, 507818534a1Smrg XkbDeviceLedChangesPtr changes, 508818534a1Smrg int *sz_rtrn, 509818534a1Smrg int *nleds_rtrn) 5101ab64890Smrg{ 511818534a1Smrg int i, nMatch, class, id; 512818534a1Smrg LedInfoStuff *linfo; 513818534a1Smrg Bool match; 514818534a1Smrg 515818534a1Smrg nMatch = 0; 516818534a1Smrg class = changes->led_class; 517818534a1Smrg id = changes->led_id; 518818534a1Smrg if (class == XkbDfltXIClass) 519818534a1Smrg class = stuff->dflt_class; 520818534a1Smrg for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) { 521818534a1Smrg XkbDeviceLedInfoPtr devli; 522818534a1Smrg LedInfoStuff *dflt; 523818534a1Smrg 524818534a1Smrg devli = linfo->devli; 525818534a1Smrg match = ((class == devli->led_class) || (class == XkbAllXIClasses)); 526818534a1Smrg if (devli->led_class == KbdFeedbackClass) 527818534a1Smrg dflt = stuff->dflt_kbd_fb; 528818534a1Smrg else 529818534a1Smrg dflt = stuff->dflt_led_fb; 530818534a1Smrg match = (match && (id == devli->led_id)) || 531818534a1Smrg (id == XkbAllXIIds) || 532818534a1Smrg ((id == XkbDfltXIId) && (linfo == dflt)); 533818534a1Smrg if (match) { 534818534a1Smrg if (!linfo->used) { 535818534a1Smrg *sz_rtrn += _XkbSizeLedInfo(stuff->wanted, devli); 536818534a1Smrg *nleds_rtrn += 1; 537818534a1Smrg linfo->used = True; 538818534a1Smrg if ((class != XkbAllXIClasses) && (id != XkbAllXIIds)) 539818534a1Smrg return True; 540818534a1Smrg } 541818534a1Smrg nMatch++; 542818534a1Smrg linfo->used = True; 543818534a1Smrg } 5441ab64890Smrg } 545818534a1Smrg return (nMatch > 0); 5461ab64890Smrg} 5471ab64890Smrg 5481ab64890Smrg/***====================================================================***/ 5491ab64890Smrg 5501ab64890Smrg 5511ab64890Smrgstatic Status 552818534a1Smrg_XkbSetDeviceInfoSize(XkbDeviceInfoPtr devi, 553818534a1Smrg XkbDeviceChangesPtr changes, 554818534a1Smrg SetLedStuff *stuff, 555818534a1Smrg int *sz_rtrn, 556818534a1Smrg int *num_leds_rtrn) 5571ab64890Smrg{ 558818534a1Smrg *sz_rtrn = 0; 559818534a1Smrg if ((changes->changed & XkbXI_ButtonActionsMask) && (changes->num_btns > 0)) { 560818534a1Smrg if (!XkbXI_LegalDevBtn 561818534a1Smrg (devi, (changes->first_btn + changes->num_btns - 1))) 562818534a1Smrg return BadMatch; 563818534a1Smrg *sz_rtrn += changes->num_btns * SIZEOF(xkbActionWireDesc); 5641ab64890Smrg } 5651ab64890Smrg else { 566818534a1Smrg changes->changed &= ~XkbXI_ButtonActionsMask; 567818534a1Smrg changes->first_btn = changes->num_btns = 0; 5681ab64890Smrg } 569818534a1Smrg if ((changes->changed & XkbXI_IndicatorsMask) && 570818534a1Smrg XkbLegalXILedClass(changes->leds.led_class)) { 571818534a1Smrg XkbDeviceLedChangesPtr leds; 572818534a1Smrg 573818534a1Smrg for (leds = &changes->leds; leds != NULL; leds = leds->next) { 574818534a1Smrg if (!_SizeMatches(stuff, leds, sz_rtrn, num_leds_rtrn)) 575818534a1Smrg return BadMatch; 576818534a1Smrg } 5771ab64890Smrg } 5781ab64890Smrg else { 579818534a1Smrg changes->changed &= ~XkbXI_IndicatorsMask; 580818534a1Smrg *num_leds_rtrn = 0; 5811ab64890Smrg } 5821ab64890Smrg return Success; 5831ab64890Smrg} 5841ab64890Smrg 5851ab64890Smrgstatic char * 586818534a1Smrg_XkbWriteLedInfo(char *wire, unsigned changed, XkbDeviceLedInfoPtr devli) 5871ab64890Smrg{ 588818534a1Smrg register int i; 589818534a1Smrg register unsigned bit, namesNeeded, mapsNeeded; 590818534a1Smrg xkbDeviceLedsWireDesc *lwire; 591818534a1Smrg 592818534a1Smrg namesNeeded = mapsNeeded = 0; 593818534a1Smrg if (changed & XkbXI_IndicatorNamesMask) 594818534a1Smrg namesNeeded = devli->names_present; 595818534a1Smrg if (changed & XkbXI_IndicatorMapsMask) 596818534a1Smrg mapsNeeded = devli->maps_present; 597818534a1Smrg 598818534a1Smrg lwire = (xkbDeviceLedsWireDesc *) wire; 599818534a1Smrg lwire->ledClass = devli->led_class; 600818534a1Smrg lwire->ledID = devli->led_id; 601818534a1Smrg lwire->namesPresent = namesNeeded; 602818534a1Smrg lwire->mapsPresent = mapsNeeded; 603818534a1Smrg lwire->physIndicators = devli->phys_indicators; 604818534a1Smrg lwire->state = devli->state; 605818534a1Smrg wire = (char *) &lwire[1]; 6061ab64890Smrg if (namesNeeded) { 607818534a1Smrg CARD32 *awire = (CARD32 *) wire; 608818534a1Smrg 609818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 610818534a1Smrg if (namesNeeded & bit) { 611818534a1Smrg *awire = (CARD32) devli->names[i]; 612818534a1Smrg awire++; 613818534a1Smrg } 614818534a1Smrg } 615818534a1Smrg wire = (char *) awire; 6161ab64890Smrg } 6171ab64890Smrg if (mapsNeeded) { 618818534a1Smrg xkbIndicatorMapWireDesc *mwire = (xkbIndicatorMapWireDesc *) wire; 619818534a1Smrg 620818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 621818534a1Smrg if (mapsNeeded & bit) { 622818534a1Smrg XkbIndicatorMapPtr map = &devli->maps[i]; 623818534a1Smrg 624818534a1Smrg mwire->flags = map->flags; 625818534a1Smrg mwire->whichGroups = map->which_groups; 626818534a1Smrg mwire->groups = map->groups; 627818534a1Smrg mwire->whichMods = map->which_mods; 628818534a1Smrg mwire->mods = map->mods.mask; 629818534a1Smrg mwire->realMods = map->mods.real_mods; 630818534a1Smrg mwire->virtualMods = map->mods.vmods; 631818534a1Smrg mwire->ctrls = map->ctrls; 632818534a1Smrg mwire++; 633818534a1Smrg } 634818534a1Smrg } 635818534a1Smrg wire = (char *) mwire; 6361ab64890Smrg } 6371ab64890Smrg return wire; 6381ab64890Smrg} 6391ab64890Smrg 6401ab64890Smrg 6411ab64890Smrgstatic int 642818534a1Smrg_XkbWriteSetDeviceInfo(char *wire, 643818534a1Smrg XkbDeviceChangesPtr changes, 644818534a1Smrg SetLedStuff *stuff, 645818534a1Smrg XkbDeviceInfoPtr devi) 6461ab64890Smrg{ 647818534a1Smrg char *start = wire; 648818534a1Smrg 649818534a1Smrg if (changes->changed & XkbXI_ButtonActionsMask) { 650818534a1Smrg int size = changes->num_btns * SIZEOF(xkbActionWireDesc); 651818534a1Smrg 6529c019ec5Smaya memcpy(wire, (char *) &devi->btn_acts[changes->first_btn], (size_t) size); 653818534a1Smrg wire += size; 6541ab64890Smrg } 655818534a1Smrg if (changes->changed & XkbXI_IndicatorsMask) { 656818534a1Smrg register int i; 657818534a1Smrg register LedInfoStuff *linfo; 658818534a1Smrg 659818534a1Smrg for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) { 660818534a1Smrg if (linfo->used) { 661818534a1Smrg register char *new_wire; 662818534a1Smrg 663818534a1Smrg new_wire = _XkbWriteLedInfo(wire, stuff->wanted, linfo->devli); 664818534a1Smrg if (!new_wire) 665818534a1Smrg return wire - start; 666818534a1Smrg wire = new_wire; 667818534a1Smrg } 668818534a1Smrg } 6691ab64890Smrg } 670818534a1Smrg return wire - start; 6711ab64890Smrg} 6721ab64890Smrg 6731ab64890SmrgBool 674818534a1SmrgXkbSetDeviceInfo(Display *dpy, unsigned which, XkbDeviceInfoPtr devi) 6751ab64890Smrg{ 6761ab64890Smrg register xkbSetDeviceInfoReq *req; 677818534a1Smrg Status ok = 0; 678818534a1Smrg int size, nLeds; 679818534a1Smrg XkbInfoPtr xkbi; 680818534a1Smrg XkbDeviceChangesRec changes; 681818534a1Smrg SetLedStuff lstuff; 6821ab64890Smrg 6831ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 684818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 685818534a1Smrg return False; 686818534a1Smrg if ((!devi) || (which & (~XkbXI_AllDeviceFeaturesMask)) || 687818534a1Smrg ((which & XkbXI_ButtonActionsMask) && (!XkbXI_DevHasBtnActs(devi))) || 688818534a1Smrg ((which & XkbXI_IndicatorsMask) && (!XkbXI_DevHasLeds(devi)))) 689818534a1Smrg return False; 690818534a1Smrg 691818534a1Smrg bzero((char *) &changes, sizeof(XkbDeviceChangesRec)); 692818534a1Smrg changes.changed = which; 693818534a1Smrg changes.first_btn = 0; 694818534a1Smrg changes.num_btns = devi->num_btns; 695818534a1Smrg changes.leds.led_class = XkbAllXIClasses; 696818534a1Smrg changes.leds.led_id = XkbAllXIIds; 697818534a1Smrg changes.leds.defined = 0; 698818534a1Smrg size = nLeds = 0; 699818534a1Smrg _InitLedStuff(&lstuff, changes.changed, devi); 700818534a1Smrg if (_XkbSetDeviceInfoSize(devi, &changes, &lstuff, &size, &nLeds) != 701818534a1Smrg Success) 702818534a1Smrg return False; 7031ab64890Smrg LockDisplay(dpy); 7041ab64890Smrg xkbi = dpy->xkb_info; 7051ab64890Smrg GetReq(kbSetDeviceInfo, req); 706818534a1Smrg req->length += size / 4; 707818534a1Smrg req->reqType = xkbi->codes->major_opcode; 708818534a1Smrg req->xkbReqType = X_kbSetDeviceInfo; 709818534a1Smrg req->deviceSpec = devi->device_spec; 710818534a1Smrg req->firstBtn = changes.first_btn; 711818534a1Smrg req->nBtns = changes.num_btns; 712818534a1Smrg req->change = changes.changed; 713818534a1Smrg req->nDeviceLedFBs = nLeds; 714818534a1Smrg if (size > 0) { 715818534a1Smrg char *wire; 716818534a1Smrg 717818534a1Smrg BufAlloc(char *, wire, size); 718818534a1Smrg ok = (wire != NULL) && 719818534a1Smrg (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size); 7201ab64890Smrg } 7211ab64890Smrg UnlockDisplay(dpy); 7221ab64890Smrg SyncHandle(); 7231ab64890Smrg _FreeLedStuff(&lstuff); 7241ab64890Smrg /* 12/11/95 (ef) -- XXX!! should clear changes here */ 7251ab64890Smrg return ok; 7261ab64890Smrg} 7271ab64890Smrg 7281ab64890SmrgBool 729818534a1SmrgXkbChangeDeviceInfo(Display *dpy, 730818534a1Smrg XkbDeviceInfoPtr devi, 731818534a1Smrg XkbDeviceChangesPtr changes) 7321ab64890Smrg{ 7331ab64890Smrg register xkbSetDeviceInfoReq *req; 734818534a1Smrg Status ok = 0; 735818534a1Smrg int size, nLeds; 736818534a1Smrg XkbInfoPtr xkbi; 737818534a1Smrg SetLedStuff lstuff; 7381ab64890Smrg 7391ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 740818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 741818534a1Smrg return False; 742818534a1Smrg if ((!devi) || (changes->changed & (~XkbXI_AllDeviceFeaturesMask)) || 743818534a1Smrg ((changes->changed & XkbXI_ButtonActionsMask) && 744818534a1Smrg (!XkbXI_DevHasBtnActs(devi))) || 745818534a1Smrg ((changes->changed & XkbXI_IndicatorsMask) && 746818534a1Smrg (!XkbXI_DevHasLeds(devi)))) 747818534a1Smrg return False; 748818534a1Smrg 749818534a1Smrg size = nLeds = 0; 750818534a1Smrg _InitLedStuff(&lstuff, changes->changed, devi); 751818534a1Smrg if (_XkbSetDeviceInfoSize(devi, changes, &lstuff, &size, &nLeds) != Success) 752818534a1Smrg return False; 7531ab64890Smrg LockDisplay(dpy); 7541ab64890Smrg xkbi = dpy->xkb_info; 7551ab64890Smrg GetReq(kbSetDeviceInfo, req); 756818534a1Smrg req->length += size / 4; 757818534a1Smrg req->reqType = xkbi->codes->major_opcode; 758818534a1Smrg req->xkbReqType = X_kbSetDeviceInfo; 759818534a1Smrg req->deviceSpec = devi->device_spec; 760818534a1Smrg req->firstBtn = changes->first_btn; 761818534a1Smrg req->nBtns = changes->num_btns; 762818534a1Smrg req->change = changes->changed; 763818534a1Smrg req->nDeviceLedFBs = nLeds; 764818534a1Smrg if (size > 0) { 765818534a1Smrg char *wire; 766818534a1Smrg 767818534a1Smrg BufAlloc(char *, wire, size); 768818534a1Smrg ok = (wire != NULL) && 769818534a1Smrg (_XkbWriteSetDeviceInfo(wire, changes, &lstuff, devi) == size); 7701ab64890Smrg } 7711ab64890Smrg UnlockDisplay(dpy); 7721ab64890Smrg SyncHandle(); 7731ab64890Smrg _FreeLedStuff(&lstuff); 7741ab64890Smrg /* 12/11/95 (ef) -- XXX!! should clear changes here */ 7751ab64890Smrg return ok; 7761ab64890Smrg} 7771ab64890Smrg 77861b2299dSmrgBool 779818534a1SmrgXkbSetDeviceLedInfo(Display *dpy, 780818534a1Smrg XkbDeviceInfoPtr devi, 781818534a1Smrg unsigned ledClass, 782818534a1Smrg unsigned ledID, 783818534a1Smrg unsigned which) 7841ab64890Smrg{ 7851ab64890Smrg return False; 7861ab64890Smrg} 7871ab64890Smrg 78861b2299dSmrgBool 789818534a1SmrgXkbSetDeviceButtonActions(Display *dpy, 790818534a1Smrg XkbDeviceInfoPtr devi, 791818534a1Smrg unsigned int first, 792818534a1Smrg unsigned int nBtns) 7931ab64890Smrg{ 7941ab64890Smrg register xkbSetDeviceInfoReq *req; 795818534a1Smrg Status ok = 0; 796818534a1Smrg int size, nLeds; 797818534a1Smrg XkbInfoPtr xkbi; 798818534a1Smrg XkbDeviceChangesRec changes; 799818534a1Smrg SetLedStuff lstuff; 8001ab64890Smrg 8011ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 802818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 803818534a1Smrg return False; 804818534a1Smrg if ((!devi) || (!XkbXI_DevHasBtnActs(devi)) || 805818534a1Smrg (first + nBtns > devi->num_btns)) 806818534a1Smrg return False; 807818534a1Smrg if (nBtns == 0) 808818534a1Smrg return True; 809818534a1Smrg 810818534a1Smrg bzero((char *) &changes, sizeof(XkbDeviceChangesRec)); 811818534a1Smrg changes.changed = XkbXI_ButtonActionsMask; 812818534a1Smrg changes.first_btn = first; 813818534a1Smrg changes.num_btns = nBtns; 814818534a1Smrg changes.leds.led_class = XkbXINone; 815818534a1Smrg changes.leds.led_id = XkbXINone; 816818534a1Smrg changes.leds.defined = 0; 817818534a1Smrg size = nLeds = 0; 818818534a1Smrg if (_XkbSetDeviceInfoSize(devi, &changes, NULL, &size, &nLeds) != Success) 819818534a1Smrg return False; 8201ab64890Smrg LockDisplay(dpy); 8211ab64890Smrg xkbi = dpy->xkb_info; 8221ab64890Smrg GetReq(kbSetDeviceInfo, req); 823818534a1Smrg req->length += size / 4; 824818534a1Smrg req->reqType = xkbi->codes->major_opcode; 825818534a1Smrg req->xkbReqType = X_kbSetDeviceInfo; 826818534a1Smrg req->deviceSpec = devi->device_spec; 827818534a1Smrg req->firstBtn = changes.first_btn; 828818534a1Smrg req->nBtns = changes.num_btns; 829818534a1Smrg req->change = changes.changed; 830818534a1Smrg req->nDeviceLedFBs = nLeds; 831818534a1Smrg if (size > 0) { 832818534a1Smrg char *wire; 833818534a1Smrg 834818534a1Smrg BufAlloc(char *, wire, size); 835818534a1Smrg ok = (wire != NULL) && 836818534a1Smrg (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size); 8371ab64890Smrg } 8381ab64890Smrg UnlockDisplay(dpy); 8391ab64890Smrg SyncHandle(); 8401ab64890Smrg return ok; 8411ab64890Smrg} 842