From a528b80cb09977806129249ea604aaef3830f3ec Mon Sep 17 00:00:00 2001 From: balrog Date: Tue, 30 Oct 2007 22:38:53 +0000 Subject: [PATCH] Miscellaneous VNC related fixes from Xen forwarded by Matthew Kent. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3489 c046a42c-6fe2-441c-8c8c-71466251a162 --- console.c | 21 +++++++++++-------- keymaps.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- vl.h | 1 + vnc.c | 35 ++++++++++++++++++++++++++++++-- vnc_keysym.h | 14 +++++++++++++ 5 files changed, 124 insertions(+), 11 deletions(-) diff --git a/console.c b/console.c index ff725c2..9d3c2f6 100644 --- a/console.c +++ b/console.c @@ -509,7 +509,7 @@ static void text_console_resize(TextConsole *s) c++; } } - free(s->cells); + qemu_free(s->cells); s->cells = cells; } @@ -1167,11 +1167,21 @@ int is_graphic_console(void) return active_console->console_type == GRAPHIC_CONSOLE; } +void console_color_init(DisplayState *ds) +{ + int i, j; + for (j = 0; j < 2; j++) { + for (i = 0; i < 8; i++) { + color_table[j][i] = col_expand(ds, + vga_get_color(ds, color_table_rgb[j][i])); + } + } +} + CharDriverState *text_console_init(DisplayState *ds, const char *p) { CharDriverState *chr; TextConsole *s; - int i,j; unsigned width; unsigned height; static int color_inited; @@ -1195,12 +1205,7 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) if (!color_inited) { color_inited = 1; - for(j = 0; j < 2; j++) { - for(i = 0; i < 8; i++) { - color_table[j][i] = col_expand(s->ds, - vga_get_color(s->ds, color_table_rgb[j][i])); - } - } + console_color_init(s->ds); } s->y_displayed = 0; s->y_base = 0; diff --git a/keymaps.c b/keymaps.c index f0f8c10..15c40fa 100644 --- a/keymaps.c +++ b/keymaps.c @@ -32,6 +32,12 @@ static int get_keysym(const char *name) return 0; } +struct key_range { + int start; + int end; + struct key_range *next; +}; + #define MAX_NORMAL_KEYCODE 512 #define MAX_EXTRA_COUNT 256 typedef struct { @@ -41,8 +47,34 @@ typedef struct { uint16_t keycode; } keysym2keycode_extra[MAX_EXTRA_COUNT]; int extra_count; + struct key_range *keypad_range; + struct key_range *numlock_range; } kbd_layout_t; +static void add_to_key_range(struct key_range **krp, int code) { + struct key_range *kr; + for (kr = *krp; kr; kr = kr->next) { + if (code >= kr->start && code <= kr->end) + break; + if (code == kr->start - 1) { + kr->start--; + break; + } + if (code == kr->end + 1) { + kr->end++; + break; + } + } + if (kr == NULL) { + kr = qemu_mallocz(sizeof(*kr)); + if (kr) { + kr->start = kr->end = code; + kr->next = *krp; + *krp = kr; + } + } +} + static kbd_layout_t *parse_keyboard_layout(const char *language, kbd_layout_t * k) { @@ -87,7 +119,15 @@ static kbd_layout_t *parse_keyboard_layout(const char *language, // fprintf(stderr, "Warning: unknown keysym %s\n", line); } else { const char *rest = end_of_keysym + 1; - int keycode = strtol(rest, NULL, 0); + char *rest2; + int keycode = strtol(rest, &rest2, 0); + + if (rest && strstr(rest, "numlock")) { + add_to_key_range(&k->keypad_range, keycode); + add_to_key_range(&k->numlock_range, keysym); + //fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode); + } + /* if(keycode&0x80) keycode=(keycode<<8)^0x80e0; */ if (keysym < MAX_NORMAL_KEYCODE) { @@ -143,3 +183,25 @@ static int keysym2scancode(void *kbd_layout, int keysym) } return 0; } + +static inline int keycode_is_keypad(void *kbd_layout, int keycode) +{ + kbd_layout_t *k = kbd_layout; + struct key_range *kr; + + for (kr = k->keypad_range; kr; kr = kr->next) + if (keycode >= kr->start && keycode <= kr->end) + return 1; + return 0; +} + +static inline int keysym_is_numlock(void *kbd_layout, int keysym) +{ + kbd_layout_t *k = kbd_layout; + struct key_range *kr; + + for (kr = k->numlock_range; kr; kr = kr->next) + if (keysym >= kr->start && keysym <= kr->end) + return 1; + return 0; +} diff --git a/vl.h b/vl.h index 6c98033..90fdcf9 100644 --- a/vl.h +++ b/vl.h @@ -374,6 +374,7 @@ void vga_hw_screen_dump(const char *filename); int is_graphic_console(void); CharDriverState *text_console_init(DisplayState *ds, const char *p); void console_select(unsigned int index); +void console_color_init(DisplayState *ds); /* serial ports */ diff --git a/vnc.c b/vnc.c index 72c8d1c..83d0011 100644 --- a/vnc.c +++ b/vnc.c @@ -284,7 +284,10 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h) exit(1); } - ds->depth = vs->depth * 8; + if (ds->depth != vs->depth * 8) { + ds->depth = vs->depth * 8; + console_color_init(ds); + } size_changed = ds->width != w || ds->height != h; ds->width = w; ds->height = h; @@ -907,6 +910,12 @@ static void reset_keys(VncState *vs) } } +static void press_key(VncState *vs, int keysym) +{ + kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f); + kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80); +} + static void do_key_event(VncState *vs, int down, uint32_t sym) { int keycode; @@ -934,6 +943,28 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) return; } break; + case 0x45: /* NumLock */ + if (!down) + vs->modifiers_state[keycode] ^= 1; + break; + } + + if (keycode_is_keypad(vs->kbd_layout, keycode)) { + /* If the numlock state needs to change then simulate an additional + keypress before sending this one. This will happen if the user + toggles numlock away from the VNC window. + */ + if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) { + if (!vs->modifiers_state[0x45]) { + vs->modifiers_state[0x45] = 1; + press_key(vs, 0xff7f); + } + } else { + if (vs->modifiers_state[0x45]) { + vs->modifiers_state[0x45] = 0; + press_key(vs, 0xff7f); + } + } } if (is_graphic_console()) { @@ -991,7 +1022,7 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) static void key_event(VncState *vs, int down, uint32_t sym) { - if (sym >= 'A' && sym <= 'Z') + if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) sym = sym - 'A' + 'a'; do_key_event(vs, down, sym); } diff --git a/vnc_keysym.h b/vnc_keysym.h index 14fe47f..5c47104 100644 --- a/vnc_keysym.h +++ b/vnc_keysym.h @@ -231,6 +231,19 @@ static name2keysym_t name2keysym[]={ {"Home", 0xff50}, /* XK_Home */ {"End", 0xff57}, /* XK_End */ {"Scroll_Lock", 0xff14}, /* XK_Scroll_Lock */ +{"KP_Home", 0xff95}, +{"KP_Left", 0xff96}, +{"KP_Up", 0xff97}, +{"KP_Right", 0xff98}, +{"KP_Down", 0xff99}, +{"KP_Prior", 0xff9a}, +{"KP_Page_Up", 0xff9a}, +{"KP_Next", 0xff9b}, +{"KP_Page_Down", 0xff9b}, +{"KP_End", 0xff9c}, +{"KP_Begin", 0xff9d}, +{"KP_Insert", 0xff9e}, +{"KP_Delete", 0xff9f}, {"F1", 0xffbe}, /* XK_F1 */ {"F2", 0xffbf}, /* XK_F2 */ {"F3", 0xffc0}, /* XK_F3 */ @@ -258,6 +271,7 @@ static name2keysym_t name2keysym[]={ {"KP_8", 0xffb8}, /* XK_KP_8 */ {"KP_9", 0xffb9}, /* XK_KP_9 */ {"KP_Add", 0xffab}, /* XK_KP_Add */ +{"KP_Separator", 0xffac},/* XK_KP_Separator */ {"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ {"KP_Divide", 0xffaf}, /* XK_KP_Divide */ {"KP_Enter", 0xff8d}, /* XK_KP_Enter */ -- 1.7.9.5