aminal/gui/input.go

306 lines
5.8 KiB
Go

package gui
import (
"fmt"
"strings"
"github.com/go-gl/glfw/v3.3/glfw"
)
// send typed runes straight through to the pty
func (gui *GUI) char(w *glfw.Window, r rune) {
gui.terminal.Write([]byte(string(r)))
}
func modsPressed(pressed glfw.ModifierKey, mods ...glfw.ModifierKey) bool {
for _, mod := range mods {
if pressed&mod == 0 {
return false
}
pressed ^= mod
}
return pressed == 0
}
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) {
if action == glfw.Repeat || action == glfw.Press {
if gui.overlay != nil {
if key == glfw.KeyEscape {
gui.setOverlay(nil)
}
}
// get key name to handle alternative keyboard layouts
name := glfw.GetKeyName(key, scancode)
if len(name) == 1 {
r := rune(strings.ToLower(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
}
}
// pass through alt codes
if modsPressed(mods, glfw.ModAlt) {
if r >= 97 && r < 123 || r >= 65 && r < 91 {
gui.terminal.Write([]byte{0x1b, byte(r)})
return
}
}
}
modStr := getModStr(mods)
switch key {
case glfw.KeyF1:
gui.terminal.Write([]byte{
0x1b,
'O',
'P',
})
case glfw.KeyF2:
gui.terminal.Write([]byte{
0x1b,
'O',
'Q',
})
case glfw.KeyF3:
gui.terminal.Write([]byte{
0x1b,
'O',
'R',
})
case glfw.KeyF4:
gui.terminal.Write([]byte{
0x1b,
'O',
'S',
})
case glfw.KeyF5:
gui.terminal.Write([]byte{
0x1b,
'[',
'1', '5', '~',
})
case glfw.KeyF6:
gui.terminal.Write([]byte{
0x1b,
'[',
'1', '7', '~',
})
case glfw.KeyF7:
gui.terminal.Write([]byte{
0x1b,
'[',
'1', '8', '~',
})
case glfw.KeyF8:
gui.terminal.Write([]byte{
0x1b,
'[',
'1', '9', '~',
})
case glfw.KeyF9:
gui.terminal.Write([]byte{
0x1b,
'[',
'2', '0', '~',
})
case glfw.KeyF10:
gui.terminal.Write([]byte{
0x1b,
'[',
'2', '1', '~',
})
case glfw.KeyF11:
gui.terminal.Write([]byte{
0x1b,
'[',
'2', '3', '~',
})
case glfw.KeyF12:
gui.terminal.Write([]byte{
0x1b,
'[',
'2', '4', '~',
})
case glfw.KeyInsert:
gui.terminal.Write([]byte{
0x1b,
'[',
'2', '~',
})
case glfw.KeyDelete:
gui.terminal.Write([]byte{
0x1b,
'[',
'3', '~',
})
case glfw.KeyHome:
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
if modStr == "" {
gui.terminal.Write([]byte("\x1b[1~"))
} else {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[1;%s~", modStr)))
}
} else {
gui.terminal.Write([]byte("\x1b[H"))
}
case glfw.KeyEnd:
if modStr == "" {
gui.terminal.Write([]byte("\x1b[4~"))
} else {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[4;%s~", modStr)))
}
case glfw.KeyPageUp:
if modStr == "" {
gui.terminal.Write([]byte("\x1b[5~"))
} else {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[5;%s~", modStr)))
}
case glfw.KeyPageDown:
if modStr == "" {
gui.terminal.Write([]byte("\x1b[6~"))
} else {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[6;%s~", modStr)))
}
case glfw.KeyEscape:
gui.terminal.Write([]byte{
0x1b,
})
case glfw.KeyTab:
gui.terminal.Write([]byte{
0x09,
})
case glfw.KeyEnter:
gui.terminal.WriteReturn()
case glfw.KeyKPEnter:
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
gui.terminal.Write([]byte{
0x1b,
'O',
'M',
})
} else {
gui.terminal.WriteReturn()
}
case glfw.KeyBackspace:
if modsPressed(mods, glfw.ModAlt) {
gui.terminal.Write([]byte{0x17}) // ctrl-w/delete word
} else {
gui.terminal.Write([]byte{0x7f}) // 0x7f is DEL
}
case glfw.KeyUp:
if modStr != "" {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[1;%sA", modStr)))
}
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
gui.terminal.Write([]byte{
0x1b,
'O',
'A',
})
} else {
gui.terminal.Write([]byte{
0x1b,
'[',
'A',
})
}
case glfw.KeyDown:
if modStr != "" {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[1;%sB", modStr)))
}
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
gui.terminal.Write([]byte{
0x1b,
'O',
'B',
})
} else {
gui.terminal.Write([]byte{
0x1b,
'[',
'B',
})
}
case glfw.KeyLeft:
if modStr != "" {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[1;%sD", modStr)))
}
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
gui.terminal.Write([]byte{
0x1b,
'O',
'D',
})
} else {
gui.terminal.Write([]byte{
0x1b,
'[',
'D',
})
}
case glfw.KeyRight:
if modStr != "" {
gui.terminal.Write([]byte(fmt.Sprintf("\x1b[1;%sC", modStr)))
}
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
gui.terminal.Write([]byte{
0x1b,
'O',
'C',
})
} else {
gui.terminal.Write([]byte{
0x1b,
'[',
'C',
})
}
}
}
}