Mouse Keys in Hyprland!
Who wants to use the mouse anyways?
Will ideally, no one should need to use the mouse, however “modern” software sometimes forces you use the cancer known as the mouse.
Cirno hates your mouse usage! (Picture by Tad Fibnonacci)
Step by step…
While you could scroll to the bottom and find the juicy copyable snippet, why not iterate together?
One can use ydotool to automate the mouse movements like so, note that I prefer vim’s hjkl
input, and you might need to change your bindings, but the gist remains the same.
bind = $mainMod ctrl, h, exec, ydotool mousemove -- -40 0
bind = $mainMod ctrl, j, exec, ydotool mousemove -- 0 40
bind = $mainMod ctrl, k, exec, ydotool mousemove -- 0 -40
bind = $mainMod ctrl, l, exec, ydotool mousemove -- 40 0
bind = $mainMod ctrl, u, exec, ydotool click 0xC0 # left click
bind = $mainMod ctrl, i, exec, ydotool click 0xC2 # middle click
bind = $mainMod ctrl, o, exec, ydotool click 0xC1 # right click
Repetition when holding down the keys…
Now this works, but you need to constantly click to move the mouse, holding the button doesn’t repeatedly invoke the command.
This is easily solved by changing bind
to bindl
(refer to Hyprland documentation). We also don’t need the repetition with the clicks.
bindl = $mainMod ctrl, h, exec, ydotool mousemove -- -40 0
bindl = $mainMod ctrl, j, exec, ydotool mousemove -- 0 40
bindl = $mainMod ctrl, k, exec, ydotool mousemove -- 0 -40
bindl = $mainMod ctrl, l, exec, ydotool mousemove -- 40 0
bind = $mainMod ctrl, u, exec, ydotool click 0xC0 # left click
bind = $mainMod ctrl, i, exec, ydotool click 0xC2 # middle click
bind = $mainMod ctrl, o, exec, ydotool click 0xC1 # right click
Mouse Acceleration
Ok, this gets annoying to use after less than 5 seconds. Without acceleration this is unusable.
We can simply write a bash script to output a number (say 40
) and increase the value i.e., accelerate, if we repetitively invoke the function. If we don’t invoke it, it will reset back to the baseline of 40
.
$ bin/mouse_accel.sh
40
# wait between commands
$ bin/mouse_accel.sh; bin/mouse_accel.sh
40
60
# wait between commands
$ bin/mouse_accel.sh; bin/mouse_accel.sh; bin/mouse_accel.sh
40
60
80
# Note: Max speed is capped 200
I ChatGPT:
#!/bin/bash
STATE_FILE="/tmp/mouse_accel_state"
DEFAULT_SPEED=40
STEP=20
MAX_SPEED=200
TIME_THRESHOLD_MS=100
now_ms() {
date +%s%3N # current time in milliseconds
}
# Read previous state
if [[ -f "$STATE_FILE" ]]; then
read -r last_time last_speed < "$STATE_FILE"
else
last_time=0
last_speed=$DEFAULT_SPEED
fi
current_time=$(now_ms)
delta=$((current_time - last_time))
if (( delta <= TIME_THRESHOLD_MS )); then
# Accelerate
new_speed=$((last_speed + STEP))
[[ $new_speed -gt $MAX_SPEED ]] && new_speed=$MAX_SPEED
else
# Reset
new_speed=$DEFAULT_SPEED
fi
# Save new state
echo "$current_time $new_speed" > "$STATE_FILE"
# Output the new speed
echo "$new_speed"
And use it in my ydotool
!
bindl = $mainMod ctrl, h, exec, ydotool mousemove -- -$(~/bin/mouse_accel.sh) 0
bindl = $mainMod ctrl, j, exec, ydotool mousemove -- 0 $(~/bin/mouse_accel.sh)
bindl = $mainMod ctrl, k, exec, ydotool mousemove -- 0 -$(~/bin/mouse_accel.sh)
bindl = $mainMod ctrl, l, exec, ydotool mousemove -- $(~/bin/mouse_accel.sh) 0
bind = $mainMod ctrl, u, exec, ydotool click 0xC0 # left click
bind = $mainMod ctrl, i, exec, ydotool click 0xC2 # middle click
bind = $mainMod ctrl, o, exec, ydotool click 0xC1 # right click
That’s all! Best of luck with your ricing :3