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 */ | ... | ... |