aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-07-23 10:03:17 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-07-23 10:03:17 +0100
commit5465cafcd9d36ab18cc2d66638e50a93fc194e7a (patch)
tree6cc9f3c0c267bcb8d78333c671feb6caa62ce396 /tools
parentc5b151445d21dcbc0bc80b70e4bdfcde789ee3ca (diff)
downloadxen-5465cafcd9d36ab18cc2d66638e50a93fc194e7a.tar.gz
xen-5465cafcd9d36ab18cc2d66638e50a93fc194e7a.tar.bz2
xen-5465cafcd9d36ab18cc2d66638e50a93fc194e7a.zip
[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>
Diffstat (limited to 'tools')
-rw-r--r--tools/xenfb/vncfb.c106
1 files changed, 103 insertions, 3 deletions
diff --git a/tools/xenfb/vncfb.c b/tools/xenfb/vncfb.c
index 1ae06809fc..ba598e5b00 100644
--- a/tools/xenfb/vncfb.c
+++ b/tools/xenfb/vncfb.c
@@ -55,12 +55,47 @@ static unsigned char atkbd_unxlate_table[128] = {
unsigned char keycode_table[512];
static void *kbd_layout;
+uint8_t modifiers_state[256];
static int btnmap[] = {
BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK
};
+static void press_key_shift_down(struct xenfb* xenfb, int down, int scancode)
+{
+ if (down)
+ xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
+
+ if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
+ fprintf(stderr, "Key %d %s lost (%s)\n",
+ scancode, "down", strerror(errno));
+
+ if (!down)
+ xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
+}
+
+static void press_key_shift_up(struct xenfb* xenfb, int down, int scancode)
+{
+ if (down) {
+ if (modifiers_state[0x2a])
+ xenfb_send_key(xenfb, 0, keycode_table[0x2a]);
+ if (modifiers_state[0x36])
+ xenfb_send_key(xenfb, 0, keycode_table[0x36]);
+ }
+
+ if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
+ fprintf(stderr, "Key %d %s lost (%s)\n",
+ scancode, "down", strerror(errno));
+
+ if (!down) {
+ if (modifiers_state[0x2a])
+ xenfb_send_key(xenfb, 1, keycode_table[0x2a]);
+ if (modifiers_state[0x36])
+ xenfb_send_key(xenfb, 1, keycode_table[0x36]);
+ }
+}
+
static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
{
/*
@@ -75,14 +110,75 @@ static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
rfbScreenInfoPtr server = cl->screen;
struct xenfb *xenfb = server->screenData;
int scancode;
+ int shift = 0;
+ int shift_keys = 0;
- if (keycode >= 'A' && keycode <= 'Z')
+ if (keycode >= 'A' && keycode <= 'Z') {
keycode += 'a' - 'A';
+ shift = 1;
+ }
+ else {
+ shift = keysymIsShift(kbd_layout, keycode);
+ }
+ shift_keys = modifiers_state[0x2a] | modifiers_state[0x36];
- scancode = keycode_table[keysym2scancode(kbd_layout, keycode)];
+ scancode = keysym2scancode(kbd_layout, keycode);
if (scancode == 0)
return;
- if (xenfb_send_key(xenfb, down, scancode) < 0)
+
+ switch(scancode) {
+ case 0x2a: /* Left Shift */
+ case 0x36: /* Right Shift */
+ case 0x1d: /* Left CTRL */
+ case 0x9d: /* Right CTRL */
+ case 0x38: /* Left ALT */
+ case 0xb8: /* Right ALT */
+ if (down)
+ modifiers_state[scancode] = 1;
+ else
+ modifiers_state[scancode] = 0;
+ xenfb_send_key(xenfb, down, keycode_table[scancode]);
+ return;
+ case 0x45: /* NumLock */
+ if (!down)
+ modifiers_state[scancode] ^= 1;
+ xenfb_send_key(xenfb, down, keycode_table[scancode]);
+ return;
+ }
+
+ if (keycodeIsKeypad(kbd_layout, scancode)) {
+ /* 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.
+ */
+ if (keysymIsNumlock(kbd_layout, keycode)) {
+ if (!modifiers_state[0x45]) {
+ modifiers_state[0x45] = 1;
+ xenfb_send_key(xenfb, 1, keycode_table[0x45]);
+ xenfb_send_key(xenfb, 0, keycode_table[0x45]);
+ }
+ } else {
+ if (modifiers_state[0x45]) {
+ modifiers_state[0x45] = 0;
+ xenfb_send_key(xenfb, 1, keycode_table[0x45]);
+ xenfb_send_key(xenfb, 0, keycode_table[0x45]);
+ }
+ }
+ }
+
+ /* If the shift state needs to change then simulate an additional
+ keypress before sending this one.
+ */
+ if (shift && !shift_keys) {
+ press_key_shift_down(xenfb, down, scancode);
+ return;
+ }
+ else if (!shift && shift_keys) {
+ press_key_shift_up(xenfb, down, scancode);
+ return;
+ }
+
+ if (xenfb_send_key(xenfb, down, keycode_table[scancode]) < 0)
fprintf(stderr, "Key %d %s lost (%s)\n",
scancode, down ? "down" : "up",
strerror(errno));
@@ -314,6 +410,10 @@ int main(int argc, char **argv)
atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
}
+ for (i = 0; i < 256; i++ ) {
+ modifiers_state[i] = 0;
+ }
+
fake_argv[2] = portstr;
if (title != NULL)