Rolling overload: when the release of the first key happends before the release of the second key
I configured
capslock = overload(control, capslock)
in order to have capslock behaving like control unless I just type it, in which case it should behave like capslock.
Unfortunately, when I type stuff like C-a, I naturally do a rolling movement, resulting in the following event:
- press capslock
- press a
- release capslock
- release a
Unfortunately, it seems like
overloadwill consider this as a kind of tap (but not exactly as capslock is not enabled)… at least it printsainstead of selecting the text.
Is there a way to consider also this sequence as a valid overload? Or am I missing something?
That sequence should indeed emit C-a. Are you sure your config is correct? What is your full config and the output in the logs? (journalctl -u keyd on systemd-based systems)
Thanks for your quick answer. So I'm using 2.4.3 and indeed if the config is only:
$ cat /etc/keyd/test.conf
[ids]
*
[main]
capslock = overload(control, capslock)
then it works as intended. But if I do:
[ids]
*
[main]
capslock = overload(control, capslock)
# Without the dt version, typing 'at' really quickly would move the cursor instead of typing 'at'
a = overloadt(arrows, a, 200)
[arrows]
k=up
j=left
l=down
;=right
h=C-right
'=C-left
i=C-up
o=C-down
then the behavior I mentionned starts with the later a. Similarly, if I press really quickly shift + a, then a will not be printed in upper case letter.
$ journalct -u keyd
mai 22 18:08:52 bestos systemd[1]: Stopped Keyd remapping daemon.
mai 22 18:08:52 bestos systemd[1]: keyd.service: Consumed 1.628s CPU time, no IP traffic.
mai 22 18:08:52 bestos systemd[1]: Started Keyd remapping daemon.
mai 22 18:08:52 bestos keyd[1669277]: WARNING: failed to set effective group to "keyd" (make sure the group exists)
mai 22 18:08:52 bestos keyd[1669277]: CONFIG: parsing /etc/keyd/test.conf
mai 22 18:08:52 bestos keyd[1669277]: Starting keyd v2.4.3 ()
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: ignoring 0fac:1ade (keyd virtual pointer)
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: ignoring 0002:0001 (PS/2 Generic Mouse)
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: ignoring 0488:121f (DELL08B9:00 0488:121F Touchpad)
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: ignoring 0488:121f (DELL08B9:00 0488:121F Mouse)
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: ignoring 03f0:6141 (HP 280M HP 280 Silent Wireless Mouse Consumer Control)
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: ignoring 03f0:6141 (HP 280M HP 280 Silent Wireless Mouse)
mai 22 18:08:52 bestos keyd[1669277]: DEVICE: match 0001:0001 /etc/keyd/test.conf (AT Translated Set 2 keyboard)
Ah, gotcha. The problem is not with the capslock = overload(...) but with the a = overloadt(...). When you tap a, it will emit the macro a, but it either emits it too late (after keyup, so you will have released capslock and thus control already), or it just doesn't stack in general. I don't remember which it is, and will investigate more later, but for now I think you should be able to explicitly override the overlapping case like this:
[main]
capslock = overload(control, capslock)
a = overloadt(arrows, a, 200)
[control]
a = C-a
[arrows]
# ...
Thanks a lot, I'm not sure to understand what this changes but it seems to fix this bug. I also did:
[shift]
a = S-a
and it seems to fix the bug with shift-A… not sure why, is it because the signal is sent twice?
EDIT
Oh, I guess this behaves as a priority, where if control is already typed then it sends C-a instead of the overloadt. So I might want to do it for all modifiers.
Oh, I guess this behaves as a priority, where if control is already typed then it sends C-a instead of the overloadt. So I might want to do it for all modifiers.
Yes, exactly, that's how the solution works.
Ideally, I suppose you shouldn't need it: when overload is activated, whatever modifiers were active at the start of the keypress should be applied to the emitted macro when the overloaded key is released, even if that modifier is no longer active. But I'm not sure that is desirable in all situations. What do others think?
But I'm not sure that is desirable in all situations. What do others think?
I guess in some cases it might be desirable to sent an event without the modifier active? I guess I lack experienced with keyd use cases to judge here…
But actually, now I experienced two issues: if I press slowly a followed by a key outside the layer arrows, say y, (this occurs sometimes when I'm not typing fast enough normal text) then it will print y but not a, while I would expect this to print ay. Is there a way to force this behavior?
You would have to add bindings like y = macro(a y) inside the arrows layer: unbound keys do fall through other layers by default, but they still also have to effectively go back and add the key that activated the layer in the first place. Of course, this only works for overlaps of length 1, so even apart from the verbosity it's not perfect. I'll reference some previous issues regarding this later.
Ok thanks! It's indeed not ideal, but I guess better than nothing…
It just occurred to me that making an [empty] layer and binding y = swapm(empty, macro(a y)) would make it work for longer overlaps too. Still not ideal, but one problem down!
Oh, I guess this behaves as a priority, where if control is already typed then it sends C-a instead of the overloadt. So I might want to do it for all modifiers.
Yes, exactly, that's how the solution works.
Ideally, I suppose you shouldn't need it: when
overloadis activated, whatever modifiers were active at the start of the keypress should be applied to the emitted macro when the overloaded key is released, even if that modifier is no longer active. But I'm not sure that is desirable in all situations. What do others think?
I think that's how it should work. I had the same problem with overloading "a"
a = overloadi(a, overloadt2(<custom_layer>, a, 200), 150)
since i use tmux/screen a lot pressing C-a very quickly resulted in
leftcontrol down
leftcontrl up
a down
a up
however adding priority to [control] layer fixed this for me as well
So to continue this issue, I realized that the priority solution does not work for the altgr modifier (or I can't make it work). I tried to add a section:
[rightalt]
a = G-a
f = G-f
without success: pressing quickly altgr+f (or actually e when in bépo mode) produces e instead of €. Any idea why it works for all of them but this one?
Full code:
[ids]
*
[main]
capslock = layer(control)
f1+f2=capslock
# Without the dt version, typing 'at' really quickly would move the cursor instead of typing 'at'
a = overloadt(arrows, a, 200)
f = overloadt(numbers, f, 200)
# https://github.com/rvaiya/keyd/issues/756
[control]
a = C-a
f = C-f
[shift]
a = S-a
f = S-f
[rightalt]
a = G-a
f = G-f
[meta]
a = M-a
f = M-f
[leftalt]
a = A-a
f = A-f
#capslock = overload(control, capslock)
#a=lettermod(layer(arrows), a, 150, 200)
#a = overloadi(a, overloadt2(layer(arrows), a, 200), 150)
#a = overloadi(a, overloadt2(control, a, 200), 150)
[numbers]
space=kp0
m=kp1
,=kp2
.=kp3
j=kp4
k=kp5
l=kp6
u=kp7
i=kp8
o=kp9
;=oneshot(allLayers)
[allLayers]
f=oneshot(emojiLayer)
[emojiLayer]
j=😉
# Mapping:
# C-^
# C-backspace backspace ^ delete C-delete
# C-< < v > C->
# Pageup Home C-v End Pagedown
# This is not only super easy to remember, mimics the usual arrow shape, but also quite ergonomic. I tried to put before
# all arrows on the same line like in vim, but I ended up using the pinky way too much in
# a repetitive fashion, leading to some pain.
[arrows]
k=down
j=left
l=right
i=up
h=C-left
;=C-right
8=C-up
,=C-down
u=backspace
o=delete
y=C-backspace
p=C-delete
m=home
.=end
n=pageup
/=pagedown
Oh, another related question: when I press a + x in a slow rollup motion, I have only x printed. I tried to add to the above configuration:
[arrows]
x=macro(a x)
This works… but it means that I need to repeat this for all letters that I often type in a rollup fashion… which is really tedious, especially when we have many layers. And it also only works when I know the key pressed to access the layer. A solution to this issue would be great!
Arg, it seems like I'm missing something… So to continue my epic journey (that is actually very pleasant except for these minor issues), I noticed something different: if I press in a relatively slow motion something like a x, it only prints x instead of a x (note that I don't associate any special action for x)… I guess this is because once we switched to the arrow layout, keyd kind of forgets that we arrived there from a, but it is quite annoying. So then the solution is to write:
[main]
a = overloadt(arrows, a, 200)
[arrows]
x=macro(a x)
… repeat for all letters that are not bound to an action.
but this has multiple issues:
- first it is really not elegant (who wants to write 15 lines for each layer?)
- then, the layer needs to know how it is called (here by pressing
a) so that we can writex=macro(a x) - most importantly, it has some annoying side effects, for instance when rolling
aef(which is needed in bépo), it createsaeafinstead.
Any idea why it works for all of them but this one?
rightalt is a key name. altgr is the corresponding layer name. So try [altgr] ;)
most importantly, it has some annoying side effects, for instance when rolling
aef(which is needed in bépo), it createsaeafinstead.
Perhaps you can do:
[main]
a = overloadt(arrows, a, 200)
[empty]
[arrows]
x=swapm(empty, a x)
… repeat for all letters that are not bound to an action.
This would also deactivate the arrows layer as soon as you press a key that is not bound to an action.
I fear that the other issues are going to be solvable only with more additions to keyd that have been discussed elsewhere --- I agree that the current solution is not ideal. Though until then, it may be good to remember the include mechanism to avoid egregious repetitions.
rightalt is a key name. altgr is the corresponding layer name. So try [altgr] ;)
Oh good point, it works, thanks a lot!
Perhaps you can do
x=swapm(empty, a x)
Hum thanks… So it gets better, but still not 100% perfect (but it's starting to be fairly usable): doing x=swapm(empty, macro(a x)) (I guess your code was a typo, because if I use it the a gets removed when pressing a x slowly) works for rolling keys which are not themself lead keys. But if the 3rd key is a lead key (with overloadt as above), the last key is never printed. So I tried to change the empty layer into:
[empty]
a=a
b=b
c=c
d=d
e=e
f=f
g=g
h=h
i=i
j=j
k=k
l=l
m=m
n=n
o=o
p=p
q=q
r=r
s=s
t=t
u=u
v=v
w=w
x=x
y=y
z=z
Now, the third key is printed if I press the three keys and then release them like press a; press e; press f; release a; release e; release f, it prints aef as expected. But if I do press a; press e; release a; press f; release e; release f, it prints ae instead of aef. Don't know if it is possible to solve this in a clean way…
Though until then, it may be good to remember the include mechanism
Oh good to know. But is it really helping here? Cause the file is dependent on the key that was called before, so x=swapm(empty, a x) would be something else in another layer depending on how it is called.
Could this be the same as #731 ?