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