Home | History | Annotate | Line # | Download | only in xkb
      1 /************************************************************
      2 Copyright (c) 1993 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_CONFIG_H
     28 #include <config.h>
     29 #endif
     30 #include <stdio.h>
     31 #include "Xlibint.h"
     32 #include <X11/extensions/XKBproto.h>
     33 #include "XKBlibint.h"
     34 
     35 static int
     36 _XkbSizeKeyTypes(XkbDescPtr xkb, xkbSetMapReq *req)
     37 {
     38     XkbKeyTypePtr map;
     39     int i, len;
     40 
     41     if (((req->present & XkbKeyTypesMask) == 0) || (req->nTypes == 0)) {
     42         req->present &= ~XkbKeyTypesMask;
     43         req->firstType = req->nTypes = 0;
     44         return 0;
     45     }
     46     len = 0;
     47     map = &xkb->map->types[req->firstType];
     48     for (i = 0; i < req->nTypes; i++, map++) {
     49         len += SIZEOF(xkbKeyTypeWireDesc);
     50         len += map->map_count * SIZEOF(xkbKTSetMapEntryWireDesc);
     51         if (map->preserve)
     52             len += map->map_count * SIZEOF(xkbModsWireDesc);
     53     }
     54     return len;
     55 }
     56 
     57 static void
     58 _XkbWriteKeyTypes(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
     59 {
     60     char *buf;
     61     XkbKeyTypePtr type;
     62     int i, n;
     63     xkbKeyTypeWireDesc *desc;
     64 
     65     if ((req->present & XkbKeyTypesMask) == 0)
     66         return;
     67     type = &xkb->map->types[req->firstType];
     68     for (i = 0; i < req->nTypes; i++, type++) {
     69         int sz = SIZEOF(xkbKeyTypeWireDesc);
     70         sz += type->map_count * SIZEOF(xkbKTSetMapEntryWireDesc);
     71         if (type->preserve)
     72             sz += type->map_count * SIZEOF(xkbModsWireDesc);
     73         BufAlloc(xkbKeyTypeWireDesc *, desc, sz);
     74         desc->mask = type->mods.mask;
     75         desc->realMods = type->mods.real_mods;
     76         desc->virtualMods = type->mods.vmods;
     77         desc->numLevels = type->num_levels;
     78         desc->nMapEntries = type->map_count;
     79         desc->preserve = (type->preserve != NULL);
     80         buf = (char *) &desc[1];
     81         if (desc->nMapEntries > 0) {
     82             xkbKTSetMapEntryWireDesc *wire = (xkbKTSetMapEntryWireDesc *) buf;
     83 
     84             for (n = 0; n < type->map_count; n++, wire++) {
     85                 wire->level = type->map[n].level;
     86                 wire->realMods = type->map[n].mods.real_mods;
     87                 wire->virtualMods = type->map[n].mods.vmods;
     88             }
     89             buf = (char *) wire;
     90             if (type->preserve) {
     91                 xkbModsWireDesc *pwire = (xkbModsWireDesc *) buf;
     92 
     93                 for (n = 0; n < type->map_count; n++, pwire++) {
     94                     pwire->realMods = type->preserve[n].real_mods;
     95                     pwire->virtualMods = type->preserve[n].vmods;
     96                 }
     97             }
     98         }
     99     }
    100     return;
    101 }
    102 
    103 static int
    104 _XkbSizeKeySyms(XkbDescPtr xkb, xkbSetMapReq *req)
    105 {
    106     int i, len;
    107     unsigned nSyms;
    108 
    109     if (((req->present & XkbKeySymsMask) == 0) || (req->nKeySyms == 0)) {
    110         req->present &= ~XkbKeySymsMask;
    111         req->firstKeySym = req->nKeySyms = 0;
    112         req->totalSyms = 0;
    113         return 0;
    114     }
    115     len = (int) (req->nKeySyms * sizeof(XkbSymMapRec));
    116     for (i = nSyms = 0; i < req->nKeySyms; i++) {
    117         nSyms += XkbKeyNumSyms(xkb, i + req->firstKeySym);
    118     }
    119     len += nSyms * sizeof(CARD32);
    120     req->totalSyms = nSyms;
    121     return len;
    122 }
    123 
    124 static void
    125 _XkbWriteKeySyms(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    126 {
    127     register KeySym *pSym;
    128     CARD32 *outSym;
    129     XkbSymMapPtr symMap;
    130     xkbSymMapWireDesc *desc;
    131     register int i;
    132 
    133     if ((req->present & XkbKeySymsMask) == 0)
    134         return;
    135     symMap = &xkb->map->key_sym_map[req->firstKeySym];
    136     for (i = 0; i < req->nKeySyms; i++, symMap++) {
    137         BufAlloc(xkbSymMapWireDesc *, desc,
    138                  SIZEOF(xkbSymMapWireDesc) +
    139                  (XkbKeyNumSyms(xkb, i + req->firstKeySym) * sizeof(CARD32)));
    140         desc->ktIndex[0] = symMap->kt_index[0];
    141         desc->ktIndex[1] = symMap->kt_index[1];
    142         desc->ktIndex[2] = symMap->kt_index[2];
    143         desc->ktIndex[3] = symMap->kt_index[3];
    144         desc->groupInfo = symMap->group_info;
    145         desc->width = symMap->width;
    146         desc->nSyms = XkbKeyNumSyms(xkb, i + req->firstKeySym);
    147         outSym = (CARD32 *) &desc[1];
    148         if (desc->nSyms > 0) {
    149             pSym = XkbKeySymsPtr(xkb, i + req->firstKeySym);
    150             _XkbWriteCopyKeySyms(pSym, outSym, desc->nSyms);
    151         }
    152     }
    153     return;
    154 }
    155 
    156 static int
    157 _XkbSizeKeyActions(XkbDescPtr xkb, xkbSetMapReq *req)
    158 {
    159     int i, len, nActs;
    160 
    161     if (((req->present & XkbKeyActionsMask) == 0) || (req->nKeyActs == 0)) {
    162         req->present &= ~XkbKeyActionsMask;
    163         req->firstKeyAct = req->nKeyActs = 0;
    164         req->totalActs = 0;
    165         return 0;
    166     }
    167     for (nActs = i = 0; i < req->nKeyActs; i++) {
    168         if (xkb->server->key_acts[i + req->firstKeyAct] != 0)
    169             nActs += XkbKeyNumActions(xkb, i + req->firstKeyAct);
    170     }
    171     len = XkbPaddedSize(req->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc));
    172     req->totalActs = nActs;
    173     return len;
    174 }
    175 
    176 static void
    177 _XkbWriteKeyActions(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    178 {
    179     register int i;
    180     int n;
    181     CARD8 *numDesc;
    182     XkbAction *actDesc;
    183 
    184     if ((req->present & XkbKeyActionsMask) == 0)
    185         return;
    186     n = XkbPaddedSize(req->nKeyActs);
    187     n += (req->totalActs * SIZEOF(xkbActionWireDesc));
    188 
    189     BufAlloc(CARD8 *, numDesc, n);
    190     for (i = 0; i < req->nKeyActs; i++) {
    191         if (xkb->server->key_acts[i + req->firstKeyAct] == 0)
    192             numDesc[i] = 0;
    193         else
    194             numDesc[i] = XkbKeyNumActions(xkb, (i + req->firstKeyAct));
    195     }
    196     actDesc = (XkbAction *) &numDesc[XkbPaddedSize(req->nKeyActs)];
    197     for (i = 0; i < req->nKeyActs; i++) {
    198         if (xkb->server->key_acts[i + req->firstKeyAct] != 0) {
    199             n = XkbKeyNumActions(xkb, (i + req->firstKeyAct));
    200             memcpy(actDesc, XkbKeyActionsPtr(xkb, (i + req->firstKeyAct)),
    201                    n * SIZEOF(xkbActionWireDesc));
    202             actDesc += n;
    203         }
    204     }
    205     return;
    206 }
    207 
    208 static int
    209 _XkbSizeKeyBehaviors(XkbDescPtr xkb, xkbSetMapReq *req)
    210 {
    211     register int i, first, last, nFound;
    212 
    213     if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) {
    214         req->present &= ~XkbKeyBehaviorsMask;
    215         req->firstKeyBehavior = req->nKeyBehaviors = 0;
    216         req->totalKeyBehaviors = 0;
    217         return 0;
    218     }
    219     first = req->firstKeyBehavior;
    220     last = first + req->nKeyBehaviors - 1;
    221     for (i = first, nFound = 0; i <= last; i++) {
    222         if (xkb->server->behaviors[i].type != XkbKB_Default)
    223             nFound++;
    224     }
    225     req->totalKeyBehaviors = nFound;
    226     return (nFound * SIZEOF(xkbBehaviorWireDesc));
    227 }
    228 
    229 static void
    230 _XkbWriteKeyBehaviors(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    231 {
    232     register int i, first, last;
    233     xkbBehaviorWireDesc *wire;
    234     char *buf;
    235 
    236     if ((req->present & XkbKeyBehaviorsMask) == 0)
    237         return;
    238     first = req->firstKeyBehavior;
    239     last = first + req->nKeyBehaviors - 1;
    240 
    241     i = req->totalKeyBehaviors * SIZEOF(xkbBehaviorWireDesc);
    242     BufAlloc(char *, buf, i);
    243     wire = (xkbBehaviorWireDesc *) buf;
    244     for (i = first; i <= last; i++) {
    245         if (xkb->server->behaviors[i].type != XkbKB_Default) {
    246             wire->key = i;
    247             wire->type = xkb->server->behaviors[i].type;
    248             wire->data = xkb->server->behaviors[i].data;
    249             buf += SIZEOF(xkbBehaviorWireDesc);
    250             wire = (xkbBehaviorWireDesc *) buf;
    251         }
    252     }
    253     return;
    254 }
    255 
    256 static unsigned
    257 _XkbSizeVirtualMods(xkbSetMapReq *req)
    258 {
    259     register int i, bit, nMods;
    260 
    261     if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0)) {
    262         req->present &= ~XkbVirtualModsMask;
    263         req->virtualMods = 0;
    264         return 0;
    265     }
    266     for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
    267         if (req->virtualMods & bit)
    268             nMods++;
    269     }
    270     return XkbPaddedSize(nMods);
    271 }
    272 
    273 static void
    274 _XkbWriteVirtualMods(Display *dpy,
    275                      XkbDescPtr xkb,
    276                      xkbSetMapReq *req,
    277                      unsigned size)
    278 {
    279     register int i, bit;
    280     CARD8 *vmods;
    281 
    282     /* This was req->present&XkbVirtualModsMask==0, and '==' beats '&' */
    283     if (((req->present & XkbVirtualModsMask) == 0) || (size < 1))
    284         return;
    285     BufAlloc(CARD8 *, vmods, size);
    286     for (i = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
    287         if (req->virtualMods & bit)
    288             *vmods++ = xkb->server->vmods[i];
    289     }
    290     return;
    291 }
    292 
    293 static int
    294 _XkbSizeKeyExplicit(XkbDescPtr xkb, xkbSetMapReq *req)
    295 {
    296     register int i, first, last, nFound;
    297 
    298     if (((req->present & XkbExplicitComponentsMask) == 0) ||
    299         (req->nKeyExplicit == 0)) {
    300         req->present &= ~XkbExplicitComponentsMask;
    301         req->firstKeyExplicit = req->nKeyExplicit = 0;
    302         req->totalKeyExplicit = 0;
    303         return 0;
    304     }
    305     first = req->firstKeyExplicit;
    306     last = first + req->nKeyExplicit - 1;
    307 
    308     for (i = first, nFound = 0; i <= last; i++) {
    309         if (xkb->server->explicit[i] != 0)
    310             nFound++;
    311     }
    312     req->totalKeyExplicit = nFound;
    313     return XkbPaddedSize((nFound * 2));
    314 }
    315 
    316 static void
    317 _XkbWriteKeyExplicit(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    318 {
    319     register int i, first, last;
    320     CARD8 *wire;
    321 
    322     if ((req->present & XkbExplicitComponentsMask) == 0)
    323         return;
    324     first = req->firstKeyExplicit;
    325     last = first + req->nKeyExplicit - 1;
    326     i = XkbPaddedSize((req->totalKeyExplicit * 2));
    327     BufAlloc(CARD8 *, wire, i);
    328     for (i = first; i <= last; i++) {
    329         if (xkb->server->explicit[i] != 0) {
    330             wire[0] = i;
    331             wire[1] = xkb->server->explicit[i];
    332             wire += 2;
    333         }
    334     }
    335     return;
    336 }
    337 
    338 static int
    339 _XkbSizeModifierMap(XkbDescPtr xkb, xkbSetMapReq *req)
    340 {
    341     register int i, first, last, nFound;
    342 
    343     if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys == 0)) {
    344         req->present &= ~XkbModifierMapMask;
    345         req->firstModMapKey = req->nModMapKeys = 0;
    346         req->totalModMapKeys = 0;
    347         return 0;
    348     }
    349     first = req->firstModMapKey;
    350     last = first + req->nModMapKeys - 1;
    351 
    352     for (i = first, nFound = 0; i <= last; i++) {
    353         if (xkb->map->modmap[i] != 0)
    354             nFound++;
    355     }
    356     req->totalModMapKeys = nFound;
    357     return XkbPaddedSize((nFound * 2));
    358 }
    359 
    360 static void
    361 _XkbWriteModifierMap(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    362 {
    363     register int i, first, last;
    364     CARD8 *wire;
    365 
    366     if ((req->present & XkbModifierMapMask) == 0)
    367         return;
    368     first = req->firstModMapKey;
    369     last = first + req->nModMapKeys - 1;
    370     if (req->totalModMapKeys > 0) {
    371         i = XkbPaddedSize((req->totalModMapKeys * 2));
    372         BufAlloc(CARD8 *, wire, i);
    373 
    374         for (i = first; i <= last; i++) {
    375             if (xkb->map->modmap[i] != 0) {
    376                 wire[0] = i;
    377                 wire[1] = xkb->map->modmap[i];
    378                 wire += 2;
    379             }
    380         }
    381     }
    382     return;
    383 }
    384 
    385 static int
    386 _XkbSizeVirtualModMap(XkbDescPtr xkb, xkbSetMapReq *req)
    387 {
    388     register int i, first, last, nFound;
    389 
    390     if (((req->present & XkbVirtualModMapMask) == 0) ||
    391         (req->nVModMapKeys == 0)) {
    392         req->present &= ~XkbVirtualModMapMask;
    393         req->firstVModMapKey = req->nVModMapKeys = 0;
    394         req->totalVModMapKeys = 0;
    395         return 0;
    396     }
    397     first = req->firstVModMapKey;
    398     last = first + req->nVModMapKeys - 1;
    399 
    400     for (i = first, nFound = 0; i <= last; i++) {
    401         if (xkb->server->vmodmap[i] != 0)
    402             nFound++;
    403     }
    404     req->totalVModMapKeys = nFound;
    405     return nFound * SIZEOF(xkbVModMapWireDesc);
    406 }
    407 
    408 static void
    409 _XkbWriteVirtualModMap(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    410 {
    411     register int i, first, last;
    412     xkbVModMapWireDesc *wire;
    413 
    414     if ((req->present & XkbVirtualModMapMask) == 0)
    415         return;
    416     first = req->firstVModMapKey;
    417     last = first + req->nVModMapKeys - 1;
    418     if (req->totalVModMapKeys > 0) {
    419         i = req->totalVModMapKeys * SIZEOF(xkbVModMapWireDesc);
    420         BufAlloc(xkbVModMapWireDesc *, wire, i);
    421         for (i = first; i <= last; i++) {
    422             if (xkb->server->vmodmap[i] != 0) {
    423                 wire->key = i;
    424                 wire->vmods = xkb->server->vmodmap[i];
    425                 wire++;
    426             }
    427         }
    428     }
    429     return;
    430 }
    431 
    432 static void
    433 SendSetMap(Display *dpy, XkbDescPtr xkb, xkbSetMapReq *req)
    434 {
    435     xkbSetMapReq tmp;
    436     unsigned szMods;
    437 
    438     req->length += _XkbSizeKeyTypes(xkb, req) / 4;
    439     req->length += _XkbSizeKeySyms(xkb, req) / 4;
    440     req->length += _XkbSizeKeyActions(xkb, req) / 4;
    441     req->length += _XkbSizeKeyBehaviors(xkb, req) / 4;
    442     szMods = _XkbSizeVirtualMods(req);
    443     req->length += szMods / 4;
    444     req->length += _XkbSizeKeyExplicit(xkb, req) / 4;
    445     req->length += _XkbSizeModifierMap(xkb, req) / 4;
    446     req->length += _XkbSizeVirtualModMap(xkb, req) / 4;
    447 
    448     tmp = *req;
    449     if (tmp.nTypes > 0)
    450         _XkbWriteKeyTypes(dpy, xkb, &tmp);
    451     if (tmp.nKeySyms > 0)
    452         _XkbWriteKeySyms(dpy, xkb, &tmp);
    453     if (tmp.nKeyActs)
    454         _XkbWriteKeyActions(dpy, xkb, &tmp);
    455     if (tmp.totalKeyBehaviors > 0)
    456         _XkbWriteKeyBehaviors(dpy, xkb, &tmp);
    457     if (tmp.virtualMods)
    458         _XkbWriteVirtualMods(dpy, xkb, &tmp, szMods);
    459     if (tmp.totalKeyExplicit > 0)
    460         _XkbWriteKeyExplicit(dpy, xkb, &tmp);
    461     if (tmp.totalModMapKeys > 0)
    462         _XkbWriteModifierMap(dpy, xkb, &tmp);
    463     if (tmp.totalVModMapKeys > 0)
    464         _XkbWriteVirtualModMap(dpy, xkb, &tmp);
    465     return;
    466 }
    467 
    468 Bool
    469 XkbSetMap(Display *dpy, unsigned which, XkbDescPtr xkb)
    470 {
    471     register xkbSetMapReq *req;
    472     XkbInfoPtr xkbi;
    473     XkbServerMapPtr srv;
    474     XkbClientMapPtr map;
    475 
    476     if ((dpy->flags & XlibDisplayNoXkb) ||
    477         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) || (!xkb))
    478         return False;
    479     map = xkb->map;
    480     srv = xkb->server;
    481 
    482     if (((which & XkbKeyTypesMask) && ((!map) || (!map->types))) ||
    483         ((which & XkbKeySymsMask) &&
    484          ((!map) || (!map->syms) || (!map->key_sym_map))) ||
    485         ((which & XkbKeyActionsMask) && ((!srv) || (!srv->key_acts))) ||
    486         ((which & XkbKeyBehaviorsMask) && ((!srv) || (!srv->behaviors))) ||
    487         ((which & XkbVirtualModsMask) && (!srv)) ||
    488         ((which & XkbExplicitComponentsMask) && ((!srv) || (!srv->explicit))) ||
    489         ((which & XkbModifierMapMask) && ((!map) || (!map->modmap))) ||
    490         ((which & XkbVirtualModMapMask) && ((!srv) || (!srv->vmodmap))))
    491         return False;
    492 
    493     LockDisplay(dpy);
    494     xkbi = dpy->xkb_info;
    495     GetReq(kbSetMap, req);
    496     req->reqType = xkbi->codes->major_opcode;
    497     req->xkbReqType = X_kbSetMap;
    498     req->deviceSpec = xkb->device_spec;
    499     req->present = which;
    500     req->flags = XkbSetMapAllFlags;
    501     req->minKeyCode = xkb->min_key_code;
    502     req->maxKeyCode = xkb->max_key_code;
    503     req->firstType = 0;
    504     if (which & XkbKeyTypesMask)
    505         req->nTypes = map->num_types;
    506     else
    507         req->nTypes = 0;
    508     if (which & XkbKeySymsMask) {
    509         req->firstKeySym = xkb->min_key_code;
    510         req->nKeySyms = XkbNumKeys(xkb);
    511     }
    512     if (which & XkbKeyActionsMask) {
    513         req->firstKeyAct = xkb->min_key_code;
    514         req->nKeyActs = XkbNumKeys(xkb);
    515     }
    516     if (which & XkbKeyBehaviorsMask) {
    517         req->firstKeyBehavior = xkb->min_key_code;
    518         req->nKeyBehaviors = XkbNumKeys(xkb);
    519     }
    520     if (which & XkbVirtualModsMask)
    521         req->virtualMods = ~0;
    522     if (which & XkbExplicitComponentsMask) {
    523         req->firstKeyExplicit = xkb->min_key_code;
    524         req->nKeyExplicit = XkbNumKeys(xkb);
    525     }
    526     if (which & XkbModifierMapMask) {
    527         req->firstModMapKey = xkb->min_key_code;
    528         req->nModMapKeys = XkbNumKeys(xkb);
    529     }
    530     if (which & XkbVirtualModMapMask) {
    531         req->firstVModMapKey = xkb->min_key_code;
    532         req->nVModMapKeys = XkbNumKeys(xkb);
    533     }
    534     SendSetMap(dpy, xkb, req);
    535     UnlockDisplay(dpy);
    536     SyncHandle();
    537     return True;
    538 }
    539 
    540 Bool
    541 XkbChangeMap(Display *dpy, XkbDescPtr xkb, XkbMapChangesPtr changes)
    542 {
    543     register xkbSetMapReq *req;
    544     XkbInfoPtr xkbi;
    545     XkbServerMapPtr srv;
    546     XkbClientMapPtr map;
    547 
    548     if ((dpy->flags & XlibDisplayNoXkb) ||
    549         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) ||
    550         (!xkb) || (!changes))
    551         return False;
    552     srv = xkb->server;
    553     map = xkb->map;
    554 
    555     if (((changes->changed & XkbKeyTypesMask) && ((!map) || (!map->types))) ||
    556         ((changes->changed & XkbKeySymsMask) && ((!map) || (!map->syms) ||
    557                                                  (!map->key_sym_map))) ||
    558         ((changes->changed & XkbKeyActionsMask) && ((!srv) || (!srv->key_acts)))
    559         || ((changes->changed & XkbKeyBehaviorsMask) &&
    560             ((!srv) || (!srv->behaviors))) ||
    561         ((changes->changed & XkbVirtualModsMask) && (!srv)) ||
    562         ((changes->changed & XkbExplicitComponentsMask) &&
    563          ((!srv) || (!srv->explicit))) ||
    564         ((changes->changed & XkbModifierMapMask) && ((!map) || (!map->modmap)))
    565         || ((changes->changed & XkbVirtualModMapMask) &&
    566             ((!srv) || (!srv->vmodmap))))
    567         return False;
    568 
    569     LockDisplay(dpy);
    570     xkbi = dpy->xkb_info;
    571     GetReq(kbSetMap, req);
    572     req->reqType = xkbi->codes->major_opcode;
    573     req->xkbReqType = X_kbSetMap;
    574     req->deviceSpec = xkb->device_spec;
    575     req->present = changes->changed;
    576     req->flags = XkbSetMapRecomputeActions;
    577     req->minKeyCode = xkb->min_key_code;
    578     req->maxKeyCode = xkb->max_key_code;
    579     req->firstType = changes->first_type;
    580     req->nTypes = changes->num_types;
    581     req->firstKeySym = changes->first_key_sym;
    582     req->nKeySyms = changes->num_key_syms;
    583     req->firstKeyAct = changes->first_key_act;
    584     req->nKeyActs = changes->num_key_acts;
    585     req->firstKeyBehavior = changes->first_key_behavior;
    586     req->nKeyBehaviors = changes->num_key_behaviors;
    587     req->virtualMods = changes->vmods;
    588     req->firstKeyExplicit = changes->first_key_explicit;
    589     req->nKeyExplicit = changes->num_key_explicit;
    590     req->firstModMapKey = changes->first_modmap_key;
    591     req->nModMapKeys = changes->num_modmap_keys;
    592     req->firstVModMapKey = changes->first_vmodmap_key;
    593     req->nVModMapKeys = changes->num_vmodmap_keys;
    594     SendSetMap(dpy, xkb, req);
    595     UnlockDisplay(dpy);
    596     SyncHandle();
    597     return True;
    598 }
    599