qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: "Daniel P. Berrange" <berrange@redhat.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] opengl rendering in the sdl window
Date: Sun, 07 Sep 2008 19:12:34 -0500	[thread overview]
Message-ID: <48C46DF2.2050007@codemonkey.ws> (raw)
In-Reply-To: <20080907163123.GD31773@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1139 bytes --]

Daniel P. Berrange wrote:
> On Sat, Sep 06, 2008 at 10:07:10PM -0500, Anthony Liguori wrote:
>   
>> Daniel P. Berrange wrote:
>>     
>>> On Wed, Sep 03, 2008 at 10:00:31PM -0500, Anthony Liguori wrote:
>>>  
>>> Actually I'm not so sure this was a good idea in the end. I'm seriously
>>> considering re-writing the GTK-VNC stuff to use Cairo, which in turn
>>> can use 2-d hardware acceleration primitives - it really doesn't need
>>> the full 3-d acceleration stack just for scaling. 
>>>  
>>>       
>> I tried to originally write the GTK-VNC scaling stuff in Cairo.  Could 
>> not get it to perform well at all.  I'd be really interested if you had 
>> better luck with it.
>>     
>
> I've just posted patches to the GTK-VNC devel list demonstrating use of
> Cairo for all rendering. I can't notice any serious drop in performance
> when enabling scaling with Cairo. If you confirm my tests, it'd be worth
> evaluating Cairo as an alternative to OpenGL in QEMU too.
>   

Here's the beginning of a GTK front-end in case someone wants to try 
adapting the Cairo patches to QEMU.

Regards,

Anthony Liguori

> Regards,
> Daniel
>   


[-- Attachment #2: gtk.patch --]
[-- Type: text/x-patch, Size: 26161 bytes --]

diff --git a/Makefile b/Makefile
index 0472e16..3927c40 100644
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,9 @@ ifdef CONFIG_CURSES
 OBJS+=curses.o
 endif
 OBJS+=vnc.o d3des.o
+ifdef CONFIG_GTK
+OBJS+=gtk.o
+endif
 
 ifdef CONFIG_COCOA
 OBJS+=cocoa.o
@@ -145,6 +148,9 @@ cocoa.o: cocoa.m
 sdl.o: sdl.c keymaps.c sdl_keysym.h
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) -c -o $@ $<
 
+gtk.o: gtk.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(GTK_CFLAGS) -c -o $@ $<
+
 vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(CONFIG_VNC_TLS_CFLAGS) -c -o $@ $<
 
diff --git a/Makefile.target b/Makefile.target
index 42162c3..572b44b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -515,6 +515,10 @@ CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
 LIBS += $(CONFIG_VNC_TLS_LIBS)
 endif
 
+ifdef CONFIG_GTK
+LIBS += $(GTK_LIBS)
+endif
+
 # SCSI layer
 OBJS+= lsi53c895a.o esp.o
 
diff --git a/configure b/configure
index 0a3b7c9..d0e63fa 100755
--- a/configure
+++ b/configure
@@ -90,6 +90,7 @@ EXESUF=""
 gdbstub="yes"
 slirp="yes"
 vde="yes"
+gtk="yes"
 fmod_lib=""
 fmod_inc=""
 vnc_tls="yes"
@@ -283,6 +284,8 @@ for opt do
   ;;
   --disable-vde) vde="no"
   ;;
+  --disable-gtk) gtk="no"
+  ;;
   --disable-kqemu) kqemu="no"
   ;;
   --disable-brlapi) brlapi="no"
@@ -436,6 +439,7 @@ echo "  --fmod-inc               path to FMOD includes"
 echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
 echo "  --sparc_cpu=V            Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
 echo "  --disable-vde            disable support for vde network"
+echo "  --disable-gtk            disable support for GTK"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -758,6 +762,20 @@ EOF
     fi
 fi
 
+if test "$gtk" = "yes" ; then
+    cat > $TMPC <<EOF
+#include <gtk/gtk.h>
+int main(int argc, char **argv) { gtk_init(&argc, &argv); return 0; }
+EOF
+    gtk_cflags=`pkg-config --cflags gtk+-2.0`
+    gtk_libs=`pkg-config --libs gtk+-2.0`
+    if $cc $ARCH_CFLAGS -o $TMPE $TMPC $gtk_cflags $gtk_libs ; then
+	:
+    else
+	gtk="no"
+    fi
+fi
+
 ##########################################
 # Sound support libraries probe
 
@@ -923,6 +941,7 @@ echo "Documentation     $build_docs"
 echo "uname -r          $uname_release"
 echo "NPTL support      $nptl"
 echo "vde support       $vde"
+echo "gtk support       $gtk"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -1097,6 +1116,12 @@ if test "$vde" = "yes" ; then
   echo "#define CONFIG_VDE 1" >> $config_h
   echo "VDE_LIBS=-lvdeplug" >> $config_mak
 fi
+if test "$gtk" = "yes" ; then
+  echo "CONFIG_GTK=yes" >> $config_mak
+  echo "#define CONFIG_GTK 1" >> $config_h
+  echo "GTK_CFLAGS=$gtk_cflags" >> $config_mak
+  echo "GTK_LIBS=$gtk_libs" >> $config_mak
+fi
 for card in $audio_card_list; do
     def=CONFIG_`echo $card | tr '[:lower:]' '[:upper:]'`
     echo "$def=yes" >> $config_mak
diff --git a/console.h b/console.h
index e852dd1..92de255 100644
--- a/console.h
+++ b/console.h
@@ -140,6 +140,11 @@ void qemu_console_resize(QEMUConsole *console, int width, int height);
 /* sdl.c */
 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
 
+/* gtk.c */
+void gtk_display_init(DisplayState *ds, int *argc, char ***argv);
+
+void gtk_display_main_loop(DisplayState *ds, int (*func)(void));
+
 /* cocoa.m */
 void cocoa_display_init(DisplayState *ds, int full_screen);
 
diff --git a/gdk_keysym.h b/gdk_keysym.h
new file mode 100644
index 0000000..2dce2ad
--- /dev/null
+++ b/gdk_keysym.h
@@ -0,0 +1,280 @@
+typedef struct {
+	const char* name;
+	int keysym;
+} name2keysym_t;
+static name2keysym_t name2keysym[]={
+/* ascii */
+    { "space",                GDK_space},
+    { "exclam",               GDK_exclam},
+    { "quotedbl",             GDK_quotedbl},
+    { "numbersign",           GDK_numbersign},
+    { "dollar",               GDK_dollar},
+    { "percent",              GDK_percent},
+    { "ampersand",            GDK_ampersand},
+    { "apostrophe",           GDK_apostrophe},
+    { "parenleft",            GDK_parenleft},
+    { "parenright",           GDK_parenright},
+    { "asterisk",             GDK_asterisk},
+    { "plus",                 GDK_plus},
+    { "comma",                GDK_comma},
+    { "minus",                GDK_minus},
+    { "period",               GDK_period},
+    { "slash",                GDK_slash},
+    { "0",                    GDK_0},
+    { "1",                    GDK_1},
+    { "2",                    GDK_2},
+    { "3",                    GDK_3},
+    { "4",                    GDK_4},
+    { "5",                    GDK_5},
+    { "6",                    GDK_6},
+    { "7",                    GDK_7},
+    { "8",                    GDK_8},
+    { "9",                    GDK_9},
+    { "colon",                GDK_colon},
+    { "semicolon",            GDK_semicolon},
+    { "less",                 GDK_less},
+    { "equal",                GDK_equal},
+    { "greater",              GDK_greater},
+    { "question",             GDK_question},
+    { "at",                   GDK_at},
+    { "A",                    GDK_A},
+    { "B",                    GDK_B},
+    { "C",                    GDK_C},
+    { "D",                    GDK_D},
+    { "E",                    GDK_E},
+    { "F",                    GDK_F},
+    { "G",                    GDK_G},
+    { "H",                    GDK_H},
+    { "I",                    GDK_I},
+    { "J",                    GDK_J},
+    { "K",                    GDK_K},
+    { "L",                    GDK_L},
+    { "M",                    GDK_M},
+    { "N",                    GDK_N},
+    { "O",                    GDK_O},
+    { "P",                    GDK_P},
+    { "Q",                    GDK_Q},
+    { "R",                    GDK_R},
+    { "S",                    GDK_S},
+    { "T",                    GDK_T},
+    { "U",                    GDK_U},
+    { "V",                    GDK_V},
+    { "W",                    GDK_W},
+    { "X",                    GDK_X},
+    { "Y",                    GDK_Y},
+    { "Z",                    GDK_Z},
+    { "bracketleft",          GDK_bracketleft},
+    { "backslash",            GDK_backslash},
+    { "bracketright",         GDK_bracketright},
+    { "asciicircum",          GDK_asciicircum},
+    { "underscore",           GDK_underscore},
+    { "grave",                GDK_grave},
+    { "a",                    GDK_a},
+    { "b",                    GDK_b},
+    { "c",                    GDK_c},
+    { "d",                    GDK_d},
+    { "e",                    GDK_e},
+    { "f",                    GDK_f},
+    { "g",                    GDK_g},
+    { "h",                    GDK_h},
+    { "i",                    GDK_i},
+    { "j",                    GDK_j},
+    { "k",                    GDK_k},
+    { "l",                    GDK_l},
+    { "m",                    GDK_m},
+    { "n",                    GDK_n},
+    { "o",                    GDK_o},
+    { "p",                    GDK_p},
+    { "q",                    GDK_q},
+    { "r",                    GDK_r},
+    { "s",                    GDK_s},
+    { "t",                    GDK_t},
+    { "u",                    GDK_u},
+    { "v",                    GDK_v},
+    { "w",                    GDK_w},
+    { "x",                    GDK_x},
+    { "y",                    GDK_y},
+    { "z",                    GDK_z},
+    { "braceleft",            GDK_braceleft},
+    { "bar",                  GDK_bar},
+    { "braceright",           GDK_braceright},
+    { "asciitilde",           GDK_asciitilde},
+
+/* latin 1 extensions */
+{ "nobreakspace",         GDK_nobreakspace},
+{ "exclamdown",           GDK_exclamdown},
+{ "cent",         	  GDK_cent},
+{ "sterling",             GDK_sterling},
+{ "currency",             GDK_currency},
+{ "yen",                  GDK_yen},
+{ "brokenbar",            GDK_brokenbar},
+{ "section",              GDK_section},
+{ "diaeresis",            GDK_diaeresis},
+{ "copyright",            GDK_copyright},
+{ "ordfeminine",          GDK_ordfeminine},
+{ "guillemotleft",        GDK_guillemotleft},
+{ "notsign",              GDK_notsign},
+{ "hyphen",               GDK_hyphen},
+{ "registered",           GDK_registered},
+{ "macron",               GDK_macron},
+{ "degree",               GDK_degree},
+{ "plusminus",            GDK_plusminus},
+{ "twosuperior",          GDK_twosuperior},
+{ "threesuperior",        GDK_threesuperior},
+{ "acute",                GDK_acute},
+{ "mu",                   GDK_mu},
+{ "paragraph",            GDK_paragraph},
+{ "periodcentered",       GDK_periodcentered},
+{ "cedilla",              GDK_cedilla},
+{ "onesuperior",          GDK_onesuperior},
+{ "masculine",            GDK_masculine},
+{ "guillemotright",       GDK_guillemotright},
+{ "onequarter",           GDK_onequarter},
+{ "onehalf",              GDK_onehalf},
+{ "threequarters",        GDK_threequarters},
+{ "questiondown",         GDK_questiondown},
+{ "Agrave",               GDK_Agrave},
+{ "Aacute",               GDK_Aacute},
+{ "Acircumflex",          GDK_Acircumflex},
+{ "Atilde",               GDK_Atilde},
+{ "Adiaeresis",           GDK_Adiaeresis},
+{ "Aring",                GDK_Aring},
+{ "AE",                   GDK_AE},
+{ "Ccedilla",             GDK_Ccedilla},
+{ "Egrave",               GDK_Egrave},
+{ "Eacute",               GDK_Eacute},
+{ "Ecircumflex",          GDK_Ecircumflex},
+{ "Ediaeresis",           GDK_Ediaeresis},
+{ "Igrave",               GDK_Igrave},
+{ "Iacute",               GDK_Iacute},
+{ "Icircumflex",          GDK_Icircumflex},
+{ "Idiaeresis",           GDK_Idiaeresis},
+{ "ETH",                  GDK_ETH},
+{ "Eth",                  GDK_Eth},
+{ "Ntilde",               GDK_Ntilde},
+{ "Ograve",               GDK_Ograve},
+{ "Oacute",               GDK_Oacute},
+{ "Ocircumflex",          GDK_Ocircumflex},
+{ "Otilde",               GDK_Otilde},
+{ "Odiaeresis",           GDK_Odiaeresis},
+{ "multiply",             GDK_multiply},
+{ "Ooblique",             GDK_Ooblique},
+{ "Oslash",               GDK_Oslash},
+{ "Ugrave",               GDK_Ugrave},
+{ "Uacute",               GDK_Uacute},
+{ "Ucircumflex",          GDK_Ucircumflex},
+{ "Udiaeresis",           GDK_Udiaeresis},
+{ "Yacute",               GDK_Yacute},
+{ "THORN",                GDK_THORN},
+{ "Thorn",                GDK_Thorn},
+{ "ssharp",               GDK_ssharp},
+{ "agrave",               GDK_agrave},
+{ "aacute",               GDK_aacute},
+{ "acircumflex",          GDK_acircumflex},
+{ "atilde",               GDK_atilde},
+{ "adiaeresis",           GDK_adiaeresis},
+{ "aring",                GDK_aring},
+{ "ae",                   GDK_ae},
+{ "ccedilla",             GDK_ccedilla},
+{ "egrave",               GDK_egrave},
+{ "eacute",               GDK_eacute},
+{ "ecircumflex",          GDK_ecircumflex},
+{ "ediaeresis",           GDK_ediaeresis},
+{ "igrave",               GDK_igrave},
+{ "iacute",               GDK_iacute},
+{ "icircumflex",          GDK_icircumflex},
+{ "idiaeresis",           GDK_idiaeresis},
+{ "eth",                  GDK_eth},
+{ "ntilde",               GDK_ntilde},
+{ "ograve",               GDK_ograve},
+{ "oacute",               GDK_oacute},
+{ "ocircumflex",          GDK_ocircumflex},
+{ "otilde",               GDK_otilde},
+{ "odiaeresis",           GDK_odiaeresis},
+{ "division",             GDK_division},
+{ "oslash",               GDK_oslash},
+{ "ooblique",             GDK_ooblique},
+{ "ugrave",               GDK_ugrave},
+{ "uacute",               GDK_uacute},
+{ "ucircumflex",          GDK_ucircumflex},
+{ "udiaeresis",           GDK_udiaeresis},
+{ "yacute",               GDK_yacute},
+{ "thorn",                GDK_thorn},
+{ "ydiaeresis",           GDK_ydiaeresis},
+{"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},
+{"Super_L", GDK_Super_L},
+{"Super_R", GDK_Super_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},
+#if 0
+{"Power", GDK_Power},
+#endif
+{"Print", GDK_Print},
+{"Mode_switch", GDK_Mode_switch},
+{"Multi_Key", GDK_Multi_key},
+{"Num_Lock", GDK_Num_Lock},
+{"Pause", GDK_Pause},
+{"Escape", GDK_Escape},
+
+{0,0},
+};
diff --git a/gtk.c b/gtk.c
new file mode 100644
index 0000000..9d45bef
--- /dev/null
+++ b/gtk.c
@@ -0,0 +1,356 @@
+/*
+ * GTK Front-end support for QEMU
+ *
+ * Copyright IBM, Corp. 2008
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "console.h"
+#include "sysemu.h"
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+typedef struct GtkDisplayState
+{
+    DisplayState *ds;
+    GtkWidget *window;
+    GtkWidget *widget;
+    GdkImage *image;
+    GdkGC *gc;
+    gint mouse_x, mouse_y;
+    gint mouse_buttons;
+} GtkDisplayState;
+
+static void gtk_dpy_update(DisplayState *ds, int x, int y, int w, int h)
+{
+    GtkDisplayState *s = ds->opaque;
+
+    /* Queuing the drawing area will cause an expose event to occur which is
+     * where we really draw the screen */
+    gtk_widget_queue_draw_area(s->widget, x, y, w, h);
+}
+
+static void gtk_dpy_resize(DisplayState *ds, int w, int h)
+{
+    GtkDisplayState *s = ds->opaque;
+    GdkVisual *visual;
+
+    /* Free old buffer if we have to */
+    if (s->image) {
+        g_object_unref(s->image);
+        s->image = NULL;
+    }
+    ds->data = NULL;
+
+    /* Initialize new buffer */
+    ds->width = w;
+    ds->height = h;
+
+    /* FIXME valid all DisplayState assumptions */
+    visual = gtk_widget_get_visual(s->widget);
+    s->image = gdk_image_new(GDK_IMAGE_FASTEST, visual, ds->width, ds->height);
+    ds->depth = s->image->bpp * 8;
+    ds->linesize = s->image->bpl;
+    if (s->image->byte_order == GDK_MSB_FIRST)
+        ds->bgr = 1;
+    else
+        ds->bgr = 0;
+    ds->data = s->image->mem;
+
+    /* Set the size of the widget being used to display the VGA screen. */
+    gtk_widget_set_size_request(s->widget, ds->width, ds->height);
+}
+
+static void update_caption(GtkDisplayState *s)
+{
+    char buf[1024];
+    const char *status = "";
+
+    if (!vm_running)
+        status = " [Stopped]";
+#if 0
+    else if (gui_grab)
+        status = " - Press Ctrl-Alt to exit grab";
+#endif
+
+    if (qemu_name)
+        snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
+    else
+        snprintf(buf, sizeof(buf), "QEMU%s", status);
+
+    gtk_window_set_title(GTK_WINDOW(s->window), buf);
+}
+
+static void gtk_dpy_refresh(DisplayState *ds)
+{
+    GtkDisplayState *s = ds->opaque;
+    static int last_vm_running = -1;
+
+    if (last_vm_running != vm_running) {
+        last_vm_running = vm_running;
+        update_caption(s);
+    }
+
+    vga_hw_update();
+
+    while (gtk_events_pending()) {
+        if (gtk_main_iteration()) {
+            /* GTK main loop has been exited */
+            qemu_system_shutdown_request();
+            vm_start();
+            break;
+        }
+    }
+}
+
+static gboolean gtk_dpy_expose(GtkWidget *widget, GdkEventExpose *expose,
+                               gpointer opaque)
+{
+    GtkDisplayState *s = opaque;
+    gint x, y, w, h;
+
+    /* The widget may be exposed before we are ready to go.  Be defensive */
+    if (widget->window == NULL || s->image == NULL)
+        return FALSE;
+
+    /* Create a graphics context if we need to */
+    if (s->gc == NULL)
+        s->gc = gdk_gc_new(widget->window);
+
+    /* Clip expose area to DisplayState */
+    x = MIN(expose->area.x, s->ds->width);
+    y = MIN(expose->area.y, s->ds->height);
+    w = MIN(expose->area.x + expose->area.width, s->ds->width);
+    h = MIN(expose->area.y + expose->area.height, s->ds->height);
+    w -= x;
+    h -= y;
+
+    /* Draw screen */
+    gdk_draw_image(widget->window, s->gc, s->image, x, y, x, y, w, h);
+
+    return TRUE;
+}
+
+#include "gdk_keysym.h"
+#include "keymaps.c"
+
+static kbd_layout_t *kbd_layout;
+
+static uint8_t gtk_keyevent_to_keycode_generic(GdkEventKey *key)
+{
+    return keysym2scancode(kbd_layout, key->keyval);
+}
+
+static uint8_t gtk_keyevent_to_keycode(GdkEventKey *key)
+{
+    int keycode;
+
+    keycode = key->hardware_keycode;
+
+    if (keycode < 9) {
+        keycode = 0;
+    } else if (keycode < 97) {
+        keycode -= 8;
+    } else if (keycode < 212) {
+        keycode = _translate_keycode(keycode - 97);
+    } else {
+        keycode = 0;
+    }
+
+    return keycode;
+}
+
+static gboolean gtk_dpy_key(GtkWidget *widget, GdkEventKey *key,
+                            gpointer opaque)
+{
+    int keycode, v;
+
+    if (key->keyval == GDK_Pause) {
+        v = 0;
+        if (key->type == GDK_KEY_PRESS)
+            v |= 0x80;
+        kbd_put_keycode(0xe1);
+        kbd_put_keycode(0x1d | v);
+        kbd_put_keycode(0x45 | v);
+        return TRUE;
+    }
+
+    if (kbd_layout)
+        keycode = gtk_keyevent_to_keycode_generic(key);
+    else
+        keycode = gtk_keyevent_to_keycode(key);
+
+    if (keycode & 0x80)
+        kbd_put_keycode(0xe0);
+    if (key->type == GDK_KEY_RELEASE)
+        kbd_put_keycode(keycode | 0x80);
+    else
+        kbd_put_keycode(keycode & 0x7f);
+
+    return TRUE;
+}
+
+static gboolean gtk_dpy_motion(GtkWidget *widget, GdkEventMotion *motion,
+                               gpointer opaque)
+{
+    GtkDisplayState *s = opaque;
+    int dx, dy;
+
+    if (kbd_mouse_is_absolute()) {
+        dx = (gint)motion->x * 0x7FFF / (s->ds->width - 1);
+        dy = (gint)motion->y * 0x7FFF / (s->ds->height - 1);
+    } else {
+        dx = (gint)motion->x - s->mouse_x;
+        dy = (gint)motion->y - s->mouse_y;
+    }
+
+    s->mouse_x = (gint)motion->x;
+    s->mouse_y = (gint)motion->y;
+
+    kbd_mouse_event(dx, dy, 0, s->mouse_buttons);
+
+    return TRUE;
+}
+
+static gboolean gtk_dpy_button(GtkWidget *widget, GdkEventButton *button,
+                               gpointer opaque)
+{
+    GtkDisplayState *s = opaque;
+    gint mask;
+
+    mask = 0;
+    if (button->button == 1)
+        mask |= MOUSE_EVENT_LBUTTON;
+    else if (button->button == 2)
+        mask |= MOUSE_EVENT_MBUTTON;
+    else if (button->button == 3)
+        mask |= MOUSE_EVENT_RBUTTON;
+
+    /* make sure to ignore double and triple clicks */
+    if (button->type == GDK_BUTTON_PRESS)
+        s->mouse_buttons |= mask;
+    else if (button->type == GDK_BUTTON_RELEASE)
+        s->mouse_buttons &= ~mask;
+
+    if (kbd_mouse_is_absolute())
+        kbd_mouse_event(s->mouse_x, s->mouse_y, 0, s->mouse_buttons);
+    else
+        kbd_mouse_event(0, 0, 0, s->mouse_buttons);
+
+    return TRUE;
+}
+
+static gboolean gtk_dpy_scroll(GtkWidget *widget, GdkEventScroll *scroll,
+                               gpointer opaque)
+{
+    GtkDisplayState *s = opaque;
+    gint dz = 0;
+
+    if (scroll->direction == GDK_SCROLL_UP)
+        dz = -1;
+    else if (scroll->direction == GDK_SCROLL_DOWN)
+        dz = 1;
+
+    if (kbd_mouse_is_absolute())
+        kbd_mouse_event(s->mouse_x, s->mouse_y, dz, s->mouse_buttons);
+    else
+        kbd_mouse_event(0, 0, dz, s->mouse_buttons);
+
+    return TRUE;
+}
+
+void gtk_display_init(DisplayState *ds, int *argc, char ***argv)
+{
+    GtkDisplayState *s;
+
+    gtk_init(argc, argv);
+
+    if (keyboard_layout) {
+        kbd_layout = init_keyboard_layout(keyboard_layout);
+        if (!kbd_layout)
+            exit(1);
+    }
+
+    s = qemu_mallocz(sizeof(*s));
+    if (s == NULL) {
+        fprintf(stderr, "failed to allocate GtkDisplayState\n");
+        exit(1);
+    }
+
+    s->ds = ds;
+    s->widget = gtk_drawing_area_new();
+    s->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_resizable(GTK_WINDOW(s->window), FALSE);
+    gtk_container_add(GTK_CONTAINER(s->window), s->widget);
+    gtk_widget_show_all(s->window);
+
+    gtk_signal_connect(GTK_OBJECT(s->widget), "key-press-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_key), s);
+    gtk_signal_connect(GTK_OBJECT(s->widget), "key-release-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_key), s);
+    gtk_signal_connect(GTK_OBJECT(s->widget), "motion-notify-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_motion), s);
+    gtk_signal_connect(GTK_OBJECT(s->widget), "button-press-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_button), s);
+    gtk_signal_connect(GTK_OBJECT(s->widget), "button-release-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_button), s);
+    gtk_signal_connect(GTK_OBJECT(s->widget), "scroll-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_scroll), s);
+    gtk_signal_connect(GTK_OBJECT(s->widget), "expose-event",
+                       GTK_SIGNAL_FUNC(gtk_dpy_expose), s);
+    gtk_signal_connect(GTK_OBJECT(s->window), "delete-event",
+                       GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
+
+    GTK_WIDGET_SET_FLAGS(s->widget, GTK_CAN_FOCUS);
+
+    gtk_widget_add_events(s->widget,
+                          GDK_POINTER_MOTION_MASK |
+                          GDK_BUTTON_PRESS_MASK |
+                          GDK_BUTTON_RELEASE_MASK |
+                          GDK_BUTTON_MOTION_MASK |
+                          GDK_SCROLL_MASK |
+                          GDK_KEY_PRESS_MASK |
+                          GDK_KEY_RELEASE_MASK);
+
+    gtk_widget_set_double_buffered(s->widget, FALSE);
+    gtk_widget_grab_focus(s->widget);
+
+    ds->dpy_update = gtk_dpy_update;
+    ds->dpy_resize = gtk_dpy_resize;
+    ds->dpy_refresh = gtk_dpy_refresh;
+    ds->opaque = s;
+
+    gtk_dpy_resize(ds, 640, 480);
+    update_caption(s);
+}
+
+/* GTK has it's own main loop and while it provides a mechanism to
+ * asynchronously iterate the main loop, assumes that these methods are being
+ * called from something invoked by the main loop.  To work around this, we
+ * register an idle callback that runs the QEMU main loop, and then we use the
+ * asynchronous iteration functions from the refresh callback.  This makes GTK
+ * happy while allowing QEMU to control the main loop. */
+static gboolean run_main_loop(gpointer opaque)
+{
+    void (*func)(void);
+
+    func = opaque;
+    func();
+    return FALSE;
+}
+
+/* @func is the QEMU main loop.  We pass in as a function pointer to avoid
+ * exporting the function from vl.c */
+void gtk_display_main_loop(DisplayState *ds, int (*func)(void))
+{
+    g_idle_add(run_main_loop, func);
+    gtk_main();
+}
diff --git a/hw/ps2.c b/hw/ps2.c
index 054b92f..daccc93 100644
--- a/hw/ps2.c
+++ b/hw/ps2.c
@@ -284,6 +284,8 @@ static void ps2_mouse_send_packet(PS2MouseState *s)
     unsigned int b;
     int dx1, dy1, dz1;
 
+    printf("sending packet\n");
+
     dx1 = s->mouse_dx;
     dy1 = s->mouse_dy;
     dz1 = s->mouse_dz;
@@ -332,6 +334,8 @@ static void ps2_mouse_event(void *opaque,
 {
     PS2MouseState *s = opaque;
 
+    printf("status - %d\n", (s->mouse_status & MOUSE_STATUS_ENABLED));
+
     /* check if deltas are recorded when disabled */
     if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
         return;
@@ -345,6 +349,9 @@ static void ps2_mouse_event(void *opaque,
 	return;
     s->mouse_buttons = buttons_state;
 
+    printf("remote: %d\n", !(s->mouse_status & MOUSE_STATUS_REMOTE));
+    printf("queue count %d\n", s->common.queue.count);
+
     if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
         (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
         for(;;) {
@@ -392,6 +399,7 @@ void ps2_write_mouse(void *opaque, int val)
             ps2_queue(&s->common, AUX_ACK);
             break;
         case AUX_SET_STREAM:
+            printf("stream\n");
             s->mouse_status &= ~MOUSE_STATUS_REMOTE;
             ps2_queue(&s->common, AUX_ACK);
             break;
@@ -400,6 +408,7 @@ void ps2_write_mouse(void *opaque, int val)
             ps2_queue(&s->common, AUX_ACK);
             break;
         case AUX_SET_REMOTE:
+            printf("remote\n");
             s->mouse_status |= MOUSE_STATUS_REMOTE;
             ps2_queue(&s->common, AUX_ACK);
             break;
diff --git a/vl.c b/vl.c
index 03cd386..0410bff 100644
--- a/vl.c
+++ b/vl.c
@@ -9012,7 +9012,9 @@ int main(int argc, char **argv)
     } else
 #endif
     {
-#if defined(CONFIG_SDL)
+#if defined(CONFIG_GTK)
+        gtk_display_init(ds, &argc, &argv);
+#elif defined(CONFIG_SDL)
         sdl_display_init(ds, full_screen, no_frame);
 #elif defined(CONFIG_COCOA)
         cocoa_display_init(ds, full_screen);
@@ -9146,7 +9148,11 @@ int main(int argc, char **argv)
 	close(fd);
     }
 
+#if defined(CONFIG_GTK)
+    gtk_display_main_loop(ds, main_loop);
+#else
     main_loop();
+#endif
     quit_timers();
 
 #if !defined(_WIN32)

  reply	other threads:[~2008-09-08  0:13 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-29 15:22 [Qemu-devel] [PATCH] opengl rendering in the sdl window Stefano Stabellini
2008-09-02 16:53 ` Ian Jackson
2008-09-04  3:00 ` Anthony Liguori
2008-09-04  7:41   ` Gerd Hoffmann
2008-09-04  9:42   ` Daniel P. Berrange
2008-09-04 10:06     ` Andreas Färber
2008-09-04 10:20       ` Daniel P. Berrange
2008-09-05 16:42         ` Andreas Färber
2008-09-07  7:51         ` Avi Kivity
2008-09-07  3:07     ` Anthony Liguori
2008-09-07 16:31       ` Daniel P. Berrange
2008-09-08  0:12         ` Anthony Liguori [this message]
2008-09-04 10:06   ` Stefano Stabellini
2008-09-05 12:02     ` Jamie Lokier
2008-09-05 12:11       ` Samuel Thibault
2008-09-06 23:27         ` Jamie Lokier
2008-09-07 14:22           ` Samuel Thibault
2008-09-07 14:36             ` Paul Brook
2008-09-07 14:42               ` Samuel Thibault
2008-09-07 15:03                 ` Paul Brook
2008-09-07 15:12                   ` Samuel Thibault
2008-09-07 15:35                     ` Paul Brook
2008-09-07 15:41                       ` Samuel Thibault
2008-09-07 15:57                         ` Paul Brook
2008-09-08  0:08                         ` Anthony Liguori
2008-09-08  0:21                           ` Samuel Thibault
2008-09-08  1:18               ` Jamie Lokier
2008-09-08 10:38                 ` Stefano Stabellini
2008-09-08 13:21                   ` Jamie Lokier
2008-09-05 16:44       ` Stefano Stabellini
2008-09-05 16:55         ` Daniel P. Berrange
2008-09-05 17:13           ` Stefano Stabellini
2008-09-07  3:21             ` Anthony Liguori
2008-09-08 10:48               ` Stefano Stabellini
2008-09-08 13:16               ` Jamie Lokier
2008-09-08 13:51                 ` Stefano Stabellini
2008-09-08 13:41               ` Jamie Lokier
2008-09-08 13:48                 ` Daniel P. Berrange
2008-09-08 14:56                   ` Gerd Hoffmann
2008-09-08 15:08                     ` Jamie Lokier
2008-09-08 15:35                       ` Gerd Hoffmann
2008-09-08 15:39                         ` Jamie Lokier
2008-09-08 16:23                           ` Gerd Hoffmann
2008-09-08 16:47                             ` Anthony Liguori
2008-09-08 19:15                               ` Gerd Hoffmann
2008-09-08 19:43                             ` Jamie Lokier
2008-09-08 15:47                       ` Daniel P. Berrange
2008-09-08 16:05                         ` Anthony Liguori
2008-09-08 17:08                           ` Mike Kronenberg
2008-09-08 19:21                             ` Gerd Hoffmann
2008-09-08 21:06                               ` Mike Kronenberg
2008-09-08 19:32                           ` Jamie Lokier
2008-09-08 19:48                           ` Jamie Lokier
2008-09-08 19:57                             ` Anthony Liguori
2008-09-08 20:11                               ` Jamie Lokier
2008-09-08 23:18                         ` Daniel P. Berrange
2008-09-09  0:10                           ` Jamie Lokier
2008-09-09  2:45                             ` Anthony Liguori
2008-09-09  4:17                               ` Jamie Lokier
2008-09-08 14:22                 ` Anthony Liguori
2008-09-07  7:48           ` Avi Kivity
2008-09-07 11:57             ` Daniel P. Berrange
2008-09-07 13:12               ` Avi Kivity
2008-09-08 10:30                 ` Stefano Stabellini
2008-09-08 10:35                   ` Daniel P. Berrange
2008-09-08 10:53                     ` Stefano Stabellini
2008-09-08 11:00                       ` Daniel P. Berrange
2008-09-08 12:38                         ` François Revol
2008-09-08 13:05                           ` Jamie Lokier
2008-09-08 13:08                           ` Anthony Liguori
2008-09-08 13:44                             ` François Revol
2008-09-05 18:11         ` malc
2008-09-04 10:14   ` Stefano Stabellini
2008-09-07  3:09     ` Anthony Liguori
2008-09-04 10:21   ` Andreas Färber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=48C46DF2.2050007@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=berrange@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).