- else
- switch (file->type)
- {
- case XkmSemanticsFile:
- case XkmLayoutFile:
- case XkmKeymapFile:
- WSGO("Illegal %s configuration in a %s file\n",
- XkbcConfigText(file->type), XkbcConfigText(mainType));
- ACTION("Ignored\n");
- ok = False;
- break;
- case XkmKeyNamesIndex:
- sections[KEYCODES] = file;
- break;
- case XkmTypesIndex:
- sections[TYPES] = file;
- break;
- case XkmSymbolsIndex:
- sections[SYMBOLS] = file;
- break;
- case XkmCompatMapIndex:
- sections[COMPAT] = file;
- break;
- case XkmGeometryIndex:
- case XkmGeometryFile:
- sections[GEOMETRY] = file;
- break;
- case XkmVirtualModsIndex:
- case XkmIndicatorsIndex:
- WSGO("Found an isolated %s section\n",
- XkbcConfigText(file->type));
- break;
- default:
- WSGO("Unknown file type %d\n", file->type);
- break;
+ }
+
+ if (!(key->explicit & EXPLICIT_VMODMAP))
+ key->vmodmap = vmodmap;
+
+ return true;
+}
+
+/**
+ * This collects a bunch of disparate functions which was done in the server
+ * at various points that really should've been done within xkbcomp. Turns out
+ * your actions and types are a lot more useful when any of your modifiers
+ * other than Shift actually do something ...
+ */
+static bool
+UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
+{
+ struct xkb_key *key;
+ struct xkb_mod *mod;
+ struct xkb_led *led;
+ unsigned int i, j;
+
+ /* Find all the interprets for the key and bind them to actions,
+ * which will also update the vmodmap. */
+ xkb_keys_foreach(key, keymap)
+ if (!ApplyInterpsToKey(keymap, key))
+ return false;
+
+ /* Update keymap->mods, the virtual -> real mod mapping. */
+ xkb_keys_foreach(key, keymap)
+ xkb_mods_enumerate(i, mod, &keymap->mods)
+ if (key->vmodmap & (1u << i))
+ mod->mapping |= key->modmap;
+
+ /* Now update the level masks for all the types to reflect the vmods. */
+ for (i = 0; i < keymap->num_types; i++) {
+ ComputeEffectiveMask(keymap, &keymap->types[i].mods);
+
+ for (j = 0; j < keymap->types[i].num_entries; j++) {
+ ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].mods);
+ ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].preserve);
+ }
+ }
+
+ /* Update action modifiers. */
+ xkb_keys_foreach(key, keymap)
+ for (i = 0; i < key->num_groups; i++)
+ for (j = 0; j < XkbKeyNumLevels(key, i); j++)
+ UpdateActionMods(keymap, &key->groups[i].levels[j].action,
+ key->modmap);
+
+ /* Update vmod -> led maps. */
+ xkb_leds_foreach(led, keymap)
+ ComputeEffectiveMask(keymap, &led->mods);
+
+ /* Find maximum number of groups out of all keys in the keymap. */
+ xkb_keys_foreach(key, keymap)
+ keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
+
+ return true;
+}
+
+typedef bool (*compile_file_fn)(XkbFile *file,
+ struct xkb_keymap *keymap,
+ enum merge_mode merge);
+
+static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
+ [FILE_TYPE_KEYCODES] = CompileKeycodes,
+ [FILE_TYPE_TYPES] = CompileKeyTypes,
+ [FILE_TYPE_COMPAT] = CompileCompatMap,
+ [FILE_TYPE_SYMBOLS] = CompileSymbols,
+};
+
+bool
+CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
+{
+ bool ok;
+ XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
+ enum xkb_file_type type;
+ struct xkb_context *ctx = keymap->ctx;
+
+ /* Collect section files and check for duplicates. */
+ for (file = (XkbFile *) file->defs; file;
+ file = (XkbFile *) file->common.next) {
+ if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
+ file->file_type > LAST_KEYMAP_FILE_TYPE) {
+ if (file->file_type == FILE_TYPE_GEOMETRY) {
+ log_vrb(ctx, 1,
+ XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION,
+ "Geometry sections are not supported; ignoring\n");
+ } else {
+ log_err(ctx, XKB_LOG_MESSAGE_NO_ID,
+ "Cannot define %s in a keymap file\n",
+ xkb_file_type_to_string(file->file_type));