xkbLEDs.c revision 05b261ec
1/************************************************************ 2Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31#include <stdio.h> 32#include <ctype.h> 33#include <math.h> 34#define NEED_EVENTS 1 35#include <X11/X.h> 36#include <X11/Xproto.h> 37#include "misc.h" 38#include "inputstr.h" 39 40#include <X11/extensions/XI.h> 41#include <xkbsrv.h> 42#include "xkb.h" 43 44/***====================================================================***/ 45 46 /* 47 * unsigned 48 * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn) 49 * 50 * Given a keyboard and a set of state components that have changed, 51 * this function returns the indicators on the default keyboard 52 * feedback that might be affected. It also reports whether or not 53 * any extension devices might be affected in check_devs_rtrn. 54 */ 55 56unsigned 57XkbIndicatorsToUpdate( DeviceIntPtr dev, 58 unsigned long state_changes, 59 Bool enable_changes) 60{ 61register unsigned update= 0; 62XkbSrvLedInfoPtr sli; 63 64 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 65 66 if (!sli) 67 return update; 68 69 if (state_changes&(XkbModifierStateMask|XkbGroupStateMask)) 70 update|= sli->usesEffective; 71 if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask)) 72 update|= sli->usesBase; 73 if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask)) 74 update|= sli->usesLatched; 75 if (state_changes&(XkbModifierLockMask|XkbGroupLockMask)) 76 update|= sli->usesLocked; 77 if (state_changes&XkbCompatStateMask) 78 update|= sli->usesCompat; 79 if (enable_changes) 80 update|= sli->usesControls; 81 return update; 82} 83 84/***====================================================================***/ 85 86 /* 87 * Bool 88 *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) 89 * 90 * Some indicators "drive" the keyboard when their state is explicitly 91 * changed, as described in section 9.2.1 of the XKB protocol spec. 92 * This function updates the state and controls for the keyboard 93 * specified by 'xkbi' to reflect any changes that are required 94 * when the indicator described by 'map' is turned on or off. The 95 * extent of the changes is reported in change, which must be defined. 96 */ 97static Bool 98XkbApplyLEDChangeToKeyboard( XkbSrvInfoPtr xkbi, 99 XkbIndicatorMapPtr map, 100 Bool on, 101 XkbChangesPtr change) 102{ 103Bool ctrlChange,stateChange; 104XkbStatePtr state; 105 106 if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0)) 107 return False; 108 ctrlChange= stateChange= False; 109 if (map->ctrls) { 110 XkbControlsPtr ctrls= xkbi->desc->ctrls; 111 unsigned old; 112 113 old= ctrls->enabled_ctrls; 114 if (on) ctrls->enabled_ctrls|= map->ctrls; 115 else ctrls->enabled_ctrls&= ~map->ctrls; 116 if (old!=ctrls->enabled_ctrls) { 117 change->ctrls.changed_ctrls= XkbControlsEnabledMask; 118 change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls; 119 ctrlChange= True; 120 } 121 } 122 state= &xkbi->state; 123 if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) { 124 register int i; 125 register unsigned bit,match; 126 127 if (on) match= (map->groups)&XkbAllGroupsMask; 128 else match= (~map->groups)&XkbAllGroupsMask; 129 if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) { 130 for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { 131 if (bit&match) 132 break; 133 } 134 if (map->which_groups&XkbIM_UseLatched) 135 XkbLatchGroup(xkbi->device,0); /* unlatch group */ 136 state->locked_group= i; 137 stateChange= True; 138 } 139 else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) { 140 for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { 141 if (bit&match) 142 break; 143 } 144 state->locked_group= 0; 145 XkbLatchGroup(xkbi->device,i); 146 stateChange= True; 147 } 148 } 149 if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) { 150 if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) { 151 register unsigned long old; 152 old= state->locked_mods; 153 if (on) state->locked_mods|= map->mods.mask; 154 else state->locked_mods&= ~map->mods.mask; 155 if (state->locked_mods!=old) 156 stateChange= True; 157 } 158 if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) { 159 register unsigned long newmods; 160 newmods= state->latched_mods; 161 if (on) newmods|= map->mods.mask; 162 else newmods&= ~map->mods.mask; 163 if (newmods!=state->locked_mods) { 164 newmods&= map->mods.mask; 165 XkbLatchModifiers(xkbi->device,map->mods.mask,newmods); 166 stateChange= True; 167 } 168 } 169 } 170 return (stateChange || ctrlChange); 171} 172 173 /* 174 * Bool 175 * ComputeAutoState(map,state,ctrls) 176 * 177 * This function reports the effect of applying the specified 178 * indicator map given the specified state and controls, as 179 * described in section 9.2 of the XKB protocol specification. 180 */ 181 182static Bool 183ComputeAutoState( XkbIndicatorMapPtr map, 184 XkbStatePtr state, 185 XkbControlsPtr ctrls) 186{ 187Bool on; 188CARD8 mods,group; 189 190 on= False; 191 mods= group= 0; 192 if (map->which_mods&XkbIM_UseAnyMods) { 193 if (map->which_mods&XkbIM_UseBase) 194 mods|= state->base_mods; 195 if (map->which_mods&XkbIM_UseLatched) 196 mods|= state->latched_mods; 197 if (map->which_mods&XkbIM_UseLocked) 198 mods|= state->locked_mods; 199 if (map->which_mods&XkbIM_UseEffective) 200 mods|= state->mods; 201 if (map->which_mods&XkbIM_UseCompat) 202 mods|= state->compat_state; 203 on = ((map->mods.mask&mods)!=0); 204 on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0)); 205 } 206 if (map->which_groups&XkbIM_UseAnyGroup) { 207 if (map->which_groups&XkbIM_UseBase) 208 group|= (1L << state->base_group); 209 if (map->which_groups&XkbIM_UseLatched) 210 group|= (1L << state->latched_group); 211 if (map->which_groups&XkbIM_UseLocked) 212 group|= (1L << state->locked_group); 213 if (map->which_groups&XkbIM_UseEffective) 214 group|= (1L << state->group); 215 on = on||(((map->groups&group)!=0)||(map->groups==0)); 216 } 217 if (map->ctrls) 218 on = on||(ctrls->enabled_ctrls&map->ctrls); 219 return on; 220} 221 222 223static void 224XkbUpdateLedAutoState( DeviceIntPtr dev, 225 XkbSrvLedInfoPtr sli, 226 unsigned maps_to_check, 227 xkbExtensionDeviceNotify * ed, 228 XkbChangesPtr changes, 229 XkbEventCausePtr cause) 230{ 231DeviceIntPtr kbd; 232XkbStatePtr state; 233XkbControlsPtr ctrls; 234XkbChangesRec my_changes; 235xkbExtensionDeviceNotify my_ed; 236register unsigned i,bit,affected; 237register XkbIndicatorMapPtr map; 238unsigned oldState; 239 240 if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0)) 241 return; 242 243 if (dev->key && dev->key->xkbInfo) 244 kbd= dev; 245 else kbd= (DeviceIntPtr)LookupKeyboardDevice(); 246 247 state= &kbd->key->xkbInfo->state; 248 ctrls= kbd->key->xkbInfo->desc->ctrls; 249 affected= maps_to_check; 250 oldState= sli->effectiveState; 251 sli->autoState&= ~affected; 252 for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { 253 if ((affected&bit)==0) 254 continue; 255 affected&= ~bit; 256 map= &sli->maps[i]; 257 if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls)) 258 sli->autoState|= bit; 259 } 260 sli->effectiveState= (sli->autoState|sli->explicitState); 261 affected= sli->effectiveState^oldState; 262 if (affected==0) 263 return; 264 265 if (ed==NULL) { 266 ed= &my_ed; 267 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); 268 } 269 else if ((ed->reason&XkbXI_IndicatorsMask)&& 270 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 271 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 272 } 273 274 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 275 if (changes==NULL) { 276 changes= &my_changes; 277 bzero((char *)changes,sizeof(XkbChangesRec)); 278 } 279 changes->indicators.state_changes|= affected; 280 } 281 282 ed->reason|= XkbXI_IndicatorStateMask; 283 ed->ledClass= sli->class; 284 ed->ledID= sli->id; 285 ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 286 ed->ledState= sli->effectiveState; 287 ed->unsupported|= XkbXI_IndicatorStateMask; 288 ed->supported= XkbXI_AllFeaturesMask; 289 290 if (changes!=&my_changes) changes= NULL; 291 if (ed!=&my_ed) ed= NULL; 292 if (changes || ed) 293 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 294 return; 295} 296 297static void 298XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause) 299{ 300DeviceIntPtr edev; 301XkbSrvLedInfoPtr sli; 302 303 for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { 304 if (edev->kbdfeed) { 305 KbdFeedbackPtr kf; 306 for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) { 307 if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) 308 continue; 309 sli= kf->xkb_sli; 310 XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, 311 changes,cause); 312 313 } 314 } 315 if (edev->leds) { 316 LedFeedbackPtr lf; 317 for (lf=edev->leds;lf!=NULL;lf=lf->next) { 318 if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) 319 continue; 320 sli= lf->xkb_sli; 321 XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, 322 changes,cause); 323 324 } 325 } 326 } 327 return; 328} 329 330 331/***====================================================================***/ 332 333 /* 334 * void 335 * XkbSetIndicators(dev,affect,values,cause) 336 * 337 * Attempts to change the indicators specified in 'affect' to the 338 * states specified in 'values' for the default keyboard feedback 339 * on the keyboard specified by 'dev.' Attempts to change indicator 340 * state might be ignored or have no affect, depending on the XKB 341 * indicator map for any affected indicators, as described in section 342 * 9.2 of the XKB protocol specification. 343 * 344 * If 'changes' is non-NULL, this function notes any changes to the 345 * keyboard state, controls, or indicator state that result from this 346 * attempted change. If 'changes' is NULL, this function generates 347 * XKB events to report any such changes to interested clients. 348 * 349 * If 'cause' is non-NULL, it specifies the reason for the change, 350 * as reported in some XKB events. If it is NULL, this function 351 * assumes that the change is the result of a core protocol 352 * ChangeKeyboardMapping request. 353 */ 354 355void 356XkbSetIndicators( DeviceIntPtr dev, 357 CARD32 affect, 358 CARD32 values, 359 XkbEventCausePtr cause) 360{ 361XkbSrvLedInfoPtr sli; 362XkbChangesRec changes; 363xkbExtensionDeviceNotify ed; 364unsigned side_affected; 365 366 bzero((char *)&changes,sizeof(XkbChangesRec)); 367 bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify)); 368 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 369 sli->explicitState&= ~affect; 370 sli->explicitState|= (affect&values); 371 XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause); 372 373 side_affected= 0; 374 if (changes.state_changes!=0) 375 side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False); 376 if (changes.ctrls.enabled_ctrls_changes) 377 side_affected|= sli->usesControls; 378 379 if (side_affected) { 380 XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause); 381 affect|= side_affected; 382 } 383 if (changes.state_changes || changes.ctrls.enabled_ctrls_changes) 384 XkbUpdateAllDeviceIndicators(NULL,cause); 385 386 XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause); 387 return; 388} 389 390/***====================================================================***/ 391 392/***====================================================================***/ 393 394 /* 395 * void 396 * XkbUpdateIndicators(dev,update,check_edevs,changes,cause) 397 * 398 * Applies the indicator maps for any indicators specified in 399 * 'update' from the default keyboard feedback on the device 400 * specified by 'dev.' 401 * 402 * If 'changes' is NULL, this function generates and XKB events 403 * required to report the necessary changes, otherwise it simply 404 * notes the indicators with changed state. 405 * 406 * If 'check_edevs' is True, this function also checks the indicator 407 * maps for any open extension devices that have them, and updates 408 * the state of any extension device indicators as necessary. 409 */ 410 411void 412XkbUpdateIndicators( DeviceIntPtr dev, 413 register CARD32 update, 414 Bool check_edevs, 415 XkbChangesPtr changes, 416 XkbEventCausePtr cause) 417{ 418XkbSrvLedInfoPtr sli; 419 420 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 421 XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause); 422 if (check_edevs) 423 XkbUpdateAllDeviceIndicators(changes,cause); 424 return; 425} 426 427/***====================================================================***/ 428 429/***====================================================================***/ 430 431 /* 432 * void 433 * XkbCheckIndicatorMaps(dev,sli,which) 434 * 435 * Updates the 'indicator accelerators' for the indicators specified 436 * by 'which' in the feedback specified by 'sli.' The indicator 437 * accelerators are internal to the server and are used to simplify 438 * and speed up the process of figuring out which indicators might 439 * be affected by a particular change in keyboard state or controls. 440 */ 441 442void 443XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which) 444{ 445register unsigned i,bit; 446XkbIndicatorMapPtr map; 447XkbDescPtr xkb; 448 449 if ((sli->flags&XkbSLI_HasOwnState)==0) 450 dev= (DeviceIntPtr)LookupKeyboardDevice(); 451 452 sli->usesBase&= ~which; 453 sli->usesLatched&= ~which; 454 sli->usesLocked&= ~which; 455 sli->usesEffective&= ~which; 456 sli->usesCompat&= ~which; 457 sli->usesControls&= ~which; 458 sli->mapsPresent&= ~which; 459 460 xkb= dev->key->xkbInfo->desc; 461 for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) { 462 if (which&bit) { 463 CARD8 what; 464 465 if (!XkbIM_InUse(map)) 466 continue; 467 sli->mapsPresent|= bit; 468 469 what= (map->which_mods|map->which_groups); 470 if (what&XkbIM_UseBase) 471 sli->usesBase|= bit; 472 if (what&XkbIM_UseLatched) 473 sli->usesLatched|= bit; 474 if (what&XkbIM_UseLocked) 475 sli->usesLocked|= bit; 476 if (what&XkbIM_UseEffective) 477 sli->usesEffective|= bit; 478 if (what&XkbIM_UseCompat) 479 sli->usesCompat|= bit; 480 if (map->ctrls) 481 sli->usesControls|= bit; 482 483 map->mods.mask= map->mods.real_mods; 484 if (map->mods.vmods!=0) { 485 map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); 486 } 487 } 488 } 489 sli->usedComponents= 0; 490 if (sli->usesBase) 491 sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask; 492 if (sli->usesLatched) 493 sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask; 494 if (sli->usesLocked) 495 sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask; 496 if (sli->usesEffective) 497 sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask; 498 if (sli->usesCompat) 499 sli->usedComponents|= XkbCompatStateMask; 500 return; 501} 502 503/***====================================================================***/ 504 505 /* 506 * XkbSrvLedInfoPtr 507 * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) 508 * 509 * Allocates an XkbSrvLedInfoPtr for the feedback specified by either 510 * 'kf' or 'lf' on the keyboard specified by 'dev.' 511 * 512 * If 'needed_parts' is non-zero, this function makes sure that any 513 * of the parts speicified therein are allocated. 514 */ 515XkbSrvLedInfoPtr 516XkbAllocSrvLedInfo( DeviceIntPtr dev, 517 KbdFeedbackPtr kf, 518 LedFeedbackPtr lf, 519 unsigned needed_parts) 520{ 521XkbSrvLedInfoPtr sli; 522Bool checkAccel; 523Bool checkNames; 524 525 sli= NULL; 526 checkAccel= checkNames= False; 527 if ((kf!=NULL)&&(kf->xkb_sli==NULL)) { 528 kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); 529 if (sli==NULL) 530 return NULL; /* ALLOCATION ERROR */ 531 if (dev->key && dev->key->xkbInfo) 532 sli->flags= XkbSLI_HasOwnState; 533 else sli->flags= 0; 534 sli->class= KbdFeedbackClass; 535 sli->id= kf->ctrl.id; 536 sli->fb.kf= kf; 537 538 sli->autoState= 0; 539 sli->explicitState= kf->ctrl.leds; 540 sli->effectiveState= kf->ctrl.leds; 541 542 if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) { 543 XkbDescPtr xkb; 544 xkb= dev->key->xkbInfo->desc; 545 sli->flags|= XkbSLI_IsDefault; 546 sli->physIndicators= xkb->indicators->phys_indicators; 547 sli->names= xkb->names->indicators; 548 sli->maps= xkb->indicators->maps; 549 checkNames= checkAccel= True; 550 } 551 else { 552 sli->physIndicators= XkbAllIndicatorsMask; 553 sli->names= NULL; 554 sli->maps= NULL; 555 } 556 } 557 else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) { 558 XkbDescPtr xkb; 559 xkb= dev->key->xkbInfo->desc; 560 sli->physIndicators= xkb->indicators->phys_indicators; 561 if (xkb->names->indicators!=sli->names) { 562 checkNames= True; 563 sli->names= xkb->names->indicators; 564 } 565 if (xkb->indicators->maps!=sli->maps) { 566 checkAccel= True; 567 sli->maps= xkb->indicators->maps; 568 } 569 } 570 else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) { 571 lf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec); 572 if (sli==NULL) 573 return NULL; /* ALLOCATION ERROR */ 574 if (dev->key && dev->key->xkbInfo) 575 sli->flags= XkbSLI_HasOwnState; 576 else sli->flags= 0; 577 sli->class= LedFeedbackClass; 578 sli->id= lf->ctrl.id; 579 sli->fb.lf= lf; 580 581 sli->physIndicators= lf->ctrl.led_mask; 582 sli->autoState= 0; 583 sli->explicitState= lf->ctrl.led_values; 584 sli->effectiveState= lf->ctrl.led_values; 585 sli->maps= NULL; 586 sli->names= NULL; 587 } 588 if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) 589 sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); 590 if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) 591 sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); 592 if (checkNames) { 593 register unsigned i,bit; 594 sli->namesPresent= 0; 595 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { 596 if (sli->names[i]!=None) 597 sli->namesPresent|= bit; 598 } 599 } 600 if (checkAccel) 601 XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask); 602 return sli; 603} 604 605void 606XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) 607{ 608 if ((sli->flags&XkbSLI_IsDefault)==0) { 609 if (sli->maps) _XkbFree(sli->maps); 610 if (sli->names) _XkbFree(sli->names); 611 } 612 sli->maps= NULL; 613 sli->names= NULL; 614 _XkbFree(sli); 615 return; 616} 617 618 619/***====================================================================***/ 620 621 /* 622 * XkbSrvLedInfoPtr 623 * XkbFindSrvLedInfo(dev,class,id,needed_parts) 624 * 625 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id' 626 * on the device specified by 'dev.' If the class and id specify 627 * a valid device feedback, this function returns the existing 628 * feedback or allocates a new one. 629 * 630 */ 631 632XkbSrvLedInfoPtr 633XkbFindSrvLedInfo( DeviceIntPtr dev, 634 unsigned class, 635 unsigned id, 636 unsigned needed_parts) 637{ 638XkbSrvLedInfoPtr sli; 639 640 /* optimization to check for most common case */ 641 if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) { 642 XkbSrvLedInfoPtr sli; 643 sli= dev->kbdfeed->xkb_sli; 644 if (dev->kbdfeed->xkb_sli==NULL) { 645 sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts); 646 dev->kbdfeed->xkb_sli= sli; 647 } 648 return dev->kbdfeed->xkb_sli; 649 } 650 651 sli= NULL; 652 if (class==XkbDfltXIClass) { 653 if (dev->kbdfeed) class= KbdFeedbackClass; 654 else if (dev->leds) class= LedFeedbackClass; 655 else return NULL; 656 } 657 if (class==KbdFeedbackClass) { 658 KbdFeedbackPtr kf; 659 for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { 660 if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) { 661 if (kf->xkb_sli==NULL) 662 kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts); 663 sli= kf->xkb_sli; 664 break; 665 } 666 } 667 } 668 else if (class==LedFeedbackClass) { 669 LedFeedbackPtr lf; 670 for (lf=dev->leds;lf!=NULL;lf=lf->next) { 671 if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) { 672 if (lf->xkb_sli==NULL) 673 lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts); 674 sli= lf->xkb_sli; 675 break; 676 } 677 } 678 } 679 if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) 680 sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom); 681 if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) 682 sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); 683 return sli; 684} 685 686/***====================================================================***/ 687 688void 689XkbFlushLedEvents( DeviceIntPtr dev, 690 DeviceIntPtr kbd, 691 XkbSrvLedInfoPtr sli, 692 xkbExtensionDeviceNotify * ed, 693 XkbChangesPtr changes, 694 XkbEventCausePtr cause) 695{ 696 if (changes) { 697 if (changes->indicators.state_changes) 698 XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); 699 XkbSendNotification(kbd,changes,cause); 700 bzero((char *)changes,sizeof(XkbChangesRec)); 701 702 if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) { 703 if (sli->effectiveState) 704 /* it appears that the which parameter is not used */ 705 XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask); 706 else 707 XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask); 708 } 709 } 710 if (ed && (ed->reason)) { 711 if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask)) 712 XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); 713 XkbSendExtensionDeviceNotify(dev,cause->client,ed); 714 } 715 bzero((char *)ed,sizeof(XkbExtensionDeviceNotify)); 716 return; 717} 718 719/***====================================================================***/ 720 721void 722XkbApplyLedNameChanges( DeviceIntPtr dev, 723 XkbSrvLedInfoPtr sli, 724 unsigned changed_names, 725 xkbExtensionDeviceNotify * ed, 726 XkbChangesPtr changes, 727 XkbEventCausePtr cause) 728{ 729DeviceIntPtr kbd; 730XkbChangesRec my_changes; 731xkbExtensionDeviceNotify my_ed; 732 733 if (changed_names==0) 734 return; 735 if (dev->key && dev->key->xkbInfo) 736 kbd= dev; 737 else kbd= (DeviceIntPtr)LookupKeyboardDevice(); 738 739 if (ed==NULL) { 740 ed= &my_ed; 741 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); 742 } 743 else if ((ed->reason&XkbXI_IndicatorsMask)&& 744 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 745 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 746 } 747 748 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 749 if (changes==NULL) { 750 changes= &my_changes; 751 bzero((char *)changes,sizeof(XkbChangesRec)); 752 } 753 changes->names.changed|= XkbIndicatorNamesMask; 754 changes->names.changed_indicators|= changed_names; 755 } 756 757 ed->reason|= XkbXI_IndicatorNamesMask; 758 ed->ledClass= sli->class; 759 ed->ledID= sli->id; 760 ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 761 ed->ledState= sli->effectiveState; 762 ed->unsupported= 0; 763 ed->supported= XkbXI_AllFeaturesMask; 764 765 if (changes!=&my_changes) changes= NULL; 766 if (ed!=&my_ed) ed= NULL; 767 if (changes || ed) 768 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 769 return; 770} 771/***====================================================================***/ 772 773 /* 774 * void 775 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause) 776 * 777 * Handles all of the secondary effects of the changes to the 778 * feedback specified by 'sli' on the device specified by 'dev.' 779 * 780 * If 'changed_maps' specifies any indicators, this function generates 781 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify 782 * events to report the changes, and recalculates the effective 783 * state of each indicator with a changed map. If any indicators 784 * change state, the server generates XkbExtensionDeviceNotify and 785 * XkbIndicatorStateNotify events as appropriate. 786 * 787 * If 'changes' is non-NULL, this function updates it to reflect 788 * any changes to the keyboard state or controls or to the 'core' 789 * indicator names, maps, or state. If 'changes' is NULL, this 790 * function generates XKB events as needed to report the changes. 791 * If 'dev' is not a keyboard device, any changes are reported 792 * for the core keyboard. 793 * 794 * The 'cause' specifies the reason for the event (key event or 795 * request) for the change, as reported in some XKB events. 796 */ 797 798void 799XkbApplyLedMapChanges( DeviceIntPtr dev, 800 XkbSrvLedInfoPtr sli, 801 unsigned changed_maps, 802 xkbExtensionDeviceNotify * ed, 803 XkbChangesPtr changes, 804 XkbEventCausePtr cause) 805{ 806DeviceIntPtr kbd; 807XkbChangesRec my_changes; 808xkbExtensionDeviceNotify my_ed; 809 810 if (changed_maps==0) 811 return; 812 if (dev->key && dev->key->xkbInfo) 813 kbd= dev; 814 else kbd= (DeviceIntPtr)LookupKeyboardDevice(); 815 816 if (ed==NULL) { 817 ed= &my_ed; 818 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); 819 } 820 else if ((ed->reason&XkbXI_IndicatorsMask)&& 821 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 822 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 823 } 824 825 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 826 if (changes==NULL) { 827 changes= &my_changes; 828 bzero((char *)changes,sizeof(XkbChangesRec)); 829 } 830 changes->indicators.map_changes|= changed_maps; 831 } 832 833 XkbCheckIndicatorMaps(dev,sli,changed_maps); 834 835 ed->reason|= XkbXI_IndicatorMapsMask; 836 ed->ledClass= sli->class; 837 ed->ledID= sli->id; 838 ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 839 ed->ledState= sli->effectiveState; 840 ed->unsupported|= XkbXI_IndicatorMapsMask; 841 ed->supported= XkbXI_AllFeaturesMask; 842 843 XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause); 844 845 if (changes!=&my_changes) changes= NULL; 846 if (ed!=&my_ed) ed= NULL; 847 if (changes || ed) 848 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 849 return; 850} 851 852/***====================================================================***/ 853 854void 855XkbApplyLedStateChanges(DeviceIntPtr dev, 856 XkbSrvLedInfoPtr sli, 857 unsigned changed_leds, 858 xkbExtensionDeviceNotify * ed, 859 XkbChangesPtr changes, 860 XkbEventCausePtr cause) 861{ 862XkbSrvInfoPtr xkbi; 863DeviceIntPtr kbd; 864XkbChangesRec my_changes; 865xkbExtensionDeviceNotify my_ed; 866register unsigned i,bit,affected; 867XkbIndicatorMapPtr map; 868unsigned oldState; 869Bool kb_changed; 870 871 if (changed_leds==0) 872 return; 873 if (dev->key && dev->key->xkbInfo) 874 kbd= dev; 875 else kbd= (DeviceIntPtr)LookupKeyboardDevice(); 876 xkbi= kbd->key->xkbInfo; 877 878 if (changes==NULL) { 879 changes= &my_changes; 880 bzero((char *)changes,sizeof(XkbChangesRec)); 881 } 882 883 kb_changed= False; 884 affected= changed_leds; 885 oldState= sli->effectiveState; 886 for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { 887 if ((affected&bit)==0) 888 continue; 889 affected&= ~bit; 890 map= &sli->maps[i]; 891 if (map->flags&XkbIM_NoExplicit) { 892 sli->explicitState&= ~bit; 893 continue; 894 } 895 if (map->flags&XkbIM_LEDDrivesKB) { 896 Bool on= ((sli->explicitState&bit)!=0); 897 if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes)) 898 kb_changed= True; 899 } 900 } 901 sli->effectiveState= (sli->autoState|sli->explicitState); 902 affected= sli->effectiveState^oldState; 903 904 if (ed==NULL) { 905 ed= &my_ed; 906 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify)); 907 } 908 else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&& 909 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 910 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 911 } 912 913 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) 914 changes->indicators.state_changes|= affected; 915 if (affected) { 916 ed->reason|= XkbXI_IndicatorStateMask; 917 ed->ledClass= sli->class; 918 ed->ledID= sli->id; 919 ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 920 ed->ledState= sli->effectiveState; 921 ed->unsupported|= XkbXI_IndicatorStateMask; 922 ed->supported= XkbXI_AllFeaturesMask; 923 } 924 925 if (kb_changed) { 926 XkbComputeDerivedState(kbd->key->xkbInfo); 927 XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause); 928 } 929 930 if (changes!=&my_changes) changes= NULL; 931 if (ed!=&my_ed) ed= NULL; 932 if (changes || ed) 933 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 934 if (kb_changed) 935 XkbUpdateAllDeviceIndicators(NULL,cause); 936 return; 937} 938