xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xkbLEDs.c (34220B)


      1 /************************************************************
      2 Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
      3 
      4 Permission to use, copy, modify, and distribute this
      5 software and its documentation for any purpose and without
      6 fee is hereby granted, provided that the above copyright
      7 notice appear in all copies and that both that copyright
      8 notice and this permission notice appear in supporting
      9 documentation, and that the name of Silicon Graphics not be
     10 used in advertising or publicity pertaining to distribution
     11 of the software without specific prior written permission.
     12 Silicon Graphics makes no representation about the suitability
     13 of this software for any purpose. It is provided "as is"
     14 without any express or implied warranty.
     15 
     16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
     17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
     18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
     19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
     20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
     22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
     23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
     24 
     25 ********************************************************/
     26 
     27 #ifdef HAVE_DIX_CONFIG_H
     28 #include <dix-config.h>
     29 #endif
     30 
     31 #include <stdio.h>
     32 #include <ctype.h>
     33 #include <math.h>
     34 #include <X11/X.h>
     35 #include <X11/Xproto.h>
     36 #include "misc.h"
     37 #include "inputstr.h"
     38 
     39 #include <X11/extensions/XI.h>
     40 #include <xkbsrv.h>
     41 #include "xkb.h"
     42 
     43 /***====================================================================***/
     44 
     45         /*
     46          * unsigned
     47          * XkbIndicatorsToUpdate(dev,changed,check_devs_rtrn)
     48          *
     49          * Given a keyboard and a set of state components that have changed,
     50          * this function returns the indicators on the default keyboard
     51          * feedback that might be affected.   It also reports whether or not
     52          * any extension devices might be affected in check_devs_rtrn.
     53          */
     54 
     55 unsigned
     56 XkbIndicatorsToUpdate(DeviceIntPtr dev,
     57                       unsigned long state_changes, Bool enable_changes)
     58 {
     59     register unsigned update = 0;
     60     XkbSrvLedInfoPtr sli;
     61 
     62     sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
     63 
     64     if (!sli)
     65         return update;
     66 
     67     if (state_changes & (XkbModifierStateMask | XkbGroupStateMask))
     68         update |= sli->usesEffective;
     69     if (state_changes & (XkbModifierBaseMask | XkbGroupBaseMask))
     70         update |= sli->usesBase;
     71     if (state_changes & (XkbModifierLatchMask | XkbGroupLatchMask))
     72         update |= sli->usesLatched;
     73     if (state_changes & (XkbModifierLockMask | XkbGroupLockMask))
     74         update |= sli->usesLocked;
     75     if (state_changes & XkbCompatStateMask)
     76         update |= sli->usesCompat;
     77     if (enable_changes)
     78         update |= sli->usesControls;
     79     return update;
     80 }
     81 
     82 /***====================================================================***/
     83 
     84         /*
     85          * Bool
     86          *XkbApplyLEDChangeToKeyboard(xkbi,map,on,change)
     87          *
     88          * Some indicators "drive" the keyboard when their state is explicitly
     89          * changed, as described in section 9.2.1 of the XKB protocol spec.
     90          * This function updates the state and controls for the keyboard
     91          * specified by 'xkbi' to reflect any changes that are required
     92          * when the indicator described by 'map' is turned on or off.  The
     93          * extent of the changes is reported in change, which must be defined.
     94          */
     95 static Bool
     96 XkbApplyLEDChangeToKeyboard(XkbSrvInfoPtr xkbi,
     97                             XkbIndicatorMapPtr map,
     98                             Bool on, XkbChangesPtr change)
     99 {
    100     Bool ctrlChange, stateChange;
    101     XkbStatePtr state;
    102 
    103     if ((map->flags & XkbIM_NoExplicit) ||
    104         ((map->flags & XkbIM_LEDDrivesKB) == 0))
    105         return FALSE;
    106     ctrlChange = stateChange = FALSE;
    107     if (map->ctrls) {
    108         XkbControlsPtr ctrls = xkbi->desc->ctrls;
    109         unsigned old;
    110 
    111         old = ctrls->enabled_ctrls;
    112         if (on)
    113             ctrls->enabled_ctrls |= map->ctrls;
    114         else
    115             ctrls->enabled_ctrls &= ~map->ctrls;
    116         if (old != ctrls->enabled_ctrls) {
    117             change->ctrls.changed_ctrls = XkbControlsEnabledMask;
    118             change->ctrls.enabled_ctrls_changes = old ^ ctrls->enabled_ctrls;
    119             ctrlChange = TRUE;
    120         }
    121     }
    122     state = &xkbi->state;
    123     if ((map->groups) && ((map->which_groups & (~XkbIM_UseBase)) != 0)) {
    124         register int i;
    125         register unsigned bit, match;
    126 
    127         if (on)
    128             match = (map->groups) & XkbAllGroupsMask;
    129         else
    130             match = (~map->groups) & XkbAllGroupsMask;
    131         if (map->which_groups & (XkbIM_UseLocked | XkbIM_UseEffective)) {
    132             for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
    133                 if (bit & match)
    134                     break;
    135             }
    136             if (map->which_groups & XkbIM_UseLatched)
    137                 XkbLatchGroup(xkbi->device, 0); /* unlatch group */
    138             state->locked_group = i;
    139             stateChange = TRUE;
    140         }
    141         else if (map->which_groups & (XkbIM_UseLatched | XkbIM_UseEffective)) {
    142             for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
    143                 if (bit & match)
    144                     break;
    145             }
    146             state->locked_group = 0;
    147             XkbLatchGroup(xkbi->device, i);
    148             stateChange = TRUE;
    149         }
    150     }
    151     if ((map->mods.mask) && ((map->which_mods & (~XkbIM_UseBase)) != 0)) {
    152         if (map->which_mods & (XkbIM_UseLocked | XkbIM_UseEffective)) {
    153             register unsigned long old;
    154 
    155             old = state->locked_mods;
    156             if (on)
    157                 state->locked_mods |= map->mods.mask;
    158             else
    159                 state->locked_mods &= ~map->mods.mask;
    160             if (state->locked_mods != old)
    161                 stateChange = TRUE;
    162         }
    163         if (map->which_mods & (XkbIM_UseLatched | XkbIM_UseEffective)) {
    164             register unsigned long newmods;
    165 
    166             newmods = state->latched_mods;
    167             if (on)
    168                 newmods |= map->mods.mask;
    169             else
    170                 newmods &= ~map->mods.mask;
    171             if (newmods != state->locked_mods) {
    172                 newmods &= map->mods.mask;
    173                 XkbLatchModifiers(xkbi->device, map->mods.mask, newmods);
    174                 stateChange = TRUE;
    175             }
    176         }
    177     }
    178     return stateChange || ctrlChange;
    179 }
    180 
    181         /*
    182          * Bool
    183          * ComputeAutoState(map,state,ctrls)
    184          *
    185          * This function reports the effect of applying the specified
    186          * indicator map given the specified state and controls, as
    187          * described in section 9.2 of the XKB protocol specification.
    188          */
    189 
    190 static Bool
    191 ComputeAutoState(XkbIndicatorMapPtr map,
    192                  XkbStatePtr state, XkbControlsPtr ctrls)
    193 {
    194     Bool on;
    195     CARD8 mods, group;
    196 
    197     on = FALSE;
    198     mods = group = 0;
    199     if (map->which_mods & XkbIM_UseAnyMods) {
    200         if (map->which_mods & XkbIM_UseBase)
    201             mods |= state->base_mods;
    202         if (map->which_mods & XkbIM_UseLatched)
    203             mods |= state->latched_mods;
    204         if (map->which_mods & XkbIM_UseLocked)
    205             mods |= state->locked_mods;
    206         if (map->which_mods & XkbIM_UseEffective)
    207             mods |= state->mods;
    208         if (map->which_mods & XkbIM_UseCompat)
    209             mods |= state->compat_state;
    210         on = ((map->mods.mask & mods) != 0);
    211         on = on || ((mods == 0) && (map->mods.mask == 0) &&
    212                     (map->mods.vmods == 0));
    213     }
    214     if (map->which_groups & XkbIM_UseAnyGroup) {
    215         if (map->which_groups & XkbIM_UseBase)
    216             group |= (1L << state->base_group);
    217         if (map->which_groups & XkbIM_UseLatched)
    218             group |= (1L << state->latched_group);
    219         if (map->which_groups & XkbIM_UseLocked)
    220             group |= (1L << state->locked_group);
    221         if (map->which_groups & XkbIM_UseEffective)
    222             group |= (1L << state->group);
    223         on = on || (((map->groups & group) != 0) || (map->groups == 0));
    224     }
    225     if (map->ctrls)
    226         on = on || (ctrls->enabled_ctrls & map->ctrls);
    227     return on;
    228 }
    229 
    230 static void
    231 XkbUpdateLedAutoState(DeviceIntPtr dev,
    232                       XkbSrvLedInfoPtr sli,
    233                       unsigned maps_to_check,
    234                       xkbExtensionDeviceNotify * ed,
    235                       XkbChangesPtr changes, XkbEventCausePtr cause)
    236 {
    237     DeviceIntPtr kbd;
    238     XkbStatePtr state;
    239     XkbControlsPtr ctrls;
    240     XkbChangesRec my_changes;
    241     xkbExtensionDeviceNotify my_ed;
    242     register unsigned i, bit, affected;
    243     register XkbIndicatorMapPtr map;
    244     unsigned oldState;
    245 
    246     if ((maps_to_check == 0) || (sli->maps == NULL) || (sli->mapsPresent == 0))
    247         return;
    248 
    249     if (dev->key && dev->key->xkbInfo)
    250         kbd = dev;
    251     else
    252         kbd = inputInfo.keyboard;
    253 
    254     state = &kbd->key->xkbInfo->state;
    255     ctrls = kbd->key->xkbInfo->desc->ctrls;
    256     affected = maps_to_check;
    257     oldState = sli->effectiveState;
    258     sli->autoState &= ~affected;
    259     for (i = 0, bit = 1; (i < XkbNumIndicators) && (affected); i++, bit <<= 1) {
    260         if ((affected & bit) == 0)
    261             continue;
    262         affected &= ~bit;
    263         map = &sli->maps[i];
    264         if ((!(map->flags & XkbIM_NoAutomatic)) &&
    265             ComputeAutoState(map, state, ctrls))
    266             sli->autoState |= bit;
    267     }
    268     sli->effectiveState = (sli->autoState | sli->explicitState);
    269     affected = sli->effectiveState ^ oldState;
    270     if (affected == 0)
    271         return;
    272 
    273     if (ed == NULL) {
    274         ed = &my_ed;
    275         memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
    276     }
    277     else if ((ed->reason & XkbXI_IndicatorsMask) &&
    278              ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
    279         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    280     }
    281 
    282     if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) {
    283         if (changes == NULL) {
    284             changes = &my_changes;
    285             memset((char *) changes, 0, sizeof(XkbChangesRec));
    286         }
    287         changes->indicators.state_changes |= affected;
    288     }
    289 
    290     ed->reason |= XkbXI_IndicatorStateMask;
    291     ed->ledClass = sli->class;
    292     ed->ledID = sli->id;
    293     ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
    294     ed->ledState = sli->effectiveState;
    295     ed->unsupported = 0;
    296     ed->supported = XkbXI_AllFeaturesMask;
    297 
    298     if (changes != &my_changes)
    299         changes = NULL;
    300     if (ed != &my_ed)
    301         ed = NULL;
    302     if (changes || ed)
    303         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    304     return;
    305 }
    306 
    307 void
    308 XkbUpdateAllDeviceIndicators(XkbChangesPtr changes, XkbEventCausePtr cause)
    309 {
    310     DeviceIntPtr edev;
    311     XkbSrvLedInfoPtr sli;
    312 
    313     for (edev = inputInfo.devices; edev != NULL; edev = edev->next) {
    314         if (edev->kbdfeed) {
    315             KbdFeedbackPtr kf;
    316 
    317             for (kf = edev->kbdfeed; kf != NULL; kf = kf->next) {
    318                 if ((kf->xkb_sli == NULL) || (kf->xkb_sli->maps == NULL))
    319                     continue;
    320                 sli = kf->xkb_sli;
    321                 XkbUpdateLedAutoState(edev, sli, sli->mapsPresent, NULL,
    322                                       changes, cause);
    323 
    324             }
    325         }
    326         if (edev->leds) {
    327             LedFeedbackPtr lf;
    328 
    329             for (lf = edev->leds; lf != NULL; lf = lf->next) {
    330                 if ((lf->xkb_sli == NULL) || (lf->xkb_sli->maps == NULL))
    331                     continue;
    332                 sli = lf->xkb_sli;
    333                 XkbUpdateLedAutoState(edev, sli, sli->mapsPresent, NULL,
    334                                       changes, cause);
    335 
    336             }
    337         }
    338     }
    339     return;
    340 }
    341 
    342 /***====================================================================***/
    343 
    344         /*
    345          * void
    346          * XkbSetIndicators(dev,affect,values,cause)
    347          *
    348          * Attempts to change the indicators specified in 'affect' to the
    349          * states specified in 'values' for the default keyboard feedback
    350          * on the keyboard specified by 'dev.'   Attempts to change indicator
    351          * state might be ignored or have no affect, depending on the XKB
    352          * indicator map for any affected indicators, as described in section
    353          * 9.2 of the XKB protocol specification.
    354          *
    355          * If 'changes' is non-NULL, this function notes any changes to the
    356          * keyboard state, controls, or indicator state that result from this
    357          * attempted change.   If 'changes' is NULL, this function generates
    358          * XKB events to report any such changes to interested clients.
    359          *
    360          * If 'cause' is non-NULL, it specifies the reason for the change,
    361          * as reported in some XKB events.   If it is NULL, this function
    362          * assumes that the change is the result of a core protocol
    363          * ChangeKeyboardMapping request.
    364          */
    365 
    366 void
    367 XkbSetIndicators(DeviceIntPtr dev,
    368                  CARD32 affect, CARD32 values, XkbEventCausePtr cause)
    369 {
    370     XkbSrvLedInfoPtr sli;
    371     XkbChangesRec changes;
    372     xkbExtensionDeviceNotify ed;
    373     unsigned side_affected;
    374 
    375     memset((char *) &changes, 0, sizeof(XkbChangesRec));
    376     memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
    377     sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
    378     sli->explicitState &= ~affect;
    379     sli->explicitState |= (affect & values);
    380     XkbApplyLedStateChanges(dev, sli, affect, &ed, &changes, cause);
    381 
    382     side_affected = 0;
    383     if (changes.state_changes != 0)
    384         side_affected |=
    385             XkbIndicatorsToUpdate(dev, changes.state_changes, FALSE);
    386     if (changes.ctrls.enabled_ctrls_changes)
    387         side_affected |= sli->usesControls;
    388 
    389     if (side_affected) {
    390         XkbUpdateLedAutoState(dev, sli, side_affected, &ed, &changes, cause);
    391         affect |= side_affected;
    392     }
    393     if (changes.state_changes || changes.ctrls.enabled_ctrls_changes)
    394         XkbUpdateAllDeviceIndicators(NULL, cause);
    395 
    396     XkbFlushLedEvents(dev, dev, sli, &ed, &changes, cause);
    397     return;
    398 }
    399 
    400 /***====================================================================***/
    401 
    402 /***====================================================================***/
    403 
    404         /*
    405          * void
    406          * XkbUpdateIndicators(dev,update,check_edevs,changes,cause)
    407          *
    408          * Applies the indicator maps for any indicators specified in
    409          * 'update' from the default keyboard feedback on the device
    410          * specified by 'dev.'
    411          *
    412          * If 'changes' is NULL, this function generates and XKB events
    413          * required to report the necessary changes, otherwise it simply
    414          * notes the indicators with changed state.
    415          *
    416          * If 'check_edevs' is TRUE, this function also checks the indicator
    417          * maps for any open extension devices that have them, and updates
    418          * the state of any extension device indicators as necessary.
    419          */
    420 
    421 void
    422 XkbUpdateIndicators(DeviceIntPtr dev,
    423                     register CARD32 update,
    424                     Bool check_edevs,
    425                     XkbChangesPtr changes, XkbEventCausePtr cause)
    426 {
    427     XkbSrvLedInfoPtr sli;
    428 
    429     sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
    430     XkbUpdateLedAutoState(dev, sli, update, NULL, changes, cause);
    431     if (check_edevs)
    432         XkbUpdateAllDeviceIndicators(changes, cause);
    433     return;
    434 }
    435 
    436 /***====================================================================***/
    437 
    438 /***====================================================================***/
    439 
    440         /*
    441          * void
    442          * XkbCheckIndicatorMaps(dev,sli,which)
    443          *
    444          * Updates the 'indicator accelerators' for the indicators specified
    445          * by 'which' in the feedback specified by 'sli.' The indicator
    446          * accelerators are internal to the server and are used to simplify
    447          * and speed up the process of figuring out which indicators might
    448          * be affected by a particular change in keyboard state or controls.
    449          */
    450 
    451 void
    452 XkbCheckIndicatorMaps(DeviceIntPtr dev, XkbSrvLedInfoPtr sli, unsigned which)
    453 {
    454     register unsigned i, bit;
    455     XkbIndicatorMapPtr map;
    456     XkbDescPtr xkb;
    457 
    458     if ((sli->flags & XkbSLI_HasOwnState) == 0)
    459         return;
    460 
    461     sli->usesBase &= ~which;
    462     sli->usesLatched &= ~which;
    463     sli->usesLocked &= ~which;
    464     sli->usesEffective &= ~which;
    465     sli->usesCompat &= ~which;
    466     sli->usesControls &= ~which;
    467     sli->mapsPresent &= ~which;
    468 
    469     xkb = dev->key->xkbInfo->desc;
    470     for (i = 0, bit = 1, map = sli->maps; i < XkbNumIndicators;
    471          i++, bit <<= 1, map++) {
    472         if (which & bit) {
    473             CARD8 what;
    474 
    475             if (!map || !XkbIM_InUse(map))
    476                 continue;
    477             sli->mapsPresent |= bit;
    478 
    479             what = (map->which_mods | map->which_groups);
    480             if (what & XkbIM_UseBase)
    481                 sli->usesBase |= bit;
    482             if (what & XkbIM_UseLatched)
    483                 sli->usesLatched |= bit;
    484             if (what & XkbIM_UseLocked)
    485                 sli->usesLocked |= bit;
    486             if (what & XkbIM_UseEffective)
    487                 sli->usesEffective |= bit;
    488             if (what & XkbIM_UseCompat)
    489                 sli->usesCompat |= bit;
    490             if (map->ctrls)
    491                 sli->usesControls |= bit;
    492 
    493             map->mods.mask = map->mods.real_mods;
    494             if (map->mods.vmods != 0) {
    495                 map->mods.mask |= XkbMaskForVMask(xkb, map->mods.vmods);
    496             }
    497         }
    498     }
    499     sli->usedComponents = 0;
    500     if (sli->usesBase)
    501         sli->usedComponents |= XkbModifierBaseMask | XkbGroupBaseMask;
    502     if (sli->usesLatched)
    503         sli->usedComponents |= XkbModifierLatchMask | XkbGroupLatchMask;
    504     if (sli->usesLocked)
    505         sli->usedComponents |= XkbModifierLockMask | XkbGroupLockMask;
    506     if (sli->usesEffective)
    507         sli->usedComponents |= XkbModifierStateMask | XkbGroupStateMask;
    508     if (sli->usesCompat)
    509         sli->usedComponents |= XkbCompatStateMask;
    510     return;
    511 }
    512 
    513 /***====================================================================***/
    514 
    515         /*
    516          * XkbSrvLedInfoPtr
    517          * XkbAllocSrvLedInfo(dev,kf,lf,needed_parts)
    518          *
    519          * Allocates an XkbSrvLedInfoPtr for the feedback specified by either
    520          * 'kf' or 'lf' on the keyboard specified by 'dev.'
    521          *
    522          * If 'needed_parts' is non-zero, this function makes sure that any
    523          * of the parts speicified therein are allocated.
    524          */
    525 XkbSrvLedInfoPtr
    526 XkbAllocSrvLedInfo(DeviceIntPtr dev,
    527                    KbdFeedbackPtr kf, LedFeedbackPtr lf, unsigned needed_parts)
    528 {
    529     XkbSrvLedInfoPtr sli;
    530     Bool checkAccel;
    531     Bool checkNames;
    532 
    533     sli = NULL;
    534     checkAccel = checkNames = FALSE;
    535     if ((kf != NULL) && (kf->xkb_sli == NULL)) {
    536         kf->xkb_sli = sli = calloc(1, sizeof(XkbSrvLedInfoRec));
    537         if (sli == NULL)
    538             return NULL;        /* ALLOCATION ERROR */
    539         if (dev->key && dev->key->xkbInfo)
    540             sli->flags = XkbSLI_HasOwnState;
    541         else
    542             sli->flags = 0;
    543         sli->class = KbdFeedbackClass;
    544         sli->id = kf->ctrl.id;
    545         sli->fb.kf = kf;
    546 
    547         sli->autoState = 0;
    548         sli->explicitState = kf->ctrl.leds;
    549         sli->effectiveState = kf->ctrl.leds;
    550 
    551         if ((kf == dev->kbdfeed) && (dev->key) && (dev->key->xkbInfo)) {
    552             XkbDescPtr xkb;
    553 
    554             xkb = dev->key->xkbInfo->desc;
    555             sli->flags |= XkbSLI_IsDefault;
    556             sli->physIndicators = xkb->indicators->phys_indicators;
    557             sli->names = xkb->names->indicators;
    558             sli->maps = xkb->indicators->maps;
    559             checkNames = checkAccel = TRUE;
    560         }
    561         else {
    562             sli->physIndicators = XkbAllIndicatorsMask;
    563             sli->names = NULL;
    564             sli->maps = NULL;
    565         }
    566     }
    567     else if ((kf != NULL) && ((kf->xkb_sli->flags & XkbSLI_IsDefault) != 0)) {
    568         XkbDescPtr xkb;
    569 
    570         xkb = dev->key->xkbInfo->desc;
    571         sli = kf->xkb_sli;
    572         sli->physIndicators = xkb->indicators->phys_indicators;
    573         if (xkb->names->indicators != sli->names) {
    574             checkNames = TRUE;
    575             sli->names = xkb->names->indicators;
    576         }
    577         if (xkb->indicators->maps != sli->maps) {
    578             checkAccel = TRUE;
    579             sli->maps = xkb->indicators->maps;
    580         }
    581     }
    582     else if ((lf != NULL) && (lf->xkb_sli == NULL)) {
    583         lf->xkb_sli = sli = calloc(1, sizeof(XkbSrvLedInfoRec));
    584         if (sli == NULL)
    585             return NULL;        /* ALLOCATION ERROR */
    586         if (dev->key && dev->key->xkbInfo)
    587             sli->flags = XkbSLI_HasOwnState;
    588         else
    589             sli->flags = 0;
    590         sli->class = LedFeedbackClass;
    591         sli->id = lf->ctrl.id;
    592         sli->fb.lf = lf;
    593 
    594         sli->physIndicators = lf->ctrl.led_mask;
    595         sli->autoState = 0;
    596         sli->explicitState = lf->ctrl.led_values;
    597         sli->effectiveState = lf->ctrl.led_values;
    598         sli->maps = NULL;
    599         sli->names = NULL;
    600     }
    601     else
    602         return NULL;
    603     if ((sli->names == NULL) && (needed_parts & XkbXI_IndicatorNamesMask))
    604         sli->names = calloc(XkbNumIndicators, sizeof(Atom));
    605     if ((sli->maps == NULL) && (needed_parts & XkbXI_IndicatorMapsMask))
    606         sli->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
    607     if (checkNames) {
    608         register unsigned i, bit;
    609 
    610         sli->namesPresent = 0;
    611         for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
    612             if (sli->names[i] != None)
    613                 sli->namesPresent |= bit;
    614         }
    615     }
    616     if (checkAccel)
    617         XkbCheckIndicatorMaps(dev, sli, XkbAllIndicatorsMask);
    618     return sli;
    619 }
    620 
    621 void
    622 XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli)
    623 {
    624     if ((sli->flags & XkbSLI_IsDefault) == 0) {
    625         free(sli->maps);
    626         free(sli->names);
    627     }
    628     sli->maps = NULL;
    629     sli->names = NULL;
    630     free(sli);
    631     return;
    632 }
    633 
    634 /*
    635  * XkbSrvLedInfoPtr
    636  * XkbCopySrvLedInfo(dev,src,kf,lf)
    637  *
    638  * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made,
    639  * thus the new copy behaves like the original one and can be freed with
    640  * XkbFreeSrvLedInfo.
    641  */
    642 XkbSrvLedInfoPtr
    643 XkbCopySrvLedInfo(DeviceIntPtr from,
    644                   XkbSrvLedInfoPtr src, KbdFeedbackPtr kf, LedFeedbackPtr lf)
    645 {
    646     XkbSrvLedInfoPtr sli_new = NULL;
    647 
    648     if (!src)
    649         goto finish;
    650 
    651     sli_new = calloc(1, sizeof(XkbSrvLedInfoRec));
    652     if (!sli_new)
    653         goto finish;
    654 
    655     memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec));
    656     if (sli_new->class == KbdFeedbackClass)
    657         sli_new->fb.kf = kf;
    658     else
    659         sli_new->fb.lf = lf;
    660 
    661     if (!(sli_new->flags & XkbSLI_IsDefault)) {
    662         sli_new->names = calloc(XkbNumIndicators, sizeof(Atom));
    663         sli_new->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
    664     }                           /* else sli_new->names/maps is pointing to
    665                                    dev->key->xkbInfo->desc->names->indicators;
    666                                    dev->key->xkbInfo->desc->names->indicators; */
    667 
    668  finish:
    669     return sli_new;
    670 }
    671 
    672 /***====================================================================***/
    673 
    674         /*
    675          * XkbSrvLedInfoPtr
    676          * XkbFindSrvLedInfo(dev,class,id,needed_parts)
    677          *
    678          * Finds the XkbSrvLedInfoPtr for the specified 'class' and 'id'
    679          * on the device specified by 'dev.'   If the class and id specify
    680          * a valid device feedback, this function returns the existing
    681          * feedback or allocates a new one.
    682          *
    683          */
    684 
    685 XkbSrvLedInfoPtr
    686 XkbFindSrvLedInfo(DeviceIntPtr dev,
    687                   unsigned class, unsigned id, unsigned needed_parts)
    688 {
    689     XkbSrvLedInfoPtr sli;
    690 
    691     /* optimization to check for most common case */
    692     if (((class == XkbDfltXIClass) && (id == XkbDfltXIId)) && (dev->kbdfeed)) {
    693         if (dev->kbdfeed->xkb_sli == NULL) {
    694             dev->kbdfeed->xkb_sli =
    695                 XkbAllocSrvLedInfo(dev, dev->kbdfeed, NULL, needed_parts);
    696         }
    697         return dev->kbdfeed->xkb_sli;
    698     }
    699 
    700     sli = NULL;
    701     if (class == XkbDfltXIClass) {
    702         if (dev->kbdfeed)
    703             class = KbdFeedbackClass;
    704         else if (dev->leds)
    705             class = LedFeedbackClass;
    706         else
    707             return NULL;
    708     }
    709     if (class == KbdFeedbackClass) {
    710         KbdFeedbackPtr kf;
    711 
    712         for (kf = dev->kbdfeed; kf != NULL; kf = kf->next) {
    713             if ((id == XkbDfltXIId) || (id == kf->ctrl.id)) {
    714                 if (kf->xkb_sli == NULL)
    715                     kf->xkb_sli =
    716                         XkbAllocSrvLedInfo(dev, kf, NULL, needed_parts);
    717                 sli = kf->xkb_sli;
    718                 break;
    719             }
    720         }
    721     }
    722     else if (class == LedFeedbackClass) {
    723         LedFeedbackPtr lf;
    724 
    725         for (lf = dev->leds; lf != NULL; lf = lf->next) {
    726             if ((id == XkbDfltXIId) || (id == lf->ctrl.id)) {
    727                 if (lf->xkb_sli == NULL)
    728                     lf->xkb_sli =
    729                         XkbAllocSrvLedInfo(dev, NULL, lf, needed_parts);
    730                 sli = lf->xkb_sli;
    731                 break;
    732             }
    733         }
    734     }
    735     if (sli) {
    736         if ((sli->names == NULL) && (needed_parts & XkbXI_IndicatorNamesMask))
    737             sli->names = calloc(XkbNumIndicators, sizeof(Atom));
    738         if ((sli->maps == NULL) && (needed_parts & XkbXI_IndicatorMapsMask))
    739             sli->maps = calloc(XkbNumIndicators, sizeof(XkbIndicatorMapRec));
    740     }
    741     return sli;
    742 }
    743 
    744 /***====================================================================***/
    745 
    746 void
    747 XkbFlushLedEvents(DeviceIntPtr dev,
    748                   DeviceIntPtr kbd,
    749                   XkbSrvLedInfoPtr sli,
    750                   xkbExtensionDeviceNotify * ed,
    751                   XkbChangesPtr changes, XkbEventCausePtr cause)
    752 {
    753     if (changes) {
    754         if (changes->indicators.state_changes)
    755             XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState);
    756         XkbSendNotification(kbd, changes, cause);
    757         memset((char *) changes, 0, sizeof(XkbChangesRec));
    758 
    759         if (XkbAX_NeedFeedback
    760             (kbd->key->xkbInfo->desc->ctrls, XkbAX_IndicatorFBMask)) {
    761             if (sli->effectiveState)
    762                 /* it appears that the which parameter is not used */
    763                 XkbDDXAccessXBeep(dev, _BEEP_LED_ON, XkbAccessXFeedbackMask);
    764             else
    765                 XkbDDXAccessXBeep(dev, _BEEP_LED_OFF, XkbAccessXFeedbackMask);
    766         }
    767     }
    768     if (ed) {
    769         if (ed->reason) {
    770             if ((dev != kbd) && (ed->reason & XkbXI_IndicatorStateMask))
    771                 XkbDDXUpdateDeviceIndicators(dev, sli, sli->effectiveState);
    772             XkbSendExtensionDeviceNotify(dev, cause->client, ed);
    773         }
    774         memset((char *) ed, 0, sizeof(XkbExtensionDeviceNotify));
    775     }
    776     return;
    777 }
    778 
    779 /***====================================================================***/
    780 
    781 void
    782 XkbApplyLedNameChanges(DeviceIntPtr dev,
    783                        XkbSrvLedInfoPtr sli,
    784                        unsigned changed_names,
    785                        xkbExtensionDeviceNotify * ed,
    786                        XkbChangesPtr changes, XkbEventCausePtr cause)
    787 {
    788     DeviceIntPtr kbd;
    789     XkbChangesRec my_changes;
    790     xkbExtensionDeviceNotify my_ed;
    791 
    792     if (changed_names == 0)
    793         return;
    794     if (dev->key && dev->key->xkbInfo)
    795         kbd = dev;
    796     else
    797         kbd = inputInfo.keyboard;
    798 
    799     if (ed == NULL) {
    800         ed = &my_ed;
    801         memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
    802     }
    803     else if ((ed->reason & XkbXI_IndicatorsMask) &&
    804              ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
    805         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    806     }
    807 
    808     if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) {
    809         if (changes == NULL) {
    810             changes = &my_changes;
    811             memset((char *) changes, 0, sizeof(XkbChangesRec));
    812         }
    813         changes->names.changed |= XkbIndicatorNamesMask;
    814         changes->names.changed_indicators |= changed_names;
    815     }
    816 
    817     ed->reason |= XkbXI_IndicatorNamesMask;
    818     ed->ledClass = sli->class;
    819     ed->ledID = sli->id;
    820     ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
    821     ed->ledState = sli->effectiveState;
    822     ed->unsupported = 0;
    823     ed->supported = XkbXI_AllFeaturesMask;
    824 
    825     if (changes != &my_changes)
    826         changes = NULL;
    827     if (ed != &my_ed)
    828         ed = NULL;
    829     if (changes || ed)
    830         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    831     return;
    832 }
    833 
    834 /***====================================================================***/
    835 
    836         /*
    837          * void
    838          * XkbApplyLedMapChanges(dev,sli,changed_maps,changes,cause)
    839          *
    840          * Handles all of the secondary effects of the changes to the
    841          * feedback specified by 'sli' on the device specified by 'dev.'
    842          *
    843          * If 'changed_maps' specifies any indicators, this function generates
    844          * XkbExtensionDeviceNotify events and possibly IndicatorMapNotify
    845          * events to report the changes, and recalculates the effective
    846          * state of each indicator with a changed map.  If any indicators
    847          * change state, the server generates XkbExtensionDeviceNotify and
    848          * XkbIndicatorStateNotify events as appropriate.
    849          *
    850          * If 'changes' is non-NULL, this function updates it to reflect
    851          * any changes to the keyboard state or controls or to the 'core'
    852          * indicator names, maps, or state.   If 'changes' is NULL, this
    853          * function generates XKB events as needed to report the changes.
    854          * If 'dev' is not a keyboard device, any changes are reported
    855          * for the core keyboard.
    856          *
    857          * The 'cause' specifies the reason for the event (key event or
    858          * request) for the change, as reported in some XKB events.
    859          */
    860 
    861 void
    862 XkbApplyLedMapChanges(DeviceIntPtr dev,
    863                       XkbSrvLedInfoPtr sli,
    864                       unsigned changed_maps,
    865                       xkbExtensionDeviceNotify * ed,
    866                       XkbChangesPtr changes, XkbEventCausePtr cause)
    867 {
    868     DeviceIntPtr kbd;
    869     XkbChangesRec my_changes;
    870     xkbExtensionDeviceNotify my_ed;
    871 
    872     if (changed_maps == 0)
    873         return;
    874     if (dev->key && dev->key->xkbInfo)
    875         kbd = dev;
    876     else
    877         kbd = inputInfo.keyboard;
    878 
    879     if (ed == NULL) {
    880         ed = &my_ed;
    881         memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
    882     }
    883     else if ((ed->reason & XkbXI_IndicatorsMask) &&
    884              ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
    885         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    886     }
    887 
    888     if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault)) {
    889         if (changes == NULL) {
    890             changes = &my_changes;
    891             memset((char *) changes, 0, sizeof(XkbChangesRec));
    892         }
    893         changes->indicators.map_changes |= changed_maps;
    894     }
    895 
    896     XkbCheckIndicatorMaps(dev, sli, changed_maps);
    897 
    898     ed->reason |= XkbXI_IndicatorMapsMask;
    899     ed->ledClass = sli->class;
    900     ed->ledID = sli->id;
    901     ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
    902     ed->ledState = sli->effectiveState;
    903     ed->unsupported = 0;
    904     ed->supported = XkbXI_AllFeaturesMask;
    905 
    906     XkbUpdateLedAutoState(dev, sli, changed_maps, ed, changes, cause);
    907 
    908     if (changes != &my_changes)
    909         changes = NULL;
    910     if (ed != &my_ed)
    911         ed = NULL;
    912     if (changes || ed)
    913         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    914     return;
    915 }
    916 
    917 /***====================================================================***/
    918 
    919 void
    920 XkbApplyLedStateChanges(DeviceIntPtr dev,
    921                         XkbSrvLedInfoPtr sli,
    922                         unsigned changed_leds,
    923                         xkbExtensionDeviceNotify * ed,
    924                         XkbChangesPtr changes, XkbEventCausePtr cause)
    925 {
    926     XkbSrvInfoPtr xkbi;
    927     DeviceIntPtr kbd;
    928     XkbChangesRec my_changes;
    929     xkbExtensionDeviceNotify my_ed;
    930     register unsigned i, bit, affected;
    931     XkbIndicatorMapPtr map;
    932     unsigned oldState;
    933     Bool kb_changed;
    934 
    935     if (changed_leds == 0)
    936         return;
    937     if (dev->key && dev->key->xkbInfo)
    938         kbd = dev;
    939     else
    940         kbd = inputInfo.keyboard;
    941     xkbi = kbd->key->xkbInfo;
    942 
    943     if (changes == NULL) {
    944         changes = &my_changes;
    945         memset((char *) changes, 0, sizeof(XkbChangesRec));
    946     }
    947 
    948     kb_changed = FALSE;
    949     affected = changed_leds;
    950     oldState = sli->effectiveState;
    951     for (i = 0, bit = 1; (i < XkbNumIndicators) && (affected); i++, bit <<= 1) {
    952         if ((affected & bit) == 0)
    953             continue;
    954         affected &= ~bit;
    955         map = &sli->maps[i];
    956         if (map->flags & XkbIM_NoExplicit) {
    957             sli->explicitState &= ~bit;
    958             continue;
    959         }
    960         if (map->flags & XkbIM_LEDDrivesKB) {
    961             Bool on = ((sli->explicitState & bit) != 0);
    962 
    963             if (XkbApplyLEDChangeToKeyboard(xkbi, map, on, changes))
    964                 kb_changed = TRUE;
    965         }
    966     }
    967     sli->effectiveState = (sli->autoState | sli->explicitState);
    968     affected = sli->effectiveState ^ oldState;
    969 
    970     if (ed == NULL) {
    971         ed = &my_ed;
    972         memset((char *) ed, 0, sizeof(xkbExtensionDeviceNotify));
    973     }
    974     else if (affected && (ed->reason & XkbXI_IndicatorsMask) &&
    975              ((ed->ledClass != sli->class) || (ed->ledID != sli->id))) {
    976         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
    977     }
    978 
    979     if ((kbd == dev) && (sli->flags & XkbSLI_IsDefault))
    980         changes->indicators.state_changes |= affected;
    981     if (affected) {
    982         ed->reason |= XkbXI_IndicatorStateMask;
    983         ed->ledClass = sli->class;
    984         ed->ledID = sli->id;
    985         ed->ledsDefined = sli->namesPresent | sli->mapsPresent;
    986         ed->ledState = sli->effectiveState;
    987         ed->unsupported = 0;
    988         ed->supported = XkbXI_AllFeaturesMask;
    989     }
    990 
    991     if (kb_changed) {
    992         XkbComputeDerivedState(kbd->key->xkbInfo);
    993         XkbUpdateLedAutoState(dev, sli, sli->mapsPresent, ed, changes, cause);
    994     }
    995 
    996     if (changes != &my_changes)
    997         changes = NULL;
    998     if (ed != &my_ed)
    999         ed = NULL;
   1000     if (changes || ed)
   1001         XkbFlushLedEvents(dev, kbd, sli, ed, changes, cause);
   1002     if (kb_changed)
   1003         XkbUpdateAllDeviceIndicators(NULL, cause);
   1004     return;
   1005 }