alols / xcape

Linux utility to configure modifier keys to act as other keys when pressed and released on their own.
GNU General Public License v3.0
2.1k stars 117 forks source link

make enter key act as 'super' key when held #58

Closed vyp closed 8 years ago

vyp commented 8 years ago

As the title says, I want to make the enter key act as an extra modifier as the 'super' key (i.e. the 'windows' key) when held (as part of a key chord), but act as a normal enter when just pressed by itself.

Following from the example in the README, I tried the following:

spare_modifier='Hyper_L'
xmodmap -e "keycode 36 = $spare_modifier" &
xmodmap -e "remove mod4 = $spare_modifier" &
xmodmap -e "add Super_R = $spare_modifier" &
xmodmap -e 'keycode any = Return' &
xcape -e "$spare_modifier=Return" &

in .xinitrc, but it didn't seem to work. As in, the enter key still works, produces an enter when you tap the enter key. But holding it down and pressing it as part of a chord does not produce a Super_R.

36 is the keycode for 'Return' (enter key), got from xev.

What am I doing wrong?

vyp commented 8 years ago

As a potential workaround, anyone know if there is a way to use setxkbmap to set 'Return' as rwin? That way I should be able to just do xcape -e 'Super_R=Return' I think. But unfortunately it seems the manual for setxkbmap is not too informative so I cannot figure out if it is possible and if so, how.

vyp commented 8 years ago

I brilliantly managed to miss the point about valid MODIFIERNAMEs for the clear expression in the man page for xmodmap. So the add Super_R above will not work because Super_R is not a valid MODIFIERNAME! :expressionless: So it is fixed by using setxkbmap to set rwin as Mod3:

setxkbmap -option 'lv3:rwin_switch' &
spare_modifier='Hyper_L'
xmodmap -e "keycode 36 = $spare_modifier" &
xmodmap -e "remove Mod4 = $spare_modifier" &
xmodmap -e "add Mod3 = $spare_modifier" &
xmodmap -e 'keycode any = Return' &
xcape -e "$spare_modifier=Return" &

(the &s because it's from .xinitrc)

This seems to work by my rudimentary testing.

I'm not sure if setting Mod3 to rwin is the best/correct way to solve this, but nevertheless I will close this at least until I find in the future that this is insufficient. Anyhow, sorry for the noise.

vyp commented 8 years ago

Unfortunately the above does not seem to work anymore. By which I mean that the enter key works as normal, but does not produce a Super_R when held as part of a chord. (The actual Super_L key and all the Super bindings still work as normal.) So what happened was it worked like maybe once or twice (as in, after boot), but then now everytime I boot up it doesn't work anymore! Same exact setup, no new software installed, no new updates in the meantime (100% sure of that). So I'm going to reopen because I haven't been able to figure out the solution despite spending considerable time on this.

So I think it might be something to do with these commands (setxkbmap/xmodmap) having some sort of state across boots? However, I do know that running setxkbmap -option '' first resets everything (even xmodmap commands), and putting that command first and running all the same commands again does not seem to change anything.

Using xev I see that with the above block of commands (in the previous comment), tapping the enter key produces a Return (as expected), but holding it produces Hyper_L, instead of Super_R as I would expect...

I think the problem though might be that setxkbmap -option 'lv3:rwin_switch' is not setting mod3 to rwin anymore, because the output of xmodmap does not show Super_R in the mod3 row...

vyp commented 8 years ago

Edit: I ended up switching fully to interception-tools for this: https://github.com/vyp/dots/tree/98cd30599945d11ed9a2b10e52487b6581995e2d/interception-tools/plugins


To my surprise (because I was trying all this other more 'complicated' stuff), the following works, at least for the moment (I rebooted twice to see if it was persistent across boots, and it seems like it is):

xmodmap -e 'keycode 36 = Super_R'
xmodmap -e 'keycode any = Return'
xcape -e 'Super_R=Return'

This may be the 'proper' solution too because at least it doesn't mess with mod3 (or mod4). But that does bring up the question, why does the example in the readme mess with mod4 and Hyper_L instead of just doing something like the above? (To be fair, I haven't actually tried the example in the readme for myself, nor have I tried something similar to the above, but for space+control, either. But this just seems so much easier to understand and less prone to error, hence the curiousity.)

Now just for the sake of being complete, and also if anyone reading wants to be able to reproduce what I'm doing fully, I not only use xcape for changing the behaviour of the enter key, but I also use it for the more standard use case of making control act like escape if tapped, or just control when held as normal. So combining the above with that is the following, which I have in my .xinitrc:

setxkbmap -option ''
setxkbmap -option 'ctrl:nocaps'
xmodmap -e 'keycode 36 = Super_R'
xmodmap -e 'keycode any = Return'
xcape -e 'Super_R=Return'
xcape -e 'Control_L=Escape'
xcape -e 'Control_R=Escape'

The first setxkbmap command I believe resets all prior setxkbmap/xmodmap modifications, if any, just in case (even though that doesn't make sense because this in the .xinitrc). I put the setxkbmap commands first because each setxkbmap supposedly resets all prior xmodmap bindings. Then I put all the xmodmap commands before the xcape commands because of the note in the readme.

The second setxkbmap command is only related to the escape+control duo (and not to enter+super). But all it just does is make the caps lock key become a control key instead (whilst also keeping the other two standard control keys). As a vim/emacs user, I won't be missing the normal functionality of the caps lock key anyway. And of course the last two xcape commands are also related to escape+control, nothing to do with enter+super.

Yes, none of the commands have &s at the end just to be sure they run completely synchronously, because it's likely that some order matters here (so you don't want race conditions randomly on boot).