[gtk-vnc-devel] [RFT] Experiment scancode VNC extension



The following two patches implement a very rough interface for passing raw scan codes directly from gtk-vnc to QEMU. This is not at all ready for committing as it doesn't properly negotiate support or anything. I don't own a non-US keyboard though so I wanted some basic validation that this addresses the problem before moving forward.

With these two patches applied to qemu (or KVM) and gtk-vnc, you should be able to send key presses from a non-US keyboard to a guest with the same keymap as the host without specifying a '-k XX' option to QEMU.

Please let me know if either of these patches are helpful.

Regards,

Anthony Liguori
diff -r 55e935408794 src/gvnc.c
--- a/src/gvnc.c	Sat Jan 12 16:04:53 2008 -0600
+++ b/src/gvnc.c	Sat Jan 12 16:42:57 2008 -0600
@@ -887,6 +887,17 @@ gboolean gvnc_key_event(struct gvnc *gvn
 	gvnc_buffered_write_u8(gvnc, down_flag);
 	gvnc_buffered_write(gvnc, pad, 2);
 	gvnc_buffered_write_u32(gvnc, key);
+	gvnc_buffered_flush(gvnc);
+	return !gvnc_has_error(gvnc);
+}
+
+gboolean gvnc_key_event_scancode(struct gvnc *gvnc, uint8_t down_flag,
+				 uint16_t scancode)
+{
+	gvnc_buffered_write_u8(gvnc, 255);
+	gvnc_buffered_write_u8(gvnc, 0);
+	gvnc_buffered_write_u16(gvnc, down_flag);
+	gvnc_buffered_write_u16(gvnc, scancode);
 	gvnc_buffered_flush(gvnc);
 	return !gvnc_has_error(gvnc);
 }
diff -r 55e935408794 src/gvnc.h
--- a/src/gvnc.h	Sat Jan 12 16:04:53 2008 -0600
+++ b/src/gvnc.h	Sat Jan 12 16:42:57 2008 -0600
@@ -150,6 +150,8 @@ gboolean gvnc_pointer_event(struct gvnc 
 			    uint16_t x, uint16_t y);
 
 gboolean gvnc_key_event(struct gvnc *gvnc, uint8_t down_flag, uint32_t key);
+gboolean gvnc_key_event_scancode(struct gvnc *gvnc, uint8_t down_flag,
+				 uint16_t scancode);
 
 gboolean gvnc_framebuffer_update_request(struct gvnc *gvnc,
 					 uint8_t incremental,
diff -r 55e935408794 src/vncdisplay.c
--- a/src/vncdisplay.c	Sat Jan 12 16:04:53 2008 -0600
+++ b/src/vncdisplay.c	Sat Jan 12 16:42:57 2008 -0600
@@ -419,7 +419,7 @@ static gboolean key_event(GtkWidget *wid
 			if (priv->down_keyval[i] == 0) {
 				priv->down_keyval[i] = keyval;
 				/* Send the actual key event we're dealing with */
-				gvnc_key_event(priv->gvnc, 1, keyval);
+				gvnc_key_event_scancode(priv->gvnc, 1, key->hardware_keycode);
 				break;
 			} else if (priv->down_keyval[i] == keyval) {
 				/* Got an press when we're already pressed ! Why ... ?
@@ -431,9 +431,9 @@ static gboolean key_event(GtkWidget *wid
 				 * them into a sensible stream of press+release pairs
 				 */
 				/* Fake an up event for the previous down event */
-				gvnc_key_event(priv->gvnc, 0, keyval);
+				gvnc_key_event_scancode(priv->gvnc, 0, key->hardware_keycode);
 				/* Now send our actual ldown event */
-				gvnc_key_event(priv->gvnc, 1, keyval);
+				gvnc_key_event_scancode(priv->gvnc, 1, key->hardware_keycode);
 			}
 		}
 	} else {
@@ -443,7 +443,7 @@ static gboolean key_event(GtkWidget *wid
 			if (priv->down_keyval[i] == keyval) {
 				priv->down_keyval[i] = 0;
 				/* ..send the key releae event we're dealing with */
-				gvnc_key_event(priv->gvnc, 0, keyval);
+				gvnc_key_event_scancode(priv->gvnc, 0, key->hardware_keycode);
 				break;
 			}
 		}
? .pc
? dev.img
? extboot
? patches
Index: vnc.c
===================================================================
RCS file: /sources/qemu/qemu/vnc.c,v
retrieving revision 1.31
diff -u -r1.31 vnc.c
--- vnc.c	16 Dec 2007 03:02:08 -0000	1.31
+++ vnc.c	12 Jan 2008 22:42:41 -0000
@@ -927,12 +927,8 @@
     kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
 }
 
-static void do_key_event(VncState *vs, int down, uint32_t sym)
+static void do_key_event(VncState *vs, int down, int keycode, int sym)
 {
-    int keycode;
-
-    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
-
     /* QEMU console switch */
     switch(keycode) {
     case 0x2a:                          /* Left Shift */
@@ -960,7 +956,7 @@
         break;
     }
 
-    if (keycode_is_keypad(vs->kbd_layout, keycode)) {
+    if (sym != -1 && keycode_is_keypad(vs->kbd_layout, keycode)) {
         /* 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.
@@ -1033,9 +1029,31 @@
 
 static void key_event(VncState *vs, int down, uint32_t sym)
 {
+    int keycode;
+
     if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
 	sym = sym - 'A' + 'a';
-    do_key_event(vs, down, sym);
+
+    keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
+    do_key_event(vs, down, keycode, sym);
+}
+
+static void key_event_scancode(VncState *vs, int down, uint16_t scancode)
+{
+    int keycode;
+
+    keycode = scancode;
+    if (keycode < 9)
+	keycode = 0;
+    else if (keycode < 97)
+	keycode -= 8;
+    else if (keycode < 212)
+	keycode = _translate_keycode(keycode - 97);
+    else
+	keycode = 0;
+
+    do_key_event(vs, down, keycode, -1);
+
 }
 
 static void framebuffer_update_request(VncState *vs, int incremental,
@@ -1245,6 +1263,23 @@
 
 	client_cut_text(vs, read_u32(data, 4), data + 8);
 	break;
+    case 255:
+	if (len == 1)
+	    return 2;
+
+	switch (read_u8(data, 1)) {
+	case 0:
+	    if (len == 2)
+		return 6;
+
+	    key_event_scancode(vs, read_u16(data, 2), read_u16(data, 4));
+	    break;
+	default:
+	    printf("Msg: %d\n", read_u16(data, 0));
+	    vnc_client_error(vs);
+	    break;
+	}
+	break;
     default:
 	printf("Msg: %d\n", data[0]);
 	vnc_client_error(vs);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]