aboutsummaryrefslogtreecommitdiff

mouseboard

Keyboard-driven virtual pointer for Wayland and Windows. Bring up a labelled grid over the screen, type a label to jump to a cell, refine the spot by bisection, then press one key to click. No mouse, no daemon.

What it does

Run mouseboard (bound to a hotkey) and a grid is drawn over every monitor:

  1. Grid Type the two-or-so letter label in a cell to jump there.
  2. Refine The cell becomes the active region. Split it by quadrant with u/i/j/k until the crosshair sits exactly where you want; the pointer tracks the region centre live. Backspace undoes a split.
  3. Click m left, , middle, . right, ; double, v drag. Esc cancels.

Bisection gives unlimited precision in a few keystrokes, so the coarse grid can stay coarse and the labels short.

Requirements

Linux: a wlroots-based compositor (sway, Hyprland, river, Wayfire, labwc, ...) implementing wlr-layer-shell and wlr-virtual-pointer. GNOME and KDE are not supported yet (see Portability). A shipped static binary needs nothing else.

Windows: Windows 10 1703 or newer (per-monitor DPI v2). The shipped .exe is static and needs nothing else.

Build and install

The Wayland protocols are vendored under proto/, so a build needs only a toolchain. The release build is static: provision its dependencies once, then build and install.

./provision-static.sh    # once per machine: static wayland/xkbcommon/ffi
                         # archives (pinned, checksummed) into musl-sysroot/
make static              # -> ./mouseboard, one static binary
sudo make install

The result is self-contained, already stripped, and runs on any Linux.

Besides a C compiler, make and pkg-config, provisioning needs meson, ninja, bison, expat, curl and the Linux kernel headers - plus a musl toolchain on a glibc distro (Debian, Arch). It builds its own wayland-scanner from source, so the host's version does not matter. On musl-native distros (Alpine, Void-musl) gcc is already musl and provision-static.sh uses it automatically; set CC only to override the detected compiler.

These commands install enough for both Linux builds:

# Debian / Ubuntu
sudo apt install build-essential pkgconf libwayland-bin libwayland-dev \
    libxkbcommon-dev meson ninja-build bison curl musl-tools libexpat1-dev

# Arch
sudo pacman -S --needed base-devel wayland libxkbcommon meson ninja bison \
    curl linux-api-headers musl expat

# Alpine  (musl-native: gcc is already musl, detected automatically)
sudo apk add build-base pkgconf wayland-dev libxkbcommon-dev meson samurai \
    bison curl linux-headers expat-dev

# Void  (use the musl flavour: gcc is already musl, detected automatically)
sudo xbps-install -S base-devel pkgconf wayland-devel libxkbcommon-devel \
    meson ninja bison curl expat-devel

# Gentoo  (gcc/make/pkg-config already in @system)
sudo emerge --ask dev-libs/wayland x11-libs/libxkbcommon dev-libs/expat \
    meson ninja sys-devel/bison net-misc/curl sys-kernel/linux-headers

Windows build

The .exe is cross-built from Linux with a mingw-w64 toolchain (native mingw on Windows builds the same way). It links only gdi32/user32, so there are no other libraries:

# Debian / Ubuntu
sudo apt install gcc-mingw-w64-x86-64 make

# Arch
sudo pacman -S --needed mingw-w64-gcc make

# Fedora
sudo dnf install mingw64-gcc make

make -f Makefile.win              # -> mouseboard.exe

Copy the result to the Windows machine and run it; there is nothing to install.

Developing (dynamic build)

A plain make links against the system's shared libraries, so it needs no provisioning - only wayland-scanner (it ships with the Wayland package) plus the wayland-client, xkbcommon and Linux kernel development headers:

make                         # dev build; produces ./mouseboard
make check                   # dependency-free core and state-machine tests

If anything is missing it tells you exactly what to install. make static cleans first (the modes use different compilers); run make clean when switching back.

Usage

Wayland does not let a client grab a global hotkey, so bind the command in your compositor. One binding runs the whole flow; the final key decides the button.

sway (~/.config/sway/config):

bindsym $mod+g exec mouseboard

Hyprland (~/.config/hypr/hyprland.conf):

bind = SUPER, G, exec, mouseboard

Windows: run mouseboard.exe directly, or bind it to a hotkey with a shortcut or a tool such as AutoHotkey. It grabs the keyboard while the grid is up, so keys do not leak to the focused window; Esc cancels.

Try it without clicking anything; it prints the target and action instead:

mouseboard --dry-run

Keys

Defaults; all are configurable (see Configuration).

label chars   f j d k s l a g h r u e i w o q p t y v b c n x m z
refine        u top-left  i top-right  j bottom-left  k bottom-right
click         m left   , middle   . right   ; double   v drag
Enter         left click (once a cell is selected)
Backspace     undo last split (or return to the grid)
Esc           cancel

Drag is two targets: press v over the start, then pick the end the same way (grid, refine) and press any click key to release.

Configuration

Optional file at $XDG_CONFIG_HOME/mouseboard/config (default ~/.config/mouseboard/config; on Windows %APPDATA%\mouseboard\config). Lines are key = value; lines starting with # are comments. Command-line flags override the file. See config.example for every key with its default. Colours are #RRGGBB or #RRGGBBAA. Two opacities (0..100): opacity_bg dims the desktop (default 33; 100 is solid) and opacity_fg sets how strong the labels, grid and crosshair are (default 65).

How to debug

mouseboard --dry-run     print "x y action" instead of moving the pointer
mouseboard --selftest    run offline checks of labels/bisection/config
WAYLAND_DEBUG=1 mouseboard --dry-run   trace every protocol message

If it exits with "compositor lacks ...", the compositor does not implement a required wlroots protocol and is not supported. If labels do not appear, confirm the binding actually launched mouseboard (run it from a terminal to see errors).

Portability

The core (grid, labels, bisection, rendering, config) talks only to the backend interface in platform.h and never includes an OS header. A backend is one file providing platform_init(), and exactly one is linked into the binary.

The wlroots Wayland backend uses layer-shell for the overlay and virtual-pointer for input. The Win32 backend draws a per-monitor layered overlay with UpdateLayeredWindow, grabs the keyboard with a low-level hook, and clicks via SendInput. It is a GUI-subsystem binary, so a hotkey launch shows no console; it attaches to a parent console when run from a terminal, so --dry-run and --help still print.

Credits

mouseboard is released under the MIT licence; see LICENSE. It bundles third-party files, each kept under its own terms:

  • font8x8_basic.h: 8x8 bitmap font by Daniel Hepper and Marcel Sondaar / IBM, public domain.
  • proto/*.xml: Wayland protocol descriptions from wayland-protocols and wlr-protocols, MIT/Expat. Per-file provenance is in proto/SOURCES.