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