Hello Jim,

As fabrice know, i have done some work about it, but no time to debug.
Nevertheless, I think the code is near to work.

Maybe it can help you or someone to finish gtk2 driver...
(you can apply it directly on CVS, see TODO on gtk.c top for bugs)

Bye.

-- 
Sebastien Bechet <[EMAIL PROTECTED]>
av7.net
Index: Makefile
===================================================================
RCS file: /cvsroot/qemu/qemu/Makefile,v
retrieving revision 1.87
diff -u -r1.87 Makefile
--- Makefile	28 Apr 2005 21:15:08 -0000	1.87
+++ Makefile	27 May 2005 10:48:38 -0000
@@ -25,8 +25,13 @@
 endif
 endif
 
+ifdef CONFIG_GTK
+qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c gtk-qemu-img/src/callbacks.c gtk-qemu-img/src/interface.c gtk-qemu-img/src/support.c
+	$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
+else
 qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
 	$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
+endif
 
 dyngen$(EXESUF): dyngen.c
 	$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
Index: Makefile.target
===================================================================
RCS file: /cvsroot/qemu/qemu/Makefile.target,v
retrieving revision 1.69
diff -u -r1.69 Makefile.target
--- Makefile.target	28 Apr 2005 21:15:08 -0000	1.69
+++ Makefile.target	27 May 2005 10:48:39 -0000
@@ -14,7 +14,7 @@
 VPATH+=:$(SRC_PATH)/linux-user
 DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
 endif
-CFLAGS=-Wall -O2 -g -fno-strict-aliasing
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing $(GTK_CFLAGS)
 #CFLAGS+=-Werror
 LDFLAGS=-g
 LIBS=
@@ -357,6 +357,9 @@
 ifdef CONFIG_SDL
 VL_OBJS+=sdl.o
 endif
+ifdef CONFIG_GTK
+VL_OBJS+=gtk.o
+endif
 ifdef CONFIG_COCOA
 VL_OBJS+=cocoa.o
 COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa
@@ -392,13 +395,16 @@
 endif
 
 $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
-	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(GTK_LIBS) $(VL_LIBS)
 
 cocoa.o: cocoa.m
 	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
 
 sdl.o: sdl.c keymaps.c sdl_keysym.h
-	$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+	$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) $(GTK_CFLAGS) -c -o $@ $<
+
+gtk.o : gtk.c
+	$(CC) $(CFLAGS) $(DEFINES) $(GTK_CFLAGS) -c -o $@ $<
 
 sdlaudio.o: sdlaudio.c
 	$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
Index: configure
===================================================================
RCS file: /cvsroot/qemu/qemu/configure,v
retrieving revision 1.66
diff -u -r1.66 configure
--- configure	28 Apr 2005 20:41:53 -0000	1.66
+++ configure	27 May 2005 10:48:39 -0000
@@ -168,6 +168,8 @@
   ;;
   --disable-sdl) sdl="no"
   ;;
+  --enable-gtk) gtk="yes" ; sdl="no" ; sdl_static="no"
+  ;;
   --enable-fmod) fmod="yes"
   ;;
   --fmod-lib=*) fmod_lib=${opt#--fmod-lib=}
@@ -306,6 +308,34 @@
 fi # cross compilation
 fi # -z $sdl
 
+##########################################
+# GTK probe
+
+gtk_too_old=no
+
+if test -z "$gtk" ; then
+
+gtk=no
+
+# normal GTK probe
+cat > $TMPC << EOF
+#include <stdlib.h>
+#include <gtk/gtk.h>
+int main(int argc, char **argv) { gtk_init(&argc, &argv); return EXIT_SUCCESS; }
+EOF
+
+if $cc -o $TMPE `pkg-config --cflags --libs gtk+-2.0 2> /dev/null` $TMPC 2> /dev/null ; then
+_gtkversion=`pkg-config --modversion gtk+-2.0 | sed 's/[^0-9]//g'`
+if test "$_sdlversion" -lt 240 ; then
+  gtk_too_old=yes
+else
+  gtk=yes
+fi
+
+fi # gtk compile test
+
+fi # -z $gtk
+
 if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
 cat << EOF
 
@@ -422,6 +452,7 @@
 if test "$sdl" != "no" ; then
     echo "SDL static link   $sdl_static"
 fi
+echo "GTK support       $gtk"
 echo "mingw32 support   $mingw32"
 echo "Adlib support     $adlib"
 echo -n "FMOD support      $fmod"
@@ -704,6 +735,14 @@
     fi
 fi
 
+if test "$gtk" = "yes" ; then
+    echo "#define CONFIG_GTK 1" >> $config_h
+    echo "CONFIG_GTK=yes" >> $config_mak
+    echo "GTK_LIBS=`pkg-config --libs gtk+-2.0`" >> $config_mak
+    echo "GTK_CFLAGS=`pkg-config --cflags gtk+-2.0`" >> $config_mak
+    echo "" >> $config_mak
+fi
+
 if test "$cocoa" = "yes" ; then
     echo "#define CONFIG_COCOA 1" >> $config_h
     echo "CONFIG_COCOA=yes" >> $config_mak
Index: qemu-img.c
===================================================================
RCS file: /cvsroot/qemu/qemu/qemu-img.c,v
retrieving revision 1.7
diff -u -r1.7 qemu-img.c
--- qemu-img.c	28 Apr 2005 21:15:08 -0000	1.7
+++ qemu-img.c	27 May 2005 10:48:39 -0000
@@ -21,6 +21,12 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#ifdef CONFIG_GTK
+#include <gtk/gtk.h>
+#include "interface.h"
+#include "support.h"
+#endif
+
 #include "vl.h"
 
 void *get_mmap_addr(unsigned long size)
@@ -675,6 +681,7 @@
     return 0;
 }
 
+#ifndef CONFIG_GTK
 int main(int argc, char **argv)
 {
     const char *cmd;
@@ -697,3 +704,21 @@
     }
     return 0;
 }
+#else
+int main(int argc, char **argv)
+{
+	GtkWidget *qimg;
+
+	bdrv_init();
+
+	gtk_set_locale ();
+	gtk_init (&argc, &argv);
+
+	qimg = create_qimg ();
+	gtk_widget_show (qimg);
+
+	gtk_main ();
+
+	return 0;
+}
+#endif
Index: vl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.c,v
retrieving revision 1.127
diff -u -r1.127 vl.c
--- vl.c	30 Apr 2005 16:10:35 -0000	1.127
+++ vl.c	27 May 2005 10:48:44 -0000
@@ -23,6 +23,8 @@
  */
 #include "vl.h"
 
+#include <gtk/gtk.h>
+
 #include <unistd.h>
 #include <fcntl.h>
 #include <signal.h>
@@ -2679,7 +2681,6 @@
             }
         }
 #endif
-
         if (vm_running) {
             qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], 
                             qemu_get_clock(vm_clock));
@@ -2721,6 +2722,11 @@
         } else {
             timeout = 10;
         }
+
+    if (gtk_events_pending ()) {
+        gtk_main_iteration_do (FALSE);
+    }
+
         main_loop_wait(timeout);
     }
     cpu_disable_ticks();
@@ -3597,6 +3603,8 @@
     } else {
 #if defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen);
+#elif defined(CONFIG_GTK)
+		gtk_display_init(ds, full_screen);
 #elif defined(CONFIG_COCOA)
         cocoa_display_init(ds, full_screen);
 #else
Index: vl.h
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.h,v
retrieving revision 1.74
diff -u -r1.74 vl.h
--- vl.h	30 Apr 2005 16:10:35 -0000	1.74
+++ vl.h	27 May 2005 10:48:44 -0000
@@ -577,6 +577,9 @@
 /* sdl.c */
 void sdl_display_init(DisplayState *ds, int full_screen);
 
+/* gtk.c */
+void gtk_display_init(DisplayState *ds, int full_screen);
+
 /* cocoa.m */
 void cocoa_display_init(DisplayState *ds, int full_screen);
 
Index: hw/vga.c
===================================================================
RCS file: /cvsroot/qemu/qemu/hw/vga.c,v
retrieving revision 1.40
diff -u -r1.40 vga.c
--- hw/vga.c	23 Apr 2005 18:43:45 -0000	1.40
+++ hw/vga.c	27 May 2005 10:48:44 -0000
@@ -803,7 +803,11 @@
 
 static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
 {
-    return (r << 16) | (g << 8) | b;
+#ifdef CONFIG_GTK
+	return 0xFF000000 | (b << 16) | (g << 8) | r;
+#else
+	return (r << 16) | (g << 8) | b;
+#endif
 }
 
 #define DEPTH 8
#include <gdk/gdkkeysyms.h>

typedef struct {
	const char* name;
	int keysym;
} name2keysym_t;
static name2keysym_t name2keysym[]={
/* ascii */
    { "space",                0x020},
    { "exclam",               0x021},
    { "quotedbl",             0x022},
    { "numbersign",           0x023},
    { "dollar",               0x024},
    { "percent",              0x025},
    { "ampersand",            0x026},
    { "apostrophe",           0x027},
    { "parenleft",            0x028},
    { "parenright",           0x029},
    { "asterisk",             0x02a},
    { "plus",                 0x02b},
    { "comma",                0x02c},
    { "minus",                0x02d},
    { "period",               0x02e},
    { "slash",                0x02f},
    { "0",                    0x030},
    { "1",                    0x031},
    { "2",                    0x032},
    { "3",                    0x033},
    { "4",                    0x034},
    { "5",                    0x035},
    { "6",                    0x036},
    { "7",                    0x037},
    { "8",                    0x038},
    { "9",                    0x039},
    { "colon",                0x03a},
    { "semicolon",            0x03b},
    { "less",                 0x03c},
    { "equal",                0x03d},
    { "greater",              0x03e},
    { "question",             0x03f},
    { "at",                   0x040},
    { "A",                    0x041},
    { "B",                    0x042},
    { "C",                    0x043},
    { "D",                    0x044},
    { "E",                    0x045},
    { "F",                    0x046},
    { "G",                    0x047},
    { "H",                    0x048},
    { "I",                    0x049},
    { "J",                    0x04a},
    { "K",                    0x04b},
    { "L",                    0x04c},
    { "M",                    0x04d},
    { "N",                    0x04e},
    { "O",                    0x04f},
    { "P",                    0x050},
    { "Q",                    0x051},
    { "R",                    0x052},
    { "S",                    0x053},
    { "T",                    0x054},
    { "U",                    0x055},
    { "V",                    0x056},
    { "W",                    0x057},
    { "X",                    0x058},
    { "Y",                    0x059},
    { "Z",                    0x05a},
    { "bracketleft",          0x05b},
    { "backslash",            0x05c},
    { "bracketright",         0x05d},
    { "asciicircum",          0x05e},
    { "underscore",           0x05f},
    { "grave",                0x060},
    { "a",                    0x061},
    { "b",                    0x062},
    { "c",                    0x063},
    { "d",                    0x064},
    { "e",                    0x065},
    { "f",                    0x066},
    { "g",                    0x067},
    { "h",                    0x068},
    { "i",                    0x069},
    { "j",                    0x06a},
    { "k",                    0x06b},
    { "l",                    0x06c},
    { "m",                    0x06d},
    { "n",                    0x06e},
    { "o",                    0x06f},
    { "p",                    0x070},
    { "q",                    0x071},
    { "r",                    0x072},
    { "s",                    0x073},
    { "t",                    0x074},
    { "u",                    0x075},
    { "v",                    0x076},
    { "w",                    0x077},
    { "x",                    0x078},
    { "y",                    0x079},
    { "z",                    0x07a},
    { "braceleft",            0x07b},
    { "bar",                  0x07c},
    { "braceright",           0x07d},
    { "asciitilde",           0x07e},

/* latin 1 extensions */
{ "nobreakspace",         0x0a0},
{ "exclamdown",           0x0a1},
{ "cent",         	  0x0a2},
{ "sterling",             0x0a3},
{ "currency",             0x0a4},
{ "yen",                  0x0a5},
{ "brokenbar",            0x0a6},
{ "section",              0x0a7},
{ "diaeresis",            0x0a8},
{ "copyright",            0x0a9},
{ "ordfeminine",          0x0aa},
{ "guillemotleft",        0x0ab},
{ "notsign",              0x0ac},
{ "hyphen",               0x0ad},
{ "registered",           0x0ae},
{ "macron",               0x0af},
{ "degree",               0x0b0},
{ "plusminus",            0x0b1},
{ "twosuperior",          0x0b2},
{ "threesuperior",        0x0b3},
{ "acute",                0x0b4},
{ "mu",                   0x0b5},
{ "paragraph",            0x0b6},
{ "periodcentered",       0x0b7},
{ "cedilla",              0x0b8},
{ "onesuperior",          0x0b9},
{ "masculine",            0x0ba},
{ "guillemotright",       0x0bb},
{ "onequarter",           0x0bc},
{ "onehalf",              0x0bd},
{ "threequarters",        0x0be},
{ "questiondown",         0x0bf},
{ "Agrave",               0x0c0},
{ "Aacute",               0x0c1},
{ "Acircumflex",          0x0c2},
{ "Atilde",               0x0c3},
{ "Adiaeresis",           0x0c4},
{ "Aring",                0x0c5},
{ "AE",                   0x0c6},
{ "Ccedilla",             0x0c7},
{ "Egrave",               0x0c8},
{ "Eacute",               0x0c9},
{ "Ecircumflex",          0x0ca},
{ "Ediaeresis",           0x0cb},
{ "Igrave",               0x0cc},
{ "Iacute",               0x0cd},
{ "Icircumflex",          0x0ce},
{ "Idiaeresis",           0x0cf},
{ "ETH",                  0x0d0},
{ "Eth",                  0x0d0},
{ "Ntilde",               0x0d1},
{ "Ograve",               0x0d2},
{ "Oacute",               0x0d3},
{ "Ocircumflex",          0x0d4},
{ "Otilde",               0x0d5},
{ "Odiaeresis",           0x0d6},
{ "multiply",             0x0d7},
{ "Ooblique",             0x0d8},
{ "Oslash",               0x0d8},
{ "Ugrave",               0x0d9},
{ "Uacute",               0x0da},
{ "Ucircumflex",          0x0db},
{ "Udiaeresis",           0x0dc},
{ "Yacute",               0x0dd},
{ "THORN",                0x0de},
{ "Thorn",                0x0de},
{ "ssharp",               0x0df},
{ "agrave",               0x0e0},
{ "aacute",               0x0e1},
{ "acircumflex",          0x0e2},
{ "atilde",               0x0e3},
{ "adiaeresis",           0x0e4},
{ "aring",                0x0e5},
{ "ae",                   0x0e6},
{ "ccedilla",             0x0e7},
{ "egrave",               0x0e8},
{ "eacute",               0x0e9},
{ "ecircumflex",          0x0ea},
{ "ediaeresis",           0x0eb},
{ "igrave",               0x0ec},
{ "iacute",               0x0ed},
{ "icircumflex",          0x0ee},
{ "idiaeresis",           0x0ef},
{ "eth",                  0x0f0},
{ "ntilde",               0x0f1},
{ "ograve",               0x0f2},
{ "oacute",               0x0f3},
{ "ocircumflex",          0x0f4},
{ "otilde",               0x0f5},
{ "odiaeresis",           0x0f6},
{ "division",             0x0f7},
{ "oslash",               0x0f8},
{ "ooblique",             0x0f8},
{ "ugrave",               0x0f9},
{ "uacute",               0x0fa},
{ "ucircumflex",          0x0fb},
{ "udiaeresis",           0x0fc},
{ "yacute",               0x0fd},
{ "thorn",                0x0fe},
{ "ydiaeresis",           0x0ff},
{"EuroSign", GDK_EuroSign},

    /* modifiers */
{"Control_L", GDK_Control_L},
{"Control_R", GDK_Control_R},
{"Alt_L", GDK_Alt_L},
{"Alt_R", GDK_Alt_R},
{"Caps_Lock", GDK_Caps_Lock},
{"Meta_L", GDK_Meta_L},
{"Meta_R", GDK_Meta_R},
{"Shift_L", GDK_Shift_L},
{"Shift_R", GDK_Shift_R},

    /* special keys */
{"BackSpace", GDK_BackSpace},
{"Tab", GDK_Tab},
{"Return", GDK_Return},
{"Right", GDK_Right},
{"Left", GDK_Left},
{"Up", GDK_Up},
{"Down", GDK_Down},
{"Page_Down", GDK_Page_Down},
{"Page_Up", GDK_Page_Up},
{"Insert", GDK_Insert},
{"Delete", GDK_Delete},
{"Home", GDK_Home},
{"End", GDK_End},
{"Scroll_Lock", GDK_Scroll_Lock},
{"F1", GDK_F1},
{"F2", GDK_F2},
{"F3", GDK_F3},
{"F4", GDK_F4},
{"F5", GDK_F5},
{"F6", GDK_F6},
{"F7", GDK_F7},
{"F8", GDK_F8},
{"F9", GDK_F9},
{"F10", GDK_F10},
{"F11", GDK_F11},
{"F12", GDK_F12},
{"F13", GDK_F13},
{"F14", GDK_F14},
{"F15", GDK_F15},
{"Sys_Req", GDK_Sys_Req},
{"KP_0", GDK_KP_0},
{"KP_1", GDK_KP_1},
{"KP_2", GDK_KP_2},
{"KP_3", GDK_KP_3},
{"KP_4", GDK_KP_4},
{"KP_5", GDK_KP_5},
{"KP_6", GDK_KP_6},
{"KP_7", GDK_KP_7},
{"KP_8", GDK_KP_8},
{"KP_9", GDK_KP_9},
{"KP_Add", GDK_KP_Add},
{"KP_Decimal", GDK_KP_Decimal},
{"KP_Divide", GDK_KP_Divide},
{"KP_Enter", GDK_KP_Enter},
{"KP_Equal", GDK_KP_Equal},
{"KP_Multiply", GDK_KP_Multiply},
{"KP_Subtract", GDK_KP_Subtract},
{"help", GDK_Help},
{"Menu", GDK_Menu},
{"Print", GDK_Print},
{"Mode_switch", GDK_Mode_switch},
{"Multi_Key", GDK_Multi_key},
{"Num_Lock", GDK_Num_Lock},
{"Pause", GDK_Pause},

{0,0},
};
/*
 * QEMU GTK display driver
 * 
 * Copyright (c) 2004 Sebastien Bechet
 * Copyright (c) 2003 Fabrice Bellard
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
/*
TODO :
configure !i386-softmmu
grab
RGBA endian problem in vga.c
fullscreen
gtk key release event ok, remove modifiers_state, reset_keys ...

*/
#include "vl.h"

#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>

GtkWidget *pWindow;
GtkImage *pImage;
GdkPixbuf *pPixbuf;

static int mouse_dx, mouse_dy, mouse_dz, mouse_buttons;

static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int last_vm_running;
static int gui_saved_grab;
static int gui_fullscreen;

static int gui_key_modifier_pressed;
static int gui_keysym;
static int gui_fullscreen_initial_grab;
static int gui_grab_code = GDK_CONTROL_MASK | GDK_MOD1_MASK;
static uint8_t modifiers_state[256];

static void gtk_update(DisplayState *ds, int x, int y, int w, int h)
{
    GdkRectangle grect;
    GdkRegion *pRegion;
    
    grect.x = (gint)x;
    grect.y = (gint)y;
    grect.width = (gint)w;
    grect.height = (gint)h;

    pRegion = gdk_region_rectangle(&grect);
    gdk_window_invalidate_region(GTK_WIDGET(pImage)->window,pRegion,TRUE);
    gdk_region_destroy(pRegion);
}

static void gtk_resize(DisplayState *ds, int w, int h)
{
    if (pPixbuf != NULL) g_object_unref(pPixbuf);
    pPixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,TRUE, 8, w, h);
    gtk_image_set_from_pixbuf(pImage,pPixbuf);
    gtk_window_resize(GTK_WINDOW(pWindow), w, h);

    if (gui_fullscreen)
        gtk_window_fullscreen(GTK_WINDOW(pWindow));
    else
        gtk_window_unfullscreen(GTK_WINDOW(pWindow));

    ds->data = gdk_pixbuf_get_pixels(pPixbuf);
    ds->linesize = gdk_pixbuf_get_rowstride(pPixbuf);
    ds->depth = gdk_pixbuf_get_n_channels(pPixbuf)*gdk_pixbuf_get_bits_per_sample(pPixbuf); //4*8;
    ds->width = gdk_pixbuf_get_width(pPixbuf);
    ds->height = gdk_pixbuf_get_height(pPixbuf);
}

/* generic keyboard conversion */

#include "gtk_keysym.h"
#include "keymaps.c"

static kbd_layout_t *kbd_layout = NULL;

static uint8_t gtk_keyevent_to_keycode_generic(const GdkEventKey *ev)
{
    int keysym;
    /* workaround for X11+SDL bug with AltGR */
    keysym = ev->keyval;
/* XXX : ?
        if (keysym == 0 && ev->keysym.scancode == 113)
        keysym = SDLK_MODE;*/
    return keysym2scancode(kbd_layout, keysym);
}

/* specific keyboard conversions from scan codes */

#if defined(_WIN32)

static uint8_t gtk_keyevent_to_keycode(const GdkEventKey *ev)
{
    return ev->hardware_keycode;
}

#else

static const uint8_t x_keycode_to_pc_keycode[61] = {
   0xc7,      /*  97  Home   */
   0xc8,      /*  98  Up     */
   0xc9,      /*  99  PgUp   */
   0xcb,      /* 100  Left   */
   0x4c,        /* 101  KP-5   */
   0xcd,      /* 102  Right  */
   0xcf,      /* 103  End    */
   0xd0,      /* 104  Down   */
   0xd1,      /* 105  PgDn   */
   0xd2,      /* 106  Ins    */
   0xd3,      /* 107  Del    */
   0x9c,      /* 108  Enter  */
   0x9d,      /* 109  Ctrl-R */
   0x0,       /* 110  Pause  */
   0xb7,      /* 111  Print  */
   0xb5,      /* 112  Divide */
   0xb8,      /* 113  Alt-R  */
   0xc6,      /* 114  Break  */   
   0x0,         /* 115 */
   0x0,         /* 116 */
   0x0,         /* 117 */
   0x0,         /* 118 */
   0x0,         /* 119 */
   0x70,         /* 120 Hiragana_Katakana */
   0x0,         /* 121 */
   0x0,         /* 122 */
   0x73,         /* 123 backslash */
   0x0,         /* 124 */
   0x0,         /* 125 */
   0x0,         /* 126 */
   0x0,         /* 127 */
   0x0,         /* 128 */
   0x79,         /* 129 Henkan */
   0x0,         /* 130 */
   0x7b,         /* 131 Muhenkan */
   0x0,         /* 132 */
   0x7d,         /* 133 Yen */
   0x0,         /* 134 */
   0x0,         /* 135 */
   0x47,         /* 136 KP_7 */
   0x48,         /* 137 KP_8 */
   0x49,         /* 138 KP_9 */
   0x4b,         /* 139 KP_4 */
   0x4c,         /* 140 KP_5 */
   0x4d,         /* 141 KP_6 */
   0x4f,         /* 142 KP_1 */
   0x50,         /* 143 KP_2 */
   0x51,         /* 144 KP_3 */
   0x52,         /* 145 KP_0 */
   0x53,         /* 146 KP_. */
   0x47,         /* 147 KP_HOME */
   0x48,         /* 148 KP_UP */
   0x49,         /* 149 KP_PgUp */
   0x4b,         /* 150 KP_Left */
   0x4c,         /* 151 KP_ */
   0x4d,         /* 152 KP_Right */
   0x4f,         /* 153 KP_End */
   0x50,         /* 154 KP_Down */
   0x51,         /* 155 KP_PgDn */
   0x52,         /* 156 KP_Ins */
   0x53,         /* 157 KP_Del */
};

static uint8_t gtk_keyevent_to_keycode(const GdkEventKey *ev)
{
    int keycode;

    keycode = ev->hardware_keycode;

    if (keycode < 9) {
        keycode = 0;
    } else if (keycode < 97) {
        keycode -= 8; /* just an offset */
    } else if (keycode < 158) {
        /* use conversion table */
        keycode = x_keycode_to_pc_keycode[keycode - 97];
    } else {
        keycode = 0;
    }
    return keycode;
}

#endif

static void reset_keys(void)
{
    int i;
    for(i = 0; i < 256; i++) {
        if (modifiers_state[i]) {
            if (i & 0x80)
                kbd_put_keycode(0xe0);
            kbd_put_keycode(i | 0x80);
            modifiers_state[i] = 0;
        }
    }
}

static void gtk_process_key(GdkEventKey *ev)
{
    int keycode, v;

    /* Pause key */
    if (ev->hardware_keycode == 0x6E) {
	/* specific case */
	v = 0;
	if (ev->type == GDK_KEY_RELEASE)
	    v |= 0x80;
	kbd_put_keycode(0xe1);
	kbd_put_keycode(0x1d | v);
	kbd_put_keycode(0x45 | v);
        return;
    }

    if (kbd_layout) {
        keycode = gtk_keyevent_to_keycode_generic(ev);
    } else {
        keycode = gtk_keyevent_to_keycode(ev);
    }

    switch(keycode) {
    case 0x00:
	/* sent when leaving window: reset the modifiers state */
        reset_keys();
        return;
    case 0x32:	/* Left Shift */
    case 0x3E:	/* Right Shift */
    case 0x25:	/* Left CTRL */
    case 0x6D:	/* Right CTRL */
    case 0x40:	/* Left ALT */
    case 0x71:	/* Right ALT */
	    if (ev->type == GDK_KEY_RELEASE)
		modifiers_state[keycode] = 0;
	    else
		modifiers_state[keycode] = 1;
	    break;
    case 0x45: /* num lock */
    case 0x3a: /* caps lock */
        /*XXX : GTK send the key up event... */
        kbd_put_keycode(keycode);
        kbd_put_keycode(keycode | 0x80);
        return;

    }

    /* now send the key code */
    if (keycode & 0x80)
        kbd_put_keycode(0xe0);
    if (ev->type == GDK_KEY_RELEASE)
        kbd_put_keycode(keycode | 0x80);
    else
        kbd_put_keycode(keycode & 0x7f);   
}

static void gtk_update_caption(void)
{
    char buf[1024];
    strcpy(buf, "QEMU");
    if (!vm_running) {
        strcat(buf, " [Stopped]");
    }
    if (gui_grab) {
        strcat(buf, " - Press Ctrl-Alt to exit grab");
    }
    gtk_window_set_title(GTK_WINDOW(pWindow), buf);
}

static void gtk_grab_start(void)
{
    /* showcursor(false),grabinput*/
	
/*	gdk_pointer_grab(pWindow->window,
			TRUE,
			GDK_POINTER_MOTION_MASK |
			GDK_BUTTON_PRESS_MASK | 
			GDK_BUTTON_RELEASE_MASK,
			pWindow->window,
			NULL,
			GDK_CURRENT_TIME);*/
	gui_grab = 1;
	gtk_update_caption();
}

static void gtk_grab_end(void)
{
/*	gdk_pointer_ungrab(GDK_CURRENT_TIME);*/
	gui_grab = 0;
	gtk_update_caption();
}

static void gtk_send_mouse_event(void)
{
    fprintf(stderr,"dx=%d, dy=%d dz=%d buttons=%d\n",mouse_dx, mouse_dy, mouse_dz, mouse_buttons);
    kbd_mouse_event(mouse_dx, mouse_dy, mouse_dz, mouse_buttons);
}

static void toggle_full_screen(DisplayState *ds)
{
    gui_fullscreen = !gui_fullscreen;
    if (gui_fullscreen) {
        gui_saved_grab = gui_grab;
	gtk_grab_start();
    } else {
	if (!gui_saved_grab)
	    gtk_grab_end();
	
    }
    vga_invalidate_display();
    vga_update_display();
}

static void gtk_refresh(DisplayState *ds)
{
    if (last_vm_running != vm_running) {
        last_vm_running = vm_running;
        gtk_update_caption();
    }

    if (is_active_console(vga_console)) 
        vga_update_display();

    if (gtk_events_pending ()) {
	gtk_main_iteration_do (FALSE);
    }

//    fprintf(stderr,"gtk_refresh d=%d, w=%d, h=%d, ls=%d\n",ds->depth,ds->width,ds->height,ds->linesize);
}

static gboolean on_key(GtkWidget *widget, GdkEventKey *ev, DisplayState *ds)
{
    int mod_state;

    fprintf(stderr,"on_key : se=%02X state=%02X key=0x%02X hkey=0x%02X grp=%d\n",ev->send_event,ev->state,ev->keyval,ev->hardware_keycode,ev->group);
    if (ev->type == GDK_KEY_PRESS) {
	mod_state = (ev->state & gui_grab_code) == gui_grab_code;
	gui_key_modifier_pressed = mod_state;
	if (gui_key_modifier_pressed) {
	    int keycode;
	    keycode = ev->hardware_keycode;
	    switch(keycode) {
	    case 0x29: /* 'f' hardware key */
		toggle_full_screen(ds);
	        gui_keysym = 1;
	        break;
	    case 0x0a ... 0x12: /* '1' to '9' keys */
		console_select(keycode - 0x0a);
	        if (is_active_console(vga_console)) {
		    /* tell the vga console to redisplay itself */
		    vga_invalidate_display();
		} else {
		    if (gui_grab)
			gtk_grab_end();
		}
		gui_keysym = 1;
		break;
	    default:
		break;
	    }
	} else if (!is_active_console(vga_console)) {
	    int keysym;
            keysym = 0;
	    if (ev->state & GDK_CONTROL_MASK) {
                switch(ev->hardware_keycode) {
                case 0x62: keysym = QEMU_KEY_CTRL_UP; break;
                case 0x68: keysym = QEMU_KEY_CTRL_DOWN; break;
                case 0x64: keysym = QEMU_KEY_CTRL_LEFT; break;
                case 0x66: keysym = QEMU_KEY_CTRL_RIGHT; break;
                case 0x61: keysym = QEMU_KEY_CTRL_HOME; break;
                case 0x67: keysym = QEMU_KEY_CTRL_END; break;
                case 0x63: keysym = QEMU_KEY_CTRL_PAGEUP; break;
                case 0x69: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
                default: break;
                }
	    } else {
                switch(ev->hardware_keycode) {
                case 0x62: keysym = QEMU_KEY_UP; break;
                case 0x68: keysym = QEMU_KEY_DOWN; break;
                case 0x64: keysym = QEMU_KEY_LEFT; break;
                case 0x66: keysym = QEMU_KEY_RIGHT; break;
                case 0x61: keysym = QEMU_KEY_HOME; break;
                case 0x67: keysym = QEMU_KEY_END; break;
                case 0x63: keysym = QEMU_KEY_PAGEUP; break;
                case 0x69: keysym = QEMU_KEY_PAGEDOWN; break;
                case 0x16: keysym = QEMU_KEY_BACKSPACE; break;
		case 0x6b: keysym = QEMU_KEY_DELETE; break;
                default: break;
                }
	    }
	    if (keysym) {
                kbd_put_keysym(keysym);
            } else {
                kbd_put_keysym(ev->keyval);
            }
	}
    } else if (ev->type == GDK_KEY_RELEASE) {
	mod_state = (ev->state & gui_grab_code);
	if (!mod_state) {
	    if (gui_key_modifier_pressed) {
                if (gui_keysym == 0) {
		    /* exit/enter grab if pressing Ctrl-Alt */
                    if (!gui_grab)
                        gtk_grab_start();
                    else
                        gtk_grab_end();
		    reset_keys();
                    return TRUE;
	        }
	        gui_key_modifier_pressed = 0;
                gui_keysym = 0;
            }
	}
    }
    if (is_active_console(vga_console))
	gtk_process_key(ev);
    return TRUE;
}

static gboolean on_motion(GtkWidget *widget, GdkEventMotion *event, DisplayState *ds)
{
    if (gui_grab) {
        mouse_dx = event->x;
        mouse_dy = event->y;
        gtk_send_mouse_event();
    }
    return TRUE;
}

#ifdef SDL_BUTTON_WHEELUP
static gboolean on_scroll(GtkWidget *widget, GdkEventScroll *event, DisplayState *ds)
{
    if (event->direction == GDK_SCROLL_UP)
        mouse_dz--;
    if (event->direction == GDK_SCROLL_DOWN)
        mouse_dz++;
    gtk_send_mouse_event();
    return TRUE;
}
#endif

static gboolean on_button(GtkWidget *widget, GdkEventButton *event, DisplayState *ds)
{
    mouse_dx = event->x;
    mouse_dy = event->y;

    if (!gui_grab) {
        if (event->type == GDK_BUTTON_PRESS &&
	    event->button == 1) {
            gtk_grab_start();
	}
    } else {
        if (event->button == 1)
	    mouse_buttons ^= MOUSE_EVENT_LBUTTON;
        else if (event->button == 2)
	    mouse_buttons ^= MOUSE_EVENT_MBUTTON;
        else if (event->button == 3)
	    mouse_buttons ^= MOUSE_EVENT_RBUTTON;

	gtk_send_mouse_event();
    }

    return TRUE;
}

static void on_quit_clicked()
{
    fprintf(stderr,"click\n");
}


void gtk_display_init(DisplayState *ds, int full_screen)
{
	
    mouse_dx = mouse_dy = mouse_dz = mouse_buttons = 0;

#if defined(__APPLE__)
    /* always use generic keymaps */
    if (!keyboard_layout)
        keyboard_layout = "en-us";
#endif
    if(keyboard_layout) {
        kbd_layout = init_keyboard_layout(keyboard_layout);
        if (!kbd_layout)
            exit(1);
    }
	
    gtk_init(NULL,NULL);
    pWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    pImage = GTK_IMAGE(gtk_image_new());
    pPixbuf = NULL;

    ds->dpy_update = gtk_update;
    ds->dpy_resize = gtk_resize;
    ds->dpy_refresh = gtk_refresh;

    gtk_container_add(GTK_CONTAINER(pWindow), GTK_WIDGET(pImage));
	
    gtk_resize(ds, 640, 400);
    gtk_update_caption();

    g_signal_connect(pWindow,"delete-event", G_CALLBACK(on_quit_clicked), NULL);
    g_signal_connect(pWindow,"key-press-event", G_CALLBACK(on_key), ds);
    g_signal_connect(pWindow,"key-release-event", G_CALLBACK(on_key), ds);
    g_signal_connect(pWindow,"motion-notify-event", G_CALLBACK(on_motion), ds);
    g_signal_connect(pWindow,"button-press-event", G_CALLBACK(on_button), ds);
    g_signal_connect(pWindow,"button-release-event", G_CALLBACK(on_button), ds);
#ifdef SDL_BUTTON_WHEELUP
    g_signal_connect(pWindow,"scroll-event", G_CALLBACK(on_scroll), ds);
    gtk_widget_add_events(pWindow,GDK_SCROLL_MASK);
#endif
    gtk_widget_add_events(pWindow,GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
    
    gtk_widget_show_all(pWindow);
    
    if (full_screen) {
	gui_fullscreen = 1;
	gui_fullscreen_initial_grab = 1;
	gtk_grab_start();
    }

}
_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel

Reply via email to