xkeysnail is yet another keyboard remapping tool for X environment written in Python

Overview

xkeysnail

xkeysnail is yet another keyboard remapping tool for X environment written in Python. It's like xmodmap but allows more flexible remappings.

screenshot

  • Pros
    • Has high-level and flexible remapping mechanisms, such as
      • per-application keybindings can be defined
      • multiple stroke keybindings can be defined such as Ctrl+x Ctrl+c to Ctrl+q
      • not only key remapping but arbitrary commands defined by Python can be bound to a key
    • Runs in low-level layer (evdev and uinput), making remapping work in almost all the places
  • Cons
    • Runs in root-mode (requires sudo)

The key remapping mechanism of xkeysnail is based on pykeymacs (https://github.com/DreaminginCodeZH/pykeymacs).

Installation

Requires root privilege and Python 3.

Ubuntu

sudo apt install python3-pip
sudo pip3 install xkeysnail

# If you plan to compile from source
sudo apt install python3-dev

Fedora

sudo dnf install python3-pip
sudo pip3 install xkeysnail
# Add your user to input group if you don't want to run xkeysnail
# with sudo (log out and log in again to apply group change)
sudo usermod -a -G input $USER

# If you plan to compile from source
sudo dnf install python3-devel

Manjaro/Arch

# Some distros will need to compile evdev components 
# and may fail to do so if gcc is not installed.
sudo pacman -Syy
sudo pacman -S gcc

Solus

# Some distros will need to compile evdev components 
# and may fail to do so if gcc is not installed.
sudo eopkg install gcc
sudo eopkg install -c system.devel

From source

git clone --depth 1 https://github.com/mooz/xkeysnail.git
cd xkeysnail
sudo pip3 install --upgrade .

Usage

sudo xkeysnail config.py

When you encounter the errors like Xlib.error.DisplayConnectionError: Can't connect to display ":0.0": b'No protocol specified\n' , try

xhost +SI:localuser:root
sudo xkeysnail config.py

If you want to specify keyboard devices, use --devices option:

sudo xkeysnail config.py --devices /dev/input/event3 'Topre Corporation HHKB Professional'

If you have hot-plugging keyboards, use --watch option.

If you want to suppress output of key events, use -q / --quiet option especially when running as a daemon.

How to prepare config.py?

(If you just need Emacs-like keybindings, consider to use example/config.py, which contains Emacs-like keybindings).

Configuration file is a Python script that consists of several keymaps defined by define_keymap(condition, mappings, name)

define_keymap(condition, mappings, name)

Defines a keymap consists of mappings, which is activated when the condition is satisfied.

Argument condition specifies the condition of activating the mappings on an application and takes one of the following forms:

  • Regular expression (e.g., re.compile("YYY"))
    • Activates the mappings if the pattern YYY matches the WM_CLASS of the application.
    • Case Insensitivity matching against WM_CLASS via re.IGNORECASE (e.g. re.compile('Gnome-terminal', re.IGNORECASE))
  • lambda wm_class: some_condition(wm_class)
    • Activates the mappings if the WM_CLASS of the application satisfies the condition specified by the lambda function.
    • Case Insensitivity matching via casefold() or lambda wm_class: wm_class.casefold() (see example below to see how to compare to a list of names)
  • None: Refers to no condition. None-specified keymap will be a global keymap and is always enabled.

Argument mappings is a dictionary in the form of {key: command, key2: command2, ...} where key and command take following forms:

  • key: Key to override specified by K("YYY")
  • command: one of the followings
    • K("YYY"): Dispatch custom key to the application.
    • [command1, command2, ...]: Execute commands sequentially.
    • { ... }: Sub-keymap. Used to define multiple stroke keybindings. See multiple stroke keys for details.
    • pass_through_key: Pass through key to the application. Useful to override the global mappings behavior on certain applications.
    • escape_next_key: Escape next key.
    • Arbitrary function: The function is executed and the returned value is used as a command.
      • Can be used to invoke UNIX commands.

Argument name specifies the keymap name. This is an optional argument.

Key Specification

Key specification in a keymap is in a form of K("( -)* ") where

is one of the followings

  • C or Ctrl -> Control key
  • M or Alt -> Alt key
  • Shift -> Shift key
  • Super or Win -> Super/Windows key

You can specify left/right modifiers by adding any one of prefixes L/R.

And is a key whose name is defined in key.py.

Here is a list of key specification examples:

  • K("C-M-j"): Ctrl + Alt + j
  • K("Ctrl-m"): Ctrl + m
  • K("Win-o"): Super/Windows + o
  • K("M-Shift-comma"): Alt + Shift + comma (= Alt + >)

Multiple stroke keys

When you needs multiple stroke keys, define nested keymap. For example, the following example remaps C-x C-c to C-q.

define_keymap(None, {
    K("C-x"): {
      K("C-c"): K("C-q"),
      K("C-f"): K("C-q"),
    }
})

Checking an application's WM_CLASS with xprop

To check WM_CLASS of the application you want to have custom keymap, use xprop command:

xprop WM_CLASS

and then click the application. xprop tells WM_CLASS of the application as follows.

WM_CLASS(STRING) = "Navigator", "Firefox"

Use the second value (in this case Firefox) as the WM_CLASS value in your config.py.

Example config.py

See example/config.py.

Here is an excerpt of example/config.py.

from xkeysnail.transform import *

define_keymap(re.compile("Firefox|Google-chrome"), {
    # Ctrl+Alt+j/k to switch next/previous tab
    K("C-M-j"): K("C-TAB"),
    K("C-M-k"): K("C-Shift-TAB"),
}, "Firefox and Chrome")

define_keymap(re.compile("Zeal"), {
    # Ctrl+s to focus search area
    K("C-s"): K("C-k"),
}, "Zeal")

define_keymap(lambda wm_class: wm_class not in ("Emacs", "URxvt"), {
    # Cancel
    K("C-g"): [K("esc"), set_mark(False)],
    # Escape
    K("C-q"): escape_next_key,
    # C-x YYY
    K("C-x"): {
        # C-x h (select all)
        K("h"): [K("C-home"), K("C-a"), set_mark(True)],
        # C-x C-f (open)
        K("C-f"): K("C-o"),
        # C-x C-s (save)
        K("C-s"): K("C-s"),
        # C-x k (kill tab)
        K("k"): K("C-f4"),
        # C-x C-c (exit)
        K("C-c"): K("M-f4"),
        # cancel
        K("C-g"): pass_through_key,
        # C-x u (undo)
        K("u"): [K("C-z"), set_mark(False)],
    }
}, "Emacs-like keys")

Example of Case Insensitivity Matching

terminals = ["gnome-terminal","konsole","io.elementary.terminal","sakura"]
terminals = [term.casefold() for term in terminals]
termStr = "|".join(str(x) for x in terminals)

# [Conditional modmap] Change modifier keys in certain applications
define_conditional_modmap(lambda wm_class: wm_class.casefold() not in terminals,{
    # Default Mac/Win
    Key.LEFT_ALT: Key.RIGHT_CTRL,   # WinMac
    Key.LEFT_META: Key.LEFT_ALT,    # WinMac
    Key.LEFT_CTRL: Key.LEFT_META,   # WinMac
    Key.RIGHT_ALT: Key.RIGHT_CTRL,  # WinMac
    Key.RIGHT_META: Key.RIGHT_ALT,  # WinMac
    Key.RIGHT_CTRL: Key.RIGHT_META, # WinMac
})

# [Conditional modmap] Change modifier keys in certain applications
define_conditional_modmap(re.compile(termStr, re.IGNORECASE), {

    # Default Mac/Win
    Key.LEFT_ALT: Key.RIGHT_CTRL,   # WinMac
    Key.LEFT_META: Key.LEFT_ALT,    # WinMac
    Key.LEFT_CTRL: Key.LEFT_CTRL,   # WinMac
    Key.RIGHT_ALT: Key.RIGHT_CTRL,  # WinMac
    Key.RIGHT_META: Key.RIGHT_ALT,  # WinMac
    Key.RIGHT_CTRL: Key.LEFT_CTRL,  # WinMac
})

FAQ

How do I fix Firefox capturing Alt before xkeysnail?

In the Firefox location bar, go to about:config, search for ui.key.menuAccessKeyFocuses, and set the Value to false.

License

xkeysnail is distributed under GPL.

xkeysnail
Copyright (C) 2018 Masafumi Oyamada

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
   
   .

xkeysnail is based on pykeymacs (https://github.com/DreaminginCodeZH/pykeymacs), which is distributed under GPL.

pykeymacs
Copyright (C) 2015 Zhang Hai

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
   
   .
Owner
Masafumi Oyamada
Masafumi Oyamada
Brute-Force-Connected

Brute-Force-Connected Guess the password for Connected accounts the use : Create a new file and put usernames and passwords in it Example : joker:1234

4 Jun 05, 2022
Collection Of Discord Hacking Tools / Fun Stuff / Exploits That Is Completely Made Using Python.

Venom Collection Of Discord Hacking Tools / Fun Stuff / Exploits That Is Completely Made Using Python. Report Bug · Request Feature Contributing Well,

PndaBoi 25 Dec 06, 2022
BurpSuite Extension: Log4j2 RCE Scanner

Log4j2 RCE Scanner 作者:[email protected]元亨实验室 声明:由于传播、利用本项目所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,项目作者不为此承担任何责

ᴋᴇʏ 87 Dec 29, 2021
Cve-2021-22005-exp

cve-2021-22005-exp 0x01 漏洞简介 2021年9月21日,VMware发布安全公告,公开披露了vCenter Server中的19个安全漏洞,这些漏洞的CVSSv3评分范围为4.3-9.8。 其中,最为严重的漏洞为vCenter Server 中的任意文件上传漏洞(CVE-20

Jing Ling 146 Dec 31, 2022
log4j-tools: CVE-2021-44228 poses a serious threat to a wide range of Java-based applications

log4j-tools Quick links Click to find: Inclusions of log4j2 in compiled code Calls to log4j2 in compiled code Calls to log4j2 in source code Overview

JFrog Ltd. 171 Dec 25, 2022
Argument Injection in Dragonfly Ruby Gem

CVE-2021-33564 PoC Exploit script for CVE-2021-33564 (Argument Injection in Dragonfly Ruby Gem). Usage Arbitrary File Read python3 poc.py -u https://

Michael Tsai 12 Nov 09, 2022
A small POC plugin for launching dumpulator emulation within IDA, passing it addresses from your IDA view using the context menu.

Dumpulator-IDA Currently proof-of-concept This project is a small POC plugin for launching dumpulator emulation within IDA, passing it addresses from

Michael 9 Sep 21, 2022
A terminal based web shell controller

shell-hack Tribute to Chinese ant sword; A Powerful terminal based webshell controller; Usage : Usage : python3 shell-hack.py --url [URL] --w

s1mple 10 Dec 28, 2021
This is an injection tool that can inject any xposed modules apk into the debug android app

This is an injection tool that can inject any xposed modules apk into the debug android app, the native code in the xposed module can also be injected.

Windy 32 Nov 05, 2022
A curated list of amazingly awesome Cybersecurity datasets

A curated list of amazingly awesome Cybersecurity datasets

758 Dec 28, 2022
Python & JavaScript Obfuscator made in Python 3.

Python Code Obfuscator A script that converts code into full on random numerical expressions. Simple Scripts: Python Mode... Input: Function that deco

rzx. 1 Dec 29, 2021
MD5-CRACKER - A gmail brute force app created with python3

MD5-CRACKER So this is my first app i created with python3 . if you guys downloa

2 Nov 10, 2022
A deobfuscator for multiple python obfuscators

PY4COC A deobfuscator for multiple python obfuscators, supports exe's packed with pyinstaller too. How to use python3 py4coc.py exe file or py file o

svenskithesource 16 Dec 03, 2022
Obfuscate your python code into a string of integers. De-obfuscate also supported.

int-obfuscator Obfuscate your python code into a string of integers. De-obfuscate also supported. How it works: Each printable character gets replaced

6 Nov 13, 2022
Selamat Datang DiTools Crack-Old, Crack Old Adalah Sebuah Crack Tanpa Login Dan Crack Menggunakan Akun Facebook Tua/Old.

Selamat Datang DiTools Crack-Old, Crack Old Adalah Sebuah Crack Tanpa Login Dan Crack Menggunakan Akun Facebook Tua/Old. ([Welcome to Crack-Old Tools, Old Crack Is A Crack Without Login And Crack Usi

Risky [ Zero Tow ] 7 Dec 25, 2022
Quickstart resources for the WiFi Nugget, a cat themed WiFi Security platform for beginners.

Quickstart resources for the WiFi Nugget, a cat themed WiFi Security platform for beginners.

HakCat 62 Jan 08, 2023
A signature parser for hikari's command handler tanjun.

tanchi A signature parser for hikari's command handler tanjun. Finally be able to define your commands without those bloody decorator chains! Example

sadru 11 Nov 17, 2022
Generate obfuscated meterpreter shells

Generator Evade AV with obfuscated payloads Installation must install dotnet prior to running the script with net45 Running ./generator.py -ip Your-I

Fawaz Al-Mutairi 219 Nov 28, 2022
Polkit - Local Privilege Escalation (CVE-2021-3560)

CVE-2021-3560 Polkit - Local Privilege Escalation Original discovery by kevin_backhouse from GitHub Security Lab References https://github.blog/2021-0

Salman Asad 1 Nov 12, 2021