From d254ae5b0d8c4add7f114533d5c938d63a44b49c Mon Sep 17 00:00:00 2001 From: Unrud Date: Thu, 23 Feb 2023 01:09:30 +0100 Subject: [PATCH] uinput-controller: Map runes/keys directly and handle errors --- inputcontrol/controller_uinput.go | 273 ++++++++++++++++-------------- inputcontrol/keysyms.generated.go | 2 +- inputcontrol/keysyms.generator.go | 2 +- inputcontrol/keysyms.go | 2 +- 4 files changed, 150 insertions(+), 129 deletions(-) diff --git a/inputcontrol/controller_uinput.go b/inputcontrol/controller_uinput.go index bfd9b91..df6b5a2 100644 --- a/inputcontrol/controller_uinput.go +++ b/inputcontrol/controller_uinput.go @@ -2,6 +2,7 @@ /* * Copyright (c) 2023 De_Coder github.com/ps100000 + * Copyright (c) 2023 Unrud * * 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)) } diff --git a/inputcontrol/keysyms.generated.go b/inputcontrol/keysyms.generated.go index 3e0ead8..8734718 100644 --- a/inputcontrol/keysyms.generated.go +++ b/inputcontrol/keysyms.generated.go @@ -1,5 +1,5 @@ // Code generated by keysyms.generator.go. DO NOT EDIT. -//go:build portal || x11 || uinput +//go:build portal || x11 package inputcontrol diff --git a/inputcontrol/keysyms.generator.go b/inputcontrol/keysyms.generator.go index 71b4094..cc18417 100644 --- a/inputcontrol/keysyms.generator.go +++ b/inputcontrol/keysyms.generator.go @@ -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) diff --git a/inputcontrol/keysyms.go b/inputcontrol/keysyms.go index f0dcf0a..de183a1 100644 --- a/inputcontrol/keysyms.go +++ b/inputcontrol/keysyms.go @@ -1,4 +1,4 @@ -//go:build portal || x11 || uinput +//go:build portal || x11 /* * Copyright (c) 2018 Unrud