Skip to content

Instantly share code, notes, and snippets.

@jkassemi
Created September 24, 2025 03:43
Show Gist options
  • Select an option

  • Save jkassemi/300b4945aefe820a25dac0eb10558d1f to your computer and use it in GitHub Desktop.

Select an option

Save jkassemi/300b4945aefe820a25dac0eb10558d1f to your computer and use it in GitHub Desktop.
Omarchy mouse acceleration configuration generation
#!/usr/bin/env python3
# vibed by grok4
# macOS-like pointer acceleration configuration for Hyprland Omarchy, with device selection and config update between comments
import subprocess
import sys
import os
# Parameters
sample_point_count = 100 # Smoothness (20 is balanced)
low, mid, high = 0.9, 0.01, 0.002 # Gentler curve to reduce overshoot
max_speed = 100 # Max input speed (units/ms)
input_conf_path = os.path.expanduser("~/.config/hypr/input.conf")
start_comment = "# BEGIN MOUSE ACCEL"
end_comment = "# END MOUSE ACCEL"
def macos_acceleration(speed_in):
return low * speed_in + mid * speed_in**2 + high * speed_in**3
def generate_curve_points(count):
step = max_speed / count
speeds = [step * i for i in range(count)]
factors = [macos_acceleration(s) for s in speeds]
return [f"{f:.3f}" for f in factors], step
def get_mouse_devices():
try:
result = subprocess.run(["hyprctl", "devices"], capture_output=True, text=True, check=True)
output = result.stdout
devices = []
in_mice_section = False
in_new_device_section = False
for line in output.splitlines():
if line.strip() == "mice:":
in_mice_section = True
in_new_device_section = False
continue
elif in_mice_section and line.strip().startswith("Mouse at"):
in_new_device_section = True
continue
elif in_new_device_section:
in_new_device_section = False
device_name = line.strip()
devices.append(device_name)
elif in_mice_section and not line.strip():
break
return devices
except subprocess.CalledProcessError as e:
print(f"Error running hyprctl devices: {e}")
sys.exit(1)
def select_device():
devices = get_mouse_devices()
if not devices:
print("No mouse devices found. Check 'hyprctl devices'.")
sys.exit(1)
print("Available mouse devices:")
for i, device in enumerate(devices, 1):
print(f"{i}. {device}")
while True:
try:
choice = int(input("Select a device (1-{}): ".format(len(devices))))
if 1 <= choice <= len(devices):
return devices[choice - 1]
print("Invalid choice. Try again.")
except ValueError:
print("Enter a number. Try again.")
def hyprctl_set(device, option, arg):
cmd = f"hyprctl keyword 'device[{device}]:{option}' '{arg}'"
try:
subprocess.run(cmd, shell=True, check=True)
print(f"Applied {option} for {device}: {arg}")
except subprocess.CalledProcessError as e:
print(f"Error applying {option} for {device}: {e}")
def update_input_conf(device, step, points):
points_str = " ".join(points)
device_block = f"""\
{start_comment} {device}
device {{
name = {device}
accel_profile = custom {step} {points_str}
scroll_points = {step} {points_str}
sensitivity = -0.1
}}
{end_comment} {device}
"""
try:
if not os.path.exists(input_conf_path):
print(f"{input_conf_path} does not exist. Please add the following to it manually:")
print(device_block)
print(f"Ensure 'source = ~/.config/hypr/input.conf' is in ~/.config/hypr/hyprland.conf")
return
with open(input_conf_path, "r") as f:
lines = f.readlines()
# Find and replace between comments
new_lines = []
i = 0
while i < len(lines):
if lines[i].strip() == start_comment:
# Skip existing block until end_comment
while i < len(lines) and lines[i].strip() != end_comment:
i += 1
if i < len(lines):
i += 1 # Skip end_comment
new_lines.append(device_block)
else:
new_lines.append(lines[i])
i += 1
# If comments not found, append block
if start_comment not in ''.join(lines):
print(f"{start_comment} not found in {input_conf_path}. Please add the following manually:")
print(device_block)
print(f"Ensure 'source = ~/.config/hypr/input.conf' is in ~/.config/hypr/hyprland.conf")
new_lines.append("\n" + device_block)
with open(input_conf_path, "w") as f:
f.writelines(new_lines)
print(f"Updated {input_conf_path} between {start_comment} and {end_comment}")
except IOError as e:
print(f"Error updating {input_conf_path}: {e}")
def main():
points, step = generate_curve_points(sample_point_count)
points_str = " ".join(points)
print(f"Generated curve - Step: {step}, Points: {points_str}")
device = None
for arg in sys.argv[1:]:
if arg.startswith("device="):
device = arg[7:]
break
if not device:
device = select_device()
# Apply accel_profile and scroll_points
hyprctl_set(device, "accel_profile", f"custom {step} {points_str}")
hyprctl_set(device, "scroll_points", f"{step} {points_str}")
# Update input.conf
update_input_conf(device, step, points)
print("Settings applied. Reload Hyprland with 'Super + Shift + R' or 'hyprctl reload' for full effect.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment