1 /************************************************************
2 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
31 #define NEED_MAP_READERS
33 #include <X11/extensions/XKBproto.h>
34 #include "XKBlibint.h"
35 #include <X11/extensions/XI.h>
37 /***====================================================================***/
40 XkbNoteDeviceChanges( XkbDeviceChangesPtr old,
41 XkbExtensionDeviceNotifyEvent * new,
44 if ((!old)||(!new)||(!wanted)||((new->reason&wanted)==0))
46 if ((wanted&new->reason)&XkbXI_ButtonActionsMask) {
47 if (old->changed&XkbXI_ButtonActionsMask) {
48 int first,last,newLast;
49 if (new->first_btn<old->first_btn)
50 first= new->first_btn;
51 else first= old->first_btn;
52 last= old->first_btn+old->num_btns-1;
53 newLast= new->first_btn+new->num_btns-1;
56 old->first_btn= first;
57 old->num_btns= (last-first)+1;
60 old->changed|= XkbXI_ButtonActionsMask;
61 old->first_btn= new->first_btn;
62 old->num_btns= new->num_btns;
65 if ((wanted&new->reason)&XkbXI_IndicatorsMask) {
66 XkbDeviceLedChangesPtr this;
67 if (old->changed&XkbXI_IndicatorsMask) {
68 XkbDeviceLedChangesPtr found;
70 for (this= &old->leds;this&&(!found);this=this->next) {
71 if ((this->led_class==new->led_class)&&
72 (this->led_id==new->led_id)) {
77 found= _XkbTypedCalloc(1,XkbDeviceLedChangesRec);
80 found->next= old->leds.next;
81 found->led_class= new->led_class;
82 found->led_id= new->led_id;
83 old->leds.next= found;
85 if ((wanted&new->reason)&XkbXI_IndicatorNamesMask)
86 found->defined= new->leds_defined;
89 old->changed|= ((wanted&new->reason)&XkbXI_IndicatorsMask);
90 old->leds.led_class= new->led_class;
91 old->leds.led_id= new->led_id;
92 old->leds.defined= new->leds_defined;
94 XkbDeviceLedChangesPtr next;
95 for (this=old->leds.next;this;this=next) {
106 /***====================================================================***/
109 _XkbReadDeviceLedInfo( XkbReadBufferPtr buf,
111 XkbDeviceInfoPtr devi)
113 register unsigned i,bit;
114 XkbDeviceLedInfoPtr devli;
115 xkbDeviceLedsWireDesc * wireli;
117 wireli= _XkbGetTypedRdBufPtr(buf,1,xkbDeviceLedsWireDesc);
120 devli= XkbAddDeviceLedInfo(devi,wireli->ledClass,wireli->ledID);
123 devli->phys_indicators= wireli->physIndicators;
125 if (present&XkbXI_IndicatorStateMask)
126 devli->state= wireli->state;
128 if (present&XkbXI_IndicatorNamesMask) {
129 devli->names_present= wireli->namesPresent;
130 if (devli->names_present) {
131 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
132 if (wireli->namesPresent&bit) {
133 if (!_XkbCopyFromReadBuffer(buf,(char *)&devli->names[i],4))
140 if (present&XkbXI_IndicatorMapsMask) {
141 devli->maps_present= wireli->mapsPresent;
142 if (devli->maps_present) {
143 XkbIndicatorMapPtr im;
144 xkbIndicatorMapWireDesc * wireim;
145 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
146 if (wireli->mapsPresent&bit) {
147 wireim= _XkbGetTypedRdBufPtr(buf,1,xkbIndicatorMapWireDesc);
151 im->flags= wireim->flags;
152 im->which_groups= wireim->whichGroups;
153 im->groups= wireim->groups;
154 im->which_mods= wireim->whichMods;
155 im->mods.mask= wireim->mods;
156 im->mods.real_mods= wireim->realMods;
157 im->mods.vmods= wireim->virtualMods;
158 im->ctrls= wireim->ctrls;
167 _XkbReadGetDeviceInfoReply( Display * dpy,
168 xkbGetDeviceInfoReply * rep,
169 XkbDeviceInfoPtr devi)
171 XkbReadBufferRec buf;
175 if (!_XkbInitReadBuffer(dpy,&buf,(int)rep->length*4))
178 if ((rep->totalBtns>0)&&(rep->totalBtns!=devi->num_btns)) {
179 tmp= XkbResizeDeviceButtonActions(devi,rep->totalBtns);
183 if (rep->nBtnsWanted>0) {
184 act= &devi->btn_acts[rep->firstBtnWanted];
185 bzero((char *)act,(rep->nBtnsWanted*sizeof(XkbAction)));
187 if (devi->name!=NULL)
188 _XkbFree(devi->name);
189 if (!_XkbGetReadBufferCountedString(&buf,&devi->name))
191 if (rep->nBtnsRtrn>0) {
193 act= &devi->btn_acts[rep->firstBtnRtrn];
194 size= rep->nBtnsRtrn*SIZEOF(xkbActionWireDesc);
195 if (!_XkbCopyFromReadBuffer(&buf,(char *)act,size))
198 if (rep->nDeviceLedFBs>0) {
200 for (i=0;i<rep->nDeviceLedFBs;i++) {
201 if ((tmp= _XkbReadDeviceLedInfo(&buf,rep->present,devi))!=Success)
205 tmp= _XkbFreeReadBuffer(&buf);
207 fprintf(stderr,"GetDeviceInfo! Bad length (%d extra bytes)\n",tmp);
208 if (tmp || buf.error)
212 _XkbFreeReadBuffer(&buf);
217 XkbGetDeviceInfo( Display * dpy,
223 register xkbGetDeviceInfoReq * req;
224 xkbGetDeviceInfoReply rep;
226 XkbDeviceInfoPtr devi;
228 if ((dpy->flags & XlibDisplayNoXkb) ||
229 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
232 GetReq(kbGetDeviceInfo, req);
233 req->reqType = dpy->xkb_info->codes->major_opcode;
234 req->xkbReqType = X_kbGetDeviceInfo;
235 req->deviceSpec = deviceSpec;
237 req->allBtns= ((which&XkbXI_ButtonActionsMask)!=0);
238 req->firstBtn= req->nBtns= 0;
239 req->ledClass= class;
241 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
246 devi= XkbAllocDeviceInfo(rep.deviceID,rep.totalBtns,rep.nDeviceLedFBs);
248 devi->supported= rep.supported;
249 devi->unsupported= rep.unsupported;
250 devi->type= rep.devType;
251 devi->has_own_state= rep.hasOwnState;
252 devi->dflt_kbd_fb = rep.dfltKbdFB;
253 devi->dflt_led_fb = rep.dfltLedFB;
254 status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
255 if (status!=Success) {
256 XkbFreeDeviceInfo(devi,XkbXI_AllDeviceFeaturesMask,True);
266 XkbGetDeviceInfoChanges( Display * dpy,
267 XkbDeviceInfoPtr devi,
268 XkbDeviceChangesPtr changes)
270 register xkbGetDeviceInfoReq * req;
271 xkbGetDeviceInfoReply rep;
274 if ((dpy->flags & XlibDisplayNoXkb) ||
275 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
277 if ((changes->changed&XkbXI_AllDeviceFeaturesMask)==0)
279 changes->changed&= ~XkbXI_AllDeviceFeaturesMask;
282 while ((changes->changed)&&(status==Success)) {
283 GetReq(kbGetDeviceInfo, req);
284 req->reqType = dpy->xkb_info->codes->major_opcode;
285 req->xkbReqType = X_kbGetDeviceInfo;
286 req->deviceSpec = devi->device_spec;
287 req->wanted= changes->changed;
289 if (changes->changed&XkbXI_ButtonActionsMask) {
290 req->firstBtn= changes->first_btn;
291 req->nBtns= changes->num_btns;
292 changes->changed&= ~XkbXI_ButtonActionsMask;
294 else req->firstBtn= req->nBtns= 0;
295 if (changes->changed&XkbXI_IndicatorsMask) {
296 req->ledClass= changes->leds.led_class;
297 req->ledID= changes->leds.led_id;
298 if (changes->leds.next==NULL)
299 changes->changed&= ~XkbXI_IndicatorsMask;
301 XkbDeviceLedChangesPtr next;
302 next= changes->leds.next;
303 changes->leds= *next;
308 req->ledClass= XkbDfltXIClass;
309 req->ledID= XkbDfltXIId;
311 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
315 devi->supported|= rep.supported;
316 devi->unsupported|= rep.unsupported;
317 devi->type= rep.devType;
318 status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
326 XkbGetDeviceButtonActions( Display * dpy,
327 XkbDeviceInfoPtr devi,
332 register xkbGetDeviceInfoReq * req;
333 xkbGetDeviceInfoReply rep;
336 if ((dpy->flags & XlibDisplayNoXkb) ||
337 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
342 GetReq(kbGetDeviceInfo, req);
343 req->reqType = dpy->xkb_info->codes->major_opcode;
344 req->xkbReqType = X_kbGetDeviceInfo;
345 req->deviceSpec = devi->device_spec;
346 req->wanted= XkbXI_ButtonActionsMask;
348 req->firstBtn= first;
350 req->ledClass= XkbDfltXIClass;
351 req->ledID= XkbDfltXIId;
352 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
357 devi->type= rep.devType;
358 devi->supported= rep.supported;
359 devi->unsupported= rep.unsupported;
360 status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
367 XkbGetDeviceLedInfo( Display * dpy,
368 XkbDeviceInfoPtr devi,
369 unsigned int ledClass,
373 register xkbGetDeviceInfoReq * req;
374 xkbGetDeviceInfoReply rep;
377 if ((dpy->flags & XlibDisplayNoXkb) ||
378 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
380 if (((which&XkbXI_IndicatorsMask)==0)||(which&(~XkbXI_IndicatorsMask)))
385 GetReq(kbGetDeviceInfo, req);
386 req->reqType = dpy->xkb_info->codes->major_opcode;
387 req->xkbReqType = X_kbGetDeviceInfo;
388 req->deviceSpec = devi->device_spec;
391 req->firstBtn= req->nBtns= 0;
392 req->ledClass= ledClass;
394 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
399 devi->type= rep.devType;
400 devi->supported= rep.supported;
401 devi->unsupported= rep.unsupported;
402 status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
408 /***====================================================================***/
410 typedef struct _LedInfoStuff {
412 XkbDeviceLedInfoPtr devli;
415 typedef struct _SetLedStuff {
419 LedInfoStuff * dflt_kbd_fb;
420 LedInfoStuff * dflt_led_fb;
425 _InitLedStuff(SetLedStuff *stuff,unsigned wanted,XkbDeviceInfoPtr devi)
428 register XkbDeviceLedInfoPtr devli;
430 bzero(stuff,sizeof(SetLedStuff));
431 stuff->wanted= wanted;
432 stuff->dflt_class= XkbXINone;
433 if ((devi->num_leds<1)||((wanted&XkbXI_IndicatorsMask)==0))
435 stuff->info= _XkbTypedCalloc(devi->num_leds,LedInfoStuff);
438 stuff->num_info= devi->num_leds;
439 for (devli=&devi->leds[0],i=0;i<devi->num_leds;i++,devli++) {
440 stuff->info[i].devli= devli;
441 if (devli->led_class==KbdFeedbackClass) {
442 stuff->dflt_class= KbdFeedbackClass;
443 if (stuff->dflt_kbd_fb==NULL)
444 stuff->dflt_kbd_fb= &stuff->info[i];
446 else if (devli->led_class==LedFeedbackClass) {
447 if (stuff->dflt_class==XkbXINone)
448 stuff->dflt_class= LedFeedbackClass;
449 if (stuff->dflt_led_fb==NULL)
450 stuff->dflt_led_fb= &stuff->info[i];
457 _FreeLedStuff(SetLedStuff *stuff)
459 if ((stuff->num_info>0)&&(stuff->info!=NULL))
460 _XkbFree(stuff->info);
461 bzero(stuff,sizeof(SetLedStuff));
466 _XkbSizeLedInfo(unsigned changed,XkbDeviceLedInfoPtr devli)
469 register unsigned bit,namesNeeded,mapsNeeded;
471 size= SIZEOF(xkbDeviceLedsWireDesc);
472 namesNeeded= mapsNeeded= 0;
473 if (changed&XkbXI_IndicatorNamesMask)
474 namesNeeded= devli->names_present;
475 if (changed&XkbXI_IndicatorMapsMask)
476 mapsNeeded= devli->maps_present;
477 if ((namesNeeded)||(mapsNeeded)) {
478 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
480 size+= 4; /* atoms are 4 bytes on the wire */
482 size+= SIZEOF(xkbIndicatorMapWireDesc);
489 _SizeMatches( SetLedStuff * stuff,
490 XkbDeviceLedChangesPtr changes,
494 int i,nMatch,class,id;
495 LedInfoStuff * linfo;
499 class= changes->led_class;
501 if (class==XkbDfltXIClass)
502 class= stuff->dflt_class;
503 for (i=0,linfo=&stuff->info[0];i<stuff->num_info;i++,linfo++) {
504 XkbDeviceLedInfoPtr devli;
508 match= ((class==devli->led_class)||(class==XkbAllXIClasses));
509 if (devli->led_class==KbdFeedbackClass) dflt= stuff->dflt_kbd_fb;
510 else dflt= stuff->dflt_led_fb;
511 match = (match && (id == devli->led_id)) ||
512 (id == XkbAllXIIds) ||
513 ((id == XkbDfltXIId) &&
517 *sz_rtrn+= _XkbSizeLedInfo(stuff->wanted,devli);
520 if ((class!=XkbAllXIClasses)&&(id!=XkbAllXIIds))
530 /***====================================================================***/
534 _XkbSetDeviceInfoSize( XkbDeviceInfoPtr devi,
535 XkbDeviceChangesPtr changes,
541 if ((changes->changed&XkbXI_ButtonActionsMask)&&(changes->num_btns>0)) {
542 if (!XkbXI_LegalDevBtn(devi,(changes->first_btn+changes->num_btns-1)))
544 *sz_rtrn+= changes->num_btns*SIZEOF(xkbActionWireDesc);
547 changes->changed&= ~XkbXI_ButtonActionsMask;
548 changes->first_btn= changes->num_btns= 0;
550 if ((changes->changed&XkbXI_IndicatorsMask)&&
551 XkbLegalXILedClass(changes->leds.led_class)) {
552 XkbDeviceLedChangesPtr leds;
554 for (leds=&changes->leds;leds!=NULL;leds= leds->next) {
555 if (!_SizeMatches(stuff,leds,sz_rtrn,num_leds_rtrn))
560 changes->changed&= ~XkbXI_IndicatorsMask;
567 _XkbWriteLedInfo(char *wire,unsigned changed,XkbDeviceLedInfoPtr devli)
570 register unsigned bit,namesNeeded,mapsNeeded;
571 xkbDeviceLedsWireDesc * lwire;
573 namesNeeded= mapsNeeded= 0;
574 if (changed&XkbXI_IndicatorNamesMask)
575 namesNeeded= devli->names_present;
576 if (changed&XkbXI_IndicatorMapsMask)
577 mapsNeeded= devli->maps_present;
579 lwire= (xkbDeviceLedsWireDesc *)wire;
580 lwire->ledClass= devli->led_class;
581 lwire->ledID= devli->led_id;
582 lwire->namesPresent= namesNeeded;
583 lwire->mapsPresent= mapsNeeded;
584 lwire->physIndicators= devli->phys_indicators;
585 lwire->state= devli->state;
586 wire= (char *)&lwire[1];
589 awire= (CARD32 *)wire;
590 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
591 if (namesNeeded&bit) {
592 *awire= (CARD32)devli->names[i];
599 xkbIndicatorMapWireDesc *mwire;
601 mwire= (xkbIndicatorMapWireDesc *)wire;
602 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
603 if (mapsNeeded&bit) {
604 XkbIndicatorMapPtr map;
605 map= &devli->maps[i];
606 mwire->flags= map->flags;
607 mwire->whichGroups= map->which_groups;
608 mwire->groups= map->groups;
609 mwire->whichMods= map->which_mods;
610 mwire->mods= map->mods.mask;
611 mwire->realMods= map->mods.real_mods;
612 mwire->virtualMods= map->mods.vmods;
613 mwire->ctrls= map->ctrls;
624 _XkbWriteSetDeviceInfo( char * wire,
625 XkbDeviceChangesPtr changes,
627 XkbDeviceInfoPtr devi)
632 if (changes->changed&XkbXI_ButtonActionsMask) {
634 size= changes->num_btns*SIZEOF(xkbActionWireDesc);
635 memcpy(wire,(char *)&devi->btn_acts[changes->first_btn],size);
638 if (changes->changed&XkbXI_IndicatorsMask) {
640 register LedInfoStuff *linfo;
642 for (i=0,linfo=&stuff->info[0];i<stuff->num_info;i++,linfo++) {
644 register char *new_wire;
645 new_wire= _XkbWriteLedInfo(wire,stuff->wanted,linfo->devli);
656 XkbSetDeviceInfo( Display * dpy,
658 XkbDeviceInfoPtr devi)
660 register xkbSetDeviceInfoReq *req;
664 XkbDeviceChangesRec changes;
667 if ((dpy->flags & XlibDisplayNoXkb) ||
668 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
670 if ((!devi) || (which&(~XkbXI_AllDeviceFeaturesMask)) ||
671 ((which&XkbXI_ButtonActionsMask)&&(!XkbXI_DevHasBtnActs(devi)))||
672 ((which&XkbXI_IndicatorsMask)&&(!XkbXI_DevHasLeds(devi))))
675 bzero((char *)&changes,sizeof(XkbDeviceChangesRec));
676 changes.changed= which;
677 changes.first_btn= 0;
678 changes.num_btns= devi->num_btns;
679 changes.leds.led_class= XkbAllXIClasses;
680 changes.leds.led_id= XkbAllXIIds;
681 changes.leds.defined= 0;
683 _InitLedStuff(&lstuff,changes.changed,devi);
684 if (_XkbSetDeviceInfoSize(devi,&changes,&lstuff,&size,&nLeds)!=Success)
687 xkbi = dpy->xkb_info;
688 GetReq(kbSetDeviceInfo, req);
689 req->length+= size/4;
690 req->reqType= xkbi->codes->major_opcode;
691 req->xkbReqType= X_kbSetDeviceInfo;
692 req->deviceSpec= devi->device_spec;
693 req->firstBtn= changes.first_btn;
694 req->nBtns= changes.num_btns;
695 req->change= changes.changed;
696 req->nDeviceLedFBs= nLeds;
699 BufAlloc(char *,wire,size);
701 (_XkbWriteSetDeviceInfo(wire,&changes,&lstuff,devi)==size);
705 _FreeLedStuff(&lstuff);
706 /* 12/11/95 (ef) -- XXX!! should clear changes here */
711 XkbChangeDeviceInfo( Display * dpy,
712 XkbDeviceInfoPtr devi,
713 XkbDeviceChangesPtr changes)
715 register xkbSetDeviceInfoReq *req;
721 if ((dpy->flags & XlibDisplayNoXkb) ||
722 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
724 if ((!devi) || (changes->changed&(~XkbXI_AllDeviceFeaturesMask)) ||
725 ((changes->changed&XkbXI_ButtonActionsMask)&&
726 (!XkbXI_DevHasBtnActs(devi)))||
727 ((changes->changed&XkbXI_IndicatorsMask)&&(!XkbXI_DevHasLeds(devi))))
731 _InitLedStuff(&lstuff,changes->changed,devi);
732 if (_XkbSetDeviceInfoSize(devi,changes,&lstuff,&size,&nLeds)!=Success)
735 xkbi = dpy->xkb_info;
736 GetReq(kbSetDeviceInfo, req);
737 req->length+= size/4;
738 req->reqType= xkbi->codes->major_opcode;
739 req->xkbReqType= X_kbSetDeviceInfo;
740 req->deviceSpec= devi->device_spec;
741 req->firstBtn= changes->first_btn;
742 req->nBtns= changes->num_btns;
743 req->change= changes->changed;
744 req->nDeviceLedFBs= nLeds;
747 BufAlloc(char *,wire,size);
749 (_XkbWriteSetDeviceInfo(wire,changes,&lstuff,devi)==size);
753 _FreeLedStuff(&lstuff);
754 /* 12/11/95 (ef) -- XXX!! should clear changes here */
759 XkbSetDeviceLedInfo( Display * dpy,
760 XkbDeviceInfoPtr devi,
769 XkbSetDeviceButtonActions( Display * dpy,
770 XkbDeviceInfoPtr devi,
774 register xkbSetDeviceInfoReq *req;
778 XkbDeviceChangesRec changes;
781 if ((dpy->flags & XlibDisplayNoXkb) ||
782 (!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
784 if ((!devi)||(!XkbXI_DevHasBtnActs(devi))||(first+nBtns>devi->num_btns))
789 bzero((char *)&changes,sizeof(XkbDeviceChangesRec));
790 changes.changed= XkbXI_ButtonActionsMask;
791 changes.first_btn= first;
792 changes.num_btns= nBtns;
793 changes.leds.led_class= XkbXINone;
794 changes.leds.led_id= XkbXINone;
795 changes.leds.defined= 0;
797 if (_XkbSetDeviceInfoSize(devi,&changes,NULL,&size,&nLeds)!=Success)
800 xkbi = dpy->xkb_info;
801 GetReq(kbSetDeviceInfo, req);
802 req->length+= size/4;
803 req->reqType= xkbi->codes->major_opcode;
804 req->xkbReqType= X_kbSetDeviceInfo;
805 req->deviceSpec= devi->device_spec;
806 req->firstBtn= changes.first_btn;
807 req->nBtns= changes.num_btns;
808 req->change= changes.changed;
809 req->nDeviceLedFBs= nLeds;
812 BufAlloc(char *,wire,size);
814 (_XkbWriteSetDeviceInfo(wire,&changes,&lstuff,devi)==size);