1 /************************************************************
2 Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
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.
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.
25 ********************************************************/
27 #include "xkbcomp-priv.h"
28 #include "parseutils.h"
30 #include "indicators.h"
33 typedef struct _SymInterpInfo
36 struct xkb_sym_interpret interp;
39 #define _SI_VirtualMod (1<<0)
40 #define _SI_Action (1<<1)
41 #define _SI_AutoRepeat (1<<2)
42 #define _SI_LockingKey (1<<3)
43 #define _SI_LevelOneOnly (1<<4)
45 typedef struct _GroupCompatInfo
50 unsigned char real_mods;
54 typedef struct _CompatInfo
60 SymInterpInfo *interps;
63 GroupCompatInfo groupCompat[XkbNumKbdGroups];
67 struct xkb_keymap * xkb;
70 /***====================================================================***/
72 #define ReportSINotArray(si,f,i) \
73 ReportNotArray("symbol interpretation",(f),siText((si),(i)))
74 #define ReportSIBadType(si,f,w,i) \
75 ReportBadType("symbol interpretation",(f),siText((si),(i)),(w))
77 /***====================================================================***/
80 siText(SymInterpInfo * si, CompatInfo * info)
84 if (si == &info->dflt)
86 snprintf(buf, sizeof(buf), "default");
90 snprintf(buf, sizeof(buf), "%s+%s(%s)",
91 XkbcKeysymText(si->interp.sym),
92 XkbcSIMatchText(si->interp.match),
93 XkbcModMaskText(si->interp.mods, false));
99 InitCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
106 info->errorCount = 0;
108 info->interps = NULL;
110 info->dflt.defs.fileID = info->fileID;
111 info->dflt.defs.defined = 0;
112 info->dflt.defs.merge = MergeOverride;
113 info->dflt.interp.flags = 0;
114 info->dflt.interp.virtual_mod = XkbNoModifier;
115 info->dflt.interp.act.type = XkbSA_NoAction;
116 for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
117 info->dflt.interp.act.any.data[i] = 0;
118 ClearIndicatorMapInfo(&info->ledDflt);
119 info->ledDflt.defs.fileID = info->fileID;
120 info->ledDflt.defs.defined = 0;
121 info->ledDflt.defs.merge = MergeOverride;
122 memset(&info->groupCompat[0], 0,
123 XkbNumKbdGroups * sizeof(GroupCompatInfo));
125 InitVModInfo(&info->vmods, xkb);
129 ClearCompatInfo(CompatInfo * info, struct xkb_keymap * xkb)
136 info->dflt.defs.defined = 0;
137 info->dflt.defs.merge = MergeAugment;
138 info->dflt.interp.flags = 0;
139 info->dflt.interp.virtual_mod = XkbNoModifier;
140 info->dflt.interp.act.type = XkbSA_NoAction;
141 for (i = 0; i < sizeof(info->dflt.interp.act.any.data); i++)
142 info->dflt.interp.act.any.data[i] = 0;
143 ClearIndicatorMapInfo(&info->ledDflt);
145 info->interps = (SymInterpInfo *) ClearCommonInfo(&info->interps->defs);
146 memset(&info->groupCompat[0], 0,
147 XkbNumKbdGroups * sizeof(GroupCompatInfo));
148 info->leds = (LEDInfo *) ClearCommonInfo(&info->leds->defs);
150 next = info->act->next;
154 ClearVModInfo(&info->vmods, xkb);
157 static SymInterpInfo *
158 NextInterp(CompatInfo * info)
162 si = uTypedAlloc(SymInterpInfo);
165 memset(si, 0, sizeof(SymInterpInfo));
167 (SymInterpInfo *) AddCommonInfo(&info->interps->defs,
174 static SymInterpInfo *
175 FindMatchingInterp(CompatInfo * info, SymInterpInfo * new)
179 for (old = info->interps; old != NULL;
180 old = (SymInterpInfo *) old->defs.next)
182 if ((old->interp.sym == new->interp.sym) &&
183 (old->interp.mods == new->interp.mods) &&
184 (old->interp.match == new->interp.match))
193 AddInterp(CompatInfo * info, SymInterpInfo * new)
199 old = FindMatchingInterp(info, new);
202 if (new->defs.merge == MergeReplace)
204 SymInterpInfo *next = (SymInterpInfo *) old->defs.next;
205 if (((old->defs.fileID == new->defs.fileID)
206 && (warningLevel > 0)) || (warningLevel > 9))
208 WARN("Multiple definitions for \"%s\"\n", siText(new, info));
209 ACTION("Earlier interpretation ignored\n");
212 old->defs.next = &next->defs;
215 if (UseNewField(_SI_VirtualMod, &old->defs, &new->defs, &collide))
217 old->interp.virtual_mod = new->interp.virtual_mod;
218 old->defs.defined |= _SI_VirtualMod;
220 if (UseNewField(_SI_Action, &old->defs, &new->defs, &collide))
222 old->interp.act = new->interp.act;
223 old->defs.defined |= _SI_Action;
225 if (UseNewField(_SI_AutoRepeat, &old->defs, &new->defs, &collide))
227 old->interp.flags &= ~XkbSI_AutoRepeat;
228 old->interp.flags |= (new->interp.flags & XkbSI_AutoRepeat);
229 old->defs.defined |= _SI_AutoRepeat;
231 if (UseNewField(_SI_LockingKey, &old->defs, &new->defs, &collide))
233 old->interp.flags &= ~XkbSI_LockingKey;
234 old->interp.flags |= (new->interp.flags & XkbSI_LockingKey);
235 old->defs.defined |= _SI_LockingKey;
237 if (UseNewField(_SI_LevelOneOnly, &old->defs, &new->defs, &collide))
239 old->interp.match &= ~XkbSI_LevelOneOnly;
240 old->interp.match |= (new->interp.match & XkbSI_LevelOneOnly);
241 old->defs.defined |= _SI_LevelOneOnly;
245 WARN("Multiple interpretations of \"%s\"\n", siText(new, info));
246 ACTION("Using %s definition for duplicate fields\n",
247 (new->defs.merge != MergeAugment ? "last" : "first"));
252 if ((new = NextInterp(info)) == NULL)
255 new->defs.next = NULL;
260 AddGroupCompat(CompatInfo * info, unsigned group, GroupCompatInfo * newGC)
265 merge = newGC->merge;
266 gc = &info->groupCompat[group];
267 if (((gc->real_mods == newGC->real_mods) && (gc->vmods == newGC->vmods)))
271 if (((gc->fileID == newGC->fileID) && (warningLevel > 0))
272 || (warningLevel > 9))
274 WARN("Compat map for group %d redefined\n", group + 1);
275 ACTION("Using %s definition\n",
276 (merge == MergeAugment ? "old" : "new"));
278 if (newGC->defined && (merge != MergeAugment || !gc->defined))
283 /***====================================================================***/
286 ResolveStateAndPredicate(ExprDef * expr,
288 unsigned *mods_rtrn, CompatInfo * info)
294 *pred_rtrn = XkbSI_AnyOfOrNone;
299 *pred_rtrn = XkbSI_Exactly;
300 if (expr->op == ExprActionDecl)
302 const char *pred_txt = XkbcAtomText(expr->value.action.name);
303 if (strcasecmp(pred_txt, "noneof") == 0)
304 *pred_rtrn = XkbSI_NoneOf;
305 else if (strcasecmp(pred_txt, "anyofornone") == 0)
306 *pred_rtrn = XkbSI_AnyOfOrNone;
307 else if (strcasecmp(pred_txt, "anyof") == 0)
308 *pred_rtrn = XkbSI_AnyOf;
309 else if (strcasecmp(pred_txt, "allof") == 0)
310 *pred_rtrn = XkbSI_AllOf;
311 else if (strcasecmp(pred_txt, "exactly") == 0)
312 *pred_rtrn = XkbSI_Exactly;
315 ERROR("Illegal modifier predicate \"%s\"\n", pred_txt);
319 expr = expr->value.action.args;
321 else if (expr->op == ExprIdent)
323 const char *pred_txt = XkbcAtomText(expr->value.str);
324 if ((pred_txt) && (strcasecmp(pred_txt, "any") == 0))
326 *pred_rtrn = XkbSI_AnyOf;
332 if (ExprResolveModMask(expr, &result))
334 *mods_rtrn = result.uval;
340 /***====================================================================***/
343 MergeIncludedCompatMaps(CompatInfo * into, CompatInfo * from, unsigned merge)
346 LEDInfo *led, *rtrn, *next;
347 GroupCompatInfo *gcm;
350 if (from->errorCount > 0)
352 into->errorCount += from->errorCount;
355 if (into->name == NULL)
357 into->name = from->name;
360 for (si = from->interps; si; si = (SymInterpInfo *) si->defs.next)
362 if (merge != MergeDefault)
363 si->defs.merge = merge;
364 if (!AddInterp(into, si))
367 for (i = 0, gcm = &from->groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++)
369 if (merge != MergeDefault)
371 if (!AddGroupCompat(into, i, gcm))
374 for (led = from->leds; led != NULL; led = next)
376 next = (LEDInfo *) led->defs.next;
377 if (merge != MergeDefault)
378 led->defs.merge = merge;
379 rtrn = AddIndicatorMap(into->leds, led);
387 typedef void (*FileHandler) (XkbFile *rtrn, struct xkb_keymap *xkb,
388 unsigned merge, CompatInfo *info);
391 HandleIncludeCompatMap(IncludeStmt * stmt,
392 struct xkb_keymap * xkb, CompatInfo * info, FileHandler hndlr)
400 if ((stmt->file == NULL) && (stmt->map == NULL))
404 memset(info, 0, sizeof(CompatInfo));
406 else if (ProcessIncludeFile(xkb->context, stmt, XkmCompatMapIndex, &rtrn,
409 InitCompatInfo(&included, xkb);
410 included.fileID = rtrn->id;
411 included.dflt = info->dflt;
412 included.dflt.defs.fileID = rtrn->id;
413 included.dflt.defs.merge = newMerge;
414 included.ledDflt.defs.fileID = rtrn->id;
415 included.ledDflt.defs.merge = newMerge;
416 included.act = info->act;
417 (*hndlr) (rtrn, xkb, MergeOverride, &included);
418 if (stmt->stmt != NULL)
421 included.name = stmt->stmt;
424 if (info->act != NULL)
430 info->errorCount += 10;
433 if ((stmt->next != NULL) && (included.errorCount < 1))
437 CompatInfo next_incl;
439 for (next = stmt->next; next != NULL; next = next->next)
441 if ((next->file == NULL) && (next->map == NULL))
444 MergeIncludedCompatMaps(&included, info, next->merge);
445 ClearCompatInfo(info, xkb);
447 else if (ProcessIncludeFile(xkb->context, next, XkmCompatMapIndex,
450 InitCompatInfo(&next_incl, xkb);
451 next_incl.fileID = rtrn->id;
452 next_incl.dflt = info->dflt;
453 next_incl.dflt.defs.fileID = rtrn->id;
454 next_incl.dflt.defs.merge = op;
455 next_incl.ledDflt.defs.fileID = rtrn->id;
456 next_incl.ledDflt.defs.merge = op;
457 next_incl.act = info->act;
458 (*hndlr) (rtrn, xkb, MergeOverride, &next_incl);
459 MergeIncludedCompatMaps(&included, &next_incl, op);
460 if (info->act != NULL)
461 next_incl.act = NULL;
462 ClearCompatInfo(&next_incl, xkb);
467 info->errorCount += 10;
476 MergeIncludedCompatMaps(info, &included, newMerge);
477 ClearCompatInfo(&included, xkb);
479 return (info->errorCount == 0);
482 static const LookupEntry useModMapValues[] = {
491 SetInterpField(SymInterpInfo * si,
492 struct xkb_keymap * xkb,
494 ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
499 if (strcasecmp(field, "action") == 0)
501 if (arrayNdx != NULL)
502 return ReportSINotArray(si, field, info);
503 ok = HandleActionDef(value, xkb, &si->interp.act.any, info->act);
505 si->defs.defined |= _SI_Action;
507 else if ((strcasecmp(field, "virtualmodifier") == 0) ||
508 (strcasecmp(field, "virtualmod") == 0))
510 if (arrayNdx != NULL)
511 return ReportSINotArray(si, field, info);
512 ok = ResolveVirtualModifier(value, xkb, &tmp, &info->vmods);
515 si->interp.virtual_mod = tmp.uval;
516 si->defs.defined |= _SI_VirtualMod;
519 return ReportSIBadType(si, field, "virtual modifier", info);
521 else if (strcasecmp(field, "repeat") == 0)
523 if (arrayNdx != NULL)
524 return ReportSINotArray(si, field, info);
525 ok = ExprResolveBoolean(value, &tmp);
529 si->interp.flags |= XkbSI_AutoRepeat;
531 si->interp.flags &= ~XkbSI_AutoRepeat;
532 si->defs.defined |= _SI_AutoRepeat;
535 return ReportSIBadType(si, field, "boolean", info);
537 else if (strcasecmp(field, "locking") == 0)
539 if (arrayNdx != NULL)
540 return ReportSINotArray(si, field, info);
541 ok = ExprResolveBoolean(value, &tmp);
545 si->interp.flags |= XkbSI_LockingKey;
547 si->interp.flags &= ~XkbSI_LockingKey;
548 si->defs.defined |= _SI_LockingKey;
551 return ReportSIBadType(si, field, "boolean", info);
553 else if ((strcasecmp(field, "usemodmap") == 0) ||
554 (strcasecmp(field, "usemodmapmods") == 0))
556 if (arrayNdx != NULL)
557 return ReportSINotArray(si, field, info);
558 ok = ExprResolveEnum(value, &tmp, useModMapValues);
562 si->interp.match |= XkbSI_LevelOneOnly;
564 si->interp.match &= ~XkbSI_LevelOneOnly;
565 si->defs.defined |= _SI_LevelOneOnly;
568 return ReportSIBadType(si, field, "level specification", info);
572 ok = ReportBadField("symbol interpretation", field, siText(si, info));
578 HandleInterpVar(VarDef * stmt, struct xkb_keymap * xkb, CompatInfo * info)
580 ExprResult elem, field;
584 if (ExprResolveLhs(stmt->name, &elem, &field, &ndx) == 0)
585 ret = 0; /* internal error, already reported */
586 else if (elem.str && (strcasecmp(elem.str, "interpret") == 0))
587 ret = SetInterpField(&info->dflt, xkb, field.str, ndx, stmt->value,
589 else if (elem.str && (strcasecmp(elem.str, "indicator") == 0))
590 ret = SetIndicatorMapField(&info->ledDflt, xkb, field.str, ndx,
593 ret = SetActionField(xkb, elem.str, field.str, ndx, stmt->value,
601 HandleInterpBody(VarDef * def, struct xkb_keymap * xkb, SymInterpInfo * si,
605 ExprResult tmp, field;
608 for (; def != NULL; def = (VarDef *) def->common.next)
610 if ((def->name) && (def->name->type == ExprFieldRef))
612 ok = HandleInterpVar(def, xkb, info);
615 ok = ExprResolveLhs(def->name, &tmp, &field, &arrayNdx);
617 ok = SetInterpField(si, xkb, field.str, arrayNdx, def->value,
626 HandleInterpDef(InterpDef * def, struct xkb_keymap * xkb, unsigned merge,
632 if (!ResolveStateAndPredicate(def->match, &pred, &mods, info))
634 ERROR("Couldn't determine matching modifiers\n");
635 ACTION("Symbol interpretation ignored\n");
638 if (def->merge != MergeDefault)
642 si.defs.merge = merge;
643 if (!LookupKeysym(def->sym, &si.interp.sym))
645 ERROR("Could not resolve keysym %s\n", def->sym);
646 ACTION("Symbol interpretation ignored\n");
649 si.interp.match = pred & XkbSI_OpMask;
650 si.interp.mods = mods;
651 if (!HandleInterpBody(def->def, xkb, &si, info))
657 if (!AddInterp(info, &si))
666 HandleGroupCompatDef(GroupCompatDef * def,
667 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
672 if (def->merge != MergeDefault)
674 if (!XkbIsLegalGroup(def->group - 1))
676 ERROR("Keyboard group must be in the range 1..%d\n",
677 XkbNumKbdGroups + 1);
678 ACTION("Compatibility map for illegal group %d ignored\n",
682 tmp.fileID = info->fileID;
684 if (!ExprResolveVModMask(def->def, &val, xkb))
686 ERROR("Expected a modifier mask in group compatibility definition\n");
687 ACTION("Ignoring illegal compatibility map for group %d\n",
691 tmp.real_mods = val.uval & 0xff;
692 tmp.vmods = (val.uval >> 8) & 0xffff;
694 return AddGroupCompat(info, def->group - 1, &tmp);
698 HandleCompatMapFile(XkbFile * file,
699 struct xkb_keymap * xkb, unsigned merge, CompatInfo * info)
703 if (merge == MergeDefault)
704 merge = MergeAugment;
706 info->name = uDupString(file->name);
710 switch (stmt->stmtType)
713 if (!HandleIncludeCompatMap((IncludeStmt *) stmt, xkb, info,
714 HandleCompatMapFile))
718 if (!HandleInterpDef((InterpDef *) stmt, xkb, merge, info))
721 case StmtGroupCompatDef:
722 if (!HandleGroupCompatDef
723 ((GroupCompatDef *) stmt, xkb, merge, info))
726 case StmtIndicatorMapDef:
729 rtrn = HandleIndicatorMapDef((IndicatorMapDef *) stmt, xkb,
730 &info->ledDflt, info->leds, merge);
738 if (!HandleInterpVar((VarDef *) stmt, xkb, info))
742 if (!HandleVModDef((VModDef *) stmt, xkb, merge, &info->vmods))
746 ERROR("Interpretation files may not include other types\n");
747 ACTION("Ignoring definition of key name\n");
751 WSGO("Unexpected statement type %d in HandleCompatMapFile\n",
756 if (info->errorCount > 10)
759 ERROR("Too many errors\n");
761 ACTION("Abandoning compatibility map \"%s\"\n", file->topName);
768 CopyInterps(CompatInfo * info,
769 struct xkb_compat_map * compat, bool needSymbol, unsigned pred)
773 for (si = info->interps; si; si = (SymInterpInfo *) si->defs.next)
775 if (((si->interp.match & XkbSI_OpMask) != pred) ||
776 (needSymbol && (si->interp.sym == XKB_KEYSYM_NO_SYMBOL)) ||
777 ((!needSymbol) && (si->interp.sym != XKB_KEYSYM_NO_SYMBOL)))
779 if (compat->num_si >= compat->size_si)
781 WSGO("No room to merge symbol interpretations\n");
782 ACTION("Symbol interpretations lost\n");
785 compat->sym_interpret[compat->num_si++] = si->interp;
790 CompileCompatMap(XkbFile *file, struct xkb_keymap *xkb, unsigned merge,
791 LEDInfoPtr *unboundLEDs)
795 GroupCompatInfo *gcm;
797 InitCompatInfo(&info, xkb);
798 info.dflt.defs.merge = merge;
799 info.ledDflt.defs.merge = merge;
801 HandleCompatMapFile(file, xkb, merge, &info);
803 if (info.errorCount != 0)
806 if (XkbcAllocCompatMap(xkb, info.nInterps) != Success) {
807 WSGO("Couldn't allocate compatibility map\n");
811 if (info.nInterps > 0) {
812 CopyInterps(&info, xkb->compat, true, XkbSI_Exactly);
813 CopyInterps(&info, xkb->compat, true, XkbSI_AllOf | XkbSI_NoneOf);
814 CopyInterps(&info, xkb->compat, true, XkbSI_AnyOf);
815 CopyInterps(&info, xkb->compat, true, XkbSI_AnyOfOrNone);
816 CopyInterps(&info, xkb->compat, false, XkbSI_Exactly);
817 CopyInterps(&info, xkb->compat, false, XkbSI_AllOf | XkbSI_NoneOf);
818 CopyInterps(&info, xkb->compat, false, XkbSI_AnyOf);
819 CopyInterps(&info, xkb->compat, false, XkbSI_AnyOfOrNone);
822 for (i = 0, gcm = &info.groupCompat[0]; i < XkbNumKbdGroups; i++, gcm++) {
823 if ((gcm->fileID != 0) || (gcm->real_mods != 0) || (gcm->vmods != 0)) {
824 xkb->compat->groups[i].mask = gcm->real_mods;
825 xkb->compat->groups[i].real_mods = gcm->real_mods;
826 xkb->compat->groups[i].vmods = gcm->vmods;
830 if (info.leds != NULL) {
831 if (!CopyIndicatorMapDefs(xkb, info.leds, unboundLEDs))
836 ClearCompatInfo(&info, xkb);
840 ClearCompatInfo(&info, xkb);
845 VModsToReal(struct xkb_keymap *xkb, uint32_t vmodmask)
853 for (i = 0; i < XkbNumVirtualMods; i++) {
854 if (!(vmodmask & (1 << i)))
856 ret |= xkb->server->vmods[i];
863 UpdateActionMods(struct xkb_keymap *xkb, union xkb_action *act, uint32_t rmodmask)
867 case XkbSA_LatchMods:
869 if (act->mods.flags & XkbSA_UseModMapMods)
870 act->mods.real_mods = rmodmask;
871 act->mods.mask = act->mods.real_mods;
872 act->mods.mask |= VModsToReal(xkb, act->mods.vmods);
875 if (act->iso.flags & XkbSA_UseModMapMods)
876 act->iso.real_mods = rmodmask;
877 act->iso.mask = act->iso.real_mods;
878 act->iso.mask |= VModsToReal(xkb, act->iso.vmods);
886 * Find an interpretation which applies to this particular level, either by
887 * finding an exact match for the symbol and modifier combination, or a
888 * generic XKB_KEYSYM_NO_SYMBOL match.
890 static struct xkb_sym_interpret *
891 FindInterpForKey(struct xkb_keymap *xkb, xkb_keycode_t key, uint32_t group, uint32_t level)
893 struct xkb_sym_interpret *ret = NULL;
894 const xkb_keysym_t *syms;
898 num_syms = xkb_key_get_syms_by_level(xkb, key, group, level, &syms);
902 for (i = 0; i < xkb->compat->num_si; i++) {
903 struct xkb_sym_interpret *interp = &xkb->compat->sym_interpret[i];
907 if ((num_syms > 1 || interp->sym != syms[0]) &&
908 interp->sym != XKB_KEYSYM_NO_SYMBOL)
911 if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
912 mods = xkb->map->modmap[key];
916 switch (interp->match & XkbSI_OpMask) {
918 found = !(interp->mods & mods);
920 case XkbSI_AnyOfOrNone:
921 found = (!mods || (interp->mods & mods));
924 found = !!(interp->mods & mods);
927 found = ((interp->mods & mods) == mods);
930 found = (interp->mods == mods);
937 if (found && interp->sym != XKB_KEYSYM_NO_SYMBOL)
939 else if (found && !ret)
949 ApplyInterpsToKey(struct xkb_keymap *xkb, xkb_keycode_t key)
951 #define INTERP_SIZE (8 * 4)
952 struct xkb_sym_interpret *interps[INTERP_SIZE];
953 union xkb_action *acts;
954 uint32_t vmodmask = 0;
957 int width = XkbKeyGroupsWidth(xkb, key);
960 /* If we've been told not to bind interps to this key, then don't. */
961 if (xkb->server->explicit[key] & XkbExplicitInterpretMask)
964 for (i = 0; i < INTERP_SIZE; i++)
967 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
968 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
969 i = (group * width) + level;
970 if (i >= INTERP_SIZE) /* XXX FIXME */
972 interps[i] = FindInterpForKey(xkb, key, group, level);
979 num_acts = XkbKeyNumGroups(xkb, key) * width;
980 acts = XkbcResizeKeyActions(xkb, key, num_acts);
986 for (group = 0; group < XkbKeyNumGroups(xkb, key); group++) {
987 for (level = 0; level < XkbKeyGroupWidth(xkb, key, group); level++) {
988 struct xkb_sym_interpret *interp;
990 i = (group * width) + level;
993 /* Infer default key behaviours from the base level. */
994 if (group == 0 && level == 0) {
995 if (!(xkb->server->explicit[key] & XkbExplicitAutoRepeatMask) &&
996 (!interp || interp->flags & XkbSI_AutoRepeat))
997 xkb->ctrls->per_key_repeat[key / 8] |= (1 << (key % 8));
998 if (!(xkb->server->explicit[key] & XkbExplicitBehaviorMask) &&
999 interp && (interp->flags & XkbSI_LockingKey))
1000 xkb->server->behaviors[key].type = XkbKB_Lock;
1006 if ((group == 0 && level == 0) ||
1007 !(interp->match & XkbSI_LevelOneOnly)) {
1008 if (interp->virtual_mod != XkbNoModifier)
1009 vmodmask |= (1 << interp->virtual_mod);
1011 acts[i] = interp->act;
1015 if (!(xkb->server->explicit[key] & XkbExplicitVModMapMask))
1016 xkb->server->vmodmap[key] = vmodmask;
1023 * This collects a bunch of disparate functions which was done in the server
1024 * at various points that really should've been done within xkbcomp. Turns out
1025 * your actions and types are a lot more useful when any of your modifiers
1026 * other than Shift actually do something ...
1029 UpdateModifiersFromCompat(struct xkb_keymap *xkb)
1034 /* Find all the interprets for the key and bind them to actions,
1035 * which will also update the vmodmap. */
1036 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++)
1037 if (!ApplyInterpsToKey(xkb, key))
1040 /* Update xkb->server->vmods, the virtual -> real mod mapping. */
1041 for (i = 0; i < XkbNumVirtualMods; i++)
1042 xkb->server->vmods[i] = 0;
1043 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1044 if (!xkb->server->vmodmap[key])
1046 for (i = 0; i < XkbNumVirtualMods; i++) {
1047 if (!(xkb->server->vmodmap[key] & (1 << i)))
1049 xkb->server->vmods[i] |= xkb->map->modmap[key];
1053 /* Now update the level masks for all the types to reflect the vmods. */
1054 for (i = 0; i < xkb->map->num_types; i++) {
1055 struct xkb_key_type *type = &xkb->map->types[i];
1058 type->mods.mask = type->mods.real_mods;
1059 type->mods.mask |= VModsToReal(xkb, type->mods.vmods);
1060 for (j = 0; j < XkbNumVirtualMods; j++) {
1061 if (!(type->mods.vmods & (1 << j)))
1063 mask |= xkb->server->vmods[j];
1065 for (j = 0; j < type->map_count; j++) {
1066 struct xkb_mods *mods = &type->map[j].mods;
1067 mods->mask = mods->real_mods | VModsToReal(xkb, mods->vmods);
1071 /* Update action modifiers. */
1072 for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
1073 union xkb_action *acts = XkbKeyActionsPtr(xkb, key);
1074 for (i = 0; i < XkbKeyNumActions(xkb, key); i++) {
1075 if (acts[i].any.type == XkbSA_NoAction)
1077 UpdateActionMods(xkb, &acts[i], xkb->map->modmap[key]);
1081 /* Update group modifiers. */
1082 for (i = 0; i < XkbNumKbdGroups; i++) {
1083 struct xkb_mods *group = &xkb->compat->groups[i];
1084 group->mask = group->real_mods | VModsToReal(xkb, group->vmods);
1087 /* Update vmod -> indicator maps. */
1088 for (i = 0; i < XkbNumIndicators; i++) {
1089 struct xkb_mods *led = &xkb->indicators->maps[i].mods;
1090 led->mask = led->real_mods | VModsToReal(xkb, led->vmods);