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

Fixing release events when keys are released in order of pressing #965

Open
wants to merge 24 commits into
base: main
Choose a base branch
from

Conversation

sezanzeb
Copy link
Owner

@sezanzeb sezanzeb commented Oct 4, 2024

1.

a + b -> c

  1. press a
  2. press b
  3. release a
  4. release b

the release event for a was never injected


2.

"release_input" "on" released events, for which no key-down event was written before

@sezanzeb sezanzeb marked this pull request as ready for review October 4, 2024 13:47
Copy link
Collaborator

@jonasBoss jonasBoss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are still some bugs in the notify() method. There are 3 different states and 6 different state transitions:

  • P Passive
  • A Active
  • S Suppressed
  1. P->P with key down
  2. P->P with key up
  3. P->A key down
  4. A->P key up
  5. P->S key down
  6. S->P key up

I think the first 4 transitions are good, but not the transitions 5 and 6.

On transition 5 self.forward_release() will be executed (line 129). Basically releasing the input even though the mapping does not execute. A test for this would be two mappings:
a+b+c->1 and a+c->2 on mapping 1 set release_combination_keys=False and then input a+b+c the first mapping will be active, the second one suppressed but the key a is still released.

On transition 6 the line return not self.should_release_event(event) (line 125) is executed. Now there are two possibilities: the released key is the exact same key that triggered transition 5 -> Return False
the released key is a different one -> Return True

I think the second possibility can cause a stuck key like so (assuming transition 5 is fixed):
mappings: a+b+d->1 and c+d->2
press a+b+c+d -> mapping 1 is in sate A and 2 in state S
release c -> mapping 2 does transition 6 but the release of c is not forwarded because line 125 returns True (i think)

@sezanzeb
Copy link
Owner Author

Thanks. I'm pretty impressed that you figured that out by looking at the code.

I reproduced transition 5 in test_suppressed_doesnt_forward_releases and fixed it.

I couldn't reproduce transition 6. Did I test that correctly in test_no_stuck_key?

@jonasBoss
Copy link
Collaborator

I had to draw a state diagram in order to wrap my head around this and see all the possible state transitions.

Going to look at transition 6 again, as I could not check this without the fix for transition 5.

@sezanzeb
Copy link
Owner Author

Sounds like something that I should do as well sometimes. I'm curious, could you please share the state diagram?

@jonasBoss
Copy link
Collaborator

Bildschirmfoto_20241016_221743

@jonasBoss
Copy link
Collaborator

I think I was wrong with the transition 6. should_release_event will always return True (assuming there are no duplicate key-up events).

The only key that is not in _requires_a_release is the one that triggered transition 5, and that key must have triggered transition 3 in a mapping with higher priority. Therefore it did not get forwarded and cannot get stuck.

@jonasBoss jonasBoss self-requested a review October 16, 2024 21:00
@sezanzeb
Copy link
Owner Author

Ok, thank you. Shall we merge?

@sezanzeb
Copy link
Owner Author

Should we keep test_no_stuck_key?

Copy link
Collaborator

@jonasBoss jonasBoss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we keep test_no_stuck_key?

I think it is fine to keep

Ok, thank you. Shall we merge?

You can change the things I commented or not, I am not sure what is more readable

@sezanzeb
Copy link
Owner Author

sezanzeb commented Oct 17, 2024

I think we can remove the calls to event.modify. tests are still passing. key_handler handles it correctly by doing bool(value), so any value > 0 is true. The abs_to_btn handler modifies the value already based on the threshold anyway.

@sezanzeb
Copy link
Owner Author

sezanzeb commented Oct 17, 2024

With the recent changes and discoveries, I managed to split it into 4 separate methods

  • _handle_freshly_activated
  • _handle_freshly_deactivated
  • _handle_no_change_press
  • _handle_no_change_release

Is this more maintainable? I guess so

@sezanzeb sezanzeb force-pushed the release-combination-fix branch 3 times, most recently from e8a6519 to 3437103 Compare October 17, 2024 17:41
Comment on lines 114 to 123
if changed:
if is_pressed:
return self._handle_freshly_activated(suppress, event, source)
else:
return self._handle_freshly_deactivated(event, source)
else:
if is_pressed:
return self._handle_no_change_press(event)
else:
return self._handle_no_change_release(event)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea, but I think this is a bit misleading. If I read this correctly _handle_no_change_release will be called when the state changes from suppressed to passive. I guess a simple comment should be fine.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit lost, could you please propose a change with the comment?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants