Consider this an "outside opinion" from an external developer, but my first impression upon reading the thread is that I think the whole design of "key state caching" is wrong and a symptom of a bigger problem.
Apps are polling GetAsyncKeyState() for good reason --- because they want that low-latency responsiveness which is important in situations like drawing with the mouse. Adding a cache defeats that, hence leading to bugs like this one. If your API implementation is slow, then profile and figure out how to make it faster because it obviously works fine in Windows.
As the saying goes, "Never add another layer of complexity when your problem can be solved by removing and/or optimising the existing ones."
The architecture is inherently different: it works fine in Windows because there's only one canonical key state and the operating system is looking after it.
Wine, on the other hand, is running within X Windows, and the canonical key state belongs to X. It's in a different process and it might even be on a different computer. So either they have to poll it (slowly), arrange for asynchronous notifications (may not be possible and undoubtedly has similar conflicts with synchronous access), or poll it a limited amount and then cache it.
The whole point of Wine is adapting one API to a fundamentally different one. It is the added layer of complexity.
Edit: another discussion suggests the X by design does not allow an application to see keystrokes aimed at another window, nor is there a global hook mechanism.
"they want that low-latency responsiveness which is important in situations like drawing with the mouse"
Yes to this in general, not just with mouse polling- I've noticed a disturbing trend towards more and more buffering, caching, and latency in a lot of modern software and hardware. In my humble opinion, if your API/interface can't match the response time of the human nervous system, then it's just flat out broken. Nerves fire at 100 hz, for pete's sake. Transistors operate on a gigahertz level. Let's get our sh together, people.
Apps are polling GetAsyncKeyState() for good reason --- because they want that low-latency responsiveness which is important in situations like drawing with the mouse. Adding a cache defeats that, hence leading to bugs like this one. If your API implementation is slow, then profile and figure out how to make it faster because it obviously works fine in Windows.
As the saying goes, "Never add another layer of complexity when your problem can be solved by removing and/or optimising the existing ones."