xkbLEDs.c revision 6747b715
105b261ecSmrg/************************************************************
205b261ecSmrgCopyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
305b261ecSmrg
405b261ecSmrgPermission to use, copy, modify, and distribute this
505b261ecSmrgsoftware and its documentation for any purpose and without
605b261ecSmrgfee is hereby granted, provided that the above copyright
705b261ecSmrgnotice appear in all copies and that both that copyright
805b261ecSmrgnotice and this permission notice appear in supporting
905b261ecSmrgdocumentation, and that the name of Silicon Graphics not be
1005b261ecSmrgused in advertising or publicity pertaining to distribution
1105b261ecSmrgof the software without specific prior written permission.
1205b261ecSmrgSilicon Graphics makes no representation about the suitability
1305b261ecSmrgof this software for any purpose. It is provided "as is"
1405b261ecSmrgwithout any express or implied warranty.
1505b261ecSmrg
1605b261ecSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
1705b261ecSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
1905b261ecSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
2005b261ecSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
2105b261ecSmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2205b261ecSmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
2305b261ecSmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2805b261ecSmrg#include <dix-config.h>
2905b261ecSmrg#endif
3005b261ecSmrg
3105b261ecSmrg#include <stdio.h>
3205b261ecSmrg#include <ctype.h>
3305b261ecSmrg#include <math.h>
3405b261ecSmrg#include <X11/X.h>
3505b261ecSmrg#include <X11/Xproto.h>
3605b261ecSmrg#include "misc.h"
3705b261ecSmrg#include "inputstr.h"
3805b261ecSmrg
3905b261ecSmrg#include <X11/extensions/XI.h>
4005b261ecSmrg#include <xkbsrv.h>
4105b261ecSmrg#include "xkb.h"
4205b261ecSmrg
4305b261ecSmrg/***====================================================================***/
4405b261ecSmrg
4505b261ecSmrg	/*
4605b261ecSmrg	 * unsigned
4705b261ecSmrg	 * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
4805b261ecSmrg	 *
4905b261ecSmrg	 * Given a keyboard and a set of state components that have changed,
5005b261ecSmrg	 * this function returns the indicators on the default keyboard
5105b261ecSmrg	 * feedback that might be affected.   It also reports whether or not
5205b261ecSmrg	 * any extension devices might be affected in check_devs_rtrn.
5305b261ecSmrg	 */
5405b261ecSmrg
5505b261ecSmrgunsigned
5605b261ecSmrgXkbIndicatorsToUpdate(	DeviceIntPtr	dev,
5705b261ecSmrg			unsigned long 	state_changes,
5805b261ecSmrg			Bool		enable_changes)
5905b261ecSmrg{
6005b261ecSmrgregister unsigned	update=	0;
6105b261ecSmrgXkbSrvLedInfoPtr	sli;
6205b261ecSmrg
6305b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
6405b261ecSmrg
6505b261ecSmrg    if (!sli)
6605b261ecSmrg        return update;
6705b261ecSmrg
6805b261ecSmrg    if (state_changes&(XkbModifierStateMask|XkbGroupStateMask))
6905b261ecSmrg	update|= sli->usesEffective;
7005b261ecSmrg    if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask))
7105b261ecSmrg	update|= sli->usesBase;
7205b261ecSmrg    if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask))
7305b261ecSmrg	update|= sli->usesLatched;
7405b261ecSmrg    if (state_changes&(XkbModifierLockMask|XkbGroupLockMask))
7505b261ecSmrg	update|= sli->usesLocked;
7605b261ecSmrg    if (state_changes&XkbCompatStateMask)
7705b261ecSmrg	update|= sli->usesCompat;
7805b261ecSmrg    if (enable_changes)
7905b261ecSmrg	update|= sli->usesControls;
8005b261ecSmrg    return update;
8105b261ecSmrg}
8205b261ecSmrg
8305b261ecSmrg/***====================================================================***/
8405b261ecSmrg
8505b261ecSmrg	/*
8605b261ecSmrg	 * Bool
8705b261ecSmrg	 *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
8805b261ecSmrg	 *
8905b261ecSmrg	 * Some indicators "drive" the keyboard when their state is explicitly
9005b261ecSmrg	 * changed, as described in section 9.2.1 of the XKB protocol spec.
9105b261ecSmrg	 * This function updates the state and controls for the keyboard
9205b261ecSmrg	 * specified by 'xkbi' to reflect any changes that are required
9305b261ecSmrg	 * when the indicator described by 'map' is turned on or off.  The
9405b261ecSmrg	 * extent of the changes is reported in change, which must be defined.
9505b261ecSmrg	 */
9605b261ecSmrgstatic Bool
9705b261ecSmrgXkbApplyLEDChangeToKeyboard(	XkbSrvInfoPtr		xkbi,
9805b261ecSmrg				XkbIndicatorMapPtr	map,
9905b261ecSmrg				Bool			on,
10005b261ecSmrg				XkbChangesPtr		change)
10105b261ecSmrg{
10205b261ecSmrgBool		ctrlChange,stateChange;
10305b261ecSmrgXkbStatePtr	state;
10405b261ecSmrg
10505b261ecSmrg    if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0))
1066747b715Smrg	return FALSE;
1076747b715Smrg    ctrlChange= stateChange= FALSE;
10805b261ecSmrg    if (map->ctrls) {
10905b261ecSmrg	XkbControlsPtr	ctrls= xkbi->desc->ctrls;
11005b261ecSmrg	unsigned 	old;
11105b261ecSmrg
11205b261ecSmrg	old= ctrls->enabled_ctrls;
11305b261ecSmrg	if (on)	ctrls->enabled_ctrls|= map->ctrls;
11405b261ecSmrg	else	ctrls->enabled_ctrls&= ~map->ctrls;
11505b261ecSmrg	if (old!=ctrls->enabled_ctrls) {
11605b261ecSmrg	    change->ctrls.changed_ctrls= XkbControlsEnabledMask;
11705b261ecSmrg	    change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls;
1186747b715Smrg	    ctrlChange= TRUE;
11905b261ecSmrg	}
12005b261ecSmrg    }
12105b261ecSmrg    state= &xkbi->state;
12205b261ecSmrg    if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) {
12305b261ecSmrg	register int i;
12405b261ecSmrg	register unsigned bit,match;
12505b261ecSmrg
12605b261ecSmrg	if (on)	match= (map->groups)&XkbAllGroupsMask;
12705b261ecSmrg	else 	match= (~map->groups)&XkbAllGroupsMask;
12805b261ecSmrg	if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) {
12905b261ecSmrg	    for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
13005b261ecSmrg		if (bit&match)
13105b261ecSmrg		    break;
13205b261ecSmrg	    }
13305b261ecSmrg	    if (map->which_groups&XkbIM_UseLatched)
13405b261ecSmrg		XkbLatchGroup(xkbi->device,0); /* unlatch group */
13505b261ecSmrg	    state->locked_group= i;
1366747b715Smrg	    stateChange= TRUE;
13705b261ecSmrg	}
13805b261ecSmrg	else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) {
13905b261ecSmrg	    for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
14005b261ecSmrg		if (bit&match)
14105b261ecSmrg		    break;
14205b261ecSmrg	    }
14305b261ecSmrg	    state->locked_group= 0;
14405b261ecSmrg	    XkbLatchGroup(xkbi->device,i);
1456747b715Smrg	    stateChange= TRUE;
14605b261ecSmrg	}
14705b261ecSmrg    }
14805b261ecSmrg    if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) {
14905b261ecSmrg	if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) {
15005b261ecSmrg	    register unsigned long old;
15105b261ecSmrg	    old= state->locked_mods;
15205b261ecSmrg	    if (on)	state->locked_mods|= map->mods.mask;
15305b261ecSmrg	    else	state->locked_mods&= ~map->mods.mask;
15405b261ecSmrg	    if (state->locked_mods!=old)
1556747b715Smrg		stateChange= TRUE;
15605b261ecSmrg	}
15705b261ecSmrg	if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) {
15805b261ecSmrg	    register unsigned long newmods;
15905b261ecSmrg	    newmods= state->latched_mods;
16005b261ecSmrg	    if (on)	newmods|=  map->mods.mask;
16105b261ecSmrg	    else	newmods&= ~map->mods.mask;
16205b261ecSmrg	    if (newmods!=state->locked_mods) {
16305b261ecSmrg		newmods&= map->mods.mask;
16405b261ecSmrg		XkbLatchModifiers(xkbi->device,map->mods.mask,newmods);
1656747b715Smrg		stateChange= TRUE;
16605b261ecSmrg	    }
16705b261ecSmrg	}
16805b261ecSmrg    }
1696747b715Smrg    return stateChange || ctrlChange;
17005b261ecSmrg}
17105b261ecSmrg
17205b261ecSmrg	/*
17305b261ecSmrg	 * Bool
17405b261ecSmrg	 * ComputeAutoState(map,state,ctrls)
17505b261ecSmrg	 *
17605b261ecSmrg	 * This function reports the effect of applying the specified
17705b261ecSmrg	 * indicator map given the specified state and controls, as
17805b261ecSmrg	 * described in section 9.2 of the XKB protocol specification.
17905b261ecSmrg	 */
18005b261ecSmrg
18105b261ecSmrgstatic Bool
18205b261ecSmrgComputeAutoState(	XkbIndicatorMapPtr	map,
18305b261ecSmrg			XkbStatePtr 		state,
18405b261ecSmrg			XkbControlsPtr 		ctrls)
18505b261ecSmrg{
18605b261ecSmrgBool 			on;
18705b261ecSmrgCARD8 			mods,group;
18805b261ecSmrg
1896747b715Smrg    on= FALSE;
19005b261ecSmrg    mods= group= 0;
19105b261ecSmrg    if (map->which_mods&XkbIM_UseAnyMods) {
19205b261ecSmrg	if (map->which_mods&XkbIM_UseBase)
19305b261ecSmrg	    mods|= state->base_mods;
19405b261ecSmrg	if (map->which_mods&XkbIM_UseLatched)
19505b261ecSmrg	    mods|= state->latched_mods;
19605b261ecSmrg	if (map->which_mods&XkbIM_UseLocked)
19705b261ecSmrg	    mods|= state->locked_mods;
19805b261ecSmrg	if (map->which_mods&XkbIM_UseEffective)
19905b261ecSmrg	    mods|= state->mods;
20005b261ecSmrg	if (map->which_mods&XkbIM_UseCompat)
20105b261ecSmrg	    mods|= state->compat_state;
20205b261ecSmrg	on = ((map->mods.mask&mods)!=0);
20305b261ecSmrg	on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0));
20405b261ecSmrg    }
20505b261ecSmrg    if (map->which_groups&XkbIM_UseAnyGroup) {
20605b261ecSmrg	if (map->which_groups&XkbIM_UseBase)
20705b261ecSmrg	    group|= (1L << state->base_group);
20805b261ecSmrg	if (map->which_groups&XkbIM_UseLatched)
20905b261ecSmrg	    group|= (1L << state->latched_group);
21005b261ecSmrg	if (map->which_groups&XkbIM_UseLocked)
21105b261ecSmrg	    group|= (1L << state->locked_group);
21205b261ecSmrg	if (map->which_groups&XkbIM_UseEffective)
21305b261ecSmrg	    group|= (1L << state->group);
21405b261ecSmrg	on = on||(((map->groups&group)!=0)||(map->groups==0));
21505b261ecSmrg    }
21605b261ecSmrg    if (map->ctrls)
21705b261ecSmrg	on = on||(ctrls->enabled_ctrls&map->ctrls);
21805b261ecSmrg    return on;
21905b261ecSmrg}
22005b261ecSmrg
22105b261ecSmrg
22205b261ecSmrgstatic void
22305b261ecSmrgXkbUpdateLedAutoState(	DeviceIntPtr			dev,
22405b261ecSmrg			XkbSrvLedInfoPtr		sli,
22505b261ecSmrg			unsigned			maps_to_check,
22605b261ecSmrg			xkbExtensionDeviceNotify *	ed,
22705b261ecSmrg			XkbChangesPtr			changes,
22805b261ecSmrg			XkbEventCausePtr		cause)
22905b261ecSmrg{
23005b261ecSmrgDeviceIntPtr			kbd;
23105b261ecSmrgXkbStatePtr			state;
23205b261ecSmrgXkbControlsPtr			ctrls;
23305b261ecSmrgXkbChangesRec			my_changes;
23405b261ecSmrgxkbExtensionDeviceNotify	my_ed;
23505b261ecSmrgregister unsigned		i,bit,affected;
23605b261ecSmrgregister XkbIndicatorMapPtr	map;
23705b261ecSmrgunsigned			oldState;
23805b261ecSmrg
23905b261ecSmrg    if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0))
24005b261ecSmrg	return;
24105b261ecSmrg
24205b261ecSmrg    if (dev->key && dev->key->xkbInfo)
24305b261ecSmrg	 kbd= dev;
2444642e01fSmrg    else kbd= inputInfo.keyboard;
24505b261ecSmrg
24605b261ecSmrg    state= &kbd->key->xkbInfo->state;
24705b261ecSmrg    ctrls= kbd->key->xkbInfo->desc->ctrls;
24805b261ecSmrg    affected= maps_to_check;
24905b261ecSmrg    oldState= sli->effectiveState;
25005b261ecSmrg    sli->autoState&= ~affected;
25105b261ecSmrg    for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
25205b261ecSmrg	if ((affected&bit)==0)
25305b261ecSmrg	    continue;
25405b261ecSmrg	affected&= ~bit;
25505b261ecSmrg	map= &sli->maps[i];
25605b261ecSmrg	if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls))
25705b261ecSmrg	    sli->autoState|= bit;
25805b261ecSmrg    }
25905b261ecSmrg    sli->effectiveState= (sli->autoState|sli->explicitState);
26005b261ecSmrg    affected= sli->effectiveState^oldState;
26105b261ecSmrg    if (affected==0)
26205b261ecSmrg	return;
26305b261ecSmrg
26405b261ecSmrg    if (ed==NULL) {
26505b261ecSmrg	ed= &my_ed;
2666747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
26705b261ecSmrg    }
26805b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
26905b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
27005b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
27105b261ecSmrg    }
27205b261ecSmrg
27305b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
27405b261ecSmrg	if (changes==NULL) {
27505b261ecSmrg	    changes= &my_changes;
2766747b715Smrg	    memset((char *)changes, 0, sizeof(XkbChangesRec));
27705b261ecSmrg	}
27805b261ecSmrg	changes->indicators.state_changes|= affected;
27905b261ecSmrg    }
28005b261ecSmrg
28105b261ecSmrg    ed->reason|=	XkbXI_IndicatorStateMask;
28205b261ecSmrg    ed->ledClass= 	sli->class;
28305b261ecSmrg    ed->ledID=		sli->id;
28405b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
28505b261ecSmrg    ed->ledState=	sli->effectiveState;
2866747b715Smrg    ed->unsupported=	0;
28705b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
28805b261ecSmrg
28905b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
29005b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
29105b261ecSmrg    if (changes || ed)
29205b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
29305b261ecSmrg    return;
29405b261ecSmrg}
29505b261ecSmrg
29605b261ecSmrgstatic void
29705b261ecSmrgXkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause)
29805b261ecSmrg{
29905b261ecSmrgDeviceIntPtr		edev;
30005b261ecSmrgXkbSrvLedInfoPtr	sli;
30105b261ecSmrg
30205b261ecSmrg    for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) {
30305b261ecSmrg	if (edev->kbdfeed) {
30405b261ecSmrg	    KbdFeedbackPtr	kf;
30505b261ecSmrg	    for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) {
30605b261ecSmrg		if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL))
30705b261ecSmrg		    continue;
30805b261ecSmrg		sli= kf->xkb_sli;
30905b261ecSmrg		XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
31005b261ecSmrg								changes,cause);
31105b261ecSmrg
31205b261ecSmrg	    }
31305b261ecSmrg	}
31405b261ecSmrg	if (edev->leds) {
31505b261ecSmrg	    LedFeedbackPtr	lf;
31605b261ecSmrg	    for (lf=edev->leds;lf!=NULL;lf=lf->next) {
31705b261ecSmrg		if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL))
31805b261ecSmrg		    continue;
31905b261ecSmrg		sli= lf->xkb_sli;
32005b261ecSmrg		XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
32105b261ecSmrg								changes,cause);
32205b261ecSmrg
32305b261ecSmrg	    }
32405b261ecSmrg	}
32505b261ecSmrg    }
32605b261ecSmrg    return;
32705b261ecSmrg}
32805b261ecSmrg
32905b261ecSmrg
33005b261ecSmrg/***====================================================================***/
33105b261ecSmrg
33205b261ecSmrg	/*
33305b261ecSmrg	 * void
33405b261ecSmrg	 * XkbSetIndicators(dev,affect,values,cause)
33505b261ecSmrg	 *
33605b261ecSmrg	 * Attempts to change the indicators specified in 'affect' to the
33705b261ecSmrg	 * states specified in 'values' for the default keyboard feedback
33805b261ecSmrg	 * on the keyboard specified by 'dev.'   Attempts to change indicator
33905b261ecSmrg	 * state might be ignored or have no affect, depending on the XKB
34005b261ecSmrg	 * indicator map for any affected indicators, as described in section
34105b261ecSmrg	 * 9.2 of the XKB protocol specification.
34205b261ecSmrg	 *
34305b261ecSmrg	 * If 'changes' is non-NULL, this function notes any changes to the
34405b261ecSmrg	 * keyboard state, controls, or indicator state that result from this
34505b261ecSmrg	 * attempted change.   If 'changes' is NULL, this function generates
34605b261ecSmrg	 * XKB events to report any such changes to interested clients.
34705b261ecSmrg	 *
34805b261ecSmrg	 * If 'cause' is non-NULL, it specifies the reason for the change,
34905b261ecSmrg	 * as reported in some XKB events.   If it is NULL, this function
35005b261ecSmrg	 * assumes that the change is the result of a core protocol
35105b261ecSmrg	 * ChangeKeyboardMapping request.
35205b261ecSmrg	 */
35305b261ecSmrg
35405b261ecSmrgvoid
35505b261ecSmrgXkbSetIndicators(	DeviceIntPtr		dev,
35605b261ecSmrg			CARD32			affect,
35705b261ecSmrg			CARD32			values,
35805b261ecSmrg			XkbEventCausePtr	cause)
35905b261ecSmrg{
36005b261ecSmrgXkbSrvLedInfoPtr		sli;
36105b261ecSmrgXkbChangesRec			changes;
36205b261ecSmrgxkbExtensionDeviceNotify	ed;
36305b261ecSmrgunsigned 			side_affected;
36405b261ecSmrg
3656747b715Smrg    memset((char *)&changes, 0, sizeof(XkbChangesRec));
3666747b715Smrg    memset((char *)&ed, 0, sizeof(xkbExtensionDeviceNotify));
36705b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
36805b261ecSmrg    sli->explicitState&= ~affect;
36905b261ecSmrg    sli->explicitState|= (affect&values);
37005b261ecSmrg    XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause);
37105b261ecSmrg
37205b261ecSmrg    side_affected= 0;
37305b261ecSmrg    if (changes.state_changes!=0)
3746747b715Smrg	side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,FALSE);
37505b261ecSmrg    if (changes.ctrls.enabled_ctrls_changes)
37605b261ecSmrg	side_affected|= sli->usesControls;
37705b261ecSmrg
37805b261ecSmrg    if (side_affected) {
37905b261ecSmrg	XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause);
38005b261ecSmrg	affect|= side_affected;
38105b261ecSmrg    }
38205b261ecSmrg    if (changes.state_changes || changes.ctrls.enabled_ctrls_changes)
38305b261ecSmrg	XkbUpdateAllDeviceIndicators(NULL,cause);
38405b261ecSmrg
38505b261ecSmrg    XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause);
38605b261ecSmrg    return;
38705b261ecSmrg}
38805b261ecSmrg
38905b261ecSmrg/***====================================================================***/
39005b261ecSmrg
39105b261ecSmrg/***====================================================================***/
39205b261ecSmrg
39305b261ecSmrg	/*
39405b261ecSmrg	 * void
39505b261ecSmrg	 * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
39605b261ecSmrg	 *
39705b261ecSmrg	 * Applies the indicator maps for any indicators specified in
39805b261ecSmrg	 * 'update' from the default keyboard feedback on the device
39905b261ecSmrg	 * specified by 'dev.'
40005b261ecSmrg	 *
40105b261ecSmrg	 * If 'changes' is NULL, this function generates and XKB events
40205b261ecSmrg	 * required to report the necessary changes, otherwise it simply
40305b261ecSmrg	 * notes the indicators with changed state.
40405b261ecSmrg	 *
4056747b715Smrg	 * If 'check_edevs' is TRUE, this function also checks the indicator
40605b261ecSmrg	 * maps for any open extension devices that have them, and updates
40705b261ecSmrg	 * the state of any extension device indicators as necessary.
40805b261ecSmrg	 */
40905b261ecSmrg
41005b261ecSmrgvoid
41105b261ecSmrgXkbUpdateIndicators(	DeviceIntPtr		dev,
41205b261ecSmrg			register CARD32		update,
41305b261ecSmrg			Bool			check_edevs,
41405b261ecSmrg			XkbChangesPtr		changes,
41505b261ecSmrg			XkbEventCausePtr	cause)
41605b261ecSmrg{
41705b261ecSmrgXkbSrvLedInfoPtr	sli;
41805b261ecSmrg
41905b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
42005b261ecSmrg    XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause);
42105b261ecSmrg    if (check_edevs)
42205b261ecSmrg	XkbUpdateAllDeviceIndicators(changes,cause);
42305b261ecSmrg    return;
42405b261ecSmrg}
42505b261ecSmrg
42605b261ecSmrg/***====================================================================***/
42705b261ecSmrg
42805b261ecSmrg/***====================================================================***/
42905b261ecSmrg
43005b261ecSmrg	/*
43105b261ecSmrg	 * void
43205b261ecSmrg	 * XkbCheckIndicatorMaps(dev,sli,which)
43305b261ecSmrg	 *
43405b261ecSmrg	 * Updates the 'indicator accelerators' for the indicators specified
43505b261ecSmrg	 * by 'which' in the feedback specified by 'sli.' The indicator
43605b261ecSmrg	 * accelerators are internal to the server and are used to simplify
43705b261ecSmrg	 * and speed up the process of figuring out which indicators might
43805b261ecSmrg	 * be affected by a particular change in keyboard state or controls.
43905b261ecSmrg	 */
44005b261ecSmrg
44105b261ecSmrgvoid
44205b261ecSmrgXkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which)
44305b261ecSmrg{
44405b261ecSmrgregister unsigned	i,bit;
44505b261ecSmrgXkbIndicatorMapPtr	map;
44605b261ecSmrgXkbDescPtr		xkb;
44705b261ecSmrg
44805b261ecSmrg    if ((sli->flags&XkbSLI_HasOwnState)==0)
4494642e01fSmrg        return;
45005b261ecSmrg
45105b261ecSmrg    sli->usesBase&=	 ~which;
45205b261ecSmrg    sli->usesLatched&=	 ~which;
45305b261ecSmrg    sli->usesLocked&=	 ~which;
45405b261ecSmrg    sli->usesEffective&= ~which;
45505b261ecSmrg    sli->usesCompat&=	 ~which;
45605b261ecSmrg    sli->usesControls&=	 ~which;
45705b261ecSmrg    sli->mapsPresent&=	 ~which;
45805b261ecSmrg
45905b261ecSmrg    xkb= dev->key->xkbInfo->desc;
46005b261ecSmrg    for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) {
46105b261ecSmrg	if (which&bit) {
46205b261ecSmrg	    CARD8		what;
46305b261ecSmrg
4644642e01fSmrg	    if (!map || !XkbIM_InUse(map))
46505b261ecSmrg		continue;
46605b261ecSmrg	    sli->mapsPresent|= bit;
46705b261ecSmrg
46805b261ecSmrg	    what= (map->which_mods|map->which_groups);
46905b261ecSmrg	    if (what&XkbIM_UseBase)
47005b261ecSmrg		 sli->usesBase|= bit;
47105b261ecSmrg	    if (what&XkbIM_UseLatched)
47205b261ecSmrg		 sli->usesLatched|= bit;
47305b261ecSmrg	    if (what&XkbIM_UseLocked)
47405b261ecSmrg		 sli->usesLocked|= bit;
47505b261ecSmrg	    if (what&XkbIM_UseEffective)
47605b261ecSmrg		 sli->usesEffective|= bit;
47705b261ecSmrg	    if (what&XkbIM_UseCompat)
47805b261ecSmrg		 sli->usesCompat|= bit;
47905b261ecSmrg	    if (map->ctrls)
48005b261ecSmrg		 sli->usesControls|= bit;
48105b261ecSmrg
48205b261ecSmrg	    map->mods.mask= map->mods.real_mods;
48305b261ecSmrg	    if (map->mods.vmods!=0) {
48405b261ecSmrg		map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods);
48505b261ecSmrg	    }
48605b261ecSmrg	}
48705b261ecSmrg    }
48805b261ecSmrg    sli->usedComponents= 0;
48905b261ecSmrg    if (sli->usesBase)
49005b261ecSmrg	sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask;
49105b261ecSmrg    if (sli->usesLatched)
49205b261ecSmrg	sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask;
49305b261ecSmrg    if (sli->usesLocked)
49405b261ecSmrg	sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask;
49505b261ecSmrg    if (sli->usesEffective)
49605b261ecSmrg	sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask;
49705b261ecSmrg    if (sli->usesCompat)
49805b261ecSmrg	sli->usedComponents|= XkbCompatStateMask;
49905b261ecSmrg    return;
50005b261ecSmrg}
50105b261ecSmrg
50205b261ecSmrg/***====================================================================***/
50305b261ecSmrg
50405b261ecSmrg	/*
50505b261ecSmrg	 * XkbSrvLedInfoPtr
50605b261ecSmrg	 * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
50705b261ecSmrg	 *
50805b261ecSmrg	 * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
50905b261ecSmrg	 * 'kf' or 'lf' on the keyboard specified by 'dev.'
51005b261ecSmrg	 *
51105b261ecSmrg	 * If 'needed_parts' is non-zero, this function makes sure that any
51205b261ecSmrg	 * of the parts speicified therein are allocated.
51305b261ecSmrg	 */
51405b261ecSmrgXkbSrvLedInfoPtr
51505b261ecSmrgXkbAllocSrvLedInfo(	DeviceIntPtr		dev,
51605b261ecSmrg			KbdFeedbackPtr		kf,
51705b261ecSmrg			LedFeedbackPtr		lf,
51805b261ecSmrg			unsigned		needed_parts)
51905b261ecSmrg{
52005b261ecSmrgXkbSrvLedInfoPtr	sli;
52105b261ecSmrgBool			checkAccel;
52205b261ecSmrgBool			checkNames;
52305b261ecSmrg
52405b261ecSmrg    sli= NULL;
5256747b715Smrg    checkAccel= checkNames= FALSE;
52605b261ecSmrg    if ((kf!=NULL)&&(kf->xkb_sli==NULL)) {
5276747b715Smrg	kf->xkb_sli= sli= calloc(1, sizeof(XkbSrvLedInfoRec));
52805b261ecSmrg	if (sli==NULL)
52905b261ecSmrg	    return NULL; /* ALLOCATION ERROR */
53005b261ecSmrg	if (dev->key && dev->key->xkbInfo)
53105b261ecSmrg	     sli->flags= XkbSLI_HasOwnState;
53205b261ecSmrg	else sli->flags= 0;
53305b261ecSmrg	sli->class=	KbdFeedbackClass;
53405b261ecSmrg	sli->id=	kf->ctrl.id;
53505b261ecSmrg	sli->fb.kf=	kf;
53605b261ecSmrg
53705b261ecSmrg	sli->autoState=		0;
53805b261ecSmrg	sli->explicitState=	kf->ctrl.leds;
53905b261ecSmrg	sli->effectiveState=	kf->ctrl.leds;
54005b261ecSmrg
54105b261ecSmrg	if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) {
54205b261ecSmrg	    XkbDescPtr	xkb;
54305b261ecSmrg	    xkb= dev->key->xkbInfo->desc;
54405b261ecSmrg	    sli->flags|= 		XkbSLI_IsDefault;
54505b261ecSmrg	    sli->physIndicators=	xkb->indicators->phys_indicators;
54605b261ecSmrg	    sli->names=			xkb->names->indicators;
54705b261ecSmrg	    sli->maps=			xkb->indicators->maps;
5486747b715Smrg	    checkNames= checkAccel=	TRUE;
54905b261ecSmrg	}
55005b261ecSmrg	else {
55105b261ecSmrg	    sli->physIndicators=	XkbAllIndicatorsMask;
55205b261ecSmrg	    sli->names=			NULL;
55305b261ecSmrg	    sli->maps=			NULL;
55405b261ecSmrg	}
55505b261ecSmrg    }
55605b261ecSmrg    else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) {
55705b261ecSmrg	XkbDescPtr	xkb;
55805b261ecSmrg	xkb= dev->key->xkbInfo->desc;
55905b261ecSmrg	sli->physIndicators=	xkb->indicators->phys_indicators;
56005b261ecSmrg	if (xkb->names->indicators!=sli->names) {
5616747b715Smrg	    checkNames= TRUE;
56205b261ecSmrg	    sli->names= xkb->names->indicators;
56305b261ecSmrg	}
56405b261ecSmrg	if (xkb->indicators->maps!=sli->maps) {
5656747b715Smrg	    checkAccel= TRUE;
56605b261ecSmrg	    sli->maps= xkb->indicators->maps;
56705b261ecSmrg	}
56805b261ecSmrg    }
56905b261ecSmrg    else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) {
5706747b715Smrg	lf->xkb_sli= sli= calloc(1, sizeof(XkbSrvLedInfoRec));
57105b261ecSmrg	if (sli==NULL)
57205b261ecSmrg	    return NULL; /* ALLOCATION ERROR */
57305b261ecSmrg	if (dev->key && dev->key->xkbInfo)
57405b261ecSmrg	     sli->flags= XkbSLI_HasOwnState;
57505b261ecSmrg	else sli->flags= 0;
57605b261ecSmrg	sli->class=	LedFeedbackClass;
57705b261ecSmrg	sli->id=	lf->ctrl.id;
57805b261ecSmrg	sli->fb.lf=	lf;
57905b261ecSmrg
58005b261ecSmrg	sli->physIndicators=	lf->ctrl.led_mask;
58105b261ecSmrg	sli->autoState=		0;
58205b261ecSmrg	sli->explicitState=	lf->ctrl.led_values;
58305b261ecSmrg	sli->effectiveState=	lf->ctrl.led_values;
58405b261ecSmrg	sli->maps=		NULL;
58505b261ecSmrg	sli->names=		NULL;
58605b261ecSmrg    }
58705b261ecSmrg    if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
5886747b715Smrg	sli->names= calloc(XkbNumIndicators, sizeof(Atom));
58905b261ecSmrg    if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
5906747b715Smrg	sli->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
59105b261ecSmrg    if (checkNames) {
59205b261ecSmrg	register unsigned i,bit;
59305b261ecSmrg	sli->namesPresent=	0;
59405b261ecSmrg	for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
59505b261ecSmrg	    if (sli->names[i]!=None)
59605b261ecSmrg		sli->namesPresent|= bit;
59705b261ecSmrg	}
59805b261ecSmrg    }
59905b261ecSmrg    if (checkAccel)
60005b261ecSmrg	 XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask);
60105b261ecSmrg    return sli;
60205b261ecSmrg}
60305b261ecSmrg
60405b261ecSmrgvoid
60505b261ecSmrgXkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
60605b261ecSmrg{
60705b261ecSmrg    if ((sli->flags&XkbSLI_IsDefault)==0) {
6086747b715Smrg	free(sli->maps);
6096747b715Smrg	free(sli->names);
61005b261ecSmrg    }
61105b261ecSmrg    sli->maps= NULL;
61205b261ecSmrg    sli->names= NULL;
6136747b715Smrg    free(sli);
61405b261ecSmrg    return;
61505b261ecSmrg}
61605b261ecSmrg
6174642e01fSmrg/*
6184642e01fSmrg * XkbSrvLedInfoPtr
6194642e01fSmrg * XkbCopySrvLedInfo(dev,src,kf,lf)
6204642e01fSmrg *
6214642e01fSmrg * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made,
6224642e01fSmrg * thus the new copy behaves like the original one and can be freed with
6234642e01fSmrg * XkbFreeSrvLedInfo.
6244642e01fSmrg */
6254642e01fSmrgXkbSrvLedInfoPtr
6264642e01fSmrgXkbCopySrvLedInfo(	DeviceIntPtr		from,
6274642e01fSmrg			XkbSrvLedInfoPtr	src,
6284642e01fSmrg			KbdFeedbackPtr		kf,
6294642e01fSmrg			LedFeedbackPtr		lf)
6304642e01fSmrg{
6314642e01fSmrg    XkbSrvLedInfoPtr sli_new = NULL;
6324642e01fSmrg
6334642e01fSmrg    if (!src)
6344642e01fSmrg	goto finish;
6354642e01fSmrg
6366747b715Smrg    sli_new = calloc(1, sizeof( XkbSrvLedInfoRec));
6374642e01fSmrg    if (!sli_new)
6384642e01fSmrg	goto finish;
6394642e01fSmrg
6404642e01fSmrg    memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec));
6414642e01fSmrg    if (sli_new->class == KbdFeedbackClass)
6424642e01fSmrg	sli_new->fb.kf = kf;
6434642e01fSmrg    else
6444642e01fSmrg	sli_new->fb.lf = lf;
6454642e01fSmrg
6466747b715Smrg    if (!(sli_new->flags & XkbSLI_IsDefault)) {
6476747b715Smrg	sli_new->names= calloc(XkbNumIndicators, sizeof(Atom));
6486747b715Smrg	sli_new->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
6494642e01fSmrg    } /* else sli_new->names/maps is pointing to
6504642e01fSmrg	dev->key->xkbInfo->desc->names->indicators;
6514642e01fSmrg	dev->key->xkbInfo->desc->names->indicators; */
6524642e01fSmrg
6534642e01fSmrgfinish:
6544642e01fSmrg    return sli_new;
6554642e01fSmrg}
65605b261ecSmrg
65705b261ecSmrg/***====================================================================***/
65805b261ecSmrg
65905b261ecSmrg	/*
66005b261ecSmrg	 * XkbSrvLedInfoPtr
66105b261ecSmrg	 * XkbFindSrvLedInfo(dev,class,id,needed_parts)
66205b261ecSmrg	 *
66305b261ecSmrg	 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
66405b261ecSmrg	 * on the device specified by 'dev.'   If the class and id specify
66505b261ecSmrg	 * a valid device feedback, this function returns the existing
66605b261ecSmrg	 * feedback or allocates a new one.
66705b261ecSmrg	 *
66805b261ecSmrg	 */
66905b261ecSmrg
6706747b715SmrgXkbSrvLedInfoPtr
67105b261ecSmrgXkbFindSrvLedInfo(	DeviceIntPtr		dev,
67205b261ecSmrg			unsigned		class,
67305b261ecSmrg			unsigned		id,
67405b261ecSmrg			unsigned		needed_parts)
67505b261ecSmrg{
67605b261ecSmrgXkbSrvLedInfoPtr	sli;
67705b261ecSmrg
67805b261ecSmrg    /* optimization to check for most common case */
67905b261ecSmrg    if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) {
68005b261ecSmrg	XkbSrvLedInfoPtr	sli;
68105b261ecSmrg	sli= dev->kbdfeed->xkb_sli;
68205b261ecSmrg	if (dev->kbdfeed->xkb_sli==NULL) {
68305b261ecSmrg	    sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts);
68405b261ecSmrg	    dev->kbdfeed->xkb_sli= sli;
68505b261ecSmrg	}
68605b261ecSmrg	return dev->kbdfeed->xkb_sli;
68705b261ecSmrg    }
68805b261ecSmrg
68905b261ecSmrg    sli= NULL;
69005b261ecSmrg    if (class==XkbDfltXIClass) {
69105b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
69205b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
69305b261ecSmrg	else 			return NULL;
69405b261ecSmrg    }
69505b261ecSmrg    if (class==KbdFeedbackClass) {
69605b261ecSmrg	KbdFeedbackPtr	kf;
69705b261ecSmrg	for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) {
69805b261ecSmrg	    if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) {
69905b261ecSmrg		if (kf->xkb_sli==NULL)
70005b261ecSmrg		    kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts);
70105b261ecSmrg		sli= kf->xkb_sli;
70205b261ecSmrg		break;
70305b261ecSmrg	    }
70405b261ecSmrg	}
70505b261ecSmrg    }
70605b261ecSmrg    else if (class==LedFeedbackClass) {
70705b261ecSmrg	LedFeedbackPtr	lf;
70805b261ecSmrg	for (lf=dev->leds;lf!=NULL;lf=lf->next) {
70905b261ecSmrg	    if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) {
71005b261ecSmrg		if (lf->xkb_sli==NULL)
71105b261ecSmrg		    lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts);
71205b261ecSmrg		sli= lf->xkb_sli;
71305b261ecSmrg		break;
71405b261ecSmrg	    }
71505b261ecSmrg	}
71605b261ecSmrg    }
71705b261ecSmrg    if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
7186747b715Smrg	sli->names= calloc(XkbNumIndicators, sizeof(Atom));
71905b261ecSmrg    if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
7206747b715Smrg	sli->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
72105b261ecSmrg    return sli;
72205b261ecSmrg}
72305b261ecSmrg
72405b261ecSmrg/***====================================================================***/
72505b261ecSmrg
72605b261ecSmrgvoid
72705b261ecSmrgXkbFlushLedEvents(	DeviceIntPtr			dev,
72805b261ecSmrg			DeviceIntPtr			kbd,
72905b261ecSmrg			XkbSrvLedInfoPtr		sli,
73005b261ecSmrg			xkbExtensionDeviceNotify *	ed,
73105b261ecSmrg			XkbChangesPtr			changes,
73205b261ecSmrg			XkbEventCausePtr		cause)
73305b261ecSmrg{
73405b261ecSmrg    if (changes) {
73505b261ecSmrg	if (changes->indicators.state_changes)
73605b261ecSmrg	    XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
73705b261ecSmrg	XkbSendNotification(kbd,changes,cause);
7386747b715Smrg	memset((char *)changes, 0, sizeof(XkbChangesRec));
73905b261ecSmrg
74005b261ecSmrg	if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
74105b261ecSmrg		if (sli->effectiveState)
74205b261ecSmrg			/* it appears that the which parameter is not used */
74305b261ecSmrg			XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
74405b261ecSmrg		else
74505b261ecSmrg			XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
74605b261ecSmrg	}
74705b261ecSmrg    }
7486747b715Smrg    if (ed) {
7496747b715Smrg	if (ed->reason) {
7506747b715Smrg	    if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask))
7516747b715Smrg		XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
7526747b715Smrg	    XkbSendExtensionDeviceNotify(dev,cause->client,ed);
7536747b715Smrg	}
7546747b715Smrg	memset((char *)ed, 0, sizeof(XkbExtensionDeviceNotify));
75505b261ecSmrg    }
75605b261ecSmrg    return;
75705b261ecSmrg}
75805b261ecSmrg
75905b261ecSmrg/***====================================================================***/
76005b261ecSmrg
76105b261ecSmrgvoid
76205b261ecSmrgXkbApplyLedNameChanges(	DeviceIntPtr 			dev,
76305b261ecSmrg			XkbSrvLedInfoPtr		sli,
76405b261ecSmrg			unsigned			changed_names,
76505b261ecSmrg			xkbExtensionDeviceNotify *	ed,
76605b261ecSmrg			XkbChangesPtr			changes,
76705b261ecSmrg			XkbEventCausePtr		cause)
76805b261ecSmrg{
76905b261ecSmrgDeviceIntPtr			kbd;
77005b261ecSmrgXkbChangesRec			my_changes;
77105b261ecSmrgxkbExtensionDeviceNotify	my_ed;
77205b261ecSmrg
77305b261ecSmrg    if (changed_names==0)
77405b261ecSmrg	return;
77505b261ecSmrg    if (dev->key && dev->key->xkbInfo)
77605b261ecSmrg	 kbd= dev;
7774642e01fSmrg    else kbd= inputInfo.keyboard;
77805b261ecSmrg
77905b261ecSmrg    if (ed==NULL) {
78005b261ecSmrg	ed= &my_ed;
7816747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
78205b261ecSmrg    }
78305b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
78405b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
78505b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
78605b261ecSmrg    }
78705b261ecSmrg
78805b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
78905b261ecSmrg	if (changes==NULL) {
79005b261ecSmrg	   changes= &my_changes;
7916747b715Smrg	   memset((char *)changes, 0, sizeof(XkbChangesRec));
79205b261ecSmrg	}
79305b261ecSmrg	changes->names.changed|= XkbIndicatorNamesMask;
79405b261ecSmrg	changes->names.changed_indicators|= changed_names;
79505b261ecSmrg    }
79605b261ecSmrg
79705b261ecSmrg    ed->reason|=	XkbXI_IndicatorNamesMask;
79805b261ecSmrg    ed->ledClass= 	sli->class;
79905b261ecSmrg    ed->ledID=		sli->id;
80005b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
80105b261ecSmrg    ed->ledState=	sli->effectiveState;
80205b261ecSmrg    ed->unsupported=	0;
80305b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
80405b261ecSmrg
80505b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
80605b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
80705b261ecSmrg    if (changes || ed)
80805b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
80905b261ecSmrg    return;
81005b261ecSmrg}
81105b261ecSmrg/***====================================================================***/
81205b261ecSmrg
81305b261ecSmrg	/*
81405b261ecSmrg	 * void
81505b261ecSmrg	 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
81605b261ecSmrg	 *
81705b261ecSmrg	 * Handles all of the secondary effects of the changes to the
81805b261ecSmrg	 * feedback specified by 'sli' on the device specified by 'dev.'
81905b261ecSmrg	 *
82005b261ecSmrg	 * If 'changed_maps' specifies any indicators, this function generates
82105b261ecSmrg	 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
82205b261ecSmrg	 * events to report the changes, and recalculates the effective
82305b261ecSmrg	 * state of each indicator with a changed map.  If any indicators
82405b261ecSmrg	 * change state, the server generates XkbExtensionDeviceNotify and
82505b261ecSmrg	 * XkbIndicatorStateNotify events as appropriate.
82605b261ecSmrg	 *
82705b261ecSmrg	 * If 'changes' is non-NULL, this function updates it to reflect
82805b261ecSmrg	 * any changes to the keyboard state or controls or to the 'core'
82905b261ecSmrg	 * indicator names, maps, or state.   If 'changes' is NULL, this
83005b261ecSmrg	 * function generates XKB events as needed to report the changes.
83105b261ecSmrg	 * If 'dev' is not a keyboard device, any changes are reported
83205b261ecSmrg	 * for the core keyboard.
83305b261ecSmrg	 *
83405b261ecSmrg	 * The 'cause' specifies the reason for the event (key event or
83505b261ecSmrg	 * request) for the change, as reported in some XKB events.
83605b261ecSmrg	 */
83705b261ecSmrg
83805b261ecSmrgvoid
83905b261ecSmrgXkbApplyLedMapChanges(	DeviceIntPtr 			dev,
84005b261ecSmrg			XkbSrvLedInfoPtr		sli,
84105b261ecSmrg			unsigned			changed_maps,
84205b261ecSmrg			xkbExtensionDeviceNotify *	ed,
84305b261ecSmrg			XkbChangesPtr			changes,
84405b261ecSmrg			XkbEventCausePtr		cause)
84505b261ecSmrg{
84605b261ecSmrgDeviceIntPtr			kbd;
84705b261ecSmrgXkbChangesRec			my_changes;
84805b261ecSmrgxkbExtensionDeviceNotify	my_ed;
84905b261ecSmrg
85005b261ecSmrg    if (changed_maps==0)
85105b261ecSmrg	return;
85205b261ecSmrg    if (dev->key && dev->key->xkbInfo)
85305b261ecSmrg	 kbd= dev;
8544642e01fSmrg    else kbd= inputInfo.keyboard;
85505b261ecSmrg
85605b261ecSmrg    if (ed==NULL) {
85705b261ecSmrg	ed= &my_ed;
8586747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
85905b261ecSmrg    }
86005b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
86105b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
86205b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
86305b261ecSmrg    }
86405b261ecSmrg
86505b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
86605b261ecSmrg	if (changes==NULL) {
86705b261ecSmrg	    changes= &my_changes;
8686747b715Smrg	    memset((char *)changes, 0, sizeof(XkbChangesRec));
86905b261ecSmrg	}
87005b261ecSmrg	changes->indicators.map_changes|= changed_maps;
87105b261ecSmrg    }
87205b261ecSmrg
87305b261ecSmrg    XkbCheckIndicatorMaps(dev,sli,changed_maps);
87405b261ecSmrg
87505b261ecSmrg    ed->reason|=	XkbXI_IndicatorMapsMask;
87605b261ecSmrg    ed->ledClass= 	sli->class;
87705b261ecSmrg    ed->ledID=		sli->id;
87805b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
87905b261ecSmrg    ed->ledState=	sli->effectiveState;
8806747b715Smrg    ed->unsupported=	0;
88105b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
88205b261ecSmrg
88305b261ecSmrg    XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause);
88405b261ecSmrg
88505b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
88605b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
88705b261ecSmrg    if (changes || ed)
88805b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
88905b261ecSmrg    return;
89005b261ecSmrg}
89105b261ecSmrg
89205b261ecSmrg/***====================================================================***/
89305b261ecSmrg
89405b261ecSmrgvoid
89505b261ecSmrgXkbApplyLedStateChanges(DeviceIntPtr 			dev,
89605b261ecSmrg			XkbSrvLedInfoPtr		sli,
89705b261ecSmrg			unsigned			changed_leds,
89805b261ecSmrg			xkbExtensionDeviceNotify *	ed,
89905b261ecSmrg			XkbChangesPtr			changes,
90005b261ecSmrg			XkbEventCausePtr		cause)
90105b261ecSmrg{
90205b261ecSmrgXkbSrvInfoPtr			xkbi;
90305b261ecSmrgDeviceIntPtr			kbd;
90405b261ecSmrgXkbChangesRec			my_changes;
90505b261ecSmrgxkbExtensionDeviceNotify	my_ed;
90605b261ecSmrgregister unsigned		i,bit,affected;
90705b261ecSmrgXkbIndicatorMapPtr		map;
90805b261ecSmrgunsigned			oldState;
90905b261ecSmrgBool				kb_changed;
91005b261ecSmrg
91105b261ecSmrg    if (changed_leds==0)
91205b261ecSmrg	return;
91305b261ecSmrg    if (dev->key && dev->key->xkbInfo)
91405b261ecSmrg	 kbd= dev;
9154642e01fSmrg    else kbd= inputInfo.keyboard;
91605b261ecSmrg    xkbi= kbd->key->xkbInfo;
91705b261ecSmrg
91805b261ecSmrg    if (changes==NULL) {
91905b261ecSmrg	changes= &my_changes;
9206747b715Smrg	memset((char *)changes, 0, sizeof(XkbChangesRec));
92105b261ecSmrg    }
92205b261ecSmrg
9236747b715Smrg    kb_changed= FALSE;
92405b261ecSmrg    affected= changed_leds;
92505b261ecSmrg    oldState= sli->effectiveState;
92605b261ecSmrg    for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
92705b261ecSmrg	if ((affected&bit)==0)
92805b261ecSmrg	    continue;
92905b261ecSmrg	affected&= ~bit;
93005b261ecSmrg	map= &sli->maps[i];
93105b261ecSmrg	if (map->flags&XkbIM_NoExplicit) {
93205b261ecSmrg	    sli->explicitState&= ~bit;
93305b261ecSmrg	    continue;
93405b261ecSmrg	}
93505b261ecSmrg	if (map->flags&XkbIM_LEDDrivesKB) {
93605b261ecSmrg	    Bool on= ((sli->explicitState&bit)!=0);
93705b261ecSmrg	    if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes))
9386747b715Smrg		kb_changed= TRUE;
93905b261ecSmrg	}
94005b261ecSmrg    }
94105b261ecSmrg    sli->effectiveState= (sli->autoState|sli->explicitState);
94205b261ecSmrg    affected= sli->effectiveState^oldState;
94305b261ecSmrg
94405b261ecSmrg    if (ed==NULL) {
94505b261ecSmrg	ed= &my_ed;
9466747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
94705b261ecSmrg    }
94805b261ecSmrg    else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&&
94905b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
95005b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
95105b261ecSmrg    }
95205b261ecSmrg
95305b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault))
95405b261ecSmrg	changes->indicators.state_changes|= affected;
95505b261ecSmrg    if (affected) {
95605b261ecSmrg	ed->reason|=		XkbXI_IndicatorStateMask;
95705b261ecSmrg	ed->ledClass= 		sli->class;
95805b261ecSmrg	ed->ledID=		sli->id;
95905b261ecSmrg	ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
96005b261ecSmrg	ed->ledState=		sli->effectiveState;
9616747b715Smrg	ed->unsupported=	0;
96205b261ecSmrg	ed->supported=		XkbXI_AllFeaturesMask;
96305b261ecSmrg    }
96405b261ecSmrg
96505b261ecSmrg    if (kb_changed) {
96605b261ecSmrg	XkbComputeDerivedState(kbd->key->xkbInfo);
96705b261ecSmrg	XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause);
96805b261ecSmrg    }
96905b261ecSmrg
97005b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
97105b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
97205b261ecSmrg    if (changes || ed)
97305b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
97405b261ecSmrg    if (kb_changed)
97505b261ecSmrg	XkbUpdateAllDeviceIndicators(NULL,cause);
97605b261ecSmrg    return;
97705b261ecSmrg}
978