Uinput
This package provides pure go wrapper functions for the LINUX uinput device, which allows to create virtual input devices
in userspace. At the moment this package offers a virtual keyboard implementation as well as a virtual mouse device,gamepad,
a touch pad device & a dial device.
The keyboard can be used to either send single key presses or hold down a specified key and release it later
(useful for building game controllers). The mouse device issues relative positional change events to the x and y axis
of the mouse pointer and may also fire click events (left and right click). For implementing things like region selects
via a virtual mouse pointer, press and release functions for the mouse device are also included.
The touch pad, on the other hand can be used to move the mouse cursor to the specified position on the screen and to
issue left and right clicks. Note that you'll need to specify the region size of your screen first though (happens during
device creation).
Dial devices support triggering rotation events, like turns on a volume knob.
Please note that you will need to make sure to have the necessary rights to write to uinput. You can either chmod your
uinput device, or add a rule in /etc/udev/rules.d to allow your user's group or a dedicated group to write to the device.
You may use the following two commands to add the necessary rights for you current user to a file called 99-$USER.rules
(where $USER is your current user's name):
echo KERNEL==\"uinput\", GROUP=\"$USER\", MODE:=\"0660\" | sudo tee /etc/udev/rules.d/99-$USER.rules
sudo udevadm trigger
Installation
Simply check out the repository and use the commands
go build && go install
The package will then be installed to your local respository, along with the package documentation.
The documentation contains more details on the usage of this package.
Alternatively, if you'd like to use a specific version/tag of this library, you may use the gopkg.in service.
To get v.1.x.x (latest stable v1), simply enter this on your command line:
go get gopkg.in/bendahl/uinput.v1
To import this version in your code use:
import "gopkg.in/bendahl/uinput.v1"
You may then refer to it as "uinput" in your code. For further details see: https://gopkg.in/bendahl/uinput.v1
Thanks to gopkg.in for offering this great service!
Usage
The following section explains some common ways to use this lib.
Using the virtual keyboard device:
package main
import "github.com/bendahl/uinput"
func main() {
keyboard, err := uinput.CreateKeyboard("/dev/uinput", []byte("testkeyboard"))
if err != nil {
return
}
defer keyboard.Close()
keyboard.KeyPress(uinput.KeyA)
keyboard.KeyDown(uinput.KeyLeftshift)
keyboard.KeyPress(uinput.KeyA)
keyboard.KeyUp(uinput.KeyLeftshift)
for i := 0; i < 5; i++ {
keyboard.KeyPress(uinput.Key0)
}
}
Using the virtual mouse device:
package main
import "github.com/bendahl/uinput"
func main() {
mouse, err := uinput.CreateMouse("/dev/uinput", []byte("testmouse"))
if err != nil {
return
}
defer mouse.Close()
mouse.MoveUp(10)
mouse.MoveRight(10)
mouse.MoveDown(10)
mouse.MoveLeft(10)
mouse.Move(100, 100)
mouse.LeftClick()
mouse.RightClick()
mouse.MiddleClick()
mouse.LeftPress()
mouse.MoveDown(100)
mouse.LeftRelease()
mouse.Wheel(false, 1)
mouse.Wheel(false, -1)
mouse.Wheel(true, 1)
mouse.Wheel(true, -1)
}
Using the virtual touch pad device:
package main
import "github.com/bendahl/uinput"
func main() {
touch, err := uinput.CreateTouchPad("/dev/uinput", []byte("testpad"), 0, 800, 0, 600)
if err != nil {
return
}
defer touch.Close()
touch.MoveTo(300, 200)
touch.LeftPress()
touch.MoveTo(400, 400)
touch.LeftRelease()
touch.TouchDown()
touch.TouchUp()
}
Using the virtual dial device:
package main
import "github.com/bendahl/uinput"
func main() {
dial, err := uinput.CreateDial("/dev/uinput", []byte("testdial"))
if err != nil {
return
}
defer dial.Close()
dial.Turn(-1)
dial.Turn(1)
}
License
The package falls under the MIT license. Please see the "LICENSE" file for details.
Current Status
2018-03-31: I am happy to announce that v1.0.0 is finally out! Go ahead and use this library in your own projects! Feedback is always welcome.
2019-03-24: Release v1.0.1 fixes a positioning issue that affects the touchpad. See issue #11 for details (positioning works now, but a (possibly) better solution is under investigation).
2019-07-24: Don't panic! As of version v1.0.2 the uinput library will provide an error instead of raising a panic in case of a faulty initialization.
See pull request #12 for details (many thanks to muesli for the contribution).
2019-09-15: Add single touch event (resistive)
2019-12-31: Release v1.1.0 introduces yet another cool feature: Mouse wheel support. Thanks to muesli for this contribution!
2020-01-07: Release v1.2.0 introduces dial device support. Thanks again to muesli!
2020-11-15: Release v1.4.0 introduces a new Move(x, y) function to the mouse device along with a little cleanup and additional tests.
Thanks robpre and MetalBlueberry for your valuable input!
2021-03-25: Release v1.4.1 fixes a keyboard issue that may affect android systems. See issue #24 for details.
2022-01-09: Release v1.5.0 introduces middle button support for the mouse. Thanks so much to @jbensmann for the great work! Also, thank you @djsavvy for the thorough review!
2022-02-11: Release v1.5.1 finally fixes the MoveTo(x, y) function of the touch pad device. Big shout out to @mafredri for this find! Thank you so much!
2022-09-01: Release v1.6.0 adds a new gamepad device. Thanks @gitautas for providing the implementation and thanks to @AndrusGerman for the inspiration!
Also, thanks to @sheharyaar there is now a new function FetchSyspath()
that returns the syspath to the device file.
2023-04-27: Release 1.6.1 fixes uinput functionality on Wayland. Thanks to @gslandtreter for this fix and for pointing out the relevant piece of documentation!
2023-05-10: Release 1.6.2 fixes uinput an issue introduced in version 1.6.1 that will break backward compatibility. The change will be reverted for now.
Options to improve compatibility with newer systems are being evaluated. Thanks to @wenfer for the hint!
TODO
The current API can be considered stable and the overall functionality (as originally envisioned) is complete.
Testing on x86_64 and ARM platforms (specifically the RaspberryPi) has been successful. If you'd like to use this library
on a different platform that supports Linux, feel free to test it and share the results. This would be greatly appreciated.