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 935c4bbdfSmrgdocumentation, and that the name of Silicon Graphics not be 1035c4bbdfSmrgused in advertising or publicity pertaining to distribution 1105b261ecSmrgof the software without specific prior written permission. 1235c4bbdfSmrgSilicon 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 1635c4bbdfSmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 1735c4bbdfSmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1805b261ecSmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 1935c4bbdfSmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 2035c4bbdfSmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 2135c4bbdfSmrgDATA 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 4535c4bbdfSmrg /* 4635c4bbdfSmrg * unsigned 4735c4bbdfSmrg * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn) 4835c4bbdfSmrg * 4935c4bbdfSmrg * Given a keyboard and a set of state components that have changed, 5035c4bbdfSmrg * this function returns the indicators on the default keyboard 5135c4bbdfSmrg * feedback that might be affected. It also reports whether or not 5235c4bbdfSmrg * any extension devices might be affected in check_devs_rtrn. 5335c4bbdfSmrg */ 5405b261ecSmrg 5505b261ecSmrgunsigned 5635c4bbdfSmrgXkbIndicatorsToUpdate(DeviceIntPtr dev, 5735c4bbdfSmrg unsigned long state_changes, Bool enable_changes) 5805b261ecSmrg{ 5935c4bbdfSmrg register unsigned update = 0; 6035c4bbdfSmrg XkbSrvLedInfoPtr sli; 6105b261ecSmrg 6235c4bbdfSmrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0); 6305b261ecSmrg 6405b261ecSmrg if (!sli) 6505b261ecSmrg return update; 6605b261ecSmrg 6735c4bbdfSmrg if (state_changes & (XkbModifierStateMask | XkbGroupStateMask)) 6835c4bbdfSmrg update |= sli->usesEffective; 6935c4bbdfSmrg if (state_changes & (XkbModifierBaseMask | XkbGroupBaseMask)) 7035c4bbdfSmrg update |= sli->usesBase; 7135c4bbdfSmrg if (state_changes & (XkbModifierLatchMask | XkbGroupLatchMask)) 7235c4bbdfSmrg update |= sli->usesLatched; 7335c4bbdfSmrg if (state_changes & (XkbModifierLockMask | XkbGroupLockMask)) 7435c4bbdfSmrg update |= sli->usesLocked; 7535c4bbdfSmrg if (state_changes & XkbCompatStateMask) 7635c4bbdfSmrg update |= sli->usesCompat; 7705b261ecSmrg if (enable_changes) 7835c4bbdfSmrg update |= sli->usesControls; 7905b261ecSmrg return update; 8005b261ecSmrg} 8105b261ecSmrg 8205b261ecSmrg/***====================================================================***/ 8305b261ecSmrg 8435c4bbdfSmrg /* 8535c4bbdfSmrg * Bool 8635c4bbdfSmrg *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change) 8735c4bbdfSmrg * 8835c4bbdfSmrg * Some indicators "drive" the keyboard when their state is explicitly 8935c4bbdfSmrg * changed, as described in section 9.2.1 of the XKB protocol spec. 9035c4bbdfSmrg * This function updates the state and controls for the keyboard 9135c4bbdfSmrg * specified by 'xkbi' to reflect any changes that are required 9235c4bbdfSmrg * when the indicator described by 'map' is turned on or off. The 9335c4bbdfSmrg * extent of the changes is reported in change, which must be defined. 9435c4bbdfSmrg */ 9505b261ecSmrgstatic Bool 9635c4bbdfSmrgXkbApplyLEDChangeToKeyboard(XkbSrvInfoPtr xkbi, 9735c4bbdfSmrg XkbIndicatorMapPtr map, 9835c4bbdfSmrg Bool on, XkbChangesPtr change) 9905b261ecSmrg{ 10035c4bbdfSmrg Bool ctrlChange, stateChange; 10135c4bbdfSmrg XkbStatePtr state; 10205b261ecSmrg 10335c4bbdfSmrg if ((map->flags & XkbIM_NoExplicit) || 10435c4bbdfSmrg ((map->flags & XkbIM_LEDDrivesKB) == 0)) 10535c4bbdfSmrg return FALSE; 10635c4bbdfSmrg ctrlChange = stateChange = FALSE; 10705b261ecSmrg if (map->ctrls) { 10835c4bbdfSmrg XkbControlsPtr ctrls = xkbi->desc->ctrls; 10935c4bbdfSmrg unsigned old; 11035c4bbdfSmrg 11135c4bbdfSmrg old = ctrls->enabled_ctrls; 11235c4bbdfSmrg if (on) 11335c4bbdfSmrg ctrls->enabled_ctrls |= map->ctrls; 11435c4bbdfSmrg else 11535c4bbdfSmrg ctrls->enabled_ctrls &= ~map->ctrls; 11635c4bbdfSmrg if (old != ctrls->enabled_ctrls) { 11735c4bbdfSmrg change->ctrls.changed_ctrls = XkbControlsEnabledMask; 11835c4bbdfSmrg change->ctrls.enabled_ctrls_changes = old ^ ctrls->enabled_ctrls; 11935c4bbdfSmrg ctrlChange = TRUE; 12035c4bbdfSmrg } 12135c4bbdfSmrg } 12235c4bbdfSmrg state = &xkbi->state; 12335c4bbdfSmrg if ((map->groups) && ((map->which_groups & (~XkbIM_UseBase)) != 0)) { 12435c4bbdfSmrg register int i; 12535c4bbdfSmrg register unsigned bit, match; 12635c4bbdfSmrg 12735c4bbdfSmrg if (on) 12835c4bbdfSmrg match = (map->groups) & XkbAllGroupsMask; 12935c4bbdfSmrg else 13035c4bbdfSmrg match = (~map->groups) & XkbAllGroupsMask; 13135c4bbdfSmrg if (map->which_groups & (XkbIM_UseLocked | XkbIM_UseEffective)) { 13235c4bbdfSmrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 13335c4bbdfSmrg if (bit & match) 13435c4bbdfSmrg break; 13535c4bbdfSmrg } 13635c4bbdfSmrg if (map->which_groups & XkbIM_UseLatched) 13735c4bbdfSmrg XkbLatchGroup(xkbi->device, 0); /* unlatch group */ 13835c4bbdfSmrg state->locked_group = i; 13935c4bbdfSmrg stateChange = TRUE; 14035c4bbdfSmrg } 14135c4bbdfSmrg else if (map->which_groups & (XkbIM_UseLatched | XkbIM_UseEffective)) { 14235c4bbdfSmrg for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) { 14335c4bbdfSmrg if (bit & match) 14435c4bbdfSmrg break; 14535c4bbdfSmrg } 14635c4bbdfSmrg state->locked_group = 0; 14735c4bbdfSmrg XkbLatchGroup(xkbi->device, i); 14835c4bbdfSmrg stateChange = TRUE; 14935c4bbdfSmrg } 15035c4bbdfSmrg } 15135c4bbdfSmrg if ((map->mods.mask) && ((map->which_mods & (~XkbIM_UseBase)) != 0)) { 15235c4bbdfSmrg if (map->which_mods & (XkbIM_UseLocked | XkbIM_UseEffective)) { 15335c4bbdfSmrg register unsigned long old; 15435c4bbdfSmrg 15535c4bbdfSmrg old = state->locked_mods; 15635c4bbdfSmrg if (on) 15735c4bbdfSmrg state->locked_mods |= map->mods.mask; 15835c4bbdfSmrg else 15935c4bbdfSmrg state->locked_mods &= ~map->mods.mask; 16035c4bbdfSmrg if (state->locked_mods != old) 16135c4bbdfSmrg stateChange = TRUE; 16235c4bbdfSmrg } 16335c4bbdfSmrg if (map->which_mods & (XkbIM_UseLatched | XkbIM_UseEffective)) { 16435c4bbdfSmrg register unsigned long newmods; 16535c4bbdfSmrg 16635c4bbdfSmrg newmods = state->latched_mods; 16735c4bbdfSmrg if (on) 16835c4bbdfSmrg newmods |= map->mods.mask; 16935c4bbdfSmrg else 17035c4bbdfSmrg newmods &= ~map->mods.mask; 17135c4bbdfSmrg if (newmods != state->locked_mods) { 17235c4bbdfSmrg newmods &= map->mods.mask; 17335c4bbdfSmrg XkbLatchModifiers(xkbi->device, map->mods.mask, newmods); 17435c4bbdfSmrg stateChange = TRUE; 17535c4bbdfSmrg } 17635c4bbdfSmrg } 17705b261ecSmrg } 1786747b715Smrg return stateChange || ctrlChange; 17905b261ecSmrg} 18035c4bbdfSmrg 18135c4bbdfSmrg /* 18235c4bbdfSmrg * Bool 18335c4bbdfSmrg * ComputeAutoState(map,state,ctrls) 18435c4bbdfSmrg * 18535c4bbdfSmrg * This function reports the effect of applying the specified 18635c4bbdfSmrg * indicator map given the specified state and controls, as 18735c4bbdfSmrg * described in section 9.2 of the XKB protocol specification. 18835c4bbdfSmrg */ 18905b261ecSmrg 19005b261ecSmrgstatic Bool 19135c4bbdfSmrgComputeAutoState(XkbIndicatorMapPtr map, 19235c4bbdfSmrg XkbStatePtr state, XkbControlsPtr ctrls) 19305b261ecSmrg{ 19435c4bbdfSmrg Bool on; 19535c4bbdfSmrg CARD8 mods, group; 19635c4bbdfSmrg 19735c4bbdfSmrg on = FALSE; 19835c4bbdfSmrg mods = group = 0; 19935c4bbdfSmrg if (map->which_mods & XkbIM_UseAnyMods) { 20035c4bbdfSmrg if (map->which_mods & XkbIM_UseBase) 20135c4bbdfSmrg mods |= state->base_mods; 20235c4bbdfSmrg if (map->which_mods & XkbIM_UseLatched) 20335c4bbdfSmrg mods |= state->latched_mods; 20435c4bbdfSmrg if (map->which_mods & XkbIM_UseLocked) 20535c4bbdfSmrg mods |= state->locked_mods; 20635c4bbdfSmrg if (map->which_mods & XkbIM_UseEffective) 20735c4bbdfSmrg mods |= state->mods; 20835c4bbdfSmrg if (map->which_mods & XkbIM_UseCompat) 20935c4bbdfSmrg mods |= state->compat_state; 21035c4bbdfSmrg on = ((map->mods.mask & mods) != 0); 21135c4bbdfSmrg on = on || ((mods == 0) && (map->mods.mask == 0) && 21235c4bbdfSmrg (map->mods.vmods == 0)); 21335c4bbdfSmrg } 21435c4bbdfSmrg if (map->which_groups & XkbIM_UseAnyGroup) { 21535c4bbdfSmrg if (map->which_groups & XkbIM_UseBase) 21635c4bbdfSmrg group |= (1L << state->base_group); 21735c4bbdfSmrg if (map->which_groups & XkbIM_UseLatched) 21835c4bbdfSmrg group |= (1L << state->latched_group); 21935c4bbdfSmrg if (map->which_groups & XkbIM_UseLocked) 22035c4bbdfSmrg group |= (1L << state->locked_group); 22135c4bbdfSmrg if (map->which_groups & XkbIM_UseEffective) 22235c4bbdfSmrg group |= (1L << state->group); 22335c4bbdfSmrg on = on || (((map->groups & group) != 0) || (map->groups == 0)); 22405b261ecSmrg } 22505b261ecSmrg if (map->ctrls) 22635c4bbdfSmrg on = on || (ctrls->enabled_ctrls & map->ctrls); 22705b261ecSmrg return on; 22805b261ecSmrg} 22905b261ecSmrg 23005b261ecSmrgstatic void 23135c4bbdfSmrgXkbUpdateLedAutoState(DeviceIntPtr dev, 23235c4bbdfSmrg XkbSrvLedInfoPtr sli, 23335c4bbdfSmrg unsigned maps_to_check, 23435c4bbdfSmrg xkbExtensionDeviceNotify * ed, 23535c4bbdfSmrg XkbChangesPtr changes, XkbEventCausePtr cause) 23605b261ecSmrg{ 23735c4bbdfSmrg DeviceIntPtr kbd; 23835c4bbdfSmrg XkbStatePtr state; 23935c4bbdfSmrg XkbControlsPtr ctrls; 24035c4bbdfSmrg XkbChangesRec my_changes; 24135c4bbdfSmrg xkbExtensionDeviceNotify my_ed; 24235c4bbdfSmrg register unsigned i, bit, affected; 24335c4bbdfSmrg register XkbIndicatorMapPtr map; 24435c4bbdfSmrg unsigned oldState; 24535c4bbdfSmrg 24635c4bbdfSmrg if ((maps_to_check == 0) || (sli->maps == NULL) || (sli->mapsPresent == 0)) 24735c4bbdfSmrg return; 24805b261ecSmrg 24905b261ecSmrg if (dev->key && dev->key->xkbInfo) 25035c4bbdfSmrg kbd = dev; 25135c4bbdfSmrg else 25235c4bbdfSmrg kbd = inputInfo.keyboard; 25335c4bbdfSmrg 25435c4bbdfSmrg state = &kbd->key->xkbInfo->state; 25535c4bbdfSmrg ctrls = kbd->key->xkbInfo->desc->ctrls; 25635c4bbdfSmrg affected = maps_to_check; 25735c4bbdfSmrg oldState = sli->effectiveState; 25835c4bbdfSmrg sli->autoState &= ~affected; 25935c4bbdfSmrg for (i = 0, bit = 1; (i < XkbNumIndicators) && (affected); i++, bit <<= 1) { 26035c4bbdfSmrg if ((affected & bit) == 0) 26135c4bbdfSmrg continue; 26235c4bbdfSmrg affected &= ~bit; 26335c4bbdfSmrg map = &sli->maps[i]; 26435c4bbdfSmrg if ((!(map->flags & XkbIM_NoAutomatic)) && 26535c4bbdfSmrg ComputeAutoState(map, state, ctrls)) 26635c4bbdfSmrg sli->autoState |= bit; 26735c4bbdfSmrg } 26835c4bbdfSmrg sli->effectiveState = (sli->autoState | sli->explicitState); 26935c4bbdfSmrg affected = sli->effectiveState ^ oldState; 27035c4bbdfSmrg if (affected == 0) 27135c4bbdfSmrg return; 27235c4bbdfSmrg 27335c4bbdfSmrg if (ed == NULL) { 27435c4bbdfSmrg ed = &my_ed; 27535c4bbdfSmrg memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify)); 27635c4bbdfSmrg } 27735c4bbdfSmrg else if ((ed->reason & XkbXI_IndicatorsMask) && 27835c4bbdfSmrg ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) { 27935c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 28035c4bbdfSmrg } 28135c4bbdfSmrg 28235c4bbdfSmrg if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) { 28335c4bbdfSmrg if (changes == NULL) { 28435c4bbdfSmrg changes = &my_changes; 28535c4bbdfSmrg memset((char *) changes, 0, sizeof(XkbChangesRec)); 28635c4bbdfSmrg } 28735c4bbdfSmrg changes->indicators.state_changes |= affected; 28835c4bbdfSmrg } 28935c4bbdfSmrg 29035c4bbdfSmrg ed->reason |= XkbXI_IndicatorStateMask; 29135c4bbdfSmrg ed->ledClass = sli->class; 29235c4bbdfSmrg ed->ledID = sli->id; 29335c4bbdfSmrg ed->ledsDefined = sli->namesPresent | sli->mapsPresent; 29435c4bbdfSmrg ed->ledState = sli->effectiveState; 29535c4bbdfSmrg ed->unsupported = 0; 29635c4bbdfSmrg ed->supported = XkbXI_AllFeaturesMask; 29735c4bbdfSmrg 29835c4bbdfSmrg if (changes != &my_changes) 29935c4bbdfSmrg changes = NULL; 30035c4bbdfSmrg if (ed != &my_ed) 30135c4bbdfSmrg ed = NULL; 30205b261ecSmrg if (changes || ed) 30335c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 30405b261ecSmrg return; 30505b261ecSmrg} 30605b261ecSmrg 30735c4bbdfSmrgvoid 30835c4bbdfSmrgXkbUpdateAllDeviceIndicators(XkbChangesPtr changes, XkbEventCausePtr cause) 30905b261ecSmrg{ 31035c4bbdfSmrg DeviceIntPtr edev; 31135c4bbdfSmrg XkbSrvLedInfoPtr sli; 31235c4bbdfSmrg 31335c4bbdfSmrg for (edev = inputInfo.devices; edev != NULL; edev = edev->next) { 31435c4bbdfSmrg if (edev->kbdfeed) { 31535c4bbdfSmrg KbdFeedbackPtr kf; 31635c4bbdfSmrg 31735c4bbdfSmrg for (kf = edev->kbdfeed; kf != NULL; kf = kf->next) { 31835c4bbdfSmrg if ((kf->xkb_sli == NULL) || (kf->xkb_sli->maps == NULL)) 31935c4bbdfSmrg continue; 32035c4bbdfSmrg sli = kf->xkb_sli; 32135c4bbdfSmrg XkbUpdateLedAutoState(edev, sli, sli->mapsPresent, NULL, 32235c4bbdfSmrg changes, cause); 32335c4bbdfSmrg 32435c4bbdfSmrg } 32535c4bbdfSmrg } 32635c4bbdfSmrg if (edev->leds) { 32735c4bbdfSmrg LedFeedbackPtr lf; 32835c4bbdfSmrg 32935c4bbdfSmrg for (lf = edev->leds; lf != NULL; lf = lf->next) { 33035c4bbdfSmrg if ((lf->xkb_sli == NULL) || (lf->xkb_sli->maps == NULL)) 33135c4bbdfSmrg continue; 33235c4bbdfSmrg sli = lf->xkb_sli; 33335c4bbdfSmrg XkbUpdateLedAutoState(edev, sli, sli->mapsPresent, NULL, 33435c4bbdfSmrg changes, cause); 33535c4bbdfSmrg 33635c4bbdfSmrg } 33735c4bbdfSmrg } 33805b261ecSmrg } 33905b261ecSmrg return; 34005b261ecSmrg} 34105b261ecSmrg 34205b261ecSmrg/***====================================================================***/ 34305b261ecSmrg 34435c4bbdfSmrg /* 34535c4bbdfSmrg * void 34635c4bbdfSmrg * XkbSetIndicators(dev,affect,values,cause) 34735c4bbdfSmrg * 34835c4bbdfSmrg * Attempts to change the indicators specified in 'affect' to the 34935c4bbdfSmrg * states specified in 'values' for the default keyboard feedback 35035c4bbdfSmrg * on the keyboard specified by 'dev.' Attempts to change indicator 35135c4bbdfSmrg * state might be ignored or have no affect, depending on the XKB 35235c4bbdfSmrg * indicator map for any affected indicators, as described in section 35335c4bbdfSmrg * 9.2 of the XKB protocol specification. 35435c4bbdfSmrg * 35535c4bbdfSmrg * If 'changes' is non-NULL, this function notes any changes to the 35635c4bbdfSmrg * keyboard state, controls, or indicator state that result from this 35735c4bbdfSmrg * attempted change. If 'changes' is NULL, this function generates 35835c4bbdfSmrg * XKB events to report any such changes to interested clients. 35935c4bbdfSmrg * 36035c4bbdfSmrg * If 'cause' is non-NULL, it specifies the reason for the change, 36135c4bbdfSmrg * as reported in some XKB events. If it is NULL, this function 36235c4bbdfSmrg * assumes that the change is the result of a core protocol 36335c4bbdfSmrg * ChangeKeyboardMapping request. 36435c4bbdfSmrg */ 36505b261ecSmrg 36605b261ecSmrgvoid 36735c4bbdfSmrgXkbSetIndicators(DeviceIntPtr dev, 36835c4bbdfSmrg CARD32 affect, CARD32 values, XkbEventCausePtr cause) 36905b261ecSmrg{ 37035c4bbdfSmrg XkbSrvLedInfoPtr sli; 37135c4bbdfSmrg XkbChangesRec changes; 37235c4bbdfSmrg xkbExtensionDeviceNotify ed; 37335c4bbdfSmrg unsigned side_affected; 37435c4bbdfSmrg 37535c4bbdfSmrg memset((char *) &changes, 0, sizeof(XkbChangesRec)); 37635c4bbdfSmrg memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify)); 37735c4bbdfSmrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0); 37835c4bbdfSmrg sli->explicitState &= ~affect; 37935c4bbdfSmrg sli->explicitState |= (affect & values); 38035c4bbdfSmrg XkbApplyLedStateChanges(dev, sli, affect, &ed, &changes, cause); 38135c4bbdfSmrg 38235c4bbdfSmrg side_affected = 0; 38335c4bbdfSmrg if (changes.state_changes != 0) 38435c4bbdfSmrg side_affected |= 38535c4bbdfSmrg XkbIndicatorsToUpdate(dev, changes.state_changes, FALSE); 38605b261ecSmrg if (changes.ctrls.enabled_ctrls_changes) 38735c4bbdfSmrg side_affected |= sli->usesControls; 38805b261ecSmrg 38905b261ecSmrg if (side_affected) { 39035c4bbdfSmrg XkbUpdateLedAutoState(dev, sli, side_affected, &ed, &changes, cause); 39135c4bbdfSmrg affect |= side_affected; 39205b261ecSmrg } 39305b261ecSmrg if (changes.state_changes || changes.ctrls.enabled_ctrls_changes) 39435c4bbdfSmrg XkbUpdateAllDeviceIndicators(NULL, cause); 39505b261ecSmrg 39635c4bbdfSmrg XkbFlushLedEvents(dev, dev, sli, &ed, &changes, cause); 39705b261ecSmrg return; 39805b261ecSmrg} 39905b261ecSmrg 40005b261ecSmrg/***====================================================================***/ 40105b261ecSmrg 40205b261ecSmrg/***====================================================================***/ 40305b261ecSmrg 40435c4bbdfSmrg /* 40535c4bbdfSmrg * void 40635c4bbdfSmrg * XkbUpdateIndicators(dev,update,check_edevs,changes,cause) 40735c4bbdfSmrg * 40835c4bbdfSmrg * Applies the indicator maps for any indicators specified in 40935c4bbdfSmrg * 'update' from the default keyboard feedback on the device 41035c4bbdfSmrg * specified by 'dev.' 41135c4bbdfSmrg * 41235c4bbdfSmrg * If 'changes' is NULL, this function generates and XKB events 41335c4bbdfSmrg * required to report the necessary changes, otherwise it simply 41435c4bbdfSmrg * notes the indicators with changed state. 41535c4bbdfSmrg * 41635c4bbdfSmrg * If 'check_edevs' is TRUE, this function also checks the indicator 41735c4bbdfSmrg * maps for any open extension devices that have them, and updates 41835c4bbdfSmrg * the state of any extension device indicators as necessary. 41935c4bbdfSmrg */ 42005b261ecSmrg 42105b261ecSmrgvoid 42235c4bbdfSmrgXkbUpdateIndicators(DeviceIntPtr dev, 42335c4bbdfSmrg register CARD32 update, 42435c4bbdfSmrg Bool check_edevs, 42535c4bbdfSmrg XkbChangesPtr changes, XkbEventCausePtr cause) 42605b261ecSmrg{ 42735c4bbdfSmrg XkbSrvLedInfoPtr sli; 42805b261ecSmrg 42935c4bbdfSmrg sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0); 43035c4bbdfSmrg XkbUpdateLedAutoState(dev, sli, update, NULL, changes, cause); 43105b261ecSmrg if (check_edevs) 43235c4bbdfSmrg XkbUpdateAllDeviceIndicators(changes, cause); 43305b261ecSmrg return; 43405b261ecSmrg} 43505b261ecSmrg 43605b261ecSmrg/***====================================================================***/ 43705b261ecSmrg 43805b261ecSmrg/***====================================================================***/ 43905b261ecSmrg 44035c4bbdfSmrg /* 44135c4bbdfSmrg * void 44235c4bbdfSmrg * XkbCheckIndicatorMaps(dev,sli,which) 44335c4bbdfSmrg * 44435c4bbdfSmrg * Updates the 'indicator accelerators' for the indicators specified 44535c4bbdfSmrg * by 'which' in the feedback specified by 'sli.' The indicator 44635c4bbdfSmrg * accelerators are internal to the server and are used to simplify 44735c4bbdfSmrg * and speed up the process of figuring out which indicators might 44835c4bbdfSmrg * be affected by a particular change in keyboard state or controls. 44935c4bbdfSmrg */ 45005b261ecSmrg 45105b261ecSmrgvoid 45235c4bbdfSmrgXkbCheckIndicatorMaps(DeviceIntPtr dev, XkbSrvLedInfoPtr sli, unsigned which) 45305b261ecSmrg{ 45435c4bbdfSmrg register unsigned i, bit; 45535c4bbdfSmrg XkbIndicatorMapPtr map; 45635c4bbdfSmrg XkbDescPtr xkb; 45705b261ecSmrg 45835c4bbdfSmrg if ((sli->flags & XkbSLI_HasOwnState) == 0) 4594642e01fSmrg return; 46005b261ecSmrg 46135c4bbdfSmrg sli->usesBase &= ~which; 46235c4bbdfSmrg sli->usesLatched &= ~which; 46335c4bbdfSmrg sli->usesLocked &= ~which; 46435c4bbdfSmrg sli->usesEffective &= ~which; 46535c4bbdfSmrg sli->usesCompat &= ~which; 46635c4bbdfSmrg sli->usesControls &= ~which; 46735c4bbdfSmrg sli->mapsPresent &= ~which; 46835c4bbdfSmrg 46935c4bbdfSmrg xkb = dev->key->xkbInfo->desc; 47035c4bbdfSmrg for (i = 0, bit = 1, map = sli->maps; i < XkbNumIndicators; 47135c4bbdfSmrg i++, bit <<= 1, map++) { 47235c4bbdfSmrg if (which & bit) { 47335c4bbdfSmrg CARD8 what; 47435c4bbdfSmrg 47535c4bbdfSmrg if (!map || !XkbIM_InUse(map)) 47635c4bbdfSmrg continue; 47735c4bbdfSmrg sli->mapsPresent |= bit; 47835c4bbdfSmrg 47935c4bbdfSmrg what = (map->which_mods | map->which_groups); 48035c4bbdfSmrg if (what & XkbIM_UseBase) 48135c4bbdfSmrg sli->usesBase |= bit; 48235c4bbdfSmrg if (what & XkbIM_UseLatched) 48335c4bbdfSmrg sli->usesLatched |= bit; 48435c4bbdfSmrg if (what & XkbIM_UseLocked) 48535c4bbdfSmrg sli->usesLocked |= bit; 48635c4bbdfSmrg if (what & XkbIM_UseEffective) 48735c4bbdfSmrg sli->usesEffective |= bit; 48835c4bbdfSmrg if (what & XkbIM_UseCompat) 48935c4bbdfSmrg sli->usesCompat |= bit; 49035c4bbdfSmrg if (map->ctrls) 49135c4bbdfSmrg sli->usesControls |= bit; 49235c4bbdfSmrg 49335c4bbdfSmrg map->mods.mask = map->mods.real_mods; 49435c4bbdfSmrg if (map->mods.vmods != 0) { 49535c4bbdfSmrg map->mods.mask |= XkbMaskForVMask(xkb, map->mods.vmods); 49635c4bbdfSmrg } 49735c4bbdfSmrg } 49835c4bbdfSmrg } 49935c4bbdfSmrg sli->usedComponents = 0; 50005b261ecSmrg if (sli->usesBase) 50135c4bbdfSmrg sli->usedComponents |= XkbModifierBaseMask | XkbGroupBaseMask; 50205b261ecSmrg if (sli->usesLatched) 50335c4bbdfSmrg sli->usedComponents |= XkbModifierLatchMask | XkbGroupLatchMask; 50405b261ecSmrg if (sli->usesLocked) 50535c4bbdfSmrg sli->usedComponents |= XkbModifierLockMask | XkbGroupLockMask; 50605b261ecSmrg if (sli->usesEffective) 50735c4bbdfSmrg sli->usedComponents |= XkbModifierStateMask | XkbGroupStateMask; 50805b261ecSmrg if (sli->usesCompat) 50935c4bbdfSmrg sli->usedComponents |= XkbCompatStateMask; 51005b261ecSmrg return; 51105b261ecSmrg} 51205b261ecSmrg 51305b261ecSmrg/***====================================================================***/ 51405b261ecSmrg 51535c4bbdfSmrg /* 51635c4bbdfSmrg * XkbSrvLedInfoPtr 51735c4bbdfSmrg * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts) 51835c4bbdfSmrg * 51935c4bbdfSmrg * Allocates an XkbSrvLedInfoPtr for the feedback specified by either 52035c4bbdfSmrg * 'kf' or 'lf' on the keyboard specified by 'dev.' 52135c4bbdfSmrg * 52235c4bbdfSmrg * If 'needed_parts' is non-zero, this function makes sure that any 52335c4bbdfSmrg * of the parts speicified therein are allocated. 52435c4bbdfSmrg */ 52505b261ecSmrgXkbSrvLedInfoPtr 52635c4bbdfSmrgXkbAllocSrvLedInfo(DeviceIntPtr dev, 52735c4bbdfSmrg KbdFeedbackPtr kf, LedFeedbackPtr lf, unsigned needed_parts) 52805b261ecSmrg{ 52935c4bbdfSmrg XkbSrvLedInfoPtr sli; 53035c4bbdfSmrg Bool checkAccel; 53135c4bbdfSmrg Bool checkNames; 53235c4bbdfSmrg 53335c4bbdfSmrg sli = NULL; 53435c4bbdfSmrg checkAccel = checkNames = FALSE; 53535c4bbdfSmrg if ((kf != NULL) && (kf->xkb_sli == NULL)) { 53635c4bbdfSmrg kf->xkb_sli = sli = calloc(1, sizeof(XkbSrvLedInfoRec)); 53735c4bbdfSmrg if (sli == NULL) 53835c4bbdfSmrg return NULL; /* ALLOCATION ERROR */ 53935c4bbdfSmrg if (dev->key && dev->key->xkbInfo) 54035c4bbdfSmrg sli->flags = XkbSLI_HasOwnState; 54135c4bbdfSmrg else 54235c4bbdfSmrg sli->flags = 0; 54335c4bbdfSmrg sli->class = KbdFeedbackClass; 54435c4bbdfSmrg sli->id = kf->ctrl.id; 54535c4bbdfSmrg sli->fb.kf = kf; 54635c4bbdfSmrg 54735c4bbdfSmrg sli->autoState = 0; 54835c4bbdfSmrg sli->explicitState = kf->ctrl.leds; 54935c4bbdfSmrg sli->effectiveState = kf->ctrl.leds; 55035c4bbdfSmrg 55135c4bbdfSmrg if ((kf == dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) { 55235c4bbdfSmrg XkbDescPtr xkb; 55335c4bbdfSmrg 55435c4bbdfSmrg xkb = dev->key->xkbInfo->desc; 55535c4bbdfSmrg sli->flags |= XkbSLI_IsDefault; 55635c4bbdfSmrg sli->physIndicators = xkb->indicators->phys_indicators; 55735c4bbdfSmrg sli->names = xkb->names->indicators; 55835c4bbdfSmrg sli->maps = xkb->indicators->maps; 55935c4bbdfSmrg checkNames = checkAccel = TRUE; 56035c4bbdfSmrg } 56135c4bbdfSmrg else { 56235c4bbdfSmrg sli->physIndicators = XkbAllIndicatorsMask; 56335c4bbdfSmrg sli->names = NULL; 56435c4bbdfSmrg sli->maps = NULL; 56535c4bbdfSmrg } 56635c4bbdfSmrg } 56735c4bbdfSmrg else if ((kf != NULL) && ((kf->xkb_sli->flags & XkbSLI_IsDefault) != 0)) { 56835c4bbdfSmrg XkbDescPtr xkb; 56935c4bbdfSmrg 57035c4bbdfSmrg xkb = dev->key->xkbInfo->desc; 57135c4bbdfSmrg sli = kf->xkb_sli; 57235c4bbdfSmrg sli->physIndicators = xkb->indicators->phys_indicators; 57335c4bbdfSmrg if (xkb->names->indicators != sli->names) { 57435c4bbdfSmrg checkNames = TRUE; 57535c4bbdfSmrg sli->names = xkb->names->indicators; 57635c4bbdfSmrg } 57735c4bbdfSmrg if (xkb->indicators->maps != sli->maps) { 57835c4bbdfSmrg checkAccel = TRUE; 57935c4bbdfSmrg sli->maps = xkb->indicators->maps; 58035c4bbdfSmrg } 58135c4bbdfSmrg } 58235c4bbdfSmrg else if ((lf != NULL) && (lf->xkb_sli == NULL)) { 58335c4bbdfSmrg lf->xkb_sli = sli = calloc(1, sizeof(XkbSrvLedInfoRec)); 58435c4bbdfSmrg if (sli == NULL) 58535c4bbdfSmrg return NULL; /* ALLOCATION ERROR */ 58635c4bbdfSmrg if (dev->key && dev->key->xkbInfo) 58735c4bbdfSmrg sli->flags = XkbSLI_HasOwnState; 58835c4bbdfSmrg else 58935c4bbdfSmrg sli->flags = 0; 59035c4bbdfSmrg sli->class = LedFeedbackClass; 59135c4bbdfSmrg sli->id = lf->ctrl.id; 59235c4bbdfSmrg sli->fb.lf = lf; 59335c4bbdfSmrg 59435c4bbdfSmrg sli->physIndicators = lf->ctrl.led_mask; 59535c4bbdfSmrg sli->autoState = 0; 59635c4bbdfSmrg sli->explicitState = lf->ctrl.led_values; 59735c4bbdfSmrg sli->effectiveState = lf->ctrl.led_values; 59835c4bbdfSmrg sli->maps = NULL; 59935c4bbdfSmrg sli->names = NULL; 60005b261ecSmrg } 6019ace9065Smrg else 60235c4bbdfSmrg return NULL; 60335c4bbdfSmrg if ((sli->names == NULL) && (needed_parts & XkbXI_IndicatorNamesMask)) 60435c4bbdfSmrg sli->names = calloc(XkbNumIndicators, sizeof(Atom)); 60535c4bbdfSmrg if ((sli->maps == NULL) && (needed_parts & XkbXI_IndicatorMapsMask)) 60635c4bbdfSmrg sli->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec)); 60705b261ecSmrg if (checkNames) { 60835c4bbdfSmrg register unsigned i, bit; 60935c4bbdfSmrg 61035c4bbdfSmrg sli->namesPresent = 0; 61135c4bbdfSmrg for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) { 61235c4bbdfSmrg if (sli->names[i] != None) 61335c4bbdfSmrg sli->namesPresent |= bit; 61435c4bbdfSmrg } 61505b261ecSmrg } 61605b261ecSmrg if (checkAccel) 61735c4bbdfSmrg XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask); 61805b261ecSmrg return sli; 61905b261ecSmrg} 62005b261ecSmrg 62105b261ecSmrgvoid 62205b261ecSmrgXkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) 62305b261ecSmrg{ 62435c4bbdfSmrg if ((sli->flags & XkbSLI_IsDefault) == 0) { 62535c4bbdfSmrg free(sli->maps); 62635c4bbdfSmrg free(sli->names); 62705b261ecSmrg } 62835c4bbdfSmrg sli->maps = NULL; 62935c4bbdfSmrg sli->names = NULL; 6306747b715Smrg free(sli); 63105b261ecSmrg return; 63205b261ecSmrg} 63305b261ecSmrg 6344642e01fSmrg/* 6354642e01fSmrg * XkbSrvLedInfoPtr 6364642e01fSmrg * XkbCopySrvLedInfo(dev,src,kf,lf) 6374642e01fSmrg * 6384642e01fSmrg * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made, 6394642e01fSmrg * thus the new copy behaves like the original one and can be freed with 6404642e01fSmrg * XkbFreeSrvLedInfo. 6414642e01fSmrg */ 6424642e01fSmrgXkbSrvLedInfoPtr 64335c4bbdfSmrgXkbCopySrvLedInfo(DeviceIntPtr from, 64435c4bbdfSmrg XkbSrvLedInfoPtr src, KbdFeedbackPtr kf, LedFeedbackPtr lf) 6454642e01fSmrg{ 6464642e01fSmrg XkbSrvLedInfoPtr sli_new = NULL; 6474642e01fSmrg 6484642e01fSmrg if (!src) 64935c4bbdfSmrg goto finish; 6504642e01fSmrg 65135c4bbdfSmrg sli_new = calloc(1, sizeof(XkbSrvLedInfoRec)); 6524642e01fSmrg if (!sli_new) 65335c4bbdfSmrg goto finish; 6544642e01fSmrg 6554642e01fSmrg memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec)); 6564642e01fSmrg if (sli_new->class == KbdFeedbackClass) 65735c4bbdfSmrg sli_new->fb.kf = kf; 6584642e01fSmrg else 65935c4bbdfSmrg sli_new->fb.lf = lf; 6604642e01fSmrg 6616747b715Smrg if (!(sli_new->flags & XkbSLI_IsDefault)) { 66235c4bbdfSmrg sli_new->names = calloc(XkbNumIndicators, sizeof(Atom)); 66335c4bbdfSmrg sli_new->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec)); 66435c4bbdfSmrg } /* else sli_new->names/maps is pointing to 66535c4bbdfSmrg dev->key->xkbInfo->desc->names->indicators; 66635c4bbdfSmrg dev->key->xkbInfo->desc->names->indicators; */ 6674642e01fSmrg 66835c4bbdfSmrg finish: 6694642e01fSmrg return sli_new; 6704642e01fSmrg} 67105b261ecSmrg 67205b261ecSmrg/***====================================================================***/ 67305b261ecSmrg 67435c4bbdfSmrg /* 67535c4bbdfSmrg * XkbSrvLedInfoPtr 67635c4bbdfSmrg * XkbFindSrvLedInfo(dev,class,id,needed_parts) 67735c4bbdfSmrg * 67835c4bbdfSmrg * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id' 67935c4bbdfSmrg * on the device specified by 'dev.' If the class and id specify 68035c4bbdfSmrg * a valid device feedback, this function returns the existing 68135c4bbdfSmrg * feedback or allocates a new one. 68235c4bbdfSmrg * 68335c4bbdfSmrg */ 68405b261ecSmrg 6856747b715SmrgXkbSrvLedInfoPtr 68635c4bbdfSmrgXkbFindSrvLedInfo(DeviceIntPtr dev, 68735c4bbdfSmrg unsigned class, unsigned id, unsigned needed_parts) 68805b261ecSmrg{ 68935c4bbdfSmrg XkbSrvLedInfoPtr sli; 69005b261ecSmrg 69105b261ecSmrg /* optimization to check for most common case */ 69235c4bbdfSmrg if (((class == XkbDfltXIClass) && (id == XkbDfltXIId)) && (dev->kbdfeed)) { 69335c4bbdfSmrg if (dev->kbdfeed->xkb_sli == NULL) { 69435c4bbdfSmrg dev->kbdfeed->xkb_sli = 69535c4bbdfSmrg XkbAllocSrvLedInfo(dev, dev->kbdfeed, NULL, needed_parts); 69635c4bbdfSmrg } 69735c4bbdfSmrg return dev->kbdfeed->xkb_sli; 69835c4bbdfSmrg } 69935c4bbdfSmrg 70035c4bbdfSmrg sli = NULL; 70135c4bbdfSmrg if (class == XkbDfltXIClass) { 70235c4bbdfSmrg if (dev->kbdfeed) 70335c4bbdfSmrg class = KbdFeedbackClass; 70435c4bbdfSmrg else if (dev->leds) 70535c4bbdfSmrg class = LedFeedbackClass; 70635c4bbdfSmrg else 70735c4bbdfSmrg return NULL; 70835c4bbdfSmrg } 70935c4bbdfSmrg if (class == KbdFeedbackClass) { 71035c4bbdfSmrg KbdFeedbackPtr kf; 71135c4bbdfSmrg 71235c4bbdfSmrg for (kf = dev->kbdfeed; kf != NULL; kf = kf->next) { 71335c4bbdfSmrg if ((id == XkbDfltXIId) || (id == kf->ctrl.id)) { 71435c4bbdfSmrg if (kf->xkb_sli == NULL) 71535c4bbdfSmrg kf->xkb_sli = 71635c4bbdfSmrg XkbAllocSrvLedInfo(dev, kf, NULL, needed_parts); 71735c4bbdfSmrg sli = kf->xkb_sli; 71835c4bbdfSmrg break; 71935c4bbdfSmrg } 72035c4bbdfSmrg } 72135c4bbdfSmrg } 72235c4bbdfSmrg else if (class == LedFeedbackClass) { 72335c4bbdfSmrg LedFeedbackPtr lf; 72435c4bbdfSmrg 72535c4bbdfSmrg for (lf = dev->leds; lf != NULL; lf = lf->next) { 72635c4bbdfSmrg if ((id == XkbDfltXIId) || (id == lf->ctrl.id)) { 72735c4bbdfSmrg if (lf->xkb_sli == NULL) 72835c4bbdfSmrg lf->xkb_sli = 72935c4bbdfSmrg XkbAllocSrvLedInfo(dev, NULL, lf, needed_parts); 73035c4bbdfSmrg sli = lf->xkb_sli; 73135c4bbdfSmrg break; 73235c4bbdfSmrg } 73335c4bbdfSmrg } 73405b261ecSmrg } 7359ace9065Smrg if (sli) { 73635c4bbdfSmrg if ((sli->names == NULL) && (needed_parts & XkbXI_IndicatorNamesMask)) 73735c4bbdfSmrg sli->names = calloc(XkbNumIndicators, sizeof(Atom)); 73835c4bbdfSmrg if ((sli->maps == NULL) && (needed_parts & XkbXI_IndicatorMapsMask)) 73935c4bbdfSmrg sli->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec)); 7409ace9065Smrg } 74105b261ecSmrg return sli; 74205b261ecSmrg} 74305b261ecSmrg 74405b261ecSmrg/***====================================================================***/ 74505b261ecSmrg 74605b261ecSmrgvoid 74735c4bbdfSmrgXkbFlushLedEvents(DeviceIntPtr dev, 74835c4bbdfSmrg DeviceIntPtr kbd, 74935c4bbdfSmrg XkbSrvLedInfoPtr sli, 75035c4bbdfSmrg xkbExtensionDeviceNotify * ed, 75135c4bbdfSmrg XkbChangesPtr changes, XkbEventCausePtr cause) 75205b261ecSmrg{ 75305b261ecSmrg if (changes) { 75435c4bbdfSmrg if (changes->indicators.state_changes) 75535c4bbdfSmrg XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState); 75635c4bbdfSmrg XkbSendNotification(kbd, changes, cause); 75735c4bbdfSmrg memset((char *) changes, 0, sizeof(XkbChangesRec)); 75835c4bbdfSmrg 75935c4bbdfSmrg if (XkbAX_NeedFeedback 76035c4bbdfSmrg (kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) { 76135c4bbdfSmrg if (sli->effectiveState) 76235c4bbdfSmrg /* it appears that the which parameter is not used */ 76335c4bbdfSmrg XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask); 76435c4bbdfSmrg else 76535c4bbdfSmrg XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask); 76635c4bbdfSmrg } 76705b261ecSmrg } 7686747b715Smrg if (ed) { 76935c4bbdfSmrg if (ed->reason) { 77035c4bbdfSmrg if ((dev != kbd) && (ed->reason & XkbXI_IndicatorStateMask)) 77135c4bbdfSmrg XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState); 77235c4bbdfSmrg XkbSendExtensionDeviceNotify(dev, cause->client, ed); 77335c4bbdfSmrg } 77435c4bbdfSmrg memset((char *) ed, 0, sizeof(XkbExtensionDeviceNotify)); 77505b261ecSmrg } 77605b261ecSmrg return; 77705b261ecSmrg} 77805b261ecSmrg 77905b261ecSmrg/***====================================================================***/ 78005b261ecSmrg 78105b261ecSmrgvoid 78235c4bbdfSmrgXkbApplyLedNameChanges(DeviceIntPtr dev, 78335c4bbdfSmrg XkbSrvLedInfoPtr sli, 78435c4bbdfSmrg unsigned changed_names, 78535c4bbdfSmrg xkbExtensionDeviceNotify * ed, 78635c4bbdfSmrg XkbChangesPtr changes, XkbEventCausePtr cause) 78705b261ecSmrg{ 78835c4bbdfSmrg DeviceIntPtr kbd; 78935c4bbdfSmrg XkbChangesRec my_changes; 79035c4bbdfSmrg xkbExtensionDeviceNotify my_ed; 79105b261ecSmrg 79235c4bbdfSmrg if (changed_names == 0) 79335c4bbdfSmrg return; 79405b261ecSmrg if (dev->key && dev->key->xkbInfo) 79535c4bbdfSmrg kbd = dev; 79635c4bbdfSmrg else 79735c4bbdfSmrg kbd = inputInfo.keyboard; 79835c4bbdfSmrg 79935c4bbdfSmrg if (ed == NULL) { 80035c4bbdfSmrg ed = &my_ed; 80135c4bbdfSmrg memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify)); 80235c4bbdfSmrg } 80335c4bbdfSmrg else if ((ed->reason & XkbXI_IndicatorsMask) && 80435c4bbdfSmrg ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) { 80535c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 80635c4bbdfSmrg } 80735c4bbdfSmrg 80835c4bbdfSmrg if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) { 80935c4bbdfSmrg if (changes == NULL) { 81035c4bbdfSmrg changes = &my_changes; 81135c4bbdfSmrg memset((char *) changes, 0, sizeof(XkbChangesRec)); 81235c4bbdfSmrg } 81335c4bbdfSmrg changes->names.changed |= XkbIndicatorNamesMask; 81435c4bbdfSmrg changes->names.changed_indicators |= changed_names; 81535c4bbdfSmrg } 81635c4bbdfSmrg 81735c4bbdfSmrg ed->reason |= XkbXI_IndicatorNamesMask; 81835c4bbdfSmrg ed->ledClass = sli->class; 81935c4bbdfSmrg ed->ledID = sli->id; 82035c4bbdfSmrg ed->ledsDefined = sli->namesPresent | sli->mapsPresent; 82135c4bbdfSmrg ed->ledState = sli->effectiveState; 82235c4bbdfSmrg ed->unsupported = 0; 82335c4bbdfSmrg ed->supported = XkbXI_AllFeaturesMask; 82435c4bbdfSmrg 82535c4bbdfSmrg if (changes != &my_changes) 82635c4bbdfSmrg changes = NULL; 82735c4bbdfSmrg if (ed != &my_ed) 82835c4bbdfSmrg ed = NULL; 82905b261ecSmrg if (changes || ed) 83035c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 83105b261ecSmrg return; 83205b261ecSmrg} 83335c4bbdfSmrg 83405b261ecSmrg/***====================================================================***/ 83505b261ecSmrg 83635c4bbdfSmrg /* 83735c4bbdfSmrg * void 83835c4bbdfSmrg * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause) 83935c4bbdfSmrg * 84035c4bbdfSmrg * Handles all of the secondary effects of the changes to the 84135c4bbdfSmrg * feedback specified by 'sli' on the device specified by 'dev.' 84235c4bbdfSmrg * 84335c4bbdfSmrg * If 'changed_maps' specifies any indicators, this function generates 84435c4bbdfSmrg * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify 84535c4bbdfSmrg * events to report the changes, and recalculates the effective 84635c4bbdfSmrg * state of each indicator with a changed map. If any indicators 84735c4bbdfSmrg * change state, the server generates XkbExtensionDeviceNotify and 84835c4bbdfSmrg * XkbIndicatorStateNotify events as appropriate. 84935c4bbdfSmrg * 85035c4bbdfSmrg * If 'changes' is non-NULL, this function updates it to reflect 85135c4bbdfSmrg * any changes to the keyboard state or controls or to the 'core' 85235c4bbdfSmrg * indicator names, maps, or state. If 'changes' is NULL, this 85335c4bbdfSmrg * function generates XKB events as needed to report the changes. 85435c4bbdfSmrg * If 'dev' is not a keyboard device, any changes are reported 85535c4bbdfSmrg * for the core keyboard. 85635c4bbdfSmrg * 85735c4bbdfSmrg * The 'cause' specifies the reason for the event (key event or 85835c4bbdfSmrg * request) for the change, as reported in some XKB events. 85935c4bbdfSmrg */ 86005b261ecSmrg 86105b261ecSmrgvoid 86235c4bbdfSmrgXkbApplyLedMapChanges(DeviceIntPtr dev, 86335c4bbdfSmrg XkbSrvLedInfoPtr sli, 86435c4bbdfSmrg unsigned changed_maps, 86535c4bbdfSmrg xkbExtensionDeviceNotify * ed, 86635c4bbdfSmrg XkbChangesPtr changes, XkbEventCausePtr cause) 86705b261ecSmrg{ 86835c4bbdfSmrg DeviceIntPtr kbd; 86935c4bbdfSmrg XkbChangesRec my_changes; 87035c4bbdfSmrg xkbExtensionDeviceNotify my_ed; 87105b261ecSmrg 87235c4bbdfSmrg if (changed_maps == 0) 87335c4bbdfSmrg return; 87405b261ecSmrg if (dev->key && dev->key->xkbInfo) 87535c4bbdfSmrg kbd = dev; 87635c4bbdfSmrg else 87735c4bbdfSmrg kbd = inputInfo.keyboard; 87805b261ecSmrg 87935c4bbdfSmrg if (ed == NULL) { 88035c4bbdfSmrg ed = &my_ed; 88135c4bbdfSmrg memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify)); 88205b261ecSmrg } 88335c4bbdfSmrg else if ((ed->reason & XkbXI_IndicatorsMask) && 88435c4bbdfSmrg ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) { 88535c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 88605b261ecSmrg } 88705b261ecSmrg 88835c4bbdfSmrg if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) { 88935c4bbdfSmrg if (changes == NULL) { 89035c4bbdfSmrg changes = &my_changes; 89135c4bbdfSmrg memset((char *) changes, 0, sizeof(XkbChangesRec)); 89235c4bbdfSmrg } 89335c4bbdfSmrg changes->indicators.map_changes |= changed_maps; 89405b261ecSmrg } 89505b261ecSmrg 89635c4bbdfSmrg XkbCheckIndicatorMaps(dev, sli, changed_maps); 89705b261ecSmrg 89835c4bbdfSmrg ed->reason |= XkbXI_IndicatorMapsMask; 89935c4bbdfSmrg ed->ledClass = sli->class; 90035c4bbdfSmrg ed->ledID = sli->id; 90135c4bbdfSmrg ed->ledsDefined = sli->namesPresent | sli->mapsPresent; 90235c4bbdfSmrg ed->ledState = sli->effectiveState; 90335c4bbdfSmrg ed->unsupported = 0; 90435c4bbdfSmrg ed->supported = XkbXI_AllFeaturesMask; 90505b261ecSmrg 90635c4bbdfSmrg XkbUpdateLedAutoState(dev, sli, changed_maps, ed, changes, cause); 90705b261ecSmrg 90835c4bbdfSmrg if (changes != &my_changes) 90935c4bbdfSmrg changes = NULL; 91035c4bbdfSmrg if (ed != &my_ed) 91135c4bbdfSmrg ed = NULL; 91205b261ecSmrg if (changes || ed) 91335c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 91405b261ecSmrg return; 91505b261ecSmrg} 91605b261ecSmrg 91705b261ecSmrg/***====================================================================***/ 91805b261ecSmrg 91905b261ecSmrgvoid 92035c4bbdfSmrgXkbApplyLedStateChanges(DeviceIntPtr dev, 92135c4bbdfSmrg XkbSrvLedInfoPtr sli, 92235c4bbdfSmrg unsigned changed_leds, 92335c4bbdfSmrg xkbExtensionDeviceNotify * ed, 92435c4bbdfSmrg XkbChangesPtr changes, XkbEventCausePtr cause) 92505b261ecSmrg{ 92635c4bbdfSmrg XkbSrvInfoPtr xkbi; 92735c4bbdfSmrg DeviceIntPtr kbd; 92835c4bbdfSmrg XkbChangesRec my_changes; 92935c4bbdfSmrg xkbExtensionDeviceNotify my_ed; 93035c4bbdfSmrg register unsigned i, bit, affected; 93135c4bbdfSmrg XkbIndicatorMapPtr map; 93235c4bbdfSmrg unsigned oldState; 93335c4bbdfSmrg Bool kb_changed; 93435c4bbdfSmrg 93535c4bbdfSmrg if (changed_leds == 0) 93635c4bbdfSmrg return; 93705b261ecSmrg if (dev->key && dev->key->xkbInfo) 93835c4bbdfSmrg kbd = dev; 93935c4bbdfSmrg else 94035c4bbdfSmrg kbd = inputInfo.keyboard; 94135c4bbdfSmrg xkbi = kbd->key->xkbInfo; 94235c4bbdfSmrg 94335c4bbdfSmrg if (changes == NULL) { 94435c4bbdfSmrg changes = &my_changes; 94535c4bbdfSmrg memset((char *) changes, 0, sizeof(XkbChangesRec)); 94635c4bbdfSmrg } 94735c4bbdfSmrg 94835c4bbdfSmrg kb_changed = FALSE; 94935c4bbdfSmrg affected = changed_leds; 95035c4bbdfSmrg oldState = sli->effectiveState; 95135c4bbdfSmrg for (i = 0, bit = 1; (i < XkbNumIndicators) && (affected); i++, bit <<= 1) { 95235c4bbdfSmrg if ((affected & bit) == 0) 95335c4bbdfSmrg continue; 95435c4bbdfSmrg affected &= ~bit; 95535c4bbdfSmrg map = &sli->maps[i]; 95635c4bbdfSmrg if (map->flags & XkbIM_NoExplicit) { 95735c4bbdfSmrg sli->explicitState &= ~bit; 95835c4bbdfSmrg continue; 95935c4bbdfSmrg } 96035c4bbdfSmrg if (map->flags & XkbIM_LEDDrivesKB) { 96135c4bbdfSmrg Bool on = ((sli->explicitState & bit) != 0); 96235c4bbdfSmrg 96335c4bbdfSmrg if (XkbApplyLEDChangeToKeyboard(xkbi, map, on, changes)) 96435c4bbdfSmrg kb_changed = TRUE; 96535c4bbdfSmrg } 96635c4bbdfSmrg } 96735c4bbdfSmrg sli->effectiveState = (sli->autoState | sli->explicitState); 96835c4bbdfSmrg affected = sli->effectiveState ^ oldState; 96935c4bbdfSmrg 97035c4bbdfSmrg if (ed == NULL) { 97135c4bbdfSmrg ed = &my_ed; 97235c4bbdfSmrg memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify)); 97335c4bbdfSmrg } 97435c4bbdfSmrg else if (affected && (ed->reason & XkbXI_IndicatorsMask) && 97535c4bbdfSmrg ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) { 97635c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 97735c4bbdfSmrg } 97835c4bbdfSmrg 97935c4bbdfSmrg if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) 98035c4bbdfSmrg changes->indicators.state_changes |= affected; 98105b261ecSmrg if (affected) { 98235c4bbdfSmrg ed->reason |= XkbXI_IndicatorStateMask; 98335c4bbdfSmrg ed->ledClass = sli->class; 98435c4bbdfSmrg ed->ledID = sli->id; 98535c4bbdfSmrg ed->ledsDefined = sli->namesPresent | sli->mapsPresent; 98635c4bbdfSmrg ed->ledState = sli->effectiveState; 98735c4bbdfSmrg ed->unsupported = 0; 98835c4bbdfSmrg ed->supported = XkbXI_AllFeaturesMask; 98905b261ecSmrg } 99005b261ecSmrg 99105b261ecSmrg if (kb_changed) { 99235c4bbdfSmrg XkbComputeDerivedState(kbd->key->xkbInfo); 99335c4bbdfSmrg XkbUpdateLedAutoState(dev, sli, sli->mapsPresent, ed, changes, cause); 99405b261ecSmrg } 99505b261ecSmrg 99635c4bbdfSmrg if (changes != &my_changes) 99735c4bbdfSmrg changes = NULL; 99835c4bbdfSmrg if (ed != &my_ed) 99935c4bbdfSmrg ed = NULL; 100005b261ecSmrg if (changes || ed) 100135c4bbdfSmrg XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause); 100205b261ecSmrg if (kb_changed) 100335c4bbdfSmrg XkbUpdateAllDeviceIndicators(NULL, cause); 100405b261ecSmrg return; 100505b261ecSmrg} 1006