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 { type KeyCombination struct {
mods glfw.ModifierKey mods glfw.ModifierKey
key glfw.Key char rune
} }
type KeyMod string type KeyMod string
@ -28,41 +28,11 @@ var modMap = map[KeyMod]glfw.ModifierKey{
super: glfw.ModSuper, 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" // keyStr e.g. "ctrl + alt + a"
func parseKeyCombination(keyStr string) (*KeyCombination, error) { func parseKeyCombination(keyStr string) (*KeyCombination, error) {
var mods glfw.ModifierKey var mods glfw.ModifierKey
var key *glfw.Key var key rune
keys := strings.Split(keyStr, "+") keys := strings.Split(keyStr, "+")
for _, k := range keys { for _, k := range keys {
@ -72,19 +42,15 @@ func parseKeyCombination(keyStr string) (*KeyCombination, error) {
mods = mods + mod mods = mods + mod
continue continue
} }
mappedKey, ok := keyMap[k]
if ok { if key > 0 {
if key != nil {
return nil, fmt.Errorf("Multiple non-modifier keys specified in keyboard shortcut") return nil, fmt.Errorf("Multiple non-modifier keys specified in keyboard shortcut")
} }
key = &mappedKey
continue key = rune(k[0])
} }
return nil, fmt.Errorf("Unknown key '%s' in configured keyboard shortcut", k) if key == 0 {
}
if key == nil {
return nil, fmt.Errorf("No non-modifier key specified in keyboard shortcut") return nil, fmt.Errorf("No non-modifier key specified in keyboard shortcut")
} }
@ -94,12 +60,12 @@ func parseKeyCombination(keyStr string) (*KeyCombination, error) {
return &KeyCombination{ return &KeyCombination{
mods: mods, mods: mods,
key: *key, char: key,
}, nil }, nil
} }
func (combi KeyCombination) Match(pressedMods glfw.ModifierKey, pressedKey glfw.Key) bool { func (combi KeyCombination) Match(pressedMods glfw.ModifierKey, pressedChar rune) bool {
return pressedKey == combi.key && pressedMods == combi.mods return pressedChar == combi.char && pressedMods == combi.mods
} }
func (keyMapConfig KeyMappingConfig) GenerateActionMap() (map[UserAction]*KeyCombination, error) { 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 return pressed == 0
} }
var ctrlBytes = map[glfw.Key]byte{ func getModStr(mods glfw.ModifierKey) string {
glfw.KeyA: 0x1,
glfw.KeyB: 0x2, switch true {
glfw.KeyC: 0x3, case modsPressed(mods, glfw.ModControl, glfw.ModShift, glfw.ModAlt):
glfw.KeyD: 0x4, return "8"
glfw.KeyE: 0x5, case modsPressed(mods, glfw.ModControl, glfw.ModAlt):
glfw.KeyF: 0x6, return "7"
glfw.KeyG: 0x7, case modsPressed(mods, glfw.ModControl, glfw.ModShift):
glfw.KeyH: 0x08, return "6"
glfw.KeyI: 0x9, case modsPressed(mods, glfw.ModControl):
glfw.KeyJ: 0x0a, return "5"
glfw.KeyK: 0x0b, case modsPressed(mods, glfw.ModAlt, glfw.ModShift):
glfw.KeyL: 0x0c, return "4"
glfw.KeyM: 0x0d, case modsPressed(mods, glfw.ModAlt):
glfw.KeyN: 0x0e, return "3"
glfw.KeyO: 0x0f, case modsPressed(mods, glfw.ModShift):
glfw.KeyP: 0x10, return "2"
glfw.KeyQ: 0x11, }
glfw.KeyR: 0x12,
glfw.KeyS: 0x13, return ""
glfw.KeyT: 0x14,
glfw.KeyU: 0x15,
glfw.KeyV: 0x16,
glfw.KeyW: 0x17,
glfw.KeyX: 0x18,
glfw.KeyY: 0x19,
glfw.KeyZ: 0x1a,
} }
func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) { func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
@ -60,8 +53,12 @@ func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Acti
} }
} }
// 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 { for userAction, shortcut := range gui.keyboardShortcuts {
if shortcut.Match(mods, key) { if shortcut.Match(mods, r) {
f, ok := actionMap[userAction] f, ok := actionMap[userAction]
if ok { if ok {
f(gui) f(gui)
@ -70,27 +67,19 @@ func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Acti
} }
} }
modStr := "" // standard ctrl codes e.g. ^C
switch true { if modsPressed(mods, glfw.ModControl) {
case modsPressed(mods, glfw.ModControl, glfw.ModShift, glfw.ModAlt): if r >= 97 && r < 123 {
modStr = "8" gui.terminal.Write([]byte{byte(r) - 96})
case modsPressed(mods, glfw.ModControl, glfw.ModAlt): return
modStr = "7" } else if r >= 65 && r < 91 {
case modsPressed(mods, glfw.ModControl, glfw.ModShift): gui.terminal.Write([]byte{byte(r) - 64})
modStr = "6"
case modsPressed(mods, glfw.ModControl):
modStr = "5"
if b, ok := ctrlBytes[key]; ok {
gui.terminal.Write([]byte{b})
return 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 { switch key {
case glfw.KeyF1: case glfw.KeyF1: