#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#define NEED_REPLIES
#define NEED_EVENTS
#define NEED_MAP_READERS
#include "Xlibint.h"
#include <X11/extensions/XKBproto.h>
#include "XKBlibint.h"
#include <X11/extensions/XI.h>
extern void
XkbNoteDeviceChanges( XkbDeviceChangesPtr old,
XkbExtensionDeviceNotifyEvent * new,
unsigned int wanted)
{
if ((!old)||(!new)||(!wanted)||((new->reason&wanted)==0))
return;
if ((wanted&new->reason)&XkbXI_ButtonActionsMask) {
if (old->changed&XkbXI_ButtonActionsMask) {
int first,last,newLast;
if (new->first_btn<old->first_btn)
first= new->first_btn;
else first= old->first_btn;
last= old->first_btn+old->num_btns-1;
newLast= new->first_btn+new->num_btns-1;
if (newLast>last)
last= newLast;
old->first_btn= first;
old->num_btns= (last-first)+1;
}
else {
old->changed|= XkbXI_ButtonActionsMask;
old->first_btn= new->first_btn;
old->num_btns= new->num_btns;
}
}
if ((wanted&new->reason)&XkbXI_IndicatorsMask) {
XkbDeviceLedChangesPtr this;
if (old->changed&XkbXI_IndicatorsMask) {
XkbDeviceLedChangesPtr found;
found= NULL;
for (this= &old->leds;this&&(!found);this=this->next) {
if ((this->led_class==new->led_class)&&
(this->led_id==new->led_id)) {
found= this;
}
}
if (!found) {
found= _XkbTypedCalloc(1,XkbDeviceLedChangesRec);
if (!found)
return;
found->next= old->leds.next;
found->led_class= new->led_class;
found->led_id= new->led_id;
old->leds.next= found;
}
if ((wanted&new->reason)&XkbXI_IndicatorNamesMask)
found->defined= new->leds_defined;
}
else {
old->changed|= ((wanted&new->reason)&XkbXI_IndicatorsMask);
old->leds.led_class= new->led_class;
old->leds.led_id= new->led_id;
old->leds.defined= new->leds_defined;
if (old->leds.next) {
XkbDeviceLedChangesPtr next;
for (this=old->leds.next;this;this=next) {
next= this->next;
_XkbFree(this);
}
old->leds.next= NULL;
}
}
}
return;
}
static Status
_XkbReadDeviceLedInfo( XkbReadBufferPtr buf,
unsigned present,
XkbDeviceInfoPtr devi)
{
register unsigned i,bit;
XkbDeviceLedInfoPtr devli;
xkbDeviceLedsWireDesc * wireli;
wireli= _XkbGetTypedRdBufPtr(buf,1,xkbDeviceLedsWireDesc);
if (!wireli)
return BadLength;
devli= XkbAddDeviceLedInfo(devi,wireli->ledClass,wireli->ledID);
if (!devli)
return BadAlloc;
devli->phys_indicators= wireli->physIndicators;
if (present&XkbXI_IndicatorStateMask)
devli->state= wireli->state;
if (present&XkbXI_IndicatorNamesMask) {
devli->names_present= wireli->namesPresent;
if (devli->names_present) {
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (wireli->namesPresent&bit) {
if (!_XkbCopyFromReadBuffer(buf,(char *)&devli->names[i],4))
return BadLength;
}
}
}
}
if (present&XkbXI_IndicatorMapsMask) {
devli->maps_present= wireli->mapsPresent;
if (devli->maps_present) {
XkbIndicatorMapPtr im;
xkbIndicatorMapWireDesc * wireim;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (wireli->mapsPresent&bit) {
wireim= _XkbGetTypedRdBufPtr(buf,1,xkbIndicatorMapWireDesc);
if (!wireim)
return BadAlloc;
im= &devli->maps[i];
im->flags= wireim->flags;
im->which_groups= wireim->whichGroups;
im->groups= wireim->groups;
im->which_mods= wireim->whichMods;
im->mods.mask= wireim->mods;
im->mods.real_mods= wireim->realMods;
im->mods.vmods= wireim->virtualMods;
im->ctrls= wireim->ctrls;
}
}
}
}
return Success;
}
static Status
_XkbReadGetDeviceInfoReply( Display * dpy,
xkbGetDeviceInfoReply * rep,
XkbDeviceInfoPtr devi)
{
XkbReadBufferRec buf;
XkbAction * act;
int tmp;
if (!_XkbInitReadBuffer(dpy,&buf,(int)rep->length*4))
return BadAlloc;
if ((rep->totalBtns>0)&&(rep->totalBtns!=devi->num_btns)) {
tmp= XkbResizeDeviceButtonActions(devi,rep->totalBtns);
if (tmp!=Success)
return tmp;
}
if (rep->nBtnsWanted>0) {
act= &devi->btn_acts[rep->firstBtnWanted];
bzero((char *)act,(rep->nBtnsWanted*sizeof(XkbAction)));
}
if (devi->name!=NULL)
_XkbFree(devi->name);
if (!_XkbGetReadBufferCountedString(&buf,&devi->name))
goto BAILOUT;
if (rep->nBtnsRtrn>0) {
int size;
act= &devi->btn_acts[rep->firstBtnRtrn];
size= rep->nBtnsRtrn*SIZEOF(xkbActionWireDesc);
if (!_XkbCopyFromReadBuffer(&buf,(char *)act,size))
goto BAILOUT;
}
if (rep->nDeviceLedFBs>0) {
register int i;
for (i=0;i<rep->nDeviceLedFBs;i++) {
if ((tmp= _XkbReadDeviceLedInfo(&buf,rep->present,devi))!=Success)
return tmp;
}
}
tmp= _XkbFreeReadBuffer(&buf);
if (tmp)
fprintf(stderr,"GetDeviceInfo! Bad length (%d extra bytes)\n",tmp);
if (tmp || buf.error)
return BadLength;
return Success;
BAILOUT:
_XkbFreeReadBuffer(&buf);
return BadLength;
}
XkbDeviceInfoPtr
XkbGetDeviceInfo( Display * dpy,
unsigned which,
unsigned deviceSpec,
unsigned class,
unsigned id)
{
register xkbGetDeviceInfoReq * req;
xkbGetDeviceInfoReply rep;
Status status;
XkbDeviceInfoPtr devi;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return NULL;
LockDisplay(dpy);
GetReq(kbGetDeviceInfo, req);
req->reqType = dpy->xkb_info->codes->major_opcode;
req->xkbReqType = X_kbGetDeviceInfo;
req->deviceSpec = deviceSpec;
req->wanted= which;
req->allBtns= ((which&XkbXI_ButtonActionsMask)!=0);
req->firstBtn= req->nBtns= 0;
req->ledClass= class;
req->ledID= id;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return NULL;
}
devi= XkbAllocDeviceInfo(rep.deviceID,rep.totalBtns,rep.nDeviceLedFBs);
if (devi) {
devi->supported= rep.supported;
devi->unsupported= rep.unsupported;
devi->type= rep.devType;
devi->has_own_state= rep.hasOwnState;
devi->dflt_kbd_fb = rep.dfltKbdFB;
devi->dflt_led_fb = rep.dfltLedFB;
status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
if (status!=Success) {
XkbFreeDeviceInfo(devi,XkbXI_AllDeviceFeaturesMask,True);
devi= NULL;
}
}
UnlockDisplay(dpy);
SyncHandle();
return devi;
}
Status
XkbGetDeviceInfoChanges( Display * dpy,
XkbDeviceInfoPtr devi,
XkbDeviceChangesPtr changes)
{
register xkbGetDeviceInfoReq * req;
xkbGetDeviceInfoReply rep;
Status status;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return BadMatch;
if ((changes->changed&XkbXI_AllDeviceFeaturesMask)==0)
return Success;
changes->changed&= ~XkbXI_AllDeviceFeaturesMask;
status= Success;
LockDisplay(dpy);
while ((changes->changed)&&(status==Success)) {
GetReq(kbGetDeviceInfo, req);
req->reqType = dpy->xkb_info->codes->major_opcode;
req->xkbReqType = X_kbGetDeviceInfo;
req->deviceSpec = devi->device_spec;
req->wanted= changes->changed;
req->allBtns= False;
if (changes->changed&XkbXI_ButtonActionsMask) {
req->firstBtn= changes->first_btn;
req->nBtns= changes->num_btns;
changes->changed&= ~XkbXI_ButtonActionsMask;
}
else req->firstBtn= req->nBtns= 0;
if (changes->changed&XkbXI_IndicatorsMask) {
req->ledClass= changes->leds.led_class;
req->ledID= changes->leds.led_id;
if (changes->leds.next==NULL)
changes->changed&= ~XkbXI_IndicatorsMask;
else {
XkbDeviceLedChangesPtr next;
next= changes->leds.next;
changes->leds= *next;
_XkbFree(next);
}
}
else {
req->ledClass= XkbDfltXIClass;
req->ledID= XkbDfltXIId;
}
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
status= BadLength;
break;
}
devi->supported|= rep.supported;
devi->unsupported|= rep.unsupported;
devi->type= rep.devType;
status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
}
UnlockDisplay(dpy);
SyncHandle();
return status;
}
Status
XkbGetDeviceButtonActions( Display * dpy,
XkbDeviceInfoPtr devi,
Bool all,
unsigned int first,
unsigned int num)
{
register xkbGetDeviceInfoReq * req;
xkbGetDeviceInfoReply rep;
Status status;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return BadMatch;
if (!devi)
return BadValue;
LockDisplay(dpy);
GetReq(kbGetDeviceInfo, req);
req->reqType = dpy->xkb_info->codes->major_opcode;
req->xkbReqType = X_kbGetDeviceInfo;
req->deviceSpec = devi->device_spec;
req->wanted= XkbXI_ButtonActionsMask;
req->allBtns= all;
req->firstBtn= first;
req->nBtns= num;
req->ledClass= XkbDfltXIClass;
req->ledID= XkbDfltXIId;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return BadLength;
}
devi->type= rep.devType;
devi->supported= rep.supported;
devi->unsupported= rep.unsupported;
status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
UnlockDisplay(dpy);
SyncHandle();
return status;
}
Status
XkbGetDeviceLedInfo( Display * dpy,
XkbDeviceInfoPtr devi,
unsigned int ledClass,
unsigned int ledId,
unsigned int which)
{
register xkbGetDeviceInfoReq * req;
xkbGetDeviceInfoReply rep;
Status status;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return BadMatch;
if (((which&XkbXI_IndicatorsMask)==0)||(which&(~XkbXI_IndicatorsMask)))
return BadMatch;
if (!devi)
return BadValue;
LockDisplay(dpy);
GetReq(kbGetDeviceInfo, req);
req->reqType = dpy->xkb_info->codes->major_opcode;
req->xkbReqType = X_kbGetDeviceInfo;
req->deviceSpec = devi->device_spec;
req->wanted= which;
req->allBtns= False;
req->firstBtn= req->nBtns= 0;
req->ledClass= ledClass;
req->ledID= ledId;
if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
UnlockDisplay(dpy);
SyncHandle();
return BadLength;
}
devi->type= rep.devType;
devi->supported= rep.supported;
devi->unsupported= rep.unsupported;
status= _XkbReadGetDeviceInfoReply(dpy,&rep,devi);
UnlockDisplay(dpy);
SyncHandle();
return status;
}
typedef struct _LedInfoStuff {
Bool used;
XkbDeviceLedInfoPtr devli;
} LedInfoStuff;
typedef struct _SetLedStuff {
unsigned wanted;
int num_info;
int dflt_class;
LedInfoStuff * dflt_kbd_fb;
LedInfoStuff * dflt_led_fb;
LedInfoStuff * info;
} SetLedStuff;
static void
_InitLedStuff(SetLedStuff *stuff,unsigned wanted,XkbDeviceInfoPtr devi)
{
int i;
register XkbDeviceLedInfoPtr devli;
bzero(stuff,sizeof(SetLedStuff));
stuff->wanted= wanted;
stuff->dflt_class= XkbXINone;
if ((devi->num_leds<1)||((wanted&XkbXI_IndicatorsMask)==0))
return;
stuff->info= _XkbTypedCalloc(devi->num_leds,LedInfoStuff);
if (!stuff->info)
return;
stuff->num_info= devi->num_leds;
for (devli=&devi->leds[0],i=0;i<devi->num_leds;i++,devli++) {
stuff->info[i].devli= devli;
if (devli->led_class==KbdFeedbackClass) {
stuff->dflt_class= KbdFeedbackClass;
if (stuff->dflt_kbd_fb==NULL)
stuff->dflt_kbd_fb= &stuff->info[i];
}
else if (devli->led_class==LedFeedbackClass) {
if (stuff->dflt_class==XkbXINone)
stuff->dflt_class= LedFeedbackClass;
if (stuff->dflt_led_fb==NULL)
stuff->dflt_led_fb= &stuff->info[i];
}
}
return;
}
static void
_FreeLedStuff(SetLedStuff *stuff)
{
if ((stuff->num_info>0)&&(stuff->info!=NULL))
_XkbFree(stuff->info);
bzero(stuff,sizeof(SetLedStuff));
return;
}
static int
_XkbSizeLedInfo(unsigned changed,XkbDeviceLedInfoPtr devli)
{
register int i,size;
register unsigned bit,namesNeeded,mapsNeeded;
size= SIZEOF(xkbDeviceLedsWireDesc);
namesNeeded= mapsNeeded= 0;
if (changed&XkbXI_IndicatorNamesMask)
namesNeeded= devli->names_present;
if (changed&XkbXI_IndicatorMapsMask)
mapsNeeded= devli->maps_present;
if ((namesNeeded)||(mapsNeeded)) {
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (namesNeeded&bit)
size+= 4;
if (mapsNeeded&bit)
size+= SIZEOF(xkbIndicatorMapWireDesc);
}
}
return size;
}
static Bool
_SizeMatches( SetLedStuff * stuff,
XkbDeviceLedChangesPtr changes,
int * sz_rtrn,
int * nleds_rtrn)
{
int i,nMatch,class,id;
LedInfoStuff * linfo;
Bool match;
nMatch= 0;
class= changes->led_class;
id= changes->led_id;
if (class==XkbDfltXIClass)
class= stuff->dflt_class;
for (i=0,linfo=&stuff->info[0];i<stuff->num_info;i++,linfo++) {
XkbDeviceLedInfoPtr devli;
LedInfoStuff * dflt;
devli= linfo->devli;
match= ((class==devli->led_class)||(class==XkbAllXIClasses));
if (devli->led_class==KbdFeedbackClass) dflt= stuff->dflt_kbd_fb;
else dflt= stuff->dflt_led_fb;
match = (match && (id == devli->led_id)) ||
(id == XkbAllXIIds) ||
((id == XkbDfltXIId) &&
(linfo == dflt));
if (match) {
if (!linfo->used) {
*sz_rtrn+= _XkbSizeLedInfo(stuff->wanted,devli);
*nleds_rtrn+= 1;
linfo->used= True;
if ((class!=XkbAllXIClasses)&&(id!=XkbAllXIIds))
return True;
}
nMatch++;
linfo->used= True;
}
}
return (nMatch>0);
}
static Status
_XkbSetDeviceInfoSize( XkbDeviceInfoPtr devi,
XkbDeviceChangesPtr changes,
SetLedStuff * stuff,
int * sz_rtrn,
int * num_leds_rtrn)
{
*sz_rtrn= 0;
if ((changes->changed&XkbXI_ButtonActionsMask)&&(changes->num_btns>0)) {
if (!XkbXI_LegalDevBtn(devi,(changes->first_btn+changes->num_btns-1)))
return BadMatch;
*sz_rtrn+= changes->num_btns*SIZEOF(xkbActionWireDesc);
}
else {
changes->changed&= ~XkbXI_ButtonActionsMask;
changes->first_btn= changes->num_btns= 0;
}
if ((changes->changed&XkbXI_IndicatorsMask)&&
XkbLegalXILedClass(changes->leds.led_class)) {
XkbDeviceLedChangesPtr leds;
for (leds=&changes->leds;leds!=NULL;leds= leds->next) {
if (!_SizeMatches(stuff,leds,sz_rtrn,num_leds_rtrn))
return BadMatch;
}
}
else {
changes->changed&= ~XkbXI_IndicatorsMask;
*num_leds_rtrn= 0;
}
return Success;
}
static char *
_XkbWriteLedInfo(char *wire,unsigned changed,XkbDeviceLedInfoPtr devli)
{
register int i;
register unsigned bit,namesNeeded,mapsNeeded;
xkbDeviceLedsWireDesc * lwire;
namesNeeded= mapsNeeded= 0;
if (changed&XkbXI_IndicatorNamesMask)
namesNeeded= devli->names_present;
if (changed&XkbXI_IndicatorMapsMask)
mapsNeeded= devli->maps_present;
lwire= (xkbDeviceLedsWireDesc *)wire;
lwire->ledClass= devli->led_class;
lwire->ledID= devli->led_id;
lwire->namesPresent= namesNeeded;
lwire->mapsPresent= mapsNeeded;
lwire->physIndicators= devli->phys_indicators;
lwire->state= devli->state;
wire= (char *)&lwire[1];
if (namesNeeded) {
CARD32 *awire;
awire= (CARD32 *)wire;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (namesNeeded&bit) {
*awire= (CARD32)devli->names[i];
awire++;
}
}
wire= (char *)awire;
}
if (mapsNeeded) {
xkbIndicatorMapWireDesc *mwire;
mwire= (xkbIndicatorMapWireDesc *)wire;
for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
if (mapsNeeded&bit) {
XkbIndicatorMapPtr map;
map= &devli->maps[i];
mwire->flags= map->flags;
mwire->whichGroups= map->which_groups;
mwire->groups= map->groups;
mwire->whichMods= map->which_mods;
mwire->mods= map->mods.mask;
mwire->realMods= map->mods.real_mods;
mwire->virtualMods= map->mods.vmods;
mwire->ctrls= map->ctrls;
mwire++;
}
}
wire= (char *)mwire;
}
return wire;
}
static int
_XkbWriteSetDeviceInfo( char * wire,
XkbDeviceChangesPtr changes,
SetLedStuff * stuff,
XkbDeviceInfoPtr devi)
{
char *start;
start= wire;
if (changes->changed&XkbXI_ButtonActionsMask) {
int size;
size= changes->num_btns*SIZEOF(xkbActionWireDesc);
memcpy(wire,(char *)&devi->btn_acts[changes->first_btn],size);
wire+= size;
}
if (changes->changed&XkbXI_IndicatorsMask) {
register int i;
register LedInfoStuff *linfo;
for (i=0,linfo=&stuff->info[0];i<stuff->num_info;i++,linfo++) {
if (linfo->used) {
register char *new_wire;
new_wire= _XkbWriteLedInfo(wire,stuff->wanted,linfo->devli);
if (!new_wire)
return wire-start;
wire= new_wire;
}
}
}
return wire-start;
}
Bool
XkbSetDeviceInfo( Display * dpy,
unsigned which,
XkbDeviceInfoPtr devi)
{
register xkbSetDeviceInfoReq *req;
Status ok = 0;
int size,nLeds;
XkbInfoPtr xkbi;
XkbDeviceChangesRec changes;
SetLedStuff lstuff;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return False;
if ((!devi) || (which&(~XkbXI_AllDeviceFeaturesMask)) ||
((which&XkbXI_ButtonActionsMask)&&(!XkbXI_DevHasBtnActs(devi)))||
((which&XkbXI_IndicatorsMask)&&(!XkbXI_DevHasLeds(devi))))
return False;
bzero((char *)&changes,sizeof(XkbDeviceChangesRec));
changes.changed= which;
changes.first_btn= 0;
changes.num_btns= devi->num_btns;
changes.leds.led_class= XkbAllXIClasses;
changes.leds.led_id= XkbAllXIIds;
changes.leds.defined= 0;
size= nLeds= 0;
_InitLedStuff(&lstuff,changes.changed,devi);
if (_XkbSetDeviceInfoSize(devi,&changes,&lstuff,&size,&nLeds)!=Success)
return False;
LockDisplay(dpy);
xkbi = dpy->xkb_info;
GetReq(kbSetDeviceInfo, req);
req->length+= size/4;
req->reqType= xkbi->codes->major_opcode;
req->xkbReqType= X_kbSetDeviceInfo;
req->deviceSpec= devi->device_spec;
req->firstBtn= changes.first_btn;
req->nBtns= changes.num_btns;
req->change= changes.changed;
req->nDeviceLedFBs= nLeds;
if (size>0) {
char * wire;
BufAlloc(char *,wire,size);
ok= (wire!=NULL)&&
(_XkbWriteSetDeviceInfo(wire,&changes,&lstuff,devi)==size);
}
UnlockDisplay(dpy);
SyncHandle();
_FreeLedStuff(&lstuff);
return ok;
}
Bool
XkbChangeDeviceInfo( Display * dpy,
XkbDeviceInfoPtr devi,
XkbDeviceChangesPtr changes)
{
register xkbSetDeviceInfoReq *req;
Status ok = 0;
int size,nLeds;
XkbInfoPtr xkbi;
SetLedStuff lstuff;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return False;
if ((!devi) || (changes->changed&(~XkbXI_AllDeviceFeaturesMask)) ||
((changes->changed&XkbXI_ButtonActionsMask)&&
(!XkbXI_DevHasBtnActs(devi)))||
((changes->changed&XkbXI_IndicatorsMask)&&(!XkbXI_DevHasLeds(devi))))
return False;
size= nLeds= 0;
_InitLedStuff(&lstuff,changes->changed,devi);
if (_XkbSetDeviceInfoSize(devi,changes,&lstuff,&size,&nLeds)!=Success)
return False;
LockDisplay(dpy);
xkbi = dpy->xkb_info;
GetReq(kbSetDeviceInfo, req);
req->length+= size/4;
req->reqType= xkbi->codes->major_opcode;
req->xkbReqType= X_kbSetDeviceInfo;
req->deviceSpec= devi->device_spec;
req->firstBtn= changes->first_btn;
req->nBtns= changes->num_btns;
req->change= changes->changed;
req->nDeviceLedFBs= nLeds;
if (size>0) {
char * wire;
BufAlloc(char *,wire,size);
ok= (wire!=NULL)&&
(_XkbWriteSetDeviceInfo(wire,changes,&lstuff,devi)==size);
}
UnlockDisplay(dpy);
SyncHandle();
_FreeLedStuff(&lstuff);
return ok;
}
Bool
XkbSetDeviceLedInfo( Display * dpy,
XkbDeviceInfoPtr devi,
unsigned ledClass,
unsigned ledID,
unsigned which)
{
return False;
}
Bool
XkbSetDeviceButtonActions( Display * dpy,
XkbDeviceInfoPtr devi,
unsigned int first,
unsigned int nBtns)
{
register xkbSetDeviceInfoReq *req;
Status ok = 0;
int size,nLeds;
XkbInfoPtr xkbi;
XkbDeviceChangesRec changes;
SetLedStuff lstuff;
if ((dpy->flags & XlibDisplayNoXkb) ||
(!dpy->xkb_info && !XkbUseExtension(dpy,NULL,NULL)))
return False;
if ((!devi)||(!XkbXI_DevHasBtnActs(devi))||(first+nBtns>devi->num_btns))
return False;
if (nBtns==0)
return True;
bzero((char *)&changes,sizeof(XkbDeviceChangesRec));
changes.changed= XkbXI_ButtonActionsMask;
changes.first_btn= first;
changes.num_btns= nBtns;
changes.leds.led_class= XkbXINone;
changes.leds.led_id= XkbXINone;
changes.leds.defined= 0;
size= nLeds= 0;
if (_XkbSetDeviceInfoSize(devi,&changes,NULL,&size,&nLeds)!=Success)
return False;
LockDisplay(dpy);
xkbi = dpy->xkb_info;
GetReq(kbSetDeviceInfo, req);
req->length+= size/4;
req->reqType= xkbi->codes->major_opcode;
req->xkbReqType= X_kbSetDeviceInfo;
req->deviceSpec= devi->device_spec;
req->firstBtn= changes.first_btn;
req->nBtns= changes.num_btns;
req->change= changes.changed;
req->nDeviceLedFBs= nLeds;
if (size>0) {
char * wire;
BufAlloc(char *,wire,size);
ok= (wire!=NULL)&&
(_XkbWriteSetDeviceInfo(wire,&changes,&lstuff,devi)==size);
}
UnlockDisplay(dpy);
SyncHandle();
return ok;
}