-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(keyboard): keyboard state/layout from events
- Loading branch information
1 parent
e40ebd2
commit 214338e
Showing
7 changed files
with
291 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package kbext |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package kbext | ||
|
||
type keymap struct { | ||
plain string | ||
altgr string | ||
shift string | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package kbext | ||
|
||
import evdev "github.com/holoplot/go-evdev" | ||
|
||
type LayoutID string | ||
|
||
var ( | ||
LayoutQuertyEnUs LayoutID = "querty-en-US" | ||
) | ||
|
||
type layout map[evdev.EvCode]keymap | ||
|
||
var layouts = map[LayoutID]layout{ | ||
LayoutQuertyEnUs: quertyEnUs, | ||
} | ||
|
||
func LayoutKeys() []LayoutID { | ||
r := make([]LayoutID, 0, len(layouts)) | ||
for k := range layouts { | ||
r = append(r, k) | ||
} | ||
return r | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package kbext | ||
|
||
import evdev "github.com/holoplot/go-evdev" | ||
|
||
var ( | ||
// LayoutQuertyEnUs LayoutID = "querty-en-US" | ||
|
||
quertyEnUs = map[evdev.EvCode]keymap{ | ||
evdev.KEY_NUMERIC_STAR: {plain: "*", altgr: "*", shift: "*"}, | ||
evdev.KEY_NUMERIC_3: {plain: "3", altgr: "3", shift: "3"}, | ||
evdev.KEY_NUMERIC_2: {plain: "2", altgr: "2", shift: "2"}, | ||
evdev.KEY_NUMERIC_5: {plain: "5", altgr: "5", shift: "5"}, | ||
evdev.KEY_NUMERIC_4: {plain: "4", altgr: "4", shift: "4"}, | ||
evdev.KEY_NUMERIC_7: {plain: "7", altgr: "7", shift: "7"}, | ||
evdev.KEY_NUMERIC_6: {plain: "6", altgr: "6", shift: "6"}, | ||
evdev.KEY_NUMERIC_9: {plain: "9", altgr: "9", shift: "9"}, | ||
evdev.KEY_NUMERIC_8: {plain: "8", altgr: "8", shift: "8"}, | ||
evdev.KEY_NUMERIC_1: {plain: "1", altgr: "1", shift: "1"}, | ||
evdev.KEY_NUMERIC_0: {plain: "0", altgr: "0", shift: "0"}, | ||
|
||
evdev.KEY_KP4: {plain: "4", altgr: "4", shift: "4"}, | ||
evdev.KEY_KP5: {plain: "5", altgr: "5", shift: "5"}, | ||
evdev.KEY_KP6: {plain: "6", altgr: "6", shift: "6"}, | ||
evdev.KEY_KP7: {plain: "7", altgr: "7", shift: "7"}, | ||
evdev.KEY_KP0: {plain: "0", altgr: "0", shift: "0"}, | ||
evdev.KEY_KP1: {plain: "1", altgr: "1", shift: "1"}, | ||
evdev.KEY_KP2: {plain: "2", altgr: "2", shift: "2"}, | ||
evdev.KEY_KP3: {plain: "3", altgr: "3", shift: "3"}, | ||
evdev.KEY_KP8: {plain: "8", altgr: "8", shift: "8"}, | ||
evdev.KEY_KP9: {plain: "9", altgr: "9", shift: "9"}, | ||
|
||
evdev.KEY_U: {plain: "u", altgr: "u", shift: "U"}, | ||
evdev.KEY_W: {plain: "w", altgr: "w", shift: "W"}, | ||
evdev.KEY_E: {plain: "e", altgr: "e", shift: "E"}, | ||
evdev.KEY_D: {plain: "d", altgr: "d", shift: "D"}, | ||
evdev.KEY_G: {plain: "g", altgr: "g", shift: "G"}, | ||
evdev.KEY_F: {plain: "f", altgr: "f", shift: "F"}, | ||
evdev.KEY_A: {plain: "a", altgr: "a", shift: "A"}, | ||
evdev.KEY_C: {plain: "c", altgr: "c", shift: "C"}, | ||
evdev.KEY_B: {plain: "b", altgr: "b", shift: "B"}, | ||
evdev.KEY_M: {plain: "m", altgr: "m", shift: "M"}, | ||
evdev.KEY_L: {plain: "l", altgr: "l", shift: "L"}, | ||
evdev.KEY_O: {plain: "o", altgr: "o", shift: "O"}, | ||
evdev.KEY_N: {plain: "n", altgr: "n", shift: "N"}, | ||
evdev.KEY_I: {plain: "i", altgr: "i", shift: "I"}, | ||
evdev.KEY_H: {plain: "h", altgr: "h", shift: "H"}, | ||
evdev.KEY_K: {plain: "k", altgr: "k", shift: "K"}, | ||
evdev.KEY_J: {plain: "j", altgr: "j", shift: "J"}, | ||
evdev.KEY_Q: {plain: "q", altgr: "q", shift: "Q"}, | ||
evdev.KEY_P: {plain: "p", altgr: "p", shift: "P"}, | ||
evdev.KEY_S: {plain: "s", altgr: "s", shift: "S"}, | ||
evdev.KEY_X: {plain: "x", altgr: "x", shift: "X"}, | ||
evdev.KEY_Z: {plain: "z", altgr: "z", shift: "Z"}, | ||
evdev.KEY_T: {plain: "t", altgr: "t", shift: "T"}, | ||
evdev.KEY_V: {plain: "v", altgr: "v", shift: "V"}, | ||
evdev.KEY_R: {plain: "r", altgr: "r", shift: "R"}, | ||
evdev.KEY_Y: {plain: "y", altgr: "y", shift: "Y"}, | ||
|
||
evdev.KEY_1: {plain: "1", altgr: "~", shift: "!"}, | ||
evdev.KEY_2: {plain: "2", altgr: "2", shift: "@"}, | ||
evdev.KEY_3: {plain: "3", altgr: "^", shift: "#"}, | ||
evdev.KEY_4: {plain: "4", altgr: "4", shift: "$"}, | ||
evdev.KEY_5: {plain: "5", altgr: "5", shift: "%"}, | ||
evdev.KEY_6: {plain: "6", altgr: "6", shift: "^"}, | ||
evdev.KEY_7: {plain: "7", altgr: "7", shift: "&"}, | ||
evdev.KEY_8: {plain: "8", altgr: "8", shift: "*"}, | ||
evdev.KEY_9: {plain: "9", altgr: "9", shift: "("}, | ||
evdev.KEY_0: {plain: "0", altgr: "0", shift: ")"}, | ||
|
||
evdev.KEY_BACKSLASH: {plain: "\\", altgr: "\\", shift: "|"}, | ||
evdev.KEY_TAB: {plain: "\t", altgr: "\t", shift: "\t"}, | ||
evdev.KEY_MINUS: {plain: "-", altgr: "-", shift: "-"}, | ||
evdev.KEY_SPACE: {plain: " ", altgr: " ", shift: " "}, | ||
evdev.KEY_GRAVE: {plain: "`", altgr: "`", shift: "`"}, | ||
evdev.KEY_LEFTBRACE: {plain: "[", altgr: "[", shift: "["}, | ||
evdev.KEY_RIGHTBRACE: {plain: "]", altgr: "]", shift: "]"}, | ||
evdev.KEY_COMMA: {plain: ",", altgr: ",", shift: ","}, | ||
evdev.KEY_EQUAL: {plain: "=", altgr: "=", shift: "="}, | ||
evdev.KEY_SEMICOLON: {plain: ";", altgr: ";", shift: ";"}, | ||
evdev.KEY_APOSTROPHE: {plain: "'", altgr: "'", shift: "'"}, | ||
evdev.KEY_DOT: {plain: ".", altgr: ".", shift: "."}, | ||
evdev.KEY_SLASH: {plain: "/", altgr: "/", shift: "/"}, | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package kbext | ||
|
||
import ( | ||
"errors" | ||
"log" | ||
|
||
evdev "github.com/holoplot/go-evdev" | ||
) | ||
|
||
type KbState struct { | ||
layout LayoutID | ||
shift bool | ||
altgr bool | ||
} | ||
|
||
var ( | ||
ErrNotACharKey = errors.New("last event was not a printable char key down") | ||
ErrNotHandled = errors.New("event not handled") | ||
ErrUnknwownLayout = errors.New("unknown layout") | ||
) | ||
|
||
func NewKbState(layout LayoutID) KbState { | ||
return KbState{ | ||
layout: layout, | ||
shift: false, | ||
altgr: false, | ||
} | ||
} | ||
|
||
func (kb *KbState) KeyEvent(kbEvt *evdev.KeyEvent) (string, error) { | ||
switch kbEvt.State { | ||
case evdev.KeyUp: | ||
_, err := kb.handleKey(kbEvt, false) | ||
if err == nil { | ||
err = ErrNotACharKey | ||
} | ||
return "", err | ||
case evdev.KeyDown: | ||
return kb.handleKey(kbEvt, true) | ||
} | ||
return "", ErrNotHandled | ||
} | ||
|
||
func (kb *KbState) handleKey(kbEvt *evdev.KeyEvent, down bool) (string, error) { | ||
switch kbEvt.Scancode { | ||
case evdev.KEY_LEFTSHIFT: | ||
fallthrough | ||
case evdev.KEY_RIGHTSHIFT: | ||
kb.shift = down | ||
return "", ErrNotACharKey | ||
|
||
case evdev.KEY_ENTER: | ||
fallthrough | ||
case evdev.KEY_KPENTER: | ||
return "\n", nil | ||
} | ||
|
||
layout, ok := layouts[kb.layout] | ||
if !ok { | ||
return "", ErrUnknwownLayout | ||
} | ||
|
||
keyinfo, ok := layout[kbEvt.Scancode] | ||
if !ok { | ||
return "", errors.New("KeyInfo not found") | ||
} | ||
|
||
if kb.altgr { | ||
if keyinfo.plain != keyinfo.altgr { | ||
return keyinfo.altgr, nil | ||
} | ||
keyName := evdev.KEYToString[kbEvt.Scancode] | ||
log.Printf("TODO : altgr mapping for %v", keyName) | ||
return keyinfo.altgr, nil | ||
} | ||
if kb.shift { | ||
if keyinfo.plain != keyinfo.shift { | ||
return keyinfo.shift, nil | ||
} | ||
keyName := evdev.KEYToString[kbEvt.Scancode] | ||
log.Printf("TODO : shift mapping for %v", keyName) | ||
return keyinfo.shift, nil | ||
} | ||
return keyinfo.plain, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package evdev | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
type KeyEventState uint8 | ||
|
||
const ( | ||
KeyUp KeyEventState = 0x0 | ||
KeyDown KeyEventState = 0x1 | ||
KeyHold KeyEventState = 0x2 | ||
) | ||
|
||
// KeyEvents are used to describe state changes of keyboards, buttons, | ||
// or other key-like devices. | ||
type KeyEvent struct { | ||
Event *InputEvent | ||
Scancode EvCode | ||
Keycode uint16 | ||
State KeyEventState | ||
} | ||
|
||
func (kev *KeyEvent) New(ev *InputEvent) { | ||
kev.Event = ev | ||
kev.Keycode = 0 // :todo | ||
kev.Scancode = ev.Code | ||
|
||
switch ev.Value { | ||
case 0: | ||
kev.State = KeyUp | ||
case 2: | ||
kev.State = KeyHold | ||
case 1: | ||
kev.State = KeyDown | ||
} | ||
} | ||
|
||
func NewKeyEvent(ev *InputEvent) *KeyEvent { | ||
kev := &KeyEvent{} | ||
kev.New(ev) | ||
return kev | ||
} | ||
|
||
func (ev *KeyEvent) String() string { | ||
state := "unknown" | ||
|
||
switch ev.State { | ||
case KeyUp: | ||
state = "up" | ||
case KeyHold: | ||
state = "hold" | ||
case KeyDown: | ||
state = "down" | ||
} | ||
|
||
return fmt.Sprintf("key event %d (%d), (%s)", ev.Scancode, ev.Event.Code, state) | ||
} |