1706f2543Smrg/************************************************************ 2706f2543SmrgCopyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 3706f2543Smrg 4706f2543SmrgPermission to use, copy, modify, and distribute this 5706f2543Smrgsoftware and its documentation for any purpose and without 6706f2543Smrgfee is hereby granted, provided that the above copyright 7706f2543Smrgnotice appear in all copies and that both that copyright 8706f2543Smrgnotice and this permission notice appear in supporting 9706f2543Smrgdocumentation, and that the name of Silicon Graphics not be 10706f2543Smrgused in advertising or publicity pertaining to distribution 11706f2543Smrgof the software without specific prior written permission. 12706f2543SmrgSilicon Graphics makes no representation about the suitability 13706f2543Smrgof this software for any purpose. It is provided "as is" 14706f2543Smrgwithout any express or implied warranty. 15706f2543Smrg 16706f2543SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17706f2543SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18706f2543SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19706f2543SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20706f2543SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21706f2543SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22706f2543SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23706f2543SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE. 24706f2543Smrg 25706f2543Smrg********************************************************/ 26706f2543Smrg 27706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 28706f2543Smrg#include <dix-config.h> 29706f2543Smrg#endif 30706f2543Smrg 31706f2543Smrg#include <stdio.h> 32706f2543Smrg#include <ctype.h> 33706f2543Smrg#include <math.h> 34706f2543Smrg#include <X11/X.h> 35706f2543Smrg#include <X11/Xproto.h> 36706f2543Smrg#include "misc.h" 37706f2543Smrg#include "inputstr.h" 38706f2543Smrg 39706f2543Smrg#include <X11/extensions/XI.h> 40706f2543Smrg#include <xkbsrv.h> 41706f2543Smrg#include "xkb.h" 42706f2543Smrg 43706f2543Smrg/***====================================================================***/ 44706f2543Smrg 45706f2543Smrg /* 46706f2543Smrg * unsigned 47706f2543Smrg * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn) 48706f2543Smrg * 49706f2543Smrg * Given a keyboard and a set of state components that have changed, 50706f2543Smrg * this function returns the indicators on the default keyboard 51706f2543Smrg * feedback that might be affected. It also reports whether or not 52706f2543Smrg * any extension devices might be affected in check_devs_rtrn. 53706f2543Smrg */ 54706f2543Smrg 55706f2543Smrgunsigned 56706f2543SmrgXkbIndicatorsToUpdate( DeviceIntPtr dev, 57706f2543Smrg unsigned long state_changes, 58706f2543Smrg Bool enable_changes) 59706f2543Smrg{ 60706f2543Smrgregister unsigned update= 0; 61706f2543SmrgXkbSrvLedInfoPtr sli; 62706f2543Smrg 63706f2543Smrg sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 64706f2543Smrg 65706f2543Smrg if (!sli) 66706f2543Smrg return update; 67706f2543Smrg 68706f2543Smrg if (state_changes&(XkbModifierStateMask|XkbGroupStateMask)) 69706f2543Smrg update|= sli->usesEffective; 70706f2543Smrg if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask)) 71706f2543Smrg update|= sli->usesBase; 72706f2543Smrg if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask)) 73706f2543Smrg update|= sli->usesLatched; 74706f2543Smrg if (state_changes&(XkbModifierLockMask|XkbGroupLockMask)) 75706f2543Smrg update|= sli->usesLocked; 76706f2543Smrg if (state_changes&XkbCompatStateMask) 77706f2543Smrg update|= sli->usesCompat; 78706f2543Smrg if (enable_changes) 79706f2543Smrg update|= sli->usesControls; 80706f2543Smrg return update; 81706f2543Smrg} 82706f2543Smrg 83706f2543Smrg/***====================================================================***/ 84706f2543Smrg 85706f2543Smrg /* 86706f2543Smrg * Bool 87706f2543Smrg *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) 88706f2543Smrg * 89706f2543Smrg * Some indicators "drive" the keyboard when their state is explicitly 90706f2543Smrg * changed, as described in section 9.2.1 of the XKB protocol spec. 91706f2543Smrg * This function updates the state and controls for the keyboard 92706f2543Smrg * specified by 'xkbi' to reflect any changes that are required 93706f2543Smrg * when the indicator described by 'map' is turned on or off. The 94706f2543Smrg * extent of the changes is reported in change, which must be defined. 95706f2543Smrg */ 96706f2543Smrgstatic Bool 97706f2543SmrgXkbApplyLEDChangeToKeyboard( XkbSrvInfoPtr xkbi, 98706f2543Smrg XkbIndicatorMapPtr map, 99706f2543Smrg Bool on, 100706f2543Smrg XkbChangesPtr change) 101706f2543Smrg{ 102706f2543SmrgBool ctrlChange,stateChange; 103706f2543SmrgXkbStatePtr state; 104706f2543Smrg 105706f2543Smrg if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0)) 106706f2543Smrg return FALSE; 107706f2543Smrg ctrlChange= stateChange= FALSE; 108706f2543Smrg if (map->ctrls) { 109706f2543Smrg XkbControlsPtr ctrls= xkbi->desc->ctrls; 110706f2543Smrg unsigned old; 111706f2543Smrg 112706f2543Smrg old= ctrls->enabled_ctrls; 113706f2543Smrg if (on) ctrls->enabled_ctrls|= map->ctrls; 114706f2543Smrg else ctrls->enabled_ctrls&= ~map->ctrls; 115706f2543Smrg if (old!=ctrls->enabled_ctrls) { 116706f2543Smrg change->ctrls.changed_ctrls= XkbControlsEnabledMask; 117706f2543Smrg change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls; 118706f2543Smrg ctrlChange= TRUE; 119706f2543Smrg } 120706f2543Smrg } 121706f2543Smrg state= &xkbi->state; 122706f2543Smrg if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) { 123706f2543Smrg register int i; 124706f2543Smrg register unsigned bit,match; 125706f2543Smrg 126706f2543Smrg if (on) match= (map->groups)&XkbAllGroupsMask; 127706f2543Smrg else match= (~map->groups)&XkbAllGroupsMask; 128706f2543Smrg if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) { 129706f2543Smrg for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { 130706f2543Smrg if (bit&match) 131706f2543Smrg break; 132706f2543Smrg } 133706f2543Smrg if (map->which_groups&XkbIM_UseLatched) 134706f2543Smrg XkbLatchGroup(xkbi->device,0); /* unlatch group */ 135706f2543Smrg state->locked_group= i; 136706f2543Smrg stateChange= TRUE; 137706f2543Smrg } 138706f2543Smrg else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) { 139706f2543Smrg for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) { 140706f2543Smrg if (bit&match) 141706f2543Smrg break; 142706f2543Smrg } 143706f2543Smrg state->locked_group= 0; 144706f2543Smrg XkbLatchGroup(xkbi->device,i); 145706f2543Smrg stateChange= TRUE; 146706f2543Smrg } 147706f2543Smrg } 148706f2543Smrg if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) { 149706f2543Smrg if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) { 150706f2543Smrg register unsigned long old; 151706f2543Smrg old= state->locked_mods; 152706f2543Smrg if (on) state->locked_mods|= map->mods.mask; 153706f2543Smrg else state->locked_mods&= ~map->mods.mask; 154706f2543Smrg if (state->locked_mods!=old) 155706f2543Smrg stateChange= TRUE; 156706f2543Smrg } 157706f2543Smrg if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) { 158706f2543Smrg register unsigned long newmods; 159706f2543Smrg newmods= state->latched_mods; 160706f2543Smrg if (on) newmods|= map->mods.mask; 161706f2543Smrg else newmods&= ~map->mods.mask; 162706f2543Smrg if (newmods!=state->locked_mods) { 163706f2543Smrg newmods&= map->mods.mask; 164706f2543Smrg XkbLatchModifiers(xkbi->device,map->mods.mask,newmods); 165706f2543Smrg stateChange= TRUE; 166706f2543Smrg } 167706f2543Smrg } 168706f2543Smrg } 169706f2543Smrg return stateChange || ctrlChange; 170706f2543Smrg} 171706f2543Smrg 172706f2543Smrg /* 173706f2543Smrg * Bool 174706f2543Smrg * ComputeAutoState(map,state,ctrls) 175706f2543Smrg * 176706f2543Smrg * This function reports the effect of applying the specified 177706f2543Smrg * indicator map given the specified state and controls, as 178706f2543Smrg * described in section 9.2 of the XKB protocol specification. 179706f2543Smrg */ 180706f2543Smrg 181706f2543Smrgstatic Bool 182706f2543SmrgComputeAutoState( XkbIndicatorMapPtr map, 183706f2543Smrg XkbStatePtr state, 184706f2543Smrg XkbControlsPtr ctrls) 185706f2543Smrg{ 186706f2543SmrgBool on; 187706f2543SmrgCARD8 mods,group; 188706f2543Smrg 189706f2543Smrg on= FALSE; 190706f2543Smrg mods= group= 0; 191706f2543Smrg if (map->which_mods&XkbIM_UseAnyMods) { 192706f2543Smrg if (map->which_mods&XkbIM_UseBase) 193706f2543Smrg mods|= state->base_mods; 194706f2543Smrg if (map->which_mods&XkbIM_UseLatched) 195706f2543Smrg mods|= state->latched_mods; 196706f2543Smrg if (map->which_mods&XkbIM_UseLocked) 197706f2543Smrg mods|= state->locked_mods; 198706f2543Smrg if (map->which_mods&XkbIM_UseEffective) 199706f2543Smrg mods|= state->mods; 200706f2543Smrg if (map->which_mods&XkbIM_UseCompat) 201706f2543Smrg mods|= state->compat_state; 202706f2543Smrg on = ((map->mods.mask&mods)!=0); 203706f2543Smrg on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0)); 204706f2543Smrg } 205706f2543Smrg if (map->which_groups&XkbIM_UseAnyGroup) { 206706f2543Smrg if (map->which_groups&XkbIM_UseBase) 207706f2543Smrg group|= (1L << state->base_group); 208706f2543Smrg if (map->which_groups&XkbIM_UseLatched) 209706f2543Smrg group|= (1L << state->latched_group); 210706f2543Smrg if (map->which_groups&XkbIM_UseLocked) 211706f2543Smrg group|= (1L << state->locked_group); 212706f2543Smrg if (map->which_groups&XkbIM_UseEffective) 213706f2543Smrg group|= (1L << state->group); 214706f2543Smrg on = on||(((map->groups&group)!=0)||(map->groups==0)); 215706f2543Smrg } 216706f2543Smrg if (map->ctrls) 217706f2543Smrg on = on||(ctrls->enabled_ctrls&map->ctrls); 218706f2543Smrg return on; 219706f2543Smrg} 220706f2543Smrg 221706f2543Smrg 222706f2543Smrgstatic void 223706f2543SmrgXkbUpdateLedAutoState( DeviceIntPtr dev, 224706f2543Smrg XkbSrvLedInfoPtr sli, 225706f2543Smrg unsigned maps_to_check, 226706f2543Smrg xkbExtensionDeviceNotify * ed, 227706f2543Smrg XkbChangesPtr changes, 228706f2543Smrg XkbEventCausePtr cause) 229706f2543Smrg{ 230706f2543SmrgDeviceIntPtr kbd; 231706f2543SmrgXkbStatePtr state; 232706f2543SmrgXkbControlsPtr ctrls; 233706f2543SmrgXkbChangesRec my_changes; 234706f2543SmrgxkbExtensionDeviceNotify my_ed; 235706f2543Smrgregister unsigned i,bit,affected; 236706f2543Smrgregister XkbIndicatorMapPtr map; 237706f2543Smrgunsigned oldState; 238706f2543Smrg 239706f2543Smrg if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0)) 240706f2543Smrg return; 241706f2543Smrg 242706f2543Smrg if (dev->key && dev->key->xkbInfo) 243706f2543Smrg kbd= dev; 244706f2543Smrg else kbd= inputInfo.keyboard; 245706f2543Smrg 246706f2543Smrg state= &kbd->key->xkbInfo->state; 247706f2543Smrg ctrls= kbd->key->xkbInfo->desc->ctrls; 248706f2543Smrg affected= maps_to_check; 249706f2543Smrg oldState= sli->effectiveState; 250706f2543Smrg sli->autoState&= ~affected; 251706f2543Smrg for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { 252706f2543Smrg if ((affected&bit)==0) 253706f2543Smrg continue; 254706f2543Smrg affected&= ~bit; 255706f2543Smrg map= &sli->maps[i]; 256706f2543Smrg if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls)) 257706f2543Smrg sli->autoState|= bit; 258706f2543Smrg } 259706f2543Smrg sli->effectiveState= (sli->autoState|sli->explicitState); 260706f2543Smrg affected= sli->effectiveState^oldState; 261706f2543Smrg if (affected==0) 262706f2543Smrg return; 263706f2543Smrg 264706f2543Smrg if (ed==NULL) { 265706f2543Smrg ed= &my_ed; 266706f2543Smrg memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify)); 267706f2543Smrg } 268706f2543Smrg else if ((ed->reason&XkbXI_IndicatorsMask)&& 269706f2543Smrg ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 270706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 271706f2543Smrg } 272706f2543Smrg 273706f2543Smrg if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 274706f2543Smrg if (changes==NULL) { 275706f2543Smrg changes= &my_changes; 276706f2543Smrg memset((char *)changes, 0, sizeof(XkbChangesRec)); 277706f2543Smrg } 278706f2543Smrg changes->indicators.state_changes|= affected; 279706f2543Smrg } 280706f2543Smrg 281706f2543Smrg ed->reason|= XkbXI_IndicatorStateMask; 282706f2543Smrg ed->ledClass= sli->class; 283706f2543Smrg ed->ledID= sli->id; 284706f2543Smrg ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 285706f2543Smrg ed->ledState= sli->effectiveState; 286706f2543Smrg ed->unsupported= 0; 287706f2543Smrg ed->supported= XkbXI_AllFeaturesMask; 288706f2543Smrg 289706f2543Smrg if (changes!=&my_changes) changes= NULL; 290706f2543Smrg if (ed!=&my_ed) ed= NULL; 291706f2543Smrg if (changes || ed) 292706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 293706f2543Smrg return; 294706f2543Smrg} 295706f2543Smrg 296706f2543Smrgstatic void 297706f2543SmrgXkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause) 298706f2543Smrg{ 299706f2543SmrgDeviceIntPtr edev; 300706f2543SmrgXkbSrvLedInfoPtr sli; 301706f2543Smrg 302706f2543Smrg for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) { 303706f2543Smrg if (edev->kbdfeed) { 304706f2543Smrg KbdFeedbackPtr kf; 305706f2543Smrg for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) { 306706f2543Smrg if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL)) 307706f2543Smrg continue; 308706f2543Smrg sli= kf->xkb_sli; 309706f2543Smrg XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, 310706f2543Smrg changes,cause); 311706f2543Smrg 312706f2543Smrg } 313706f2543Smrg } 314706f2543Smrg if (edev->leds) { 315706f2543Smrg LedFeedbackPtr lf; 316706f2543Smrg for (lf=edev->leds;lf!=NULL;lf=lf->next) { 317706f2543Smrg if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL)) 318706f2543Smrg continue; 319706f2543Smrg sli= lf->xkb_sli; 320706f2543Smrg XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL, 321706f2543Smrg changes,cause); 322706f2543Smrg 323706f2543Smrg } 324706f2543Smrg } 325706f2543Smrg } 326706f2543Smrg return; 327706f2543Smrg} 328706f2543Smrg 329706f2543Smrg 330706f2543Smrg/***====================================================================***/ 331706f2543Smrg 332706f2543Smrg /* 333706f2543Smrg * void 334706f2543Smrg * XkbSetIndicators(dev,affect,values,cause) 335706f2543Smrg * 336706f2543Smrg * Attempts to change the indicators specified in 'affect' to the 337706f2543Smrg * states specified in 'values' for the default keyboard feedback 338706f2543Smrg * on the keyboard specified by 'dev.' Attempts to change indicator 339706f2543Smrg * state might be ignored or have no affect, depending on the XKB 340706f2543Smrg * indicator map for any affected indicators, as described in section 341706f2543Smrg * 9.2 of the XKB protocol specification. 342706f2543Smrg * 343706f2543Smrg * If 'changes' is non-NULL, this function notes any changes to the 344706f2543Smrg * keyboard state, controls, or indicator state that result from this 345706f2543Smrg * attempted change. If 'changes' is NULL, this function generates 346706f2543Smrg * XKB events to report any such changes to interested clients. 347706f2543Smrg * 348706f2543Smrg * If 'cause' is non-NULL, it specifies the reason for the change, 349706f2543Smrg * as reported in some XKB events. If it is NULL, this function 350706f2543Smrg * assumes that the change is the result of a core protocol 351706f2543Smrg * ChangeKeyboardMapping request. 352706f2543Smrg */ 353706f2543Smrg 354706f2543Smrgvoid 355706f2543SmrgXkbSetIndicators( DeviceIntPtr dev, 356706f2543Smrg CARD32 affect, 357706f2543Smrg CARD32 values, 358706f2543Smrg XkbEventCausePtr cause) 359706f2543Smrg{ 360706f2543SmrgXkbSrvLedInfoPtr sli; 361706f2543SmrgXkbChangesRec changes; 362706f2543SmrgxkbExtensionDeviceNotify ed; 363706f2543Smrgunsigned side_affected; 364706f2543Smrg 365706f2543Smrg memset((char *)&changes, 0, sizeof(XkbChangesRec)); 366706f2543Smrg memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify)); 367706f2543Smrg sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 368706f2543Smrg sli->explicitState&= ~affect; 369706f2543Smrg sli->explicitState|= (affect&values); 370706f2543Smrg XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause); 371706f2543Smrg 372706f2543Smrg side_affected= 0; 373706f2543Smrg if (changes.state_changes!=0) 374706f2543Smrg side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,FALSE); 375706f2543Smrg if (changes.ctrls.enabled_ctrls_changes) 376706f2543Smrg side_affected|= sli->usesControls; 377706f2543Smrg 378706f2543Smrg if (side_affected) { 379706f2543Smrg XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause); 380706f2543Smrg affect|= side_affected; 381706f2543Smrg } 382706f2543Smrg if (changes.state_changes || changes.ctrls.enabled_ctrls_changes) 383706f2543Smrg XkbUpdateAllDeviceIndicators(NULL,cause); 384706f2543Smrg 385706f2543Smrg XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause); 386706f2543Smrg return; 387706f2543Smrg} 388706f2543Smrg 389706f2543Smrg/***====================================================================***/ 390706f2543Smrg 391706f2543Smrg/***====================================================================***/ 392706f2543Smrg 393706f2543Smrg /* 394706f2543Smrg * void 395706f2543Smrg * XkbUpdateIndicators(dev,update,check_edevs,changes,cause) 396706f2543Smrg * 397706f2543Smrg * Applies the indicator maps for any indicators specified in 398706f2543Smrg * 'update' from the default keyboard feedback on the device 399706f2543Smrg * specified by 'dev.' 400706f2543Smrg * 401706f2543Smrg * If 'changes' is NULL, this function generates and XKB events 402706f2543Smrg * required to report the necessary changes, otherwise it simply 403706f2543Smrg * notes the indicators with changed state. 404706f2543Smrg * 405706f2543Smrg * If 'check_edevs' is TRUE, this function also checks the indicator 406706f2543Smrg * maps for any open extension devices that have them, and updates 407706f2543Smrg * the state of any extension device indicators as necessary. 408706f2543Smrg */ 409706f2543Smrg 410706f2543Smrgvoid 411706f2543SmrgXkbUpdateIndicators( DeviceIntPtr dev, 412706f2543Smrg register CARD32 update, 413706f2543Smrg Bool check_edevs, 414706f2543Smrg XkbChangesPtr changes, 415706f2543Smrg XkbEventCausePtr cause) 416706f2543Smrg{ 417706f2543SmrgXkbSrvLedInfoPtr sli; 418706f2543Smrg 419706f2543Smrg sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0); 420706f2543Smrg XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause); 421706f2543Smrg if (check_edevs) 422706f2543Smrg XkbUpdateAllDeviceIndicators(changes,cause); 423706f2543Smrg return; 424706f2543Smrg} 425706f2543Smrg 426706f2543Smrg/***====================================================================***/ 427706f2543Smrg 428706f2543Smrg/***====================================================================***/ 429706f2543Smrg 430706f2543Smrg /* 431706f2543Smrg * void 432706f2543Smrg * XkbCheckIndicatorMaps(dev,sli,which) 433706f2543Smrg * 434706f2543Smrg * Updates the 'indicator accelerators' for the indicators specified 435706f2543Smrg * by 'which' in the feedback specified by 'sli.' The indicator 436706f2543Smrg * accelerators are internal to the server and are used to simplify 437706f2543Smrg * and speed up the process of figuring out which indicators might 438706f2543Smrg * be affected by a particular change in keyboard state or controls. 439706f2543Smrg */ 440706f2543Smrg 441706f2543Smrgvoid 442706f2543SmrgXkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which) 443706f2543Smrg{ 444706f2543Smrgregister unsigned i,bit; 445706f2543SmrgXkbIndicatorMapPtr map; 446706f2543SmrgXkbDescPtr xkb; 447706f2543Smrg 448706f2543Smrg if ((sli->flags&XkbSLI_HasOwnState)==0) 449706f2543Smrg return; 450706f2543Smrg 451706f2543Smrg sli->usesBase&= ~which; 452706f2543Smrg sli->usesLatched&= ~which; 453706f2543Smrg sli->usesLocked&= ~which; 454706f2543Smrg sli->usesEffective&= ~which; 455706f2543Smrg sli->usesCompat&= ~which; 456706f2543Smrg sli->usesControls&= ~which; 457706f2543Smrg sli->mapsPresent&= ~which; 458706f2543Smrg 459706f2543Smrg xkb= dev->key->xkbInfo->desc; 460706f2543Smrg for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) { 461706f2543Smrg if (which&bit) { 462706f2543Smrg CARD8 what; 463706f2543Smrg 464706f2543Smrg if (!map || !XkbIM_InUse(map)) 465706f2543Smrg continue; 466706f2543Smrg sli->mapsPresent|= bit; 467706f2543Smrg 468706f2543Smrg what= (map->which_mods|map->which_groups); 469706f2543Smrg if (what&XkbIM_UseBase) 470706f2543Smrg sli->usesBase|= bit; 471706f2543Smrg if (what&XkbIM_UseLatched) 472706f2543Smrg sli->usesLatched|= bit; 473706f2543Smrg if (what&XkbIM_UseLocked) 474706f2543Smrg sli->usesLocked|= bit; 475706f2543Smrg if (what&XkbIM_UseEffective) 476706f2543Smrg sli->usesEffective|= bit; 477706f2543Smrg if (what&XkbIM_UseCompat) 478706f2543Smrg sli->usesCompat|= bit; 479706f2543Smrg if (map->ctrls) 480706f2543Smrg sli->usesControls|= bit; 481706f2543Smrg 482706f2543Smrg map->mods.mask= map->mods.real_mods; 483706f2543Smrg if (map->mods.vmods!=0) { 484706f2543Smrg map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods); 485706f2543Smrg } 486706f2543Smrg } 487706f2543Smrg } 488706f2543Smrg sli->usedComponents= 0; 489706f2543Smrg if (sli->usesBase) 490706f2543Smrg sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask; 491706f2543Smrg if (sli->usesLatched) 492706f2543Smrg sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask; 493706f2543Smrg if (sli->usesLocked) 494706f2543Smrg sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask; 495706f2543Smrg if (sli->usesEffective) 496706f2543Smrg sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask; 497706f2543Smrg if (sli->usesCompat) 498706f2543Smrg sli->usedComponents|= XkbCompatStateMask; 499706f2543Smrg return; 500706f2543Smrg} 501706f2543Smrg 502706f2543Smrg/***====================================================================***/ 503706f2543Smrg 504706f2543Smrg /* 505706f2543Smrg * XkbSrvLedInfoPtr 506706f2543Smrg * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) 507706f2543Smrg * 508706f2543Smrg * Allocates an XkbSrvLedInfoPtr for the feedback specified by either 509706f2543Smrg * 'kf' or 'lf' on the keyboard specified by 'dev.' 510706f2543Smrg * 511706f2543Smrg * If 'needed_parts' is non-zero, this function makes sure that any 512706f2543Smrg * of the parts speicified therein are allocated. 513706f2543Smrg */ 514706f2543SmrgXkbSrvLedInfoPtr 515706f2543SmrgXkbAllocSrvLedInfo( DeviceIntPtr dev, 516706f2543Smrg KbdFeedbackPtr kf, 517706f2543Smrg LedFeedbackPtr lf, 518706f2543Smrg unsigned needed_parts) 519706f2543Smrg{ 520706f2543SmrgXkbSrvLedInfoPtr sli; 521706f2543SmrgBool checkAccel; 522706f2543SmrgBool checkNames; 523706f2543Smrg 524706f2543Smrg sli= NULL; 525706f2543Smrg checkAccel= checkNames= FALSE; 526706f2543Smrg if ((kf!=NULL)&&(kf->xkb_sli==NULL)) { 527706f2543Smrg kf->xkb_sli= sli= calloc(1, sizeof(XkbSrvLedInfoRec)); 528706f2543Smrg if (sli==NULL) 529706f2543Smrg return NULL; /* ALLOCATION ERROR */ 530706f2543Smrg if (dev->key && dev->key->xkbInfo) 531706f2543Smrg sli->flags= XkbSLI_HasOwnState; 532706f2543Smrg else sli->flags= 0; 533706f2543Smrg sli->class= KbdFeedbackClass; 534706f2543Smrg sli->id= kf->ctrl.id; 535706f2543Smrg sli->fb.kf= kf; 536706f2543Smrg 537706f2543Smrg sli->autoState= 0; 538706f2543Smrg sli->explicitState= kf->ctrl.leds; 539706f2543Smrg sli->effectiveState= kf->ctrl.leds; 540706f2543Smrg 541706f2543Smrg if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) { 542706f2543Smrg XkbDescPtr xkb; 543706f2543Smrg xkb= dev->key->xkbInfo->desc; 544706f2543Smrg sli->flags|= XkbSLI_IsDefault; 545706f2543Smrg sli->physIndicators= xkb->indicators->phys_indicators; 546706f2543Smrg sli->names= xkb->names->indicators; 547706f2543Smrg sli->maps= xkb->indicators->maps; 548706f2543Smrg checkNames= checkAccel= TRUE; 549706f2543Smrg } 550706f2543Smrg else { 551706f2543Smrg sli->physIndicators= XkbAllIndicatorsMask; 552706f2543Smrg sli->names= NULL; 553706f2543Smrg sli->maps= NULL; 554706f2543Smrg } 555706f2543Smrg } 556706f2543Smrg else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) { 557706f2543Smrg XkbDescPtr xkb; 558706f2543Smrg xkb= dev->key->xkbInfo->desc; 559706f2543Smrg sli= kf->xkb_sli; 560706f2543Smrg sli->physIndicators= xkb->indicators->phys_indicators; 561706f2543Smrg if (xkb->names->indicators!=sli->names) { 562706f2543Smrg checkNames= TRUE; 563706f2543Smrg sli->names= xkb->names->indicators; 564706f2543Smrg } 565706f2543Smrg if (xkb->indicators->maps!=sli->maps) { 566706f2543Smrg checkAccel= TRUE; 567706f2543Smrg sli->maps= xkb->indicators->maps; 568706f2543Smrg } 569706f2543Smrg } 570706f2543Smrg else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) { 571706f2543Smrg lf->xkb_sli= sli= calloc(1, sizeof(XkbSrvLedInfoRec)); 572706f2543Smrg if (sli==NULL) 573706f2543Smrg return NULL; /* ALLOCATION ERROR */ 574706f2543Smrg if (dev->key && dev->key->xkbInfo) 575706f2543Smrg sli->flags= XkbSLI_HasOwnState; 576706f2543Smrg else sli->flags= 0; 577706f2543Smrg sli->class= LedFeedbackClass; 578706f2543Smrg sli->id= lf->ctrl.id; 579706f2543Smrg sli->fb.lf= lf; 580706f2543Smrg 581706f2543Smrg sli->physIndicators= lf->ctrl.led_mask; 582706f2543Smrg sli->autoState= 0; 583706f2543Smrg sli->explicitState= lf->ctrl.led_values; 584706f2543Smrg sli->effectiveState= lf->ctrl.led_values; 585706f2543Smrg sli->maps= NULL; 586706f2543Smrg sli->names= NULL; 587706f2543Smrg } 588706f2543Smrg else 589706f2543Smrg return NULL; 590706f2543Smrg if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) 591706f2543Smrg sli->names= calloc(XkbNumIndicators, sizeof(Atom)); 592706f2543Smrg if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) 593706f2543Smrg sli->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec)); 594706f2543Smrg if (checkNames) { 595706f2543Smrg register unsigned i,bit; 596706f2543Smrg sli->namesPresent= 0; 597706f2543Smrg for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) { 598706f2543Smrg if (sli->names[i]!=None) 599706f2543Smrg sli->namesPresent|= bit; 600706f2543Smrg } 601706f2543Smrg } 602706f2543Smrg if (checkAccel) 603706f2543Smrg XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask); 604706f2543Smrg return sli; 605706f2543Smrg} 606706f2543Smrg 607706f2543Smrgvoid 608706f2543SmrgXkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) 609706f2543Smrg{ 610706f2543Smrg if ((sli->flags&XkbSLI_IsDefault)==0) { 611706f2543Smrg free(sli->maps); 612706f2543Smrg free(sli->names); 613706f2543Smrg } 614706f2543Smrg sli->maps= NULL; 615706f2543Smrg sli->names= NULL; 616706f2543Smrg free(sli); 617706f2543Smrg return; 618706f2543Smrg} 619706f2543Smrg 620706f2543Smrg/* 621706f2543Smrg * XkbSrvLedInfoPtr 622706f2543Smrg * XkbCopySrvLedInfo(dev,src,kf,lf) 623706f2543Smrg * 624706f2543Smrg * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made, 625706f2543Smrg * thus the new copy behaves like the original one and can be freed with 626706f2543Smrg * XkbFreeSrvLedInfo. 627706f2543Smrg */ 628706f2543SmrgXkbSrvLedInfoPtr 629706f2543SmrgXkbCopySrvLedInfo( DeviceIntPtr from, 630706f2543Smrg XkbSrvLedInfoPtr src, 631706f2543Smrg KbdFeedbackPtr kf, 632706f2543Smrg LedFeedbackPtr lf) 633706f2543Smrg{ 634706f2543Smrg XkbSrvLedInfoPtr sli_new = NULL; 635706f2543Smrg 636706f2543Smrg if (!src) 637706f2543Smrg goto finish; 638706f2543Smrg 639706f2543Smrg sli_new = calloc(1, sizeof( XkbSrvLedInfoRec)); 640706f2543Smrg if (!sli_new) 641706f2543Smrg goto finish; 642706f2543Smrg 643706f2543Smrg memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec)); 644706f2543Smrg if (sli_new->class == KbdFeedbackClass) 645706f2543Smrg sli_new->fb.kf = kf; 646706f2543Smrg else 647706f2543Smrg sli_new->fb.lf = lf; 648706f2543Smrg 649706f2543Smrg if (!(sli_new->flags & XkbSLI_IsDefault)) { 650706f2543Smrg sli_new->names= calloc(XkbNumIndicators, sizeof(Atom)); 651706f2543Smrg sli_new->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec)); 652706f2543Smrg } /* else sli_new->names/maps is pointing to 653706f2543Smrg dev->key->xkbInfo->desc->names->indicators; 654706f2543Smrg dev->key->xkbInfo->desc->names->indicators; */ 655706f2543Smrg 656706f2543Smrgfinish: 657706f2543Smrg return sli_new; 658706f2543Smrg} 659706f2543Smrg 660706f2543Smrg/***====================================================================***/ 661706f2543Smrg 662706f2543Smrg /* 663706f2543Smrg * XkbSrvLedInfoPtr 664706f2543Smrg * XkbFindSrvLedInfo(dev,class,id,needed_parts) 665706f2543Smrg * 666706f2543Smrg * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id' 667706f2543Smrg * on the device specified by 'dev.' If the class and id specify 668706f2543Smrg * a valid device feedback, this function returns the existing 669706f2543Smrg * feedback or allocates a new one. 670706f2543Smrg * 671706f2543Smrg */ 672706f2543Smrg 673706f2543SmrgXkbSrvLedInfoPtr 674706f2543SmrgXkbFindSrvLedInfo( DeviceIntPtr dev, 675706f2543Smrg unsigned class, 676706f2543Smrg unsigned id, 677706f2543Smrg unsigned needed_parts) 678706f2543Smrg{ 679706f2543SmrgXkbSrvLedInfoPtr sli; 680706f2543Smrg 681706f2543Smrg /* optimization to check for most common case */ 682706f2543Smrg if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) { 683706f2543Smrg XkbSrvLedInfoPtr sli; 684706f2543Smrg sli= dev->kbdfeed->xkb_sli; 685706f2543Smrg if (dev->kbdfeed->xkb_sli==NULL) { 686706f2543Smrg sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts); 687706f2543Smrg dev->kbdfeed->xkb_sli= sli; 688706f2543Smrg } 689706f2543Smrg return dev->kbdfeed->xkb_sli; 690706f2543Smrg } 691706f2543Smrg 692706f2543Smrg sli= NULL; 693706f2543Smrg if (class==XkbDfltXIClass) { 694706f2543Smrg if (dev->kbdfeed) class= KbdFeedbackClass; 695706f2543Smrg else if (dev->leds) class= LedFeedbackClass; 696706f2543Smrg else return NULL; 697706f2543Smrg } 698706f2543Smrg if (class==KbdFeedbackClass) { 699706f2543Smrg KbdFeedbackPtr kf; 700706f2543Smrg for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) { 701706f2543Smrg if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) { 702706f2543Smrg if (kf->xkb_sli==NULL) 703706f2543Smrg kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts); 704706f2543Smrg sli= kf->xkb_sli; 705706f2543Smrg break; 706706f2543Smrg } 707706f2543Smrg } 708706f2543Smrg } 709706f2543Smrg else if (class==LedFeedbackClass) { 710706f2543Smrg LedFeedbackPtr lf; 711706f2543Smrg for (lf=dev->leds;lf!=NULL;lf=lf->next) { 712706f2543Smrg if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) { 713706f2543Smrg if (lf->xkb_sli==NULL) 714706f2543Smrg lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts); 715706f2543Smrg sli= lf->xkb_sli; 716706f2543Smrg break; 717706f2543Smrg } 718706f2543Smrg } 719706f2543Smrg } 720706f2543Smrg if (sli) { 721706f2543Smrg if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask)) 722706f2543Smrg sli->names= calloc(XkbNumIndicators, sizeof(Atom)); 723706f2543Smrg if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask)) 724706f2543Smrg sli->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec)); 725706f2543Smrg } 726706f2543Smrg return sli; 727706f2543Smrg} 728706f2543Smrg 729706f2543Smrg/***====================================================================***/ 730706f2543Smrg 731706f2543Smrgvoid 732706f2543SmrgXkbFlushLedEvents( DeviceIntPtr dev, 733706f2543Smrg DeviceIntPtr kbd, 734706f2543Smrg XkbSrvLedInfoPtr sli, 735706f2543Smrg xkbExtensionDeviceNotify * ed, 736706f2543Smrg XkbChangesPtr changes, 737706f2543Smrg XkbEventCausePtr cause) 738706f2543Smrg{ 739706f2543Smrg if (changes) { 740706f2543Smrg if (changes->indicators.state_changes) 741706f2543Smrg XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); 742706f2543Smrg XkbSendNotification(kbd,changes,cause); 743706f2543Smrg memset((char *)changes, 0, sizeof(XkbChangesRec)); 744706f2543Smrg 745706f2543Smrg if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) { 746706f2543Smrg if (sli->effectiveState) 747706f2543Smrg /* it appears that the which parameter is not used */ 748706f2543Smrg XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask); 749706f2543Smrg else 750706f2543Smrg XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask); 751706f2543Smrg } 752706f2543Smrg } 753706f2543Smrg if (ed) { 754706f2543Smrg if (ed->reason) { 755706f2543Smrg if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask)) 756706f2543Smrg XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState); 757706f2543Smrg XkbSendExtensionDeviceNotify(dev,cause->client,ed); 758706f2543Smrg } 759706f2543Smrg memset((char *)ed, 0, sizeof(XkbExtensionDeviceNotify)); 760706f2543Smrg } 761706f2543Smrg return; 762706f2543Smrg} 763706f2543Smrg 764706f2543Smrg/***====================================================================***/ 765706f2543Smrg 766706f2543Smrgvoid 767706f2543SmrgXkbApplyLedNameChanges( DeviceIntPtr dev, 768706f2543Smrg XkbSrvLedInfoPtr sli, 769706f2543Smrg unsigned changed_names, 770706f2543Smrg xkbExtensionDeviceNotify * ed, 771706f2543Smrg XkbChangesPtr changes, 772706f2543Smrg XkbEventCausePtr cause) 773706f2543Smrg{ 774706f2543SmrgDeviceIntPtr kbd; 775706f2543SmrgXkbChangesRec my_changes; 776706f2543SmrgxkbExtensionDeviceNotify my_ed; 777706f2543Smrg 778706f2543Smrg if (changed_names==0) 779706f2543Smrg return; 780706f2543Smrg if (dev->key && dev->key->xkbInfo) 781706f2543Smrg kbd= dev; 782706f2543Smrg else kbd= inputInfo.keyboard; 783706f2543Smrg 784706f2543Smrg if (ed==NULL) { 785706f2543Smrg ed= &my_ed; 786706f2543Smrg memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify)); 787706f2543Smrg } 788706f2543Smrg else if ((ed->reason&XkbXI_IndicatorsMask)&& 789706f2543Smrg ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 790706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 791706f2543Smrg } 792706f2543Smrg 793706f2543Smrg if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 794706f2543Smrg if (changes==NULL) { 795706f2543Smrg changes= &my_changes; 796706f2543Smrg memset((char *)changes, 0, sizeof(XkbChangesRec)); 797706f2543Smrg } 798706f2543Smrg changes->names.changed|= XkbIndicatorNamesMask; 799706f2543Smrg changes->names.changed_indicators|= changed_names; 800706f2543Smrg } 801706f2543Smrg 802706f2543Smrg ed->reason|= XkbXI_IndicatorNamesMask; 803706f2543Smrg ed->ledClass= sli->class; 804706f2543Smrg ed->ledID= sli->id; 805706f2543Smrg ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 806706f2543Smrg ed->ledState= sli->effectiveState; 807706f2543Smrg ed->unsupported= 0; 808706f2543Smrg ed->supported= XkbXI_AllFeaturesMask; 809706f2543Smrg 810706f2543Smrg if (changes!=&my_changes) changes= NULL; 811706f2543Smrg if (ed!=&my_ed) ed= NULL; 812706f2543Smrg if (changes || ed) 813706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 814706f2543Smrg return; 815706f2543Smrg} 816706f2543Smrg/***====================================================================***/ 817706f2543Smrg 818706f2543Smrg /* 819706f2543Smrg * void 820706f2543Smrg * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause) 821706f2543Smrg * 822706f2543Smrg * Handles all of the secondary effects of the changes to the 823706f2543Smrg * feedback specified by 'sli' on the device specified by 'dev.' 824706f2543Smrg * 825706f2543Smrg * If 'changed_maps' specifies any indicators, this function generates 826706f2543Smrg * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify 827706f2543Smrg * events to report the changes, and recalculates the effective 828706f2543Smrg * state of each indicator with a changed map. If any indicators 829706f2543Smrg * change state, the server generates XkbExtensionDeviceNotify and 830706f2543Smrg * XkbIndicatorStateNotify events as appropriate. 831706f2543Smrg * 832706f2543Smrg * If 'changes' is non-NULL, this function updates it to reflect 833706f2543Smrg * any changes to the keyboard state or controls or to the 'core' 834706f2543Smrg * indicator names, maps, or state. If 'changes' is NULL, this 835706f2543Smrg * function generates XKB events as needed to report the changes. 836706f2543Smrg * If 'dev' is not a keyboard device, any changes are reported 837706f2543Smrg * for the core keyboard. 838706f2543Smrg * 839706f2543Smrg * The 'cause' specifies the reason for the event (key event or 840706f2543Smrg * request) for the change, as reported in some XKB events. 841706f2543Smrg */ 842706f2543Smrg 843706f2543Smrgvoid 844706f2543SmrgXkbApplyLedMapChanges( DeviceIntPtr dev, 845706f2543Smrg XkbSrvLedInfoPtr sli, 846706f2543Smrg unsigned changed_maps, 847706f2543Smrg xkbExtensionDeviceNotify * ed, 848706f2543Smrg XkbChangesPtr changes, 849706f2543Smrg XkbEventCausePtr cause) 850706f2543Smrg{ 851706f2543SmrgDeviceIntPtr kbd; 852706f2543SmrgXkbChangesRec my_changes; 853706f2543SmrgxkbExtensionDeviceNotify my_ed; 854706f2543Smrg 855706f2543Smrg if (changed_maps==0) 856706f2543Smrg return; 857706f2543Smrg if (dev->key && dev->key->xkbInfo) 858706f2543Smrg kbd= dev; 859706f2543Smrg else kbd= inputInfo.keyboard; 860706f2543Smrg 861706f2543Smrg if (ed==NULL) { 862706f2543Smrg ed= &my_ed; 863706f2543Smrg memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify)); 864706f2543Smrg } 865706f2543Smrg else if ((ed->reason&XkbXI_IndicatorsMask)&& 866706f2543Smrg ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 867706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 868706f2543Smrg } 869706f2543Smrg 870706f2543Smrg if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 871706f2543Smrg if (changes==NULL) { 872706f2543Smrg changes= &my_changes; 873706f2543Smrg memset((char *)changes, 0, sizeof(XkbChangesRec)); 874706f2543Smrg } 875706f2543Smrg changes->indicators.map_changes|= changed_maps; 876706f2543Smrg } 877706f2543Smrg 878706f2543Smrg XkbCheckIndicatorMaps(dev,sli,changed_maps); 879706f2543Smrg 880706f2543Smrg ed->reason|= XkbXI_IndicatorMapsMask; 881706f2543Smrg ed->ledClass= sli->class; 882706f2543Smrg ed->ledID= sli->id; 883706f2543Smrg ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 884706f2543Smrg ed->ledState= sli->effectiveState; 885706f2543Smrg ed->unsupported= 0; 886706f2543Smrg ed->supported= XkbXI_AllFeaturesMask; 887706f2543Smrg 888706f2543Smrg XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause); 889706f2543Smrg 890706f2543Smrg if (changes!=&my_changes) changes= NULL; 891706f2543Smrg if (ed!=&my_ed) ed= NULL; 892706f2543Smrg if (changes || ed) 893706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 894706f2543Smrg return; 895706f2543Smrg} 896706f2543Smrg 897706f2543Smrg/***====================================================================***/ 898706f2543Smrg 899706f2543Smrgvoid 900706f2543SmrgXkbApplyLedStateChanges(DeviceIntPtr dev, 901706f2543Smrg XkbSrvLedInfoPtr sli, 902706f2543Smrg unsigned changed_leds, 903706f2543Smrg xkbExtensionDeviceNotify * ed, 904706f2543Smrg XkbChangesPtr changes, 905706f2543Smrg XkbEventCausePtr cause) 906706f2543Smrg{ 907706f2543SmrgXkbSrvInfoPtr xkbi; 908706f2543SmrgDeviceIntPtr kbd; 909706f2543SmrgXkbChangesRec my_changes; 910706f2543SmrgxkbExtensionDeviceNotify my_ed; 911706f2543Smrgregister unsigned i,bit,affected; 912706f2543SmrgXkbIndicatorMapPtr map; 913706f2543Smrgunsigned oldState; 914706f2543SmrgBool kb_changed; 915706f2543Smrg 916706f2543Smrg if (changed_leds==0) 917706f2543Smrg return; 918706f2543Smrg if (dev->key && dev->key->xkbInfo) 919706f2543Smrg kbd= dev; 920706f2543Smrg else kbd= inputInfo.keyboard; 921706f2543Smrg xkbi= kbd->key->xkbInfo; 922706f2543Smrg 923706f2543Smrg if (changes==NULL) { 924706f2543Smrg changes= &my_changes; 925706f2543Smrg memset((char *)changes, 0, sizeof(XkbChangesRec)); 926706f2543Smrg } 927706f2543Smrg 928706f2543Smrg kb_changed= FALSE; 929706f2543Smrg affected= changed_leds; 930706f2543Smrg oldState= sli->effectiveState; 931706f2543Smrg for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) { 932706f2543Smrg if ((affected&bit)==0) 933706f2543Smrg continue; 934706f2543Smrg affected&= ~bit; 935706f2543Smrg map= &sli->maps[i]; 936706f2543Smrg if (map->flags&XkbIM_NoExplicit) { 937706f2543Smrg sli->explicitState&= ~bit; 938706f2543Smrg continue; 939706f2543Smrg } 940706f2543Smrg if (map->flags&XkbIM_LEDDrivesKB) { 941706f2543Smrg Bool on= ((sli->explicitState&bit)!=0); 942706f2543Smrg if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes)) 943706f2543Smrg kb_changed= TRUE; 944706f2543Smrg } 945706f2543Smrg } 946706f2543Smrg sli->effectiveState= (sli->autoState|sli->explicitState); 947706f2543Smrg affected= sli->effectiveState^oldState; 948706f2543Smrg 949706f2543Smrg if (ed==NULL) { 950706f2543Smrg ed= &my_ed; 951706f2543Smrg memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify)); 952706f2543Smrg } 953706f2543Smrg else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&& 954706f2543Smrg ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) { 955706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 956706f2543Smrg } 957706f2543Smrg 958706f2543Smrg if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) 959706f2543Smrg changes->indicators.state_changes|= affected; 960706f2543Smrg if (affected) { 961706f2543Smrg ed->reason|= XkbXI_IndicatorStateMask; 962706f2543Smrg ed->ledClass= sli->class; 963706f2543Smrg ed->ledID= sli->id; 964706f2543Smrg ed->ledsDefined= sli->namesPresent|sli->mapsPresent; 965706f2543Smrg ed->ledState= sli->effectiveState; 966706f2543Smrg ed->unsupported= 0; 967706f2543Smrg ed->supported= XkbXI_AllFeaturesMask; 968706f2543Smrg } 969706f2543Smrg 970706f2543Smrg if (kb_changed) { 971706f2543Smrg XkbComputeDerivedState(kbd->key->xkbInfo); 972706f2543Smrg XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause); 973706f2543Smrg } 974706f2543Smrg 975706f2543Smrg if (changes!=&my_changes) changes= NULL; 976706f2543Smrg if (ed!=&my_ed) ed= NULL; 977706f2543Smrg if (changes || ed) 978706f2543Smrg XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause); 979706f2543Smrg if (kb_changed) 980706f2543Smrg XkbUpdateAllDeviceIndicators(NULL,cause); 981706f2543Smrg return; 982706f2543Smrg} 983