'Win32 raw input blocks input locale switching when RIDEV_NOLEGACY is specified

I'm writing a keyboard input system for Windows based on Raw Input. It is implemented with RIDEV_NOLEGACY flag set, and legacy keyboard messages are generated manually, only when input was not processed by clients.

I've managed to get it working but language switching hotkey (Alt+Shift in my case) is now broken.

The system must:

  1. distinguish between different input devices;

  2. detect device [dis]connection;

  3. allow handlers to consume input, preventing it from being processed by least priority handlers;

  4. keep alt codes functional;

  5. if possible, keep accelerators with system keys functional too;

I've tried many combinations of raw input settings, but each one violates some of requirements. The main problem now is with 3.

With RIDEV_NOLEGACY handler can consume WM_INPUT or leave it unprocessed. In the second case system generates WM_[SYS]KEYUP / WM_[SYS]KEYDOWN messages by itself and posts them via PostMessage. Since PostMessage doesn't update thread's keyboard state, system updates it too in an appropriate place. So 3, 4 and 5 are OK. But Alt+Shift stops responding.

Without RIDEV_NOLEGACY Alt+Shift changes locale as expected, but raw input generates legacy WM_[SYS]KEYUP / WM_[SYS]KEYDOWN regardless of whether some client processed WM_INPUT or not.

There is a minimal working example of the problem: https://github.com/niello/misc/tree/master/RawInputLocale

Reproduced on Win10 and Win8.1, but probably will be the same on any Windows since Vista.

Note that if you set USE_NOLEGACY_RAW_INPUT in an example to true, WM_CHAR messages are generated only for each second keystroke, as if another one was consumed by our system client, but if you try to change input locale, nothing happens. And if you set USE_NOLEGACY_RAW_INPUT to false you will switch locale normally and receive WM_INPUTLANGCHANGE, but WM_CHAR will be generated for consumed keystrokes too.

I've run out of ideas, so any help will be greatly appreciated.



Solution 1:[1]

After another day it seems there is no easy solution. RIDEV_NOLEGACY just kills language switching by hotkey. The good news is that all necessary logic can be implemented by hand. That's my solution for now. It takes into account system hotkey setting, suppresses character generation for '`' key when it is used as hotkey, and even detects system hotkey changes without restarting an application. The code is available in the same repo. Hope this will help someone else too.

Solution 2:[2]

I think use of RIDEV_NOLEGACY for keyboard and mouse raw input is not worth it - you can just ignore these "legacy" WM_KEY*/WM_MOUSE* messages in your app. This no legacy mode is buggy and there is no clear perfomance gains. Same applies to RIDEV_CAPTUREMOUSE.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Niello
Solution 2 DJm00n