Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: idle timer fake_key_depress_timer #502

Closed
gerhard-h opened this issue Jul 28, 2023 · 10 comments · Fixed by #512 or #528
Closed

Feature request: idle timer fake_key_depress_timer #502

gerhard-h opened this issue Jul 28, 2023 · 10 comments · Fixed by #512 or #528
Labels
enhancement New feature or request

Comments

@gerhard-h
Copy link
Contributor

Is your feature request related to a problem? Please describe.

lately my typing speed improved slightly and now my home row shifts I run into issues shifting to much.

e (tap-hold 1 160 e lsft) 
n (tap-hold 1 160 n rsft) 

example typing eine I get eiN ( maybe a timing issue maybe I really typed eien) then I still want eien as output to show the typing error and encourage correction and further speed improvment.

Describe the solution you'd like.

Intstead of diving into the tap-hold timings, my idea is:
disable home row shifts while typing fast
enable it after special keys: spc ret ctl
enable it when idle or after timeout

since I have no idea to define typing fast I would go with typing any letter
like this for all letters:
aletter (multi (on-press-fakekey nosft_fk press) aletter )

but how to release after timeout?

I would like
(onidle 150 (on-press-fakekey nosft_fk release))

Describe alternatives you've considered.

Maybe a more generel timeout system has more usecases

(deftimeout mytimeoutname)
(update-timeout mytimeoutname 150 (action))

or it could be in the fake key
(on-press-fakekey-timeout nosft_fk press 150 release)

Additional context

No response

@gerhard-h gerhard-h added the enhancement New feature or request label Jul 28, 2023
@jtroo
Copy link
Owner

jtroo commented Jul 29, 2023

This seems like a nice solution for the use case described here:
#499 (comment)

It seems the proposed solution has some cases where the one shot key is unintentionally ended early by some actions, e.g. the tap action of a tap-hold.

Implementation details:

As you suggested, I think using fake keys is the easy approach since it's the easiest way to activate arbitrary actions that aren't mapped in a deflayer.

This is probably better to add in kanata than in keyberon since it operates on fake keys. Gotta remember to update can_block.

Should deduplicate multiples of identical on-idle for efficiency reasons.

@gerhard-h
Copy link
Contributor Author

gerhard-h commented Aug 8, 2023

whow you was fast with this.

though if I understand correcly on-idle-fakekey must be called AFTER the idle periode has happend?

like releasing the shift blocker key the next time I hit shift

(multi
     (on-idle-fakekey noshift_fk release 200 )
     (tap-hold 1 160  f  lsft) 
)

that maches my use case.

May be the docs should use past tense: Activate a fake key action if the keyboard has been idle for at least...

else people (like) me could believe they could schedule an event, that happens without a key press.

@jtroo jtroo reopened this Aug 8, 2023
@jtroo
Copy link
Owner

jtroo commented Aug 8, 2023

Sounds good, thanks for the suggestion to improve doc clarity :)

I also reopened since I'm finding some weirdness with how long it takes for the "post-idle" state to be done, that needs some looking into.

@jtroo jtroo linked a pull request Aug 9, 2023 that will close this issue
@gerhard-h
Copy link
Contributor Author

sadly me test procedure was wrong, it seems not to work for me. nosft_fk is F22
tap i
(multi (on-press-fakekey nosft_fk press) i )

 [DEBUG] (2) kanata::kanata: key release   I
 [DEBUG] (2) kanata::oskbd::windows::interception: kanata sending Keyboard { code: I, state: UP, information: 0 } to driver
 [TRACE] (2) kanata::kanata: [src\kanata\mod.rs:641] [F22, F22, F22, F22]
 [TRACE] (2) kanata::kanata: [src\kanata\mod.rs:644] F22 is old press
...
 [TRACE] (2) kanata::kanata: [src\kanata\mod.rs:1467] blocking on channel

so the fake key presses F22 as intended

then I press

(multi
      (on-idle-fakekey nosft_fk release 1 )
      (tap-hold 1 160 e  lsft) 
 )

and f22 does not get released

[TRACE] (2) kanata::kanata: [src\kanata\mod.rs:641] [F22, LShift]
[TRACE] (2) kanata::kanata: [src\kanata\mod.rs:644] F22 is old press
[DEBUG] (2) kanata::kanata: key press     LShift
[DEBUG] (2) kanata::oskbd::windows::interception: kanata sending Keyboard { code: LeftShift, state: DOWN, information: 0 } to driver
[TRACE] (2) kanata::kanata: [src\kanata\mod.rs:628] [F22, LShift]
[TRACE] (2) kanata::kanata: [src\kanata\mod.rs:641] [F22, LShift]

May be the (interception) keyboard is not considered idle because F22 is pressed?

@jtroo jtroo closed this as completed in #528 Aug 9, 2023
@jtroo jtroo reopened this Aug 9, 2023
@jtroo
Copy link
Owner

jtroo commented Aug 9, 2023

That's not an interception thing, but rather that's how on-idle currently behaves.

I tried this out and found a config that works for me. The dvorak-tp layer is the "typing" layer. The idle time is quite small because the time-to-idle only starts after kanata is completely idle. Meaning if you overlap keys as part of typing, there will be zero chance for the on-idle action to activate. Partial config:

(deffakekeys
  to-dvorak (layer-switch dvorak)
)

(defalias
  ;; alias to cancel tap-hold keys if typing rapidly but restore after a shord idle period
  tp (multi
    (layer-switch dvorak-tp)
    (on-idle-fakekey to-dvorak tap 35)
  )

  ' (multi ' @tp)
  , (multi , @tp)
  p (multi p @tp)
  y (multi y @tp)
  f (multi f @tp)
  g (multi g @tp)
  c (multi c @tp)
  r (multi r @tp)
  l (multi l @tp)
  / (multi / @tp)
  = (multi = @tp)
  i (multi i @tp)
  d (multi d @tp)
  h (multi h @tp)
  t (multi t @tp)
  n (multi n @tp)
  s (multi s @tp)
  - (multi - @tp)
  ; (multi ; @tp)
  q (multi q @tp)
  j (multi j @tp)
  k (multi k @tp)
  x (multi x @tp)
  b (multi b @tp)
  m (multi m @tp)
  w (multi w @tp)
  v (multi v @tp)
  z (multi z @tp)
  . (multi . @tp)
  a (multi a @tp)
  o (multi o @tp)
  e (multi e @tp)
  u (multi u @tp)
)

(deflayer dvorak
  (tap-hold-press $tt $ht esc rctl)
  @grl 1    2    3    4    5    6    7    8    9    0    [    ]    bspc
  tab  @'   @,   @.ms @p   @y   @f   @g   @c   @r   @l   @/   @=   \
  @cap @anm @oar @ech @umc @i   @d   @h   @t   @n   @s   @-   ret
  @lsf @;   @q   @j   @k   @x   @b   @m   @w   @v   @z   @osf
  @lcl lmet @lal          spc            @ral @rmt rctl
)

(deflayer dvorak-tp
  (tap-hold-press $tt $ht esc rctl)
  @grl 1    2    3    4    5    6    7    8    9    0    [    ]    bspc
  tab  '   ,   .   p   y   f   g   c   r   l   /   =   \
  @cap a   o   e   u   i   d   h   t   n   s   -   ret
  @lsf ;   q   j   k   x   b   m   w   v   z   @osf
  @lcl lmet @lal          spc            @ral @rmt rctl
)

@gerhard-h
Copy link
Contributor Author

thanks again.
Your version to layer-switch in and out of a fast-typing-layer is so much simpler to implement than my shift blocking idea.
Not to mention the added benefit of also working :)

@gerhard-h
Copy link
Contributor Author

gerhard-h commented Oct 21, 2023

latest testing with this config revealed a problem (for me)!
I hold down t ( j on querty) to shift and roll over e and i ( f and d on querty)
The result is EI but I want Ei.

(deffakekeys
  to-base (layer-switch base)
)
(defsrc
  i e t  lsft rsft ins
)

(defalias
  ;; alias to cancel tap-hold keys if typing rapidly but restore after a shord idle period
  tp (multi
    (layer-switch fasttyping)
    (on-idle-fakekey to-base tap 25)
  )

  i (multi i @tp)
  t (tap-hold 1 160 (multi t @tp ) rsft) 
  e (tap-hold 1 160 (multi e @tp) lsft)
)

(deflayer base
  @i @e @t _ _ lrld
)
(deflayer fasttyping
  i e t  _ _ _
)

Sidenote: The config above already fixes tap-holds within words like iet stays that way even if I hold e for to long.

Instead of trying to release the shift I lowercased the fasttyping-layer

(deflayer fasttyping
  (unicode i) (unicode e) (unicode t)  _ _ _
)

instead of (unicode) I now use (unmod) in the fasttyping layer

(unmod i) (unmod e) (unmod t)

@gerhard-h
Copy link
Contributor Author

But if fasttyping is unicode
Holding shift and pressing multiple uppercase keys does not work any more :)
(because while shift is held the keyboard is not idle)

On holding the shift keys longer I can switch to a layer that does not trigger @tp
t (tap-hold 1 160 (multi t @tp) (multi rsft (tap-hold 1 900 XX (layer-toggle base-layer-without-tp))) )

@gerhard-h
Copy link
Contributor Author

Here my LATEST SOLUTION IT Messes with caps a little and with capswords a lot

(deffakekeys
  to-base (layer-switch base)
)
(defsrc
  i e t  lsft rsft ins
)

(defalias
  ;; alias to cancel tap-hold keys if typing rapidly but restore after a shord idle period
  tp (multi
    (one-shot 35 (layer-toggle fasttyping))
    (on-idle-fakekey to-base tap 25)
  )

  i (multi i @tp)
  t (tap-hold 1 160 (multi t @tp ) rsft) 
  e (tap-hold 1 160 (multi e @tp) lsft)
)

(deflayer base
  @i @e @t _ _ lrld
)
(deflayer fasttyping
  (unicode i) (unicode e) (unicode t)  _ _ _
)

@gerhard-h
Copy link
Contributor Author

First problem with the config in the post above is that when using caps or holding shift to type upper case you must type there must be more than 35ms between keystrokes else you get Ei instead of EI ... not a real problem to me.

Second problem caps-words will not work, but building a personal shift layer would help.

Third Problem when using Windows 10 Powertoys (v0.73) I get the letters in revered Order iE instead of Ei

Since it seems to be a timing issue I tried to trigger @tp earlier

  i (multi (tap-hold 1 260 i (multi (layer-toggle base) lctl)) @tp )
  t (multi (tap-hold 1 160 t (multi (layer-toggle base) rsft)) @tp ) 
  e (multi (tap-hold 1 160 e (multi (layer-toggle base) lsft)) @tp )

this has a consistent structur, but it works only with Powertoys running but not without.

here is another "with Powertoys" version that fixes the ei case even if Powertoys are not running.

i  (multi (tap-hold 500 500 (fork i (unicode i) (f17)) (multi (layer-toggle base) lctl) ) @tp)
t  (tap-hold 1 160 (multi t @tp) rsft )
e  (tap-hold 1 160 (fork e (multi e f17) (rsft)) lsft ) ;; F17 does nothing it is just here to get forked

to be continued...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
2 participants