-
-xkb_mod_mask_t
-VModsToReal(struct xkb_keymap *keymap, xkb_mod_mask_t vmodmask)
-{
- xkb_mod_mask_t ret = 0;
- xkb_mod_index_t i;
-
- if (!vmodmask)
- return 0;
-
- for (i = 0; i < XkbNumVirtualMods; i++) {
- if (!(vmodmask & (1 << i)))
- continue;
- ret |= keymap->vmods[i];
- }
-
- return ret;
-}
-
-static void
-UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
- xkb_mod_mask_t rmodmask)
-{
- switch (act->type) {
- case XkbSA_SetMods:
- case XkbSA_LatchMods:
- case XkbSA_LockMods:
- if (act->mods.flags & XkbSA_UseModMapMods)
- act->mods.real_mods = rmodmask;
- act->mods.mask = act->mods.real_mods;
- act->mods.mask |= VModsToReal(keymap, act->mods.vmods);
- break;
-
- case XkbSA_ISOLock:
- if (act->iso.flags & XkbSA_UseModMapMods)
- act->iso.real_mods = rmodmask;
- act->iso.mask = act->iso.real_mods;
- act->iso.mask |= VModsToReal(keymap, act->iso.vmods);
- break;
-
- default:
- break;
- }
-}
-
-/**
- * Find an interpretation which applies to this particular level, either by
- * finding an exact match for the symbol and modifier combination, or a
- * generic XKB_KEY_NoSymbol match.
- */
-static struct xkb_sym_interpret *
-FindInterpForKey(struct xkb_keymap *keymap, struct xkb_key *key,
- xkb_group_index_t group, xkb_level_index_t level)
-{
- struct xkb_sym_interpret *ret = NULL;
- struct xkb_sym_interpret *interp;
- const xkb_keysym_t *syms;
- int num_syms;
-
- num_syms = xkb_key_get_syms_by_level(keymap, key, group, level, &syms);
- if (num_syms == 0)
- return NULL;
-
- darray_foreach(interp, keymap->sym_interpret) {
- uint32_t mods;
- bool found;
-
- if ((num_syms > 1 || interp->sym != syms[0]) &&
- interp->sym != XKB_KEY_NoSymbol)
- continue;
-
- if (level == 0 || !(interp->match & XkbSI_LevelOneOnly))
- mods = key->modmap;
- else
- mods = 0;
-
- switch (interp->match & XkbSI_OpMask) {
- case XkbSI_NoneOf:
- found = !(interp->mods & mods);
- break;
- case XkbSI_AnyOfOrNone:
- found = (!mods || (interp->mods & mods));
- break;
- case XkbSI_AnyOf:
- found = !!(interp->mods & mods);
- break;
- case XkbSI_AllOf:
- found = ((interp->mods & mods) == interp->mods);
- break;
- case XkbSI_Exactly:
- found = (interp->mods == mods);
- break;
- default:
- found = false;
- break;
- }
-
- if (found && interp->sym != XKB_KEY_NoSymbol)
- return interp;
- else if (found && !ret)
- ret = interp;
- }
-
- return ret;
-}
-
-/**
- */
-static bool
-ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
-{
-#define INTERP_SIZE (8 * 4)
- struct xkb_sym_interpret *interps[INTERP_SIZE];
- union xkb_action *acts;
- xkb_mod_mask_t vmodmask = 0;
- int num_acts = 0;
- xkb_group_index_t group;
- xkb_level_index_t level;
- unsigned int i;
-
- /* If we've been told not to bind interps to this key, then don't. */
- if (key->explicit & XkbExplicitInterpretMask)
- return true;
-
- for (i = 0; i < INTERP_SIZE; i++)
- interps[i] = NULL;
-
- for (group = 0; group < key->num_groups; group++) {
- for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
- level++) {
- i = (group * key->width) + level;
- if (i >= INTERP_SIZE) /* XXX FIXME */
- return false;
- interps[i] = FindInterpForKey(keymap, key, group, level);
- if (interps[i])
- num_acts++;
- }
- }
-
- if (num_acts)
- num_acts = key->num_groups * key->width;
- acts = ResizeKeyActions(keymap, key, num_acts);
- if (num_acts && !acts)
- return false;
-
- for (group = 0; group < key->num_groups; group++) {
- for (level = 0; level < XkbKeyGroupWidth(keymap, key, group);
- level++) {
- struct xkb_sym_interpret *interp;
-
- i = (group * key->width) + level;
- interp = interps[i];
-
- /* Infer default key behaviours from the base level. */
- if (group == 0 && level == 0) {
- if (!(key->explicit & XkbExplicitAutoRepeatMask) &&
- (!interp || (interp->flags & XkbSI_AutoRepeat)))
- key->repeats = true;
- }
-
- if (!interp)
- continue;
-
- if ((group == 0 && level == 0) ||
- !(interp->match & XkbSI_LevelOneOnly)) {
- if (interp->virtual_mod != XkbNoModifier)
- vmodmask |= (1 << interp->virtual_mod);
- }
- acts[i] = interp->act;
- }
- }
-
- if (!(key->explicit & XkbExplicitVModMapMask))
- key->vmodmap = vmodmask;
-
- return true;
-#undef INTERP_SIZE
-}
-
-/**
- * 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 ...
- */
-bool
-UpdateModifiersFromCompat(struct xkb_keymap *keymap)
-{
- xkb_mod_index_t vmod;
- xkb_group_index_t grp;
- xkb_led_index_t led;
- unsigned int i;
- struct xkb_key *key;
- struct xkb_key_type *type;
- struct xkb_kt_map_entry *entry;
-
- /* Find all the interprets for the key and bind them to actions,
- * which will also update the vmodmap. */
- xkb_foreach_key(key, keymap)
- if (!ApplyInterpsToKey(keymap, key))
- return false;
-
- /* Update keymap->vmods, the virtual -> real mod mapping. */
- for (vmod = 0; vmod < XkbNumVirtualMods; vmod++)
- keymap->vmods[vmod] = 0;
-
- xkb_foreach_key(key, keymap) {
- if (!key->vmodmap)
- continue;
-
- for (vmod = 0; vmod < XkbNumVirtualMods; vmod++) {
- if (!(key->vmodmap & (1 << vmod)))
- continue;
- keymap->vmods[vmod] |= key->modmap;
- }
- }
-
- /* Now update the level masks for all the types to reflect the vmods. */
- for (i = 0; i < keymap->num_types; i++) {
- xkb_mod_mask_t mask = 0;
- type = &keymap->types[i];
- type->mods.mask = type->mods.real_mods;
- type->mods.mask |= VModsToReal(keymap, type->mods.vmods);
-
- /* FIXME: We compute the mask with doing anything with it? */
- for (vmod = 0; vmod < XkbNumVirtualMods; vmod++) {
- if (!(type->mods.vmods & (1 << vmod)))
- continue;
- mask |= keymap->vmods[vmod];
- }
-
- darray_foreach(entry, type->map)
- entry->mods.mask = entry->mods.real_mods |
- VModsToReal(keymap, entry->mods.vmods);
- }
-
- /* Update action modifiers. */
- xkb_foreach_key(key, keymap) {
- union xkb_action *acts = XkbKeyActionsPtr(keymap, key);
- for (i = 0; i < XkbKeyNumActions(key); i++) {
- if (acts[i].any.type == XkbSA_NoAction)
- continue;
- UpdateActionMods(keymap, &acts[i], key->modmap);
- }
- }
-
- /* Update group modifiers. */
- for (grp = 0; grp < XkbNumKbdGroups; grp++) {
- struct xkb_mods *group = &keymap->groups[grp];
- group->mask = group->real_mods | VModsToReal(keymap, group->vmods);
- }
-
- /* Update vmod -> indicator maps. */
- for (led = 0; led < XkbNumIndicators; led++) {
- struct xkb_mods *mods = &keymap->indicators[led].mods;
- mods->mask = mods->real_mods | VModsToReal(keymap, mods->vmods);
- }
-
- return true;
-}