WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1 of 3][IOEMU] Fix keymap handling for vnc console

To: xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 1 of 3][IOEMU] Fix keymap handling for vnc console
From: John Haxby <john.haxby@xxxxxxxxxx>
Date: Thu, 11 Dec 2008 16:42:11 +0000
Delivery-date: Thu, 11 Dec 2008 08:42:47 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <494141E2.4000304@xxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <494141E2.4000304@xxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.18 (X11/20081119)
Fix keymap handling for international keyboards

Signed-off-by: John Haxby <john.haxby@xxxxxxxxxx>

keymaps.c |  364 ++++++++++++++++++++++++++++++++++++--------------------------
vnc.c     |  134 ++++++++--------------
2 files changed, 264 insertions(+), 234 deletions(-)

diff --git a/keymaps.c b/keymaps.c
index 1984678..4029500 100644
--- a/keymaps.c
+++ b/keymaps.c
@@ -22,60 +22,62 @@
 * THE SOFTWARE.
 */

+static int cmp_keysym(const void *a, const void *b) {
+    return strcmp(((name2keysym_t *) a)->name, ((name2keysym_t *) b)->name);
+}
+
static int get_keysym(const char *name)
{
-    name2keysym_t *p;
-    for(p = name2keysym; p->name != NULL; p++) {
-        if (!strcmp(p->name, name))
-            return p->keysym;
+    static int n = -1;
+    int l, r, m;
+
+    if (n < 0) {
+       for (n = 0; name2keysym[n].name; n++);
+       qsort(name2keysym, n, sizeof(name2keysym_t), cmp_keysym);
+    }
+    l = 0;
+    r = n-1;
+    while (l <= r) {
+       m = (l + r) / 2;
+       int cmp = strcmp(name2keysym[m].name, name);
+       if (cmp < 0)
+           l = m + 1;
+       else if (cmp > 0)
+           r = m - 1;
+       else
+           return name2keysym[m].keysym;
+    }
+    if (name[0] == 'U') {
+       /* unicode symbol key */
+       char *ptr;
+       int k = strtol(name+1, &ptr, 16);
+       return *ptr ? 0 : k;
    }
    return 0;
}

-struct key_range {
-    int start;
-    int end;
-    struct key_range *next;
-};
+#define MAX_SCANCODE 256
+#define KEY_LOCALSTATE 0x1
+#define KEY_KEYPAD 0x2

-#define MAX_NORMAL_KEYCODE 512
-#define MAX_EXTRA_COUNT 256
typedef struct {
-    uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
-    struct {
-       int keysym;
-       uint16_t keycode;
-    } keysym2keycode_extra[MAX_EXTRA_COUNT];
-    int extra_count;
-    struct key_range *keypad_range;
-    struct key_range *numlock_range;
-    struct key_range *shift_range;
-    struct key_range *localstate_range;
-} kbd_layout_t;
+    int keysym;
+    int keycode;
+} keysym2keycode_t;

-static void add_to_key_range(struct key_range **krp, int code) {
-    struct key_range *kr;
-    for (kr = *krp; kr; kr = kr->next) {
-       if (code >= kr->start && code <= kr->end)
-           break;
-       if (code == kr->start - 1) {
-           kr->start--;
-           break;
-       }
-       if (code == kr->end + 1) {
-           kr->end++;
-           break;
-       }
-    }
-    if (kr == NULL) {
-       kr = qemu_mallocz(sizeof(*kr));
-       if (kr) {
-           kr->start = kr->end = code;
-           kr->next = *krp;
-           *krp = kr;
-       }
-    }
-}
+typedef struct {
+    int n;
+    keysym2keycode_t k[MAX_SCANCODE];
+} keysym_map_t;
+
+typedef struct {
+    keysym_map_t plain;
+    keysym_map_t shift;
+    keysym_map_t altgr;
+    keysym_map_t shift_altgr;
+    keysym_map_t numlock;
+    uint32_t flags [MAX_SCANCODE];
+} kbd_layout_t;

static kbd_layout_t *parse_keyboard_layout(const char *language,
                                           kbd_layout_t * k)
@@ -97,143 +99,209 @@ static kbd_layout_t *parse_keyboard_layout(const char 
*language,
                "Could not read keymap file: '%s'\n", file_name);
        return 0;
    }
-    for(;;) {
-       if (fgets(line, 1024, f) == NULL)
-            break;
-        len = strlen(line);
-        if (len > 0 && line[len - 1] == '\n')
-            line[len - 1] = '\0';
-        if (line[0] == '#')
+    while (fgets(line, 1024, f)) {
+       char *ptr = strchr(line, '#');
+       char keyname[1024], p1[1024], p2[1024];
+       int keysym, keycode;
+       int shift = 0;
+       int altgr = 0;
+       int addupper = 0;
+       int numlock = 0;
+       int inhibit = 0;
+
+       if (ptr)
+           *ptr-- = '\0';
+       else
+           ptr = &line[strlen(line)-1];
+       while (isspace(*ptr))
+           *ptr-- = '\0';
+       if (!*line)
+           continue;
+       if (strncmp(line, "map ", 4) == 0)
+           continue;
+       if (sscanf(line, "include %s", p1) == 1) {
+           parse_keyboard_layout(p1, k);
            continue;
-       if (!strncmp(line, "map ", 4))
+       }
+       if (sscanf(line, "%s %i %s %s", keyname, &keycode, p1, p2) == 4) {
+           shift = (strcmp(p1, "shift") == 0 || strcmp(p2, "shift") == 0);
+           altgr = (strcmp(p1, "altgr") == 0 || strcmp(p2, "altgr") == 0);
+       } else if (sscanf(line, "%s %i %s", keyname, &keycode, p1) == 3) {
+           shift = (strcmp(p1, "shift") == 0);
+           altgr = (strcmp(p1, "altgr") == 0);
+           addupper = (strcmp(p1, "addupper") == 0);
+           numlock = (strcmp(p1, "numlock") == 0);
+           inhibit = (strcmp(p1, "inhibit") == 0);
+       } else if (sscanf(line, "%s %i", keyname, &keycode) != 2)
+           /* silently ignore spurious lines */
+           continue;
+
+       if (inhibit)
+           continue;
+       if ((keysym = get_keysym(keyname)) == 0) {
+           fprintf(stderr, "%s: warning: unknown keysym %s\n",
+                   file_name, keyname);
            continue;
-       if (!strncmp(line, "include ", 8)) {
-           parse_keyboard_layout(line + 8, k);
-        } else {
-           char *end_of_keysym = line;
-           while (*end_of_keysym != 0 && *end_of_keysym != ' ')
-               end_of_keysym++;
-           if (*end_of_keysym) {
-               int keysym;
-               *end_of_keysym = 0;
-               keysym = get_keysym(line);
-               if (keysym == 0) {
-                    //             fprintf(stderr, "Warning: unknown keysym 
%s\n", line);
-               } else {
-                   const char *rest = end_of_keysym + 1;
-                   char *rest2;
-                   int keycode = strtol(rest, &rest2, 0);
-
-                   if (rest && strstr(rest, "numlock")) {
-                       add_to_key_range(&k->keypad_range, keycode);
-                       add_to_key_range(&k->numlock_range, keysym);
-                       //fprintf(stderr, "keypad keysym %04x keycode %d\n", 
keysym, keycode);
-                   }
-                   if (rest && strstr(rest, "shift")) {
-                       add_to_key_range(&k->shift_range, keysym);
-                       //fprintf(stderr, "shift keysym %04x keycode %d\n", 
keysym, keycode);
-                   }
-                   if (rest && strstr(rest, "localstate")) {
-                       add_to_key_range(&k->localstate_range, keycode);
-                       //fprintf(stderr, "localstate keysym %04x keycode 
%d\n", keysym, keycode);
-                   }
-
-                   /* if(keycode&0x80)
-                      keycode=(keycode<<8)^0x80e0; */
-                   if (keysym < MAX_NORMAL_KEYCODE) {
-                       //fprintf(stderr,"Setting keysym %s (%d) to 
%d\n",line,keysym,keycode);
-                       k->keysym2keycode[keysym] = keycode;
-                   } else {
-                       if (k->extra_count >= MAX_EXTRA_COUNT) {
-                           fprintf(stderr,
-                                   "Warning: Could not assign keysym %s (0x%x) 
because of memory constraints.\n",
-                                   line, keysym);
-                       } else {
-#if 0
-                           fprintf(stderr, "Setting %d: %d,%d\n",
-                                   k->extra_count, keysym, keycode);
-#endif
-                           k->keysym2keycode_extra[k->extra_count].
-                               keysym = keysym;
-                           k->keysym2keycode_extra[k->extra_count].
-                               keycode = keycode;
-                           k->extra_count++;
-                       }
-                   }
-               }
-           }
+       }
+       if (keycode <= 0 || keycode >= MAX_SCANCODE) {
+           fprintf(stderr, "%s: warning: keycode %#x for %s out of range\n",
+                   file_name, keycode, keyname);
+           continue;
+       }
+       if (numlock)
+           k->numlock.k[keycode].keysym = keysym;
+       else if (shift && altgr)
+           k->shift_altgr.k[keycode].keysym = keysym;
+       else if (altgr)
+           k->altgr.k[keycode].keysym = keysym;
+       else if (shift)
+           k->shift.k[keycode].keysym = keysym;
+       else {
+           k->plain.k[keycode].keysym = keysym;
+           if (addupper)
+               k->shift.k[keycode].keysym = keysym + 'A' - 'a';
        }
    }
    fclose(f);
    return k;
}

+static int cmp_map (const void *a, const void *b) {
+    return ((keysym2keycode_t *) b)->keysym - ((keysym2keycode_t *) a)->keysym;
+}
+
+static void sort_map (keysym_map_t *map) {
+    int i;
+    for (i = 0; i < MAX_SCANCODE; i++)
+       map->k[i].keycode = i;
+    /* sort undefined scancodes to the end */
+    qsort(map->k, MAX_SCANCODE, sizeof(keysym2keycode_t), cmp_map);
+    for (map->n = 0; map->n < MAX_SCANCODE; map->n++)
+       if (!map->k[map->n].keysym)
+           break;
+}
+
static void *init_keyboard_layout(const char *language)
{
-    return parse_keyboard_layout(language, 0);
+    kbd_layout_t *k = parse_keyboard_layout(language, NULL);
+    if (k) {
+       int i;
+       for (i = 0; i < MAX_SCANCODE; i++) {
+           if (!(k->shift.k[i].keysym
+                 || k->altgr.k[i].keysym
+                 || k->shift_altgr.k[i].keysym))
+               k->flags[i] |= KEY_LOCALSTATE;
+           if (k->numlock.k[i].keysym)
+               k->flags[i] |= KEY_KEYPAD;
+       }
+       sort_map(&k->plain);
+       sort_map(&k->shift);
+       sort_map(&k->altgr);
+       sort_map(&k->shift_altgr);
+       sort_map(&k->numlock);
+    }
+    return k;
}

-static int keysym2scancode(void *kbd_layout, int keysym)
+static int keysym2scancode_map (keysym_map_t *map, int keysym)
{
-    kbd_layout_t *k = kbd_layout;
-    if (keysym < MAX_NORMAL_KEYCODE) {
-       if (k->keysym2keycode[keysym] == 0)
-           fprintf(stderr, "Warning: no scancode found for keysym %d\n",
-                   keysym);
-       return k->keysym2keycode[keysym];
-    } else {
-       int i;
-#ifdef XK_ISO_Left_Tab
-       if (keysym == XK_ISO_Left_Tab)
-           keysym = XK_Tab;
-#endif
-       for (i = 0; i < k->extra_count; i++)
-           if (k->keysym2keycode_extra[i].keysym == keysym)
-               return k->keysym2keycode_extra[i].keycode;
+    int l = 0, r = map->n - 1, m;
+    while (l <= r) {
+       m = (l + r) / 2;
+       if (map->k[m].keysym == keysym)
+           return map->k[m].keycode;
+       else if (map->k[m].keysym < keysym)
+           r = m - 1;
+       else
+           l = m + 1;
    }
    return 0;
}

-static inline int keycode_is_keypad(void *kbd_layout, int keycode)
+static int keysym2scancode(void *kbd_layout, int keysym)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
+    int scancode;

-    for (kr = k->keypad_range; kr; kr = kr->next)
-        if (keycode >= kr->start && keycode <= kr->end)
-            return 1;
+    if ((scancode = keysym2scancode_map(&k->plain, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->numlock, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->shift, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->altgr, keysym)))
+       return scancode;
+    if ((scancode = keysym2scancode_map(&k->shift_altgr, keysym)))
+       return scancode;
    return 0;
}

-static inline int keysym_is_numlock(void *kbd_layout, int keysym)
+static int keysym2scancode1(void *kbd_layout, int keysym,
+                           int *shift, int *altgr)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
+    int s;
+
+    /* normal case: keysym can be found the expected modifier's map */
+    if (*shift && *altgr && (s = keysym2scancode_map(&k->shift_altgr, keysym)))
+       return s;
+    if (*altgr && (s = keysym2scancode_map(&k->altgr, keysym)))
+       return s;
+    if (*shift && (s = keysym2scancode_map(&k->shift, keysym)))
+       return s;
+    if ((s = keysym2scancode_map(&k->plain, keysym)))
+       return s;
+    if ((s = keysym2scancode_map(&k->numlock, keysym)))
+       return s;

-    for (kr = k->numlock_range; kr; kr = kr->next)
-        if (keysym >= kr->start && keysym <= kr->end)
-            return 1;
+    /* fallback for when there is some keyboard/state mismatch */
+    if ((s = keysym2scancode_map(&k->plain, keysym))) {
+       *shift = 0;
+       *altgr = 0;
+       return s;
+    }
+    if ((s = keysym2scancode_map(&k->shift, keysym))) {
+       *shift = 1;
+       *altgr = 0;
+       return s;
+    }
+    if ((s = keysym2scancode_map(&k->altgr, keysym))) {
+       *shift = 0;
+       *altgr = 1;
+       return s;
+    }
+    if ((s = keysym2scancode_map(&k->shift_altgr, keysym))) {
+       *shift = 1;
+       *altgr = 1;
+       return s;
+    }
    return 0;
-}
+}
-static inline int keysym_is_shift(void *kbd_layout, int keysym)
+static int keycode_is_keypad(void *kbd_layout, int keycode)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
-
-    for (kr = k->shift_range; kr; kr = kr->next)
-        if (keysym >= kr->start && keysym <= kr->end)
-            return 1;
+    if (keycode >= 0 && keycode < MAX_SCANCODE)
+       return !!(k->flags[keycode] & KEY_KEYPAD);
    return 0;
}

-static inline int keycode_is_shiftable(void *kbd_layout, int keycode)
+static int keysym_is_numlock(void *kbd_layout, int keysym)
+{
+    kbd_layout_t *k = kbd_layout;
+    return (keysym2scancode_map(&k->numlock, keysym) != 0);
+}
+
+static int keysym_is_shift(void *kbd_layout, int keysym)
{
    kbd_layout_t *k = kbd_layout;
-    struct key_range *kr;
+    return (keysym2scancode_map(&k->shift, keysym) != 0);
+}

-    for (kr = k->localstate_range; kr; kr = kr->next)
-       if (keycode >= kr->start && keycode <= kr->end)
-           return 0;
-    return 1;
+static int keycode_is_shiftable(void *kbd_layout, int keycode)
+{
+    kbd_layout_t *k = kbd_layout;
+    if (keycode >= 0 || keycode < MAX_SCANCODE)
+       return !(k->flags[keycode] & KEY_LOCALSTATE);
+    return 0;
}
diff --git a/vnc.c b/vnc.c
index 01e22e5..e19860c 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1272,14 +1272,22 @@ static void pointer_event(VncState *vs, int 
button_mask, int x, int y)
    check_pointer_type_change(vs, kbd_mouse_is_absolute());
}

+static void put_keycode(int keycode, int down)
+{
+    if (keycode & 0x80)
+       kbd_put_keycode(0xe0);
+    if (down)
+       kbd_put_keycode(keycode & 0x7f);
+    else
+       kbd_put_keycode(keycode | 0x80);
+}
+
static void reset_keys(VncState *vs)
{
    int i;
    for(i = 0; i < 256; i++) {
        if (vs->modifiers_state[i]) {
-            if (i & 0x80)
-                kbd_put_keycode(0xe0);
-            kbd_put_keycode(i | 0x80);
+           put_keycode(i, 0);
            vs->modifiers_state[i] = 0;
        }
    }
@@ -1287,69 +1295,34 @@ static void reset_keys(VncState *vs)

static void press_key(VncState *vs, int keysym)
{
-    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) & 0x7f);
-    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
+    put_keycode(keysym2scancode(vs->kbd_layout, keysym), 1);
+    put_keycode(keysym2scancode(vs->kbd_layout, keysym), 0);
}

-static void press_key_shift_down(VncState *vs, int down, int keycode)
+static void twiddle_modifiers(VncState *vs, int down, int shift, int altgr)
{
-    if (down)
-        kbd_put_keycode(0x2a & 0x7f);
-
-    if (keycode & 0x80)
-        kbd_put_keycode(0xe0);
-    if (down)
-        kbd_put_keycode(keycode & 0x7f);
-    else
-        kbd_put_keycode(keycode | 0x80);
-
-    if (!down)
-        kbd_put_keycode(0x2a | 0x80);
-}
-
-static void press_key_shift_up(VncState *vs, int down, int keycode)
-{
-    if (down) {
-        if (vs->modifiers_state[0x2a])
-            kbd_put_keycode(0x2a | 0x80);
- if (vs->modifiers_state[0x36]) - kbd_put_keycode(0x36 | 0x80);
-    }
-
-    if (keycode & 0x80)
-        kbd_put_keycode(0xe0);
-    if (down)
-        kbd_put_keycode(keycode & 0x7f);
-    else
-        kbd_put_keycode(keycode | 0x80);
-
-    if (!down) {
-        if (vs->modifiers_state[0x2a])
-            kbd_put_keycode(0x2a & 0x7f);
- if (vs->modifiers_state[0x36]) - kbd_put_keycode(0x36 & 0x7f);
-    }
+    if (shift && !(vs->modifiers_state[0x2a] || vs->modifiers_state[0x36]))
+       put_keycode(0x2a, down);
+    if (!shift && vs->modifiers_state[0x2a])
+       put_keycode(0x2a, !down);
+    if (!shift && vs->modifiers_state[0x36])
+       put_keycode(0x36, !down);
+    if (altgr && !vs->modifiers_state[0xb8])
+       put_keycode(0xb8, down);
+    if (!altgr && vs->modifiers_state[0xb8])
+       put_keycode(0xb8, !down);
}

static void do_key_event(VncState *vs, int down, uint32_t sym)
{
    int keycode;
-    int shift_keys = 0;
+    int altgr = 0;
    int shift = 0;
    int keypad = 0;

-    if (is_graphic_console()) {
-        if (sym >= 'A' && sym <= 'Z') {
-            sym = sym - 'A' + 'a';
-            shift = 1;
-        }
-        else {
-            shift = keysym_is_shift(vs->kbd_layout, sym & 0xFFFF);
-        }
-    }
-    shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
-
-    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
+    shift = (vs->modifiers_state[0x2a] || vs->modifiers_state[0x36]);
+    altgr = vs->modifiers_state[0xb8];
+    keycode = keysym2scancode1(vs->kbd_layout, sym & 0xFFFF, &shift, &altgr);
    if (keycode == 0) {
        fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
        return;
@@ -1362,17 +1335,9 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
    case 0x1d:                          /* Left CTRL */
    case 0x9d:                          /* Right CTRL */
    case 0x38:                          /* Left ALT */
-    case 0xb8:                          /* Right ALT */
-        if (keycode & 0x80)
-            kbd_put_keycode(0xe0);
-        if (down) {
-            vs->modifiers_state[keycode] = 1;
-            kbd_put_keycode(keycode & 0x7f);
-        }
-        else {
-            vs->modifiers_state[keycode] = 0;
-            kbd_put_keycode(keycode | 0x80);
-        }
+    case 0xb8:                          /* Right ALT aka AltGr */
+       vs->modifiers_state[keycode] = down;
+       put_keycode(keycode, down);
        return;
case 0x02 ... 0x0a: /* '1' to '9' keys */ if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
@@ -1383,13 +1348,15 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
        }
        break;
    case 0x3a:                  /* CapsLock */
+       if (is_graphic_console())
+           return;
    case 0x45:                  /* NumLock */
        if (down) {
-            kbd_put_keycode(keycode & 0x7f);
+            put_keycode(keycode, 1);
        }
        else {  
            vs->modifiers_state[keycode] ^= 1;
-            kbd_put_keycode(keycode | 0x80);
+            put_keycode(keycode, 0);
        }
        return;
    }
@@ -1398,7 +1365,10 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
    if (keypad) {
        /* If the numlock state needs to change then simulate an additional
           keypress before sending this one.  This will happen if the user
-           toggles numlock away from the VNC window.
+           toggles numlock away from the VNC window.  This isn't perfect as
+          pressing the shift key will typically and temporarily have the
+          effect of inverting the numlock setting: the shift key will be
+          effectively cancelled out.
        */
        if (keysym_is_numlock(vs->kbd_layout, sym & 0xFFFF)) {
            if (!vs->modifiers_state[0x45]) {
@@ -1417,22 +1387,14 @@ static void do_key_event(VncState *vs, int down, 
uint32_t sym)
        /*  If the shift state needs to change then simulate an additional
            keypress before sending this one. Ignore for non shiftable keys.
        */
-        if (shift && !shift_keys) {
-            press_key_shift_down(vs, down, keycode);
-            return;
-        }
-        else if (!shift && shift_keys && !keypad &&
-                 keycode_is_shiftable(vs->kbd_layout, keycode)) {
-            press_key_shift_up(vs, down, keycode);
-            return;
-        }
-
-        if (keycode & 0x80)
-            kbd_put_keycode(0xe0);
-        if (down)
-            kbd_put_keycode(keycode & 0x7f);
-        else
-            kbd_put_keycode(keycode | 0x80);
+       if (keycode_is_shiftable(vs->kbd_layout, keycode) && !keypad) {
+           if (down)
+               twiddle_modifiers(vs, down, shift, altgr);
+           put_keycode(keycode, down);
+           if (!down)
+               twiddle_modifiers(vs, down, shift, altgr);
+       } else
+           put_keycode(keycode, down);
    } else {
        /* QEMU console emulation */
        if (down) {
@@ -2528,7 +2490,7 @@ void vnc_display_init(DisplayState *ds)
    vs->kbd_layout = init_keyboard_layout(keyboard_layout);
    if (!vs->kbd_layout)
        exit(1);
-    vs->modifiers_state[0x45] = 1; /* NumLock on - on boot */
+    vs->modifiers_state[0x45] = 0; /* NumLock off - on boot */

    vs->ds->data = NULL;
    vs->ds->dpy_update = vnc_dpy_update;



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel