vmod: bring back support for direct vmod -> real mod mapping This brings back the functionality that was removed in b9c87eb710ba4a86455601ca8c5a516b25e20366. Though it is not used in xkeyboard-config, from our current perspective it can be quite useful to be able to set the mappings directly, thus sidestepping the ugly and legacy-ridden modifier_map statement. Here's an example of how to get rid of modifier_map statements (though that would break core-X11 applications, since they must have the mappings through keysyms): virtual_modifiers NumLock = Mod2; virtual_modifiers Alt = Mod1; // Would be nice to map these to Alt, but that would be // incompatible with xkbcomp and somewhat complicated virtual_modifiers LAlt = Mod1; virtual_modifiers RAlt = Mod1; virtual_modifiers LevelThree = Mod5; virtual_modifiers RControl = Control; virtual_modifiers LControl = Control; virtual_modifiers Super = Mod4; virtual_modifiers Meta = Mod1; virtual_modifiers Hyper = Mod4; virtual_modifiers AltGr = Mod5; virtual_modifiers LShift = Shift; virtual_modifiers RShift = Shift; Signed-off-by: Ran Benita <ran234@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
diff --git a/src/xkbcomp/compat.c b/src/xkbcomp/compat.c
index bd44f36..475895c 100644
--- a/src/xkbcomp/compat.c
+++ b/src/xkbcomp/compat.c
@@ -768,7 +768,7 @@ HandleCompatMapFile(CompatInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
- ok = HandleVModDef(info->keymap, (VModDef *) stmt);
+ ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
break;
default:
log_err(info->keymap->ctx,
diff --git a/src/xkbcomp/symbols.c b/src/xkbcomp/symbols.c
index 87f56db..eda8b8e 100644
--- a/src/xkbcomp/symbols.c
+++ b/src/xkbcomp/symbols.c
@@ -1203,7 +1203,7 @@ HandleSymbolsFile(SymbolsInfo *info, XkbFile *file, enum merge_mode merge)
ok = HandleGlobalVar(info, (VarDef *) stmt);
break;
case STMT_VMOD:
- ok = HandleVModDef(info->keymap, (VModDef *) stmt);
+ ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
break;
case STMT_MODMAP:
ok = HandleModMapDef(info, (ModMapDef *) stmt);
diff --git a/src/xkbcomp/types.c b/src/xkbcomp/types.c
index b61ad55..7708da3 100644
--- a/src/xkbcomp/types.c
+++ b/src/xkbcomp/types.c
@@ -639,7 +639,7 @@ HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file, enum merge_mode merge)
ok = true;
break;
case STMT_VMOD:
- ok = HandleVModDef(info->keymap, (VModDef *) stmt);
+ ok = HandleVModDef(info->keymap, (VModDef *) stmt, merge);
break;
default:
log_err(info->keymap->ctx,
diff --git a/src/xkbcomp/vmod.c b/src/xkbcomp/vmod.c
index 206e162..86e7bec 100644
--- a/src/xkbcomp/vmod.c
+++ b/src/xkbcomp/vmod.c
@@ -30,27 +30,64 @@
#include "vmod.h"
bool
-HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt)
+HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
+ enum merge_mode merge)
{
xkb_mod_index_t i;
- const struct xkb_mod *mod;
+ struct xkb_mod *mod;
+ xkb_mod_mask_t mapping;
struct xkb_mod new;
- if (stmt->value)
- log_err(keymap->ctx,
- "Support for setting a value in a virtual_modifiers statement has been removed; "
- "Value ignored\n");
+ merge = (merge == MERGE_DEFAULT ? stmt->merge : merge);
+
+ if (stmt->value) {
+ /*
+ * This is a statement such as 'virtualModifiers NumLock = Mod1';
+ * it sets the vmod-to-real-mod[s] mapping directly instead of going
+ * through modifier_map or some such.
+ */
+ if (!ExprResolveModMask(keymap, stmt->value, MOD_REAL, &mapping)) {
+ log_err(keymap->ctx,
+ "Declaration of %s ignored\n",
+ xkb_atom_text(keymap->ctx, stmt->name));
+ return false;
+ }
+ }
+ else {
+ mapping = 0;
+ }
darray_enumerate(i, mod, keymap->mods) {
if (mod->name == stmt->name) {
- if (mod->type == MOD_VIRT)
+ if (mod->type != MOD_VIRT) {
+ log_err(keymap->ctx,
+ "Can't add a virtual modifier named \"%s\"; "
+ "there is already a non-virtual modifier with this name! Ignored\n",
+ xkb_atom_text(keymap->ctx, mod->name));
+ return false;
+ }
+
+ if (mod->mapping == mapping)
return true;
- log_err(keymap->ctx,
- "Can't add a virtual modifier named \"%s\"; "
- "there is already a non-virtual modifier with this name! Ignored\n",
- xkb_atom_text(keymap->ctx, mod->name));
- return false;
+ if (mod->mapping != 0) {
+ xkb_mod_mask_t use, ignore;
+
+ use = (merge == MERGE_OVERRIDE ? mapping : mod->mapping);
+ ignore = (merge == MERGE_OVERRIDE ? mod->mapping : mapping);
+
+ log_warn(keymap->ctx,
+ "Virtual modifier %s defined multiple times; "
+ "Using %s, ignoring %s\n",
+ xkb_atom_text(keymap->ctx, stmt->name),
+ ModMaskText(keymap, use),
+ ModMaskText(keymap, ignore));
+
+ mapping = use;
+ }
+
+ mod->mapping = mapping;
+ return true;
}
}
@@ -62,7 +99,7 @@ HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt)
}
new.name = stmt->name;
- new.mapping = 0;
+ new.mapping = mapping;
new.type = MOD_VIRT;
darray_append(keymap->mods, new);
return true;
diff --git a/src/xkbcomp/vmod.h b/src/xkbcomp/vmod.h
index 9915507..1ba59f7 100644
--- a/src/xkbcomp/vmod.h
+++ b/src/xkbcomp/vmod.h
@@ -28,6 +28,7 @@
#define XKBCOMP_VMOD_H
bool
-HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt);
+HandleVModDef(struct xkb_keymap *keymap, VModDef *stmt,
+ enum merge_mode merge);
#endif