Moonstar

@Moonstar@lemmy.fmhy.ml
1 Post – 3 Comments
Joined 1 years ago

A Computer Scientist alumnus with a passion for the open-source community... no wonder I'm here!

The results have made me realize that the bash way of doing this is just not worth attempting, and a Python script is much more simple. At the end of the day, I ended up using this GIST with a custom handler function:

https://gist.github.com/dperelman/c1d3c966d397ff884abb8b3baf7990db

class MouseProfile(Enum):
    DEFAULT = 0
    BLOONS = 1
    GAMING_COMMON = 2
    CALL_OF_DUTY = 3
    REALM_GRINDER = 4

def handle_change(new_state: dict):
    """
    Using `libratbag`, switch the profile of the mouse based on the active window title.
    """
    # Get the title of the active window
    title: str = new_state['title']
    profile: MouseProfile = MouseProfile.DEFAULT
    match title:
        case "BloonsTD6":
            profile = MouseProfile.BLOONS
        case "Realm Grinder":
            profile = MouseProfile.REALM_GRINDER
        case _:
            if title:
              if search(r"^Call of Duty.*", title):
                  profile = MouseProfile.CALL_OF_DUTY
              elif search(r"^Deep Rock Galactic.*", title):
                  profile = MouseProfile.GAMING_COMMON
    # Send the ratbag command to switch the profile
    run(["ratbagctl", "Logitech", "profile", "active", "set", str(profile.value)], stdout=PIPE, stderr=PIPE)

I have been tinkering with my script some more and figured I would post an update:

  • As I have been experimenting with the script, I have noticed some weird window dragging issues. I have learned that, if you switch a profile, your mouse is temporarily interrupted, even when switching to the same profile. So, I have added a variable that stores the profile to ensure that you only switch when actually needed.

GIST with source code used: https://gist.github.com/dperelman/c1d3c966d397ff884abb8b3baf7990db

from enum import Enum
from re import search
from subprocess import run, PIPE

# Code from the GIST
... 

class MouseProfile(Enum):
    DEFAULT = 0
    BLOONS = 1
    GAMING_COMMON = 2
    CALL_OF_DUTY = 3
    REALM_GRINDER = 4

current_profile: MouseProfile = MouseProfile.DEFAULT

def handle_change(new_state: dict):
    """
    Using `libratbag`, switch the profile of the mouse
    based on the active window title.
    """
    global current_profile

    # Get the title of the active window
    title: str = new_state['title']
    profile: MouseProfile = MouseProfile.DEFAULT
    match title:
        case "BloonsTD6":
            profile = MouseProfile.BLOONS
        case "Realm Grinder":
            profile = MouseProfile.REALM_GRINDER
        case _:
            if title:
                if search(r"^Call of Duty.*", title):
                    profile = MouseProfile.CALL_OF_DUTY
                elif search(r"^Deep Rock Galactic.*", title):
                    profile = MouseProfile.GAMING_COMMON
    # Send the ratbag command to switch the profile
    if profile != current_profile:
        run([
            "ratbagctl", "Logitech", "profile", "active", "set", str(profile.value)
        ], stdout=PIPE, stderr=PIPE)
        current_profile = profile


if __name__ == '__main__':
    # Get the current mouse profile and set it as the current profile
    result = run(
        ["ratbagctl", "Logitech", "profile", "active", "get"],
        stdout=PIPE, stderr=PIPE
    )
    current_profile = MouseProfile(int(result.stdout)) if result.returncode == 0 else MouseProfile.DEFAULT

    # Listen for _NET_ACTIVE_WINDOW changes
    root.change_attributes(event_mask=X.PropertyChangeMask)

    # Prime last_seen with whatever window was active when we started this
    get_window_name(get_active_window()[0])
    handle_change(last_seen)

    while True:
        handle_xevent(display.next_event())

Don't you mean from 1 to 11? (And 3 is not a valid option.) Sorry, I saw an opening for a stupid joke and had to jump.