This should be fixed now. I ended up copying GLFW's approach; LWJGL will now create virtual key up events for all keys that were pressed when the window loses focus. If a key is pressed before regaining focus (or it was never released), normally you'd get a stream of repeat events (if enabled) after the window activation. The trick is to handle the first of those repeat events as a normal key down event. So, it'll go like this:
key down -> repeat down -> ... -> repeat down -> focus lost -> key up
then after gaining focus:
focus gained -> key down -> repeat down -> ...
On Windows, it works perfectly and is actually a cleaner solution than the previous workaround.
On Linux, it works just as great, except for modifier keys. Linux apparently does not send repeat events for those. It still works better than before though, if the user never releases the modifier between the focus events, they'll just have to release and press again. The app will only receive the virtual up when focus was lost, not the real one after focus was gained.