Skip to content

Instantly share code, notes, and snippets.

@tropical32
Last active September 14, 2024 15:49
Show Gist options
  • Save tropical32/c66823887f8f902b71403507979f5bf8 to your computer and use it in GitHub Desktop.
Save tropical32/c66823887f8f902b71403507979f5bf8 to your computer and use it in GitHub Desktop.
This acceleration profile aims to slow down the mouse acceleration for small movements for extra precision.
#!/usr/bin/env python3
# based on https://gist.github.com/fufexan/de2099bc3086f3a6c83d61fc1fcc06c9
import struct
import os
import sys
import math
# ===== PARAMETERS =====
# set according to your device:
device_dpi = 2048 * 1.5 # mouse dpi
screen_dpi = 163
screen_scaling_factor = 1
sample_point_count = 20
sensitivity_factor = 6
def sigmoid(x, a=1.0):
return 1 / (1 + math.exp(-a * (x - 0.5)))
def find_arg(arg):
for i in sys.argv:
if i == arg:
return True
return False
def float16x16(num):
return struct.unpack('<i', num[:-4])[0] / int(0xffff)
if find_arg("help") or find_arg("-h") or find_arg("--help") or find_arg("h"):
print(f'{sys.argv[0]} <device>')
print('To get the device, run `hyprctl devices` and get its name')
exit(0)
# Make sure the device is passed as the first argument
if len(sys.argv) < 2:
print("Error: device not specified. Usage: <script> <device>")
exit(1)
# The first argument is treated as the device
device = sys.argv[1]
scale_x = device_dpi / 1e3
scale_y = screen_dpi / 1e3 / screen_scaling_factor * sensitivity_factor
X = [
b'\x00\x00\x00\x00\x00\x00\x00\x00',
b'\x15\x6e\x00\x00\x00\x00\x00\x00',
b'\x00\x40\x01\x00\x00\x00\x00\x00',
b'\x29\xdc\x03\x00\x00\x00\x00\x00',
b'\x00\x00\x28\x00\x00\x00\x00\x00',
]
Y = [
b'\x00\x00\x00\x00\x00\x00\x00\x00',
b'\xfd\x11\x01\x00\x00\x00\x00\x00',
b'\x00\x24\x04\x00\x00\x00\x00\x00',
b'\x00\xfc\x12\x00\x00\x00\x00\x00',
b'\x00\xc0\xbb\x01\x00\x00\x00\x00',
]
windows_points = [[float16x16(x), float16x16(y)] for x, y in zip(X, Y)]
points = [[x * scale_x, y * scale_y] for x, y in windows_points]
def find2points(x):
i = 0
while i < len(points) - 2 and x >= points[i + 1][0]:
i += 1
assert -1e6 + points[i][0] <= x <= points[i + 1][0] + 1e6, f'{points[i][0]} <= {x} <= {points[i + 1][0]}'
return points[i], points[i + 1]
def interpolate(x):
(x0, y0), (x1, y1) = find2points(x)
factor = sigmoid(x) # This smoothly adjusts based on x
y = factor * ((x - x0) * y1 + (x1 - x) * y0) / (x1 - x0)
return y
def sample_points(count):
last_point = -2
max_x = points[last_point][0]
step = max_x / (count + last_point) # we need another point for 0
sample_points_x = [si * step for si in range(count)]
sample_points_y = [interpolate(x) for x in sample_points_x]
return sample_points_x, sample_points_y
sample_points_x, sample_points_y = sample_points(sample_point_count)
step = sample_points_x[1] - sample_points_x[0]
sample_points_str = " ".join(["%.3f" % number for number in sample_points_y])
print(f'\tPoints: {sample_points_str}')
print(f'\tStep size: {step:0.10f}')
def hyprctl(device, option, arg):
os.system(f"hyprctl keyword 'device[{device}]:{option}' '{arg}'")
# Apply settings for the specified device
print(f'Setting device:\'{device}\':accel_profile using hyprctl')
hyprctl(device, 'accel_profile', f'custom {step} {sample_points_str}')

Usage:

~$ hyprctl devices
mice:
	Mouse at 56d69bc64e70:
		hid-1bcf:08a0-mouse
			default speed: 0.00000
			
~$ python accel.py hid-1bcf:08a0-mouse                                                              
	Points: 0.000 0.282 0.724 1.488 2.337 3.203 4.123 5.359 6.583 7.798 9.004 10.205 11.403 12.599 13.794 14.987 16.181 17.374 18.567 21.032
	Step size: 0.6587834897
hid-1bcf:08a0-mouse
Setting device:'hid-1bcf:08a0-mouse':accel_profile using hyprctl
ok

hyprland.conf (optional)

exec = python ~/accel.py hid-1bcf:08a0-mouse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment