ia64/xen-unstable

changeset 15642:7bdc9f6407d3

[PVFB] Fix shift key for graphical vnc display

There is a problem in the input of the key in the VNC connection on
the PV domain. When client's keyboard is not the same as the kind of
the keyboard of PVFB and GuestOS, it is not possible to input it correctly.

This patch handled the state of shift from the set keymap. When
client's keyboard is not same as the kind of PVFB/GuestOS, it is
possible to input it correctly. It was confirmed to input it correctly
mutually with this patch between en-us and ja.

Signed-off-by: Takanori Kasai <kasai.takanori@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Mon Jul 23 10:03:17 2007 +0100 (2007-07-23)
parents c64f2a0dc2d7
children 531b8ccda973
files tools/xenfb/vncfb.c
line diff
     1.1 --- a/tools/xenfb/vncfb.c	Mon Jul 23 10:02:37 2007 +0100
     1.2 +++ b/tools/xenfb/vncfb.c	Mon Jul 23 10:03:17 2007 +0100
     1.3 @@ -55,12 +55,47 @@ static unsigned char atkbd_unxlate_table
     1.4  unsigned char keycode_table[512];
     1.5  
     1.6  static void *kbd_layout;
     1.7 +uint8_t modifiers_state[256];
     1.8  
     1.9  static int btnmap[] = {
    1.10  	BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
    1.11  	BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK
    1.12  };
    1.13  
    1.14 +static void press_key_shift_down(struct xenfb* xenfb, int down, int scancode)
    1.15 +{
    1.16 +	if (down)
    1.17 +		xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
    1.18 +
    1.19 +	if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
    1.20 +		fprintf(stderr, "Key %d %s lost (%s)\n",
    1.21 +			scancode, "down", strerror(errno));
    1.22 +
    1.23 +	if (!down)
    1.24 +		xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
    1.25 +}
    1.26 +
    1.27 +static void press_key_shift_up(struct xenfb* xenfb, int down, int scancode)
    1.28 +{
    1.29 +	if (down) {
    1.30 +		if (modifiers_state[0x2a])
    1.31 +			xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
    1.32 +		if (modifiers_state[0x36])
    1.33 +			xenfb_send_key(xenfb, 0, keycode_table[0x36]);
    1.34 +	}
    1.35 +
    1.36 +	if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
    1.37 +		fprintf(stderr, "Key %d %s lost (%s)\n",
    1.38 +			scancode, "down", strerror(errno));
    1.39 +
    1.40 +	if (!down) {
    1.41 +		if (modifiers_state[0x2a])
    1.42 +			xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
    1.43 +		if (modifiers_state[0x36])
    1.44 +			xenfb_send_key(xenfb, 1, keycode_table[0x36]);
    1.45 +	}
    1.46 +}
    1.47 +
    1.48  static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
    1.49  {
    1.50  	/*
    1.51 @@ -75,14 +110,75 @@ static void on_kbd_event(rfbBool down, r
    1.52  	rfbScreenInfoPtr server = cl->screen;
    1.53  	struct xenfb *xenfb = server->screenData;
    1.54  	int scancode;
    1.55 +	int shift = 0;
    1.56 +	int shift_keys = 0;
    1.57  
    1.58 -	if (keycode >= 'A' && keycode <= 'Z')
    1.59 +	if (keycode >= 'A' && keycode <= 'Z') {
    1.60  		keycode += 'a' - 'A';
    1.61 +		shift = 1;
    1.62 +	}
    1.63 +	else {
    1.64 +		shift = keysymIsShift(kbd_layout, keycode);
    1.65 +	}
    1.66 +	shift_keys = modifiers_state[0x2a] | modifiers_state[0x36];	
    1.67  
    1.68 -	scancode = keycode_table[keysym2scancode(kbd_layout, keycode)];
    1.69 +	scancode = keysym2scancode(kbd_layout, keycode);
    1.70  	if (scancode == 0)
    1.71  		return;
    1.72 -	if (xenfb_send_key(xenfb, down, scancode) < 0)
    1.73 +
    1.74 +	switch(scancode) {
    1.75 +	case 0x2a:			/* Left Shift */
    1.76 +	case 0x36:			/* Right Shift */
    1.77 +	case 0x1d:			/* Left CTRL */
    1.78 +	case 0x9d:			/* Right CTRL */
    1.79 +	case 0x38:			/* Left ALT */
    1.80 +	case 0xb8:			/* Right ALT */
    1.81 +		if (down)
    1.82 +			modifiers_state[scancode] = 1;
    1.83 +		else
    1.84 +			modifiers_state[scancode] = 0;
    1.85 +		xenfb_send_key(xenfb, down, keycode_table[scancode]); 
    1.86 +		return;
    1.87 +	case 0x45:			/* NumLock */
    1.88 +		if (!down)
    1.89 +			modifiers_state[scancode] ^= 1;
    1.90 +		xenfb_send_key(xenfb, down, keycode_table[scancode]);
    1.91 +		return;
    1.92 +	}
    1.93 +
    1.94 +	if (keycodeIsKeypad(kbd_layout, scancode)) {
    1.95 +	/* If the numlock state needs to change then simulate an additional
    1.96 +	   keypress before sending this one.  This will happen if the user
    1.97 +	   toggles numlock away from the VNC window.
    1.98 +	*/
    1.99 +		if (keysymIsNumlock(kbd_layout, keycode)) {
   1.100 +			if (!modifiers_state[0x45]) {
   1.101 +				modifiers_state[0x45] = 1;
   1.102 +				xenfb_send_key(xenfb, 1, keycode_table[0x45]);
   1.103 +				xenfb_send_key(xenfb, 0, keycode_table[0x45]);
   1.104 +			}
   1.105 +		} else {
   1.106 +			if (modifiers_state[0x45]) {
   1.107 +				modifiers_state[0x45] = 0;
   1.108 +				xenfb_send_key(xenfb, 1, keycode_table[0x45]);
   1.109 +				xenfb_send_key(xenfb, 0, keycode_table[0x45]);
   1.110 +			}
   1.111 +		}
   1.112 +	}
   1.113 +
   1.114 +	/* If the shift state needs to change then simulate an additional
   1.115 +	   keypress before sending this one.
   1.116 +	*/
   1.117 +	if (shift && !shift_keys) {
   1.118 +		press_key_shift_down(xenfb, down, scancode);
   1.119 +		return;
   1.120 +	}
   1.121 +	else if (!shift && shift_keys) {
   1.122 +		press_key_shift_up(xenfb, down, scancode);
   1.123 +		return;
   1.124 +	}
   1.125 +
   1.126 +	if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
   1.127  		fprintf(stderr, "Key %d %s lost (%s)\n",
   1.128  			scancode, down ? "down" : "up",
   1.129  			strerror(errno));
   1.130 @@ -314,6 +410,10 @@ int main(int argc, char **argv)
   1.131  			atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
   1.132  	}
   1.133  
   1.134 +	for (i = 0; i < 256; i++ ) {
   1.135 +		modifiers_state[i] = 0;
   1.136 +	}
   1.137 +
   1.138  	fake_argv[2] = portstr;
   1.139  
   1.140          if (title != NULL)