https://github.com/gurkenlabs/input4j
Input4j ๐ฎ The pure java input library. Cross-plattform, high performance, future proof
https://github.com/gurkenlabs/input4j
cross-platform dependency-free directinput evdev ffm-api foreign-function-and-memory-api input iokit java jni-alternative linux macos panama performance polling rumble windows xinput
Last synced: 11 days ago
JSON representation
Input4j ๐ฎ The pure java input library. Cross-plattform, high performance, future proof
- Host: GitHub
- URL: https://github.com/gurkenlabs/input4j
- Owner: gurkenlabs
- License: mit
- Created: 2023-02-11T09:36:06.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2026-03-02T21:43:19.000Z (15 days ago)
- Last Synced: 2026-03-02T22:55:56.411Z (15 days ago)
- Topics: cross-platform, dependency-free, directinput, evdev, ffm-api, foreign-function-and-memory-api, input, iokit, java, jni-alternative, linux, macos, panama, performance, polling, rumble, windows, xinput
- Language: Java
- Homepage: https://gurkenlabs.github.io/input4j/
- Size: 619 KB
- Stars: 12
- Watchers: 1
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# ๐ฎ Input4j - The pure Java input library
[](https://search.maven.org/artifact/de.gurkenlabs/input4j)
[](https://github.com/gurkenlabs/input4j/actions)
[](LICENSE)
[]()
**Input4j** is a modern Java input library built on the **Foreign Function & Memory API (FFM)**.
It provides fast, cross-platform controller and gamepad input without requiring JNI or native binaries.
## ๐ Features
- ๐ฎ Game controller input support
- โก Native performance via Java FFM API
- ๐งฉ No JNI required
- ๐ฅ Cross-platform (Windows / Linux / macOS)
- ๐ฆ Available on Maven Central
- ๐งช Lightweight and dependency-free
## Why input4j?
- **Cross-Platform Input handling**: Fully compatible with Windows, Linux, and OSX.
- **Performance**: Optimized for high performance with minimal overhead.
- **Flexible Input Handling**: Supports both polling and event-based input mechanisms.
- **Simplicity**: Easy to integrate and use with straightforward APIs.
- **Future-Proof**: Built on the latest Java technologies, ensuring long-term support and compatibility.
### ๐ Advantages over traditional java input libraries
Input4j offers several advantages over traditional libraries like JInput by leveraging the new Foreign Function & Memory API (FFM API) instead of using Java Native Interface (JNI).
It is a more modern and efficient JNI alternative and an easy way to interact with native input libraries, providing the following benefits:
- No Native Artifacts & No Dependencies: Direct interaction with native libraries without the need for additional native artifacts simplifies the build and deployment process.
- Performance: Based on the FFM API, this library reduces the overhead associated with native calls, resulting in significantly faster performance then Java JNI.
- Safety: Safer memory management and access patterns reduce the risk of memory leaks and buffer overflows.
- Ease of Use: A more straightforward and modern API makes it easier to write and maintain code.
- Future-Proof: Built on the latest Java technologies, ensuring long-term support and compatibility with future Java versions.
## ๐ฆ๏ธ Installation
### Gradle
Add the following dependency to your `build.gradle` file to start using Input4j:
```groovy
dependencies {
implementation 'de.gurkenlabs:input4j:1.0.0'
}
```
### Maven
```xml
de.gurkenlabs
input4j
1.0.0
```
## ๐ป Quick start guide
### Manually Polling and Reading Input Data
```java
try (var inputDevices = InputDevices.init()) {
while (!inputDevices.getAll().isEmpty()) {
// iterate all available input devices and poll their data every second
for (var inputDevice : inputDevices.getAll()) {
inputDevice.poll();
System.out.println(inputDevice.getInstanceName() + ":" + inputDevice.getComponents());
}
Thread.sleep(1000);
}
}
```
### Event-Based Input Handling
```java
try (var devices = InputDevices.init()) {
var device = devices.getAll().stream().findFirst().orElse(null);
if (device == null) {
System.out.println("No input devices found.");
return;
}
device.onInputValueChanged(e -> System.out.println("Value changed: " + e.component() + " -> " + e.newValue()));
device.onButtonPressed(XInput.X, () -> System.out.println("X button pressed"));
device.onAxisChanged(Axis.AXIS_X, value -> System.out.println("X axis: " + value));
// simulate external polling loop
while (true) {
device.poll();
Thread.sleep(1000);
}
}
```
### Used By
input4j is the input system used by the
[LITIENGINE](https://litiengine.com) Java game engine.
## ๐ Technical Details
### Platform-Specific Input APIs
- **Windows: DirectInput โ
**
- Full implementation using `dinput.h`
- Supports legacy and modern input devices
- **Windows: XInput โ
**
- Modern gamepad support via `xinput.h`
- Xbox controller compatibility
- **Linux: evdev โ
**
- Event interface via `/dev/input`
- **macOS: IOKit โ
**
- HID device provisioning via `IOHIDManager`
### System Requirements
- Java Runtime: 22+
### Linux Permissions
On Linux, Input4j uses the modern **evdev** API (`/dev/input/event*`) which provides detailed input information. This is the same approach used by SDL2 and other modern gamepad libraries.
The `/dev/input/event*` devices are owned by `root:input` with restricted access (640).
**Quick fix - Add user to input group:**
```bash
sudo usermod -a -G input $USER
# Log out and log back in for changes to take effect
```
**Permanent solution - Create udev rules:**
Create `/etc/udev/rules.d/99-input4j.rules`:
```rules
SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="1", MODE="0666"
```
Then reload the rules:
```bash
sudo udevadm control --reload-rules
# Reconnect your gamepad
```
**Verify your setup:**
```bash
# Check device permissions
ls -la /dev/input/event*
# Check if user is in input group
getent group input
```
> **Note:** Input4j uses the modern evdev API (`/dev/input/event*`) rather than the legacy joystick API (`/dev/input/js*`). Both require the same permissions, but evdev provides more detailed input information. This is the standard approach used by SDL2 and other modern Linux input libraries.