A virtual input library: supports mouse, keyboard, joypad, trackpad and more
  • C++ 61.1%
  • Python 20.6%
  • Rust 11.7%
  • C 2.9%
  • CMake 2.7%
  • Other 1%
Find a file
ABeltramo d28ec79eb6
Merge pull request #42 from kmreisi/fix/pen-tablet-flaky-test
[1/5] Fix flaky pen-tablet test assertions
2026-07-13 09:33:25 +01:00
.github/workflows fix: CI and basic instructions in the README 2025-03-03 19:37:19 +00:00
bindings Fix rust bindings 2025-05-28 17:45:38 +02:00
cmake feat: added C ABI 2024-03-24 20:31:28 +00:00
docker Merge remote-tracking branch 'upstream/stable' into rust-fixes 2025-02-26 16:36:42 +01:00
include/inputtino feat: properly control MAC address generation 2025-08-15 21:10:23 +01:00
share/pkgconfig feat: added pkgconfig configuration 2025-01-11 16:53:52 +01:00
src fix(touch): don't reuse an active MT slot when placing a new finger 2026-07-10 23:09:43 -05:00
tests Merge pull request #42 from kmreisi/fix/pen-tablet-flaky-test 2026-07-13 09:33:25 +01:00
.clang-format feat: ported code over from Wolf 2024-02-09 20:40:17 +00:00
.clang-tidy feat: ported code over from Wolf 2024-02-09 20:40:17 +00:00
.dockerignore feat: update Docker configuration and clean up .dockerignore 2025-02-12 10:41:24 +00:00
.gitignore feat: ported code over from Wolf 2024-02-09 20:40:17 +00:00
CMakeLists.txt feat: implemented basic uinput PS joypad and toggle in the Cmake options 2025-07-08 14:49:27 +01:00
LICENSE feat: ported code over from Wolf 2024-02-09 20:40:17 +00:00
README.md feat: updated README 2025-03-24 20:15:13 +00:00

inputtino

An easy to use virtual input library for Linux built on top of uinput, evdev and uhid.
Currently in use by Wolf, Sunshine and Moonshine

Supports:

  • Keyboard
  • Mouse
  • Touchscreen
  • Trackpad
  • Pen tablet
  • Joypad
    • Correctly emulates Xbox, PS5 or Nintendo joypads
    • Supports callbacks on Rumble events
    • Gyro, Acceleration, Touchpad, Adaptive triggers, LED and battery status fully supported when creating a virtual DualSense joypad (with full support without Steam Input for games that are compatible with DualSense)

Interested in how the joypad works under the hood? Checkout these blog posts:

A special thanks goes to @hgaiser for all the help in yak shaving the DualSense implementation.

Include in a C++ project

If using Cmake it's as simple as

FetchContent_Declare(
        inputtino
        GIT_REPOSITORY https://github.com/games-on-whales/inputtino.git
        GIT_TAG <GIT_SHA_OR_TAG>)
FetchContent_MakeAvailable(inputtino)
target_link_libraries(<your_project_name> PUBLIC inputtino::libinputtino)

Example usage

#include <inputtino/input.hpp>

auto joypad = Joypad::create(Joypad::PS, Joypad::RUMBLE | Joypad::ANALOG_TRIGGERS);

joypad->set_stick(Joypad::LS, 1000, 2000);
joypad->set_pressed_buttons(Joypad::X | Joypad::DPAD_RIGHT);

auto rumble_data = std::make_shared<std::pair<int, int>>();
joypad.set_on_rumble([rumble_data](int low_freq, int high_freq) {
    rumble_data->first = low_freq;
    rumble_data->second = high_freq;
});

For more examples you can look at the unit tests under tests/: Joypads have been tested using SDL2 other input devices have been tested with libinput.

The main interface is easily accessible under include/inputtino/input.hpp

Using the Python bindings

Checkout the instructions in bindings/python/; example usage:

from inputtino import Mouse, MouseButton

# Initialize mouse device
mouse = Mouse()

# Move mouse
mouse.move(100, 50)  # Move right 100, down 50
mouse.move_abs(500, 300, 1920, 1080)  # Move to absolute position

# Click operations
mouse.click(MouseButton.LEFT)
mouse.click(MouseButton.RIGHT, duration=0.5)  # Hold for 0.5 seconds

# Scrolling
mouse.scroll_vertical(120)  # Scroll up
mouse.scroll_horizontal(-120)  # Scroll left

Using the Rust bindings

After building and installing inputtino you can use the Rust bindings by adding the following to your Cargo.toml:

[dependencies]
inputtino = { git = "https://github.com/games-on-whales/inputtino.git", branch="stable" }

Example usage:

let device = DeviceDefinition::new(
        "Rusty Keyboard",
        0xAB,
        0xCD,
        0xEF,
        "Rusty Keyboard Phys",
        "Rusty Keyboard Uniq",
    );
let keyboard = Keyboard::new(&device).unwrap();

keyboard.press_key(0x41); // KEY_A
keyboard.release_key(0x41);

See the tests for more examples.