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 | 509 | c++; |
| 510 | 510 | } |
| 511 | 511 | } |
| 512 | - free(s->cells); | |
| 512 | + qemu_free(s->cells); | |
| 513 | 513 | s->cells = cells; |
| 514 | 514 | } |
| 515 | 515 | |
| ... | ... | @@ -1167,11 +1167,21 @@ int is_graphic_console(void) |
| 1167 | 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 | 1181 | CharDriverState *text_console_init(DisplayState *ds, const char *p) |
| 1171 | 1182 | { |
| 1172 | 1183 | CharDriverState *chr; |
| 1173 | 1184 | TextConsole *s; |
| 1174 | - int i,j; | |
| 1175 | 1185 | unsigned width; |
| 1176 | 1186 | unsigned height; |
| 1177 | 1187 | static int color_inited; |
| ... | ... | @@ -1195,12 +1205,7 @@ CharDriverState *text_console_init(DisplayState *ds, const char *p) |
| 1195 | 1205 | |
| 1196 | 1206 | if (!color_inited) { |
| 1197 | 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 | 1210 | s->y_displayed = 0; |
| 1206 | 1211 | s->y_base = 0; | ... | ... |
keymaps.c
| ... | ... | @@ -32,6 +32,12 @@ static int get_keysym(const char *name) |
| 32 | 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 | 41 | #define MAX_NORMAL_KEYCODE 512 |
| 36 | 42 | #define MAX_EXTRA_COUNT 256 |
| 37 | 43 | typedef struct { |
| ... | ... | @@ -41,8 +47,34 @@ typedef struct { |
| 41 | 47 | uint16_t keycode; |
| 42 | 48 | } keysym2keycode_extra[MAX_EXTRA_COUNT]; |
| 43 | 49 | int extra_count; |
| 50 | + struct key_range *keypad_range; | |
| 51 | + struct key_range *numlock_range; | |
| 44 | 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 | 78 | static kbd_layout_t *parse_keyboard_layout(const char *language, |
| 47 | 79 | kbd_layout_t * k) |
| 48 | 80 | { |
| ... | ... | @@ -87,7 +119,15 @@ static kbd_layout_t *parse_keyboard_layout(const char *language, |
| 87 | 119 | // fprintf(stderr, "Warning: unknown keysym %s\n", line); |
| 88 | 120 | } else { |
| 89 | 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 | 131 | /* if(keycode&0x80) |
| 92 | 132 | keycode=(keycode<<8)^0x80e0; */ |
| 93 | 133 | if (keysym < MAX_NORMAL_KEYCODE) { |
| ... | ... | @@ -143,3 +183,25 @@ static int keysym2scancode(void *kbd_layout, int keysym) |
| 143 | 183 | } |
| 144 | 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 | 374 | int is_graphic_console(void); |
| 375 | 375 | CharDriverState *text_console_init(DisplayState *ds, const char *p); |
| 376 | 376 | void console_select(unsigned int index); |
| 377 | +void console_color_init(DisplayState *ds); | |
| 377 | 378 | |
| 378 | 379 | /* serial ports */ |
| 379 | 380 | ... | ... |
vnc.c
| ... | ... | @@ -284,7 +284,10 @@ static void vnc_dpy_resize(DisplayState *ds, int w, int h) |
| 284 | 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 | 291 | size_changed = ds->width != w || ds->height != h; |
| 289 | 292 | ds->width = w; |
| 290 | 293 | ds->height = h; |
| ... | ... | @@ -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 | 919 | static void do_key_event(VncState *vs, int down, uint32_t sym) |
| 911 | 920 | { |
| 912 | 921 | int keycode; |
| ... | ... | @@ -934,6 +943,28 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) |
| 934 | 943 | return; |
| 935 | 944 | } |
| 936 | 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 | 970 | if (is_graphic_console()) { |
| ... | ... | @@ -991,7 +1022,7 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) |
| 991 | 1022 | |
| 992 | 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 | 1026 | sym = sym - 'A' + 'a'; |
| 996 | 1027 | do_key_event(vs, down, sym); |
| 997 | 1028 | } | ... | ... |
vnc_keysym.h
| ... | ... | @@ -231,6 +231,19 @@ static name2keysym_t name2keysym[]={ |
| 231 | 231 | {"Home", 0xff50}, /* XK_Home */ |
| 232 | 232 | {"End", 0xff57}, /* XK_End */ |
| 233 | 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 | 247 | {"F1", 0xffbe}, /* XK_F1 */ |
| 235 | 248 | {"F2", 0xffbf}, /* XK_F2 */ |
| 236 | 249 | {"F3", 0xffc0}, /* XK_F3 */ |
| ... | ... | @@ -258,6 +271,7 @@ static name2keysym_t name2keysym[]={ |
| 258 | 271 | {"KP_8", 0xffb8}, /* XK_KP_8 */ |
| 259 | 272 | {"KP_9", 0xffb9}, /* XK_KP_9 */ |
| 260 | 273 | {"KP_Add", 0xffab}, /* XK_KP_Add */ |
| 274 | +{"KP_Separator", 0xffac},/* XK_KP_Separator */ | |
| 261 | 275 | {"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ |
| 262 | 276 | {"KP_Divide", 0xffaf}, /* XK_KP_Divide */ |
| 263 | 277 | {"KP_Enter", 0xff8d}, /* XK_KP_Enter */ | ... | ... |