]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/xserver.git/blob - xkb/xkbLEDs.c
Imported Upstream version 1.11.4
[glsdk/xserver.git] / xkb / xkbLEDs.c
1 /************************************************************
2 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be 
10 used in advertising or publicity pertaining to distribution 
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability 
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
29 #endif
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"
39 #include <X11/extensions/XI.h>
40 #include <xkbsrv.h>
41 #include "xkb.h"
43 /***====================================================================***/
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          */
55 unsigned
56 XkbIndicatorsToUpdate(  DeviceIntPtr    dev,
57                         unsigned long   state_changes,
58                         Bool            enable_changes)
59 {
60 register unsigned       update= 0;
61 XkbSrvLedInfoPtr        sli;
63     sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
65     if (!sli)
66         return update;
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 }
83 /***====================================================================***/
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          */
96 static Bool
97 XkbApplyLEDChangeToKeyboard(    XkbSrvInfoPtr           xkbi,
98                                 XkbIndicatorMapPtr      map,
99                                 Bool                    on,
100                                 XkbChangesPtr           change)
102 Bool            ctrlChange,stateChange;
103 XkbStatePtr     state;
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;
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;
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;
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          */
181 static Bool
182 ComputeAutoState(       XkbIndicatorMapPtr      map,
183                         XkbStatePtr             state,
184                         XkbControlsPtr          ctrls)
186 Bool                    on;
187 CARD8                   mods,group;
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;
222 static void
223 XkbUpdateLedAutoState(  DeviceIntPtr                    dev,
224                         XkbSrvLedInfoPtr                sli,
225                         unsigned                        maps_to_check,
226                         xkbExtensionDeviceNotify *      ed,
227                         XkbChangesPtr                   changes,
228                         XkbEventCausePtr                cause)
230 DeviceIntPtr                    kbd;
231 XkbStatePtr                     state;
232 XkbControlsPtr                  ctrls;
233 XkbChangesRec                   my_changes;
234 xkbExtensionDeviceNotify        my_ed;
235 register unsigned               i,bit,affected;
236 register XkbIndicatorMapPtr     map;
237 unsigned                        oldState;
239     if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0))
240         return;
242     if (dev->key && dev->key->xkbInfo)
243          kbd= dev;
244     else kbd= inputInfo.keyboard;
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;
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     }
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     }
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;
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;
296 static void
297 XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause)
299 DeviceIntPtr            edev;
300 XkbSrvLedInfoPtr        sli;
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;
330 /***====================================================================***/
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          */
354 void
355 XkbSetIndicators(       DeviceIntPtr            dev,
356                         CARD32                  affect,
357                         CARD32                  values,
358                         XkbEventCausePtr        cause)
360 XkbSrvLedInfoPtr                sli;
361 XkbChangesRec                   changes;
362 xkbExtensionDeviceNotify        ed;
363 unsigned                        side_affected;
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);
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;
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);
385     XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause);
386     return;
389 /***====================================================================***/
391 /***====================================================================***/
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          */
410 void
411 XkbUpdateIndicators(    DeviceIntPtr            dev,
412                         register CARD32         update,
413                         Bool                    check_edevs,
414                         XkbChangesPtr           changes,
415                         XkbEventCausePtr        cause)
417 XkbSrvLedInfoPtr        sli;
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;
426 /***====================================================================***/
428 /***====================================================================***/
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          */
441 void
442 XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which)
444 register unsigned       i,bit;
445 XkbIndicatorMapPtr      map;
446 XkbDescPtr              xkb;
448     if ((sli->flags&XkbSLI_HasOwnState)==0)
449         return;
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;
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;
464             if (!map || !XkbIM_InUse(map))
465                 continue;
466             sli->mapsPresent|= bit;
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;
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;
502 /***====================================================================***/
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          */
514 XkbSrvLedInfoPtr
515 XkbAllocSrvLedInfo(     DeviceIntPtr            dev,
516                         KbdFeedbackPtr          kf,
517                         LedFeedbackPtr          lf,
518                         unsigned                needed_parts)
520 XkbSrvLedInfoPtr        sli;
521 Bool                    checkAccel;
522 Bool                    checkNames;
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;
537         sli->autoState=         0;
538         sli->explicitState=     kf->ctrl.leds;
539         sli->effectiveState=    kf->ctrl.leds;
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;
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;
607 void
608 XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
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;
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  */
628 XkbSrvLedInfoPtr
629 XkbCopySrvLedInfo(      DeviceIntPtr            from,
630                         XkbSrvLedInfoPtr        src,
631                         KbdFeedbackPtr          kf,
632                         LedFeedbackPtr          lf)
634     XkbSrvLedInfoPtr sli_new = NULL;
636     if (!src)
637         goto finish;
639     sli_new = calloc(1, sizeof( XkbSrvLedInfoRec));
640     if (!sli_new)
641         goto finish;
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;
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; */
656 finish:
657     return sli_new;
660 /***====================================================================***/
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          */
673 XkbSrvLedInfoPtr
674 XkbFindSrvLedInfo(      DeviceIntPtr            dev,
675                         unsigned                class,
676                         unsigned                id,
677                         unsigned                needed_parts)
679 XkbSrvLedInfoPtr        sli;
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     }
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;
729 /***====================================================================***/
731 void
732 XkbFlushLedEvents(      DeviceIntPtr                    dev,
733                         DeviceIntPtr                    kbd,
734                         XkbSrvLedInfoPtr                sli,
735                         xkbExtensionDeviceNotify *      ed,
736                         XkbChangesPtr                   changes,
737                         XkbEventCausePtr                cause)
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));
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;
764 /***====================================================================***/
766 void
767 XkbApplyLedNameChanges( DeviceIntPtr                    dev,
768                         XkbSrvLedInfoPtr                sli,
769                         unsigned                        changed_names,
770                         xkbExtensionDeviceNotify *      ed,
771                         XkbChangesPtr                   changes,
772                         XkbEventCausePtr                cause)
774 DeviceIntPtr                    kbd;
775 XkbChangesRec                   my_changes;
776 xkbExtensionDeviceNotify        my_ed;
778     if (changed_names==0)
779         return;
780     if (dev->key && dev->key->xkbInfo)
781          kbd= dev;
782     else kbd= inputInfo.keyboard;
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     }
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     }
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;
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;
816 /***====================================================================***/
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          */
843 void
844 XkbApplyLedMapChanges(  DeviceIntPtr                    dev,
845                         XkbSrvLedInfoPtr                sli,
846                         unsigned                        changed_maps,
847                         xkbExtensionDeviceNotify *      ed,
848                         XkbChangesPtr                   changes,
849                         XkbEventCausePtr                cause)
851 DeviceIntPtr                    kbd;
852 XkbChangesRec                   my_changes;
853 xkbExtensionDeviceNotify        my_ed;
855     if (changed_maps==0)
856         return;
857     if (dev->key && dev->key->xkbInfo)
858          kbd= dev;
859     else kbd= inputInfo.keyboard;
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     }
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     }
878     XkbCheckIndicatorMaps(dev,sli,changed_maps);
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;
888     XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause);
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;
897 /***====================================================================***/
899 void
900 XkbApplyLedStateChanges(DeviceIntPtr                    dev,
901                         XkbSrvLedInfoPtr                sli,
902                         unsigned                        changed_leds,
903                         xkbExtensionDeviceNotify *      ed,
904                         XkbChangesPtr                   changes,
905                         XkbEventCausePtr                cause)
907 XkbSrvInfoPtr                   xkbi;
908 DeviceIntPtr                    kbd;
909 XkbChangesRec                   my_changes;
910 xkbExtensionDeviceNotify        my_ed;
911 register unsigned               i,bit,affected;
912 XkbIndicatorMapPtr              map;
913 unsigned                        oldState;
914 Bool                            kb_changed;
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;
923     if (changes==NULL) {
924         changes= &my_changes;
925         memset((char *)changes, 0, sizeof(XkbChangesRec));
926     }
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;
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     }
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     }
970     if (kb_changed) {
971         XkbComputeDerivedState(kbd->key->xkbInfo);
972         XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause);
973     }
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;