uinput-controller: Map runes/keys directly and handle errors
This commit is contained in:
parent
809d3a0064
commit
d254ae5b0d
4 changed files with 150 additions and 129 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2023 De_Coder github.com/ps100000
|
||||
* Copyright (c) 2023 Unrud <unrud@outlook.com>
|
||||
*
|
||||
* This file is part of Remote-Touchpad.
|
||||
*
|
||||
|
|
@ -22,83 +23,66 @@
|
|||
package inputcontrol
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bendahl/uinput"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
var ukeysMap = map[Keysym]int{
|
||||
0x0061: uinput.KeyA,
|
||||
0x0062: uinput.KeyB,
|
||||
0x0063: uinput.KeyC,
|
||||
0x0064: uinput.KeyD,
|
||||
0x0065: uinput.KeyE,
|
||||
0x0066: uinput.KeyF,
|
||||
0x0067: uinput.KeyG,
|
||||
0x0068: uinput.KeyH,
|
||||
0x0069: uinput.KeyI,
|
||||
0x006a: uinput.KeyJ,
|
||||
0x006b: uinput.KeyK,
|
||||
0x006c: uinput.KeyL,
|
||||
0x006d: uinput.KeyM,
|
||||
0x006e: uinput.KeyN,
|
||||
0x006f: uinput.KeyO,
|
||||
0x0070: uinput.KeyP,
|
||||
0x0071: uinput.KeyQ,
|
||||
0x0072: uinput.KeyR,
|
||||
0x0073: uinput.KeyS,
|
||||
0x0074: uinput.KeyT,
|
||||
0x0075: uinput.KeyU,
|
||||
0x0076: uinput.KeyV,
|
||||
0x0077: uinput.KeyW,
|
||||
0x0078: uinput.KeyX,
|
||||
0x0079: uinput.KeyY,
|
||||
0x007a: uinput.KeyZ,
|
||||
|
||||
0x0030: uinput.Key0,
|
||||
0x0031: uinput.Key1,
|
||||
0x0032: uinput.Key2,
|
||||
0x0033: uinput.Key3,
|
||||
0x0034: uinput.Key4,
|
||||
0x0035: uinput.Key5,
|
||||
0x0036: uinput.Key6,
|
||||
0x0037: uinput.Key7,
|
||||
0x0038: uinput.Key8,
|
||||
0x0039: uinput.Key9,
|
||||
|
||||
0xff1b: uinput.KeyEsc,
|
||||
0x002d: uinput.KeyMinus,
|
||||
0x002b: uinput.KeyKpplus,
|
||||
0x002a: uinput.KeyKpasterisk,
|
||||
0x003d: uinput.KeyEqual,
|
||||
0xff08: uinput.KeyBackspace,
|
||||
0xff09: uinput.KeyTab,
|
||||
0x0028: uinput.KeyLeftbrace,
|
||||
0x0029: uinput.KeyRightbrace,
|
||||
0xff0d: uinput.KeyEnter,
|
||||
0x003b: uinput.KeySemicolon,
|
||||
0x0027: uinput.KeyApostrophe,
|
||||
0x0060: uinput.KeyGrave,
|
||||
0x005c: uinput.KeyBackslash,
|
||||
0x002c: uinput.KeyComma,
|
||||
0x0abd: uinput.KeyDot,
|
||||
0x002f: uinput.KeySlash,
|
||||
0x0020: uinput.KeySpace,
|
||||
0xff50: uinput.KeyHome,
|
||||
0xff52: uinput.KeyUp,
|
||||
0xff51: uinput.KeyLeft,
|
||||
0xff53: uinput.KeyRight,
|
||||
0xff57: uinput.KeyEnd,
|
||||
0xff54: uinput.KeyDown,
|
||||
0xffff: uinput.KeyDelete,
|
||||
0x1008FF12: uinput.KeyMute,
|
||||
0x1008FF11: uinput.KeyVolumedown,
|
||||
0x1008FF13: uinput.KeyVolumeup,
|
||||
0xffeb: uinput.KeyLeftmeta,
|
||||
0x1008ff26: uinput.KeyBack,
|
||||
0x1008ff27: uinput.KeyForward,
|
||||
0x1008ff17: uinput.KeyNextsong,
|
||||
0x1008ff14: uinput.KeyPlaypause,
|
||||
0x1008ff16: uinput.KeyPrevioussong,
|
||||
var ukeysMap = map[rune]int{
|
||||
'a': uinput.KeyA,
|
||||
'b': uinput.KeyB,
|
||||
'c': uinput.KeyC,
|
||||
'd': uinput.KeyD,
|
||||
'e': uinput.KeyE,
|
||||
'f': uinput.KeyF,
|
||||
'g': uinput.KeyG,
|
||||
'h': uinput.KeyH,
|
||||
'i': uinput.KeyI,
|
||||
'j': uinput.KeyJ,
|
||||
'k': uinput.KeyK,
|
||||
'l': uinput.KeyL,
|
||||
'm': uinput.KeyM,
|
||||
'n': uinput.KeyN,
|
||||
'o': uinput.KeyO,
|
||||
'p': uinput.KeyP,
|
||||
'q': uinput.KeyQ,
|
||||
'r': uinput.KeyR,
|
||||
's': uinput.KeyS,
|
||||
't': uinput.KeyT,
|
||||
'u': uinput.KeyU,
|
||||
'v': uinput.KeyV,
|
||||
'w': uinput.KeyW,
|
||||
'x': uinput.KeyX,
|
||||
'y': uinput.KeyY,
|
||||
'z': uinput.KeyZ,
|
||||
'0': uinput.Key0,
|
||||
'1': uinput.Key1,
|
||||
'2': uinput.Key2,
|
||||
'3': uinput.Key3,
|
||||
'4': uinput.Key4,
|
||||
'5': uinput.Key5,
|
||||
'6': uinput.Key6,
|
||||
'7': uinput.Key7,
|
||||
'8': uinput.Key8,
|
||||
'9': uinput.Key9,
|
||||
0x1b: uinput.KeyEsc,
|
||||
'-': uinput.KeyMinus,
|
||||
'+': uinput.KeyKpplus,
|
||||
'*': uinput.KeyKpasterisk,
|
||||
'=': uinput.KeyEqual,
|
||||
0x08: uinput.KeyBackspace,
|
||||
'\t': uinput.KeyTab,
|
||||
'(': uinput.KeyLeftbrace,
|
||||
')': uinput.KeyRightbrace,
|
||||
'\n': uinput.KeyEnter,
|
||||
';': uinput.KeySemicolon,
|
||||
'\'': uinput.KeyApostrophe,
|
||||
'`': uinput.KeyGrave,
|
||||
'\\': uinput.KeyBackslash,
|
||||
',': uinput.KeyComma,
|
||||
'.': uinput.KeyDot,
|
||||
'/': uinput.KeySlash,
|
||||
' ': uinput.KeySpace,
|
||||
}
|
||||
|
||||
type uinputController struct {
|
||||
|
|
@ -107,93 +91,130 @@ type uinputController struct {
|
|||
}
|
||||
|
||||
func init() {
|
||||
RegisterController("Uinput", InitUinputController, 0)
|
||||
RegisterController("uinput", InitUinputController, 0)
|
||||
}
|
||||
|
||||
func InitUinputController() (Controller, error) {
|
||||
keyboard, err := uinput.CreateKeyboard("/dev/uinput", []byte("remote-tp-keyboard"))
|
||||
keyboard, err := uinput.CreateKeyboard("/dev/uinput", []byte("remote-touchpad-keyboard"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mouse, err := uinput.CreateMouse("/dev/uinput", []byte("remote-tp-mouse"))
|
||||
mouse, err := uinput.CreateMouse("/dev/uinput", []byte("remote-touchpad-mouse"))
|
||||
if err != nil {
|
||||
keyboard.Close()
|
||||
return nil, err
|
||||
}
|
||||
p := &uinputController{keyboard, mouse}
|
||||
return p, nil
|
||||
return &uinputController{keyboard, mouse}, nil
|
||||
}
|
||||
|
||||
func (p *uinputController) Close() error {
|
||||
p.keyboard.Close()
|
||||
p.mouse.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *uinputController) sendKeysym(sym Keysym) error {
|
||||
if sym >= 0x0041 && sym <= 0x005a { // capital letters
|
||||
p.keyboard.KeyDown(uinput.KeyLeftshift)
|
||||
p.keyboard.KeyPress(ukeysMap[sym+0x20])
|
||||
p.keyboard.KeyUp(uinput.KeyLeftshift)
|
||||
} else if key, ok := ukeysMap[sym]; ok {
|
||||
p.keyboard.KeyPress(key)
|
||||
if err := p.keyboard.Close(); err != nil {
|
||||
p.mouse.Close()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return p.mouse.Close()
|
||||
}
|
||||
|
||||
// No support for keyboard layouts, only works with QWERTY
|
||||
func (p *uinputController) KeyboardText(text string) error {
|
||||
for _, runeValue := range text {
|
||||
keysym, err := RuneToKeysym(runeValue)
|
||||
if err != nil {
|
||||
modifierShift := false
|
||||
if unicode.IsUpper(runeValue) {
|
||||
modifierShift = true
|
||||
runeValue = unicode.ToLower(runeValue)
|
||||
}
|
||||
uinputKey, found := ukeysMap[runeValue]
|
||||
if !found {
|
||||
return fmt.Errorf("unsupported rune: %q", runeValue)
|
||||
}
|
||||
if modifierShift {
|
||||
if err := p.keyboard.KeyDown(uinput.KeyLeftshift); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := p.keyboard.KeyPress(uinputKey); err != nil {
|
||||
return err
|
||||
}
|
||||
err = p.sendKeysym(keysym)
|
||||
|
||||
if modifierShift {
|
||||
if err := p.keyboard.KeyUp(uinput.KeyLeftshift); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *uinputController) KeyboardKey(key Key) error {
|
||||
keysym, err := KeyToKeysym(key)
|
||||
if err != nil {
|
||||
return err
|
||||
var uinputKey int
|
||||
switch key {
|
||||
case KeyBackSpace:
|
||||
uinputKey = uinput.KeyBackspace
|
||||
case KeyReturn:
|
||||
uinputKey = uinput.KeyEnter
|
||||
case KeyDelete:
|
||||
uinputKey = uinput.KeyDelete
|
||||
case KeyHome:
|
||||
uinputKey = uinput.KeyHome
|
||||
case KeyLeft:
|
||||
uinputKey = uinput.KeyLeft
|
||||
case KeyUp:
|
||||
uinputKey = uinput.KeyUp
|
||||
case KeyRight:
|
||||
uinputKey = uinput.KeyRight
|
||||
case KeyDown:
|
||||
uinputKey = uinput.KeyDown
|
||||
case KeyEnd:
|
||||
uinputKey = uinput.KeyEnd
|
||||
case KeySuper:
|
||||
uinputKey = uinput.KeyLeftmeta
|
||||
case KeyVolumeMute:
|
||||
uinputKey = uinput.KeyMute
|
||||
case KeyVolumeDown:
|
||||
uinputKey = uinput.KeyVolumedown
|
||||
case KeyVolumeUp:
|
||||
uinputKey = uinput.KeyVolumeup
|
||||
case KeyMediaPlayPause:
|
||||
uinputKey = uinput.KeyPlaypause
|
||||
case KeyMediaPrevTrack:
|
||||
uinputKey = uinput.KeyPrevioussong
|
||||
case KeyMediaNextTrack:
|
||||
uinputKey = uinput.KeyNextsong
|
||||
case KeyBrowserBack:
|
||||
uinputKey = uinput.KeyBack
|
||||
case KeyBrowserForward:
|
||||
uinputKey = uinput.KeyForward
|
||||
default:
|
||||
return fmt.Errorf("unsupported key: %#v", key)
|
||||
}
|
||||
return p.sendKeysym(keysym)
|
||||
return p.keyboard.KeyPress(uinputKey)
|
||||
}
|
||||
|
||||
func (p *uinputController) PointerButton(button PointerButton, press bool) error {
|
||||
switch button {
|
||||
case PointerButtonLeft:
|
||||
if press {
|
||||
p.mouse.LeftPress()
|
||||
} else {
|
||||
p.mouse.LeftRelease()
|
||||
}
|
||||
case PointerButtonRight:
|
||||
if press {
|
||||
p.mouse.RightPress()
|
||||
} else {
|
||||
p.mouse.RightRelease()
|
||||
}
|
||||
case PointerButtonMiddle:
|
||||
if press {
|
||||
p.mouse.MiddlePress()
|
||||
} else {
|
||||
p.mouse.MiddleRelease()
|
||||
}
|
||||
switch {
|
||||
case button == PointerButtonLeft && press:
|
||||
return p.mouse.LeftPress()
|
||||
case button == PointerButtonLeft && !press:
|
||||
return p.mouse.LeftRelease()
|
||||
case button == PointerButtonRight && press:
|
||||
return p.mouse.RightPress()
|
||||
case button == PointerButtonRight && !press:
|
||||
return p.mouse.RightRelease()
|
||||
case button == PointerButtonMiddle && press:
|
||||
return p.mouse.MiddlePress()
|
||||
case button == PointerButtonMiddle && !press:
|
||||
return p.mouse.MiddleRelease()
|
||||
default:
|
||||
return errors.New("unsupported pointer button")
|
||||
return fmt.Errorf("unsupported pointer button: %#v", button)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *uinputController) PointerMove(deltaX, deltaY int) error {
|
||||
p.mouse.Move(int32(deltaX), int32(deltaY))
|
||||
return nil
|
||||
return p.mouse.Move(int32(deltaX), int32(deltaY))
|
||||
}
|
||||
|
||||
func (p *uinputController) PointerScroll(deltaHorizontal, deltaVertical int, finish bool) error {
|
||||
p.mouse.Wheel(false, int32(deltaVertical))
|
||||
p.mouse.Wheel(true, int32(deltaHorizontal))
|
||||
return nil
|
||||
if err := p.mouse.Wheel(false, int32(deltaVertical)); err != nil {
|
||||
return err
|
||||
}
|
||||
return p.mouse.Wheel(true, int32(deltaHorizontal))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Code generated by keysyms.generator.go. DO NOT EDIT.
|
||||
//go:build portal || x11 || uinput
|
||||
//go:build portal || x11
|
||||
|
||||
package inputcontrol
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ func main() {
|
|||
keysymsMap[unicode] = keysym
|
||||
}
|
||||
content := "// Code generated by keysyms.generator.go. DO NOT EDIT.\n" +
|
||||
"//go:build portal || x11 || uinput\n\n" +
|
||||
"//go:build portal || x11\n\n" +
|
||||
"package inputcontrol\n\n" +
|
||||
"var keysymsMap = map[rune]Keysym{\n"
|
||||
keys := make([]rune, 0)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//go:build portal || x11 || uinput
|
||||
//go:build portal || x11
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 Unrud <unrud@outlook.com>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue