XKBExtDev.c revision 0f8248bf
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 391ab64890Smrgextern void 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) { 191818534a1Smrg if (((unsigned short) rep->firstBtnWanted + rep->nBtnsWanted) 192818534a1Smrg >= devi->num_btns) 193818534a1Smrg goto BAILOUT; 194818534a1Smrg act = &devi->btn_acts[rep->firstBtnWanted]; 195818534a1Smrg bzero((char *) act, (rep->nBtnsWanted * sizeof(XkbAction))); 1961ab64890Smrg } 1970f8248bfSmrg 1980f8248bfSmrg _XkbFree(devi->name); 199818534a1Smrg if (!_XkbGetReadBufferCountedString(&buf, &devi->name)) 200818534a1Smrg goto BAILOUT; 201818534a1Smrg if (rep->nBtnsRtrn > 0) { 202818534a1Smrg int size; 203818534a1Smrg 204818534a1Smrg if (((unsigned short) rep->firstBtnRtrn + rep->nBtnsRtrn) 205818534a1Smrg >= devi->num_btns) 206818534a1Smrg goto BAILOUT; 207818534a1Smrg act = &devi->btn_acts[rep->firstBtnRtrn]; 208818534a1Smrg size = rep->nBtnsRtrn * SIZEOF(xkbActionWireDesc); 209818534a1Smrg if (!_XkbCopyFromReadBuffer(&buf, (char *) act, size)) 210818534a1Smrg goto BAILOUT; 2111ab64890Smrg } 212818534a1Smrg if (rep->nDeviceLedFBs > 0) { 213818534a1Smrg register int i; 214818534a1Smrg 215818534a1Smrg for (i = 0; i < rep->nDeviceLedFBs; i++) { 216818534a1Smrg if ((tmp = _XkbReadDeviceLedInfo(&buf, rep->present, devi)) 217818534a1Smrg != Success) 218818534a1Smrg return tmp; 219818534a1Smrg } 2201ab64890Smrg } 221818534a1Smrg tmp = _XkbFreeReadBuffer(&buf); 22261b2299dSmrg if (tmp) 223818534a1Smrg fprintf(stderr, "GetDeviceInfo! Bad length (%d extra bytes)\n", tmp); 2241ab64890Smrg if (tmp || buf.error) 225818534a1Smrg return BadLength; 2261ab64890Smrg return Success; 227818534a1Smrg BAILOUT: 2281ab64890Smrg _XkbFreeReadBuffer(&buf); 2291ab64890Smrg return BadLength; 2301ab64890Smrg} 2311ab64890Smrg 2321ab64890SmrgXkbDeviceInfoPtr 233818534a1SmrgXkbGetDeviceInfo(Display *dpy, 234818534a1Smrg unsigned which, 235818534a1Smrg unsigned deviceSpec, 236818534a1Smrg unsigned class, 237818534a1Smrg unsigned id) 2381ab64890Smrg{ 239818534a1Smrg register xkbGetDeviceInfoReq *req; 240818534a1Smrg xkbGetDeviceInfoReply rep; 241818534a1Smrg Status status; 242818534a1Smrg XkbDeviceInfoPtr devi; 2431ab64890Smrg 2441ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 245818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 246818534a1Smrg return NULL; 2471ab64890Smrg LockDisplay(dpy); 2481ab64890Smrg GetReq(kbGetDeviceInfo, req); 2491ab64890Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 2501ab64890Smrg req->xkbReqType = X_kbGetDeviceInfo; 2511ab64890Smrg req->deviceSpec = deviceSpec; 252818534a1Smrg req->wanted = which; 253818534a1Smrg req->allBtns = ((which & XkbXI_ButtonActionsMask) != 0); 254818534a1Smrg req->firstBtn = req->nBtns = 0; 255818534a1Smrg req->ledClass = class; 256818534a1Smrg req->ledID = id; 257818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 258818534a1Smrg UnlockDisplay(dpy); 259818534a1Smrg SyncHandle(); 260818534a1Smrg return NULL; 2611ab64890Smrg } 262818534a1Smrg devi = XkbAllocDeviceInfo(rep.deviceID, rep.totalBtns, rep.nDeviceLedFBs); 2631ab64890Smrg if (devi) { 264818534a1Smrg devi->supported = rep.supported; 265818534a1Smrg devi->unsupported = rep.unsupported; 266818534a1Smrg devi->type = rep.devType; 267818534a1Smrg devi->has_own_state = rep.hasOwnState; 268818534a1Smrg devi->dflt_kbd_fb = rep.dfltKbdFB; 269818534a1Smrg devi->dflt_led_fb = rep.dfltLedFB; 270818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 271818534a1Smrg if (status != Success) { 272818534a1Smrg XkbFreeDeviceInfo(devi, XkbXI_AllDeviceFeaturesMask, True); 273818534a1Smrg devi = NULL; 274818534a1Smrg } 2751ab64890Smrg } 2761ab64890Smrg UnlockDisplay(dpy); 2771ab64890Smrg SyncHandle(); 2781ab64890Smrg return devi; 2791ab64890Smrg} 2801ab64890Smrg 2811ab64890SmrgStatus 282818534a1SmrgXkbGetDeviceInfoChanges(Display *dpy, 283818534a1Smrg XkbDeviceInfoPtr devi, 284818534a1Smrg XkbDeviceChangesPtr changes) 2851ab64890Smrg{ 286818534a1Smrg register xkbGetDeviceInfoReq *req; 287818534a1Smrg xkbGetDeviceInfoReply rep; 288818534a1Smrg Status status; 2891ab64890Smrg 2901ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 291818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 292818534a1Smrg return BadMatch; 293818534a1Smrg if ((changes->changed & XkbXI_AllDeviceFeaturesMask) == 0) 294818534a1Smrg return Success; 295818534a1Smrg changes->changed &= ~XkbXI_AllDeviceFeaturesMask; 296818534a1Smrg status = Success; 2971ab64890Smrg LockDisplay(dpy); 298818534a1Smrg while ((changes->changed) && (status == Success)) { 299818534a1Smrg GetReq(kbGetDeviceInfo, req); 300818534a1Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 301818534a1Smrg req->xkbReqType = X_kbGetDeviceInfo; 302818534a1Smrg req->deviceSpec = devi->device_spec; 303818534a1Smrg req->wanted = changes->changed; 304818534a1Smrg req->allBtns = False; 305818534a1Smrg if (changes->changed & XkbXI_ButtonActionsMask) { 306818534a1Smrg req->firstBtn = changes->first_btn; 307818534a1Smrg req->nBtns = changes->num_btns; 308818534a1Smrg changes->changed &= ~XkbXI_ButtonActionsMask; 309818534a1Smrg } 310818534a1Smrg else 311818534a1Smrg req->firstBtn = req->nBtns = 0; 312818534a1Smrg if (changes->changed & XkbXI_IndicatorsMask) { 313818534a1Smrg req->ledClass = changes->leds.led_class; 314818534a1Smrg req->ledID = changes->leds.led_id; 315818534a1Smrg if (changes->leds.next == NULL) 316818534a1Smrg changes->changed &= ~XkbXI_IndicatorsMask; 317818534a1Smrg else { 318818534a1Smrg XkbDeviceLedChangesPtr next; 319818534a1Smrg 320818534a1Smrg next = changes->leds.next; 321818534a1Smrg changes->leds = *next; 322818534a1Smrg _XkbFree(next); 323818534a1Smrg } 324818534a1Smrg } 325818534a1Smrg else { 326818534a1Smrg req->ledClass = XkbDfltXIClass; 327818534a1Smrg req->ledID = XkbDfltXIId; 328818534a1Smrg } 329818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 330818534a1Smrg status = BadLength; 331818534a1Smrg break; 332818534a1Smrg } 333818534a1Smrg devi->supported |= rep.supported; 334818534a1Smrg devi->unsupported |= rep.unsupported; 335818534a1Smrg devi->type = rep.devType; 336818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 3371ab64890Smrg } 3381ab64890Smrg UnlockDisplay(dpy); 3391ab64890Smrg SyncHandle(); 3401ab64890Smrg return status; 3411ab64890Smrg} 3421ab64890Smrg 3431ab64890SmrgStatus 344818534a1SmrgXkbGetDeviceButtonActions(Display *dpy, 345818534a1Smrg XkbDeviceInfoPtr devi, 346818534a1Smrg Bool all, 347818534a1Smrg unsigned int first, 348818534a1Smrg unsigned int num) 3491ab64890Smrg{ 350818534a1Smrg register xkbGetDeviceInfoReq *req; 351818534a1Smrg xkbGetDeviceInfoReply rep; 352818534a1Smrg Status status; 3531ab64890Smrg 35461b2299dSmrg if ((dpy->flags & XlibDisplayNoXkb) || 355818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 356818534a1Smrg return BadMatch; 3571ab64890Smrg if (!devi) 358818534a1Smrg return BadValue; 3591ab64890Smrg LockDisplay(dpy); 3601ab64890Smrg GetReq(kbGetDeviceInfo, req); 3611ab64890Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 3621ab64890Smrg req->xkbReqType = X_kbGetDeviceInfo; 3631ab64890Smrg req->deviceSpec = devi->device_spec; 364818534a1Smrg req->wanted = XkbXI_ButtonActionsMask; 365818534a1Smrg req->allBtns = all; 366818534a1Smrg req->firstBtn = first; 367818534a1Smrg req->nBtns = num; 368818534a1Smrg req->ledClass = XkbDfltXIClass; 369818534a1Smrg req->ledID = XkbDfltXIId; 370818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 371818534a1Smrg UnlockDisplay(dpy); 372818534a1Smrg SyncHandle(); 373818534a1Smrg return BadLength; 3741ab64890Smrg } 375818534a1Smrg devi->type = rep.devType; 376818534a1Smrg devi->supported = rep.supported; 377818534a1Smrg devi->unsupported = rep.unsupported; 378818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 3791ab64890Smrg UnlockDisplay(dpy); 3801ab64890Smrg SyncHandle(); 3811ab64890Smrg return status; 3821ab64890Smrg} 3831ab64890Smrg 3841ab64890SmrgStatus 385818534a1SmrgXkbGetDeviceLedInfo(Display *dpy, 386818534a1Smrg XkbDeviceInfoPtr devi, 387818534a1Smrg unsigned int ledClass, 388818534a1Smrg unsigned int ledId, 389818534a1Smrg unsigned int which) 3901ab64890Smrg{ 391818534a1Smrg register xkbGetDeviceInfoReq *req; 392818534a1Smrg xkbGetDeviceInfoReply rep; 393818534a1Smrg Status status; 3941ab64890Smrg 39561b2299dSmrg if ((dpy->flags & XlibDisplayNoXkb) || 396818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 397818534a1Smrg return BadMatch; 398818534a1Smrg if (((which & XkbXI_IndicatorsMask) == 0) || 399818534a1Smrg (which & (~XkbXI_IndicatorsMask))) 400818534a1Smrg return BadMatch; 4011ab64890Smrg if (!devi) 402818534a1Smrg return BadValue; 4031ab64890Smrg LockDisplay(dpy); 4041ab64890Smrg GetReq(kbGetDeviceInfo, req); 4051ab64890Smrg req->reqType = dpy->xkb_info->codes->major_opcode; 4061ab64890Smrg req->xkbReqType = X_kbGetDeviceInfo; 4071ab64890Smrg req->deviceSpec = devi->device_spec; 408818534a1Smrg req->wanted = which; 409818534a1Smrg req->allBtns = False; 410818534a1Smrg req->firstBtn = req->nBtns = 0; 411818534a1Smrg req->ledClass = ledClass; 412818534a1Smrg req->ledID = ledId; 413818534a1Smrg if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 414818534a1Smrg UnlockDisplay(dpy); 415818534a1Smrg SyncHandle(); 416818534a1Smrg return BadLength; 41761b2299dSmrg } 418818534a1Smrg devi->type = rep.devType; 419818534a1Smrg devi->supported = rep.supported; 420818534a1Smrg devi->unsupported = rep.unsupported; 421818534a1Smrg status = _XkbReadGetDeviceInfoReply(dpy, &rep, devi); 4221ab64890Smrg UnlockDisplay(dpy); 4231ab64890Smrg SyncHandle(); 4241ab64890Smrg return status; 4251ab64890Smrg} 4261ab64890Smrg 4271ab64890Smrg/***====================================================================***/ 4281ab64890Smrg 4291ab64890Smrgtypedef struct _LedInfoStuff { 430818534a1Smrg Bool used; 431818534a1Smrg XkbDeviceLedInfoPtr devli; 4321ab64890Smrg} LedInfoStuff; 4331ab64890Smrg 4341ab64890Smrgtypedef struct _SetLedStuff { 435818534a1Smrg unsigned wanted; 436818534a1Smrg int num_info; 437818534a1Smrg int dflt_class; 438818534a1Smrg LedInfoStuff *dflt_kbd_fb; 439818534a1Smrg LedInfoStuff *dflt_led_fb; 440818534a1Smrg LedInfoStuff *info; 4411ab64890Smrg} SetLedStuff; 4421ab64890Smrg 4431ab64890Smrgstatic void 444818534a1Smrg_InitLedStuff(SetLedStuff *stuff, unsigned wanted, XkbDeviceInfoPtr devi) 4451ab64890Smrg{ 446818534a1Smrg int i; 447818534a1Smrg register XkbDeviceLedInfoPtr devli; 448818534a1Smrg 449818534a1Smrg bzero(stuff, sizeof(SetLedStuff)); 450818534a1Smrg stuff->wanted = wanted; 451818534a1Smrg stuff->dflt_class = XkbXINone; 452818534a1Smrg if ((devi->num_leds < 1) || ((wanted & XkbXI_IndicatorsMask) == 0)) 453818534a1Smrg return; 454818534a1Smrg stuff->info = _XkbTypedCalloc(devi->num_leds, LedInfoStuff); 4551ab64890Smrg if (!stuff->info) 456818534a1Smrg return; 457818534a1Smrg stuff->num_info = devi->num_leds; 458818534a1Smrg for (devli = &devi->leds[0], i = 0; i < devi->num_leds; i++, devli++) { 459818534a1Smrg stuff->info[i].devli = devli; 460818534a1Smrg if (devli->led_class == KbdFeedbackClass) { 461818534a1Smrg stuff->dflt_class = KbdFeedbackClass; 462818534a1Smrg if (stuff->dflt_kbd_fb == NULL) 463818534a1Smrg stuff->dflt_kbd_fb = &stuff->info[i]; 464818534a1Smrg } 465818534a1Smrg else if (devli->led_class == LedFeedbackClass) { 466818534a1Smrg if (stuff->dflt_class == XkbXINone) 467818534a1Smrg stuff->dflt_class = LedFeedbackClass; 468818534a1Smrg if (stuff->dflt_led_fb == NULL) 469818534a1Smrg stuff->dflt_led_fb = &stuff->info[i]; 470818534a1Smrg } 4711ab64890Smrg } 4721ab64890Smrg return; 4731ab64890Smrg} 4741ab64890Smrg 4751ab64890Smrgstatic void 476818534a1Smrg_FreeLedStuff(SetLedStuff * stuff) 4771ab64890Smrg{ 4780f8248bfSmrg if (stuff->num_info > 0) 479818534a1Smrg _XkbFree(stuff->info); 480818534a1Smrg bzero(stuff, sizeof(SetLedStuff)); 4811ab64890Smrg return; 4821ab64890Smrg} 4831ab64890Smrg 4841ab64890Smrgstatic int 485818534a1Smrg_XkbSizeLedInfo(unsigned changed, XkbDeviceLedInfoPtr devli) 4861ab64890Smrg{ 487818534a1Smrg register int i, size; 488818534a1Smrg register unsigned bit, namesNeeded, mapsNeeded; 489818534a1Smrg 490818534a1Smrg size = SIZEOF(xkbDeviceLedsWireDesc); 491818534a1Smrg namesNeeded = mapsNeeded = 0; 492818534a1Smrg if (changed & XkbXI_IndicatorNamesMask) 493818534a1Smrg namesNeeded = devli->names_present; 494818534a1Smrg if (changed & XkbXI_IndicatorMapsMask) 495818534a1Smrg mapsNeeded = devli->maps_present; 496818534a1Smrg if ((namesNeeded) || (mapsNeeded)) { 497818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 498818534a1Smrg if (namesNeeded & bit) 499818534a1Smrg size += 4; /* atoms are 4 bytes on the wire */ 500818534a1Smrg if (mapsNeeded & bit) 501818534a1Smrg size += SIZEOF(xkbIndicatorMapWireDesc); 502818534a1Smrg } 5031ab64890Smrg } 5041ab64890Smrg return size; 5051ab64890Smrg} 5061ab64890Smrg 5071ab64890Smrgstatic Bool 508818534a1Smrg_SizeMatches(SetLedStuff *stuff, 509818534a1Smrg XkbDeviceLedChangesPtr changes, 510818534a1Smrg int *sz_rtrn, 511818534a1Smrg int *nleds_rtrn) 5121ab64890Smrg{ 513818534a1Smrg int i, nMatch, class, id; 514818534a1Smrg LedInfoStuff *linfo; 515818534a1Smrg Bool match; 516818534a1Smrg 517818534a1Smrg nMatch = 0; 518818534a1Smrg class = changes->led_class; 519818534a1Smrg id = changes->led_id; 520818534a1Smrg if (class == XkbDfltXIClass) 521818534a1Smrg class = stuff->dflt_class; 522818534a1Smrg for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) { 523818534a1Smrg XkbDeviceLedInfoPtr devli; 524818534a1Smrg LedInfoStuff *dflt; 525818534a1Smrg 526818534a1Smrg devli = linfo->devli; 527818534a1Smrg match = ((class == devli->led_class) || (class == XkbAllXIClasses)); 528818534a1Smrg if (devli->led_class == KbdFeedbackClass) 529818534a1Smrg dflt = stuff->dflt_kbd_fb; 530818534a1Smrg else 531818534a1Smrg dflt = stuff->dflt_led_fb; 532818534a1Smrg match = (match && (id == devli->led_id)) || 533818534a1Smrg (id == XkbAllXIIds) || 534818534a1Smrg ((id == XkbDfltXIId) && (linfo == dflt)); 535818534a1Smrg if (match) { 536818534a1Smrg if (!linfo->used) { 537818534a1Smrg *sz_rtrn += _XkbSizeLedInfo(stuff->wanted, devli); 538818534a1Smrg *nleds_rtrn += 1; 539818534a1Smrg linfo->used = True; 540818534a1Smrg if ((class != XkbAllXIClasses) && (id != XkbAllXIIds)) 541818534a1Smrg return True; 542818534a1Smrg } 543818534a1Smrg nMatch++; 544818534a1Smrg linfo->used = True; 545818534a1Smrg } 5461ab64890Smrg } 547818534a1Smrg return (nMatch > 0); 5481ab64890Smrg} 5491ab64890Smrg 5501ab64890Smrg/***====================================================================***/ 5511ab64890Smrg 5521ab64890Smrg 5531ab64890Smrgstatic Status 554818534a1Smrg_XkbSetDeviceInfoSize(XkbDeviceInfoPtr devi, 555818534a1Smrg XkbDeviceChangesPtr changes, 556818534a1Smrg SetLedStuff *stuff, 557818534a1Smrg int *sz_rtrn, 558818534a1Smrg int *num_leds_rtrn) 5591ab64890Smrg{ 560818534a1Smrg *sz_rtrn = 0; 561818534a1Smrg if ((changes->changed & XkbXI_ButtonActionsMask) && (changes->num_btns > 0)) { 562818534a1Smrg if (!XkbXI_LegalDevBtn 563818534a1Smrg (devi, (changes->first_btn + changes->num_btns - 1))) 564818534a1Smrg return BadMatch; 565818534a1Smrg *sz_rtrn += changes->num_btns * SIZEOF(xkbActionWireDesc); 5661ab64890Smrg } 5671ab64890Smrg else { 568818534a1Smrg changes->changed &= ~XkbXI_ButtonActionsMask; 569818534a1Smrg changes->first_btn = changes->num_btns = 0; 5701ab64890Smrg } 571818534a1Smrg if ((changes->changed & XkbXI_IndicatorsMask) && 572818534a1Smrg XkbLegalXILedClass(changes->leds.led_class)) { 573818534a1Smrg XkbDeviceLedChangesPtr leds; 574818534a1Smrg 575818534a1Smrg for (leds = &changes->leds; leds != NULL; leds = leds->next) { 576818534a1Smrg if (!_SizeMatches(stuff, leds, sz_rtrn, num_leds_rtrn)) 577818534a1Smrg return BadMatch; 578818534a1Smrg } 5791ab64890Smrg } 5801ab64890Smrg else { 581818534a1Smrg changes->changed &= ~XkbXI_IndicatorsMask; 582818534a1Smrg *num_leds_rtrn = 0; 5831ab64890Smrg } 5841ab64890Smrg return Success; 5851ab64890Smrg} 5861ab64890Smrg 5871ab64890Smrgstatic char * 588818534a1Smrg_XkbWriteLedInfo(char *wire, unsigned changed, XkbDeviceLedInfoPtr devli) 5891ab64890Smrg{ 590818534a1Smrg register int i; 591818534a1Smrg register unsigned bit, namesNeeded, mapsNeeded; 592818534a1Smrg xkbDeviceLedsWireDesc *lwire; 593818534a1Smrg 594818534a1Smrg namesNeeded = mapsNeeded = 0; 595818534a1Smrg if (changed & XkbXI_IndicatorNamesMask) 596818534a1Smrg namesNeeded = devli->names_present; 597818534a1Smrg if (changed & XkbXI_IndicatorMapsMask) 598818534a1Smrg mapsNeeded = devli->maps_present; 599818534a1Smrg 600818534a1Smrg lwire = (xkbDeviceLedsWireDesc *) wire; 601818534a1Smrg lwire->ledClass = devli->led_class; 602818534a1Smrg lwire->ledID = devli->led_id; 603818534a1Smrg lwire->namesPresent = namesNeeded; 604818534a1Smrg lwire->mapsPresent = mapsNeeded; 605818534a1Smrg lwire->physIndicators = devli->phys_indicators; 606818534a1Smrg lwire->state = devli->state; 607818534a1Smrg wire = (char *) &lwire[1]; 6081ab64890Smrg if (namesNeeded) { 609818534a1Smrg CARD32 *awire = (CARD32 *) wire; 610818534a1Smrg 611818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 612818534a1Smrg if (namesNeeded & bit) { 613818534a1Smrg *awire = (CARD32) devli->names[i]; 614818534a1Smrg awire++; 615818534a1Smrg } 616818534a1Smrg } 617818534a1Smrg wire = (char *) awire; 6181ab64890Smrg } 6191ab64890Smrg if (mapsNeeded) { 620818534a1Smrg xkbIndicatorMapWireDesc *mwire = (xkbIndicatorMapWireDesc *) wire; 621818534a1Smrg 622818534a1Smrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 623818534a1Smrg if (mapsNeeded & bit) { 624818534a1Smrg XkbIndicatorMapPtr map = &devli->maps[i]; 625818534a1Smrg 626818534a1Smrg mwire->flags = map->flags; 627818534a1Smrg mwire->whichGroups = map->which_groups; 628818534a1Smrg mwire->groups = map->groups; 629818534a1Smrg mwire->whichMods = map->which_mods; 630818534a1Smrg mwire->mods = map->mods.mask; 631818534a1Smrg mwire->realMods = map->mods.real_mods; 632818534a1Smrg mwire->virtualMods = map->mods.vmods; 633818534a1Smrg mwire->ctrls = map->ctrls; 634818534a1Smrg mwire++; 635818534a1Smrg } 636818534a1Smrg } 637818534a1Smrg wire = (char *) mwire; 6381ab64890Smrg } 6391ab64890Smrg return wire; 6401ab64890Smrg} 6411ab64890Smrg 6421ab64890Smrg 6431ab64890Smrgstatic int 644818534a1Smrg_XkbWriteSetDeviceInfo(char *wire, 645818534a1Smrg XkbDeviceChangesPtr changes, 646818534a1Smrg SetLedStuff *stuff, 647818534a1Smrg XkbDeviceInfoPtr devi) 6481ab64890Smrg{ 649818534a1Smrg char *start = wire; 650818534a1Smrg 651818534a1Smrg if (changes->changed & XkbXI_ButtonActionsMask) { 652818534a1Smrg int size = changes->num_btns * SIZEOF(xkbActionWireDesc); 653818534a1Smrg 654818534a1Smrg memcpy(wire, (char *) &devi->btn_acts[changes->first_btn], size); 655818534a1Smrg wire += size; 6561ab64890Smrg } 657818534a1Smrg if (changes->changed & XkbXI_IndicatorsMask) { 658818534a1Smrg register int i; 659818534a1Smrg register LedInfoStuff *linfo; 660818534a1Smrg 661818534a1Smrg for (i = 0, linfo = &stuff->info[0]; i < stuff->num_info; i++, linfo++) { 662818534a1Smrg if (linfo->used) { 663818534a1Smrg register char *new_wire; 664818534a1Smrg 665818534a1Smrg new_wire = _XkbWriteLedInfo(wire, stuff->wanted, linfo->devli); 666818534a1Smrg if (!new_wire) 667818534a1Smrg return wire - start; 668818534a1Smrg wire = new_wire; 669818534a1Smrg } 670818534a1Smrg } 6711ab64890Smrg } 672818534a1Smrg return wire - start; 6731ab64890Smrg} 6741ab64890Smrg 6751ab64890SmrgBool 676818534a1SmrgXkbSetDeviceInfo(Display *dpy, unsigned which, XkbDeviceInfoPtr devi) 6771ab64890Smrg{ 6781ab64890Smrg register xkbSetDeviceInfoReq *req; 679818534a1Smrg Status ok = 0; 680818534a1Smrg int size, nLeds; 681818534a1Smrg XkbInfoPtr xkbi; 682818534a1Smrg XkbDeviceChangesRec changes; 683818534a1Smrg SetLedStuff lstuff; 6841ab64890Smrg 6851ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 686818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 687818534a1Smrg return False; 688818534a1Smrg if ((!devi) || (which & (~XkbXI_AllDeviceFeaturesMask)) || 689818534a1Smrg ((which & XkbXI_ButtonActionsMask) && (!XkbXI_DevHasBtnActs(devi))) || 690818534a1Smrg ((which & XkbXI_IndicatorsMask) && (!XkbXI_DevHasLeds(devi)))) 691818534a1Smrg return False; 692818534a1Smrg 693818534a1Smrg bzero((char *) &changes, sizeof(XkbDeviceChangesRec)); 694818534a1Smrg changes.changed = which; 695818534a1Smrg changes.first_btn = 0; 696818534a1Smrg changes.num_btns = devi->num_btns; 697818534a1Smrg changes.leds.led_class = XkbAllXIClasses; 698818534a1Smrg changes.leds.led_id = XkbAllXIIds; 699818534a1Smrg changes.leds.defined = 0; 700818534a1Smrg size = nLeds = 0; 701818534a1Smrg _InitLedStuff(&lstuff, changes.changed, devi); 702818534a1Smrg if (_XkbSetDeviceInfoSize(devi, &changes, &lstuff, &size, &nLeds) != 703818534a1Smrg Success) 704818534a1Smrg return False; 7051ab64890Smrg LockDisplay(dpy); 7061ab64890Smrg xkbi = dpy->xkb_info; 7071ab64890Smrg GetReq(kbSetDeviceInfo, req); 708818534a1Smrg req->length += size / 4; 709818534a1Smrg req->reqType = xkbi->codes->major_opcode; 710818534a1Smrg req->xkbReqType = X_kbSetDeviceInfo; 711818534a1Smrg req->deviceSpec = devi->device_spec; 712818534a1Smrg req->firstBtn = changes.first_btn; 713818534a1Smrg req->nBtns = changes.num_btns; 714818534a1Smrg req->change = changes.changed; 715818534a1Smrg req->nDeviceLedFBs = nLeds; 716818534a1Smrg if (size > 0) { 717818534a1Smrg char *wire; 718818534a1Smrg 719818534a1Smrg BufAlloc(char *, wire, size); 720818534a1Smrg ok = (wire != NULL) && 721818534a1Smrg (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size); 7221ab64890Smrg } 7231ab64890Smrg UnlockDisplay(dpy); 7241ab64890Smrg SyncHandle(); 7251ab64890Smrg _FreeLedStuff(&lstuff); 7261ab64890Smrg /* 12/11/95 (ef) -- XXX!! should clear changes here */ 7271ab64890Smrg return ok; 7281ab64890Smrg} 7291ab64890Smrg 7301ab64890SmrgBool 731818534a1SmrgXkbChangeDeviceInfo(Display *dpy, 732818534a1Smrg XkbDeviceInfoPtr devi, 733818534a1Smrg XkbDeviceChangesPtr changes) 7341ab64890Smrg{ 7351ab64890Smrg register xkbSetDeviceInfoReq *req; 736818534a1Smrg Status ok = 0; 737818534a1Smrg int size, nLeds; 738818534a1Smrg XkbInfoPtr xkbi; 739818534a1Smrg SetLedStuff lstuff; 7401ab64890Smrg 7411ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 742818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 743818534a1Smrg return False; 744818534a1Smrg if ((!devi) || (changes->changed & (~XkbXI_AllDeviceFeaturesMask)) || 745818534a1Smrg ((changes->changed & XkbXI_ButtonActionsMask) && 746818534a1Smrg (!XkbXI_DevHasBtnActs(devi))) || 747818534a1Smrg ((changes->changed & XkbXI_IndicatorsMask) && 748818534a1Smrg (!XkbXI_DevHasLeds(devi)))) 749818534a1Smrg return False; 750818534a1Smrg 751818534a1Smrg size = nLeds = 0; 752818534a1Smrg _InitLedStuff(&lstuff, changes->changed, devi); 753818534a1Smrg if (_XkbSetDeviceInfoSize(devi, changes, &lstuff, &size, &nLeds) != Success) 754818534a1Smrg return False; 7551ab64890Smrg LockDisplay(dpy); 7561ab64890Smrg xkbi = dpy->xkb_info; 7571ab64890Smrg GetReq(kbSetDeviceInfo, req); 758818534a1Smrg req->length += size / 4; 759818534a1Smrg req->reqType = xkbi->codes->major_opcode; 760818534a1Smrg req->xkbReqType = X_kbSetDeviceInfo; 761818534a1Smrg req->deviceSpec = devi->device_spec; 762818534a1Smrg req->firstBtn = changes->first_btn; 763818534a1Smrg req->nBtns = changes->num_btns; 764818534a1Smrg req->change = changes->changed; 765818534a1Smrg req->nDeviceLedFBs = nLeds; 766818534a1Smrg if (size > 0) { 767818534a1Smrg char *wire; 768818534a1Smrg 769818534a1Smrg BufAlloc(char *, wire, size); 770818534a1Smrg ok = (wire != NULL) && 771818534a1Smrg (_XkbWriteSetDeviceInfo(wire, changes, &lstuff, devi) == size); 7721ab64890Smrg } 7731ab64890Smrg UnlockDisplay(dpy); 7741ab64890Smrg SyncHandle(); 7751ab64890Smrg _FreeLedStuff(&lstuff); 7761ab64890Smrg /* 12/11/95 (ef) -- XXX!! should clear changes here */ 7771ab64890Smrg return ok; 7781ab64890Smrg} 7791ab64890Smrg 78061b2299dSmrgBool 781818534a1SmrgXkbSetDeviceLedInfo(Display *dpy, 782818534a1Smrg XkbDeviceInfoPtr devi, 783818534a1Smrg unsigned ledClass, 784818534a1Smrg unsigned ledID, 785818534a1Smrg unsigned which) 7861ab64890Smrg{ 7871ab64890Smrg return False; 7881ab64890Smrg} 7891ab64890Smrg 79061b2299dSmrgBool 791818534a1SmrgXkbSetDeviceButtonActions(Display *dpy, 792818534a1Smrg XkbDeviceInfoPtr devi, 793818534a1Smrg unsigned int first, 794818534a1Smrg unsigned int nBtns) 7951ab64890Smrg{ 7961ab64890Smrg register xkbSetDeviceInfoReq *req; 797818534a1Smrg Status ok = 0; 798818534a1Smrg int size, nLeds; 799818534a1Smrg XkbInfoPtr xkbi; 800818534a1Smrg XkbDeviceChangesRec changes; 801818534a1Smrg SetLedStuff lstuff; 8021ab64890Smrg 8031ab64890Smrg if ((dpy->flags & XlibDisplayNoXkb) || 804818534a1Smrg (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 805818534a1Smrg return False; 806818534a1Smrg if ((!devi) || (!XkbXI_DevHasBtnActs(devi)) || 807818534a1Smrg (first + nBtns > devi->num_btns)) 808818534a1Smrg return False; 809818534a1Smrg if (nBtns == 0) 810818534a1Smrg return True; 811818534a1Smrg 812818534a1Smrg bzero((char *) &changes, sizeof(XkbDeviceChangesRec)); 813818534a1Smrg changes.changed = XkbXI_ButtonActionsMask; 814818534a1Smrg changes.first_btn = first; 815818534a1Smrg changes.num_btns = nBtns; 816818534a1Smrg changes.leds.led_class = XkbXINone; 817818534a1Smrg changes.leds.led_id = XkbXINone; 818818534a1Smrg changes.leds.defined = 0; 819818534a1Smrg size = nLeds = 0; 820818534a1Smrg if (_XkbSetDeviceInfoSize(devi, &changes, NULL, &size, &nLeds) != Success) 821818534a1Smrg return False; 8221ab64890Smrg LockDisplay(dpy); 8231ab64890Smrg xkbi = dpy->xkb_info; 8241ab64890Smrg GetReq(kbSetDeviceInfo, req); 825818534a1Smrg req->length += size / 4; 826818534a1Smrg req->reqType = xkbi->codes->major_opcode; 827818534a1Smrg req->xkbReqType = X_kbSetDeviceInfo; 828818534a1Smrg req->deviceSpec = devi->device_spec; 829818534a1Smrg req->firstBtn = changes.first_btn; 830818534a1Smrg req->nBtns = changes.num_btns; 831818534a1Smrg req->change = changes.changed; 832818534a1Smrg req->nDeviceLedFBs = nLeds; 833818534a1Smrg if (size > 0) { 834818534a1Smrg char *wire; 835818534a1Smrg 836818534a1Smrg BufAlloc(char *, wire, size); 837818534a1Smrg ok = (wire != NULL) && 838818534a1Smrg (_XkbWriteSetDeviceInfo(wire, &changes, &lstuff, devi) == size); 8391ab64890Smrg } 8401ab64890Smrg UnlockDisplay(dpy); 8411ab64890Smrg SyncHandle(); 8421ab64890Smrg return ok; 8431ab64890Smrg} 844