First import
[xorg_rtime.git] / xorg-server-1.4 / xkb / xkbLEDs.c
blobd607d9066ffa461dbdbefea882fb738b0928b272
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 #define NEED_EVENTS 1
35 #include <X11/X.h>
36 #include <X11/Xproto.h>
37 #include "misc.h"
38 #include "inputstr.h"
40 #include <X11/extensions/XI.h>
41 #include <xkbsrv.h>
42 #include "xkb.h"
44 /***====================================================================***/
47 * unsigned
48 * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
50 * Given a keyboard and a set of state components that have changed,
51 * this function returns the indicators on the default keyboard
52 * feedback that might be affected. It also reports whether or not
53 * any extension devices might be affected in check_devs_rtrn.
56 unsigned
57 XkbIndicatorsToUpdate( DeviceIntPtr dev,
58 unsigned long state_changes,
59 Bool enable_changes)
61 register unsigned update= 0;
62 XkbSrvLedInfoPtr sli;
64 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
66 if (state_changes&(XkbModifierStateMask|XkbGroupStateMask))
67 update|= sli->usesEffective;
68 if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask))
69 update|= sli->usesBase;
70 if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask))
71 update|= sli->usesLatched;
72 if (state_changes&(XkbModifierLockMask|XkbGroupLockMask))
73 update|= sli->usesLocked;
74 if (state_changes&XkbCompatStateMask)
75 update|= sli->usesCompat;
76 if (enable_changes)
77 update|= sli->usesControls;
78 return update;
81 /***====================================================================***/
84 * Bool
85 *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
87 * Some indicators "drive" the keyboard when their state is explicitly
88 * changed, as described in section 9.2.1 of the XKB protocol spec.
89 * This function updates the state and controls for the keyboard
90 * specified by 'xkbi' to reflect any changes that are required
91 * when the indicator described by 'map' is turned on or off. The
92 * extent of the changes is reported in change, which must be defined.
94 static Bool
95 XkbApplyLEDChangeToKeyboard( XkbSrvInfoPtr xkbi,
96 XkbIndicatorMapPtr map,
97 Bool on,
98 XkbChangesPtr change)
100 Bool ctrlChange,stateChange;
101 XkbStatePtr state;
103 if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0))
104 return False;
105 ctrlChange= stateChange= False;
106 if (map->ctrls) {
107 XkbControlsPtr ctrls= xkbi->desc->ctrls;
108 unsigned old;
110 old= ctrls->enabled_ctrls;
111 if (on) ctrls->enabled_ctrls|= map->ctrls;
112 else ctrls->enabled_ctrls&= ~map->ctrls;
113 if (old!=ctrls->enabled_ctrls) {
114 change->ctrls.changed_ctrls= XkbControlsEnabledMask;
115 change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls;
116 ctrlChange= True;
119 state= &xkbi->state;
120 if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) {
121 register int i;
122 register unsigned bit,match;
124 if (on) match= (map->groups)&XkbAllGroupsMask;
125 else match= (~map->groups)&XkbAllGroupsMask;
126 if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) {
127 for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
128 if (bit&match)
129 break;
131 if (map->which_groups&XkbIM_UseLatched)
132 XkbLatchGroup(xkbi->device,0); /* unlatch group */
133 state->locked_group= i;
134 stateChange= True;
136 else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) {
137 for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
138 if (bit&match)
139 break;
141 state->locked_group= 0;
142 XkbLatchGroup(xkbi->device,i);
143 stateChange= True;
146 if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) {
147 if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) {
148 register unsigned long old;
149 old= state->locked_mods;
150 if (on) state->locked_mods|= map->mods.mask;
151 else state->locked_mods&= ~map->mods.mask;
152 if (state->locked_mods!=old)
153 stateChange= True;
155 if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) {
156 register unsigned long newmods;
157 newmods= state->latched_mods;
158 if (on) newmods|= map->mods.mask;
159 else newmods&= ~map->mods.mask;
160 if (newmods!=state->locked_mods) {
161 newmods&= map->mods.mask;
162 XkbLatchModifiers(xkbi->device,map->mods.mask,newmods);
163 stateChange= True;
167 return (stateChange || ctrlChange);
171 * Bool
172 * ComputeAutoState(map,state,ctrls)
174 * This function reports the effect of applying the specified
175 * indicator map given the specified state and controls, as
176 * described in section 9.2 of the XKB protocol specification.
179 static Bool
180 ComputeAutoState( XkbIndicatorMapPtr map,
181 XkbStatePtr state,
182 XkbControlsPtr ctrls)
184 Bool on;
185 CARD8 mods,group;
187 on= False;
188 mods= group= 0;
189 if (map->which_mods&XkbIM_UseAnyMods) {
190 if (map->which_mods&XkbIM_UseBase)
191 mods|= state->base_mods;
192 if (map->which_mods&XkbIM_UseLatched)
193 mods|= state->latched_mods;
194 if (map->which_mods&XkbIM_UseLocked)
195 mods|= state->locked_mods;
196 if (map->which_mods&XkbIM_UseEffective)
197 mods|= state->mods;
198 if (map->which_mods&XkbIM_UseCompat)
199 mods|= state->compat_state;
200 on = ((map->mods.mask&mods)!=0);
201 on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0));
203 if (map->which_groups&XkbIM_UseAnyGroup) {
204 if (map->which_groups&XkbIM_UseBase)
205 group|= (1L << state->base_group);
206 if (map->which_groups&XkbIM_UseLatched)
207 group|= (1L << state->latched_group);
208 if (map->which_groups&XkbIM_UseLocked)
209 group|= (1L << state->locked_group);
210 if (map->which_groups&XkbIM_UseEffective)
211 group|= (1L << state->group);
212 on = on||(((map->groups&group)!=0)||(map->groups==0));
214 if (map->ctrls)
215 on = on||(ctrls->enabled_ctrls&map->ctrls);
216 return on;
220 static void
221 XkbUpdateLedAutoState( DeviceIntPtr dev,
222 XkbSrvLedInfoPtr sli,
223 unsigned maps_to_check,
224 xkbExtensionDeviceNotify * ed,
225 XkbChangesPtr changes,
226 XkbEventCausePtr cause)
228 DeviceIntPtr kbd;
229 XkbStatePtr state;
230 XkbControlsPtr ctrls;
231 XkbChangesRec my_changes;
232 xkbExtensionDeviceNotify my_ed;
233 register unsigned i,bit,affected;
234 register XkbIndicatorMapPtr map;
235 unsigned oldState;
237 if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0))
238 return;
240 if (dev->key && dev->key->xkbInfo)
241 kbd= dev;
242 else kbd= (DeviceIntPtr)LookupKeyboardDevice();
244 state= &kbd->key->xkbInfo->state;
245 ctrls= kbd->key->xkbInfo->desc->ctrls;
246 affected= maps_to_check;
247 oldState= sli->effectiveState;
248 sli->autoState&= ~affected;
249 for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
250 if ((affected&bit)==0)
251 continue;
252 affected&= ~bit;
253 map= &sli->maps[i];
254 if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls))
255 sli->autoState|= bit;
257 sli->effectiveState= (sli->autoState|sli->explicitState);
258 affected= sli->effectiveState^oldState;
259 if (affected==0)
260 return;
262 if (ed==NULL) {
263 ed= &my_ed;
264 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
266 else if ((ed->reason&XkbXI_IndicatorsMask)&&
267 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
268 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
271 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
272 if (changes==NULL) {
273 changes= &my_changes;
274 bzero((char *)changes,sizeof(XkbChangesRec));
276 changes->indicators.state_changes|= affected;
279 ed->reason|= XkbXI_IndicatorStateMask;
280 ed->ledClass= sli->class;
281 ed->ledID= sli->id;
282 ed->ledsDefined= sli->namesPresent|sli->mapsPresent;
283 ed->ledState= sli->effectiveState;
284 ed->unsupported|= XkbXI_IndicatorStateMask;
285 ed->supported= XkbXI_AllFeaturesMask;
287 if (changes!=&my_changes) changes= NULL;
288 if (ed!=&my_ed) ed= NULL;
289 if (changes || ed)
290 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
291 return;
294 static void
295 XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause)
297 DeviceIntPtr edev;
298 XkbSrvLedInfoPtr sli;
300 for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) {
301 if (edev->kbdfeed) {
302 KbdFeedbackPtr kf;
303 for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) {
304 if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL))
305 continue;
306 sli= kf->xkb_sli;
307 XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
308 changes,cause);
312 if (edev->leds) {
313 LedFeedbackPtr lf;
314 for (lf=edev->leds;lf!=NULL;lf=lf->next) {
315 if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL))
316 continue;
317 sli= lf->xkb_sli;
318 XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
319 changes,cause);
324 return;
328 /***====================================================================***/
331 * void
332 * XkbSetIndicators(dev,affect,values,cause)
334 * Attempts to change the indicators specified in 'affect' to the
335 * states specified in 'values' for the default keyboard feedback
336 * on the keyboard specified by 'dev.' Attempts to change indicator
337 * state might be ignored or have no affect, depending on the XKB
338 * indicator map for any affected indicators, as described in section
339 * 9.2 of the XKB protocol specification.
341 * If 'changes' is non-NULL, this function notes any changes to the
342 * keyboard state, controls, or indicator state that result from this
343 * attempted change. If 'changes' is NULL, this function generates
344 * XKB events to report any such changes to interested clients.
346 * If 'cause' is non-NULL, it specifies the reason for the change,
347 * as reported in some XKB events. If it is NULL, this function
348 * assumes that the change is the result of a core protocol
349 * ChangeKeyboardMapping request.
352 void
353 XkbSetIndicators( DeviceIntPtr dev,
354 CARD32 affect,
355 CARD32 values,
356 XkbEventCausePtr cause)
358 XkbSrvLedInfoPtr sli;
359 XkbChangesRec changes;
360 xkbExtensionDeviceNotify ed;
361 unsigned side_affected;
363 bzero((char *)&changes,sizeof(XkbChangesRec));
364 bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
365 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
366 sli->explicitState&= ~affect;
367 sli->explicitState|= (affect&values);
368 XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause);
370 side_affected= 0;
371 if (changes.state_changes!=0)
372 side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False);
373 if (changes.ctrls.enabled_ctrls_changes)
374 side_affected|= sli->usesControls;
376 if (side_affected) {
377 XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause);
378 affect|= side_affected;
380 if (changes.state_changes || changes.ctrls.enabled_ctrls_changes)
381 XkbUpdateAllDeviceIndicators(NULL,cause);
383 XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause);
384 return;
387 /***====================================================================***/
389 /***====================================================================***/
392 * void
393 * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
395 * Applies the indicator maps for any indicators specified in
396 * 'update' from the default keyboard feedback on the device
397 * specified by 'dev.'
399 * If 'changes' is NULL, this function generates and XKB events
400 * required to report the necessary changes, otherwise it simply
401 * notes the indicators with changed state.
403 * If 'check_edevs' is True, this function also checks the indicator
404 * maps for any open extension devices that have them, and updates
405 * the state of any extension device indicators as necessary.
408 void
409 XkbUpdateIndicators( DeviceIntPtr dev,
410 register CARD32 update,
411 Bool check_edevs,
412 XkbChangesPtr changes,
413 XkbEventCausePtr cause)
415 XkbSrvLedInfoPtr sli;
417 sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
418 XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause);
419 if (check_edevs)
420 XkbUpdateAllDeviceIndicators(changes,cause);
421 return;
424 /***====================================================================***/
426 /***====================================================================***/
429 * void
430 * XkbCheckIndicatorMaps(dev,sli,which)
432 * Updates the 'indicator accelerators' for the indicators specified
433 * by 'which' in the feedback specified by 'sli.' The indicator
434 * accelerators are internal to the server and are used to simplify
435 * and speed up the process of figuring out which indicators might
436 * be affected by a particular change in keyboard state or controls.
439 void
440 XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which)
442 register unsigned i,bit;
443 XkbIndicatorMapPtr map;
444 XkbDescPtr xkb;
446 if ((sli->flags&XkbSLI_HasOwnState)==0)
447 dev= (DeviceIntPtr)LookupKeyboardDevice();
449 sli->usesBase&= ~which;
450 sli->usesLatched&= ~which;
451 sli->usesLocked&= ~which;
452 sli->usesEffective&= ~which;
453 sli->usesCompat&= ~which;
454 sli->usesControls&= ~which;
455 sli->mapsPresent&= ~which;
457 xkb= dev->key->xkbInfo->desc;
458 for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) {
459 if (which&bit) {
460 CARD8 what;
462 if (!XkbIM_InUse(map))
463 continue;
464 sli->mapsPresent|= bit;
466 what= (map->which_mods|map->which_groups);
467 if (what&XkbIM_UseBase)
468 sli->usesBase|= bit;
469 if (what&XkbIM_UseLatched)
470 sli->usesLatched|= bit;
471 if (what&XkbIM_UseLocked)
472 sli->usesLocked|= bit;
473 if (what&XkbIM_UseEffective)
474 sli->usesEffective|= bit;
475 if (what&XkbIM_UseCompat)
476 sli->usesCompat|= bit;
477 if (map->ctrls)
478 sli->usesControls|= bit;
480 map->mods.mask= map->mods.real_mods;
481 if (map->mods.vmods!=0) {
482 map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods);
486 sli->usedComponents= 0;
487 if (sli->usesBase)
488 sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask;
489 if (sli->usesLatched)
490 sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask;
491 if (sli->usesLocked)
492 sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask;
493 if (sli->usesEffective)
494 sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask;
495 if (sli->usesCompat)
496 sli->usedComponents|= XkbCompatStateMask;
497 return;
500 /***====================================================================***/
503 * XkbSrvLedInfoPtr
504 * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
506 * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
507 * 'kf' or 'lf' on the keyboard specified by 'dev.'
509 * If 'needed_parts' is non-zero, this function makes sure that any
510 * of the parts speicified therein are allocated.
512 XkbSrvLedInfoPtr
513 XkbAllocSrvLedInfo( DeviceIntPtr dev,
514 KbdFeedbackPtr kf,
515 LedFeedbackPtr lf,
516 unsigned needed_parts)
518 XkbSrvLedInfoPtr sli;
519 Bool checkAccel;
520 Bool checkNames;
522 sli= NULL;
523 checkAccel= checkNames= False;
524 if ((kf!=NULL)&&(kf->xkb_sli==NULL)) {
525 kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec);
526 if (sli==NULL)
527 return NULL; /* ALLOCATION ERROR */
528 if (dev->key && dev->key->xkbInfo)
529 sli->flags= XkbSLI_HasOwnState;
530 else sli->flags= 0;
531 sli->class= KbdFeedbackClass;
532 sli->id= kf->ctrl.id;
533 sli->fb.kf= kf;
535 sli->autoState= 0;
536 sli->explicitState= kf->ctrl.leds;
537 sli->effectiveState= kf->ctrl.leds;
539 if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) {
540 XkbDescPtr xkb;
541 xkb= dev->key->xkbInfo->desc;
542 sli->flags|= XkbSLI_IsDefault;
543 sli->physIndicators= xkb->indicators->phys_indicators;
544 sli->names= xkb->names->indicators;
545 sli->maps= xkb->indicators->maps;
546 checkNames= checkAccel= True;
548 else {
549 sli->physIndicators= XkbAllIndicatorsMask;
550 sli->names= NULL;
551 sli->maps= NULL;
554 else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) {
555 XkbDescPtr xkb;
556 xkb= dev->key->xkbInfo->desc;
557 sli->physIndicators= xkb->indicators->phys_indicators;
558 if (xkb->names->indicators!=sli->names) {
559 checkNames= True;
560 sli->names= xkb->names->indicators;
562 if (xkb->indicators->maps!=sli->maps) {
563 checkAccel= True;
564 sli->maps= xkb->indicators->maps;
567 else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) {
568 lf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec);
569 if (sli==NULL)
570 return NULL; /* ALLOCATION ERROR */
571 if (dev->key && dev->key->xkbInfo)
572 sli->flags= XkbSLI_HasOwnState;
573 else sli->flags= 0;
574 sli->class= LedFeedbackClass;
575 sli->id= lf->ctrl.id;
576 sli->fb.lf= lf;
578 sli->physIndicators= lf->ctrl.led_mask;
579 sli->autoState= 0;
580 sli->explicitState= lf->ctrl.led_values;
581 sli->effectiveState= lf->ctrl.led_values;
582 sli->maps= NULL;
583 sli->names= NULL;
585 if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
586 sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
587 if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
588 sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
589 if (checkNames) {
590 register unsigned i,bit;
591 sli->namesPresent= 0;
592 for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
593 if (sli->names[i]!=None)
594 sli->namesPresent|= bit;
597 if (checkAccel)
598 XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask);
599 return sli;
602 void
603 XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
605 if ((sli->flags&XkbSLI_IsDefault)==0) {
606 if (sli->maps) _XkbFree(sli->maps);
607 if (sli->names) _XkbFree(sli->names);
609 sli->maps= NULL;
610 sli->names= NULL;
611 _XkbFree(sli);
612 return;
616 /***====================================================================***/
619 * XkbSrvLedInfoPtr
620 * XkbFindSrvLedInfo(dev,class,id,needed_parts)
622 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
623 * on the device specified by 'dev.' If the class and id specify
624 * a valid device feedback, this function returns the existing
625 * feedback or allocates a new one.
629 XkbSrvLedInfoPtr
630 XkbFindSrvLedInfo( DeviceIntPtr dev,
631 unsigned class,
632 unsigned id,
633 unsigned needed_parts)
635 XkbSrvLedInfoPtr sli;
637 /* optimization to check for most common case */
638 if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) {
639 XkbSrvLedInfoPtr sli;
640 sli= dev->kbdfeed->xkb_sli;
641 if (dev->kbdfeed->xkb_sli==NULL) {
642 sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts);
643 dev->kbdfeed->xkb_sli= sli;
645 return dev->kbdfeed->xkb_sli;
648 sli= NULL;
649 if (class==XkbDfltXIClass) {
650 if (dev->kbdfeed) class= KbdFeedbackClass;
651 else if (dev->leds) class= LedFeedbackClass;
652 else return NULL;
654 if (class==KbdFeedbackClass) {
655 KbdFeedbackPtr kf;
656 for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) {
657 if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) {
658 if (kf->xkb_sli==NULL)
659 kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts);
660 sli= kf->xkb_sli;
661 break;
665 else if (class==LedFeedbackClass) {
666 LedFeedbackPtr lf;
667 for (lf=dev->leds;lf!=NULL;lf=lf->next) {
668 if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) {
669 if (lf->xkb_sli==NULL)
670 lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts);
671 sli= lf->xkb_sli;
672 break;
676 if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
677 sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
678 if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
679 sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
680 return sli;
683 /***====================================================================***/
685 void
686 XkbFlushLedEvents( DeviceIntPtr dev,
687 DeviceIntPtr kbd,
688 XkbSrvLedInfoPtr sli,
689 xkbExtensionDeviceNotify * ed,
690 XkbChangesPtr changes,
691 XkbEventCausePtr cause)
693 if (changes) {
694 if (changes->indicators.state_changes)
695 XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
696 XkbSendNotification(kbd,changes,cause);
697 bzero((char *)changes,sizeof(XkbChangesRec));
699 if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
700 if (sli->effectiveState)
701 /* it appears that the which parameter is not used */
702 XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
703 else
704 XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
707 if (ed && (ed->reason)) {
708 if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask))
709 XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
710 XkbSendExtensionDeviceNotify(dev,cause->client,ed);
712 bzero((char *)ed,sizeof(XkbExtensionDeviceNotify));
713 return;
716 /***====================================================================***/
718 void
719 XkbApplyLedNameChanges( DeviceIntPtr dev,
720 XkbSrvLedInfoPtr sli,
721 unsigned changed_names,
722 xkbExtensionDeviceNotify * ed,
723 XkbChangesPtr changes,
724 XkbEventCausePtr cause)
726 DeviceIntPtr kbd;
727 XkbChangesRec my_changes;
728 xkbExtensionDeviceNotify my_ed;
730 if (changed_names==0)
731 return;
732 if (dev->key && dev->key->xkbInfo)
733 kbd= dev;
734 else kbd= (DeviceIntPtr)LookupKeyboardDevice();
736 if (ed==NULL) {
737 ed= &my_ed;
738 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
740 else if ((ed->reason&XkbXI_IndicatorsMask)&&
741 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
742 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
745 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
746 if (changes==NULL) {
747 changes= &my_changes;
748 bzero((char *)changes,sizeof(XkbChangesRec));
750 changes->names.changed|= XkbIndicatorNamesMask;
751 changes->names.changed_indicators|= changed_names;
754 ed->reason|= XkbXI_IndicatorNamesMask;
755 ed->ledClass= sli->class;
756 ed->ledID= sli->id;
757 ed->ledsDefined= sli->namesPresent|sli->mapsPresent;
758 ed->ledState= sli->effectiveState;
759 ed->unsupported= 0;
760 ed->supported= XkbXI_AllFeaturesMask;
762 if (changes!=&my_changes) changes= NULL;
763 if (ed!=&my_ed) ed= NULL;
764 if (changes || ed)
765 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
766 return;
768 /***====================================================================***/
771 * void
772 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
774 * Handles all of the secondary effects of the changes to the
775 * feedback specified by 'sli' on the device specified by 'dev.'
777 * If 'changed_maps' specifies any indicators, this function generates
778 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
779 * events to report the changes, and recalculates the effective
780 * state of each indicator with a changed map. If any indicators
781 * change state, the server generates XkbExtensionDeviceNotify and
782 * XkbIndicatorStateNotify events as appropriate.
784 * If 'changes' is non-NULL, this function updates it to reflect
785 * any changes to the keyboard state or controls or to the 'core'
786 * indicator names, maps, or state. If 'changes' is NULL, this
787 * function generates XKB events as needed to report the changes.
788 * If 'dev' is not a keyboard device, any changes are reported
789 * for the core keyboard.
791 * The 'cause' specifies the reason for the event (key event or
792 * request) for the change, as reported in some XKB events.
795 void
796 XkbApplyLedMapChanges( DeviceIntPtr dev,
797 XkbSrvLedInfoPtr sli,
798 unsigned changed_maps,
799 xkbExtensionDeviceNotify * ed,
800 XkbChangesPtr changes,
801 XkbEventCausePtr cause)
803 DeviceIntPtr kbd;
804 XkbChangesRec my_changes;
805 xkbExtensionDeviceNotify my_ed;
807 if (changed_maps==0)
808 return;
809 if (dev->key && dev->key->xkbInfo)
810 kbd= dev;
811 else kbd= (DeviceIntPtr)LookupKeyboardDevice();
813 if (ed==NULL) {
814 ed= &my_ed;
815 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
817 else if ((ed->reason&XkbXI_IndicatorsMask)&&
818 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
819 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
822 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
823 if (changes==NULL) {
824 changes= &my_changes;
825 bzero((char *)changes,sizeof(XkbChangesRec));
827 changes->indicators.map_changes|= changed_maps;
830 XkbCheckIndicatorMaps(dev,sli,changed_maps);
832 ed->reason|= XkbXI_IndicatorMapsMask;
833 ed->ledClass= sli->class;
834 ed->ledID= sli->id;
835 ed->ledsDefined= sli->namesPresent|sli->mapsPresent;
836 ed->ledState= sli->effectiveState;
837 ed->unsupported|= XkbXI_IndicatorMapsMask;
838 ed->supported= XkbXI_AllFeaturesMask;
840 XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause);
842 if (changes!=&my_changes) changes= NULL;
843 if (ed!=&my_ed) ed= NULL;
844 if (changes || ed)
845 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
846 return;
849 /***====================================================================***/
851 void
852 XkbApplyLedStateChanges(DeviceIntPtr dev,
853 XkbSrvLedInfoPtr sli,
854 unsigned changed_leds,
855 xkbExtensionDeviceNotify * ed,
856 XkbChangesPtr changes,
857 XkbEventCausePtr cause)
859 XkbSrvInfoPtr xkbi;
860 DeviceIntPtr kbd;
861 XkbChangesRec my_changes;
862 xkbExtensionDeviceNotify my_ed;
863 register unsigned i,bit,affected;
864 XkbIndicatorMapPtr map;
865 unsigned oldState;
866 Bool kb_changed;
868 if (changed_leds==0)
869 return;
870 if (dev->key && dev->key->xkbInfo)
871 kbd= dev;
872 else kbd= (DeviceIntPtr)LookupKeyboardDevice();
873 xkbi= kbd->key->xkbInfo;
875 if (changes==NULL) {
876 changes= &my_changes;
877 bzero((char *)changes,sizeof(XkbChangesRec));
880 kb_changed= False;
881 affected= changed_leds;
882 oldState= sli->effectiveState;
883 for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
884 if ((affected&bit)==0)
885 continue;
886 affected&= ~bit;
887 map= &sli->maps[i];
888 if (map->flags&XkbIM_NoExplicit) {
889 sli->explicitState&= ~bit;
890 continue;
892 if (map->flags&XkbIM_LEDDrivesKB) {
893 Bool on= ((sli->explicitState&bit)!=0);
894 if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes))
895 kb_changed= True;
898 sli->effectiveState= (sli->autoState|sli->explicitState);
899 affected= sli->effectiveState^oldState;
901 if (ed==NULL) {
902 ed= &my_ed;
903 bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
905 else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&&
906 ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
907 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
910 if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault))
911 changes->indicators.state_changes|= affected;
912 if (affected) {
913 ed->reason|= XkbXI_IndicatorStateMask;
914 ed->ledClass= sli->class;
915 ed->ledID= sli->id;
916 ed->ledsDefined= sli->namesPresent|sli->mapsPresent;
917 ed->ledState= sli->effectiveState;
918 ed->unsupported|= XkbXI_IndicatorStateMask;
919 ed->supported= XkbXI_AllFeaturesMask;
922 if (kb_changed) {
923 XkbComputeDerivedState(kbd->key->xkbInfo);
924 XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause);
927 if (changes!=&my_changes) changes= NULL;
928 if (ed!=&my_ed) ed= NULL;
929 if (changes || ed)
930 XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
931 if (kb_changed)
932 XkbUpdateAllDeviceIndicators(NULL,cause);
933 return;