70个版本

0.10.0 2024年5月20日
0.8.18 2024年3月27日
0.8.12 2023年11月29日
0.8.5 2023年4月1日
0.1.6 2021年12月30日

#34 in GUI

Download history 40/week @ 2024-05-03 35/week @ 2024-05-10 292/week @ 2024-05-17 103/week @ 2024-05-24 84/week @ 2024-05-31 101/week @ 2024-06-07 103/week @ 2024-06-14 107/week @ 2024-06-21 57/week @ 2024-06-28 125/week @ 2024-07-05 50/week @ 2024-07-12 64/week @ 2024-07-19 107/week @ 2024-07-26 84/week @ 2024-08-02 79/week @ 2024-08-09 61/week @ 2024-08-16

每月341次下载

MIT许可证

175KB
4K SLoC

Xremap ⌨️

crates.io GitHub Actions

xremap 是一个Linux的键映射器。与 xmodmap 不同,它支持应用特定的映射和Wayland。

概念

  • 快速 - Xremap是用Rust编写的,比Python等无JIT解释器快。

  • 跨平台 - Xremap使用 evdevuinput,无论您使用X11还是Wayland都可以工作。

  • 语言无关 - 配置与JSON兼容。您可以从任何语言生成它,例如 RubyPython

功能

  • 映射任何键,例如Ctrl或CapsLock。
  • 将任何键组合映射到另一个键,甚至映射到键序列。
  • 也可以映射键序列。您可以进行类似Emacs的 C-x C-c 的操作。
  • 根据是否单独按下或按住,将键映射到两个不同的键。
  • 应用特定映射。即使您的应用程序不支持,xremap也可以。
  • 设备特定映射。
  • 通过以 --watch 启动xremap来自动映射新连接的设备。
  • 支持类似Emacs的键映射,包括标记模式。
  • 在按键/释放事件上触发命令。
  • 使用非修饰键作为虚拟修饰键。

安装

发布版 下载二进制文件。

如果不起作用,请 安装Rust 并运行以下命令之一

cargo install xremap --features x11     # X11
cargo install xremap --features gnome   # GNOME Wayland
cargo install xremap --features kde     # KDE-Plasma Wayland
cargo install xremap --features wlroots # Sway, Hyprland, etc.
cargo install xremap                    # Others

您可能还需要安装 libx11-dev 以运行X11的 xremap 二进制文件。

Arch Linux

如果您在 Arch Linux 和 X11 系统上,可以从 AUR 安装 xremap-x11-bin

NixOS

如果您使用 NixOS,可以通过 flake 安装和配置 xremap。

使用方法

直接编写 配置文件,或者使用 xremap-rubyxremap-python 生成。

然后运行以下命令启动 xremap 守护进程:

sudo xremap config.yml

(您需要让它持续运行,以便映射生效。)

如果您想不以 sudo 权限运行 xremap,请点击此处。

不以 sudo 权限运行 xremap

为此,您的普通用户应能够使用 evdevuinput 而不需要 sudo。在 Ubuntu 上,可以通过运行以下命令并重新启动您的计算机来配置。

sudo gpasswd -a YOUR_USER input
echo 'KERNEL=="uinput", GROUP="input", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/input.rules

Arch Linux

以下适用于 Arch 系统。

lsmod | grep uinput

如果此模块未加载,请将其添加到 /etc/modules-load.d/uinput.conf

uinput

然后添加 udev 规则。

echo 'KERNEL=="uinput", GROUP="input", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/99-input.rules

然后重新启动计算机。

Debian

确保 uinput 的加载方式与 Arch 相同

lsmod | grep uinput

如果显示为空

echo uinput | sudo tee /etc/modules-load.d/uinput.conf

将您的用户添加到 input 组,并添加与 Ubuntu 相同的 udev 规则

sudo gpasswd -a YOUR_USER input
echo 'KERNEL=="uinput", GROUP="input", TAG+="uaccess"' | sudo tee /etc/udev/rules.d/input.rules

之后重新启动计算机或尝试

sudo modprobe uinput
sudo udevadm control --reload-rules && sudo udevadm trigger

其他平台

在其他平台上,您可能需要首先创建一个 input 组,并运行以下命令,同时也要执行相同的 udev 规则。

如果您这样做,在某些环境中,由于临时权限问题,--watch 可能无法识别新设备。在这种情况下使用 sudo 可能更有用。


请参阅以下说明以使 application 特定的重映射工作。

X11

如果您使用 sudo 运行 xremap,如果您看到 No protocol specified,则可能需要运行 xhost +SI:localuser:root

GNOME Wayland

此链接 安装 xremap 的 GNOME Shell 扩展,从关闭切换到打开。

如果您使用 sudo 运行 xremap,也请点击此处。

按照以下方式更新 /usr/share/dbus-1/session.conf,然后重新启动您的计算机。

   <policy context="default">
+    <allow user="root"/>
     <!-- Allow everything to be sent -->
     <allow send_destination="*" eavesdrop="true"/>
     <!-- Allow everything to be received -->

KDE-Plasma Wayland

xremap 不能以 root 用户身份运行。按照上述说明以无 sudo 权限运行 xremap。

配置

您的 config.yml 应该如下所示

modmap:
  - name: Except Chrome
    application:
      not: Google-chrome
    remap:
      CapsLock: Esc
keymap:
  - name: Emacs binding
    application:
      only: Slack
    remap:
      C-b: left
      C-f: right
      C-p: up
      C-n: down

另请参阅: example/config.ymlexample/emacs.yml

modmap

modmap 用于键到键的重映射,类似于 xmodmap。注意,将键重映射到修饰键(例如,CapsLock 到 Control_L)仅在 modmap 中受支持,因为 keymap 对修饰键的处理方式不同。

modmap:
  - name: Name # Optional
    exact_match: false # Optional, defaults to false
    remap: # Required
      # Replace a key with another
      KEY_XXX: KEY_YYY # Required
      # Dispatch different keys depending on whether you hold it or press it alone
      KEY_XXX:
        held: KEY_YYY # Required, also accepts arrays
        alone: KEY_ZZZ # Required, also accepts arrays
        alone_timeout_millis: 1000 # Optional
      # Hook `keymap` action on key press/release events.
      KEY_XXX:
        skip_key_event: false # Optional, skip original key event ,defaults to false
        press: { launch: ["xdotool", "mousemove", "0", "7200"] } # Required
        release: { launch: ["xdotool", "mousemove", "0", "0"] } # Required
    application: # Optional
      not: [Application, ...]
      # or
      only: [Application, ...]
    window: # Optional (only wlroots/kde clients supported)
      not: [/regex of window title/, ...]
      # or
      only: [/regex of window title/, ...]
    device: # Optional
      not: [Device, ...]
      # or
      only: [Device, ...]

对于 KEY_XXXKEY_YYY,使用 这些名称。您可以省略 KEY_,且名称不区分大小写。因此,KEY_CAPSLOCKCAPSLOCKCapsLock 是同一件事。还提供了一些 自定义别名,如 SHIFT_RCONTROL_L 等。

如果您不知道键的名称,可以通过启用 xremap 调试输出来查找。

RUST_LOG=debug xremap config.yml
# or
sudo RUST_LOG=debug xremap config.yml

然后按下一个键。

如果您指定包含 heldalone 的映射,您可以使用键的两个目的。如果在按下其他任何键之前,键在 alone_timeout_millis(默认:1000)内被按下并释放,则键被认为是 alone。否则,它被认为是 held

keymap

keymap 用于将一系列键组合重映射到另一系列键组合或其他操作。

keymap:
  - name: Name # Optional
    remap: # Required
      # Key press -> Key press
      MOD1-KEY_XXX: MOD2-KEY_YYY
      # Sequence (MOD1-KEY_XXX, MOD2-KEY_YYY) -> Key press (MOD3-KEY_ZZZ)
      MOD1-KEY_XXX:
        remap:
          MOD2-KEY_YYY: MOD3-KEY_ZZZ
        timeout_millis: 200 # Optional. No timeout by default.
      # Key press (MOD1-KEY_XXX) -> Sequence (MOD2-KEY_YYY, MOD3-KEY_ZZZ)
      MOD1-KEY_XXX: [MOD2-KEY_YYY, MOD3-KEY_ZZZ]
      # Execute a command
      MOD1-KEY_XXX:
        launch: ["bash", "-c", "echo hello > /tmp/test"]
      # Let `with_mark` also press a Shift key (useful for Emacs emulation)
      MOD1-KEY_XXX: { set_mark: true } # use { set_mark: false } to disable it
      # Also press Shift only when { set_mark: true } is used before
      MOD1-KEY_XXX: { with_mark: MOD2-KEY_YYY }
      # The next key press will ignore keymap
      MOD1-KEY_XXX: { escape_next_key: true }
      # Set mode to configure Vim-like modal remapping
      MOD1-KEY_XXX: { set_mode: default }
    application: # Optional
      not: [Application, ...]
      # or
      only: [Application, ...]
    window: # Optional (only wlroots/kde clients supported)
      not: [/regex of window title/, ...]
      # or
      only: [/regex of window title/, ...]
    device: # Optional
      not: [Device, ...]
      # or
      only: [Device, ...]
    mode: default # Optional
default_mode: default # Optional

对于 KEY_XXX,使用 这些名称。您可以省略 KEY_,且名称不区分大小写。因此,KEY_CAPSLOCKCAPSLOCKCapsLock 是同一件事。

对于 MOD1- 部分,以下前缀可以使用(不区分大小写)

  • Shift: SHIFT-
  • Control: CTRL-CONTROL-
  • Alt: ALT-
  • Windows: SUPER-WIN-WINDOWS-

您可以使用多个前缀,如 C-M-Shift-。您还可以使用 _L_R(不区分大小写)作为后缀,以便仅在左或右修饰键上触发重映射,例如 Ctrl_L-

如果您使用以下 virtual_modifiers,您也可以在 MOD1- 部分使用它。

exact_match 定义在匹配键按下时是否使用精确匹配。例如,给定映射 C-Shift-n: downexact_match: false(默认),当您按下 C-Shift-n 时,它将自动重映射到 Shift-down,而无需您定义 C-Shift-n 的映射。

application

application 可用于 modmapkeymap,允许您指定特定应用程序的重映射。

application:
  not: Application
  # or
  not: [Application, ...]
  # or
  only: Application
  # or
  only: [Application, ...]

应用程序名称可以指定为一个普通字符串,以精确匹配名称,也可以指定为被 / 包围的正则表达式,例如 /application/

要检查应用程序名称,可以使用以下命令

X11

$ wmctrl -x -l
0x02800003  0 slack.Slack           ubuntu-jammy Slack | general | ruby-jp
0x05400003  0 code.Code             ubuntu-jammy application.rs - xremap - Visual Studio Code

您可以使用第三列的整个字符串(slack.Slackcode.Code),或者仅使用 . 之后的部分(SlackCode)。

GNOME Wayland

使用以下命令或通过按 Alt+F2 并在 LookingGlass 中运行 lg 命令来检查窗口的 WMClass

busctl --user call org.gnome.Shell /com/k0kubun/Xremap com.k0kubun.Xremap WMClasses

KDE-Plasma Wayland

Xremap 将活动窗口打印到控制台。然而,只有当触发了一个使用应用程序过滤器映射后,它才会开始打印。因此,您必须使用一个虚拟应用程序名称创建一个带有过滤器的映射并触发它。然后每次切换到新的窗口时,xremap 将以以下方式打印其标题、类和名称:active window: caption: '<caption>', class: '<class>', name: '<name>' 应使用 class 属性进行应用程序匹配,而应使用 caption 属性进行窗口匹配。

如果您使用 systemd-daemon 来管理 xremap,则打印将可见于系统日志(可以通过 journalctl -f 打开)

Sway

swaymsg -t get_tree

在输出中定位 app_id

应用程序特定的键覆盖

有时您可能想定义一个适用于所有应用程序的通用键映射,但在这个映射中为特定应用程序中的特定键提供自己的定义。您可以通过将通用映射放在配置文件底部,在所有特定覆盖之后,如下所示来实现这一点。

# Emacs-style word-forward and word-back
keymap:
  - name: override to make libreoffice-writer go to end of word but before final space like emacs
    application:
      only: libreoffice-writter
    remap:
      Alt-f: [right, C-right, left]
  - name: generic for all apps
    remap:
      Alt-f: C-right
      Alt-b: C-left

注意 Alt-f 和 Alt-b 在所有应用程序中的工作方式,但在 LibreOffice Writer 中的 Alt-f 定义略有不同。当该应用程序处于活动状态时,第一个定义会覆盖第二个定义;但对于任何其他应用程序,只有第二个定义被找到。这是因为 xremap 使用它找到的第一个匹配定义。

设备

application 类似,您可以在配置文件中指定 {keymap,modmap}.device.{not,only} 以进行针对设备的特定重映射。与全局 --device 标志一致,设备匹配字符串可以是以下任何一种

  • 设备的完整路径
  • 设备的文件名
  • 设备名称
  • 设备名称的子串

要确定您的设备名称和路径,请检查 xremap 启动时的日志输出。

device:
  not: '/dev/input/event0'
  # or
  not: ['event0', ...]
  # or
  only: 'Some Cool Device Name'
  # or
  only: ['Cool Device', ...]
  # etc...

application 不同,device 不支持正则表达式。

虚拟修饰符

您可以声明应该像修饰符一样工作的键。

virtual_modifiers:
  - CapsLock
keymap:
  - remap:
      CapsLock-i: Up
      CapsLock-j: Left
      CapsLock-k: Down
      CapsLock-l: Right

keypress_delay_ms

一些应用程序在理解合成按键事件时遇到困难,尤其是在Wayland上。可以使用 keypress_delay_ms 来解决这个问题。有关详细信息,请参阅 #179

共享数据字段

您可以在 shared 字段下声明不直接进入配置的数据。
当使用锚点和别名时,这很有用。
有关Yaml锚点的更多信息,请参阅 Yaml规范

示例

shared:
  terminals: &terminals # The & Symbol marks this entry as a Anchor
    - Gnome-terminal
    - Kitty
  
  some_remaps: &some_remaps
    Ctrl-f: C-right
    Alt-b: C-up

keymap:
  - application:
      only: *terminals  # we can reuse the list here
    remap: *some_remaps # and we can reuse a map here.

许可

xremap 在MIT许可条款下作为开源软件提供。

依赖项

~11–25MB
~379K SLoC