jnativehook icon indicating copy to clipboard operation
jnativehook copied to clipboard

How to correctly consume ALT hotkey

Open sghpjuikit opened this issue 3 years ago • 1 comments

Lets say java application registers global ALT+S hotkey to do some action. It uses VoidDispatchService and consumes the key event so other applications do not perform their actions. The ALT+S event (S with exactly just ALT mask) is consumed in nativeKeyPressed as well as nativeKeyReleased. So CTRL+S nor CTRL+ALT+S is not consumed, correctly.

In order to invoke ALT+S, the order of actual events may follow 4 paths: press ALT, press S, release S, release ALT press ALT, press S, release ALT, release S press S, press ALT, release ALT, release S press S, press ALT, release S, release ALT

Ignoring the cases 2-3, which are more complicated, in the first, the most common path, the events that get consumed are press S and release S, but not the press ALT and release ALT. So ALT+S is atomic in a way that S hotkeys do not get invoked in other application. However ALT hotkeys do.

Consuming the initial press ALT makes no sense, because the application does not know if press S will follow. This would break other applications. So we don't consume press ALT.

However the release ALT can be consumed (if press ALT, press S, release S just happened) and it would prevent release ALT actions during ALT+S. There is very common action invoked on release ALT event, shared by many applications, and that is to display the application menu (which is sometimes hidden unless release ALT event). The only way I see to prevent this behavior is to consume release ALT during ALT+S.

However this breaks the symmetry press ALT -> release ALT as some applications only see the press ALT and consuming just one breaks them. The question is which side is responsible for correctly handling this: should application never consume just release? Or should the other application ALWAYS handle release event if it did handle the press event (ignoring the event.isConsumed flag)?

I'm assuming the event.isConsumed flag is passed into the application, rather than the event being filtered by the OS and not even passed in the subsequent applications. But I dont know. Can anyone confirm this?

The way I see it, whether I consume release ALT or not, something will be broken. Either release ALT produces some action during ALT+S or some application's ALT hotkey does not work properly. Maybe it means ALT is not a good modifier for a hotkey? Releasing ALT when CTRL is pressed does not produce the application menu action. I also thought about inserting CTRL press-release by my application to prevent release ALT happening elsewhere, but it seems like a hack that would invite more trouble down the line. It would look like: press ALT, press S, release S, press CTRL (programmatic), release ALT, release CTRL (programmatic).

I'm testing this on Windows 10.

What do you think @kwhat ? My thought is that the symmetry of press/release must be broken and ALT+S should consume ALT release too and if applications need press-release event pairs, the release consumption must be ignored if press was processed by the application = to properly clean up.

PS: my exact issue is ALT shortcuts in my java applications causing the currently focused application to popup context menu OR (if I consume release ALT) application AltDrag thinks ALT was not released which breaks window behavior. I dont really see way out, maybe with the CTRL hack.

sghpjuikit avatar Sep 02 '22 12:09 sghpjuikit

After reading a bit about this I think ALT should not be consumed. The problem with ALT triggering window context menu seems to be quite hated across Windows users, it seems. It may be possible to fix it with one of several possible Autohotkey scripts, one of which does use my suggested workaround of inserting some uncommon key press-release events around ALT release event. I will probably the Autohotkey route (Im already using it for other things).

sghpjuikit avatar Sep 02 '22 17:09 sghpjuikit