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
_XkbSizeKeyTypes(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteKeyTypes(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbSizeKeySyms(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteKeySyms(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbSizeKeyActions(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteKeyActions(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteKeyBehaviors(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbSizeVirtualMods(xkbSetMapReq * req)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
_XkbWriteVirtualMods(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req,unsigned size)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
_XkbSizeKeyExplicit(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteKeyExplicit(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbSizeModifierMap(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteModifierMap(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbSizeVirtualModMap(XkbDescPtr xkb,xkbSetMapReq * req)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
_XkbWriteVirtualModMap(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
SendSetMap(Display * dpy,XkbDescPtr xkb,xkbSetMapReq * req)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
XkbSetMap(Display * dpy,unsigned which,XkbDescPtr xkb)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
XkbChangeMap(Display * dpy,XkbDescPtr xkb,XkbMapChangesPtr changes)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