ia64/xen-unstable

changeset 12789:c7f4a89eb054

Fix numpad handling in QEMU's VNC server. The keymaps that we have include
information on which keys change depending upon the numlock setting, but
this isn't being used. By forcing numlock on and off as necessary, when
receiving these keysyms through the VNC connection, we ensure that the
server's numlock status is the same as the client's.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Mon Dec 04 17:52:33 2006 +0000 (2006-12-04)
parents 565cd8f32c70
children 897bb9b7ed06
files tools/ioemu/keymaps.c tools/ioemu/vnc.c tools/ioemu/vnc_keysym.h
line diff
     1.1 --- a/tools/ioemu/keymaps.c	Mon Dec 04 13:57:18 2006 +0000
     1.2 +++ b/tools/ioemu/keymaps.c	Mon Dec 04 17:52:33 2006 +0000
     1.3 @@ -36,8 +36,10 @@ static int get_keysym(const char *name)
     1.4  #define MAX_EXTRA_COUNT 256
     1.5  typedef struct {
     1.6      uint16_t keysym2keycode[MAX_NORMAL_KEYCODE];
     1.7 +    int keysym2numlock[MAX_NORMAL_KEYCODE];
     1.8      struct {
     1.9  	int keysym;
    1.10 +	int numlock;
    1.11  	uint16_t keycode;
    1.12      } keysym2keycode_extra[MAX_EXTRA_COUNT];
    1.13      int extra_count;
    1.14 @@ -50,6 +52,8 @@ static kbd_layout_t *parse_keyboard_layo
    1.15      char file_name[1024];
    1.16      char line[1024];
    1.17      int len;
    1.18 +    int *keycode2numlock;
    1.19 +    int i;
    1.20  
    1.21      snprintf(file_name, sizeof(file_name),
    1.22               "%s/keymaps/%s", bios_dir, language);
    1.23 @@ -63,6 +67,15 @@ static kbd_layout_t *parse_keyboard_layo
    1.24  		"Could not read keymap file: '%s'\n", file_name);
    1.25  	return 0;
    1.26      }
    1.27 +
    1.28 +    /* Allocate a temporary map tracking which keycodes change when numlock is
    1.29 +       set.  Keycodes are 16 bit, so 65536 is safe. */
    1.30 +    keycode2numlock = malloc(65536 * sizeof(int));
    1.31 +    if (!keycode2numlock) {
    1.32 +        perror("Could not read keymap file");
    1.33 +	return 0;
    1.34 +    }
    1.35 +
    1.36      for(;;) {
    1.37  	if (fgets(line, 1024, f) == NULL)
    1.38              break;
    1.39 @@ -86,13 +99,19 @@ static kbd_layout_t *parse_keyboard_layo
    1.40  		if (keysym == 0) {
    1.41                      //		    fprintf(stderr, "Warning: unknown keysym %s\n", line);
    1.42  		} else {
    1.43 -		    const char *rest = end_of_keysym + 1;
    1.44 -		    int keycode = strtol(rest, NULL, 0);
    1.45 +		    char *rest = end_of_keysym + 1;
    1.46 +		    int keycode = strtol(rest, &rest, 0);
    1.47 +		    int numlock = (rest != NULL &&
    1.48 +		                   strstr(rest, "numlock") != NULL);
    1.49 +
    1.50 +                    keycode2numlock[keycode] = numlock;
    1.51 +
    1.52  		    /* if(keycode&0x80)
    1.53  		       keycode=(keycode<<8)^0x80e0; */
    1.54  		    if (keysym < MAX_NORMAL_KEYCODE) {
    1.55  			//fprintf(stderr,"Setting keysym %s (%d) to %d\n",line,keysym,keycode);
    1.56  			k->keysym2keycode[keysym] = keycode;
    1.57 +			k->keysym2numlock[keysym] = numlock;
    1.58  		    } else {
    1.59  			if (k->extra_count >= MAX_EXTRA_COUNT) {
    1.60  			    fprintf(stderr,
    1.61 @@ -107,6 +126,8 @@ static kbd_layout_t *parse_keyboard_layo
    1.62  				keysym = keysym;
    1.63  			    k->keysym2keycode_extra[k->extra_count].
    1.64  				keycode = keycode;
    1.65 +			    k->keysym2keycode_extra[k->extra_count].
    1.66 +				numlock = numlock;
    1.67  			    k->extra_count++;
    1.68  			}
    1.69  		    }
    1.70 @@ -115,6 +136,22 @@ static kbd_layout_t *parse_keyboard_layo
    1.71  	}
    1.72      }
    1.73      fclose(f);
    1.74 +
    1.75 +    for (int i = 0; i < MAX_NORMAL_KEYCODE; i++) {
    1.76 +        if (k->keysym2numlock[i] != 1) {
    1.77 +            k->keysym2numlock[i] = -keycode2numlock[k->keysym2keycode[i]];
    1.78 +        }
    1.79 +    }
    1.80 +
    1.81 +    for (int i = 0; i < k->extra_count; i++) {
    1.82 +        if (k->keysym2keycode_extra[i].numlock != 1) {
    1.83 +            k->keysym2keycode_extra[i].numlock =
    1.84 +                -keycode2numlock[k->keysym2keycode_extra[i].keycode];
    1.85 +        }
    1.86 +    }
    1.87 +
    1.88 +    free(keycode2numlock);
    1.89 +
    1.90      return k;
    1.91  }
    1.92  
    1.93 @@ -143,3 +180,25 @@ static int keysym2scancode(void *kbd_lay
    1.94      }
    1.95      return 0;
    1.96  }
    1.97 +
    1.98 +/**
    1.99 + * Returns 1 if the given keysym requires numlock to be pressed, -1 if it
   1.100 + * requires it to be cleared, and 0 otherwise.
   1.101 + */
   1.102 +static int keysym2numlock(void *kbd_layout, int keysym)
   1.103 +{
   1.104 +    kbd_layout_t *k = kbd_layout;
   1.105 +    if (keysym < MAX_NORMAL_KEYCODE) {
   1.106 +	return k->keysym2numlock[keysym];
   1.107 +    } else {
   1.108 +	int i;
   1.109 +#ifdef XK_ISO_Left_Tab
   1.110 +	if (keysym == XK_ISO_Left_Tab)
   1.111 +	    keysym = XK_Tab;
   1.112 +#endif
   1.113 +	for (i = 0; i < k->extra_count; i++)
   1.114 +	    if (k->keysym2keycode_extra[i].keysym == keysym)
   1.115 +		return k->keysym2keycode_extra[i].numlock;
   1.116 +    }
   1.117 +    return 0;
   1.118 +}
     2.1 --- a/tools/ioemu/vnc.c	Mon Dec 04 13:57:18 2006 +0000
     2.2 +++ b/tools/ioemu/vnc.c	Mon Dec 04 17:52:33 2006 +0000
     2.3 @@ -115,6 +115,7 @@ struct VncState
     2.4  
     2.5      int ctl_keys;               /* Ctrl+Alt starts calibration */
     2.6      int shift_keys;             /* Shift / CapsLock keys */
     2.7 +    int numlock;
     2.8  };
     2.9  
    2.10  #define DIRTY_PIXEL_BITS 64
    2.11 @@ -854,14 +855,40 @@ static void pointer_event(VncState *vs, 
    2.12      }
    2.13  }
    2.14  
    2.15 +static void press_key(VncState *vs, int keycode)
    2.16 +{
    2.17 +    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keycode) & 0x7f);
    2.18 +    kbd_put_keycode(keysym2scancode(vs->kbd_layout, keycode) | 0x80);
    2.19 +}
    2.20 +
    2.21  static void do_key_event(VncState *vs, int down, uint32_t sym)
    2.22  {
    2.23      sym &= 0xFFFF;
    2.24  
    2.25      if (is_graphic_console()) {
    2.26  	int keycode;
    2.27 +	int numlock;
    2.28  
    2.29  	keycode = keysym2scancode(vs->kbd_layout, sym);
    2.30 +	numlock = keysym2numlock(vs->kbd_layout, sym);
    2.31 +
    2.32 +        /* If the numlock state needs to change then simulate an additional
    2.33 +           keypress before sending this one.  This will happen if the user
    2.34 +           toggles numlock away from the VNC window.
    2.35 +        */
    2.36 +	if (numlock == 1) {
    2.37 +	    if (!vs->numlock) {
    2.38 +		vs->numlock = 1;
    2.39 +		press_key(vs, XK_Num_Lock);
    2.40 +	    }
    2.41 +	}
    2.42 +	else if (numlock == -1) {
    2.43 +	    if (vs->numlock) {
    2.44 +		vs->numlock = 0;
    2.45 +		press_key(vs, XK_Num_Lock);
    2.46 +	    }
    2.47 +        }
    2.48 +
    2.49  	if (keycode & 0x80)
    2.50  	    kbd_put_keycode(0xe0);
    2.51  	if (down)
    2.52 @@ -932,6 +959,10 @@ static void do_key_event(VncState *vs, i
    2.53  	    vs->shift_keys ^= 2;
    2.54  	    break;
    2.55  
    2.56 +	case XK_Num_Lock:
    2.57 +	    vs->numlock = !vs->numlock;
    2.58 +	    break;
    2.59 +
    2.60  	case XK_1 ... XK_9:
    2.61  	    if ((vs->ctl_keys & 3) != 3)
    2.62  		break;
    2.63 @@ -1355,6 +1386,7 @@ int vnc_display_init(DisplayState *ds, i
    2.64      vs->lsock = -1;
    2.65      vs->csock = -1;
    2.66      vs->depth = 4;
    2.67 +    vs->numlock = 0;
    2.68  
    2.69      vs->ds = ds;
    2.70  
     3.1 --- a/tools/ioemu/vnc_keysym.h	Mon Dec 04 13:57:18 2006 +0000
     3.2 +++ b/tools/ioemu/vnc_keysym.h	Mon Dec 04 17:52:33 2006 +0000
     3.3 @@ -231,6 +231,19 @@ static name2keysym_t name2keysym[]={
     3.4  {"Home", 0xff50},      /* XK_Home */
     3.5  {"End", 0xff57},       /* XK_End */
     3.6  {"Scroll_Lock", 0xff14}, /* XK_Scroll_Lock */
     3.7 +{"KP_Home", 0xff95},
     3.8 +{"KP_Left", 0xff96},
     3.9 +{"KP_Up", 0xff97},
    3.10 +{"KP_Right", 0xff98},
    3.11 +{"KP_Down", 0xff99},
    3.12 +{"KP_Prior", 0xff9a},
    3.13 +{"KP_Page_Up", 0xff9a},
    3.14 +{"KP_Next", 0xff9b},
    3.15 +{"KP_Page_Down", 0xff9b},
    3.16 +{"KP_End", 0xff9c},
    3.17 +{"KP_Begin", 0xff9d},
    3.18 +{"KP_Insert", 0xff9e},
    3.19 +{"KP_Delete", 0xff9f},
    3.20  {"F1", 0xffbe},        /* XK_F1 */
    3.21  {"F2", 0xffbf},        /* XK_F2 */
    3.22  {"F3", 0xffc0},        /* XK_F3 */
    3.23 @@ -258,6 +271,7 @@ static name2keysym_t name2keysym[]={
    3.24  {"KP_8", 0xffb8},      /* XK_KP_8 */
    3.25  {"KP_9", 0xffb9},      /* XK_KP_9 */
    3.26  {"KP_Add", 0xffab},    /* XK_KP_Add */
    3.27 +{"KP_Separator", 0xffac},/* XK_KP_Separator */
    3.28  {"KP_Decimal", 0xffae},  /* XK_KP_Decimal */
    3.29  {"KP_Divide", 0xffaf},   /* XK_KP_Divide */
    3.30  {"KP_Enter", 0xff8d},    /* XK_KP_Enter */