long / short press
is there a way to do a long press different output than short press, for example:
lets say theoretical parameter hold for 0.5 second would give me b and holding it for 1 second would give me c
evsieve --input /dev/input/by-path/* grab --hook key:a send-key=key:b hold=0.5 --hook key:a send-key=key:c hold=1 --withhold key:a --output
btw the tool is great, it doesn't affect other remaps, so thank you
A somewhat convoluted way to get this done with the current version of evsieve would be the following script:
evsieve --input /dev/input/by-id/YOUR_KEYBOARD domain=in grab \
--map key:a:0@in key:info:1@a-is-released key:info:0@a-is-released key:a:0@in \
--hook key:a@in key:info@a-is-released period=0.5 send-key=key:a@out \
--withhold key:a@in \
--hook key:a@in key:info@a-is-released period=0.5 send-key=key:b \
--withhold key:a@in \
--hook key:a@in key:info@a-is-released send-key=key:c \
--withhold key:a@in \
--block key:info@a-is-released \
--output
I don't think there is a nonconvoluted way to get this done right now. That said, a clause for --hook to only trigger if its keys are held for a certain minimum/maximum amount of time is potentially a good idea though. I'll consider implementing it after I am done stabilizing version 1.5.0.
To explain the convoluted script:
The first map generates an arbitrary token keypress (key:info@a-is-released) whenever you release the A key, and puts that keypress into the event stream before the key:a:0 event.
The next hooks make use of the period=0.5 clause, which causes the hook to only activate if the keypress key:info@a-is-released is observed within 0.5 seconds after seeing the key:a:1@in event.
Each of the --withhold arguments causes the key:a:1@in event to be dropped if the preceding hook activates, or causes the key:a:1@in event to be delayed by 0.5 seconds if the corresponding key:info:1@a-is-released event is not observed within that timeframe.
This means that the key:a:1@in event will wait 0.5 seconds on the first hook and withhold, then advance to the second hook and withhold and wait another 0.5 seconds, and finally move on the the third hook&withhold and wait there indefinitely until either key:a is released or a key:info:1@a-is-released event arrives.
Finally, the first hook uses send-key=key:a@out to send the key:a event to the output device if the user presses the A key for less than 0.5 seconds. In order to not confuse this key intended for the output device with a key from the input device, all other key:a events have been specified as key:a@in.
I knew it was possible with some voodoo :), thanks, but the short version in the future would be nicer, thanks anyways
I've created a variation of @KarsMulder's script which triggers without needing to release the key, and thought I should share. In this example, if you hold a, the b key will be sent as soon as 1 second as elapsed. If you hold a for less than 1 second, nothing will happen.
--map key:a:0 key:info:1@released key:info:0@released key:info:0@repeat
--map key:a:2 key:info:1@repeat
--hook key:info@repeat key:info@released period=1
--withhold key:info@repeat
--copy key:info:1@repeat key:info:0@repeat
--toggle key:info@repeat @repeat @null id=hold-a
--hook key:info@repeat toggle=hold-a:2
--hook key:info@released toggle=hold-a:1
--hook key:info@repeat send-key=key:b
--withhold key:info@repeat
--block key:a key:info@repeat key:info@released @null
There's even more going on here than the original, so let me try to break it down line by line:
- 1: An
akey press event is mapped to a key press and key release ofkey:info@released, same as the original. Additionally, a key released forkey:info@repeatis sent. This is to make sure that the proceedinghookis reset, in caseawas previously held for less than 1 second. - 2: An
akey repeat event is mapped to a key press (but not a key release!) ofkey:info@repeat. It's important not to have a key release here, since a key release event would prevent the hook from ever firing. - 3 & 4: A hook based on
key:info@repeatandkey:info@releasedprevents the events stream from continuing until the period has elapsed, similar to the original. - 5: If we've made it past the hook, we can safely turn the "held"
key:infoevent into a proper key-press and key-release pair, so it can trigger the proceeding hooks. - 6: We need a way to make sure that the output doesn't fire on each
@repeatevent, so we can use a toggle which will let the first@repeatevent through, but discard the remaining@repeatevents. By default, events are kept in the@repeatstream, but they can be toggled into the@nullstream which are later discarded. - 7: When
key:info@repeatevent is received, we switch the toggle to the@nullstream, so any futurekey:info@repeats will not be let through. The currentkey:info@repeatcontinues through the stream, however. - 8: Whenever the
@releasedevents are eventually received, we know it is safe to reset the toggle back to@repeatrather than@null. This way, futurekey:info@repeatevents are able to proceed through the stream as normal. - 9 & 10: If we've reached this point and have a
key:info@repeatevent, then it must be the firstkey:info@repeatwhich was held back for 1 second. We can now send the output event (thebkey). - 11: Block undesired keys from the output.
The basic idea is similar to the original concept, but there's some extra complexity around managing the key release event for key:info@repeat and making sure that we only trigger the output once per key hold. Also note, the actual time it will take for the event to trigger will be a bit longer than the specified period, since the timer won't start until the key repeat events start.