xkbLEDs.c revision 05b261ec
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#define NEED_EVENTS 1
3505b261ecSmrg#include <X11/X.h>
3605b261ecSmrg#include <X11/Xproto.h>
3705b261ecSmrg#include "misc.h"
3805b261ecSmrg#include "inputstr.h"
3905b261ecSmrg
4005b261ecSmrg#include <X11/extensions/XI.h>
4105b261ecSmrg#include <xkbsrv.h>
4205b261ecSmrg#include "xkb.h"
4305b261ecSmrg
4405b261ecSmrg/***====================================================================***/
4505b261ecSmrg
4605b261ecSmrg	/*
4705b261ecSmrg	 * unsigned
4805b261ecSmrg	 * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
4905b261ecSmrg	 *
5005b261ecSmrg	 * Given a keyboard and a set of state components that have changed,
5105b261ecSmrg	 * this function returns the indicators on the default keyboard
5205b261ecSmrg	 * feedback that might be affected.   It also reports whether or not
5305b261ecSmrg	 * any extension devices might be affected in check_devs_rtrn.
5405b261ecSmrg	 */
5505b261ecSmrg
5605b261ecSmrgunsigned
5705b261ecSmrgXkbIndicatorsToUpdate(	DeviceIntPtr	dev,
5805b261ecSmrg			unsigned long 	state_changes,
5905b261ecSmrg			Bool		enable_changes)
6005b261ecSmrg{
6105b261ecSmrgregister unsigned	update=	0;
6205b261ecSmrgXkbSrvLedInfoPtr	sli;
6305b261ecSmrg
6405b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
6505b261ecSmrg
6605b261ecSmrg    if (!sli)
6705b261ecSmrg        return update;
6805b261ecSmrg
6905b261ecSmrg    if (state_changes&(XkbModifierStateMask|XkbGroupStateMask))
7005b261ecSmrg	update|= sli->usesEffective;
7105b261ecSmrg    if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask))
7205b261ecSmrg	update|= sli->usesBase;
7305b261ecSmrg    if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask))
7405b261ecSmrg	update|= sli->usesLatched;
7505b261ecSmrg    if (state_changes&(XkbModifierLockMask|XkbGroupLockMask))
7605b261ecSmrg	update|= sli->usesLocked;
7705b261ecSmrg    if (state_changes&XkbCompatStateMask)
7805b261ecSmrg	update|= sli->usesCompat;
7905b261ecSmrg    if (enable_changes)
8005b261ecSmrg	update|= sli->usesControls;
8105b261ecSmrg    return update;
8205b261ecSmrg}
8305b261ecSmrg
8405b261ecSmrg/***====================================================================***/
8505b261ecSmrg
8605b261ecSmrg	/*
8705b261ecSmrg	 * Bool
8805b261ecSmrg	 *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
8905b261ecSmrg	 *
9005b261ecSmrg	 * Some indicators "drive" the keyboard when their state is explicitly
9105b261ecSmrg	 * changed, as described in section 9.2.1 of the XKB protocol spec.
9205b261ecSmrg	 * This function updates the state and controls for the keyboard
9305b261ecSmrg	 * specified by 'xkbi' to reflect any changes that are required
9405b261ecSmrg	 * when the indicator described by 'map' is turned on or off.  The
9505b261ecSmrg	 * extent of the changes is reported in change, which must be defined.
9605b261ecSmrg	 */
9705b261ecSmrgstatic Bool
9805b261ecSmrgXkbApplyLEDChangeToKeyboard(	XkbSrvInfoPtr		xkbi,
9905b261ecSmrg				XkbIndicatorMapPtr	map,
10005b261ecSmrg				Bool			on,
10105b261ecSmrg				XkbChangesPtr		change)
10205b261ecSmrg{
10305b261ecSmrgBool		ctrlChange,stateChange;
10405b261ecSmrgXkbStatePtr	state;
10505b261ecSmrg
10605b261ecSmrg    if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0))
10705b261ecSmrg	return False;
10805b261ecSmrg    ctrlChange= stateChange= False;
10905b261ecSmrg    if (map->ctrls) {
11005b261ecSmrg	XkbControlsPtr	ctrls= xkbi->desc->ctrls;
11105b261ecSmrg	unsigned 	old;
11205b261ecSmrg
11305b261ecSmrg	old= ctrls->enabled_ctrls;
11405b261ecSmrg	if (on)	ctrls->enabled_ctrls|= map->ctrls;
11505b261ecSmrg	else	ctrls->enabled_ctrls&= ~map->ctrls;
11605b261ecSmrg	if (old!=ctrls->enabled_ctrls) {
11705b261ecSmrg	    change->ctrls.changed_ctrls= XkbControlsEnabledMask;
11805b261ecSmrg	    change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls;
11905b261ecSmrg	    ctrlChange= True;
12005b261ecSmrg	}
12105b261ecSmrg    }
12205b261ecSmrg    state= &xkbi->state;
12305b261ecSmrg    if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) {
12405b261ecSmrg	register int i;
12505b261ecSmrg	register unsigned bit,match;
12605b261ecSmrg
12705b261ecSmrg	if (on)	match= (map->groups)&XkbAllGroupsMask;
12805b261ecSmrg	else 	match= (~map->groups)&XkbAllGroupsMask;
12905b261ecSmrg	if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) {
13005b261ecSmrg	    for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
13105b261ecSmrg		if (bit&match)
13205b261ecSmrg		    break;
13305b261ecSmrg	    }
13405b261ecSmrg	    if (map->which_groups&XkbIM_UseLatched)
13505b261ecSmrg		XkbLatchGroup(xkbi->device,0); /* unlatch group */
13605b261ecSmrg	    state->locked_group= i;
13705b261ecSmrg	    stateChange= True;
13805b261ecSmrg	}
13905b261ecSmrg	else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) {
14005b261ecSmrg	    for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
14105b261ecSmrg		if (bit&match)
14205b261ecSmrg		    break;
14305b261ecSmrg	    }
14405b261ecSmrg	    state->locked_group= 0;
14505b261ecSmrg	    XkbLatchGroup(xkbi->device,i);
14605b261ecSmrg	    stateChange= True;
14705b261ecSmrg	}
14805b261ecSmrg    }
14905b261ecSmrg    if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) {
15005b261ecSmrg	if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) {
15105b261ecSmrg	    register unsigned long old;
15205b261ecSmrg	    old= state->locked_mods;
15305b261ecSmrg	    if (on)	state->locked_mods|= map->mods.mask;
15405b261ecSmrg	    else	state->locked_mods&= ~map->mods.mask;
15505b261ecSmrg	    if (state->locked_mods!=old)
15605b261ecSmrg		stateChange= True;
15705b261ecSmrg	}
15805b261ecSmrg	if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) {
15905b261ecSmrg	    register unsigned long newmods;
16005b261ecSmrg	    newmods= state->latched_mods;
16105b261ecSmrg	    if (on)	newmods|=  map->mods.mask;
16205b261ecSmrg	    else	newmods&= ~map->mods.mask;
16305b261ecSmrg	    if (newmods!=state->locked_mods) {
16405b261ecSmrg		newmods&= map->mods.mask;
16505b261ecSmrg		XkbLatchModifiers(xkbi->device,map->mods.mask,newmods);
16605b261ecSmrg		stateChange= True;
16705b261ecSmrg	    }
16805b261ecSmrg	}
16905b261ecSmrg    }
17005b261ecSmrg    return (stateChange || ctrlChange);
17105b261ecSmrg}
17205b261ecSmrg
17305b261ecSmrg	/*
17405b261ecSmrg	 * Bool
17505b261ecSmrg	 * ComputeAutoState(map,state,ctrls)
17605b261ecSmrg	 *
17705b261ecSmrg	 * This function reports the effect of applying the specified
17805b261ecSmrg	 * indicator map given the specified state and controls, as
17905b261ecSmrg	 * described in section 9.2 of the XKB protocol specification.
18005b261ecSmrg	 */
18105b261ecSmrg
18205b261ecSmrgstatic Bool
18305b261ecSmrgComputeAutoState(	XkbIndicatorMapPtr	map,
18405b261ecSmrg			XkbStatePtr 		state,
18505b261ecSmrg			XkbControlsPtr 		ctrls)
18605b261ecSmrg{
18705b261ecSmrgBool 			on;
18805b261ecSmrgCARD8 			mods,group;
18905b261ecSmrg
19005b261ecSmrg    on= False;
19105b261ecSmrg    mods= group= 0;
19205b261ecSmrg    if (map->which_mods&XkbIM_UseAnyMods) {
19305b261ecSmrg	if (map->which_mods&XkbIM_UseBase)
19405b261ecSmrg	    mods|= state->base_mods;
19505b261ecSmrg	if (map->which_mods&XkbIM_UseLatched)
19605b261ecSmrg	    mods|= state->latched_mods;
19705b261ecSmrg	if (map->which_mods&XkbIM_UseLocked)
19805b261ecSmrg	    mods|= state->locked_mods;
19905b261ecSmrg	if (map->which_mods&XkbIM_UseEffective)
20005b261ecSmrg	    mods|= state->mods;
20105b261ecSmrg	if (map->which_mods&XkbIM_UseCompat)
20205b261ecSmrg	    mods|= state->compat_state;
20305b261ecSmrg	on = ((map->mods.mask&mods)!=0);
20405b261ecSmrg	on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0));
20505b261ecSmrg    }
20605b261ecSmrg    if (map->which_groups&XkbIM_UseAnyGroup) {
20705b261ecSmrg	if (map->which_groups&XkbIM_UseBase)
20805b261ecSmrg	    group|= (1L << state->base_group);
20905b261ecSmrg	if (map->which_groups&XkbIM_UseLatched)
21005b261ecSmrg	    group|= (1L << state->latched_group);
21105b261ecSmrg	if (map->which_groups&XkbIM_UseLocked)
21205b261ecSmrg	    group|= (1L << state->locked_group);
21305b261ecSmrg	if (map->which_groups&XkbIM_UseEffective)
21405b261ecSmrg	    group|= (1L << state->group);
21505b261ecSmrg	on = on||(((map->groups&group)!=0)||(map->groups==0));
21605b261ecSmrg    }
21705b261ecSmrg    if (map->ctrls)
21805b261ecSmrg	on = on||(ctrls->enabled_ctrls&map->ctrls);
21905b261ecSmrg    return on;
22005b261ecSmrg}
22105b261ecSmrg
22205b261ecSmrg
22305b261ecSmrgstatic void
22405b261ecSmrgXkbUpdateLedAutoState(	DeviceIntPtr			dev,
22505b261ecSmrg			XkbSrvLedInfoPtr		sli,
22605b261ecSmrg			unsigned			maps_to_check,
22705b261ecSmrg			xkbExtensionDeviceNotify *	ed,
22805b261ecSmrg			XkbChangesPtr			changes,
22905b261ecSmrg			XkbEventCausePtr		cause)
23005b261ecSmrg{
23105b261ecSmrgDeviceIntPtr			kbd;
23205b261ecSmrgXkbStatePtr			state;
23305b261ecSmrgXkbControlsPtr			ctrls;
23405b261ecSmrgXkbChangesRec			my_changes;
23505b261ecSmrgxkbExtensionDeviceNotify	my_ed;
23605b261ecSmrgregister unsigned		i,bit,affected;
23705b261ecSmrgregister XkbIndicatorMapPtr	map;
23805b261ecSmrgunsigned			oldState;
23905b261ecSmrg
24005b261ecSmrg    if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0))
24105b261ecSmrg	return;
24205b261ecSmrg
24305b261ecSmrg    if (dev->key && dev->key->xkbInfo)
24405b261ecSmrg	 kbd= dev;
24505b261ecSmrg    else kbd= (DeviceIntPtr)LookupKeyboardDevice();
24605b261ecSmrg
24705b261ecSmrg    state= &kbd->key->xkbInfo->state;
24805b261ecSmrg    ctrls= kbd->key->xkbInfo->desc->ctrls;
24905b261ecSmrg    affected= maps_to_check;
25005b261ecSmrg    oldState= sli->effectiveState;
25105b261ecSmrg    sli->autoState&= ~affected;
25205b261ecSmrg    for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
25305b261ecSmrg	if ((affected&bit)==0)
25405b261ecSmrg	    continue;
25505b261ecSmrg	affected&= ~bit;
25605b261ecSmrg	map= &sli->maps[i];
25705b261ecSmrg	if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls))
25805b261ecSmrg	    sli->autoState|= bit;
25905b261ecSmrg    }
26005b261ecSmrg    sli->effectiveState= (sli->autoState|sli->explicitState);
26105b261ecSmrg    affected= sli->effectiveState^oldState;
26205b261ecSmrg    if (affected==0)
26305b261ecSmrg	return;
26405b261ecSmrg
26505b261ecSmrg    if (ed==NULL) {
26605b261ecSmrg	ed= &my_ed;
26705b261ecSmrg	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
26805b261ecSmrg    }
26905b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
27005b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
27105b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
27205b261ecSmrg    }
27305b261ecSmrg
27405b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
27505b261ecSmrg	if (changes==NULL) {
27605b261ecSmrg	    changes= &my_changes;
27705b261ecSmrg	    bzero((char *)changes,sizeof(XkbChangesRec));
27805b261ecSmrg	}
27905b261ecSmrg	changes->indicators.state_changes|= affected;
28005b261ecSmrg    }
28105b261ecSmrg
28205b261ecSmrg    ed->reason|=	XkbXI_IndicatorStateMask;
28305b261ecSmrg    ed->ledClass= 	sli->class;
28405b261ecSmrg    ed->ledID=		sli->id;
28505b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
28605b261ecSmrg    ed->ledState=	sli->effectiveState;
28705b261ecSmrg    ed->unsupported|=	XkbXI_IndicatorStateMask;
28805b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
28905b261ecSmrg
29005b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
29105b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
29205b261ecSmrg    if (changes || ed)
29305b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
29405b261ecSmrg    return;
29505b261ecSmrg}
29605b261ecSmrg
29705b261ecSmrgstatic void
29805b261ecSmrgXkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause)
29905b261ecSmrg{
30005b261ecSmrgDeviceIntPtr		edev;
30105b261ecSmrgXkbSrvLedInfoPtr	sli;
30205b261ecSmrg
30305b261ecSmrg    for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) {
30405b261ecSmrg	if (edev->kbdfeed) {
30505b261ecSmrg	    KbdFeedbackPtr	kf;
30605b261ecSmrg	    for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) {
30705b261ecSmrg		if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL))
30805b261ecSmrg		    continue;
30905b261ecSmrg		sli= kf->xkb_sli;
31005b261ecSmrg		XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
31105b261ecSmrg								changes,cause);
31205b261ecSmrg
31305b261ecSmrg	    }
31405b261ecSmrg	}
31505b261ecSmrg	if (edev->leds) {
31605b261ecSmrg	    LedFeedbackPtr	lf;
31705b261ecSmrg	    for (lf=edev->leds;lf!=NULL;lf=lf->next) {
31805b261ecSmrg		if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL))
31905b261ecSmrg		    continue;
32005b261ecSmrg		sli= lf->xkb_sli;
32105b261ecSmrg		XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
32205b261ecSmrg								changes,cause);
32305b261ecSmrg
32405b261ecSmrg	    }
32505b261ecSmrg	}
32605b261ecSmrg    }
32705b261ecSmrg    return;
32805b261ecSmrg}
32905b261ecSmrg
33005b261ecSmrg
33105b261ecSmrg/***====================================================================***/
33205b261ecSmrg
33305b261ecSmrg	/*
33405b261ecSmrg	 * void
33505b261ecSmrg	 * XkbSetIndicators(dev,affect,values,cause)
33605b261ecSmrg	 *
33705b261ecSmrg	 * Attempts to change the indicators specified in 'affect' to the
33805b261ecSmrg	 * states specified in 'values' for the default keyboard feedback
33905b261ecSmrg	 * on the keyboard specified by 'dev.'   Attempts to change indicator
34005b261ecSmrg	 * state might be ignored or have no affect, depending on the XKB
34105b261ecSmrg	 * indicator map for any affected indicators, as described in section
34205b261ecSmrg	 * 9.2 of the XKB protocol specification.
34305b261ecSmrg	 *
34405b261ecSmrg	 * If 'changes' is non-NULL, this function notes any changes to the
34505b261ecSmrg	 * keyboard state, controls, or indicator state that result from this
34605b261ecSmrg	 * attempted change.   If 'changes' is NULL, this function generates
34705b261ecSmrg	 * XKB events to report any such changes to interested clients.
34805b261ecSmrg	 *
34905b261ecSmrg	 * If 'cause' is non-NULL, it specifies the reason for the change,
35005b261ecSmrg	 * as reported in some XKB events.   If it is NULL, this function
35105b261ecSmrg	 * assumes that the change is the result of a core protocol
35205b261ecSmrg	 * ChangeKeyboardMapping request.
35305b261ecSmrg	 */
35405b261ecSmrg
35505b261ecSmrgvoid
35605b261ecSmrgXkbSetIndicators(	DeviceIntPtr		dev,
35705b261ecSmrg			CARD32			affect,
35805b261ecSmrg			CARD32			values,
35905b261ecSmrg			XkbEventCausePtr	cause)
36005b261ecSmrg{
36105b261ecSmrgXkbSrvLedInfoPtr		sli;
36205b261ecSmrgXkbChangesRec			changes;
36305b261ecSmrgxkbExtensionDeviceNotify	ed;
36405b261ecSmrgunsigned 			side_affected;
36505b261ecSmrg
36605b261ecSmrg    bzero((char *)&changes,sizeof(XkbChangesRec));
36705b261ecSmrg    bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
36805b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
36905b261ecSmrg    sli->explicitState&= ~affect;
37005b261ecSmrg    sli->explicitState|= (affect&values);
37105b261ecSmrg    XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause);
37205b261ecSmrg
37305b261ecSmrg    side_affected= 0;
37405b261ecSmrg    if (changes.state_changes!=0)
37505b261ecSmrg	side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False);
37605b261ecSmrg    if (changes.ctrls.enabled_ctrls_changes)
37705b261ecSmrg	side_affected|= sli->usesControls;
37805b261ecSmrg
37905b261ecSmrg    if (side_affected) {
38005b261ecSmrg	XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause);
38105b261ecSmrg	affect|= side_affected;
38205b261ecSmrg    }
38305b261ecSmrg    if (changes.state_changes || changes.ctrls.enabled_ctrls_changes)
38405b261ecSmrg	XkbUpdateAllDeviceIndicators(NULL,cause);
38505b261ecSmrg
38605b261ecSmrg    XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause);
38705b261ecSmrg    return;
38805b261ecSmrg}
38905b261ecSmrg
39005b261ecSmrg/***====================================================================***/
39105b261ecSmrg
39205b261ecSmrg/***====================================================================***/
39305b261ecSmrg
39405b261ecSmrg	/*
39505b261ecSmrg	 * void
39605b261ecSmrg	 * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
39705b261ecSmrg	 *
39805b261ecSmrg	 * Applies the indicator maps for any indicators specified in
39905b261ecSmrg	 * 'update' from the default keyboard feedback on the device
40005b261ecSmrg	 * specified by 'dev.'
40105b261ecSmrg	 *
40205b261ecSmrg	 * If 'changes' is NULL, this function generates and XKB events
40305b261ecSmrg	 * required to report the necessary changes, otherwise it simply
40405b261ecSmrg	 * notes the indicators with changed state.
40505b261ecSmrg	 *
40605b261ecSmrg	 * If 'check_edevs' is True, this function also checks the indicator
40705b261ecSmrg	 * maps for any open extension devices that have them, and updates
40805b261ecSmrg	 * the state of any extension device indicators as necessary.
40905b261ecSmrg	 */
41005b261ecSmrg
41105b261ecSmrgvoid
41205b261ecSmrgXkbUpdateIndicators(	DeviceIntPtr		dev,
41305b261ecSmrg			register CARD32		update,
41405b261ecSmrg			Bool			check_edevs,
41505b261ecSmrg			XkbChangesPtr		changes,
41605b261ecSmrg			XkbEventCausePtr	cause)
41705b261ecSmrg{
41805b261ecSmrgXkbSrvLedInfoPtr	sli;
41905b261ecSmrg
42005b261ecSmrg    sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
42105b261ecSmrg    XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause);
42205b261ecSmrg    if (check_edevs)
42305b261ecSmrg	XkbUpdateAllDeviceIndicators(changes,cause);
42405b261ecSmrg    return;
42505b261ecSmrg}
42605b261ecSmrg
42705b261ecSmrg/***====================================================================***/
42805b261ecSmrg
42905b261ecSmrg/***====================================================================***/
43005b261ecSmrg
43105b261ecSmrg	/*
43205b261ecSmrg	 * void
43305b261ecSmrg	 * XkbCheckIndicatorMaps(dev,sli,which)
43405b261ecSmrg	 *
43505b261ecSmrg	 * Updates the 'indicator accelerators' for the indicators specified
43605b261ecSmrg	 * by 'which' in the feedback specified by 'sli.' The indicator
43705b261ecSmrg	 * accelerators are internal to the server and are used to simplify
43805b261ecSmrg	 * and speed up the process of figuring out which indicators might
43905b261ecSmrg	 * be affected by a particular change in keyboard state or controls.
44005b261ecSmrg	 */
44105b261ecSmrg
44205b261ecSmrgvoid
44305b261ecSmrgXkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which)
44405b261ecSmrg{
44505b261ecSmrgregister unsigned	i,bit;
44605b261ecSmrgXkbIndicatorMapPtr	map;
44705b261ecSmrgXkbDescPtr		xkb;
44805b261ecSmrg
44905b261ecSmrg    if ((sli->flags&XkbSLI_HasOwnState)==0)
45005b261ecSmrg	dev= (DeviceIntPtr)LookupKeyboardDevice();
45105b261ecSmrg
45205b261ecSmrg    sli->usesBase&=	 ~which;
45305b261ecSmrg    sli->usesLatched&=	 ~which;
45405b261ecSmrg    sli->usesLocked&=	 ~which;
45505b261ecSmrg    sli->usesEffective&= ~which;
45605b261ecSmrg    sli->usesCompat&=	 ~which;
45705b261ecSmrg    sli->usesControls&=	 ~which;
45805b261ecSmrg    sli->mapsPresent&=	 ~which;
45905b261ecSmrg
46005b261ecSmrg    xkb= dev->key->xkbInfo->desc;
46105b261ecSmrg    for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) {
46205b261ecSmrg	if (which&bit) {
46305b261ecSmrg	    CARD8		what;
46405b261ecSmrg
46505b261ecSmrg	    if (!XkbIM_InUse(map))
46605b261ecSmrg		continue;
46705b261ecSmrg	    sli->mapsPresent|= bit;
46805b261ecSmrg
46905b261ecSmrg	    what= (map->which_mods|map->which_groups);
47005b261ecSmrg	    if (what&XkbIM_UseBase)
47105b261ecSmrg		 sli->usesBase|= bit;
47205b261ecSmrg	    if (what&XkbIM_UseLatched)
47305b261ecSmrg		 sli->usesLatched|= bit;
47405b261ecSmrg	    if (what&XkbIM_UseLocked)
47505b261ecSmrg		 sli->usesLocked|= bit;
47605b261ecSmrg	    if (what&XkbIM_UseEffective)
47705b261ecSmrg		 sli->usesEffective|= bit;
47805b261ecSmrg	    if (what&XkbIM_UseCompat)
47905b261ecSmrg		 sli->usesCompat|= bit;
48005b261ecSmrg	    if (map->ctrls)
48105b261ecSmrg		 sli->usesControls|= bit;
48205b261ecSmrg
48305b261ecSmrg	    map->mods.mask= map->mods.real_mods;
48405b261ecSmrg	    if (map->mods.vmods!=0) {
48505b261ecSmrg		map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods);
48605b261ecSmrg	    }
48705b261ecSmrg	}
48805b261ecSmrg    }
48905b261ecSmrg    sli->usedComponents= 0;
49005b261ecSmrg    if (sli->usesBase)
49105b261ecSmrg	sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask;
49205b261ecSmrg    if (sli->usesLatched)
49305b261ecSmrg	sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask;
49405b261ecSmrg    if (sli->usesLocked)
49505b261ecSmrg	sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask;
49605b261ecSmrg    if (sli->usesEffective)
49705b261ecSmrg	sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask;
49805b261ecSmrg    if (sli->usesCompat)
49905b261ecSmrg	sli->usedComponents|= XkbCompatStateMask;
50005b261ecSmrg    return;
50105b261ecSmrg}
50205b261ecSmrg
50305b261ecSmrg/***====================================================================***/
50405b261ecSmrg
50505b261ecSmrg	/*
50605b261ecSmrg	 * XkbSrvLedInfoPtr
50705b261ecSmrg	 * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
50805b261ecSmrg	 *
50905b261ecSmrg	 * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
51005b261ecSmrg	 * 'kf' or 'lf' on the keyboard specified by 'dev.'
51105b261ecSmrg	 *
51205b261ecSmrg	 * If 'needed_parts' is non-zero, this function makes sure that any
51305b261ecSmrg	 * of the parts speicified therein are allocated.
51405b261ecSmrg	 */
51505b261ecSmrgXkbSrvLedInfoPtr
51605b261ecSmrgXkbAllocSrvLedInfo(	DeviceIntPtr		dev,
51705b261ecSmrg			KbdFeedbackPtr		kf,
51805b261ecSmrg			LedFeedbackPtr		lf,
51905b261ecSmrg			unsigned		needed_parts)
52005b261ecSmrg{
52105b261ecSmrgXkbSrvLedInfoPtr	sli;
52205b261ecSmrgBool			checkAccel;
52305b261ecSmrgBool			checkNames;
52405b261ecSmrg
52505b261ecSmrg    sli= NULL;
52605b261ecSmrg    checkAccel= checkNames= False;
52705b261ecSmrg    if ((kf!=NULL)&&(kf->xkb_sli==NULL)) {
52805b261ecSmrg	kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec);
52905b261ecSmrg	if (sli==NULL)
53005b261ecSmrg	    return NULL; /* ALLOCATION ERROR */
53105b261ecSmrg	if (dev->key && dev->key->xkbInfo)
53205b261ecSmrg	     sli->flags= XkbSLI_HasOwnState;
53305b261ecSmrg	else sli->flags= 0;
53405b261ecSmrg	sli->class=	KbdFeedbackClass;
53505b261ecSmrg	sli->id=	kf->ctrl.id;
53605b261ecSmrg	sli->fb.kf=	kf;
53705b261ecSmrg
53805b261ecSmrg	sli->autoState=		0;
53905b261ecSmrg	sli->explicitState=	kf->ctrl.leds;
54005b261ecSmrg	sli->effectiveState=	kf->ctrl.leds;
54105b261ecSmrg
54205b261ecSmrg	if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) {
54305b261ecSmrg	    XkbDescPtr	xkb;
54405b261ecSmrg	    xkb= dev->key->xkbInfo->desc;
54505b261ecSmrg	    sli->flags|= 		XkbSLI_IsDefault;
54605b261ecSmrg	    sli->physIndicators=	xkb->indicators->phys_indicators;
54705b261ecSmrg	    sli->names=			xkb->names->indicators;
54805b261ecSmrg	    sli->maps=			xkb->indicators->maps;
54905b261ecSmrg	    checkNames= checkAccel=	True;
55005b261ecSmrg	}
55105b261ecSmrg	else {
55205b261ecSmrg	    sli->physIndicators=	XkbAllIndicatorsMask;
55305b261ecSmrg	    sli->names=			NULL;
55405b261ecSmrg	    sli->maps=			NULL;
55505b261ecSmrg	}
55605b261ecSmrg    }
55705b261ecSmrg    else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) {
55805b261ecSmrg	XkbDescPtr	xkb;
55905b261ecSmrg	xkb= dev->key->xkbInfo->desc;
56005b261ecSmrg	sli->physIndicators=	xkb->indicators->phys_indicators;
56105b261ecSmrg	if (xkb->names->indicators!=sli->names) {
56205b261ecSmrg	    checkNames= True;
56305b261ecSmrg	    sli->names= xkb->names->indicators;
56405b261ecSmrg	}
56505b261ecSmrg	if (xkb->indicators->maps!=sli->maps) {
56605b261ecSmrg	    checkAccel= True;
56705b261ecSmrg	    sli->maps= xkb->indicators->maps;
56805b261ecSmrg	}
56905b261ecSmrg    }
57005b261ecSmrg    else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) {
57105b261ecSmrg	lf->xkb_sli= sli= _XkbTypedCalloc(1,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    }
58805b261ecSmrg    if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
58905b261ecSmrg	sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
59005b261ecSmrg    if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
59105b261ecSmrg	sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
59205b261ecSmrg    if (checkNames) {
59305b261ecSmrg	register unsigned i,bit;
59405b261ecSmrg	sli->namesPresent=	0;
59505b261ecSmrg	for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
59605b261ecSmrg	    if (sli->names[i]!=None)
59705b261ecSmrg		sli->namesPresent|= bit;
59805b261ecSmrg	}
59905b261ecSmrg    }
60005b261ecSmrg    if (checkAccel)
60105b261ecSmrg	 XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask);
60205b261ecSmrg    return sli;
60305b261ecSmrg}
60405b261ecSmrg
60505b261ecSmrgvoid
60605b261ecSmrgXkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
60705b261ecSmrg{
60805b261ecSmrg    if ((sli->flags&XkbSLI_IsDefault)==0) {
60905b261ecSmrg	if (sli->maps)	_XkbFree(sli->maps);
61005b261ecSmrg	if (sli->names)	_XkbFree(sli->names);
61105b261ecSmrg    }
61205b261ecSmrg    sli->maps= NULL;
61305b261ecSmrg    sli->names= NULL;
61405b261ecSmrg    _XkbFree(sli);
61505b261ecSmrg    return;
61605b261ecSmrg}
61705b261ecSmrg
61805b261ecSmrg
61905b261ecSmrg/***====================================================================***/
62005b261ecSmrg
62105b261ecSmrg	/*
62205b261ecSmrg	 * XkbSrvLedInfoPtr
62305b261ecSmrg	 * XkbFindSrvLedInfo(dev,class,id,needed_parts)
62405b261ecSmrg	 *
62505b261ecSmrg	 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
62605b261ecSmrg	 * on the device specified by 'dev.'   If the class and id specify
62705b261ecSmrg	 * a valid device feedback, this function returns the existing
62805b261ecSmrg	 * feedback or allocates a new one.
62905b261ecSmrg	 *
63005b261ecSmrg	 */
63105b261ecSmrg
63205b261ecSmrgXkbSrvLedInfoPtr
63305b261ecSmrgXkbFindSrvLedInfo(	DeviceIntPtr		dev,
63405b261ecSmrg			unsigned		class,
63505b261ecSmrg			unsigned		id,
63605b261ecSmrg			unsigned		needed_parts)
63705b261ecSmrg{
63805b261ecSmrgXkbSrvLedInfoPtr	sli;
63905b261ecSmrg
64005b261ecSmrg    /* optimization to check for most common case */
64105b261ecSmrg    if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) {
64205b261ecSmrg	XkbSrvLedInfoPtr	sli;
64305b261ecSmrg	sli= dev->kbdfeed->xkb_sli;
64405b261ecSmrg	if (dev->kbdfeed->xkb_sli==NULL) {
64505b261ecSmrg	    sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts);
64605b261ecSmrg	    dev->kbdfeed->xkb_sli= sli;
64705b261ecSmrg	}
64805b261ecSmrg	return dev->kbdfeed->xkb_sli;
64905b261ecSmrg    }
65005b261ecSmrg
65105b261ecSmrg    sli= NULL;
65205b261ecSmrg    if (class==XkbDfltXIClass) {
65305b261ecSmrg	if (dev->kbdfeed)	class= KbdFeedbackClass;
65405b261ecSmrg	else if (dev->leds)	class= LedFeedbackClass;
65505b261ecSmrg	else 			return NULL;
65605b261ecSmrg    }
65705b261ecSmrg    if (class==KbdFeedbackClass) {
65805b261ecSmrg	KbdFeedbackPtr	kf;
65905b261ecSmrg	for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) {
66005b261ecSmrg	    if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) {
66105b261ecSmrg		if (kf->xkb_sli==NULL)
66205b261ecSmrg		    kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts);
66305b261ecSmrg		sli= kf->xkb_sli;
66405b261ecSmrg		break;
66505b261ecSmrg	    }
66605b261ecSmrg	}
66705b261ecSmrg    }
66805b261ecSmrg    else if (class==LedFeedbackClass) {
66905b261ecSmrg	LedFeedbackPtr	lf;
67005b261ecSmrg	for (lf=dev->leds;lf!=NULL;lf=lf->next) {
67105b261ecSmrg	    if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) {
67205b261ecSmrg		if (lf->xkb_sli==NULL)
67305b261ecSmrg		    lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts);
67405b261ecSmrg		sli= lf->xkb_sli;
67505b261ecSmrg		break;
67605b261ecSmrg	    }
67705b261ecSmrg	}
67805b261ecSmrg    }
67905b261ecSmrg    if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
68005b261ecSmrg	sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
68105b261ecSmrg    if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
68205b261ecSmrg	sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
68305b261ecSmrg    return sli;
68405b261ecSmrg}
68505b261ecSmrg
68605b261ecSmrg/***====================================================================***/
68705b261ecSmrg
68805b261ecSmrgvoid
68905b261ecSmrgXkbFlushLedEvents(	DeviceIntPtr			dev,
69005b261ecSmrg			DeviceIntPtr			kbd,
69105b261ecSmrg			XkbSrvLedInfoPtr		sli,
69205b261ecSmrg			xkbExtensionDeviceNotify *	ed,
69305b261ecSmrg			XkbChangesPtr			changes,
69405b261ecSmrg			XkbEventCausePtr		cause)
69505b261ecSmrg{
69605b261ecSmrg    if (changes) {
69705b261ecSmrg	if (changes->indicators.state_changes)
69805b261ecSmrg	    XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
69905b261ecSmrg	XkbSendNotification(kbd,changes,cause);
70005b261ecSmrg	bzero((char *)changes,sizeof(XkbChangesRec));
70105b261ecSmrg
70205b261ecSmrg	if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
70305b261ecSmrg		if (sli->effectiveState)
70405b261ecSmrg			/* it appears that the which parameter is not used */
70505b261ecSmrg			XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
70605b261ecSmrg		else
70705b261ecSmrg			XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
70805b261ecSmrg	}
70905b261ecSmrg    }
71005b261ecSmrg    if (ed && (ed->reason)) {
71105b261ecSmrg	if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask))
71205b261ecSmrg	    XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
71305b261ecSmrg	XkbSendExtensionDeviceNotify(dev,cause->client,ed);
71405b261ecSmrg    }
71505b261ecSmrg    bzero((char *)ed,sizeof(XkbExtensionDeviceNotify));
71605b261ecSmrg    return;
71705b261ecSmrg}
71805b261ecSmrg
71905b261ecSmrg/***====================================================================***/
72005b261ecSmrg
72105b261ecSmrgvoid
72205b261ecSmrgXkbApplyLedNameChanges(	DeviceIntPtr 			dev,
72305b261ecSmrg			XkbSrvLedInfoPtr		sli,
72405b261ecSmrg			unsigned			changed_names,
72505b261ecSmrg			xkbExtensionDeviceNotify *	ed,
72605b261ecSmrg			XkbChangesPtr			changes,
72705b261ecSmrg			XkbEventCausePtr		cause)
72805b261ecSmrg{
72905b261ecSmrgDeviceIntPtr			kbd;
73005b261ecSmrgXkbChangesRec			my_changes;
73105b261ecSmrgxkbExtensionDeviceNotify	my_ed;
73205b261ecSmrg
73305b261ecSmrg    if (changed_names==0)
73405b261ecSmrg	return;
73505b261ecSmrg    if (dev->key && dev->key->xkbInfo)
73605b261ecSmrg	 kbd= dev;
73705b261ecSmrg    else kbd= (DeviceIntPtr)LookupKeyboardDevice();
73805b261ecSmrg
73905b261ecSmrg    if (ed==NULL) {
74005b261ecSmrg	ed= &my_ed;
74105b261ecSmrg	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
74205b261ecSmrg    }
74305b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
74405b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
74505b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
74605b261ecSmrg    }
74705b261ecSmrg
74805b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
74905b261ecSmrg	if (changes==NULL) {
75005b261ecSmrg	   changes= &my_changes;
75105b261ecSmrg	   bzero((char *)changes,sizeof(XkbChangesRec));
75205b261ecSmrg	}
75305b261ecSmrg	changes->names.changed|= XkbIndicatorNamesMask;
75405b261ecSmrg	changes->names.changed_indicators|= changed_names;
75505b261ecSmrg    }
75605b261ecSmrg
75705b261ecSmrg    ed->reason|=	XkbXI_IndicatorNamesMask;
75805b261ecSmrg    ed->ledClass= 	sli->class;
75905b261ecSmrg    ed->ledID=		sli->id;
76005b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
76105b261ecSmrg    ed->ledState=	sli->effectiveState;
76205b261ecSmrg    ed->unsupported=	0;
76305b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
76405b261ecSmrg
76505b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
76605b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
76705b261ecSmrg    if (changes || ed)
76805b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
76905b261ecSmrg    return;
77005b261ecSmrg}
77105b261ecSmrg/***====================================================================***/
77205b261ecSmrg
77305b261ecSmrg	/*
77405b261ecSmrg	 * void
77505b261ecSmrg	 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
77605b261ecSmrg	 *
77705b261ecSmrg	 * Handles all of the secondary effects of the changes to the
77805b261ecSmrg	 * feedback specified by 'sli' on the device specified by 'dev.'
77905b261ecSmrg	 *
78005b261ecSmrg	 * If 'changed_maps' specifies any indicators, this function generates
78105b261ecSmrg	 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
78205b261ecSmrg	 * events to report the changes, and recalculates the effective
78305b261ecSmrg	 * state of each indicator with a changed map.  If any indicators
78405b261ecSmrg	 * change state, the server generates XkbExtensionDeviceNotify and
78505b261ecSmrg	 * XkbIndicatorStateNotify events as appropriate.
78605b261ecSmrg	 *
78705b261ecSmrg	 * If 'changes' is non-NULL, this function updates it to reflect
78805b261ecSmrg	 * any changes to the keyboard state or controls or to the 'core'
78905b261ecSmrg	 * indicator names, maps, or state.   If 'changes' is NULL, this
79005b261ecSmrg	 * function generates XKB events as needed to report the changes.
79105b261ecSmrg	 * If 'dev' is not a keyboard device, any changes are reported
79205b261ecSmrg	 * for the core keyboard.
79305b261ecSmrg	 *
79405b261ecSmrg	 * The 'cause' specifies the reason for the event (key event or
79505b261ecSmrg	 * request) for the change, as reported in some XKB events.
79605b261ecSmrg	 */
79705b261ecSmrg
79805b261ecSmrgvoid
79905b261ecSmrgXkbApplyLedMapChanges(	DeviceIntPtr 			dev,
80005b261ecSmrg			XkbSrvLedInfoPtr		sli,
80105b261ecSmrg			unsigned			changed_maps,
80205b261ecSmrg			xkbExtensionDeviceNotify *	ed,
80305b261ecSmrg			XkbChangesPtr			changes,
80405b261ecSmrg			XkbEventCausePtr		cause)
80505b261ecSmrg{
80605b261ecSmrgDeviceIntPtr			kbd;
80705b261ecSmrgXkbChangesRec			my_changes;
80805b261ecSmrgxkbExtensionDeviceNotify	my_ed;
80905b261ecSmrg
81005b261ecSmrg    if (changed_maps==0)
81105b261ecSmrg	return;
81205b261ecSmrg    if (dev->key && dev->key->xkbInfo)
81305b261ecSmrg	 kbd= dev;
81405b261ecSmrg    else kbd= (DeviceIntPtr)LookupKeyboardDevice();
81505b261ecSmrg
81605b261ecSmrg    if (ed==NULL) {
81705b261ecSmrg	ed= &my_ed;
81805b261ecSmrg	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
81905b261ecSmrg    }
82005b261ecSmrg    else if ((ed->reason&XkbXI_IndicatorsMask)&&
82105b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
82205b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
82305b261ecSmrg    }
82405b261ecSmrg
82505b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
82605b261ecSmrg	if (changes==NULL) {
82705b261ecSmrg	    changes= &my_changes;
82805b261ecSmrg	    bzero((char *)changes,sizeof(XkbChangesRec));
82905b261ecSmrg	}
83005b261ecSmrg	changes->indicators.map_changes|= changed_maps;
83105b261ecSmrg    }
83205b261ecSmrg
83305b261ecSmrg    XkbCheckIndicatorMaps(dev,sli,changed_maps);
83405b261ecSmrg
83505b261ecSmrg    ed->reason|=	XkbXI_IndicatorMapsMask;
83605b261ecSmrg    ed->ledClass= 	sli->class;
83705b261ecSmrg    ed->ledID=		sli->id;
83805b261ecSmrg    ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
83905b261ecSmrg    ed->ledState=	sli->effectiveState;
84005b261ecSmrg    ed->unsupported|=	XkbXI_IndicatorMapsMask;
84105b261ecSmrg    ed->supported=	XkbXI_AllFeaturesMask;
84205b261ecSmrg
84305b261ecSmrg    XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause);
84405b261ecSmrg
84505b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
84605b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
84705b261ecSmrg    if (changes || ed)
84805b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
84905b261ecSmrg    return;
85005b261ecSmrg}
85105b261ecSmrg
85205b261ecSmrg/***====================================================================***/
85305b261ecSmrg
85405b261ecSmrgvoid
85505b261ecSmrgXkbApplyLedStateChanges(DeviceIntPtr 			dev,
85605b261ecSmrg			XkbSrvLedInfoPtr		sli,
85705b261ecSmrg			unsigned			changed_leds,
85805b261ecSmrg			xkbExtensionDeviceNotify *	ed,
85905b261ecSmrg			XkbChangesPtr			changes,
86005b261ecSmrg			XkbEventCausePtr		cause)
86105b261ecSmrg{
86205b261ecSmrgXkbSrvInfoPtr			xkbi;
86305b261ecSmrgDeviceIntPtr			kbd;
86405b261ecSmrgXkbChangesRec			my_changes;
86505b261ecSmrgxkbExtensionDeviceNotify	my_ed;
86605b261ecSmrgregister unsigned		i,bit,affected;
86705b261ecSmrgXkbIndicatorMapPtr		map;
86805b261ecSmrgunsigned			oldState;
86905b261ecSmrgBool				kb_changed;
87005b261ecSmrg
87105b261ecSmrg    if (changed_leds==0)
87205b261ecSmrg	return;
87305b261ecSmrg    if (dev->key && dev->key->xkbInfo)
87405b261ecSmrg	 kbd= dev;
87505b261ecSmrg    else kbd= (DeviceIntPtr)LookupKeyboardDevice();
87605b261ecSmrg    xkbi= kbd->key->xkbInfo;
87705b261ecSmrg
87805b261ecSmrg    if (changes==NULL) {
87905b261ecSmrg	changes= &my_changes;
88005b261ecSmrg	bzero((char *)changes,sizeof(XkbChangesRec));
88105b261ecSmrg    }
88205b261ecSmrg
88305b261ecSmrg    kb_changed= False;
88405b261ecSmrg    affected= changed_leds;
88505b261ecSmrg    oldState= sli->effectiveState;
88605b261ecSmrg    for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
88705b261ecSmrg	if ((affected&bit)==0)
88805b261ecSmrg	    continue;
88905b261ecSmrg	affected&= ~bit;
89005b261ecSmrg	map= &sli->maps[i];
89105b261ecSmrg	if (map->flags&XkbIM_NoExplicit) {
89205b261ecSmrg	    sli->explicitState&= ~bit;
89305b261ecSmrg	    continue;
89405b261ecSmrg	}
89505b261ecSmrg	if (map->flags&XkbIM_LEDDrivesKB) {
89605b261ecSmrg	    Bool on= ((sli->explicitState&bit)!=0);
89705b261ecSmrg	    if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes))
89805b261ecSmrg		kb_changed= True;
89905b261ecSmrg	}
90005b261ecSmrg    }
90105b261ecSmrg    sli->effectiveState= (sli->autoState|sli->explicitState);
90205b261ecSmrg    affected= sli->effectiveState^oldState;
90305b261ecSmrg
90405b261ecSmrg    if (ed==NULL) {
90505b261ecSmrg	ed= &my_ed;
90605b261ecSmrg	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
90705b261ecSmrg    }
90805b261ecSmrg    else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&&
90905b261ecSmrg	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
91005b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
91105b261ecSmrg    }
91205b261ecSmrg
91305b261ecSmrg    if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault))
91405b261ecSmrg	changes->indicators.state_changes|= affected;
91505b261ecSmrg    if (affected) {
91605b261ecSmrg	ed->reason|=		XkbXI_IndicatorStateMask;
91705b261ecSmrg	ed->ledClass= 		sli->class;
91805b261ecSmrg	ed->ledID=		sli->id;
91905b261ecSmrg	ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
92005b261ecSmrg	ed->ledState=		sli->effectiveState;
92105b261ecSmrg	ed->unsupported|=	XkbXI_IndicatorStateMask;
92205b261ecSmrg	ed->supported=		XkbXI_AllFeaturesMask;
92305b261ecSmrg    }
92405b261ecSmrg
92505b261ecSmrg    if (kb_changed) {
92605b261ecSmrg	XkbComputeDerivedState(kbd->key->xkbInfo);
92705b261ecSmrg	XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause);
92805b261ecSmrg    }
92905b261ecSmrg
93005b261ecSmrg    if (changes!=&my_changes)	changes= NULL;
93105b261ecSmrg    if (ed!=&my_ed)		ed= NULL;
93205b261ecSmrg    if (changes || ed)
93305b261ecSmrg	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
93405b261ecSmrg    if (kb_changed)
93505b261ecSmrg	XkbUpdateAllDeviceIndicators(NULL,cause);
93605b261ecSmrg    return;
93705b261ecSmrg}
938