6

Context

I use xkbset to enable sticky keys:

xkbset sticky -twokey latchlock ## set sticky keys, don't disable via twokey
xkbset exp 1 =sticky ## don't expire sticky keys

That does exactly what I want, allowing me to tap and release the Shift key, and then press another key and get the 'shifted' value. Double-tapping Shift gives me CapsLock, and the same works for Ctrl, Alt, Hyper.

However, I sometimes get stuck with one or more of the modifiers in the 'locked' setting, and it can be difficult to figure out which ones are triggered in order to release them.

Question: Is there a way to 'timeout' the sticky keys?

Meaning, if I've pressed a sticky modifier, or locked a modifier, to have it revert to normal after 5 seconds or so without any further key presses.

I know that I can use xkbset to expire a setting after a set time, but that turns off the sticky keys entirely. What I want is to release all modifiers after a few seconds of inactivity, but to keep the sticky keys behaviour when I next press a modifier key.

EDIT

To clarify the difference, if I use the expire options, what I would get is:

  • I turn on shift lock by tapping Shift twice.
  • I accidentally lock control by tapping Ctrl twice.
  • confusion follows, as pressing A results in Ctrl-Shift-A being entered.
  • After the expire period, the 'stuck' shift and control modifiers are removed, but modifiers are no longer sticky - tapping Shift and then pressing A, I get a regular a, not a shifted A

Instead, I would like the following behavior after the "confusion follows" point:

  • I wait three seconds, and then the 'stuck' shift and control modifiers are removed (i.e., pressing a produces an a), but modifiers are still sticky - tapping Shift and then pressing a, I get a shifted A.

I'm using the i3 window manager, so ideally I'd like a solution that doesn't depend on a full desktop manager suite.

Alternative: automatically call a script (once) after a period of keyboard inactivity?

As a workaround, I've defined a keyboard shortcut that will reset my xkbset configuration regardless of which modifiers are pressed (i.e., PrintScr, Shift+PrintScr, Ctrl+Shift+PrintScr etc are all bound to the same script). Running this script automatically after 5 seconds of keyboard inactivity would do what I'm after.

2 Answers 2

1

The solution to the question seems to be a script like the following using xprintidle to work out when to reset the lock state. Note that it has a polling loop, so it needs to keep running continually.

#!/bin/bash

# Sets sticky keys, but has them reset state (e.g. latchlock goes back to normal) after
# a few seconds

IDLE_RESET=3000 # 3 seconds

# Set up sticky keys and double tap to lock
xkbset sticky -twokey latchlock
# Disable XAccess managed sticky mode timeout
xkbset exp =sticky =latchlock

# Sentinel so we only run the reset once every idle period
sentinel=0
while true;do
    if [ $(xprintidle) -gt $IDLE_RESET ];then
        if [ $sentinel = 0 ];then
            # Reset the state
            xkbset -sticky -twokey -latchlock;xkbset sticky -twokey latchlock
            sentinel=1
        fi
    else
        sentinel=0
    fi
    sleep 1
done
0

The help text for xkbset suggests that any AccessX feature can be automatically disabled after a given timeout:

To set the AccessX expire controls:

  xkbset exp <options>

where <options> may be all or any of (<ax_timeout> is the timeout (in
seconds) after which no user activity on X will cause the expiry; '-'
indicates the feature will be switched off, '=' incicates the feature
will be left unchanged, otherwise it will be switched on):

<ax_timeout>
[-|=]{bell|b}
[-|=]{repeatkeys|r}
[-|=]{mousekeys|m}
[-|=]{mousekeysaccel|ma}
[-|=]{accessx|a}
[-|=]{sticky|st} [[-|=]twokey|[-|=]latchlock]...
[-|=]{slowkeys|sl}
[-|=]{bouncekeys|bo}
[-|=]{feedback|f} [[-|=]dumbbell|[-|=]led|[-|=]feature|[-|=]slowwarn|
  [-|=]slowpress|[-|=]slowaccept|[-|=]slowreject|[-|=]slowrelease|
  [-|=]bouncereject|[-|=]stickybeep]...
[-|=]{overlay1|ov1}
[-|=]{overlay2|ov2}
[-|=]ignoregrouplock

And an example on the Ubuntu wiki shows the following command-line to do this:

# setting the expiry of the accessx settings
/usr/bin/xkbset exp -bell -sticky -twokey -latchlock -accessx -feedback -stickybeep -led
2
  • 1
    Yes, I mentioned that in my question. The expire controls allow me to permanently disable the AccessX features after a set period. i.e., my shift, control and alt keys would no longer be sticky. That's not what I want - I want the modifiers to remain sticky, but to have them revert to the unmodified condition.
    – Tyler
    Mar 11, 2020 at 14:30
  • So, write a script that checks if AccessX has been disabled and re-enables both the timer and the desired settings again, and have that script run in the background, looping every few seconds. Mar 11, 2020 at 17:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.