SHA256
1
0
forked from pool/xen
xen/fix-vncfb-shift-key.patch

143 lines
3.9 KiB
Diff

Index: xen-3.1-testing/tools/xenfb/vncfb.c
===================================================================
--- xen-3.1-testing.orig/tools/xenfb/vncfb.c 2007-05-17 09:51:10.000000000 -0600
+++ xen-3.1-testing/tools/xenfb/vncfb.c 2007-09-14 11:59:57.000000000 -0600
@@ -55,12 +55,47 @@
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 @@
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 @@
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)