This program does 2 things:
-
One of the things it does is add a layer behind a "toggle key" to a set of keys that can be configured based on the active application.
-
The other thing the script does is create a pop-up to show what a key will do when the toggle is being held.
This script currently only works on windows. This isn't ideal but none of this code is "ideal". It's quick and dirty and it evolved from a much simpler script. To be robust and ready for non-technical users the code will probably need to be re-factored. I'm releasing this to see if it's features are something other people like. If so I'll work on increasing the code quality and supporting other features.
This project is currently python based running it requires python 3.
The dependencies for this project are in requirements.txt use pip to install them. Then run HotkeyLayers.py.
pip install -r requirements.txt
By default pressing the toggle key is brings up a window like this
You can change where the keys go with the layout for a keyboard like the ergodex this would look like
Right clicking on a key allows you to edit the json associated with that key. You can then click escape to discard the changes or ctrl+s to save the changes.
The script is designed to be highly configurable. There are 3 configurable parts of the script.
Config.json and Application specific configs are in the hotkeysJson directory.
The keys that are used by the script are configured in config.json. If an option does not have a default it is required.
The attributes in config.json are as follows:
This is a list of all the keys to be re-mapped. The order of the list should match the order of the hks Each key has the following attributes.
--- Start Key obj attributes ---
This is the key to re-map.
baseLayer : action
This is an action to take when the key is pressed without the toggle key.
Example :
"keys":[
{
"remap": "foo",
"baseLayer" : {
"press" : "bar"
}
},
...
],
This makes it so that when 'foo' is pressed 'bar' is sent.
--- End key obj attributes---
This is the key that activates the GUI and the application specific keymap.
Should the script re-map the keys listed in keys based on an application. The toggle key is still modified.
Default - true
Should the script show use resources to show a GUI when the toggle key is held.
Default - true
This is the path the keyboard layout json. This does not support rotation. The layout can be generated/downloaded from here (This is not my work but it's cool so I used the same format). The legends in this layout should match the remap name.
Default - "Layouts/keyboard-layout-4.json"
It would be a shame to waste a key. ToggleActions allows actions to be configured for when the toggle key is pressed without pressing an action key.
--- Start ToggleActions attributes ---
tap : action
This is the action to take when the toggle key is tapped and released without pressing another key.
tap : action
This is the action to take when the toggle key is held and then released without pressing another key.
--- End ToggleActions attributes ---
These are the prefixes for use in actions using these prefixes actions can invoke pyhton functions defined in the customFuncs module. each object should contain :
--- start function attributes ---
This is the prefix for the function action beginning with this character will be mapped to the ...
This is the name of the python function to be called. The argument to this function is whatever follows the prefix in the command
--- end function attributes ---
This is the name of the application that this config applies to. This takes priority over the regex.
Regex to match with the full window title.
This is the priority for the regex. This is the priority for the regex match. If multiple regex patterns match the map with the higher priority will be applied.
This is a list of actions to map to the keys to the keys specified in Keys, this is done based on index. If a list of actions is used instead of an action those actions will be added to layers. The default layer is the first entry.
You can create an action to set/change the current layer by invoking the setLayer function.
default : Use the actions in the map with the name "default"
Actions are the object that define what a key will do. Actions have the following attributes.
--- Start actions attributes ---
This is what happens when the key is pressed. It can be either a function or a command.
default : Nothing
This is what happens when the key is released. It can be either a function or a command.
default : Nothing
This is an image to be displayed on the GUI when this layer is active. This will be displayed if it present otherwise use the description.
default : No image use the description
This is a description to be displayed on the GUI when this layer is active. This will only be displayed if no icon is specified.
default : Raw json for the actions
--- End actions attributes ---
Example :
{
"press": "{Shift down}",
"rel": "{Shift up}",
"description": "rotate camera"
}
This action presses and holds shift when a key is pressed and releases it when the key is released.
This is a function call to a python function with named arguments.
Example :
{
"function" : "foo",
"args" : {
"type" :"set",
"val": 2
}
}
is equivalent to a call foo(type="set", val=2)
Strings are just sent as written but commands are wrapped in curly braces {}
A command to send when it is parsed using the regex :
(?<!//){(?P<cmd>.*?)((?P<down> down)|(?P<up> up))?(?<!//)}|(?P<str>[^/{]+)
For each match in string
- If the string group matches send that string.
- If the cmd group matches check for a prefix from Funcs if it is present strip it and pass the rest of the command to the function as a string.
- If the down group matches press and hold the specified key until it is released with an up group
- If the up group matches release the specified key
Example :
{Shift down}s
This command presses and holds shift and taps s.
I use this software in conjunction with a MMO gaming mouse and not a keyboard. That's why I have my keymaps set up the way I do.
- Replace tkinter with a more modern GUI framework
- Create the windowed glass effect more seamlessly
- Validate jsons before parsing them
- Add support for non-windows oses
- Get closer to the kernel and communicate directly with usb devices