add cheeky support for dead keys

This commit is contained in:
John Gebbie 2023-08-15 16:57:53 +01:00
parent d1e4b66dd1
commit 3845810f7c
2 changed files with 154 additions and 10 deletions

View file

@ -364,18 +364,23 @@ func main() {
}
} else if s, ok := cutWord(text, "type"); ok {
for _, r := range s {
if sym := xkb.Utf32ToKeysym(uint32(r)); sym == 0 {
sym := xkb.Utf32ToKeysym(uint32(r))
if sym == 0 {
warn("invalid character: " + string(r))
} else if c := getChord(keymap, sym); c.Key != 0 {
c.KeyDown(keyboard)
time.Sleep(typehold)
c.KeyUp(keyboard)
} else if c1, c2 := getDeadChords(keymap, r); c1.Key != 0 {
c1.KeyDown(keyboard)
time.Sleep(typehold)
c1.KeyUp(keyboard)
time.Sleep(typedelay)
c2.KeyDown(keyboard)
time.Sleep(typehold)
c2.KeyUp(keyboard)
} else {
chord := getChord(keymap, sym)
if chord.Key == 0 {
warn("impossible character for layout: " + string(r))
time.Sleep(typehold)
} else {
chord.KeyDown(keyboard)
time.Sleep(typehold)
chord.KeyUp(keyboard)
}
}
time.Sleep(typedelay)
}

139
keys.go
View file

@ -3,6 +3,7 @@ package main
import (
"git.sr.ht/~geb/dotool/xkb"
"github.com/bendahl/uinput"
"unicode"
)
var LinuxKeys = map[string]Chord{
@ -481,6 +482,129 @@ var linuxXSyms = map[string]uint32{
var XKeys = map[string]Chord{}
type DeadKeyResult struct {
DeadKey, Key string
Result rune
}
// this relies on a conventional keymap
// this isn't exhaustive (e.g. acircumflexacute)
var DeadKeyResults = []DeadKeyResult{
{"dead_abovedot", "B", 'Ḃ'},
{"dead_abovedot", "C", 'Ċ'},
{"dead_abovedot", "D", 'Ḋ'},
{"dead_abovedot", "E", 'Ė'},
{"dead_abovedot", "F", 'Ḟ'},
{"dead_abovedot", "G", 'Ġ'},
{"dead_abovedot", "I", 'İ'},
{"dead_abovedot", "M", 'Ṁ'},
{"dead_abovedot", "P", 'Ṗ'},
{"dead_abovedot", "S", 'Ṡ'},
{"dead_abovedot", "T", 'Ṫ'},
{"dead_abovedot", "X", 'Ẋ'},
{"dead_abovedot", "Z", 'Ż'},
{"dead_acute", "A", 'Á'},
{"dead_acute", "C", 'Ć'},
{"dead_acute", "E", 'É'},
{"dead_acute", "I", 'Í'},
{"dead_acute", "L", 'Ĺ'},
{"dead_acute", "N", 'Ń'},
{"dead_acute", "O", 'Ó'},
{"dead_acute", "R", 'Ŕ'},
{"dead_acute", "S", 'Ś'},
{"dead_acute", "U", 'Ú'},
{"dead_acute", "W", 'Ẃ'},
{"dead_acute", "Y", 'Ý'},
{"dead_acute", "Z", 'Ź'},
{"dead_belowdot", "A", 'Ạ'},
{"dead_belowdot", "E", 'Ẹ'},
{"dead_belowdot", "I", 'Ị'},
{"dead_belowdot", "L", 'Ḷ'},
{"dead_belowdot", "O", 'Ọ'},
{"dead_belowdot", "U", 'Ụ'},
{"dead_belowdot", "Y", 'Ỵ'},
{"dead_breve", "A", 'Ă'},
{"dead_breve", "G", 'Ğ'},
{"dead_breve", "I", 'Ĭ'},
{"dead_breve", "U", 'Ŭ'},
{"dead_caron", "C", 'Č'},
{"dead_caron", "D", 'Ď'},
{"dead_caron", "E", 'Ě'},
{"dead_caron", "G", 'Ǧ'},
{"dead_caron", "L", 'Ľ'},
{"dead_caron", "N", 'Ň'},
{"dead_caron", "O", 'Ǒ'},
{"dead_caron", "R", 'Ř'},
{"dead_caron", "S", 'Š'},
{"dead_caron", "T", 'Ť'},
{"dead_caron", "Z", 'Ž'},
{"dead_cedilla", "C", 'Ç'},
{"dead_cedilla", "G", 'Ģ'},
{"dead_cedilla", "K", 'Ķ'},
{"dead_cedilla", "L", 'Ļ'},
{"dead_cedilla", "N", 'Ņ'},
{"dead_cedilla", "R", 'Ŗ'},
{"dead_cedilla", "S", 'Ş'},
{"dead_cedilla", "T", 'Ţ'},
{"dead_circumflex", "A", 'Â'},
{"dead_circumflex", "C", 'Ĉ'},
{"dead_circumflex", "E", 'Ê'},
{"dead_circumflex", "G", 'Ĝ'},
{"dead_circumflex", "H", 'Ĥ'},
{"dead_circumflex", "I", 'Î'},
{"dead_circumflex", "J", 'Ĵ'},
{"dead_circumflex", "O", 'Ô'},
{"dead_circumflex", "S", 'Ŝ'},
{"dead_circumflex", "U", 'Û'},
{"dead_circumflex", "W", 'Ŵ'},
{"dead_circumflex", "Y", 'Ŷ'},
{"dead_diaeresis", "A", 'Ä'},
{"dead_diaeresis", "E", 'Ë'},
{"dead_diaeresis", "I", 'Ï'},
{"dead_diaeresis", "O", 'Ö'},
{"dead_diaeresis", "U", 'Ü'},
{"dead_diaeresis", "W", 'Ẅ'},
{"dead_diaeresis", "Y", 'Ÿ'},
{"dead_doubleacute", "O", 'Ő'},
{"dead_doubleacute", "U", 'Ű'},
{"dead_grave", "A", 'À'},
{"dead_grave", "E", 'È'},
{"dead_grave", "I", 'Ì'},
{"dead_grave", "O", 'Ò'},
{"dead_grave", "U", 'Ù'},
{"dead_grave", "W", 'Ẁ'},
{"dead_grave", "Y", 'Ỳ'},
{"dead_hook", "A", 'Ả'},
{"dead_hook", "E", 'Ẻ'},
{"dead_hook", "I", 'Ỉ'},
{"dead_hook", "O", 'Ỏ'},
{"dead_hook", "U", 'Ủ'},
{"dead_hook", "Y", 'Ỷ'},
{"dead_horn", "O", 'Ơ'},
{"dead_horn", "T", 'Þ'},
{"dead_horn", "U", 'Ư'},
{"dead_macron", "A", 'Ā'},
{"dead_macron", "E", 'Ē'},
{"dead_macron", "I", 'Ī'},
{"dead_macron", "O", 'Ō'},
{"dead_macron", "U", 'Ū'},
{"dead_ogonek", "A", 'Ą'},
{"dead_ogonek", "E", 'Ę'},
{"dead_ogonek", "I", 'Į'},
{"dead_ogonek", "U", 'Ų'},
{"dead_stroke", "D", 'Đ'},
{"dead_stroke", "H", 'Ħ'},
{"dead_stroke", "L", 'Ł'},
{"dead_stroke", "Z", 'Ƶ'},
{"dead_tilde", "A", 'Ã'},
{"dead_tilde", "E", 'Ẽ'},
{"dead_tilde", "I", 'Ĩ'},
{"dead_tilde", "N", 'Ñ'},
{"dead_tilde", "O", 'Õ'},
{"dead_tilde", "U", 'Ũ'},
{"dead_tilde", "Y", 'Ỹ'},
}
func newChord(keymap *xkb.Keymap, mask, code uint32) Chord{
altGrMask := uint32(1) << keymap.ModGetIndex("Mod5")
ctrlMask := uint32(1) << keymap.ModGetIndex(xkb.ModNameCtrl)
@ -528,3 +652,18 @@ func getChord(keymap *xkb.Keymap, keysym uint32) Chord {
}
return Chord{}
}
func getDeadChords(keymap *xkb.Keymap, result rune) (Chord, Chord) {
r := unicode.ToUpper(result)
for _, d := range DeadKeyResults {
if d.Result == r {
deadKey := XKeys[d.DeadKey]
key := XKeys[d.Key]
if deadKey.Key != 0 && key.Key != 0 {
key.Shift = d.Result == result
return deadKey, key
}
}
}
return Chord{}, Chord{}
}