---
winput is a lightweight, high-performance Go library for Windows background input automation.
It provides a unified, window-centric API that abstracts the underlying input mechanism, allowing seamless switching between standard Window Messages (PostMessage) and kernel-level injection (Interception driver).
- Pure Go (No CGO): Uses dynamic DLL loading. No GCC required for compilation.
- Window-Centric API: Operations are performed on
Windowobjects, not raw HWNDs. - Read Text from Controls: Use
Text()for standard Win32 controls andValue()for best-effort reads with UI Automation fallback on modern controls. - Background Input:
- Message Backend: Sends inputs directly to window message queues. Works without window focus or mouse cursor movement.
- HID Backend: Uses the Interception driver to simulate hardware input at the kernel level.
- Coordinate Management:
- Unified Client Coordinate system for all APIs.
- Built-in
ScreenToClient/ClientToScreenconversion. - DPI Awareness: Helpers for Per-Monitor DPI scaling.
- Safety & Reliability:
- Thread-Safe: Global input serialization ensures atomic operations (
inputMutex). - Explicit error returns (no silent failures).
- Type-safe Key definitions.
- Thread-Safe: Global input serialization ensures atomic operations (
- Keyboard Layout:
- The
KeyFromRuneandTypefunctions currently assume a US QWERTY keyboard layout.
- The
Ideal for applications where window handles are unreliable.
import ( "github.com/rpdg/winput" "github.com/rpdg/winput/screen" ) func main() { winput.EnablePerMonitorDPI() // 1. Capture the entire virtual desktop (all monitors) img, err := screen.CaptureVirtualDesktop() // Or capture a specific region: // img, err := screen.CaptureRegion(0, 0, 1920, 1080) if err != nil { panic(err) } // img is a standard *image.RGBA, ready for OpenCV/GoCV // 2. Perform your CV matching here (pseudo-code) // matchX, matchY := yourCVLib.Match(img, template) // 3. Convert image coordinates to virtual desktop coordinates targetX, targetY := screen.ImageToVirtual(int32(matchX), int32(matchY)) // 4. Move and Click winput.MoveMouseTo(targetX, targetY) winput.ClickMouseAt(targetX, targetY) }
- Mechanism: Uses
PostMessageW. - Pros: No focus required, no mouse movement, works in background.
- Cons:
- Modifier Keys:
PostMessagedoes not update global keyboard state. Apps checkingGetKeyState(e.g. for Ctrl+C) might fail.Window.PressHotkeyworks around this for modifier combinations by temporarily using foreground keyboard events, so those calls are not purely background operations. - UIPI: Cannot send messages to apps running as Administrator if your app is not.
- Coordinates: Limited to 16-bit signed integer range ([-32768, 32767]). Larger coordinates will be clipped.
- Compatibility: Some games (DirectX/OpenGL/RawInput) and frameworks (Qt/WPF) ignore these messages.
- Modifier Keys:
- Mechanism: Uses Interception driver (kernel-level).
- Context: Uses a global driver context (singleton). Safe for automation scripts, but be aware if integrating into larger apps.
- Pros: Works with almost everything (games, anti-cheat), undetectable as software input.
- Cons:
- Driver Required: Must install Interception driver.
- Blocking:
Moveoperations are synchronous and blocking (to simulate human speed). - Mouse Movement: Physically moves the cursor.
- Focus: Usually requires the window to be active/foreground.
go get github.com/rpdg/winput
This library is Pure Go and does not require CGO. To use the HID backend:
- Install the Interception driver.
- Place
interception.dllin your app directory, or specify its path:winput.SetHIDLibraryPath("libs/interception.dll") if err := winput.SetBackend(winput.BackendHID); err != nil { // Handle error (e.g. fallback to Message backend) panic(err) }
Ideal for standard windows (Notepad, etc.). Works in background. Tip: For some apps (like Notepad), you may need to find the child window (e.g., "Edit") to send text.
go run cmd/example/basic_message/main.go
For apps where HWND is unreliable (VS Code, Discord, Games). Uses absolute screen coordinates.
Tip: Use screen.ImageToVirtual(x, y) to convert OpenCV screenshot coordinates to winput coordinates.
go run cmd/example/global_vision/main.go
Simulates physical hardware input. Requires driver.
go run cmd/example/advanced_hid/main.go
package main import ( "log" "github.com/rpdg/winput" ) func main() { // 1. Find target window w, err := winput.FindByTitle("Untitled - Notepad") if err != nil { log.Fatal(err) } edit, err := w.FindChildByClass("Edit") if err != nil { log.Fatal(err) } // 2. Click (Left Button) if err := edit.Click(100, 100); err != nil { log.Fatal(err) } // 3. Type text edit.Type("Hello World") edit.Press(winput.KeyEnter) // 4. Read text from a standard child text control value, err := edit.Text() if err != nil { log.Fatal(err) } fmt.Println("Current text:", value) // 5. Global Input (Target independent) winput.Type("Hello Electron!") winput.Press(winput.KeyEnter) // 6. Using winput/screen (Boundary query) // import "github.com/rpdg/winput/screen" bounds := screen.VirtualBounds() fmt.Printf("Virtual Desktop Bounds: %d, %d\n", bounds.Right, bounds.Bottom) }
winput avoids silent failures. Common errors you should handle:
| Error Variable | Description | Handling |
|---|---|---|
ErrWindowNotFound |
Window not found by Title/Class/PID. | Check if the app is running or use FindByClass as fallback. |
ErrDriverNotInstalled |
Interception driver missing (HID mode only). | Prompt user to install the driver or fallback to Message backend. |
ErrDLLLoadFailed |
interception.dll not found or invalid. |
Check DLL path (SetHIDLibraryPath) or installation. |
ErrUnsupportedKey |
Character cannot be mapped to a key. | Check input string encoding or use raw KeyDown for special keys. |
ErrPermissionDenied |
Operation blocked (e.g., UIPI). | Run your application as Administrator. |
Example of robust error handling:
// SetBackend now fails fast if the driver or DLL is missing. if err := winput.SetBackend(winput.BackendHID); err != nil { log.Printf("HID backend not available: %v. Falling back to Message backend.", err) // No need to explicitly set BackendMessage, as it is the default. } // All subsequent calls will use the successfully set backend. if err := w.Click(100, 100); err != nil { log.Fatal(err) }
Modern Windows scales applications. To ensure your (100, 100) click lands on the correct pixel:
// Call this at program start if err := winput.EnablePerMonitorDPI(); err != nil { log.Printf("DPI Awareness failed: %v", err) } // Check window specific DPI (96 is standard 100%) dpi, _ := w.DPI() fmt.Printf("Target Window DPI: %d (Scale: %.2f%%) ", dpi, float64(dpi)/96.0*100)
Use HID for games/anti-cheat, fallback to Message for standard apps.
// Try to enable HID backend if err := winput.SetBackend(winput.BackendHID); err != nil { log.Println("HID init failed, using default Message backend:", err) // No action needed, default is already BackendMessage } w.Type("password") // Works with whatever backend is active
winput maps runes to Scan Codes (Set 1).
- Supported: A-Z, 0-9, Common Symbols (
!,@,#...), Space, Enter, Tab. - Auto-Shift:
Type("A")automatically sendsShift Down->a Down->a Up->Shift Up.
| Feature | winput (Go) | C# Interceptor Wrappers | Python winput (ctypes) |
|---|---|---|---|
| Backends | Dual (HID + Message) | HID (Interception) Only | Message (User32) Only |
| API Style | Object-Oriented (w.Click) |
Low-level (SendInput) |
Function-based |
| Dependency | None (Default) / Driver (HID) | Driver Required | None |
| Safety | Explicit Errors | Exceptions / Silent | Silent / Return Codes |
| DPI Aware | ✅ Yes | ❌ Manual calc needed | ❌ Manual calc needed |
- vs Python winput: Python's version is great for simple automation but lacks the kernel-level injection capability required for games or stubborn applications.
- vs C# Interceptor: Most C# wrappers expose the raw driver API.
winputabstracts this into high-level actions (Click, Type) and adds coordinate translation logic.
| Feature | robotgo | winput |
|---|---|---|
| Input Level | OS Synthetic (SendInput / Events) |
Kernel Driver (Interception) + OS Message |
| Background Control | ❌ Fails often | ✅ Native Support (PostMessage) |
| Anti-Cheat / Protected Apps | ❌ Blocked | ✅ Bypasses most protections (HID level) |
| Coordinate System | Implicit / Device-dependent | Explicit Virtual Desktop (DPI-aware) |
| Visual Integration | Basic | Engineered for OpenCV/OCR (Capture -> Map -> Input) |
| Cross-Platform | ✅ (Win/Mac/Linux) | ❌ (Windows Optimized) |
| Use Case | Quick scripts, simple GUI automation | Engineering-grade automation, Games, Electron, Background tasks |
Summary:
- Use robotgo for quick, cross-platform scripts where reliability in edge cases (games, background) is not critical.
- Use winput when you need determinism, driver-level control, or need to interact with background windows, games, or Electron apps that ignore standard input injection.
MIT