qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] How to send Ctrl+Alt+F1 to guest OS?


From: Fabrice Bellard
Subject: Re: [Qemu-devel] How to send Ctrl+Alt+F1 to guest OS?
Date: Fri, 20 Feb 2004 00:51:10 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624

I tried something like this (see attached patch), but it does not work reliably. It seems that the X11 server does not always interpret the XChangeKeyboardMapping() function.

Does anyone have a solution ?

WARNING: if you try this patch, save your keyboard mapping with 'xmodmap -pke' before !

Fabrice.
Index: sdl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/sdl.c,v
retrieving revision 1.4
diff -u -w -r1.4 sdl.c
--- sdl.c       6 Feb 2004 19:56:42 -0000       1.4
+++ sdl.c       19 Feb 2004 23:44:07 -0000
@@ -42,6 +42,15 @@
 
 #include <SDL.h>
 
+#if defined(__linux__)
+#define HAVE_X11
+#endif
+
+#ifdef HAVE_X11
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#endif
+
 #include "cpu.h"
 #include "exec-all.h"
 
@@ -165,8 +174,123 @@
     }
 }
 
+#ifdef HAVE_X11
+
+#define NB_REDEFINED_KEYCODES 12
+#define KEYCODE_MIN 67
+#define KEYCODE_MAX 96
+
+static int redefined_keycodes[NB_REDEFINED_KEYCODES] = {
+    67, /* F1 */
+    68, 
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76, /* F10 */
+    95, /* F11 */
+    96, /* F12 */
+#if 0
+    22, /* backspace (not enabled for easier abort) */
+#endif
+};
+
+static KeySym qemu_keysyms[NB_REDEFINED_KEYCODES] = {
+    XK_F1,
+    XK_F2,
+    XK_F3,
+    XK_F4,
+    XK_F5,
+    XK_F6,
+    XK_F7,
+    XK_F8,
+    XK_F9,
+    XK_F10,
+    XK_F11,
+    XK_F12,
+#if 0
+    XK_BackSpace,
+#endif
+};
+    
+static KeySym *saved_keysyms, *new_keysyms;
+static int saved_nb_keysyms;
+static int mappings_modified;
+static Display *x11_dpy;
+
+static void change_x11_mappings(void)
+{
+    int i, j, k;
+
+    if (!x11_dpy)
+        x11_dpy = XOpenDisplay(NULL);
+
+    if (!saved_keysyms) {
+        /* save F1-F12 mappings and X11 specific mappings. We do only
+           one XGetKeyboardMapping and XSetKeyboardMapping because the
+           X11 server is not able to hangdle many mapping change at
+           once. */
+        saved_keysyms = XGetKeyboardMapping(x11_dpy, 
+                                            KEYCODE_MIN,
+                                            KEYCODE_MAX - KEYCODE_MIN + 1,
+                                            &saved_nb_keysyms);
+#if 1        
+        for(i = 0; i < NB_REDEFINED_KEYCODES; i++) {
+            printf("keycode %d = ", redefined_keycodes[i]);
+            k = (redefined_keycodes[i] - KEYCODE_MIN) * saved_nb_keysyms;
+            for(j=0;j<saved_nb_keysyms;j++)
+                printf(" 0x%lx", saved_keysyms[k + j]);
+            printf("\n");
+        }
+#endif
+        new_keysyms = malloc(sizeof(KeySym) * 
+                             (KEYCODE_MAX - KEYCODE_MIN + 1) * 
+                             saved_nb_keysyms);
+        memcpy(new_keysyms, saved_keysyms,
+               sizeof(KeySym) * 
+               (KEYCODE_MAX - KEYCODE_MIN + 1) * saved_nb_keysyms);
+        /* redefine the QEMU keycodes */
+        for(i = 0; i < NB_REDEFINED_KEYCODES; i++) {
+            k = (redefined_keycodes[i] - KEYCODE_MIN) * saved_nb_keysyms;
+            saved_keysyms[k] = qemu_keysyms[i];
+            for(j = 1; j < saved_nb_keysyms; j++)
+                saved_keysyms[k + j] = NoSymbol;
+        }
+    }
+
+    if (!mappings_modified) {
+        XChangeKeyboardMapping(x11_dpy, 
+                               KEYCODE_MIN,
+                               saved_nb_keysyms,
+                               new_keysyms,
+                               KEYCODE_MAX - KEYCODE_MIN + 1);
+        XFlush(x11_dpy);
+        mappings_modified = 1;
+    }
+}
+
+static void restore_x11_mappings(void)
+{
+    if (mappings_modified) {
+        XChangeKeyboardMapping(x11_dpy, 
+                               KEYCODE_MIN,
+                               saved_nb_keysyms,
+                               saved_keysyms,
+                               KEYCODE_MAX - KEYCODE_MIN + 1);
+        XFlush(x11_dpy);
+        mappings_modified = 0;
+    }
+}
+#endif
+
 static void sdl_grab_start(void)
 {
+#ifdef HAVE_X11
+    change_x11_mappings();
+#endif
     SDL_WM_SetCaption("QEMU - Press Ctrl-Shift to exit grab", "QEMU");
     SDL_ShowCursor(0);
     SDL_WM_GrabInput(SDL_GRAB_ON);
@@ -180,6 +304,9 @@
     SDL_WM_SetCaption("QEMU", "QEMU");
     SDL_WM_GrabInput(SDL_GRAB_OFF);
     SDL_ShowCursor(1);
+#ifdef HAVE_X11
+    restore_x11_mappings();
+#endif
     gui_grab = 0;
 }
 
@@ -260,6 +387,9 @@
 
 static void sdl_cleanup(void) 
 {
+#ifdef HAVE_X11
+    restore_x11_mappings();
+#endif
     SDL_Quit();
 }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]