Skip to content

Commit

Permalink
kbd-state: use state tracker for vnc
Browse files Browse the repository at this point in the history
Use the new keyboard state tracked for vnc.  Allows to drop the
vnc-specific modifier state tracking code.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-id: 20190122092814.14919-7-kraxel@redhat.com
  • Loading branch information
kraxel committed Feb 5, 2019
1 parent 0c0d427 commit c2f2ba4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 90 deletions.
120 changes: 33 additions & 87 deletions ui/vnc.c
Expand Up @@ -59,7 +59,6 @@ static QTAILQ_HEAD(, VncDisplay) vnc_displays =
QTAILQ_HEAD_INITIALIZER(vnc_displays);

static int vnc_cursor_define(VncState *vs);
static void vnc_release_modifiers(VncState *vs);
static void vnc_update_throttle_offset(VncState *vs);

static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
Expand Down Expand Up @@ -1267,7 +1266,7 @@ void vnc_disconnect_finish(VncState *vs)
vnc_sasl_client_cleanup(vs);
#endif /* CONFIG_VNC_SASL */
audio_del(vs);
vnc_release_modifiers(vs);
qkbd_state_lift_all_keys(vs->vd->kbd);

if (vs->mouse_mode_notifier.notify != NULL) {
qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
Expand Down Expand Up @@ -1756,26 +1755,10 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
qemu_input_event_sync();
}

static void reset_keys(VncState *vs)
static void press_key(VncState *vs, QKeyCode qcode)
{
int i;
for(i = 0; i < 256; i++) {
if (vs->modifiers_state[i]) {
qemu_input_event_send_key_number(vs->vd->dcl.con, i, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
vs->modifiers_state[i] = 0;
}
}
}

static void press_key(VncState *vs, int keysym)
{
int keycode = keysym2scancode(vs->vd->kbd_layout, keysym,
false, false, false) & SCANCODE_KEYMASK;
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, true);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
qkbd_state_key_event(vs->vd->kbd, qcode, true);
qkbd_state_key_event(vs->vd->kbd, qcode, false);
}

static void vnc_led_state_change(VncState *vs)
Expand Down Expand Up @@ -1816,32 +1799,20 @@ static void kbd_leds(void *opaque, int ledstate)

static void do_key_event(VncState *vs, int down, int keycode, int sym)
{
QKeyCode qcode = qemu_input_key_number_to_qcode(keycode);

/* QEMU console switch */
switch(keycode) {
case 0x2a: /* Left Shift */
case 0x36: /* Right Shift */
case 0x1d: /* Left CTRL */
case 0x9d: /* Right CTRL */
case 0x38: /* Left ALT */
case 0xb8: /* Right ALT */
if (down)
vs->modifiers_state[keycode] = 1;
else
vs->modifiers_state[keycode] = 0;
break;
case 0x02 ... 0x0a: /* '1' to '9' keys */
if (vs->vd->dcl.con == NULL &&
down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
switch (qcode) {
case Q_KEY_CODE_1 ... Q_KEY_CODE_9: /* '1' to '9' keys */
if (vs->vd->dcl.con == NULL && down &&
qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL) &&
qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALT)) {
/* Reset the modifiers sent to the current console */
reset_keys(vs);
console_select(keycode - 0x02);
qkbd_state_lift_all_keys(vs->vd->kbd);
console_select(qcode - Q_KEY_CODE_1);
return;
}
break;
case 0x3a: /* CapsLock */
case 0x45: /* NumLock */
if (down)
vs->modifiers_state[keycode] ^= 1;
default:
break;
}

Expand All @@ -1856,16 +1827,14 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
toggles numlock away from the VNC window.
*/
if (keysym_is_numlock(vs->vd->kbd_layout, sym & 0xFFFF)) {
if (!vs->modifiers_state[0x45]) {
if (!qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) {
trace_vnc_key_sync_numlock(true);
vs->modifiers_state[0x45] = 1;
press_key(vs, 0xff7f);
press_key(vs, Q_KEY_CODE_NUM_LOCK);
}
} else {
if (vs->modifiers_state[0x45]) {
if (qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK)) {
trace_vnc_key_sync_numlock(false);
vs->modifiers_state[0x45] = 0;
press_key(vs, 0xff7f);
press_key(vs, Q_KEY_CODE_NUM_LOCK);
}
}
}
Expand All @@ -1878,30 +1847,25 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
toggles capslock away from the VNC window.
*/
int uppercase = !!(sym >= 'A' && sym <= 'Z');
int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]);
int capslock = !!(vs->modifiers_state[0x3a]);
bool shift = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT);
bool capslock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CAPSLOCK);
if (capslock) {
if (uppercase == shift) {
trace_vnc_key_sync_capslock(false);
vs->modifiers_state[0x3a] = 0;
press_key(vs, 0xffe5);
press_key(vs, Q_KEY_CODE_CAPS_LOCK);
}
} else {
if (uppercase != shift) {
trace_vnc_key_sync_capslock(true);
vs->modifiers_state[0x3a] = 1;
press_key(vs, 0xffe5);
press_key(vs, Q_KEY_CODE_CAPS_LOCK);
}
}
}

if (qemu_console_is_graphic(NULL)) {
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, down);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
} else {
bool numlock = vs->modifiers_state[0x45];
bool control = (vs->modifiers_state[0x1d] ||
vs->modifiers_state[0x9d]);
qkbd_state_key_event(vs->vd->kbd, qcode, down);
if (!qemu_console_is_graphic(NULL)) {
bool numlock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK);
bool control = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL);
/* QEMU console emulation */
if (down) {
switch (keycode) {
Expand Down Expand Up @@ -2002,37 +1966,16 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
}
}

static void vnc_release_modifiers(VncState *vs)
{
static const int keycodes[] = {
/* shift, control, alt keys, both left & right */
0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8,
};
int i, keycode;

if (!qemu_console_is_graphic(NULL)) {
return;
}
for (i = 0; i < ARRAY_SIZE(keycodes); i++) {
keycode = keycodes[i];
if (!vs->modifiers_state[keycode]) {
continue;
}
qemu_input_event_send_key_number(vs->vd->dcl.con, keycode, false);
qemu_input_event_send_key_delay(vs->vd->key_delay_ms);
}
}

static const char *code2name(int keycode)
{
return QKeyCode_str(qemu_input_key_number_to_qcode(keycode));
}

static void key_event(VncState *vs, int down, uint32_t sym)
{
bool shift = vs->modifiers_state[0x2a] || vs->modifiers_state[0x36];
bool altgr = vs->modifiers_state[0xb8];
bool ctrl = vs->modifiers_state[0x1d] || vs->modifiers_state[0x9d];
bool shift = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_SHIFT);
bool altgr = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_ALTGR);
bool ctrl = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_CTRL);
int keycode;
int lsym = sym;

Expand Down Expand Up @@ -3259,6 +3202,7 @@ void vnc_display_init(const char *id, Error **errp)

vd->dcl.ops = &dcl_ops;
register_displaychangelistener(&vd->dcl);
vd->kbd = qkbd_state_init(vd->dcl.con);
}


Expand Down Expand Up @@ -3995,7 +3939,6 @@ void vnc_display_open(const char *id, Error **errp)
vd->led = qemu_add_led_event_handler(kbd_leds, vd);
}
vd->ledstate = 0;
vd->key_delay_ms = key_delay_ms;

device_id = qemu_opt_get(opts, "display");
if (device_id) {
Expand All @@ -4012,10 +3955,13 @@ void vnc_display_open(const char *id, Error **errp)
}

if (con != vd->dcl.con) {
qkbd_state_free(vd->kbd);
unregister_displaychangelistener(&vd->dcl);
vd->dcl.con = con;
register_displaychangelistener(&vd->dcl);
vd->kbd = qkbd_state_init(vd->dcl.con);
}
qkbd_state_set_delay(vd->kbd, key_delay_ms);

if (saddr == NULL) {
goto cleanup;
Expand Down
5 changes: 2 additions & 3 deletions ui/vnc.h
Expand Up @@ -44,6 +44,7 @@
#include "keymaps.h"
#include "vnc-palette.h"
#include "vnc-enc-zrle.h"
#include "ui/kbd-state.h"

// #define _VNC_DEBUG 1

Expand Down Expand Up @@ -155,7 +156,7 @@ struct VncDisplay
int lock_key_sync;
QEMUPutLEDEntry *led;
int ledstate;
int key_delay_ms;
QKbdState *kbd;
QemuMutex mutex;

QEMUCursor *cursor;
Expand Down Expand Up @@ -326,8 +327,6 @@ struct VncState

VncReadEvent *read_handler;
size_t read_handler_expect;
/* input */
uint8_t modifiers_state[256];

bool abort;
QemuMutex output_mutex;
Expand Down

0 comments on commit c2f2ba4

Please sign in to comment.