一键切换键盘布局

一键切换键盘布局

是否可以只用一个键(如Control_L或 )来打开特定键盘布局Shift_L,而不会丢失其主要功能?例如,我尝试为命令创建自定义键绑定,setxkbmap -layout en并通过dconf-editor将其绑定到 来编辑它Control_L。布局打开了,但常用的快捷键Control_L停止工作。

答案1

这是一个可以执行此操作的 Python 脚本。您需要sudo apt install python3-xlib

#!/usr/bin/env python3
# Based off https://stackoverflow.com/a/22368676/10477326
from Xlib.display import Display
from Xlib import X
from Xlib.ext import record
from Xlib.protocol import rq
import subprocess

TARGET_KEY = 37 # CTRL
target_pressed = False
disp = None

def handler(reply):
    global target_pressed
    data = reply.data
    # Listen for all keys
    while len(data):
        event, data = rq.EventField(None).parse_binary_value(data, disp.display, None, None)
        typ = event.type
        if typ not in (X.KeyPress, X.KeyRelease):
            # Interrupt on mouse Ctrl+Zoom or Ctrl+Click. Thank you @terdon
            target_pressed = False
            continue
        detail = event.detail
        # If there was another key in the middle,
        # stop because it's another key combination and not just
        # the one key that we desire.
        if detail != TARGET_KEY:
            target_pressed = False
            continue
        # On KeyPress, set a flag to wait for a KeyRelease to make sure
        # no other keys will be pressed.
        if typ == X.KeyPress:
            target_pressed = True
            continue
        # Previously another key in the middle was detected.
        if not target_pressed:
            continue
        # Now we know only the TARGET_KEY was pressed and released without any other keys.
        # Run your command
        subprocess.run(["setxkbmap", "-layout", "en"])
        target_pressed = False

disp = Display()
root = disp.screen().root
ctx = disp.record_create_context(
    0,
    [record.AllClients],
    [{
        'core_requests': (0, 0),
        'core_replies': (0, 0),
        'ext_requests': (0, 0, 0, 0),
        'ext_replies': (0, 0, 0, 0),
        'delivered_events': (0, 0),
        'device_events': (X.KeyReleaseMask, X.ButtonReleaseMask),
        'errors': (0, 0),
        'client_started': False,
        'client_died': False,
    }],
)
disp.record_enable_context(ctx, handler)
disp.record_free_context(ctx)

while True:
    event = root.display.next_event()

然后,您可以将其标记为可执行文件,并在启动应用程序中添加指向它的链接。主要思想是全局监听所有窗口上的所有按键。然后,我会监听其间的任何其他按键,以了解您是否要切换布局或使用其他快捷方式。目标键仍会始终发送到原始窗口。

相关内容