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