1064 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1064 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $Xorg: xkbLEDs.c,v 1.4 2001/05/10 19:54:01 steve Exp $ */
 | |
| /************************************************************
 | |
| Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this
 | |
| software and its documentation for any purpose and without
 | |
| fee is hereby granted, provided that the above copyright
 | |
| notice appear in all copies and that both that copyright
 | |
| notice and this permission notice appear in supporting
 | |
| documentation, and that the name of Silicon Graphics not be 
 | |
| used in advertising or publicity pertaining to distribution 
 | |
| of the software without specific prior written permission.
 | |
| Silicon Graphics makes no representation about the suitability 
 | |
| of this software for any purpose. It is provided "as is"
 | |
| without any express or implied warranty.
 | |
| 
 | |
| SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
 | |
| SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 
 | |
| AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
 | |
| GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
 | |
| DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 
 | |
| DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
 | |
| OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 | |
| THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | |
| 
 | |
| ********************************************************/
 | |
| /* $XFree86: xc/programs/Xserver/xkb/xkbLEDs.c,v 3.7 2003/07/16 01:39:10 dawes Exp $ */
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <ctype.h>
 | |
| #include <math.h>
 | |
| #define NEED_EVENTS 1
 | |
| #include <X11/X.h>
 | |
| #include <X11/Xproto.h>
 | |
| #include "misc.h"
 | |
| #include "inputstr.h"
 | |
| 
 | |
| #include "XI.h"
 | |
| #include "XKBsrv.h"
 | |
| #include "xkb.h"
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * unsigned
 | |
| 	 * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
 | |
| 	 *
 | |
| 	 * Given a keyboard and a set of state components that have changed,
 | |
| 	 * this function returns the indicators on the default keyboard 
 | |
| 	 * feedback that might be affected.   It also reports whether or not 
 | |
| 	 * any extension devices might be affected in check_devs_rtrn.
 | |
| 	 */
 | |
| 
 | |
| unsigned
 | |
| XkbIndicatorsToUpdate(	DeviceIntPtr	dev,
 | |
| 			unsigned long 	state_changes,
 | |
| 			Bool		enable_changes)
 | |
| {
 | |
| register unsigned	update=	0;
 | |
| XkbSrvLedInfoPtr	sli;
 | |
| 
 | |
|     sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
 | |
| 
 | |
|     if (state_changes&(XkbModifierStateMask|XkbGroupStateMask))
 | |
| 	update|= sli->usesEffective;
 | |
|     if (state_changes&(XkbModifierBaseMask|XkbGroupBaseMask))
 | |
| 	update|= sli->usesBase;
 | |
|     if (state_changes&(XkbModifierLatchMask|XkbGroupLatchMask))
 | |
| 	update|= sli->usesLatched;
 | |
|     if (state_changes&(XkbModifierLockMask|XkbGroupLockMask))
 | |
| 	update|= sli->usesLocked;
 | |
|     if (state_changes&XkbCompatStateMask)
 | |
| 	update|= sli->usesCompat;
 | |
|     if (enable_changes)
 | |
| 	update|= sli->usesControls;
 | |
|     return update;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * Bool
 | |
| 	 * XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
 | |
| 	 *
 | |
| 	 * Some indicators "drive" the keyboard when their state is explicitly 
 | |
| 	 * changed, as described in section 9.2.1 of the XKB protocol spec.
 | |
| 	 * This function updates the state and controls for the keyboard 
 | |
| 	 * specified by 'xkbi' to reflect any changes that are required 
 | |
| 	 * when the indicator described by 'map' is turned on or off.  The
 | |
| 	 * extent of the changes is reported in change, which must be defined.
 | |
| 	 */
 | |
| Bool
 | |
| XkbApplyLEDChangeToKeyboard(	XkbSrvInfoPtr		xkbi,
 | |
| 				XkbIndicatorMapPtr	map,
 | |
| 				Bool			on,
 | |
| 				XkbChangesPtr		change)
 | |
| {
 | |
| Bool		ctrlChange,stateChange;
 | |
| XkbStatePtr	state;
 | |
| 
 | |
|     if ((map->flags&XkbIM_NoExplicit)||((map->flags&XkbIM_LEDDrivesKB)==0))
 | |
| 	return False;
 | |
|     ctrlChange= stateChange= False;
 | |
|     if (map->ctrls) {
 | |
| 	XkbControlsPtr	ctrls= xkbi->desc->ctrls;
 | |
| 	unsigned 	old;
 | |
| 
 | |
| 	old= ctrls->enabled_ctrls;
 | |
| 	if (on)	ctrls->enabled_ctrls|= map->ctrls;
 | |
| 	else	ctrls->enabled_ctrls&= ~map->ctrls;
 | |
| 	if (old!=ctrls->enabled_ctrls) {
 | |
| 	    change->ctrls.changed_ctrls= XkbControlsEnabledMask;
 | |
| 	    change->ctrls.enabled_ctrls_changes= old^ctrls->enabled_ctrls;
 | |
| 	    ctrlChange= True;
 | |
| 	}
 | |
|     }
 | |
|     state= &xkbi->state;
 | |
|     if ((map->groups)&&((map->which_groups&(~XkbIM_UseBase))!=0)) {
 | |
| 	register int i;
 | |
| 	register unsigned bit,match;
 | |
| 
 | |
| 	if (on)	match= (map->groups)&XkbAllGroupsMask;
 | |
| 	else 	match= (~map->groups)&XkbAllGroupsMask;
 | |
| 	if (map->which_groups&(XkbIM_UseLocked|XkbIM_UseEffective)) {
 | |
| 	    for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
 | |
| 		if (bit&match)
 | |
| 		    break;
 | |
| 	    }
 | |
| 	    if (map->which_groups&XkbIM_UseLatched)
 | |
| 		XkbLatchGroup(xkbi->device,0); /* unlatch group */
 | |
| 	    state->locked_group= i;
 | |
| 	    stateChange= True;
 | |
| 	}
 | |
| 	else if (map->which_groups&(XkbIM_UseLatched|XkbIM_UseEffective)) {
 | |
| 	    for (i=0,bit=1;i<XkbNumKbdGroups;i++,bit<<=1) {
 | |
| 		if (bit&match)
 | |
| 		    break;
 | |
| 	    }
 | |
| 	    state->locked_group= 0;
 | |
| 	    XkbLatchGroup(xkbi->device,i);
 | |
| 	    stateChange= True;
 | |
| 	}
 | |
|     }
 | |
|     if ((map->mods.mask)&&((map->which_mods&(~XkbIM_UseBase))!=0)) {
 | |
| 	if (map->which_mods&(XkbIM_UseLocked|XkbIM_UseEffective)) {
 | |
| 	    register unsigned long old;
 | |
| 	    old= state->locked_mods;
 | |
| 	    if (on)	state->locked_mods|= map->mods.mask;
 | |
| 	    else	state->locked_mods&= ~map->mods.mask;
 | |
| 	    if (state->locked_mods!=old)
 | |
| 		stateChange= True;
 | |
| 	}
 | |
| 	if (map->which_mods&(XkbIM_UseLatched|XkbIM_UseEffective)) {
 | |
| 	    register unsigned long newmods;
 | |
| 	    newmods= state->latched_mods;
 | |
| 	    if (on)	newmods|=  map->mods.mask;
 | |
| 	    else	newmods&= ~map->mods.mask;
 | |
| 	    if (newmods!=state->locked_mods) {
 | |
| 		newmods&= map->mods.mask;
 | |
| 		XkbLatchModifiers(xkbi->device,map->mods.mask,newmods);
 | |
| 		stateChange= True;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return (stateChange || ctrlChange);
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * void
 | |
| 	 * XkbSetIndicators(dev,affect,values,cause)
 | |
| 	 *
 | |
| 	 * Attempts to change the indicators specified in 'affect' to the
 | |
| 	 * states specified in 'values' for the default keyboard feedback
 | |
| 	 * on the keyboard specified by 'dev.'   Attempts to change indicator
 | |
| 	 * state might be ignored or have no affect, depending on the XKB
 | |
| 	 * indicator map for any affected indicators, as described in section
 | |
| 	 * 9.2 of the XKB protocol specification.
 | |
| 	 *
 | |
| 	 * If 'changes' is non-NULL, this function notes any changes to the
 | |
| 	 * keyboard state, controls, or indicator state that result from this
 | |
| 	 * attempted change.   If 'changes' is NULL, this function generates
 | |
| 	 * XKB events to report any such changes to interested clients.
 | |
| 	 *
 | |
| 	 * If 'cause' is non-NULL, it specifies the reason for the change, 
 | |
| 	 * as reported in some XKB events.   If it is NULL, this function 
 | |
| 	 * assumes that the change is the result of a core protocol 
 | |
| 	 * ChangeKeyboardMapping request.
 | |
| 	 */
 | |
| 
 | |
| void
 | |
| XkbSetIndicators(	DeviceIntPtr		dev,
 | |
| 			CARD32			affect,
 | |
| 			CARD32			values,
 | |
| 			XkbEventCausePtr	cause)
 | |
| {
 | |
| XkbSrvLedInfoPtr		sli;
 | |
| XkbChangesRec			changes;
 | |
| xkbExtensionDeviceNotify	ed;
 | |
| unsigned 			side_affected;
 | |
| 
 | |
|     bzero((char *)&changes,sizeof(XkbChangesRec));
 | |
|     bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
 | |
|     sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
 | |
|     sli->explicitState&= ~affect;
 | |
|     sli->explicitState|= (affect&values);
 | |
|     XkbApplyLedStateChanges(dev,sli,affect,&ed,&changes,cause);
 | |
| 
 | |
|     side_affected= 0;
 | |
|     if (changes.state_changes!=0)
 | |
| 	side_affected|= XkbIndicatorsToUpdate(dev,changes.state_changes,False);
 | |
|     if (changes.ctrls.enabled_ctrls_changes)
 | |
| 	side_affected|= sli->usesControls;
 | |
| 
 | |
|     if (side_affected) {
 | |
| 	XkbUpdateLedAutoState(dev,sli,side_affected,&ed,&changes,cause);
 | |
| 	affect|= side_affected;
 | |
|     }
 | |
|     if (changes.state_changes || changes.ctrls.enabled_ctrls_changes)
 | |
| 	XkbUpdateAllDeviceIndicators(NULL,cause);
 | |
| 
 | |
|     XkbFlushLedEvents(dev,dev,sli,&ed,&changes,cause);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * Bool
 | |
| 	 * ComputeAutoState(map,state,ctrls)
 | |
| 	 *
 | |
| 	 * This function reports the effect of applying the specified
 | |
| 	 * indicator map given the specified state and controls, as
 | |
| 	 * described in section 9.2 of the XKB protocol specification.
 | |
| 	 */
 | |
| 
 | |
| static Bool
 | |
| ComputeAutoState(	XkbIndicatorMapPtr	map,
 | |
| 			XkbStatePtr 		state,
 | |
| 			XkbControlsPtr 		ctrls)
 | |
| {
 | |
| Bool 			on;
 | |
| CARD8 			mods,group;
 | |
| 
 | |
|     on= False;
 | |
|     mods= group= 0;
 | |
|     if (map->which_mods&XkbIM_UseAnyMods) {
 | |
| 	if (map->which_mods&XkbIM_UseBase)
 | |
| 	    mods|= state->base_mods;
 | |
| 	if (map->which_mods&XkbIM_UseLatched)
 | |
| 	    mods|= state->latched_mods;
 | |
| 	if (map->which_mods&XkbIM_UseLocked)
 | |
| 	    mods|= state->locked_mods;
 | |
| 	if (map->which_mods&XkbIM_UseEffective)
 | |
| 	    mods|= state->mods;
 | |
| 	if (map->which_mods&XkbIM_UseCompat)
 | |
| 	    mods|= state->compat_state;
 | |
| 	on = ((map->mods.mask&mods)!=0);
 | |
| 	on = on||((mods==0)&&(map->mods.mask==0)&&(map->mods.vmods==0));
 | |
|     }
 | |
|     if (map->which_groups&XkbIM_UseAnyGroup) {
 | |
| 	if (map->which_groups&XkbIM_UseBase)
 | |
| 	    group|= (1L << state->base_group);
 | |
| 	if (map->which_groups&XkbIM_UseLatched)
 | |
| 	    group|= (1L << state->latched_group);
 | |
| 	if (map->which_groups&XkbIM_UseLocked)
 | |
| 	    group|= (1L << state->locked_group);
 | |
| 	if (map->which_groups&XkbIM_UseEffective)
 | |
| 	    group|= (1L << state->group);
 | |
| 	on = on||(((map->groups&group)!=0)||(map->groups==0));
 | |
|     }
 | |
|     if (map->ctrls)
 | |
| 	on = on||(ctrls->enabled_ctrls&map->ctrls);
 | |
|     return on;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * void
 | |
| 	 * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
 | |
| 	 *
 | |
| 	 * Applies the indicator maps for any indicators specified in
 | |
| 	 * 'update' from the default keyboard feedback on the device
 | |
| 	 * specified by 'dev.' 
 | |
| 	 *
 | |
| 	 * If 'changes' is NULL, this function generates and XKB events
 | |
| 	 * required to report the necessary changes, otherwise it simply
 | |
| 	 * notes the indicators with changed state.
 | |
| 	 *
 | |
| 	 * If 'check_edevs' is True, this function also checks the indicator
 | |
| 	 * maps for any open extension devices that have them, and updates
 | |
| 	 * the state of any extension device indicators as necessary.
 | |
| 	 */
 | |
| 
 | |
| void
 | |
| XkbUpdateIndicators(	DeviceIntPtr		dev,
 | |
| 			register CARD32		update,
 | |
| 			Bool			check_edevs,
 | |
| 			XkbChangesPtr		changes,
 | |
| 			XkbEventCausePtr	cause)
 | |
| {
 | |
| XkbSrvLedInfoPtr	sli;
 | |
| 
 | |
|     sli= XkbFindSrvLedInfo(dev,XkbDfltXIClass,XkbDfltXIId,0);
 | |
|     XkbUpdateLedAutoState(dev,sli,update,NULL,changes,cause);
 | |
|     if (check_edevs)
 | |
| 	XkbUpdateAllDeviceIndicators(changes,cause);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| void
 | |
| XkbUpdateAllDeviceIndicators(XkbChangesPtr changes,XkbEventCausePtr cause)
 | |
| {
 | |
| DeviceIntPtr		edev;
 | |
| XkbSrvLedInfoPtr	sli;
 | |
| 
 | |
|     for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) {
 | |
| 	if (edev->kbdfeed) {
 | |
| 	    KbdFeedbackPtr	kf;
 | |
| 	    for (kf=edev->kbdfeed;kf!=NULL;kf=kf->next) {
 | |
| 		if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL))
 | |
| 		    continue;
 | |
| 		sli= kf->xkb_sli;
 | |
| 		XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
 | |
| 								changes,cause);
 | |
| 			
 | |
| 	    }
 | |
| 	}
 | |
| 	if (edev->leds) {
 | |
| 	    LedFeedbackPtr	lf;
 | |
| 	    for (lf=edev->leds;lf!=NULL;lf=lf->next) {
 | |
| 		if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL))
 | |
| 		    continue;
 | |
| 		sli= lf->xkb_sli;
 | |
| 		XkbUpdateLedAutoState(edev,sli,sli->mapsPresent,NULL,
 | |
| 								changes,cause);
 | |
| 			
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * void
 | |
| 	 * XkbCheckIndicatorMaps(dev,sli,which)
 | |
| 	 *
 | |
| 	 * Updates the 'indicator accelerators' for the indicators specified
 | |
| 	 * by 'which' in the feedback specified by 'sli.' The indicator 
 | |
| 	 * accelerators are internal to the server and are used to simplify 
 | |
| 	 * and speed up the process of figuring out which indicators might 
 | |
| 	 * be affected by a particular change in keyboard state or controls.
 | |
| 	 */
 | |
| 
 | |
| void
 | |
| XkbCheckIndicatorMaps(DeviceIntPtr dev,XkbSrvLedInfoPtr sli,unsigned which)
 | |
| {
 | |
| register unsigned	i,bit;
 | |
| XkbIndicatorMapPtr	map;
 | |
| XkbDescPtr		xkb;
 | |
| 
 | |
|     if ((sli->flags&XkbSLI_HasOwnState)==0)
 | |
| 	dev= (DeviceIntPtr)LookupKeyboardDevice();
 | |
| 
 | |
|     sli->usesBase&=	 ~which;
 | |
|     sli->usesLatched&=	 ~which;
 | |
|     sli->usesLocked&=	 ~which;
 | |
|     sli->usesEffective&= ~which;
 | |
|     sli->usesCompat&=	 ~which;
 | |
|     sli->usesControls&=	 ~which;
 | |
|     sli->mapsPresent&=	 ~which;
 | |
| 
 | |
|     xkb= dev->key->xkbInfo->desc;
 | |
|     for (i=0,bit=1,map=sli->maps;i<XkbNumIndicators;i++,bit<<=1,map++) {
 | |
| 	if (which&bit) {
 | |
| 	    CARD8		what;
 | |
| 
 | |
| 	    if (!XkbIM_InUse(map)) 
 | |
| 		continue;
 | |
| 	    sli->mapsPresent|= bit;
 | |
| 
 | |
| 	    what= (map->which_mods|map->which_groups);
 | |
| 	    if (what&XkbIM_UseBase)
 | |
| 		 sli->usesBase|= bit;
 | |
| 	    if (what&XkbIM_UseLatched)
 | |
| 		 sli->usesLatched|= bit;
 | |
| 	    if (what&XkbIM_UseLocked)
 | |
| 		 sli->usesLocked|= bit;
 | |
| 	    if (what&XkbIM_UseEffective)
 | |
| 		 sli->usesEffective|= bit;
 | |
| 	    if (what&XkbIM_UseCompat)
 | |
| 		 sli->usesCompat|= bit;
 | |
| 	    if (map->ctrls)
 | |
| 		 sli->usesControls|= bit;
 | |
| 
 | |
| 	    map->mods.mask= map->mods.real_mods;
 | |
| 	    if (map->mods.vmods!=0) {
 | |
| 		map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     sli->usedComponents= 0;
 | |
|     if (sli->usesBase)
 | |
| 	sli->usedComponents|= XkbModifierBaseMask|XkbGroupBaseMask;
 | |
|     if (sli->usesLatched)
 | |
| 	sli->usedComponents|= XkbModifierLatchMask|XkbGroupLatchMask;
 | |
|     if (sli->usesLocked)
 | |
| 	sli->usedComponents|= XkbModifierLockMask|XkbGroupLockMask;
 | |
|     if (sli->usesEffective)
 | |
| 	sli->usedComponents|= XkbModifierStateMask|XkbGroupStateMask;
 | |
|     if (sli->usesCompat)
 | |
| 	sli->usedComponents|= XkbCompatStateMask;
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * XkbSrvLedInfoPtr
 | |
| 	 * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
 | |
| 	 *
 | |
| 	 * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
 | |
| 	 * 'kf' or 'lf' on the keyboard specified by 'dev.'
 | |
| 	 *
 | |
| 	 * If 'needed_parts' is non-zero, this function makes sure that any
 | |
| 	 * of the parts speicified therein are allocated.
 | |
| 	 */
 | |
| XkbSrvLedInfoPtr
 | |
| XkbAllocSrvLedInfo(	DeviceIntPtr		dev,
 | |
| 			KbdFeedbackPtr		kf,
 | |
| 			LedFeedbackPtr		lf,
 | |
| 			unsigned		needed_parts)
 | |
| {
 | |
| XkbSrvLedInfoPtr	sli;
 | |
| Bool			checkAccel;
 | |
| Bool			checkNames;
 | |
| 
 | |
|     sli= NULL;
 | |
|     checkAccel= checkNames= False;
 | |
|     if ((kf!=NULL)&&(kf->xkb_sli==NULL)) {
 | |
| 	kf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec);
 | |
| 	if (sli==NULL)
 | |
| 	    return NULL; /* ALLOCATION ERROR */
 | |
| 	if (dev->key && dev->key->xkbInfo)
 | |
| 	     sli->flags= XkbSLI_HasOwnState;
 | |
| 	else sli->flags= 0;	
 | |
| 	sli->class=	KbdFeedbackClass;
 | |
| 	sli->id=	kf->ctrl.id;
 | |
| 	sli->fb.kf=	kf;
 | |
| 
 | |
| 	sli->autoState=		0;
 | |
| 	sli->explicitState=	kf->ctrl.leds;
 | |
| 	sli->effectiveState=	kf->ctrl.leds;
 | |
| 
 | |
| 	if ((kf==dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) {
 | |
| 	    XkbDescPtr	xkb;
 | |
| 	    xkb= dev->key->xkbInfo->desc;
 | |
| 	    sli->flags|= 		XkbSLI_IsDefault;
 | |
| 	    sli->physIndicators=	xkb->indicators->phys_indicators;
 | |
| 	    sli->names=			xkb->names->indicators;
 | |
| 	    sli->maps=			xkb->indicators->maps;
 | |
| 	    checkNames= checkAccel=	True;
 | |
| 	}
 | |
| 	else {
 | |
| 	    sli->physIndicators=	XkbAllIndicatorsMask;
 | |
| 	    sli->names=			NULL;
 | |
| 	    sli->maps=			NULL;
 | |
| 	}
 | |
|     }
 | |
|     else if ((kf!=NULL)&&((kf->xkb_sli->flags&XkbSLI_IsDefault)!=0)) {
 | |
| 	XkbDescPtr	xkb;
 | |
| 	xkb= dev->key->xkbInfo->desc;
 | |
| 	sli->physIndicators=	xkb->indicators->phys_indicators;
 | |
| 	if (xkb->names->indicators!=sli->names) {
 | |
| 	    checkNames= True;
 | |
| 	    sli->names= xkb->names->indicators;
 | |
| 	}
 | |
| 	if (xkb->indicators->maps!=sli->maps) {
 | |
| 	    checkAccel= True;
 | |
| 	    sli->maps= xkb->indicators->maps;
 | |
| 	}
 | |
|     }
 | |
|     else if ((lf!=NULL)&&(lf->xkb_sli==NULL)) {
 | |
| 	lf->xkb_sli= sli= _XkbTypedCalloc(1,XkbSrvLedInfoRec);
 | |
| 	if (sli==NULL)
 | |
| 	    return NULL; /* ALLOCATION ERROR */
 | |
| 	if (dev->key && dev->key->xkbInfo)
 | |
| 	     sli->flags= XkbSLI_HasOwnState;
 | |
| 	else sli->flags= 0;	
 | |
| 	sli->class=	LedFeedbackClass;
 | |
| 	sli->id=	lf->ctrl.id;
 | |
| 	sli->fb.lf=	lf;
 | |
| 
 | |
| 	sli->physIndicators=	lf->ctrl.led_mask;
 | |
| 	sli->autoState=		0;
 | |
| 	sli->explicitState=	lf->ctrl.led_values;
 | |
| 	sli->effectiveState=	lf->ctrl.led_values;
 | |
| 	sli->maps=		NULL;
 | |
| 	sli->names=		NULL;
 | |
|     }
 | |
|     if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
 | |
| 	sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
 | |
|     if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
 | |
| 	sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
 | |
|     if (checkNames) {
 | |
| 	register unsigned i,bit;
 | |
| 	sli->namesPresent=	0;
 | |
| 	for (i=0,bit=1;i<XkbNumIndicators;i++,bit<<=1) {
 | |
| 	    if (sli->names[i]!=None)
 | |
| 		sli->namesPresent|= bit;
 | |
| 	}
 | |
|     }
 | |
|     if (checkAccel)
 | |
| 	 XkbCheckIndicatorMaps(dev,sli,XkbAllIndicatorsMask);
 | |
|     return sli;
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
 | |
| {
 | |
|     if ((sli->flags&XkbSLI_IsDefault)==0) {
 | |
| 	if (sli->maps)	_XkbFree(sli->maps);
 | |
| 	if (sli->names)	_XkbFree(sli->names);
 | |
|     }
 | |
|     sli->maps= NULL;
 | |
|     sli->names= NULL;
 | |
|     _XkbFree(sli);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * XkbSrvLedInfoPtr
 | |
| 	 * XkbFindSrvLedInfo(dev,class,id,needed_parts)
 | |
| 	 *
 | |
| 	 * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
 | |
| 	 * on the device specified by 'dev.'   If the class and id specify
 | |
| 	 * a valid device feedback, this function returns the existing 
 | |
| 	 * feedback or allocates a new one.
 | |
| 	 *
 | |
| 	 */
 | |
| 
 | |
| XkbSrvLedInfoPtr 
 | |
| XkbFindSrvLedInfo(	DeviceIntPtr		dev,
 | |
| 			unsigned		class,
 | |
| 			unsigned		id,
 | |
| 			unsigned		needed_parts)
 | |
| {
 | |
| XkbSrvLedInfoPtr	sli;
 | |
| 
 | |
|     /* optimization to check for most common case */
 | |
|     if (((class==XkbDfltXIClass)&&(id==XkbDfltXIId))&&(dev->kbdfeed)) {
 | |
| 	XkbSrvLedInfoPtr	sli;
 | |
| 	sli= dev->kbdfeed->xkb_sli;
 | |
| 	if (dev->kbdfeed->xkb_sli==NULL) {
 | |
| 	    sli= XkbAllocSrvLedInfo(dev,dev->kbdfeed,NULL,needed_parts);
 | |
| 	    dev->kbdfeed->xkb_sli= sli;
 | |
| 	}
 | |
| 	return dev->kbdfeed->xkb_sli;
 | |
|     }
 | |
| 
 | |
|     sli= NULL;
 | |
|     if (class==XkbDfltXIClass) {
 | |
| 	if (dev->kbdfeed)	class= KbdFeedbackClass;
 | |
| 	else if (dev->leds)	class= LedFeedbackClass;
 | |
| 	else 			return NULL;
 | |
|     }
 | |
|     if (class==KbdFeedbackClass) {
 | |
| 	KbdFeedbackPtr	kf;
 | |
| 	for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) {
 | |
| 	    if ((id==XkbDfltXIId)||(id==kf->ctrl.id)) {
 | |
| 		if (kf->xkb_sli==NULL)
 | |
| 		    kf->xkb_sli= XkbAllocSrvLedInfo(dev,kf,NULL,needed_parts);
 | |
| 		sli= kf->xkb_sli;
 | |
| 		break;
 | |
| 	    }	
 | |
| 	}
 | |
|     }
 | |
|     else if (class==LedFeedbackClass) {
 | |
| 	LedFeedbackPtr	lf;
 | |
| 	for (lf=dev->leds;lf!=NULL;lf=lf->next) {
 | |
| 	    if ((id==XkbDfltXIId)||(id==lf->ctrl.id)) {
 | |
| 		if (lf->xkb_sli==NULL)
 | |
| 		    lf->xkb_sli= XkbAllocSrvLedInfo(dev,NULL,lf,needed_parts);
 | |
| 		sli= lf->xkb_sli;
 | |
| 		break;
 | |
| 	    }	
 | |
| 	}
 | |
|     }
 | |
|     if ((sli->names==NULL)&&(needed_parts&XkbXI_IndicatorNamesMask))
 | |
| 	sli->names= _XkbTypedCalloc(XkbNumIndicators,Atom);
 | |
|     if ((sli->maps==NULL)&&(needed_parts&XkbXI_IndicatorMapsMask))
 | |
| 	sli->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec);
 | |
|     return sli;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| void
 | |
| XkbFlushLedEvents(	DeviceIntPtr			dev,
 | |
| 			DeviceIntPtr			kbd,
 | |
| 			XkbSrvLedInfoPtr		sli,
 | |
| 			xkbExtensionDeviceNotify *	ed,
 | |
| 			XkbChangesPtr			changes,
 | |
| 			XkbEventCausePtr		cause)
 | |
| {
 | |
|     if (changes) {
 | |
| 	if (changes->indicators.state_changes)
 | |
| 	    XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
 | |
| 	XkbSendNotification(kbd,changes,cause);
 | |
| 	bzero((char *)changes,sizeof(XkbChangesRec));
 | |
| 
 | |
| 	if (XkbAX_NeedFeedback(kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
 | |
| 		if (sli->effectiveState)
 | |
| 			/* it appears that the which parameter is not used */
 | |
| 			XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
 | |
| 		else
 | |
| 			XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
 | |
| 	}
 | |
|     }
 | |
|     if (ed && (ed->reason)) {
 | |
| 	if ((dev!=kbd)&&(ed->reason&XkbXI_IndicatorStateMask))
 | |
| 	    XkbDDXUpdateDeviceIndicators(dev,sli,sli->effectiveState);
 | |
| 	XkbSendExtensionDeviceNotify(dev,cause->client,ed);
 | |
|     }
 | |
|     bzero((char *)ed,sizeof(XkbExtensionDeviceNotify));
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| void
 | |
| XkbApplyLedNameChanges(	DeviceIntPtr 			dev,
 | |
| 			XkbSrvLedInfoPtr		sli,
 | |
| 			unsigned			changed_names,
 | |
| 			xkbExtensionDeviceNotify *	ed,
 | |
| 			XkbChangesPtr			changes,
 | |
| 			XkbEventCausePtr		cause)
 | |
| {
 | |
| DeviceIntPtr			kbd;
 | |
| XkbChangesRec			my_changes;
 | |
| xkbExtensionDeviceNotify	my_ed;
 | |
| 
 | |
|     if (changed_names==0)
 | |
| 	return;
 | |
|     if (dev->key && dev->key->xkbInfo)
 | |
| 	 kbd= dev;
 | |
|     else kbd= (DeviceIntPtr)LookupKeyboardDevice();
 | |
| 
 | |
|     if (ed==NULL) {
 | |
| 	ed= &my_ed;
 | |
| 	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
 | |
|     }
 | |
|     else if ((ed->reason&XkbXI_IndicatorsMask)&&
 | |
| 	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     }
 | |
| 
 | |
|     if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) { 
 | |
| 	if (changes==NULL) {
 | |
| 	   changes= &my_changes;
 | |
| 	   bzero((char *)changes,sizeof(XkbChangesRec));
 | |
| 	}
 | |
| 	changes->names.changed|= XkbIndicatorNamesMask;
 | |
| 	changes->names.changed_indicators|= changed_names;
 | |
|     }
 | |
| 
 | |
|     ed->reason|=	(XkbXI_IndicatorNamesMask&(~XkbXIUnsupported));
 | |
|     ed->ledClass= 	sli->class;
 | |
|     ed->ledID=		sli->id;
 | |
|     ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
 | |
|     ed->ledState=	sli->effectiveState;
 | |
|     ed->unsupported|=	XkbXIUnsupported&XkbXI_IndicatorNamesMask;
 | |
|     ed->supported=	XkbXI_AllFeaturesMask&(~XkbXIUnsupported);
 | |
| 
 | |
|     if (changes!=&my_changes)	changes= NULL;
 | |
|     if (ed!=&my_ed)		ed= NULL;
 | |
|     if (changes || ed)
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     return;
 | |
| }
 | |
| /***====================================================================***/
 | |
| 
 | |
| 	/*
 | |
| 	 * void
 | |
| 	 * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
 | |
| 	 *
 | |
| 	 * Handles all of the secondary effects of the changes to the
 | |
| 	 * feedback specified by 'sli' on the device specified by 'dev.'
 | |
| 	 * 
 | |
| 	 * If 'changed_maps' specifies any indicators, this function generates
 | |
| 	 * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
 | |
| 	 * events to report the changes, and recalculates the effective
 | |
| 	 * state of each indicator with a changed map.  If any indicators
 | |
| 	 * change state, the server generates XkbExtensionDeviceNotify and
 | |
| 	 * XkbIndicatorStateNotify events as appropriate.
 | |
| 	 *
 | |
| 	 * If 'changes' is non-NULL, this function updates it to reflect
 | |
| 	 * any changes to the keyboard state or controls or to the 'core'
 | |
| 	 * indicator names, maps, or state.   If 'changes' is NULL, this
 | |
| 	 * function generates XKB events as needed to report the changes.
 | |
| 	 * If 'dev' is not a keyboard device, any changes are reported
 | |
| 	 * for the core keyboard.
 | |
| 	 *
 | |
| 	 * The 'cause' specifies the reason for the event (key event or
 | |
| 	 * request) for the change, as reported in some XKB events.
 | |
| 	 */
 | |
| 
 | |
| void
 | |
| XkbApplyLedMapChanges(	DeviceIntPtr 			dev,
 | |
| 			XkbSrvLedInfoPtr		sli,
 | |
| 			unsigned			changed_maps,
 | |
| 			xkbExtensionDeviceNotify *	ed,
 | |
| 			XkbChangesPtr			changes,
 | |
| 			XkbEventCausePtr		cause)
 | |
| {
 | |
| DeviceIntPtr			kbd;
 | |
| XkbChangesRec			my_changes;
 | |
| xkbExtensionDeviceNotify	my_ed;
 | |
| 
 | |
|     if (changed_maps==0)
 | |
| 	return;
 | |
|     if (dev->key && dev->key->xkbInfo)
 | |
| 	 kbd= dev;
 | |
|     else kbd= (DeviceIntPtr)LookupKeyboardDevice();
 | |
| 
 | |
|     if (ed==NULL) {
 | |
| 	ed= &my_ed;
 | |
| 	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
 | |
|     }
 | |
|     else if ((ed->reason&XkbXI_IndicatorsMask)&&
 | |
| 	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     }
 | |
| 
 | |
|     if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
 | |
| 	if (changes==NULL) {
 | |
| 	    changes= &my_changes;
 | |
| 	    bzero((char *)changes,sizeof(XkbChangesRec));
 | |
| 	}
 | |
| 	changes->indicators.map_changes|= changed_maps;
 | |
|     }
 | |
| 
 | |
|     XkbCheckIndicatorMaps(dev,sli,changed_maps);
 | |
| 
 | |
|     ed->reason|=	(XkbXI_IndicatorMapsMask&(~XkbXIUnsupported));
 | |
|     ed->ledClass= 	sli->class;
 | |
|     ed->ledID=		sli->id;
 | |
|     ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
 | |
|     ed->ledState=	sli->effectiveState;
 | |
|     ed->unsupported|=	XkbXIUnsupported&XkbXI_IndicatorMapsMask;
 | |
|     ed->supported=	XkbXI_AllFeaturesMask&(~XkbXIUnsupported);
 | |
| 
 | |
|     XkbUpdateLedAutoState(dev,sli,changed_maps,ed,changes,cause);
 | |
| 
 | |
|     if (changes!=&my_changes)	changes= NULL;
 | |
|     if (ed!=&my_ed)		ed= NULL;
 | |
|     if (changes || ed)
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| void
 | |
| XkbApplyLedStateChanges(DeviceIntPtr 			dev,
 | |
| 			XkbSrvLedInfoPtr		sli,
 | |
| 			unsigned			changed_leds,
 | |
| 			xkbExtensionDeviceNotify *	ed,
 | |
| 			XkbChangesPtr			changes,
 | |
| 			XkbEventCausePtr		cause)
 | |
| {
 | |
| XkbSrvInfoPtr			xkbi;
 | |
| DeviceIntPtr			kbd;
 | |
| XkbChangesRec			my_changes;
 | |
| xkbExtensionDeviceNotify	my_ed;
 | |
| register unsigned		i,bit,affected;
 | |
| XkbIndicatorMapPtr		map;
 | |
| unsigned			oldState;
 | |
| Bool				kb_changed;
 | |
| 
 | |
|     if (changed_leds==0)
 | |
| 	return;
 | |
|     if (dev->key && dev->key->xkbInfo)
 | |
| 	 kbd= dev;
 | |
|     else kbd= (DeviceIntPtr)LookupKeyboardDevice();
 | |
|     xkbi= kbd->key->xkbInfo;
 | |
| 
 | |
|     if (changes==NULL) {
 | |
| 	changes= &my_changes;
 | |
| 	bzero((char *)changes,sizeof(XkbChangesRec));
 | |
|     }
 | |
| 
 | |
|     kb_changed= False;
 | |
|     affected= changed_leds;
 | |
|     oldState= sli->effectiveState;
 | |
|     for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
 | |
| 	if ((affected&bit)==0)
 | |
| 	    continue;
 | |
| 	affected&= ~bit;
 | |
| 	map= &sli->maps[i];
 | |
| 	if (map->flags&XkbIM_NoExplicit) {
 | |
| 	    sli->explicitState&= ~bit;
 | |
| 	    continue;
 | |
| 	}
 | |
| 	if (map->flags&XkbIM_LEDDrivesKB) {
 | |
| 	    Bool on= ((sli->explicitState&bit)!=0);
 | |
| 	    if (XkbApplyLEDChangeToKeyboard(xkbi,map,on,changes))
 | |
| 		kb_changed= True;
 | |
| 	}
 | |
|     }
 | |
|     sli->effectiveState= (sli->autoState|sli->explicitState);
 | |
|     affected= sli->effectiveState^oldState;
 | |
| 
 | |
|     if (ed==NULL) {
 | |
| 	ed= &my_ed;
 | |
| 	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
 | |
|     }
 | |
|     else if (affected&&(ed->reason&XkbXI_IndicatorsMask)&&
 | |
| 	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     }
 | |
| 
 | |
|     if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault))
 | |
| 	changes->indicators.state_changes|= affected;
 | |
|     if (affected) {
 | |
| 	ed->reason|=		(XkbXI_IndicatorStateMask&(~XkbXIUnsupported));
 | |
| 	ed->ledClass= 		sli->class;
 | |
| 	ed->ledID=		sli->id;
 | |
| 	ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
 | |
| 	ed->ledState=		sli->effectiveState;
 | |
| 	ed->unsupported|=	XkbXIUnsupported&XkbXI_IndicatorStateMask;
 | |
| 	ed->supported=		XkbXI_AllFeaturesMask&(~XkbXIUnsupported);
 | |
|     }
 | |
| 
 | |
|     if (kb_changed) {
 | |
| 	XkbComputeDerivedState(kbd->key->xkbInfo);
 | |
| 	XkbUpdateLedAutoState(dev,sli,sli->mapsPresent,ed,changes,cause);
 | |
|     }
 | |
| 
 | |
|     if (changes!=&my_changes)	changes= NULL;
 | |
|     if (ed!=&my_ed)		ed= NULL;
 | |
|     if (changes || ed)
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     if (kb_changed)
 | |
| 	XkbUpdateAllDeviceIndicators(NULL,cause);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| void
 | |
| XkbUpdateLedAutoState(	DeviceIntPtr			dev,
 | |
| 			XkbSrvLedInfoPtr		sli,
 | |
| 			unsigned			maps_to_check,
 | |
| 			xkbExtensionDeviceNotify *	ed,
 | |
| 			XkbChangesPtr			changes,
 | |
| 			XkbEventCausePtr		cause)
 | |
| {
 | |
| DeviceIntPtr			kbd;
 | |
| XkbStatePtr			state;
 | |
| XkbControlsPtr			ctrls;
 | |
| XkbChangesRec			my_changes;
 | |
| xkbExtensionDeviceNotify	my_ed;
 | |
| register unsigned		i,bit,affected;
 | |
| register XkbIndicatorMapPtr	map;
 | |
| unsigned			oldState;
 | |
| 
 | |
|     if ((maps_to_check==0)||(sli->maps==NULL)||(sli->mapsPresent==0))
 | |
| 	return;
 | |
| 
 | |
|     if (dev->key && dev->key->xkbInfo)
 | |
| 	 kbd= dev;
 | |
|     else kbd= (DeviceIntPtr)LookupKeyboardDevice();
 | |
| 
 | |
|     state= &kbd->key->xkbInfo->state;
 | |
|     ctrls= kbd->key->xkbInfo->desc->ctrls;
 | |
|     affected= maps_to_check;
 | |
|     oldState= sli->effectiveState;
 | |
|     sli->autoState&= ~affected;
 | |
|     for (i=0,bit=1;(i<XkbNumIndicators)&&(affected);i++,bit<<=1) {
 | |
| 	if ((affected&bit)==0)
 | |
| 	    continue;
 | |
| 	affected&= ~bit;
 | |
| 	map= &sli->maps[i];
 | |
| 	if((!(map->flags&XkbIM_NoAutomatic))&&ComputeAutoState(map,state,ctrls))
 | |
| 	    sli->autoState|= bit;
 | |
|     }
 | |
|     sli->effectiveState= (sli->autoState|sli->explicitState);
 | |
|     affected= sli->effectiveState^oldState;
 | |
|     if (affected==0)
 | |
| 	return;
 | |
| 
 | |
|     if (ed==NULL) {
 | |
| 	ed= &my_ed;
 | |
| 	bzero((char *)ed,sizeof(xkbExtensionDeviceNotify));
 | |
|     }
 | |
|     else if ((ed->reason&XkbXI_IndicatorsMask)&&
 | |
| 	     ((ed->ledClass!=sli->class)||(ed->ledID!=sli->id))) {
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     }
 | |
| 
 | |
|     if ((kbd==dev)&&(sli->flags&XkbSLI_IsDefault)) {
 | |
| 	if (changes==NULL) {
 | |
| 	    changes= &my_changes;
 | |
| 	    bzero((char *)changes,sizeof(XkbChangesRec));
 | |
| 	}
 | |
| 	changes->indicators.state_changes|= affected;
 | |
|     }
 | |
| 
 | |
|     ed->reason|=	(XkbXI_IndicatorStateMask&(~XkbXIUnsupported));
 | |
|     ed->ledClass= 	sli->class;
 | |
|     ed->ledID=		sli->id;
 | |
|     ed->ledsDefined=	sli->namesPresent|sli->mapsPresent;
 | |
|     ed->ledState=	sli->effectiveState;
 | |
|     ed->unsupported|=	XkbXIUnsupported&XkbXI_IndicatorStateMask;
 | |
|     ed->supported=	XkbXI_AllFeaturesMask&(~XkbXIUnsupported);
 | |
| 
 | |
|     if (changes!=&my_changes)	changes= NULL;
 | |
|     if (ed!=&my_ed)		ed= NULL;
 | |
|     if (changes || ed)
 | |
| 	XkbFlushLedEvents(dev,kbd,sli,ed,changes,cause);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| /***====================================================================***/
 | |
| 
 | |
| static void
 | |
| _UpdateButtonVMods(	XkbDescPtr			xkb,
 | |
| 			unsigned			num_btns,
 | |
| 			XkbAction *			acts,
 | |
| 			unsigned			changed,
 | |
| 			xkbExtensionDeviceNotify *	ed_inout)
 | |
| {
 | |
| register int i;
 | |
| 
 | |
|     for (i=0;i<num_btns;i++,acts++) {
 | |
| 	if ((acts->any.type!=XkbSA_NoAction)&&
 | |
| 				XkbUpdateActionVirtualMods(xkb,acts,changed)) {
 | |
| 	    if ((ed_inout->reason&XkbXI_ButtonActionsMask)==0) {
 | |
| 		ed_inout->reason|= XkbXI_ButtonActionsMask;
 | |
| 		ed_inout->firstBtn= i;
 | |
| 		ed_inout->nBtns= 1;
 | |
| 	    }
 | |
| 	    else {
 | |
| 		ed_inout->nBtns= (i-ed_inout->firstBtn)+1;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void
 | |
| _UpdateMapVMods(	XkbDescPtr	xkb,
 | |
| 			register	XkbIndicatorMapPtr map,
 | |
| 			unsigned	changed_vmods,
 | |
| 			unsigned *	changed_maps_rtrn)
 | |
| {
 | |
| register int i;
 | |
| 
 | |
|     *changed_maps_rtrn= 0;
 | |
|     for (i=0;i<XkbNumIndicators;i++,map++) {
 | |
| 	if (map->mods.vmods&changed_vmods) {
 | |
| 	    map->mods.mask= map->mods.real_mods;
 | |
| 	    map->mods.mask|= XkbMaskForVMask(xkb,map->mods.vmods);
 | |
| 	    *changed_maps_rtrn|= (1L<<i);
 | |
| 	}	
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| static void
 | |
| _UpdateDeviceVMods(	DeviceIntPtr		dev,
 | |
| 			XkbDescPtr		xkb,
 | |
| 			unsigned		changed,
 | |
| 			XkbEventCausePtr	cause)
 | |
| {
 | |
| xkbExtensionDeviceNotify	ed;
 | |
| XkbSrvLedInfoPtr		sli;
 | |
| unsigned			changed_maps;
 | |
| 
 | |
|     bzero((char *)&ed,sizeof(xkbExtensionDeviceNotify));
 | |
|     ed.deviceID= dev->id;
 | |
|     if ((dev->button)&&(dev->button->xkb_acts)) {
 | |
| 	_UpdateButtonVMods(xkb,dev->button->numButtons,
 | |
| 					dev->button->xkb_acts,changed,&ed);
 | |
|     }
 | |
|     if (dev->kbdfeed) {
 | |
| 	KbdFeedbackPtr	kf;
 | |
| 	for (kf=dev->kbdfeed;kf!=NULL;kf=kf->next) {
 | |
| 	    if ((kf->xkb_sli==NULL)||(kf->xkb_sli->maps==NULL))
 | |
| 		continue;
 | |
| 	    sli= kf->xkb_sli;
 | |
| 	    _UpdateMapVMods(xkb,sli->maps,changed,&changed_maps);
 | |
| 	    if (changed_maps) {
 | |
| 		if (ed.reason&XkbXI_IndicatorsMask) {
 | |
| 		    XkbSendExtensionDeviceNotify(dev,NULL,&ed);
 | |
| 		    ed.reason= 0;
 | |
| 		    ed.firstBtn= ed.nBtns;
 | |
| 		}
 | |
| 		ed.ledClass= 	sli->class;
 | |
| 		ed.ledID=	sli->id;
 | |
| 		ed.ledsDefined= sli->namesPresent|sli->mapsPresent;
 | |
| 		ed.reason|= 	XkbXI_IndicatorMapsMask;
 | |
| 		XkbUpdateLedAutoState(dev,sli,changed_maps,&ed,NULL,cause);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     if (dev->leds) {
 | |
| 	LedFeedbackPtr	lf;
 | |
| 	for (lf=dev->leds;lf!=NULL;lf=lf->next) {
 | |
| 	    if ((lf->xkb_sli==NULL)||(lf->xkb_sli->maps==NULL))
 | |
| 		continue;
 | |
| 	    sli= lf->xkb_sli;
 | |
| 	    _UpdateMapVMods(xkb,sli->maps,changed,&changed_maps);
 | |
| 	    if (changed_maps) {
 | |
| 		if (ed.reason&XkbXI_IndicatorsMask) {
 | |
| 		    XkbSendExtensionDeviceNotify(dev,NULL,&ed);
 | |
| 		    ed.reason= 0;
 | |
| 		    ed.firstBtn= ed.nBtns;
 | |
| 		}
 | |
| 		ed.ledClass= 	sli->class;
 | |
| 		ed.ledID=	sli->id;
 | |
| 		ed.ledsDefined= sli->namesPresent|sli->mapsPresent;
 | |
| 		ed.reason|= 	XkbXI_IndicatorMapsMask;
 | |
| 		XkbUpdateLedAutoState(dev,sli,changed_maps,&ed,NULL,cause);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     if (ed.reason!=0)
 | |
| 	XkbSendExtensionDeviceNotify(dev,NULL,&ed);
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void
 | |
| XkbApplyVModChangesToAllDevices(	DeviceIntPtr		dev,
 | |
| 					XkbDescPtr 		xkb,
 | |
| 					unsigned 		changed,
 | |
| 					XkbEventCausePtr	cause)
 | |
| {
 | |
| DeviceIntPtr			edev;
 | |
|     if (dev!=(DeviceIntPtr)LookupKeyboardDevice())
 | |
| 	return;
 | |
|     for (edev=inputInfo.devices;edev!=NULL;edev=edev->next) {
 | |
| 	if (edev->key)
 | |
| 	    continue;
 | |
| 	_UpdateDeviceVMods(edev,xkb,changed,cause);
 | |
|     }
 | |
|     for (edev=inputInfo.off_devices;edev!=NULL;edev=edev->next) {
 | |
| 	if (edev->key)
 | |
| 	    continue;
 | |
| 	_UpdateDeviceVMods(edev,xkb,changed,cause);
 | |
|     }
 | |
|     return;
 | |
| }
 |