http://bugs.winehq.org/show_bug.cgi?id=35907
--- Comment #1 from Ken Thomases ken@codeweavers.com --- The problem is that the X11 driver uses the global async key state to test if the wineserver thinks the key is currently locked on or off, but that's not what TranslateMessage() uses for its call to ToUnicode(). TranslateMessage() uses the synchronous and thread-specific state. The thread-specific state is only updated when that thread gets a WM_KEYDOWN for VK_CAPITAL.
The thread-specific state has to be in sync with the messages, but I expect that if you lock Caps Lock on when one thread's window has focus, then other threads should eventually show that state when they've processed all pending messages. I don't know if each thread should see its own WM_KEYDOWN for VK_CAPITAL or its state should just silently change at the point in the message stream where such a message would have been.
If the X11 driver tries to compensate by generating VK_CAPITAL press-release pairs for every thread, then the global (desktop) key state will be wrong (depending on if there are an odd or even number of threads). So, I think this has to be solved in the wineserver.
This will require tests to determine the correct behavior.