]> git.proxmox.com Git - qemu.git/blobdiff - ui/sdl.c
aio: avoid livelock behavior for Win32
[qemu.git] / ui / sdl.c
index 8cafc44e71e95990efd36959faf2a2fbdefb0e6a..37f01b217d890ce386721ffd1bb48c1aba26c653 100644 (file)
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -55,7 +55,6 @@ static int absolute_enabled = 0;
 static int guest_cursor = 0;
 static int guest_x, guest_y;
 static SDL_Cursor *guest_sprite = NULL;
-static uint8_t allocator;
 static SDL_PixelFormat host_format;
 static int scaling_active = 0;
 static Notifier mouse_mode_notifier;
@@ -117,112 +116,13 @@ static void do_sdl_resize(int width, int height, int bpp)
 
 static void sdl_resize(DisplayState *ds)
 {
-    if  (!allocator) {
-        if (!scaling_active)
-            do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
-        else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds))
-            do_sdl_resize(real_screen->w, real_screen->h, ds_get_bits_per_pixel(ds));
-        sdl_setdata(ds);
-    } else {
-        if (guest_screen != NULL) {
-            SDL_FreeSurface(guest_screen);
-            guest_screen = NULL;
-        }
-    }
-}
-
-static PixelFormat sdl_to_qemu_pixelformat(SDL_PixelFormat *sdl_pf)
-{
-    PixelFormat qemu_pf;
-
-    memset(&qemu_pf, 0x00, sizeof(PixelFormat));
-
-    qemu_pf.bits_per_pixel = sdl_pf->BitsPerPixel;
-    qemu_pf.bytes_per_pixel = sdl_pf->BytesPerPixel;
-    qemu_pf.depth = (qemu_pf.bits_per_pixel) == 32 ? 24 : (qemu_pf.bits_per_pixel);
-
-    qemu_pf.rmask = sdl_pf->Rmask;
-    qemu_pf.gmask = sdl_pf->Gmask;
-    qemu_pf.bmask = sdl_pf->Bmask;
-    qemu_pf.amask = sdl_pf->Amask;
-
-    qemu_pf.rshift = sdl_pf->Rshift;
-    qemu_pf.gshift = sdl_pf->Gshift;
-    qemu_pf.bshift = sdl_pf->Bshift;
-    qemu_pf.ashift = sdl_pf->Ashift;
-
-    qemu_pf.rbits = 8 - sdl_pf->Rloss;
-    qemu_pf.gbits = 8 - sdl_pf->Gloss;
-    qemu_pf.bbits = 8 - sdl_pf->Bloss;
-    qemu_pf.abits = 8 - sdl_pf->Aloss;
-
-    qemu_pf.rmax = ((1 << qemu_pf.rbits) - 1);
-    qemu_pf.gmax = ((1 << qemu_pf.gbits) - 1);
-    qemu_pf.bmax = ((1 << qemu_pf.bbits) - 1);
-    qemu_pf.amax = ((1 << qemu_pf.abits) - 1);
-
-    return qemu_pf;
-}
-
-static DisplaySurface* sdl_create_displaysurface(int width, int height)
-{
-    DisplaySurface *surface = (DisplaySurface*) g_malloc0(sizeof(DisplaySurface));
-    if (surface == NULL) {
-        fprintf(stderr, "sdl_create_displaysurface: malloc failed\n");
-        exit(1);
-    }
-
-    surface->width = width;
-    surface->height = height;
-
-    if (scaling_active) {
-        int linesize;
-        PixelFormat pf;
-        if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
-            linesize = width * 4;
-            pf = qemu_default_pixelformat(32);
-        } else {
-            linesize = width * host_format.BytesPerPixel;
-            pf = sdl_to_qemu_pixelformat(&host_format);
-        }
-        qemu_alloc_display(surface, width, height, linesize, pf, 0);
-        return surface;
+    if (!scaling_active) {
+        do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
+    } else if (real_screen->format->BitsPerPixel != ds_get_bits_per_pixel(ds)) {
+        do_sdl_resize(real_screen->w, real_screen->h,
+                      ds_get_bits_per_pixel(ds));
     }
-
-    if (host_format.BitsPerPixel == 16)
-        do_sdl_resize(width, height, 16);
-    else
-        do_sdl_resize(width, height, 32);
-
-    surface->pf = sdl_to_qemu_pixelformat(real_screen->format);
-    surface->linesize = real_screen->pitch;
-    surface->data = real_screen->pixels;
-
-#ifdef HOST_WORDS_BIGENDIAN
-    surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
-#else
-    surface->flags = QEMU_REALPIXELS_FLAG;
-#endif
-    allocator = 1;
-
-    return surface;
-}
-
-static void sdl_free_displaysurface(DisplaySurface *surface)
-{
-    allocator = 0;
-    if (surface == NULL)
-        return;
-
-    if (surface->flags & QEMU_ALLOCATED_FLAG)
-        g_free(surface->data);
-    g_free(surface);
-}
-
-static DisplaySurface* sdl_resize_displaysurface(DisplaySurface *surface, int width, int height)
-{
-    sdl_free_displaysurface(surface);
-    return sdl_create_displaysurface(width, height);
+    sdl_setdata(ds);
 }
 
 /* generic keyboard conversion */
@@ -461,18 +361,23 @@ static void sdl_show_cursor(void)
 
 static void sdl_grab_start(void)
 {
+    /*
+     * If the application is not active, do not try to enter grab state. This
+     * prevents 'SDL_WM_GrabInput(SDL_GRAB_ON)' from blocking all the
+     * application (SDL bug).
+     */
+    if (!(SDL_GetAppState() & SDL_APPINPUTFOCUS)) {
+        return;
+    }
     if (guest_cursor) {
         SDL_SetCursor(guest_sprite);
         if (!kbd_mouse_is_absolute() && !absolute_enabled)
             SDL_WarpMouse(guest_x, guest_y);
     } else
         sdl_hide_cursor();
-
-    if (SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
-        gui_grab = 1;
-        sdl_update_caption();
-    } else
-        sdl_show_cursor();
+    SDL_WM_GrabInput(SDL_GRAB_ON);
+    gui_grab = 1;
+    sdl_update_caption();
 }
 
 static void sdl_grab_end(void)
@@ -483,12 +388,25 @@ static void sdl_grab_end(void)
     sdl_update_caption();
 }
 
+static void absolute_mouse_grab(void)
+{
+    int mouse_x, mouse_y;
+
+    SDL_GetMouseState(&mouse_x, &mouse_y);
+    if (mouse_x > 0 && mouse_x < real_screen->w - 1 &&
+        mouse_y > 0 && mouse_y < real_screen->h - 1) {
+        sdl_grab_start();
+    }
+}
+
 static void sdl_mouse_mode_change(Notifier *notify, void *data)
 {
     if (kbd_mouse_is_absolute()) {
         if (!absolute_enabled) {
-            sdl_grab_start();
             absolute_enabled = 1;
+            if (is_graphic_console()) {
+                absolute_mouse_grab();
+            }
         }
     } else if (absolute_enabled) {
         if (!gui_fullscreen) {
@@ -539,7 +457,7 @@ static void sdl_scale(DisplayState *ds, int width, int height)
     if (!is_buffer_shared(ds->surface)) {
         ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds),
                                                  ds_get_height(ds));
-        dpy_resize(ds);
+        dpy_gfx_resize(ds);
     }
 }
 
@@ -571,19 +489,6 @@ static void toggle_full_screen(DisplayState *ds)
     vga_hw_update();
 }
 
-static void absolute_mouse_grab(void)
-{
-    int mouse_x, mouse_y;
-
-    if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
-        SDL_GetMouseState(&mouse_x, &mouse_y);
-        if (mouse_x > 0 && mouse_x < real_screen->w - 1 &&
-            mouse_y > 0 && mouse_y < real_screen->h - 1) {
-            sdl_grab_start();
-        }
-    }
-}
-
 static void handle_keydown(DisplayState *ds, SDL_Event *ev)
 {
     int mod_state;
@@ -743,11 +648,7 @@ static void handle_keyup(DisplayState *ds, SDL_Event *ev)
         if (gui_keysym == 0) {
             /* exit/enter grab if pressing Ctrl-Alt */
             if (!gui_grab) {
-                /* If the application is not active, do not try to enter grab
-                 * state. It prevents 'SDL_WM_GrabInput(SDL_GRAB_ON)' from
-                 * blocking all the application (SDL bug). */
-                if (is_graphic_console() &&
-                    SDL_GetAppState() & SDL_APPACTIVE) {
+                if (is_graphic_console()) {
                     sdl_grab_start();
                 }
             } else if (!gui_fullscreen) {
@@ -777,7 +678,7 @@ static void handle_mousemotion(DisplayState *ds, SDL_Event *ev)
             ev->motion.x == max_x || ev->motion.y == max_y)) {
             sdl_grab_end();
         }
-        if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS &&
+        if (!gui_grab &&
             (ev->motion.x > 0 && ev->motion.x < max_x &&
             ev->motion.y > 0 && ev->motion.y < max_y)) {
             sdl_grab_start();
@@ -801,8 +702,7 @@ static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
 
     bev = &ev->button;
     if (!gui_grab && !kbd_mouse_is_absolute()) {
-        if (ev->type == SDL_MOUSEBUTTONDOWN &&
-            (bev->button == SDL_BUTTON_LEFT)) {
+        if (ev->type == SDL_MOUSEBUTTONUP && bev->button == SDL_BUTTON_LEFT) {
             /* start grabbing all events */
             sdl_grab_start();
         }
@@ -828,10 +728,14 @@ static void handle_mousebutton(DisplayState *ds, SDL_Event *ev)
 
 static void handle_activation(DisplayState *ds, SDL_Event *ev)
 {
+#ifdef _WIN32
+    /* Disable grab if the window no longer has the focus
+     * (Windows-only workaround) */
     if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
         !ev->active.gain && !gui_fullscreen) {
         sdl_grab_end();
     }
+#endif
     if (!gui_grab && ev->active.gain && is_graphic_console() &&
         (kbd_mouse_is_absolute() || absolute_enabled)) {
         absolute_mouse_grab();
@@ -899,13 +803,7 @@ static void sdl_refresh(DisplayState *ds)
     }
 }
 
-static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
-{
-    SDL_Rect dst = { x, y, w, h };
-    SDL_FillRect(real_screen, &dst, c);
-}
-
-static void sdl_mouse_warp(int x, int y, int on)
+static void sdl_mouse_warp(DisplayState *ds, int x, int y, int on)
 {
     if (on) {
         if (!guest_cursor)
@@ -921,7 +819,7 @@ static void sdl_mouse_warp(int x, int y, int on)
     guest_x = x, guest_y = y;
 }
 
-static void sdl_mouse_define(QEMUCursor *c)
+static void sdl_mouse_define(DisplayState *ds, QEMUCursor *c)
 {
     uint8_t *image, *mask;
     int bpl;
@@ -955,7 +853,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
 {
     int flags;
     uint8_t data = 0;
-    DisplayAllocator *da;
     const SDL_VideoInfo *vi;
     char *filename;
 
@@ -1020,23 +917,14 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
     }
 
     dcl = g_malloc0(sizeof(DisplayChangeListener));
-    dcl->dpy_update = sdl_update;
-    dcl->dpy_resize = sdl_resize;
+    dcl->dpy_gfx_update = sdl_update;
+    dcl->dpy_gfx_resize = sdl_resize;
     dcl->dpy_refresh = sdl_refresh;
-    dcl->dpy_setdata = sdl_setdata;
-    dcl->dpy_fill = sdl_fill;
-    ds->mouse_set = sdl_mouse_warp;
-    ds->cursor_define = sdl_mouse_define;
+    dcl->dpy_gfx_setdata = sdl_setdata;
+    dcl->dpy_mouse_set = sdl_mouse_warp;
+    dcl->dpy_cursor_define = sdl_mouse_define;
     register_displaychangelistener(ds, dcl);
 
-    da = g_malloc0(sizeof(DisplayAllocator));
-    da->create_displaysurface = sdl_create_displaysurface;
-    da->resize_displaysurface = sdl_resize_displaysurface;
-    da->free_displaysurface = sdl_free_displaysurface;
-    if (register_displayallocator(ds, da) == da) {
-        dpy_resize(ds);
-    }
-
     mouse_mode_notifier.notify = sdl_mouse_mode_change;
     qemu_add_mouse_mode_change_notifier(&mouse_mode_notifier);