Skip to content

Conversation

SuuperW
Copy link
Contributor

@SuuperW SuuperW commented Jul 24, 2025

Fix: Hotkey overrides input would cause an input to continue after a button was released if the input is bound to a combination such as Shift+A and an "internal hotkey" is bound to a single button (such as A). Also input bound to Alt would not have the alt ignored by menus.

Fix: Input overrides hotkeys did not work if both input and hotkey were bound to a combination such as Shift+A.

Fix: Controller inputs bound to a modifier key combination would not be triggered if additional modifier keys were also pressed.

Fix: autofire/autohold hotkeys would sometimes activate buttons that were already being held when the hotkey was pressed.

Check if completed:

@YoshiRulz YoshiRulz requested a review from Morilli July 25, 2025 20:47
@Morilli
Copy link
Collaborator

Morilli commented Jul 26, 2025

It's pretty hard to verify things are correct now because nothing defines "correct". Let me recap a couple things that happen.

If a key combination like Ctrl+Shift+A is pressed, it will now activate controller bindings for Ctrl, Shift, A, Ctrl+Shift, Ctrl+A, Shift+A and Ctrl+Shift+A. Only a hotkey bound to Ctrl+Shift+A will be triggered though.

"Internal" hotkeys are a separate group from normal hotkeys. If any key press activates a normal hotkey then no internal hotkey will be triggered, regardless of priority setting, except for the Frame Inch hotkey binding. The Frame Inch exception also means that binding a key combination to Frame Inch and some controller input will still have it go through in "Hotkeys override Input" mode.

The "Hotkeys override Input" branch is especially difficult for me to understand. Am I correct that the following code is functionally equivalent to what the code is currently doing?

if (ie.EventType is InputEventType.Press)
{
	var handled = triggers.Aggregate(false, (current, trigger) => current | CheckHotkey(trigger));
	if (!handled)
	{
		hotkeyCoalescer.Receive(ie);
		if (!triggers.Exists(IsInternalHotkey))
		{
			finalHostController.Receive(ie);
		}
	}
}
else
{
	hotkeyCoalescer.Receive(ie);
	finalHostController.Receive(ie);
}

@SuuperW
Copy link
Contributor Author

SuuperW commented Jul 26, 2025

It's pretty hard to verify things are correct now because nothing defines "correct".

Yeah, we really should have some tests for this.

If a key combination like Ctrl+Shift+A is pressed, it will now activate controller bindings for Ctrl, Shift, A, Ctrl+Shift, Ctrl+A, Shift+A and Ctrl+Shift+A. Only a hotkey bound to Ctrl+Shift+A will be triggered though.

This is correct, with the caveat that you cannot press Ctrl+Shift+A without first pressing Ctrl+Shift and before that either Ctrl or Shift, so hotkeys bound to those may trigger in the process. A must be pressed last or Ctrl+Shift+A won't happen for a hotkey, but a controller binding would be activated when pressing the keys in any order.

"Internal" hotkeys are a separate group from normal hotkeys. If any key press activates a normal hotkey then no internal hotkey will be triggered, regardless of priority setting, except for the Frame Inch hotkey binding. The Frame Inch exception also means that binding a key combination to Frame Inch and some controller input will still have it go through in "Hotkeys override Input" mode.

Interesting. I had not looked that much into the internal hotkeys.
I think that system should be re-worked. One reason for this is that if you set a very low emulation speed, the frame advance hotkey is unreliable. So is pausing. (because you're likely to press and release between loops, so the loop will never see it pressed)

The "Hotkeys override Input" branch is especially difficult for me to understand. Am I correct that the following code is functionally equivalent to what the code is currently doing?

Yeah lots of this code is tough to read. I believe your code is equivalent.

@YoshiRulz
Copy link
Member

[...] if you set a very low emulation speed, the frame advance hotkey is unreliable. So is pausing. (because you're likely to press and release between loops, so the loop will never see it pressed)

#2959?

@SuuperW
Copy link
Contributor Author

SuuperW commented Jul 26, 2025

OP is unclear, but yeah this is the same issue as the comments there are discussing.

@Morilli
Copy link
Collaborator

Morilli commented Jul 26, 2025

if you set a very low emulation speed, the frame advance hotkey is unreliable. So is pausing.

I can't reproduce that with the pausing hotkey. However for frame advance you can use frame inch instead as that immediately pauses instead of waiting for the actual frame loop.

@SuuperW
Copy link
Contributor Author

SuuperW commented Jul 26, 2025

Oh pause isn't an internal hotkey. Huh.
I must have been using the frame advance button to try to pause when I experienced that.

Morilli
Morilli previously approved these changes Jul 27, 2025
Copy link
Collaborator

@Morilli Morilli left a comment

Choose a reason for hiding this comment

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

Should be fine.

@SuuperW SuuperW changed the title Fix input/hotkey priority bugs Fix input/hotkey bugs Jul 30, 2025
@SuuperW
Copy link
Contributor Author

SuuperW commented Jul 30, 2025

Tests and additional fixes.

"Internal" hotkeys are a separate group from normal hotkeys. If any key press activates a normal hotkey then no internal hotkey will be triggered

This is also fixed.

Rebased onto my undo_redo branch (has its own pending PR) in order to make use of test code there.

@YoshiRulz

This comment was marked as outdated.

@SuuperW
Copy link
Contributor Author

SuuperW commented Sep 1, 2025

Rebased onto master.
I'd like to get this branch merged too.

…nternal hotkeys"; all hotkeys go to the hotkey controller now even if we don't expect to read that hotkey from the controller.

Fix: Hotkey overrides input would cause an input to continue after a button was released if the input is bound to a combination such as Shift+A and an "internal hotkey" is bound to a single button (such as A). Also input bound to Alt would not have the alt ignored by menus.
Passes tests HotkeyOverrideDoesNotEatReleaseEvents and InputIsNotSeenAsUnbound
…re bound to a combination such as Shift+A.

passes test ControllerPriorityWithModifier
…be triggered if additional modifier keys were also pressed.

passes tests ControllerInputAcceptsOutOfOrderModifier and ControllerInputIgnoresExtraModifier
…were already being held when the hotkey was pressed.

passes test AutofireHotkeyDoesNotRespondToAlreadyHeldButton
@SuuperW
Copy link
Contributor Author

SuuperW commented Sep 3, 2025

I realized that I messed up mouse coordinate transforming here. I've added a new commit 29ed1b3 that fixes that. (It's weird that we translate screen coordinates to client coordinates then to -10k to +10k range and back to client coordinates again but I assume there's a reason for that somewhere.)
I'll give you a chance to review the updates before I merge, @YoshiRulz.

@YoshiRulz
Copy link
Member

(It's weird that we translate screen coordinates to client coordinates then to -10k to +10k range and back to client coordinates again but I assume there's a reason for that somewhere.)

Not a good reason. It goes back to before e12b5d8 when axes used float.

diff still LGTM

@SuuperW SuuperW merged commit 4cc9dbe into TASEmulators:master Sep 3, 2025
4 checks passed
@SuuperW SuuperW deleted the input_handling branch September 3, 2025 07:23
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.

3 participants