Commit a528b80cb09977806129249ea604aaef3830f3ec
1 parent
12bc92ab
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
Showing
5 changed files
with
124 additions
and
11 deletions
console.c
| @@ -509,7 +509,7 @@ static void text_console_resize(TextConsole *s) | @@ -509,7 +509,7 @@ static void text_console_resize(TextConsole *s) | ||
| 509 | c++; | 509 | c++; |
| 510 | } | 510 | } |
| 511 | } | 511 | } |
| 512 | - free(s->cells); | 512 | + qemu_free(s->cells); |
| 513 | s->cells = cells; | 513 | s->cells = cells; |
| 514 | } | 514 | } |
| 515 | 515 | ||
| @@ -1167,11 +1167,21 @@ int is_graphic_console(void) | @@ -1167,11 +1167,21 @@ int is_graphic_console(void) | ||
| 1167 | return active_console->console_type == GRAPHIC_CONSOLE; | 1167 | return active_console->console_type == GRAPHIC_CONSOLE; |
| 1168 | } | 1168 | } |
| 1169 | 1169 | ||
| 1170 | +void console_color_init(DisplayState *ds) | ||
| 1171 | +{ | ||
| 1172 | + int i, j; | ||
| 1173 | + for (j = 0; j < 2; j++) { | ||
| 1174 | + for (i = 0; i < 8; i++) { | ||
| 1175 | + color_table[j][i] = col_expand(ds, | ||
| 1176 | + vga_get_color(ds, color_table_rgb[j][i])); | ||
| 1177 | + } | ||
| 1178 | + } | ||
| 1179 | +} | ||
| 1180 | + | ||
| 1170 | CharDriverState *text_console_init(DisplayState *ds, const char *p) | 1181 | CharDriverState *text_console_init(DisplayState *ds, const char *p) |
| 1171 | { | 1182 | { |
| 1172 | CharDriverState *chr; | 1183 | CharDriverState *chr; |
| 1173 | TextConsole *s; | 1184 | TextConsole *s; |
| 1174 | - int i,j; | ||
| 1175 | unsigned width; | 1185 | unsigned width; |
| 1176 | unsigned height; | 1186 | unsigned height; |
| 1177 | static int color_inited; | 1187 | static int color_inited; |
| @@ -1195,12 +1205,7 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) | @@ -1195,12 +1205,7 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) | ||
| 1195 | 1205 | ||
| 1196 | if (!color_inited) { | 1206 | if (!color_inited) { |
| 1197 | color_inited = 1; | 1207 | color_inited = 1; |
| 1198 | - for(j = 0; j < 2; j++) { | ||
| 1199 | - for(i = 0; i < 8; i++) { | ||
| 1200 | - color_table[j][i] = col_expand(s->ds, | ||
| 1201 | - vga_get_color(s->ds, color_table_rgb[j][i])); | ||
| 1202 | - } | ||
| 1203 | - } | 1208 | + console_color_init(s->ds); |
| 1204 | } | 1209 | } |
| 1205 | s->y_displayed = 0; | 1210 | s->y_displayed = 0; |
| 1206 | s->y_base = 0; | 1211 | s->y_base = 0; |
keymaps.c
| @@ -32,6 +32,12 @@ static int get_keysym(const char *name) | @@ -32,6 +32,12 @@ static int get_keysym(const char *name) | ||
| 32 | return 0; | 32 | return 0; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | +struct key_range { | ||
| 36 | + int start; | ||
| 37 | + int end; | ||
| 38 | + struct key_range *next; | ||
| 39 | +}; | ||
| 40 | + | ||
| 35 | #define MAX_NORMAL_KEYCODE 512 | 41 | #define MAX_NORMAL_KEYCODE 512 |
| 36 | #define MAX_EXTRA_COUNT 256 | 42 | #define MAX_EXTRA_COUNT 256 |
| 37 | typedef struct { | 43 | typedef struct { |
| @@ -41,8 +47,34 @@ typedef struct { | @@ -41,8 +47,34 @@ typedef struct { | ||
| 41 | uint16_t keycode; | 47 | uint16_t keycode; |
| 42 | } keysym2keycode_extra[MAX_EXTRA_COUNT]; | 48 | } keysym2keycode_extra[MAX_EXTRA_COUNT]; |
| 43 | int extra_count; | 49 | int extra_count; |
| 50 | + struct key_range *keypad_range; | ||
| 51 | + struct key_range *numlock_range; | ||
| 44 | } kbd_layout_t; | 52 | } kbd_layout_t; |
| 45 | 53 | ||
| 54 | +static void add_to_key_range(struct key_range **krp, int code) { | ||
| 55 | + struct key_range *kr; | ||
| 56 | + for (kr = *krp; kr; kr = kr->next) { | ||
| 57 | + if (code >= kr->start && code <= kr->end) | ||
| 58 | + break; | ||
| 59 | + if (code == kr->start - 1) { | ||
| 60 | + kr->start--; | ||
| 61 | + break; | ||
| 62 | + } | ||
| 63 | + if (code == kr->end + 1) { | ||
| 64 | + kr->end++; | ||
| 65 | + break; | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + if (kr == NULL) { | ||
| 69 | + kr = qemu_mallocz(sizeof(*kr)); | ||
| 70 | + if (kr) { | ||
| 71 | + kr->start = kr->end = code; | ||
| 72 | + kr->next = *krp; | ||
| 73 | + *krp = kr; | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | +} | ||
| 77 | + | ||
| 46 | static kbd_layout_t *parse_keyboard_layout(const char *language, | 78 | static kbd_layout_t *parse_keyboard_layout(const char *language, |
| 47 | kbd_layout_t * k) | 79 | kbd_layout_t * k) |
| 48 | { | 80 | { |
| @@ -87,7 +119,15 @@ static kbd_layout_t *parse_keyboard_layout(const char *language, | @@ -87,7 +119,15 @@ static kbd_layout_t *parse_keyboard_layout(const char *language, | ||
| 87 | // fprintf(stderr, "Warning: unknown keysym %s\n", line); | 119 | // fprintf(stderr, "Warning: unknown keysym %s\n", line); |
| 88 | } else { | 120 | } else { |
| 89 | const char *rest = end_of_keysym + 1; | 121 | const char *rest = end_of_keysym + 1; |
| 90 | - int keycode = strtol(rest, NULL, 0); | 122 | + char *rest2; |
| 123 | + int keycode = strtol(rest, &rest2, 0); | ||
| 124 | + | ||
| 125 | + if (rest && strstr(rest, "numlock")) { | ||
| 126 | + add_to_key_range(&k->keypad_range, keycode); | ||
| 127 | + add_to_key_range(&k->numlock_range, keysym); | ||
| 128 | + //fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode); | ||
| 129 | + } | ||
| 130 | + | ||
| 91 | /* if(keycode&0x80) | 131 | /* if(keycode&0x80) |
| 92 | keycode=(keycode<<8)^0x80e0; */ | 132 | keycode=(keycode<<8)^0x80e0; */ |
| 93 | if (keysym < MAX_NORMAL_KEYCODE) { | 133 | if (keysym < MAX_NORMAL_KEYCODE) { |
| @@ -143,3 +183,25 @@ static int keysym2scancode(void *kbd_layout, int keysym) | @@ -143,3 +183,25 @@ static int keysym2scancode(void *kbd_layout, int keysym) | ||
| 143 | } | 183 | } |
| 144 | return 0; | 184 | return 0; |
| 145 | } | 185 | } |
| 186 | + | ||
| 187 | +static inline int keycode_is_keypad(void *kbd_layout, int keycode) | ||
| 188 | +{ | ||
| 189 | + kbd_layout_t *k = kbd_layout; | ||
| 190 | + struct key_range *kr; | ||
| 191 | + | ||
| 192 | + for (kr = k->keypad_range; kr; kr = kr->next) | ||
| 193 | + if (keycode >= kr->start && keycode <= kr->end) | ||
| 194 | + return 1; | ||
| 195 | + return 0; | ||
| 196 | +} | ||
| 197 | + | ||
| 198 | +static inline int keysym_is_numlock(void *kbd_layout, int keysym) | ||
| 199 | +{ | ||
| 200 | + kbd_layout_t *k = kbd_layout; | ||
| 201 | + struct key_range *kr; | ||
| 202 | + | ||
| 203 | + for (kr = k->numlock_range; kr; kr = kr->next) | ||
| 204 | + if (keysym >= kr->start && keysym <= kr->end) | ||
| 205 | + return 1; | ||
| 206 | + return 0; | ||
| 207 | +} |
vl.h
| @@ -374,6 +374,7 @@ void vga_hw_screen_dump(const char *filename); | @@ -374,6 +374,7 @@ void vga_hw_screen_dump(const char *filename); | ||
| 374 | int is_graphic_console(void); | 374 | int is_graphic_console(void); |
| 375 | CharDriverState *text_console_init(DisplayState *ds, const char *p); | 375 | CharDriverState *text_console_init(DisplayState *ds, const char *p); |
| 376 | void console_select(unsigned int index); | 376 | void console_select(unsigned int index); |
| 377 | +void console_color_init(DisplayState *ds); | ||
| 377 | 378 | ||
| 378 | /* serial ports */ | 379 | /* serial ports */ |
| 379 | 380 |
vnc.c
| @@ -284,7 +284,10 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h) | @@ -284,7 +284,10 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h) | ||
| 284 | exit(1); | 284 | exit(1); |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | - ds->depth = vs->depth * 8; | 287 | + if (ds->depth != vs->depth * 8) { |
| 288 | + ds->depth = vs->depth * 8; | ||
| 289 | + console_color_init(ds); | ||
| 290 | + } | ||
| 288 | size_changed = ds->width != w || ds->height != h; | 291 | size_changed = ds->width != w || ds->height != h; |
| 289 | ds->width = w; | 292 | ds->width = w; |
| 290 | ds->height = h; | 293 | ds->height = h; |
| @@ -907,6 +910,12 @@ static void reset_keys(VncState *vs) | @@ -907,6 +910,12 @@ static void reset_keys(VncState *vs) | ||
| 907 | } | 910 | } |
| 908 | } | 911 | } |
| 909 | 912 | ||
| 913 | +static void press_key(VncState *vs, int keysym) | ||
| 914 | +{ | ||
| 915 | + kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f); | ||
| 916 | + kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80); | ||
| 917 | +} | ||
| 918 | + | ||
| 910 | static void do_key_event(VncState *vs, int down, uint32_t sym) | 919 | static void do_key_event(VncState *vs, int down, uint32_t sym) |
| 911 | { | 920 | { |
| 912 | int keycode; | 921 | int keycode; |
| @@ -934,6 +943,28 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) | @@ -934,6 +943,28 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) | ||
| 934 | return; | 943 | return; |
| 935 | } | 944 | } |
| 936 | break; | 945 | break; |
| 946 | + case 0x45: /* NumLock */ | ||
| 947 | + if (!down) | ||
| 948 | + vs->modifiers_state[keycode] ^= 1; | ||
| 949 | + break; | ||
| 950 | + } | ||
| 951 | + | ||
| 952 | + if (keycode_is_keypad(vs->kbd_layout, keycode)) { | ||
| 953 | + /* If the numlock state needs to change then simulate an additional | ||
| 954 | + keypress before sending this one. This will happen if the user | ||
| 955 | + toggles numlock away from the VNC window. | ||
| 956 | + */ | ||
| 957 | + if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) { | ||
| 958 | + if (!vs->modifiers_state[0x45]) { | ||
| 959 | + vs->modifiers_state[0x45] = 1; | ||
| 960 | + press_key(vs, 0xff7f); | ||
| 961 | + } | ||
| 962 | + } else { | ||
| 963 | + if (vs->modifiers_state[0x45]) { | ||
| 964 | + vs->modifiers_state[0x45] = 0; | ||
| 965 | + press_key(vs, 0xff7f); | ||
| 966 | + } | ||
| 967 | + } | ||
| 937 | } | 968 | } |
| 938 | 969 | ||
| 939 | if (is_graphic_console()) { | 970 | if (is_graphic_console()) { |
| @@ -991,7 +1022,7 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) | @@ -991,7 +1022,7 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) | ||
| 991 | 1022 | ||
| 992 | static void key_event(VncState *vs, int down, uint32_t sym) | 1023 | static void key_event(VncState *vs, int down, uint32_t sym) |
| 993 | { | 1024 | { |
| 994 | - if (sym >= 'A' && sym <= 'Z') | 1025 | + if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) |
| 995 | sym = sym - 'A' + 'a'; | 1026 | sym = sym - 'A' + 'a'; |
| 996 | do_key_event(vs, down, sym); | 1027 | do_key_event(vs, down, sym); |
| 997 | } | 1028 | } |
vnc_keysym.h
| @@ -231,6 +231,19 @@ static name2keysym_t name2keysym[]={ | @@ -231,6 +231,19 @@ static name2keysym_t name2keysym[]={ | ||
| 231 | {"Home", 0xff50}, /* XK_Home */ | 231 | {"Home", 0xff50}, /* XK_Home */ |
| 232 | {"End", 0xff57}, /* XK_End */ | 232 | {"End", 0xff57}, /* XK_End */ |
| 233 | {"Scroll_Lock", 0xff14}, /* XK_Scroll_Lock */ | 233 | {"Scroll_Lock", 0xff14}, /* XK_Scroll_Lock */ |
| 234 | +{"KP_Home", 0xff95}, | ||
| 235 | +{"KP_Left", 0xff96}, | ||
| 236 | +{"KP_Up", 0xff97}, | ||
| 237 | +{"KP_Right", 0xff98}, | ||
| 238 | +{"KP_Down", 0xff99}, | ||
| 239 | +{"KP_Prior", 0xff9a}, | ||
| 240 | +{"KP_Page_Up", 0xff9a}, | ||
| 241 | +{"KP_Next", 0xff9b}, | ||
| 242 | +{"KP_Page_Down", 0xff9b}, | ||
| 243 | +{"KP_End", 0xff9c}, | ||
| 244 | +{"KP_Begin", 0xff9d}, | ||
| 245 | +{"KP_Insert", 0xff9e}, | ||
| 246 | +{"KP_Delete", 0xff9f}, | ||
| 234 | {"F1", 0xffbe}, /* XK_F1 */ | 247 | {"F1", 0xffbe}, /* XK_F1 */ |
| 235 | {"F2", 0xffbf}, /* XK_F2 */ | 248 | {"F2", 0xffbf}, /* XK_F2 */ |
| 236 | {"F3", 0xffc0}, /* XK_F3 */ | 249 | {"F3", 0xffc0}, /* XK_F3 */ |
| @@ -258,6 +271,7 @@ static name2keysym_t name2keysym[]={ | @@ -258,6 +271,7 @@ static name2keysym_t name2keysym[]={ | ||
| 258 | {"KP_8", 0xffb8}, /* XK_KP_8 */ | 271 | {"KP_8", 0xffb8}, /* XK_KP_8 */ |
| 259 | {"KP_9", 0xffb9}, /* XK_KP_9 */ | 272 | {"KP_9", 0xffb9}, /* XK_KP_9 */ |
| 260 | {"KP_Add", 0xffab}, /* XK_KP_Add */ | 273 | {"KP_Add", 0xffab}, /* XK_KP_Add */ |
| 274 | +{"KP_Separator", 0xffac},/* XK_KP_Separator */ | ||
| 261 | {"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ | 275 | {"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ |
| 262 | {"KP_Divide", 0xffaf}, /* XK_KP_Divide */ | 276 | {"KP_Divide", 0xffaf}, /* XK_KP_Divide */ |
| 263 | {"KP_Enter", 0xff8d}, /* XK_KP_Enter */ | 277 | {"KP_Enter", 0xff8d}, /* XK_KP_Enter */ |