A Wayland virtual-pointer daemon and CLI client, written in Zig 0.16.
Emits pointer events (motion, scroll, button, click) on wlroots-based
compositors via the zwlr_virtual_pointer_v1 protocol. A long-running
daemon binds a Unix datagram socket; a short-lived CLI sends commands.
This is a Zig port of wlptrctl (Rust). The two
can coexist — they use different socket names.
- Zig 0.16.0
libwayland-clientandwayland-scanner(Arch:wayland)- A wlroots compositor (sway, Hyprland, river, ...)
zig build
zig build test
The binary lands at zig-out/bin/wlptrctl.
wlptrctl daemon
wlptrctl move <dx> <dy>
wlptrctl scroll <vertical> <horizontal>
wlptrctl button <left|right|middle|NUM> <press|release|click>
Run the daemon in one terminal, then send commands from another:
wlptrctl move 100 0
wlptrctl scroll 1 0
wlptrctl button left click
wlptrctl button 274 press
wlptrctl button 274 release
SIGINT/SIGTERM shuts the daemon down and removes the socket.
The daemon listens on $XDG_RUNTIME_DIR/wlptrctl-zig.sock (AF_UNIX,
SOCK_DGRAM). Each datagram is a fixed-size little-endian frame:
| Command | Layout | Size |
|---|---|---|
| Scroll | 0x00 i32 vertical i32 horizontal |
9 |
| Motion | 0x01 i32 dx i32 dy |
9 |
| Button | 0x02 u32 button u32 state |
9 |
| Click | 0x03 u32 button |
5 |
state is 0 (released) or 1 (pressed). Button numbers follow Linux
input event codes (left=0x110, right=0x111, middle=0x112).
build.zig wayland-scanner + link wayland-client
protocols/ vendored wlr-virtual-pointer XML
src/main.zig entry point
src/cli.zig arg parsing
src/ipc.zig wire format + socket path
src/client.zig sendto over AF_UNIX/SOCK_DGRAM
src/daemon.zig bind, signal handling, recv loop
src/wayland.zig @cImport wrapper, Pointer emit functions