Repository navigation
v93
New features and improvements
-
The indicator animates: when the indicator changes, it now eases into the new one instead of jumping to it. Sizes, thicknesses, opacities, blur radiuses, offsets and fill percents are interpolated, and the polygon morphs two edges at a time. Everything with no meaningful in-between — the colors, the label, the position — switches instead, at the start of the transition or at its end, as
transition-animation-switch-atsays. The animation belongs to the indicator being transitioned to, so each direction picks its own duration and easing:normal-mode.indicator.size=26 | _{ismousepressing} -> 39 normal-mode.indicator.transition-animation-duration-millis=200 | _{ismousepressing} -> 50 normal-mode.indicator.transition-animation-easing=smootherstep normal-mode.indicator.transition-animation-switch-at=end | _{ismousepressing} -> start
Above, a click grows the indicator and colors it in 50ms, and releasing takes 200ms to shrink back, keeping the color until it has. A change that interrupts a running animation eases from where it had reached, so nothing snaps. Every shipped configuration now animates a click: the indicator fills solid in the button's color, bursts outward into a ring, then eases back. The animation currently looks like this:
2026-08-21-uWOfAWRmZH.mp4
-
The mouse states are built-in virtual keys:
indicator.<state>.<property>is gone. Any property, and any combo, can branch onismoving,iswheeling,ismousepressing,isleftmousepressing,ismiddlemousepressing,isrightmousepressing,isunhandledkeypressingandisidling, which now means the mouse alone: not moving, not wheeling, no button pressed.normal-mode.indicator.color=#FF0000 | _{iswheeling} -> #FFFF00 | _{ismousepressing} -> #00FF00
The old per-state lines still load, with a warning:
idlebecomes the property's default value and every other state a branch on its key. -
A screen filter reads as a key: outside hint properties, a filter such as
_{300%}or_{3840x2160-150%}is a key mousemaster presses while the active screen matches it, so any property, command or mode switch can branch on it, and it can share a block with a real key. On a hint property it keeps its own meaning: there it selects the screens a value is drawn on, since one hint mesh can span several.grid-mode.grid.line-thickness=1 | _{300%} -> 0.66667 normal-mode.press.left=_{3840x2160-300%} +leftbutton
-
A mode can extend several modes:
normal-mode=_indicator-mode _clipboard-mode. The mode's own properties come first, then each parent in turn, and the first one to define a property keeps it. -
A virtual key is declared on its own line:
virtual-key.iszoom=released,virtual-key.showkeys=pressed, so the declaration can sit next to the macros that press the key. Thevirtual-keys=list still loads, with a warning. -
Key logging:
logging.redact-keysbecomeslogging.key-redaction=none(the default),pseudonymizeoranonymize.pseudonymizelogs a key that types a character askey#1, a name stable for that run only, so a press and its release still match and a key that was never released is still visible, without the log spelling out what was typed.log-last-key-events-on-exit=truelogs the last key events in combo syntax, with the milliseconds between them ([+a-377 -a-32 +leftwin]); they are always logged when a stuck key is detected. Both are there to report a combo that stopped working without leavinglogging.level=TRACEon. -
Fixes: A completed combo no longer runs its command a second time without a new key event. A hint grid opened with no previous selection is centered on the screen, like the zoom already was. A decoration covering the whole hint grid is centered on the grid instead of on the part one screen shows. The zoom and a selected hint now cope with a point that falls outside every screen. A hint label's shadow is blurred over its glyphs rather than over its whole cell. A Windows key event is identified by its virtual key in addition to its scan code, so an extended key such as volume up is no longer taken for the letter that shares its scan code. mousemaster reloads the system cursors at startup, repairing the cursor a killed run left behind. On macOS, a jump to an odd pixel no longer pins the mouse on a Retina screen.
-
Also: A property cycle is now reported as an error instead of silently dropping the properties in it. Less work is done per key press, per screen enumeration and per indicator render. The download is smaller: the unused Qt plugins are gone, the remaining libraries are embedded compressed, and the macOS bundle is trimmed. The author configuration and its documentation were rewritten, and neru's hint mode now moves the mouse as a hint is typed.
Installation on Windows
- Download mousemaster.exe (a portable executable).
- Download one of the existing configuration files:
- neo-mousekeys-ijkl.properties (recommended): an IJKL configuration (see documentation)
- neru.properties: a recursive hint configuration (see documentation)
- neo-mousekeys-wasd.properties: a WASD configuration (see documentation)
- warpd.properties: an HKJL configuration (see documentation)
- mouseable.properties: another HKJL configuration (see documentation)
- author.properties: an IJKL configuration designed to control everything with the right hand only (see documentation)
- Place the executable and the configuration file in the same directory.
- Rename the configuration file to mousemaster.properties.
- Run mousemaster.exe: make sure to run it as administrator if you want the mousemaster overlay to be displayed on top of everything else.
- Feel free to open a GitHub Issue or join the Discord if you need help creating your own configuration. If you have ideas for a better configuration that you would like to share, I'd love to hear from you.
- If you enjoy mousemaster, consider making a donation or stop by the Discord to show your support!
Installation on macOS
mousemaster reads the keyboard through the Karabiner virtual HID device, so that driver and a few permissions are needed.
- Install Karabiner-Elements, which installs the virtual HID device, and allow its system extension when macOS asks.
- Download and unzip mousemaster-macos.zip, then put mousemaster.app in /Applications.
- mousemaster is not signed or notarized, and macOS refuses to start a quarantined app that is not notarized. A browser download marks it as quarantined, so clear that before the first launch:
xattr -dr com.apple.quarantine /Applications/mousemaster.app. Or let macOS refuse it once, then allow it under System Settings > Privacy & Security > Security, where an Open Anyway button appears for it. - Download one of the configuration files above, place it in /Applications next to mousemaster.app, and rename it to mousemaster.properties.
- Run it from a terminal, as root, which the virtual HID device requires. The configuration is read from the working directory, so start it from where you put it:
cd /Applications && sudo mousemaster.app/Contents/MacOS/mousemaster - Grant the permissions macOS asks for, under System Settings > Privacy & Security, then quit and relaunch:
- Input Monitoring, to read the keys you press. Always needed.
- Accessibility, only for UI hints (
hint.type=ui). - Screen Recording, only for zoom (
mode.zoom).
License
mousemaster.exe and mousemaster.app embed Qt and QtJambi, used under the GNU Lesser General Public License. Run mousemaster with --licenses for the third-party notices and the full license texts.