source: trunk/packages/xen-common/xen-common/tools/ioemu/patches/vnc-numpad-handling @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 6.6 KB
Line 
1# HG changeset patch
2# User Ewan Mellor <ewan@xensource.com>
3# Node ID c7f4a89eb054a1ad411da1e4cdc8aeda1a98c4fa
4# Parent  565cd8f32c70da8ae7dbaaeb9dff28aa8b6307e1
5Fix numpad handling in QEMU's VNC server.  The keymaps that we have include
6information on which keys change depending upon the numlock setting, but
7this isn't being used.  By forcing numlock on and off as necessary, when
8receiving these keysyms through the VNC connection, we ensure that the
9server's numlock status is the same as the client's.
10
11Signed-off-by: Ewan Mellor <ewan@xensource.com>
12
13Index: 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+}
133Index: 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 
205Index: 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 */
Note: See TracBrowser for help on using the repository browser.