Tap & Hold keymaps - OBSD
2020-10-24
I have made a previous post living fullest - home row workflow by remapping keys to behave differently on tapping. (works regardless of X11 or wayland)
It was based on interception-tools which uses libudev and libevdev these are not *BSD-specific (there's an interesting libudev-devd implementation for FreeBSD though)
The only way AFAIK to achieve on OBSD is using xcape (happy puffer noises, it's in ports hearty thanks edd and sthen!) along with xmodmap(1)
- Caps_Lock as Escape and Control_L - previously I used meta_L (as mod in i3) yet to figure fvwm keybinds
- semicolon as Control_R on holding
- Tab as Alt_L on holding
xcape adds only extra keysym on tapping with certain timeout so holding a key longer than the timeout, functions same. In order for key, say semicolon to generate control on holding it should mapped to that first using xmodmap (with some extra bits since control mod1 mod2 .. are special keys)
Running xmodmap
will list all the modifiers.
general syntax xmodmap+xcape
First, remove the useless key (guessed it right) - Caps_Lock
xmodmap -e "remove Lock = Caps_Lock"
To avoid confusions, I'm using keycodes (it's a code representing physical keys so it won't change no matter what the key is generating)
using xev(1), the keycode of caps is 66
xmodmap -e "keycode 66 = Contrl_L"
xmodmap should be informed that newly mapped 66 is needed to function as control ie when Ctrl+C Ctrl+some_key is pressed
xmodmap -e "add Control = Contrl_L"
To generate Escape when tapped
xcape -e "Control_L=Escape"
Pseudo Keycode - for extra modifier
Holding Tab key should generate alt, the keycode being 23
xmodmap -e "keycode 23 = Alt_L"
appending 23 to mod1 list
xmodmap -e "add mod1 = Alt_L"
all done?
xcape -e "Alt_L=Tab"
This throws error, complaining keysym Tab isn't mapped to any keycodes. To avoid, map it to random keycode then run above
xmodmap -e "keycode any = Tab"
xcape -e "Alt_L=Tab"
Workaround for Shift+key lag
Similar can be done for semicolon (keycode 47)
xmodmap -e "keycode 47 = Control_R colon"
xmodmap -e "add Control = Control_R"
xmodmap -e "keycode any = semicolon"
xcape for generating semicolon on tap
xcape -e "Control_R=semicolon"
Problem with above, xcape cannot differentiate states
(state 0x1 for shifted) so Shift+semicolon
generates
:;
Decreasing tap timing with xcape -t 95
is not reliable,
sometimes ;
gets missed. I have tinkered with xset delay and
frequency
xset r rate 1200 12
nothing useful, it's how xcape
works.
For colon I have to hold left_shift and press semicolon (2 key strokes), since tapping shift_l remaining usued, it felt the most intuitive way (overcomes the lag + saving a key stroke)
xmodmap -e "keycode any = colon"
xcape -e "Shift_l=colon"
Conf Persist on Startup
xmodmap's config file
remove Lock = Caps_Lock
! keycode 66 Caps_Lock
! to control & esc on tap
keycode 66 = Control_L
add Control = Control_L
! xcape -e "Control_L=Escape"
! keycode 66 Caps_Lock
! to super (logo key) & esc on tap
! keycode 66 = Super_L
! add mod4 = Super_L
! xcape -e "Super_L=Escape"
! keycode 47 semicolon
! to control, semicolon on tap
keycode 47 = Control_R
add Control = Control_R
keycode any = semicolon
! xcape -e "Control_R=semicolon"
! keycode 50 Shift_L
! tap as colon
keycode any = colon
! xcape -e "Shift_L=colon"
! keycode 23 tab
! as alt, tab on tap
keycode 23 = Alt_L
keycode any = Tab
add mod1 = Alt_L
! xcape -e "Alt_L=Tab"
Adding before wm startup on ~/.xsession
# xinput essentials
.
.
# keymaps
xmodmap ~/.xmodmap_conf &
xcape -e " Control_L=Escape;Control_R=semicolon;Alt_L=Tab;Shift_L=colon" &
# bg term wm
.
.
/usr/X11R6/bin/fvwm
funky X
I'm confused by different ways other than xmodmap.. xkbcomp(1), setxkbmap(1), wsconsctl(1). I cannot keep track of all, the worst experience I had was with wsconsctl - none worked even the annoying keyboard bell (there's only one hotplugged keyboard it's supposed to work, no dice)
setxkbmap is (supposed) successor of xmodmap but they differ in usecase, it's easier if inbuilt option is present
# caps as control and escape on tapping
setxkbmap -option "caps:ctrl_modifier"
xcape -e "Caps_Lock=Escape"
# caps as super and escape on tapping
setxkbmap -option "caps:super"
xcape -e "Caps_Lock=Escape"
more -option on xkeyboard-config(7)
clearly XKB looks simple compared to xmodmap but I failed at making config for other keys following convoluted docs (=_=)
If someone want to experience the pain, I highly recommend
Evil Tip
For some reason if you want to revert back to RSI causing vanilla layout, setxkbmap can override xmodmap
# with no option present it maps to pre-defined layout
setxkbmap -option
# and kill xcape
pkill xcape
End notes
Even with the limitations, xcape is highly usuable I'm happy how it turned. Now that I have filled gaps of OBSD being my daily driver, what's left is figuring FVWM(2?)