xkbLEDs.c revision 9ace9065
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;
5599ace9065Smrg	sli= kf->xkb_sli;
56005b261ecSmrg	sli->physIndicators=	xkb->indicators->phys_indicators;
56105b261ecSmrg	if (xkb->names->indicators!=sli->names) {
5626747b715Smrg	    checkNames= TRUE;
56305b261ecSmrg	    sli->names= xkb->names->indicators;
56405b261ecSmrg	}
56505b261ecSmrg	if (xkb->indicators->maps!=sli->maps) {
5666747b715Smrg	    checkAccel= TRUE;
56705b261ecSmrg	    sli->maps= xkb->indicators->maps;
56805b261ecSmrg	}
56905b261ecSmrg    }
57005b261ecSmrg    else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) {
5716747b715Smrg	lf->xkb_sli= sli= calloc(1, sizeof(XkbSrvLedInfoRec));
57205b261ecSmrg	if (sli==NULL)
57305b261ecSmrg	    return NULL; /* ALLOCATION ERROR */
57405b261ecSmrg	if (dev->key && dev->key->xkbInfo)
57505b261ecSmrg	     sli->flags= XkbSLI_HasOwnState;
57605b261ecSmrg	else sli->flags= 0;
57705b261ecSmrg	sli->class=	LedFeedbackClass;
57805b261ecSmrg	sli->id=	lf->ctrl.id;
57905b261ecSmrg	sli->fb.lf=	lf;
58005b261ecSmrg
58105b261ecSmrg	sli->physIndicators=	lf->ctrl.led_mask;
58205b261ecSmrg	sli->autoState=		0;
58305b261ecSmrg	sli->explicitState=	lf->ctrl.led_values;
58405b261ecSmrg	sli->effectiveState=	lf->ctrl.led_values;
58505b261ecSmrg	sli->maps=		NULL;
58605b261ecSmrg	sli->names=		NULL;
58705b261ecSmrg    }
5889ace9065Smrg    else
5899ace9065Smrg	return NULL;
59005b261ecSmrg    if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
5916747b715Smrg	sli->names= calloc(XkbNumIndicators, sizeof(Atom));
59205b261ecSmrg    if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
5936747b715Smrg	sli->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
59405b261ecSmrg    if (checkNames) {
59505b261ecSmrg	register unsigned i,bit;
59605b261ecSmrg	sli->namesPresent=	0;
59705b261ecSmrg	for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
59805b261ecSmrg	    if (sli->names[i]!=None)
59905b261ecSmrg		sli->namesPresent|= bit;
60005b261ecSmrg	}
60105b261ecSmrg    }
60205b261ecSmrg    if (checkAccel)
60305b261ecSmrg	 XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask);
60405b261ecSmrg    return sli;
60505b261ecSmrg}
60605b261ecSmrg
60705b261ecSmrgvoid
60805b261ecSmrgXkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
60905b261ecSmrg{
61005b261ecSmrg    if ((sli->flags&XkbSLI_IsDefault)==0) {
6116747b715Smrg	free(sli->maps);
6126747b715Smrg	free(sli->names);
61305b261ecSmrg    }
61405b261ecSmrg    sli->maps= NULL;
61505b261ecSmrg    sli->names= NULL;
6166747b715Smrg    free(sli);
61705b261ecSmrg    return;
61805b261ecSmrg}
61905b261ecSmrg
6204642e01fSmrg/*
6214642e01fSmrg * XkbSrvLedInfoPtr
6224642e01fSmrg * XkbCopySrvLedInfo(dev,src,kf,lf)
6234642e01fSmrg *
6244642e01fSmrg * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made,
6254642e01fSmrg * thus the new copy behaves like the original one and can be freed with
6264642e01fSmrg * XkbFreeSrvLedInfo.
6274642e01fSmrg */
6284642e01fSmrgXkbSrvLedInfoPtr
6294642e01fSmrgXkbCopySrvLedInfo(	DeviceIntPtr		from,
6304642e01fSmrg			XkbSrvLedInfoPtr	src,
6314642e01fSmrg			KbdFeedbackPtr		kf,
6324642e01fSmrg			LedFeedbackPtr		lf)
6334642e01fSmrg{
6344642e01fSmrg    XkbSrvLedInfoPtr sli_new = NULL;
6354642e01fSmrg
6364642e01fSmrg    if (!src)
6374642e01fSmrg	goto finish;
6384642e01fSmrg
6396747b715Smrg    sli_new = calloc(1, sizeof( XkbSrvLedInfoRec));
6404642e01fSmrg    if (!sli_new)
6414642e01fSmrg	goto finish;
6424642e01fSmrg
6434642e01fSmrg    memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec));
6444642e01fSmrg    if (sli_new->class == KbdFeedbackClass)
6454642e01fSmrg	sli_new->fb.kf = kf;
6464642e01fSmrg    else
6474642e01fSmrg	sli_new->fb.lf = lf;
6484642e01fSmrg
6496747b715Smrg    if (!(sli_new->flags & XkbSLI_IsDefault)) {
6506747b715Smrg	sli_new->names= calloc(XkbNumIndicators, sizeof(Atom));
6516747b715Smrg	sli_new->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
6524642e01fSmrg    } /* else sli_new->names/maps is pointing to
6534642e01fSmrg	dev->key->xkbInfo->desc->names->indicators;
6544642e01fSmrg	dev->key->xkbInfo->desc->names->indicators; */
6554642e01fSmrg
6564642e01fSmrgfinish:
6574642e01fSmrg    return sli_new;
6584642e01fSmrg}
65905b261ecSmrg
66005b261ecSmrg/***====================================================================***/
66105b261ecSmrg
66205b261ecSmrg	/*
66305b261ecSmrg	 * XkbSrvLedInfoPtr
66405b261ecSmrg	 * XkbFindSrvLedInfo(dev,class,id,needed_parts)
66505b261ecSmrg	 *
66605b261ecSmrg	 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
66705b261ecSmrg	 * on the device specified by 'dev.'   If the class and id specify
66805b261ecSmrg	 * a valid device feedback, this function returns the existing
66905b261ecSmrg	 * feedback or allocates a new one.
67005b261ecSmrg	 *
67105b261ecSmrg	 */
67205b261ecSmrg
6736747b715SmrgXkbSrvLedInfoPtr
67405b261ecSmrgXkbFindSrvLedInfo(	DeviceIntPtr		dev,
67505b261ecSmrg			unsigned		class,
67605b261ecSmrg			unsigned		id,
67705b261ecSmrg			unsigned		needed_parts)
67805b261ecSmrg{
67905b261ecSmrgXkbSrvLedInfoPtr	sli;
68005b261ecSmrg
68105b261ecSmrg    /* optimization to check for most common case */
68205b261ecSmrg    if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) {
68305b261ecSmrg	XkbSrvLedInfoPtr	sli;
68405b261ecSmrg	sli= dev->kbdfeed->xkb_sli;
68505b261ecSmrg	if (dev->kbdfeed->xkb_sli==NULL) {
68605b261ecSmrg	    sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts);
68705b261ecSmrg	    dev->kbdfeed->xkb_sli= sli;
68805b261ecSmrg	}
68905b261ecSmrg	return dev->kbdfeed->xkb_sli;
69005b261ecSmrg    }
69105b261ecSmrg
69205b261ecSmrg    sli= NULL;
69305b261ecSmrg    if (class==XkbDfltXIClass) {
69405b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
69505b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
69605b261ecSmrg	else 			return NULL;
69705b261ecSmrg    }
69805b261ecSmrg    if (class==KbdFeedbackClass) {
69905b261ecSmrg	KbdFeedbackPtr	kf;
70005b261ecSmrg	for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) {
70105b261ecSmrg	    if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) {
70205b261ecSmrg		if (kf->xkb_sli==NULL)
70305b261ecSmrg		    kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts);
70405b261ecSmrg		sli= kf->xkb_sli;
70505b261ecSmrg		break;
70605b261ecSmrg	    }
70705b261ecSmrg	}
70805b261ecSmrg    }
70905b261ecSmrg    else if (class==LedFeedbackClass) {
71005b261ecSmrg	LedFeedbackPtr	lf;
71105b261ecSmrg	for (lf=dev->leds;lf!=NULL;lf=lf->next) {
71205b261ecSmrg	    if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) {
71305b261ecSmrg		if (lf->xkb_sli==NULL)
71405b261ecSmrg		    lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts);
71505b261ecSmrg		sli= lf->xkb_sli;
71605b261ecSmrg		break;
71705b261ecSmrg	    }
71805b261ecSmrg	}
71905b261ecSmrg    }
7209ace9065Smrg    if (sli) {
7219ace9065Smrg	if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
7229ace9065Smrg	    sli->names= calloc(XkbNumIndicators, sizeof(Atom));
7239ace9065Smrg	if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
7249ace9065Smrg	    sli->maps= calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
7259ace9065Smrg    }
72605b261ecSmrg    return sli;
72705b261ecSmrg}
72805b261ecSmrg
72905b261ecSmrg/***====================================================================***/
73005b261ecSmrg
73105b261ecSmrgvoid
73205b261ecSmrgXkbFlushLedEvents(	DeviceIntPtr			dev,
73305b261ecSmrg			DeviceIntPtr			kbd,
73405b261ecSmrg			XkbSrvLedInfoPtr		sli,
73505b261ecSmrg			xkbExtensionDeviceNotify *	ed,
73605b261ecSmrg			XkbChangesPtr			changes,
73705b261ecSmrg			XkbEventCausePtr		cause)
73805b261ecSmrg{
73905b261ecSmrg    if (changes) {
74005b261ecSmrg	if (changes->indicators.state_changes)
74105b261ecSmrg	    XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
74205b261ecSmrg	XkbSendNotification(kbd,changes,cause);
7436747b715Smrg	memset((char *)changes, 0, sizeof(XkbChangesRec));
74405b261ecSmrg
74505b261ecSmrg	if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
74605b261ecSmrg		if (sli->effectiveState)
74705b261ecSmrg			/* it appears that the which parameter is not used */
74805b261ecSmrg			XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
74905b261ecSmrg		else
75005b261ecSmrg			XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
75105b261ecSmrg	}
75205b261ecSmrg    }
7536747b715Smrg    if (ed) {
7546747b715Smrg	if (ed->reason) {
7556747b715Smrg	    if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask))
7566747b715Smrg		XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
7576747b715Smrg	    XkbSendExtensionDeviceNotify(dev,cause->client,ed);
7586747b715Smrg	}
7596747b715Smrg	memset((char *)ed, 0, sizeof(XkbExtensionDeviceNotify));
76005b261ecSmrg    }
76105b261ecSmrg    return;
76205b261ecSmrg}
76305b261ecSmrg
76405b261ecSmrg/***====================================================================***/
76505b261ecSmrg
76605b261ecSmrgvoid
76705b261ecSmrgXkbApplyLedNameChanges(	DeviceIntPtr 			dev,
76805b261ecSmrg			XkbSrvLedInfoPtr		sli,
76905b261ecSmrg			unsigned			changed_names,
77005b261ecSmrg			xkbExtensionDeviceNotify *	ed,
77105b261ecSmrg			XkbChangesPtr			changes,
77205b261ecSmrg			XkbEventCausePtr		cause)
77305b261ecSmrg{
77405b261ecSmrgDeviceIntPtr			kbd;
77505b261ecSmrgXkbChangesRec			my_changes;
77605b261ecSmrgxkbExtensionDeviceNotify	my_ed;
77705b261ecSmrg
77805b261ecSmrg    if (changed_names==0)
77905b261ecSmrg	return;
78005b261ecSmrg    if (dev->key && dev->key->xkbInfo)
78105b261ecSmrg	 kbd= dev;
7824642e01fSmrg    else kbd= inputInfo.keyboard;
78305b261ecSmrg
78405b261ecSmrg    if (ed==NULL) {
78505b261ecSmrg	ed= &my_ed;
7866747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
78705b261ecSmrg    }
78805b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
78905b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
79005b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
79105b261ecSmrg    }
79205b261ecSmrg
79305b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
79405b261ecSmrg	if (changes==NULL) {
79505b261ecSmrg	   changes= &my_changes;
7966747b715Smrg	   memset((char *)changes, 0, sizeof(XkbChangesRec));
79705b261ecSmrg	}
79805b261ecSmrg	changes->names.changed|= XkbIndicatorNamesMask;
79905b261ecSmrg	changes->names.changed_indicators|= changed_names;
80005b261ecSmrg    }
80105b261ecSmrg
80205b261ecSmrg    ed->reason|=	XkbXI_IndicatorNamesMask;
80305b261ecSmrg    ed->ledClass= 	sli->class;
80405b261ecSmrg    ed->ledID=		sli->id;
80505b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
80605b261ecSmrg    ed->ledState=	sli->effectiveState;
80705b261ecSmrg    ed->unsupported=	0;
80805b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
80905b261ecSmrg
81005b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
81105b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
81205b261ecSmrg    if (changes || ed)
81305b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
81405b261ecSmrg    return;
81505b261ecSmrg}
81605b261ecSmrg/***====================================================================***/
81705b261ecSmrg
81805b261ecSmrg	/*
81905b261ecSmrg	 * void
82005b261ecSmrg	 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
82105b261ecSmrg	 *
82205b261ecSmrg	 * Handles all of the secondary effects of the changes to the
82305b261ecSmrg	 * feedback specified by 'sli' on the device specified by 'dev.'
82405b261ecSmrg	 *
82505b261ecSmrg	 * If 'changed_maps' specifies any indicators, this function generates
82605b261ecSmrg	 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
82705b261ecSmrg	 * events to report the changes, and recalculates the effective
82805b261ecSmrg	 * state of each indicator with a changed map.  If any indicators
82905b261ecSmrg	 * change state, the server generates XkbExtensionDeviceNotify and
83005b261ecSmrg	 * XkbIndicatorStateNotify events as appropriate.
83105b261ecSmrg	 *
83205b261ecSmrg	 * If 'changes' is non-NULL, this function updates it to reflect
83305b261ecSmrg	 * any changes to the keyboard state or controls or to the 'core'
83405b261ecSmrg	 * indicator names, maps, or state.   If 'changes' is NULL, this
83505b261ecSmrg	 * function generates XKB events as needed to report the changes.
83605b261ecSmrg	 * If 'dev' is not a keyboard device, any changes are reported
83705b261ecSmrg	 * for the core keyboard.
83805b261ecSmrg	 *
83905b261ecSmrg	 * The 'cause' specifies the reason for the event (key event or
84005b261ecSmrg	 * request) for the change, as reported in some XKB events.
84105b261ecSmrg	 */
84205b261ecSmrg
84305b261ecSmrgvoid
84405b261ecSmrgXkbApplyLedMapChanges(	DeviceIntPtr 			dev,
84505b261ecSmrg			XkbSrvLedInfoPtr		sli,
84605b261ecSmrg			unsigned			changed_maps,
84705b261ecSmrg			xkbExtensionDeviceNotify *	ed,
84805b261ecSmrg			XkbChangesPtr			changes,
84905b261ecSmrg			XkbEventCausePtr		cause)
85005b261ecSmrg{
85105b261ecSmrgDeviceIntPtr			kbd;
85205b261ecSmrgXkbChangesRec			my_changes;
85305b261ecSmrgxkbExtensionDeviceNotify	my_ed;
85405b261ecSmrg
85505b261ecSmrg    if (changed_maps==0)
85605b261ecSmrg	return;
85705b261ecSmrg    if (dev->key && dev->key->xkbInfo)
85805b261ecSmrg	 kbd= dev;
8594642e01fSmrg    else kbd= inputInfo.keyboard;
86005b261ecSmrg
86105b261ecSmrg    if (ed==NULL) {
86205b261ecSmrg	ed= &my_ed;
8636747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
86405b261ecSmrg    }
86505b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
86605b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
86705b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
86805b261ecSmrg    }
86905b261ecSmrg
87005b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
87105b261ecSmrg	if (changes==NULL) {
87205b261ecSmrg	    changes= &my_changes;
8736747b715Smrg	    memset((char *)changes, 0, sizeof(XkbChangesRec));
87405b261ecSmrg	}
87505b261ecSmrg	changes->indicators.map_changes|= changed_maps;
87605b261ecSmrg    }
87705b261ecSmrg
87805b261ecSmrg    XkbCheckIndicatorMaps(dev,sli,changed_maps);
87905b261ecSmrg
88005b261ecSmrg    ed->reason|=	XkbXI_IndicatorMapsMask;
88105b261ecSmrg    ed->ledClass= 	sli->class;
88205b261ecSmrg    ed->ledID=		sli->id;
88305b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
88405b261ecSmrg    ed->ledState=	sli->effectiveState;
8856747b715Smrg    ed->unsupported=	0;
88605b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
88705b261ecSmrg
88805b261ecSmrg    XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause);
88905b261ecSmrg
89005b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
89105b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
89205b261ecSmrg    if (changes || ed)
89305b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
89405b261ecSmrg    return;
89505b261ecSmrg}
89605b261ecSmrg
89705b261ecSmrg/***====================================================================***/
89805b261ecSmrg
89905b261ecSmrgvoid
90005b261ecSmrgXkbApplyLedStateChanges(DeviceIntPtr 			dev,
90105b261ecSmrg			XkbSrvLedInfoPtr		sli,
90205b261ecSmrg			unsigned			changed_leds,
90305b261ecSmrg			xkbExtensionDeviceNotify *	ed,
90405b261ecSmrg			XkbChangesPtr			changes,
90505b261ecSmrg			XkbEventCausePtr		cause)
90605b261ecSmrg{
90705b261ecSmrgXkbSrvInfoPtr			xkbi;
90805b261ecSmrgDeviceIntPtr			kbd;
90905b261ecSmrgXkbChangesRec			my_changes;
91005b261ecSmrgxkbExtensionDeviceNotify	my_ed;
91105b261ecSmrgregister unsigned		i,bit,affected;
91205b261ecSmrgXkbIndicatorMapPtr		map;
91305b261ecSmrgunsigned			oldState;
91405b261ecSmrgBool				kb_changed;
91505b261ecSmrg
91605b261ecSmrg    if (changed_leds==0)
91705b261ecSmrg	return;
91805b261ecSmrg    if (dev->key && dev->key->xkbInfo)
91905b261ecSmrg	 kbd= dev;
9204642e01fSmrg    else kbd= inputInfo.keyboard;
92105b261ecSmrg    xkbi= kbd->key->xkbInfo;
92205b261ecSmrg
92305b261ecSmrg    if (changes==NULL) {
92405b261ecSmrg	changes= &my_changes;
9256747b715Smrg	memset((char *)changes, 0, sizeof(XkbChangesRec));
92605b261ecSmrg    }
92705b261ecSmrg
9286747b715Smrg    kb_changed= FALSE;
92905b261ecSmrg    affected= changed_leds;
93005b261ecSmrg    oldState= sli->effectiveState;
93105b261ecSmrg    for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
93205b261ecSmrg	if ((affected&bit)==0)
93305b261ecSmrg	    continue;
93405b261ecSmrg	affected&= ~bit;
93505b261ecSmrg	map= &sli->maps[i];
93605b261ecSmrg	if (map->flags&XkbIM_NoExplicit) {
93705b261ecSmrg	    sli->explicitState&= ~bit;
93805b261ecSmrg	    continue;
93905b261ecSmrg	}
94005b261ecSmrg	if (map->flags&XkbIM_LEDDrivesKB) {
94105b261ecSmrg	    Bool on= ((sli->explicitState&bit)!=0);
94205b261ecSmrg	    if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes))
9436747b715Smrg		kb_changed= TRUE;
94405b261ecSmrg	}
94505b261ecSmrg    }
94605b261ecSmrg    sli->effectiveState= (sli->autoState|sli->explicitState);
94705b261ecSmrg    affected= sli->effectiveState^oldState;
94805b261ecSmrg
94905b261ecSmrg    if (ed==NULL) {
95005b261ecSmrg	ed= &my_ed;
9516747b715Smrg	memset((char *)ed, 0, sizeof(xkbExtensionDeviceNotify));
95205b261ecSmrg    }
95305b261ecSmrg    else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&&
95405b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
95505b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
95605b261ecSmrg    }
95705b261ecSmrg
95805b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault))
95905b261ecSmrg	changes->indicators.state_changes|= affected;
96005b261ecSmrg    if (affected) {
96105b261ecSmrg	ed->reason|=		XkbXI_IndicatorStateMask;
96205b261ecSmrg	ed->ledClass= 		sli->class;
96305b261ecSmrg	ed->ledID=		sli->id;
96405b261ecSmrg	ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
96505b261ecSmrg	ed->ledState=		sli->effectiveState;
9666747b715Smrg	ed->unsupported=	0;
96705b261ecSmrg	ed->supported=		XkbXI_AllFeaturesMask;
96805b261ecSmrg    }
96905b261ecSmrg
97005b261ecSmrg    if (kb_changed) {
97105b261ecSmrg	XkbComputeDerivedState(kbd->key->xkbInfo);
97205b261ecSmrg	XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause);
97305b261ecSmrg    }
97405b261ecSmrg
97505b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
97605b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
97705b261ecSmrg    if (changes || ed)
97805b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
97905b261ecSmrg    if (kb_changed)
98005b261ecSmrg	XkbUpdateAllDeviceIndicators(NULL,cause);
98105b261ecSmrg    return;
98205b261ecSmrg}
983