@limbusfoundation/winput
v2.0.0
Published
Native Windows input capture and injection for Node.js.
Maintainers
Readme
Winput
Native Windows input capture and injection for Node.js.
@limbusfoundation/winput provides a simple TypeScript API for listening to and controlling keyboard and mouse input through native Win32 APIs.
The native implementation is written in Rust and communicates with Windows through Win32 and N-API.
Windows only
Installation
npm install @limbusfoundation/winputBasic Usage
import { Winput } from "@limbusfoundation/winput";
const input = new Winput();
input.onAnyKeydown(event => {
console.log(event.key);
});
input.onClick(event => {
console.log(event.button, event.x, event.y);
});Keyboard
Listening
onAnyKeydown
Listen for every key press.
input.onAnyKeydown(event => {
console.log(event.key);
});onAnyKeyup
Listen for every key release.
input.onAnyKeyup(event => {
console.log(event.key);
});onKeydown
Listen for a specific key.
input.onKeydown("A", event => {
console.log(event.key);
});onKeyup
Listen for a specific key release.
input.onKeyup("A", event => {
console.log(event.key);
});Keyboard Event
interface WinputKeyEvent {
key: string;
state: "Pressed" | "Released";
modifiers: string;
}modifiers contains the currently active modifier keys.
Example:
ctrl
shift
alt
noneKeyboard Injection
keyDown(key)
Press and hold a key.
input.keyDown("A");Important: keyDown() does not release the key.
The key remains pressed until keyUp() is called.
input.keyDown("A");
// A is still pressed here.
input.keyUp("A");Always release keys that were manually pressed.
keyUp(key)
Release a previously pressed key.
input.keyUp("A");keyTap(key)
Press and release a key immediately.
input.keyTap("A");For normal single-key input, prefer keyTap() when you do not need to keep the key pressed.
Mouse
Listening
onMouseMove
Listen for mouse movement.
input.onMouseMove(event => {
console.log(event.x, event.y);
});onClick
Listen for mouse button presses.
input.onClick(event => {
console.log(event.button, event.x, event.y);
});onDoubleClick
Listen for double clicks.
input.onDoubleClick(event => {
console.log(event.button, event.x, event.y);
});onMouseScroll
Listen for mouse wheel events.
input.onMouseScroll(event => {
console.log(event.delta, event.x, event.y);
});Mouse Events
interface WinputClickEvent {
button: string;
x: number;
y: number;
}interface WinputMouseMoveEvent {
x: number;
y: number;
}interface WinputMouseScrollEvent {
delta: number;
x: number;
y: number;
}Mouse Injection
mouseMove(x, y, absolute)
Move the mouse.
Absolute position
When absolute is true, the coordinates represent a position on the screen.
input.mouseMove(500, 300, true);Relative movement
When absolute is false, the coordinates represent movement relative to the current cursor position.
input.mouseMove(100, 50, false);Mouse Buttons
The following buttons are supported:
left
right
middle
x1
x2mouseDown(button)
Press and hold a mouse button.
input.mouseDown("left");Important: mouseDown() does not release the button.
The button remains pressed until mouseUp() is called.
input.mouseDown("left");
// Left button is still pressed here.
input.mouseUp("left");Always pair a manual mouseDown() with a corresponding mouseUp().
mouseUp(button)
Release a mouse button.
input.mouseUp("left");click(button)
Perform a complete click.
input.click("left");Conceptually, this performs:
input.mouseDown("left");
input.mouseUp("left");Use click() when you want a normal click.
Use mouseDown() and mouseUp() separately when you need to control how long the button remains pressed.
scroll(delta)
Inject a mouse wheel event.
input.scroll(120);Positive and negative values represent opposite scroll directions.
Safe Usage
Winput can control real system input. Be careful when using manual press/release operations.
Always release manually pressed keys
Avoid:
input.keyDown("A");without a corresponding release.
Prefer:
input.keyDown("A");
try {
// Work while A is pressed.
} finally {
input.keyUp("A");
}This guarantees that the key is released even if an error occurs.
Always release manually pressed mouse buttons
Avoid:
input.mouseDown("middle");without a corresponding mouseUp().
Prefer:
input.mouseDown("middle");
try {
// Work while the button is pressed.
} finally {
input.mouseUp("middle");
}A forgotten mouseUp() can leave the button logically pressed by Windows.
This can make the mouse behave as if it is stuck or unresponsive.
Prefer click() for normal clicks
If you simply want to click a button, use:
input.click("left");instead of manually doing:
input.mouseDown("left");
input.mouseUp("left");Manual mouseDown() / mouseUp() should be used when the pressed state itself is important.
Complete Example
import { Winput } from "@limbusfoundation/winput";
const input = new Winput();
input.onAnyKeydown(event => {
console.log("[KEY DOWN]", event.key, event.modifiers);
});
input.onAnyKeyup(event => {
console.log("[KEY UP]", event.key, event.modifiers);
});
input.onClick(event => {
console.log("[CLICK]", event.button, event.x, event.y);
});
input.onDoubleClick(event => {
console.log("[DOUBLE CLICK]", event.button, event.x, event.y);
});
input.onMouseMove(event => {
console.log("[MOVE]", event.x, event.y);
});
input.onMouseScroll(event => {
console.log("[SCROLL]", event.delta, event.x, event.y);
});
input.keyTap("A");
input.click("left");
input.mouseMove(500, 300, true);
input.scroll(120);API
| Method | Description |
| --------------------------- | --------------------------------- |
| onAnyKeydown(callback) | Listen for all key presses |
| onAnyKeyup(callback) | Listen for all key releases |
| onKeydown(key, callback) | Listen for a specific key press |
| onKeyup(key, callback) | Listen for a specific key release |
| onMouseMove(callback) | Listen for mouse movement |
| onClick(callback) | Listen for mouse button presses |
| onDoubleClick(callback) | Listen for double clicks |
| onMouseScroll(callback) | Listen for mouse wheel events |
| onMouseDown(callback) | Listen for mouse button is pressed|
| onMouseUp(callback) | Listen for mouse button is release|
| keyDown(key) | Press and hold a key |
| keyUp(key) | Release a key |
| keyTap(key) | Press and release a key |
| mouseMove(x, y, absolute) | Move the cursor |
| mouseDown(button) | Press and hold a mouse button |
| mouseUp(button) | Release a mouse button |
| click(button) | Press and release a mouse button |
| scroll(delta) | Inject mouse wheel input |
Native Implementation
Winput uses:
TypeScript
↓
N-API
↓
Rust
↓
Win32
↓
WindowsKeyboard and mouse events are captured using native Windows low-level hooks, while input injection uses the Windows SendInput API.
No third-party input automation framework is required for the native input layer.
