-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
(Question) Separate config file for custom keymaps #455
Comments
The tl;dr version of the answer to this is that you can back up your config file (toshy_config.py) and sync it between multiple machines, although at times this may fail if you do a new install or upgrade of Toshy on one machine and another machine is too far behind. There is a much longer answer: I certainly don't have the skills to have written the original keymapper that Kinto was using (xkeysnail), then someone else forked it into "keyszer" and fixed a bunch of little issues and added some functionality. What I've mainly done on the keymapper side is come up with a strategy to support to absolute mess of the Wayland compositor landscape, which has required nearly a dozen different methods to get the window context for app-specific keymapping. Eventually I forked keyszer into xwaykeyz, but other than the Wayland stuff it's still pretty much the same. In keyszer, there is an If I was a lot smarter there could be much better separation between the user's "config" and the rest of the keymapper, but the reality of how the keymapper was designed means the config file is just another part of the "program" and there are a lot of dynamic things going on in the config file, in addition to just static remaps of shortcuts. In fact Toshy's config is far more dynamic than the original Kinto config, with automatic identification of keyboard types as one of the main examples. That particular example allows the use of different keyboard types on the same machine. So what the installer does is back up any existing Toshy folder into a timestamped subfolder in In the end, all you really need to do is keep the installed version of Toshy kind of consistent across machines, and sync the If you think you can help move the keymapper toward having better config/code separation without losing functionality, I'm always open to concrete suggestions or contributions. Meanwhile, this is the best answer/explanation I can offer. |
Just a follow-up on this, the techniques I've tried to get a machine-specific ID number have required superuser permissions, so I'm a little confused about how KDE's "About" panel shows me a serial number without needing a password. It appears to be the "product_serial". Anyway, it would be possible to just stash the board serial, product serial, or product uuid in a text file, after reading it with superuser permissions from some command like this:
Then that text file could be read from the config file to enforce a machine-specific This is some example code GPT 4o just provided to safely read the file and use the unique value. Looks pretty good. def read_value_from_file(filepath):
"""
Safely reads a single value from a file.
Args:
filepath (str): The path to the file containing the value.
Returns:
str: The value from the file, or None if the file doesn't exist or cannot be read.
"""
try:
with open(filepath, "r") as file:
return file.read().strip() # Strip to remove any extra newlines or spaces
except FileNotFoundError:
print(f"File not found: {filepath}")
except PermissionError:
print(f"Permission denied: Unable to read file {filepath}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
return None
# Example usage
unique_value_file = "/path/to/your/unique_value_file"
stored_value = read_value_from_file(unique_value_file)
# Use the value in an `if` statement
if stored_value == "SPECIFIC_VALUE":
print("Value matches. Executing code...")
else:
print("Value does not match or file could not be read.") |
I found a simpler solution to grabbing a unique machine ID, which should work for most Linux systems that anyone would ever run Toshy on. It's a file that DBus uses to uniquely identify a physical system. This same ID is also usually copied or symlinked for use by This has been added to the default config files. # Global variable to store the local machine ID at runtime, for machine-specific keymaps.
# Allows syncing a single config file between different machines without overlapping the
# hardware/media key overrides, or any other machine-specific customization.
# Get the ID for each machine from /var/lib/dbus/machine-id for use in `if` conditions.
MACHINE_ID = None
def read_machine_id():
"""Reads the machine ID from the D-Bus or systemd file and stores it in a global variable."""
global MACHINE_ID
paths = ["/var/lib/dbus/machine-id", "/etc/machine-id"]
for path in paths:
try:
with open(path, "r") as f:
MACHINE_ID = f.read().strip()
obfuscated_ID = f"{MACHINE_ID[:5]} ... {MACHINE_ID[-5:]}"
debug(f"Machine ID successfully read from {path} (obfuscated): '{obfuscated_ID}'")
return # Exit after successfully reading the ID
except FileNotFoundError:
continue # Try the next file if this one is missing
except PermissionError:
error(f"Permission denied when trying to read {path}.")
return
except Exception as e:
error(f"Unexpected error occurred while reading {path}: {e}")
return
# If no valid machine ID is found
error("Error: Could not retrieve a valid machine ID from known paths.")
read_machine_id() With this in place, it should be possible to use the machine ID from a specific system to restrict a keymap to being active or loading into memory only on that physical system. For example, you could something like this: my_Acer_Aspire_laptop = '3210b7e9a6ba462689bf633a03d7e21a'
if MACHINE_ID == my_Acer_Aspire_laptop:
keymap(usual arguments for a keymap() call go here) To see what your machine ID is,
If both files exist, they should contain the same value. The files are both user-readable, so they aren't particularly secret. I'm still thinking about whether it would make sense to hash the value, but that would make it more difficult for the user to find the correct value to store in the variable or use in the |
I put the code for the machine ID in a separate Python module ( For example, for my Acer Aspire laptop: my_Acer_Aspire_laptop = 'abcd1234'
if MACHINE_ID == my_Acer_Aspire_laptop:
debug("Activating keymap for Acer Aspire laptop keyboard hardware/media keys.")
keymap("User hardware keys - Acer Aspire", {
C("CapsLock"): toggle_and_show_capslock_state, # Show CapsLock state notification
C("NumLock"): toggle_and_show_numlock_state, # Show NumLock state notification
# My hardware Sleep key on function row - BIOS set to make hardware functions require Fn key
C("Sleep"): None, # Disable hardware Sleep key (F1 + Fn)
# My brightness keys on function row - BIOS set to make hardware functions require Fn key
C("F3"): C("Brightnessdown"), # Turn F3 into brightness down button
C("F4"): C("Brightnessup"), # Turn F4 into brightness up button
# My volume keys on function row - BIOS is set to make hardware functions require Fn key
C("F9"): C("Mute"), # Turn F9 into mute button
C("F10"): C("Volumedown"), # Turn F10 into volume down button
C("F11"): C("Volumeup"), # Turn F11 into volume up button
# Reverse the behavior of the volume keys to be function keys when I use Fn key
C("Mute"): C("F9"), # Turn mute button into F9
C("Volumedown"): C("F10"), # Turn volume down button into F10
C("Volumeup"): C("F11"), # Turn volume up button into F11
}, when = lambda ctx:
cnfg.screen_has_focus and
matchProps(not_clas=remoteStr)(ctx)
) In this example I chose to also put a line inside the The machine ID is reliable up to the point where you reinstall Linux on the same system from scratch, or do something else to reset the DBus/systemd ID. It's not as permanent as the physical hardware serial or product UUID. The |
AFAIK toshy only looks for configs in a single file, and there are some special sections where you are supposed to drop custom keymaps. I want to keep my custom mappings in a separate file to put in my dotfiles git repo.
Is it possible to do this?
The text was updated successfully, but these errors were encountered: