From 4c3024d51cad63e97b09468f425c1df840d34398 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Fri, 30 Nov 2018 21:32:10 +0000 Subject: [PATCH] Support alternative keyboard layouts --- config/keys.go | 54 ++++++---------------------- gui/input.go | 97 ++++++++++++++++++++++---------------------------- 2 files changed, 53 insertions(+), 98 deletions(-) diff --git a/config/keys.go b/config/keys.go index 52ea135..bbd4ce4 100644 --- a/config/keys.go +++ b/config/keys.go @@ -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) { diff --git a/gui/input.go b/gui/input.go index 39d68b8..3f886a8 100644 --- a/gui/input.go +++ b/gui/input.go @@ -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: