使用 i3 bindsym 和 xdotool 的无限循环按键

Infinite loop of keypresses with i3 bindsym and xdotool

我正在尝试将 firefox-ctrl-q-workaround 转换为也能处理 Ctrl-Shift-C。这是因为我一直错误地在 Firefox 中使用 Ctrl-Shift-C,并且一直弹出打开的开发人员工具变得乏味。 Firefox,非常烦人,没有任何配置快捷方式的方法。

设置大致如下所示:

首先将i3中的key绑定到一个脚本中:

# i3 config
bindsym --release Control+Shift+c exec --no-startup-id ~/ctrl_c_map.sh

脚本本身如下所示:

# This is the active window
W="$(xdotool getactivewindow)"

# Get window class
WM_CLASS="$(xprop -id "$W" | awk -F '"' '/WM_CLASS/{print }')"

# Succeed if the WM_CLASS is firefox
is_firefox() {
    [ "$WM_CLASS" == "firefox" ] || [ "$WM_CLASS" == "Firefox Developer Edition" ]
}

send_key() {
    keytosend=
    xdotool key --clearmodifiers --window "$W" "$keytosend"
}

if is_firefox; then
    # remap to copy (Ctrl+C)
    send_key ctrl+c
else
    # re-send original C-S-c as it was actually useful
    send_key ctrl+shift+c
fi

这在 Firefox 中有效 - 捕获 Ctrl-Shift-C 事件并将其重新映射到 Ctrl-C,并复制任何选定的文本。万岁!

但是,在任何其他程序中(特别是在 Ctrl-Shift-C 真正有用的终端中),都会出现问题。当使用 xdotool 发送 ctrl+shift+c 密钥时,i3 再次捕获它并再次触发脚本,使我们陷入无限循环,您只能通过捣碎 Ctrl/Shift 来逃脱。此外,目标 window 从未获得其 Ctrl-Shift-C 键:它在 i3 和 bash 之间无休止地循环,但从未真正到达。

如何在没有无限循环的情况下从 i3 bindsym 触发的脚本中发送 相同的 绑定密钥?

也许您可以使用仅匹配 firefox 的标准来限制 Control+Shift+c 上的匹配,例如

bindsym Control+Shift+c [class="Firefox"] exec xdotool key --clearmodifiers ctrl+c

使用自动键

[这并不是问题的真正答案(如何停止 xdotool 和 i3 之间的无限循环),但它是一种比 i3 bindsym [class="firefox"] 方法更灵活的替代方法如果您需要执行更多可能发送原始密钥的逻辑。如果你知道你永远不会发送原始密钥,@meuh 的答案更简单,这就是我现在正在使用的。]

向自动键添加新脚本。要完全禁用密钥,请将脚本留空。发送Ctrl+C,就是:

# Send Ctrl-C instead of Ctrl-Shift-C
keyboard.send_keys('<ctrl>+c')

将热键设置为 <ctrl>+<shift>+c 并适当设置 window 过滤器。在我的例子中,Navigator.firefox 是它使用内置工具检测到的。

就是这样。

您可以向此脚本添加逻辑以根据需要向程序发送不同的密钥,包括原始密钥,(或什么都不发送)。

与i3/xdotool

如果您永远不会发送与触发器相同的密钥,并且您总是想发送相同的替换密钥,您应该使用@meuh 的回答。如果您要发送的密钥可能不同(例如 Ctrl+C 在 Firefox 或 Alt+C 在其他程序中)。

重要的是,正如@meuh 的回答,您使用 class 过滤器来防止在您发送原始密钥时调用脚本。这是一个正则表达式,所以你可以有多个过滤器:

# i3/config
bindsym --release Control+Shift+c [class="(firefox|other_prog)"] exec ~/myscript.sh

脚本本身基本上和问题一样,但它永远不能调用send_key ctrl+shift+c,否则它会循环。您可以发送任何其他密钥(除非您最终会在多个脚本的奇怪吸引子之间循环,但那是您的问题!)