1 | # HG changeset patch |
---|
2 | # User Ewan Mellor <ewan@xensource.com> |
---|
3 | # Node ID c7f4a89eb054a1ad411da1e4cdc8aeda1a98c4fa |
---|
4 | # Parent 565cd8f32c70da8ae7dbaaeb9dff28aa8b6307e1 |
---|
5 | Fix numpad handling in QEMU's VNC server. The keymaps that we have include |
---|
6 | information on which keys change depending upon the numlock setting, but |
---|
7 | this isn't being used. By forcing numlock on and off as necessary, when |
---|
8 | receiving these keysyms through the VNC connection, we ensure that the |
---|
9 | server's numlock status is the same as the client's. |
---|
10 | |
---|
11 | Signed-off-by: Ewan Mellor <ewan@xensource.com> |
---|
12 | |
---|
13 | Index: ioemu/keymaps.c |
---|
14 | =================================================================== |
---|
15 | --- ioemu.orig/keymaps.c 2006-12-06 23:41:30.000000000 +0000 |
---|
16 | +++ ioemu/keymaps.c 2006-12-08 18:20:27.000000000 +0000 |
---|
17 | @@ -36,8 +36,10 @@ |
---|
18 | #define MAX_EXTRA_COUNT 256 |
---|
19 | typedef struct { |
---|
20 | uint16_t keysym2keycode[MAX_NORMAL_KEYCODE]; |
---|
21 | + int keysym2numlock[MAX_NORMAL_KEYCODE]; |
---|
22 | struct { |
---|
23 | int keysym; |
---|
24 | + int numlock; |
---|
25 | uint16_t keycode; |
---|
26 | } keysym2keycode_extra[MAX_EXTRA_COUNT]; |
---|
27 | int extra_count; |
---|
28 | @@ -50,6 +52,8 @@ |
---|
29 | char file_name[1024]; |
---|
30 | char line[1024]; |
---|
31 | int len; |
---|
32 | + int *keycode2numlock; |
---|
33 | + int i; |
---|
34 | |
---|
35 | snprintf(file_name, sizeof(file_name), |
---|
36 | "%s/keymaps/%s", bios_dir, language); |
---|
37 | @@ -63,6 +67,15 @@ |
---|
38 | "Could not read keymap file: '%s'\n", file_name); |
---|
39 | return 0; |
---|
40 | } |
---|
41 | + |
---|
42 | + /* Allocate a temporary map tracking which keycodes change when numlock is |
---|
43 | + set. Keycodes are 16 bit, so 65536 is safe. */ |
---|
44 | + keycode2numlock = malloc(65536 * sizeof(int)); |
---|
45 | + if (!keycode2numlock) { |
---|
46 | + perror("Could not read keymap file"); |
---|
47 | + return 0; |
---|
48 | + } |
---|
49 | + |
---|
50 | for(;;) { |
---|
51 | if (fgets(line, 1024, f) == NULL) |
---|
52 | break; |
---|
53 | @@ -86,13 +99,19 @@ |
---|
54 | if (keysym == 0) { |
---|
55 | // fprintf(stderr, "Warning: unknown keysym %s\n", line); |
---|
56 | } else { |
---|
57 | - const char *rest = end_of_keysym + 1; |
---|
58 | - int keycode = strtol(rest, NULL, 0); |
---|
59 | + char *rest = end_of_keysym + 1; |
---|
60 | + int keycode = strtol(rest, &rest, 0); |
---|
61 | + int numlock = (rest != NULL && |
---|
62 | + strstr(rest, "numlock") != NULL); |
---|
63 | + |
---|
64 | + keycode2numlock[keycode] = numlock; |
---|
65 | + |
---|
66 | /* if(keycode&0x80) |
---|
67 | keycode=(keycode<<8)^0x80e0; */ |
---|
68 | if (keysym < MAX_NORMAL_KEYCODE) { |
---|
69 | //fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode); |
---|
70 | k->keysym2keycode[keysym] = keycode; |
---|
71 | + k->keysym2numlock[keysym] = numlock; |
---|
72 | } else { |
---|
73 | if (k->extra_count >= MAX_EXTRA_COUNT) { |
---|
74 | fprintf(stderr, |
---|
75 | @@ -107,6 +126,8 @@ |
---|
76 | keysym = keysym; |
---|
77 | k->keysym2keycode_extra[k->extra_count]. |
---|
78 | keycode = keycode; |
---|
79 | + k->keysym2keycode_extra[k->extra_count]. |
---|
80 | + numlock = numlock; |
---|
81 | k->extra_count++; |
---|
82 | } |
---|
83 | } |
---|
84 | @@ -115,6 +136,22 @@ |
---|
85 | } |
---|
86 | } |
---|
87 | fclose(f); |
---|
88 | + |
---|
89 | + for (i = 0; i < MAX_NORMAL_KEYCODE; i++) { |
---|
90 | + if (k->keysym2numlock[i] != 1) { |
---|
91 | + k->keysym2numlock[i] = -keycode2numlock[k->keysym2keycode[i]]; |
---|
92 | + } |
---|
93 | + } |
---|
94 | + |
---|
95 | + for (i = 0; i < k->extra_count; i++) { |
---|
96 | + if (k->keysym2keycode_extra[i].numlock != 1) { |
---|
97 | + k->keysym2keycode_extra[i].numlock = |
---|
98 | + -keycode2numlock[k->keysym2keycode_extra[i].keycode]; |
---|
99 | + } |
---|
100 | + } |
---|
101 | + |
---|
102 | + free(keycode2numlock); |
---|
103 | + |
---|
104 | return k; |
---|
105 | } |
---|
106 | |
---|
107 | @@ -143,3 +180,25 @@ |
---|
108 | } |
---|
109 | return 0; |
---|
110 | } |
---|
111 | + |
---|
112 | +/** |
---|
113 | + * Returns 1 if the given keysym requires numlock to be pressed, -1 if it |
---|
114 | + * requires it to be cleared, and 0 otherwise. |
---|
115 | + */ |
---|
116 | +static int keysym2numlock(void *kbd_layout, int keysym) |
---|
117 | +{ |
---|
118 | + kbd_layout_t *k = kbd_layout; |
---|
119 | + if (keysym < MAX_NORMAL_KEYCODE) { |
---|
120 | + return k->keysym2numlock[keysym]; |
---|
121 | + } else { |
---|
122 | + int i; |
---|
123 | +#ifdef XK_ISO_Left_Tab |
---|
124 | + if (keysym == XK_ISO_Left_Tab) |
---|
125 | + keysym = XK_Tab; |
---|
126 | +#endif |
---|
127 | + for (i = 0; i < k->extra_count; i++) |
---|
128 | + if (k->keysym2keycode_extra[i].keysym == keysym) |
---|
129 | + return k->keysym2keycode_extra[i].numlock; |
---|
130 | + } |
---|
131 | + return 0; |
---|
132 | +} |
---|
133 | Index: ioemu/vnc.c |
---|
134 | =================================================================== |
---|
135 | --- ioemu.orig/vnc.c 2006-12-08 18:18:26.000000000 +0000 |
---|
136 | +++ ioemu/vnc.c 2006-12-08 18:19:43.000000000 +0000 |
---|
137 | @@ -115,6 +115,7 @@ |
---|
138 | |
---|
139 | int ctl_keys; /* Ctrl+Alt starts calibration */ |
---|
140 | int shift_keys; /* Shift / CapsLock keys */ |
---|
141 | + int numlock; |
---|
142 | }; |
---|
143 | |
---|
144 | #define DIRTY_PIXEL_BITS 64 |
---|
145 | @@ -854,14 +855,40 @@ |
---|
146 | } |
---|
147 | } |
---|
148 | |
---|
149 | +static void press_key(VncState *vs, int keycode) |
---|
150 | +{ |
---|
151 | + kbd_put_keycode(keysym2scancode(vs->kbd_layout, keycode) & 0x7f); |
---|
152 | + kbd_put_keycode(keysym2scancode(vs->kbd_layout, keycode) | 0x80); |
---|
153 | +} |
---|
154 | + |
---|
155 | static void do_key_event(VncState *vs, int down, uint32_t sym) |
---|
156 | { |
---|
157 | sym &= 0xFFFF; |
---|
158 | |
---|
159 | if (is_graphic_console()) { |
---|
160 | int keycode; |
---|
161 | + int numlock; |
---|
162 | |
---|
163 | keycode = keysym2scancode(vs->kbd_layout, sym); |
---|
164 | + numlock = keysym2numlock(vs->kbd_layout, sym); |
---|
165 | + |
---|
166 | + /* If the numlock state needs to change then simulate an additional |
---|
167 | + keypress before sending this one. This will happen if the user |
---|
168 | + toggles numlock away from the VNC window. |
---|
169 | + */ |
---|
170 | + if (numlock == 1) { |
---|
171 | + if (!vs->numlock) { |
---|
172 | + vs->numlock = 1; |
---|
173 | + press_key(vs, XK_Num_Lock); |
---|
174 | + } |
---|
175 | + } |
---|
176 | + else if (numlock == -1) { |
---|
177 | + if (vs->numlock) { |
---|
178 | + vs->numlock = 0; |
---|
179 | + press_key(vs, XK_Num_Lock); |
---|
180 | + } |
---|
181 | + } |
---|
182 | + |
---|
183 | if (keycode & 0x80) |
---|
184 | kbd_put_keycode(0xe0); |
---|
185 | if (down) |
---|
186 | @@ -932,6 +959,10 @@ |
---|
187 | vs->shift_keys ^= 2; |
---|
188 | break; |
---|
189 | |
---|
190 | + case XK_Num_Lock: |
---|
191 | + vs->numlock = !vs->numlock; |
---|
192 | + break; |
---|
193 | + |
---|
194 | case XK_1 ... XK_9: |
---|
195 | if ((vs->ctl_keys & 3) != 3) |
---|
196 | break; |
---|
197 | @@ -1355,6 +1386,7 @@ |
---|
198 | vs->lsock = -1; |
---|
199 | vs->csock = -1; |
---|
200 | vs->depth = 4; |
---|
201 | + vs->numlock = 0; |
---|
202 | |
---|
203 | vs->ds = ds; |
---|
204 | |
---|
205 | Index: ioemu/vnc_keysym.h |
---|
206 | =================================================================== |
---|
207 | --- ioemu.orig/vnc_keysym.h 2006-12-08 18:17:01.000000000 +0000 |
---|
208 | +++ ioemu/vnc_keysym.h 2006-12-08 18:19:43.000000000 +0000 |
---|
209 | @@ -231,6 +231,19 @@ |
---|
210 | {"Home", 0xff50}, /* XK_Home */ |
---|
211 | {"End", 0xff57}, /* XK_End */ |
---|
212 | {"Scroll_Lock", 0xff14}, /* XK_Scroll_Lock */ |
---|
213 | +{"KP_Home", 0xff95}, |
---|
214 | +{"KP_Left", 0xff96}, |
---|
215 | +{"KP_Up", 0xff97}, |
---|
216 | +{"KP_Right", 0xff98}, |
---|
217 | +{"KP_Down", 0xff99}, |
---|
218 | +{"KP_Prior", 0xff9a}, |
---|
219 | +{"KP_Page_Up", 0xff9a}, |
---|
220 | +{"KP_Next", 0xff9b}, |
---|
221 | +{"KP_Page_Down", 0xff9b}, |
---|
222 | +{"KP_End", 0xff9c}, |
---|
223 | +{"KP_Begin", 0xff9d}, |
---|
224 | +{"KP_Insert", 0xff9e}, |
---|
225 | +{"KP_Delete", 0xff9f}, |
---|
226 | {"F1", 0xffbe}, /* XK_F1 */ |
---|
227 | {"F2", 0xffbf}, /* XK_F2 */ |
---|
228 | {"F3", 0xffc0}, /* XK_F3 */ |
---|
229 | @@ -258,6 +271,7 @@ |
---|
230 | {"KP_8", 0xffb8}, /* XK_KP_8 */ |
---|
231 | {"KP_9", 0xffb9}, /* XK_KP_9 */ |
---|
232 | {"KP_Add", 0xffab}, /* XK_KP_Add */ |
---|
233 | +{"KP_Separator", 0xffac},/* XK_KP_Separator */ |
---|
234 | {"KP_Decimal", 0xffae}, /* XK_KP_Decimal */ |
---|
235 | {"KP_Divide", 0xffaf}, /* XK_KP_Divide */ |
---|
236 | {"KP_Enter", 0xff8d}, /* XK_KP_Enter */ |
---|