Spice LEDs get out of sync if guest doesn't act on CapsLock
In the commit ff9c8d49, the Spice server switched from the QEMU LED state to its own internal LED state. In the commit message, it says that:
When the guest notifies its change, the modifiers_watch is supposed to fix any wrong state.
However, in that same commit, the modifiers_watch
(which calls key_modifiers_sender
), simply sends what the Spice server thinks is the modifier state:
inputs_channel_push_keyboard_modifiers(inputs, inputs->modifiers);
(This is now converted to the C++ inputs->push_keyboard_modifiers();
which calls pipes_add(red::make_shared<RedKeyModifiersPipeItem>(modifiers));
, but does effectively the same thing.)
In fact, in the whole file, the only time we ever query the guest's state by calling kbd_get_leds
is in pipe_add_init
. As such, anytime the guest ignores the CapsLock for some reason, its LED state goes out of sync with what the Spice server thinks is the LED state.
We discovered this bug while debugging a user-reported issue in our Spice client. This user remapped the CapsLock key in the VM to Escape, which causes the guest to not toggle the CapsLock LED when the CapsLock key is pressed. However, the Spice server thinks the CapsLock LED is on. When the Spice client sends SPICE_MSGC_INPUTS_KEY_MODIFIERS
without the CapsLock modifier, the Spice server generates a spurious CapsLock press in the guest to cancel out the CapsLock LED, which the server believes is on. In the user's case, this causes Escape to be pressed spuriously.
I suspect something similar happens with all the other modifier keys (e.g. NumLock and ScrollLock) when remapped.