cleaned up some code
handle delays better add ability to have comments add defaults to keymaps
This commit is contained in:
parent
bf090a5b67
commit
0b2415ac40
101
ghid/keyboard.go
101
ghid/keyboard.go
@ -18,17 +18,22 @@ type syncer interface {
|
|||||||
Sync() error
|
Sync() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Key is a USB HID value
|
||||||
type Key struct {
|
type Key struct {
|
||||||
Modifier []string `json:"modifier"`
|
Modifier []string `json:"modifier"`
|
||||||
Decimal byte `json:"decimal"`
|
Decimal byte `json:"decimal"`
|
||||||
DelayDelimiter bool `json:"delayDelimiter,omitempty"`
|
PressDelayDelimiter bool `json:"pressDelayDelimiter,omitempty"`
|
||||||
|
ReleaseDelayDelimiter bool `json:"releaseDelayDelimiter,omitempty"`
|
||||||
|
Comment bool `json:"comment,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A Keymap is a json representation of the unicode rune mapped to its USB HID value
|
||||||
type Keymap map[string]Key
|
type Keymap map[string]Key
|
||||||
|
|
||||||
|
// Keyboard is a type to attach the methods to if someone wants to use it
|
||||||
type Keyboard struct{}
|
type Keyboard struct{}
|
||||||
|
|
||||||
const NONE = 0
|
// bit flag of modifier keys
|
||||||
const (
|
const (
|
||||||
LCTRL byte = 1 << iota
|
LCTRL byte = 1 << iota
|
||||||
LSHIFT
|
LSHIFT
|
||||||
@ -38,18 +43,20 @@ const (
|
|||||||
RSHIFT
|
RSHIFT
|
||||||
RALT
|
RALT
|
||||||
RSUPER
|
RSUPER
|
||||||
|
NONE = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
const delayDelimiter = "⏲"
|
const delayDelimiter = "⏲"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
currentKeyMap int
|
PressDelay time.Duration // PressDelay is the time in ms to delay befor sending a press event
|
||||||
DefaultDelay time.Duration
|
ReleaseDelay time.Duration // ReleaseDelay is the time in ms to wait before sending the release event
|
||||||
|
KeymapOrder []string // Keymap Order is the order in which the specified keymaps cycle on the computer
|
||||||
|
KeymapShortcut [8]byte // KeymapShortcut is the key combo that will cycle the current keymap by one
|
||||||
|
ErrOnUnknownKey bool // ErrOnUnknownKey whether or not to fail if the unicode rune is invalid or is not in the specified keymaps
|
||||||
|
KeymapPath string // KeymapPath is the pathe to where the keymap files are stored
|
||||||
|
|
||||||
KeymapOrder []string = []string{"qwerty"}
|
currentKeyMap int
|
||||||
KeymapShortcut [8]byte
|
|
||||||
ErrOnUnknownKey bool
|
|
||||||
KeymapPath string
|
|
||||||
keys = make(map[string]Keymap)
|
keys = make(map[string]Keymap)
|
||||||
flags = map[string]byte{
|
flags = map[string]byte{
|
||||||
"LSHIFT": LSHIFT,
|
"LSHIFT": LSHIFT,
|
||||||
@ -89,9 +96,6 @@ func write(p []byte) (n int, err error) {
|
|||||||
var (
|
var (
|
||||||
mod byte
|
mod byte
|
||||||
)
|
)
|
||||||
if DefaultDelay > 0 && i > 2 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
r, s = utf8.DecodeRune(p[index:])
|
r, s = utf8.DecodeRune(p[index:])
|
||||||
if r == utf8.RuneError {
|
if r == utf8.RuneError {
|
||||||
return index, fmt.Errorf("invalid rune: 0x%X", p[index]) // This probably screws things up if the last rune in 'p' is incomplete
|
return index, fmt.Errorf("invalid rune: 0x%X", p[index]) // This probably screws things up if the last rune in 'p' is incomplete
|
||||||
@ -103,26 +107,44 @@ func write(p []byte) (n int, err error) {
|
|||||||
return index, fmt.Errorf("rune not in keymap: %c", r)
|
return index, fmt.Errorf("rune not in keymap: %c", r)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break
|
break press
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is a delay
|
switch {
|
||||||
if cur.DelayDelimiter {
|
case cur.PressDelayDelimiter:
|
||||||
index += s + parseDelay(p[index+s:])
|
var n int
|
||||||
break
|
n, PressDelay = parseDelay(p[index+s:])
|
||||||
}
|
index += s + n
|
||||||
|
break press
|
||||||
|
|
||||||
|
case cur.ReleaseDelayDelimiter:
|
||||||
|
var n int
|
||||||
|
n, PressDelay = parseDelay(p[index+s:])
|
||||||
|
index += s + n
|
||||||
|
break press
|
||||||
|
|
||||||
|
case cur.Comment:
|
||||||
|
var n int
|
||||||
|
n = bytes.Index(p[index+s:], []byte("\n"))
|
||||||
|
if n < 0 {
|
||||||
|
n = 0
|
||||||
|
}
|
||||||
|
index += s + n
|
||||||
|
break press
|
||||||
|
|
||||||
|
default:
|
||||||
// Calculate next modifier byte
|
// Calculate next modifier byte
|
||||||
for _, v := range cur.Modifier {
|
for _, v := range cur.Modifier {
|
||||||
mod = mod | flags[v]
|
mod = mod | flags[v]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the modifier if it is the first key otherwise
|
// Set the modifier if it is the first key otherwise
|
||||||
// check if the next modifier byte is the same
|
// check if the next modifier byte is the same
|
||||||
if i == 2 {
|
if i == 2 {
|
||||||
flag = mod
|
flag = mod
|
||||||
} else if flag != mod {
|
} else if flag != mod {
|
||||||
break
|
break press
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for duplicate key press. You can't press a key if it is already pressed.
|
// Check for duplicate key press. You can't press a key if it is already pressed.
|
||||||
@ -131,20 +153,24 @@ func write(p []byte) (n int, err error) {
|
|||||||
break press
|
break press
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
report[i] = cur.Decimal
|
report[i] = cur.Decimal
|
||||||
index += s
|
index += s
|
||||||
|
if PressDelay > 0 {
|
||||||
|
break press
|
||||||
|
}
|
||||||
}
|
}
|
||||||
report[0] = flag
|
report[0] = flag
|
||||||
r, _ = utf8.DecodeRune(p[index-1:])
|
r, _ = utf8.DecodeRune(p[index-1:])
|
||||||
fmt.Printf("%c: delay: %v %v\n", r, DefaultDelay, DefaultDelay > (0))
|
|
||||||
Press(report, Hidg0)
|
Press(report, Hidg0)
|
||||||
delay()
|
delay(PressDelay)
|
||||||
}
|
}
|
||||||
keymapto0() // To make it reproducible
|
keymapto0() // To make it reproducible
|
||||||
return index, nil
|
return index, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDelay(buffer []byte) int {
|
func parseDelay(buffer []byte) (count int, delay time.Duration) {
|
||||||
var index int
|
var index int
|
||||||
sb := strings.Builder{}
|
sb := strings.Builder{}
|
||||||
for index < len(buffer) {
|
for index < len(buffer) {
|
||||||
@ -158,26 +184,24 @@ func parseDelay(buffer []byte) int {
|
|||||||
}
|
}
|
||||||
i, err := strconv.Atoi(sb.String())
|
i, err := strconv.Atoi(sb.String())
|
||||||
if err == nil || err == strconv.ErrRange {
|
if err == nil || err == strconv.ErrRange {
|
||||||
DefaultDelay = time.Millisecond * time.Duration(i)
|
return index, time.Millisecond * time.Duration(i)
|
||||||
return index
|
|
||||||
}
|
}
|
||||||
return 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func delay() {
|
func delay(Delay time.Duration) {
|
||||||
if DefaultDelay > 0 {
|
if Delay > 0 {
|
||||||
if syncCheck, ok := Hidg0.(syncer); ok {
|
if syncCheck, ok := Hidg0.(syncer); ok {
|
||||||
syncCheck.Sync()
|
syncCheck.Sync()
|
||||||
}
|
}
|
||||||
time.Sleep(DefaultDelay)
|
time.Sleep(Delay)
|
||||||
// DefaultDelay = 0
|
// DefaultDelay = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Press(press [8]byte, file io.Writer) {
|
func Press(press [8]byte, file io.Writer) {
|
||||||
file.Write(press[:])
|
file.Write(press[:])
|
||||||
Hidg0.(syncer).Sync()
|
delay(ReleaseDelay)
|
||||||
time.Sleep(DefaultDelay)
|
|
||||||
file.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
file.Write([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,37 +222,40 @@ func changeKeymap(r rune) bool {
|
|||||||
buf := bytes.NewBuffer(make([]byte, 0, 8*len(KeymapOrder))) // To batch shortcut presses
|
buf := bytes.NewBuffer(make([]byte, 0, 8*len(KeymapOrder))) // To batch shortcut presses
|
||||||
|
|
||||||
for i := 0; i < len(KeymapOrder); i++ {
|
for i := 0; i < len(KeymapOrder); i++ {
|
||||||
if _, ok := CurrentKeymap()[string(r)]; ok {
|
_, ok := CurrentKeymap()[string(r)]
|
||||||
|
if ok {
|
||||||
Hidg0.Write(buf.Bytes())
|
Hidg0.Write(buf.Bytes())
|
||||||
return true
|
return true
|
||||||
} else {
|
}
|
||||||
Press(KeymapShortcut, buf)
|
Press(KeymapShortcut, buf)
|
||||||
if currentKeyMap == len(KeymapOrder)-1 {
|
if currentKeyMap == len(KeymapOrder)-1 {
|
||||||
currentKeyMap = 0
|
currentKeyMap = 0
|
||||||
} else {
|
} else {
|
||||||
currentKeyMap++
|
currentKeyMap++
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func CurrentKeymap() Keymap {
|
func CurrentKeymap() Keymap {
|
||||||
if keymap, ok := keys[KeymapOrder[currentKeyMap]]; ok {
|
keymap, ok := keys[KeymapOrder[currentKeyMap]]
|
||||||
|
if ok {
|
||||||
return keymap
|
return keymap
|
||||||
} else {
|
|
||||||
return LoadKeymap(KeymapOrder[currentKeyMap])
|
|
||||||
}
|
}
|
||||||
|
return LoadKeymap(KeymapOrder[currentKeyMap])
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadKeymap(keymapName string) Keymap {
|
func LoadKeymap(keymapName string) Keymap {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
content []byte
|
content []byte
|
||||||
|
file = path.Join(path.Join(KeymapPath, "hid"), keymapName+".json")
|
||||||
tmp = make(Keymap, 0)
|
tmp = make(Keymap, 0)
|
||||||
)
|
)
|
||||||
fmt.Println(path.Join(path.Join(KeymapPath, "hid"), keymapName+".json"))
|
fmt.Println(file)
|
||||||
content, err = ioutil.ReadFile(path.Join(path.Join(KeymapPath, "hid"), keymapName+".json"))
|
content, err = ioutil.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -386,5 +386,20 @@
|
|||||||
" ": {
|
" ": {
|
||||||
"modifier": ["NONE"],
|
"modifier": ["NONE"],
|
||||||
"decimal": 44
|
"decimal": 44
|
||||||
|
},
|
||||||
|
"⏲": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"PressDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"🐉": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"releaseDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"⨌": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"comment": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,6 +390,16 @@
|
|||||||
"⏲": {
|
"⏲": {
|
||||||
"modifier": ["NONE"],
|
"modifier": ["NONE"],
|
||||||
"decimal": 0,
|
"decimal": 0,
|
||||||
"delayDelimiter": true
|
"PressDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"🐉": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"releaseDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"⨌": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"comment": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,5 +306,20 @@
|
|||||||
" ": {
|
" ": {
|
||||||
"modifier": ["NONE"],
|
"modifier": ["NONE"],
|
||||||
"decimal": 44
|
"decimal": 44
|
||||||
|
},
|
||||||
|
"⏲": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"PressDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"🐉": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"releaseDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"⨌": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"comment": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,5 +374,20 @@
|
|||||||
" ": {
|
" ": {
|
||||||
"modifier": ["NONE"],
|
"modifier": ["NONE"],
|
||||||
"decimal": 44
|
"decimal": 44
|
||||||
|
},
|
||||||
|
"⏲": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"PressDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"🐉": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"releaseDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"⨌": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"comment": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,5 +558,20 @@
|
|||||||
" ": {
|
" ": {
|
||||||
"modifier": ["NONE"],
|
"modifier": ["NONE"],
|
||||||
"decimal": 44
|
"decimal": 44
|
||||||
|
},
|
||||||
|
"⏲": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"PressDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"🐉": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"releaseDelayDelimiter": true
|
||||||
|
},
|
||||||
|
"⨌": {
|
||||||
|
"modifier": ["NONE"],
|
||||||
|
"decimal": 0,
|
||||||
|
"comment": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
main.go
2
main.go
@ -4,6 +4,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"timmy.narnian.us/hid/ghid"
|
"timmy.narnian.us/hid/ghid"
|
||||||
)
|
)
|
||||||
@ -20,6 +21,7 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
hid.KeymapOrder = flag.Args()
|
hid.KeymapOrder = flag.Args()
|
||||||
|
hid.ReleaseDelay = time.Duration(10) * time.Millisecond
|
||||||
|
|
||||||
fmt.Println(hid.KeymapPath)
|
fmt.Println(hid.KeymapPath)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user