Allow Ctrl modmaps in layouts

The 'ctrl' modmap is different from the other modmaps as it also applies
the built-in Ctrl modifier to the resulting character, even if it was
first modified by the custom modmap.

For example, this will map Ctrl+в to Ctrl+V (not to v):

    <ctrl a="в" b="v"/>

This is intended to add keyboard shortcuts in non-latin layouts.

A caveat is that the latin character appears on the keyboard while Ctrl
is activated.
This commit is contained in:
Jules Aguillon 2024-07-25 23:40:58 +02:00
parent 35f35b27be
commit 29b4b665dc
2 changed files with 22 additions and 4 deletions

View File

@ -51,7 +51,7 @@ public final class KeyModifier
{ {
switch (mod) switch (mod)
{ {
case CTRL: case CTRL: return apply_ctrl(k);
case ALT: case ALT:
case META: return turn_into_keyevent(k); case META: return turn_into_keyevent(k);
case FN: return apply_fn(k); case FN: return apply_fn(k);
@ -440,6 +440,19 @@ public final class KeyModifier
} }
} }
private static KeyValue apply_ctrl(KeyValue k)
{
if (_modmap != null)
{
KeyValue mapped = _modmap.ctrl.get(k);
// Do not return the modified character right away, first turn it into a
// key event.
if (mapped != null)
k = mapped;
}
return turn_into_keyevent(k);
}
private static KeyValue turn_into_keyevent(KeyValue k) private static KeyValue turn_into_keyevent(KeyValue k)
{ {
if (k.getKind() != KeyValue.Kind.Char) if (k.getKind() != KeyValue.Kind.Char)

View File

@ -563,18 +563,20 @@ public final class KeyboardData
{ {
public final Map<KeyValue, KeyValue> shift; public final Map<KeyValue, KeyValue> shift;
public final Map<KeyValue, KeyValue> fn; public final Map<KeyValue, KeyValue> fn;
public final Map<KeyValue, KeyValue> ctrl;
public Modmap(Map<KeyValue, KeyValue> s, Map<KeyValue, KeyValue> f) public Modmap(Map<KeyValue, KeyValue> s, Map<KeyValue, KeyValue> f, Map<KeyValue, KeyValue> c)
{ {
shift = s; shift = s;
fn = f; fn = f;
ctrl = c;
} }
public static Modmap parse(XmlPullParser parser) throws Exception public static Modmap parse(XmlPullParser parser) throws Exception
{ {
HashMap<KeyValue, KeyValue> shift = new HashMap<KeyValue, KeyValue>(); HashMap<KeyValue, KeyValue> shift = new HashMap<KeyValue, KeyValue>();
HashMap<KeyValue, KeyValue> fn = new HashMap<KeyValue, KeyValue>(); HashMap<KeyValue, KeyValue> fn = new HashMap<KeyValue, KeyValue>();
HashMap<KeyValue, KeyValue> ctrl = new HashMap<KeyValue, KeyValue>();
while (next_tag(parser)) while (next_tag(parser))
{ {
switch (parser.getName()) switch (parser.getName())
@ -585,12 +587,15 @@ public final class KeyboardData
case "fn": case "fn":
parse_mapping(parser, fn); parse_mapping(parser, fn);
break; break;
case "ctrl":
parse_mapping(parser, ctrl);
break;
default: default:
throw error(parser, "Expecting tag <shift> or <fn>, got <" + parser.getName() + ">"); throw error(parser, "Expecting tag <shift> or <fn>, got <" + parser.getName() + ">");
} }
} }
return new Modmap(shift, fn); return new Modmap(shift, fn, ctrl);
} }
private static void parse_mapping(XmlPullParser parser, Map<KeyValue, KeyValue> dst) throws Exception private static void parse_mapping(XmlPullParser parser, Map<KeyValue, KeyValue> dst) throws Exception