Reputation: 6372
I am trying to convert firefox-ctrl-q-workaround to also handle Ctrl-Shift-C. This is because I keep using Ctrl-Shift-C in Firefox by mistake and popping open Developer Tools all the time is getting tedious. Firefox, incredibly annoyingly, does not have any way of configuring shortcuts.
The setup looks broadly like this:
First, bind the key in i3 to a script:
# i3 config
bindsym --release Control+Shift+c exec --no-startup-id ~/ctrl_c_map.sh
And the script itself looks like:
# This is the active window
W="$(xdotool getactivewindow)"
# Get window class
WM_CLASS="$(xprop -id "$W" | awk -F '"' '/WM_CLASS/{print $4}')"
# Succeed if the WM_CLASS is firefox
is_firefox() {
[ "$WM_CLASS" == "firefox" ] || [ "$WM_CLASS" == "Firefox Developer Edition" ]
}
send_key() {
keytosend=$1
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
This works in Firefox - the Ctrl-Shift-C event is caught and remapped to a Ctrl-C, and any selected text is copied. Horray!
However, in any other program (specifically in a terminal where Ctrl-Shift-C is genuinely useful), there's a problem. When the ctrl+shift+c
key is sent using xdotool
, i3 catches it again and fires the script again, landing us in an infinite loop that you can only escape by mashing Ctrl/Shift. Moreover, the target window never gets its Ctrl-Shift-C key: it's endlessly circulating between i3 and bash, but never actually arriving.
How can you send the same bound key from within an i3 bindsym
-triggered script without a infinite loop?
Upvotes: 1
Views: 1178
Reputation: 6372
[This isn't really an answer to the question (how to stop infinite loops between xdotool and i3), but it's an alternative that is more flexible that the i3 bindsym [class="firefox"]
approach in case you need to execute more logic that might send the original key. If you know you'll never send the original key, @meuh's answer is simpler and it's what I'm using right now.]
Add a new script to autokey. To disable the key entirely, leave the script empty. To send Ctrl+C, it's simply:
# Send Ctrl-C instead of Ctrl-Shift-C
keyboard.send_keys('<ctrl>+c')
Set the hotkey to <ctrl>+<shift>+c
and the window filter appropriately. In my case, Navigator.firefox
is what it detected with it's built-in tool.
That's it.
You can add logic to this script to dispatch different keys, including the original key, (or nothing) to the program as needed.
If you will never send the same key as the trigger, and you always want to send the same replacement key, you should use @meuh's answer. You can also call a script to do the key dispatch if the key you want send might be different (e.g. Ctrl+C in Firefox or Alt+C in some other program).
Critically, as in @meuh's answer, you use the class
filter to prevent calling the script any time you would send the original key. It's a regex, so you can have multiple filters:
# i3/config
bindsym --release Control+Shift+c [class="(firefox|other_prog)"] exec ~/myscript.sh
The script itself is basically as in the question, but it can never call send_key ctrl+shift+c
, or it'll loop. You can send any other key (unless you'd end up looping between a strange attractor of multiple scripts, but that's your problem!)
Upvotes: 3
Reputation: 12255
Perhaps you could restrict the match on Control+Shift+c
by using criteria which matches just firefox, something like
bindsym Control+Shift+c [class="Firefox"] exec xdotool key --clearmodifiers ctrl+c
Upvotes: 2