]> Freerunner's - dotfiles.git/commitdiff
hypr: custom mouse acceleration
authorAndre Ramnitz <tux.rising@gmail.com>
Mon, 26 Aug 2024 10:56:36 +0000 (12:56 +0200)
committerAndre Ramnitz <tux.rising@gmail.com>
Mon, 26 Aug 2024 13:52:01 +0000 (15:52 +0200)
config/hypr/hyprland.conf
local/bin/accel.py [new file with mode: 0755]

index 2f0d3dfc9fd7f96c26300befdc3020d18e29a6d2..3a7ffc337bbd02bcc8999f2df90d2a63a4e08df8 100644 (file)
@@ -38,10 +38,10 @@ env = SDL_VIDEODRIVER,wayland # remove or set to x11 for games providing older v
 # env = WLR_DRM_NO_ATOMIC,0
 
 # set cursor
-env = XCURSOR_THEME,breeze
-env = XCURSOR_SIZE,30
-env = HYPRCURSOR_THEME,Bibata-Modern-Amber
-env = HYPRCURSOR_SIZE,30
+env = XCURSOR_THEME,BreezeX-Black
+env = XCURSOR_SIZE,40
+env = HYPRCURSOR_THEME,rose-pine-hyprcursors
+env = HYPRCURSOR_SIZE,40
 
 # Execute your favorite apps at launch
 exec-once = hyprpm enable hyprbars
@@ -159,9 +159,11 @@ misc {
 
 # Example per-device config
 # See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
-# device:epic-mouse-v1 {
-#     sensitivity = -0.5
-# }
+device {
+    name = razer-razer-basilisk-v3
+    sensitivity = 0
+    accel_profile = custom 0.3431164009 0.000 0.291 0.582 1.019 1.456 1.894 2.370 3.035 3.700 4.364 5.029 5.694 6.358 7.023 7.688 8.353 9.017 9.682 10.347 11.720
+}
 
 group {
        insert_after_current = false
diff --git a/local/bin/accel.py b/local/bin/accel.py
new file mode 100755 (executable)
index 0000000..a78d2ca
--- /dev/null
@@ -0,0 +1,153 @@
+#!/usr/bin/env python3
+
+# original at https://gist.github.com/yinonburgansky/7be4d0489a0df8c06a923240b8eb0191
+# modified for ease of use in Hyprland
+
+# calculation are based on http://www.esreality.com/index.php?a=post&id=1945096
+# assuming windows 10 uses the same calculation as windows 7.
+# guesses have been made calculation is not accurate
+# touchpad users make sure your touchpad is calibrated with `sudo libinput measure touchpad-size`
+# import matplotlib.pyplot as plt
+import struct
+import os
+import sys
+
+# set according to your device:
+device_dpi = 1600 # mouse dpi
+screen_dpi = 109
+screen_scaling_factor = 1
+sample_point_count = 20 # should be enough but you can try to increase for accuracy of windows function
+sensitivity_factor = 5
+# sensitivity factor translation table: (windows slider notches)
+# 1 = 0.1
+# 2 = 0.2
+# 3 = 0.4
+# 4 = 0.6
+# 5 = 0.8
+# 6 = 1.0 default
+# 7 = 1.2
+# 8 = 1.4
+# 9 = 1.6
+# 10 = 1.8
+# 11 = 2.0
+
+def findArg(arg):
+    for i in sys.argv:
+        if i == arg:
+            return True
+
+    return False
+
+
+if findArg("help") or findArg("-h") or findArg("--help"):
+    print(f'{sys.argv[0]} [[accel_device] [scroll_points] device=<device>]')
+    print('To get the device, run `hyprctl devices`')
+    exit(0)
+
+# TODO: find accurate formulas for scale x and scale y
+# mouse speed: inch/s to device-units/millisecond
+scale_x = device_dpi / 1e3
+# pointer speed: inch/s to screen pixels/millisecond
+scale_y =  screen_dpi / 1e3 / screen_scaling_factor * sensitivity_factor
+
+print(f'scale_x={scale_x}, scale_y={scale_y}')
+
+
+def float16x16(num):
+    return struct.unpack('<i', num[:-4])[0] / int(0xffff)
+
+# windows 10 registry values:
+# HKEY_CURRENT_USER\Control Panel\Mouse\SmoothMouseXCurve
+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',
+]
+# HKEY_CURRENT_USER\Control Panel\Mouse\SmoothMouseYCurve
+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)]
+
+print('Windows original points:')
+for point in windows_points:
+    print(point)
+
+# scale windows points according to device config
+points = [[x * scale_x, y * scale_y] for x, y in windows_points]
+
+print('Windows scaled points')
+for point in points:
+    print(point)
+
+
+# plt.plot(*list(zip(*windows_points)), label=f'windows points')
+# plt.plot(*list(zip(*points)), label=f'scaled points')
+# plt.xlabel('device-speed')
+# plt.ylabel('pointer-speed')
+# plt.legend(loc='best')
+# plt.show()
+# exit()
+
+def getDevice():
+    for i in sys.argv:
+        if str(i).startswith('device='):
+            print(str(i)[7::])
+            return str(i)[7::]
+
+
+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)
+    y = ((x-x0)*y1+(x1-x)*y0)/(x1-x0)
+    return y
+
+
+def sample_points(count):
+    # use linear extrapolation for last point to get better accuracy for lower points
+    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]
+
+# plt.plot(sample_points_x, sample_points_y, label=f'windows {sample_point_count} points')
+# plt.plot(*sample_points(1024), label=f'windows 1024 points')
+# plt.xlabel('device-speed')
+# plt.ylabel('pointer-speed')
+# plt.legend(loc='best')
+# plt.show()
+# exit()
+
+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}')
+
+if (findArg("accel_profile")):
+    device = getDevice()
+    print(f'Setting device:\'{device}\':accel_profile using hyprctl')
+    os.system(f'hyprctl keyword device:\'{device}\':accel_profile \'custom {step} {sample_points_str}\'')
+
+if (findArg("scroll_points")):
+    device = getDevice()
+    print(f'Setting device:\'{device}\':scroll_points using hyprctl')
+    os.system(f'hyprctl keyword device:\'{device}\':scroll_points \'{step} {sample_points_str}\'')