Support alternative keyboard layouts

This commit is contained in:
Liam Galvin 2018-11-30 21:32:10 +00:00
parent f0939347a3
commit 4c3024d51c
2 changed files with 53 additions and 98 deletions

View File

@ -9,7 +9,7 @@ import (
type KeyCombination struct {
mods glfw.ModifierKey
key glfw.Key
char rune
}
type KeyMod string
@ -28,41 +28,11 @@ var modMap = map[KeyMod]glfw.ModifierKey{
super: glfw.ModSuper,
}
var keyMap = map[string]glfw.Key{
"a": glfw.KeyA,
"b": glfw.KeyB,
"c": glfw.KeyC,
"d": glfw.KeyD,
"e": glfw.KeyE,
"f": glfw.KeyF,
"g": glfw.KeyG,
"h": glfw.KeyH,
"i": glfw.KeyI,
"j": glfw.KeyJ,
"k": glfw.KeyK,
"l": glfw.KeyL,
"m": glfw.KeyM,
"n": glfw.KeyN,
"o": glfw.KeyO,
"p": glfw.KeyP,
"q": glfw.KeyQ,
"r": glfw.KeyR,
"s": glfw.KeyS,
"t": glfw.KeyT,
"u": glfw.KeyU,
"v": glfw.KeyV,
"w": glfw.KeyW,
"x": glfw.KeyX,
"y": glfw.KeyY,
"z": glfw.KeyZ,
";": glfw.KeySemicolon,
}
// keyStr e.g. "ctrl + alt + a"
func parseKeyCombination(keyStr string) (*KeyCombination, error) {
var mods glfw.ModifierKey
var key *glfw.Key
var key rune
keys := strings.Split(keyStr, "+")
for _, k := range keys {
@ -72,19 +42,15 @@ func parseKeyCombination(keyStr string) (*KeyCombination, error) {
mods = mods + mod
continue
}
mappedKey, ok := keyMap[k]
if ok {
if key != nil {
return nil, fmt.Errorf("Multiple non-modifier keys specified in keyboard shortcut")
}
key = &mappedKey
continue
if key > 0 {
return nil, fmt.Errorf("Multiple non-modifier keys specified in keyboard shortcut")
}
return nil, fmt.Errorf("Unknown key '%s' in configured keyboard shortcut", k)
key = rune(k[0])
}
if key == nil {
if key == 0 {
return nil, fmt.Errorf("No non-modifier key specified in keyboard shortcut")
}
@ -94,12 +60,12 @@ func parseKeyCombination(keyStr string) (*KeyCombination, error) {
return &KeyCombination{
mods: mods,
key: *key,
char: key,
}, nil
}
func (combi KeyCombination) Match(pressedMods glfw.ModifierKey, pressedKey glfw.Key) bool {
return pressedKey == combi.key && pressedMods == combi.mods
func (combi KeyCombination) Match(pressedMods glfw.ModifierKey, pressedChar rune) bool {
return pressedChar == combi.char && pressedMods == combi.mods
}
func (keyMapConfig KeyMappingConfig) GenerateActionMap() (map[UserAction]*KeyCombination, error) {

View File

@ -21,33 +21,26 @@ func modsPressed(pressed glfw.ModifierKey, mods ...glfw.ModifierKey) bool {
return pressed == 0
}
var ctrlBytes = map[glfw.Key]byte{
glfw.KeyA: 0x1,
glfw.KeyB: 0x2,
glfw.KeyC: 0x3,
glfw.KeyD: 0x4,
glfw.KeyE: 0x5,
glfw.KeyF: 0x6,
glfw.KeyG: 0x7,
glfw.KeyH: 0x08,
glfw.KeyI: 0x9,
glfw.KeyJ: 0x0a,
glfw.KeyK: 0x0b,
glfw.KeyL: 0x0c,
glfw.KeyM: 0x0d,
glfw.KeyN: 0x0e,
glfw.KeyO: 0x0f,
glfw.KeyP: 0x10,
glfw.KeyQ: 0x11,
glfw.KeyR: 0x12,
glfw.KeyS: 0x13,
glfw.KeyT: 0x14,
glfw.KeyU: 0x15,
glfw.KeyV: 0x16,
glfw.KeyW: 0x17,
glfw.KeyX: 0x18,
glfw.KeyY: 0x19,
glfw.KeyZ: 0x1a,
func getModStr(mods glfw.ModifierKey) string {
switch true {
case modsPressed(mods, glfw.ModControl, glfw.ModShift, glfw.ModAlt):
return "8"
case modsPressed(mods, glfw.ModControl, glfw.ModAlt):
return "7"
case modsPressed(mods, glfw.ModControl, glfw.ModShift):
return "6"
case modsPressed(mods, glfw.ModControl):
return "5"
case modsPressed(mods, glfw.ModAlt, glfw.ModShift):
return "4"
case modsPressed(mods, glfw.ModAlt):
return "3"
case modsPressed(mods, glfw.ModShift):
return "2"
}
return ""
}
func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
@ -60,37 +53,33 @@ func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Acti
}
}
for userAction, shortcut := range gui.keyboardShortcuts {
if shortcut.Match(mods, key) {
f, ok := actionMap[userAction]
if ok {
f(gui)
break
// get key name to handle alternative keyboard layouts
name := glfw.GetKeyName(key, scancode)
if len(name) == 1 {
r := rune(name[0])
for userAction, shortcut := range gui.keyboardShortcuts {
if shortcut.Match(mods, r) {
f, ok := actionMap[userAction]
if ok {
f(gui)
break
}
}
}
// standard ctrl codes e.g. ^C
if modsPressed(mods, glfw.ModControl) {
if r >= 97 && r < 123 {
gui.terminal.Write([]byte{byte(r) - 96})
return
} else if r >= 65 && r < 91 {
gui.terminal.Write([]byte{byte(r) - 64})
return
}
}
}
modStr := ""
switch true {
case modsPressed(mods, glfw.ModControl, glfw.ModShift, glfw.ModAlt):
modStr = "8"
case modsPressed(mods, glfw.ModControl, glfw.ModAlt):
modStr = "7"
case modsPressed(mods, glfw.ModControl, glfw.ModShift):
modStr = "6"
case modsPressed(mods, glfw.ModControl):
modStr = "5"
if b, ok := ctrlBytes[key]; ok {
gui.terminal.Write([]byte{b})
return
}
case modsPressed(mods, glfw.ModAlt, glfw.ModShift):
modStr = "4"
case modsPressed(mods, glfw.ModAlt):
modStr = "3"
case modsPressed(mods, glfw.ModShift):
modStr = "2"
}
modStr := getModStr(mods)
switch key {
case glfw.KeyF1: