summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2013-10-04 18:48:41 +0200
committerMarc-André Lureau <marcandre.lureau@gmail.com>2013-10-07 16:33:20 +0200
commit2d28da3c17f115fb1be4e5045e4a7a67fd1158b9 (patch)
treef16450a956b8a3c3cfa7f9ce8524409d619785cb
parentfe0941fb025d02a750bdaee296f93e8024375d25 (diff)
downloadspice-2d28da3c17f115fb1be4e5045e4a7a67fd1158b9.tar.gz
spice-2d28da3c17f115fb1be4e5045e4a7a67fd1158b9.tar.xz
spice-2d28da3c17f115fb1be4e5045e4a7a67fd1158b9.zip
server: release all pressed keys on client disconnect
Releasing modifiers keys unconditionally on disconnect leads to unexpected guest wakeups. To improve the situation, the server can release only the pressed keys, which will prevent the wakeup in most cases. Furthermore, it's not sufficient to release only the modifiers keys. Any key should be released on client disconnect to avoid sticky key press across connections. https://bugzilla.redhat.com/show_bug.cgi?id=871240
-rw-r--r--server/inputs_channel.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/server/inputs_channel.c b/server/inputs_channel.c
index 931dac17..bda525a0 100644
--- a/server/inputs_channel.c
+++ b/server/inputs_channel.c
@@ -27,6 +27,7 @@
#include <spice/macros.h>
#include <spice/vd_agent.h>
#include <spice/protocol.h>
+#include <stdbool.h>
#include "common/marshaller.h"
#include "common/messages.h"
@@ -53,7 +54,11 @@
(4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) * SPICE_AGENT_MAX_DATA_SIZE)
struct SpiceKbdState {
- int dummy;
+ bool push_ext;
+
+ /* track key press state */
+ bool key[0x7f];
+ bool key_ext[0x7f];
};
struct SpiceMouseState {
@@ -221,6 +226,16 @@ static void kbd_push_scan(SpiceKbdInstance *sin, uint8_t scan)
return;
}
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceKbdInterface, base);
+
+ /* track XT scan code set 1 key state */
+ if (scan == 0xe0) {
+ sin->st->push_ext = TRUE;
+ } else {
+ bool *state = sin->st->push_ext ? sin->st->key : sin->st->key_ext;
+ sin->st->push_ext = FALSE;
+ state[scan & 0x7f] = !(scan & 0x80);
+ }
+
sif->push_scan_freg(sin, scan);
}
@@ -466,12 +481,25 @@ static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, ui
static void inputs_relase_keys(void)
{
- kbd_push_scan(keyboard, 0x2a | 0x80); //LSHIFT
- kbd_push_scan(keyboard, 0x36 | 0x80); //RSHIFT
- kbd_push_scan(keyboard, 0xe0); kbd_push_scan(keyboard, 0x1d | 0x80); //RCTRL
- kbd_push_scan(keyboard, 0x1d | 0x80); //LCTRL
- kbd_push_scan(keyboard, 0xe0); kbd_push_scan(keyboard, 0x38 | 0x80); //RALT
- kbd_push_scan(keyboard, 0x38 | 0x80); //LALT
+ int i;
+ SpiceKbdState *st = keyboard->st;
+
+ for (i = 0; i < SPICE_N_ELEMENTS(st->key); i++) {
+ if (!st->key[i])
+ continue;
+
+ st->key[i] = FALSE;
+ kbd_push_scan(keyboard, i | 0x80);
+ }
+
+ for (i = 0; i < SPICE_N_ELEMENTS(st->key_ext); i++) {
+ if (!st->key_ext[i])
+ continue;
+
+ st->key_ext[i] = FALSE;
+ kbd_push_scan(keyboard, 0xe0);
+ kbd_push_scan(keyboard, i | 0x80);
+ }
}
static void inputs_channel_on_disconnect(RedChannelClient *rcc)