#include "console.h"
#include "sysemu.h"
#include "x_keymap.h"
+#include "sdl_zoom.h"
static DisplayChangeListener *dcl;
static SDL_Surface *real_screen;
static int absolute_enabled = 0;
static int guest_cursor = 0;
static int guest_x, guest_y;
-static SDL_Cursor *guest_sprite = 0;
+static SDL_Cursor *guest_sprite = NULL;
static uint8_t allocator;
-static uint8_t hostbpp;
+static SDL_PixelFormat host_format;
+static int scaling_active = 0;
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
{
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
+ SDL_Rect rec;
+ rec.x = x;
+ rec.y = y;
+ rec.w = w;
+ rec.h = h;
+
if (guest_screen) {
- SDL_Rect rec;
- rec.x = x;
- rec.y = y;
- rec.w = w;
- rec.h = h;
- SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
- }
- SDL_UpdateRect(real_screen, x, y, w, h);
+ if (!scaling_active) {
+ SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
+ } else {
+ if (sdl_zoom_blit(guest_screen, real_screen, SMOOTHING_ON, &rec) < 0) {
+ fprintf(stderr, "Zoom blit failed\n");
+ exit(1);
+ }
+ }
+ }
+ SDL_UpdateRect(real_screen, rec.x, rec.y, rec.w, rec.h);
}
static void sdl_setdata(DisplayState *ds)
// printf("resizing to %d %d\n", w, h);
- flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_RESIZABLE;
if (gui_fullscreen)
flags |= SDL_FULLSCREEN;
if (gui_noframe)
static void sdl_resize(DisplayState *ds)
{
if (!allocator) {
- do_sdl_resize(ds_get_width(ds), ds_get_height(ds), 0);
+ 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) {
surface->width = width;
surface->height = height;
+
+ if (scaling_active) {
+ if (host_format.BytesPerPixel != 2 && host_format.BytesPerPixel != 4) {
+ surface->linesize = width * 4;
+ surface->pf = qemu_default_pixelformat(32);
+ } else {
+ surface->linesize = width * host_format.BytesPerPixel;
+ surface->pf = sdl_to_qemu_pixelformat(&host_format);
+ }
+#ifdef HOST_WORDS_BIGENDIAN
+ surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+#else
+ surface->flags = QEMU_ALLOCATED_FLAG;
+#endif
+ surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
+
+ return surface;
+ }
- if (hostbpp == 16)
+ if (host_format.BitsPerPixel == 16)
do_sdl_resize(width, height, 16);
else
do_sdl_resize(width, height, 32);
surface->linesize = real_screen->pitch;
surface->data = real_screen->pixels;
-#ifdef WORDS_BIGENDIAN
- surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
+#ifdef HOST_WORDS_BIGENDIAN
+ surface->flags = QEMU_REALPIXELS_FLAG | QEMU_BIG_ENDIAN_FLAG;
#else
- surface->flags = QEMU_ALLOCATED_FLAG;
+ surface->flags = QEMU_REALPIXELS_FLAG;
#endif
allocator = 1;
allocator = 0;
if (surface == NULL)
return;
+
+ if (surface->flags & QEMU_ALLOCATED_FLAG)
+ qemu_free(surface->data);
qemu_free(surface);
}
static int check_for_evdev(void)
{
SDL_SysWMinfo info;
- XkbDescPtr desc;
+ XkbDescPtr desc = NULL;
int has_evdev = 0;
- const char *keycodes;
+ char *keycodes = NULL;
SDL_VERSION(&info.version);
- if (!SDL_GetWMInfo(&info))
+ if (!SDL_GetWMInfo(&info)) {
return 0;
-
+ }
desc = XkbGetKeyboard(info.info.x11.display,
XkbGBN_AllComponentsMask,
XkbUseCoreKbd);
- if (desc == NULL || desc->names == NULL)
- return 0;
-
- keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
- if (keycodes == NULL)
- fprintf(stderr, "could not lookup keycode name\n");
- else if (strstart(keycodes, "evdev", NULL))
- has_evdev = 1;
- else if (!strstart(keycodes, "xfree86", NULL))
- fprintf(stderr,
- keycodes);
-
- XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
+ if (desc && desc->names) {
+ keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
+ if (keycodes == NULL) {
+ fprintf(stderr, "could not lookup keycode name\n");
+ } else if (strstart(keycodes, "evdev", NULL)) {
+ has_evdev = 1;
+ } else if (!strstart(keycodes, "xfree86", NULL)) {
+ fprintf(stderr, "unknown keycodes `%s', please report to "
+ }
+ }
+ if (desc) {
+ XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
+ }
+ if (keycodes) {
+ XFree(keycodes);
+ }
return has_evdev;
}
#else
static void sdl_update_caption(void)
{
- char buf[1024];
+ char win_title[1024];
+ char icon_title[1024];
const char *status = "";
if (!vm_running)
status = " [Stopped]";
else if (gui_grab) {
- if (!alt_grab)
- status = " - Press Ctrl-Alt to exit grab";
- else
+ if (alt_grab)
status = " - Press Ctrl-Alt-Shift to exit grab";
+ else if (ctrl_grab)
+ status = " - Press Right-Ctrl to exit grab";
+ else
+ status = " - Press Ctrl-Alt to exit grab";
}
- if (qemu_name)
- snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
- else
- snprintf(buf, sizeof(buf), "QEMU%s", status);
+ if (qemu_name) {
+ snprintf(win_title, sizeof(win_title), "QEMU (%s)%s", qemu_name, status);
+ snprintf(icon_title, sizeof(icon_title), "QEMU (%s)", qemu_name);
+ } else {
+ snprintf(win_title, sizeof(win_title), "QEMU%s", status);
+ snprintf(icon_title, sizeof(icon_title), "QEMU");
+ }
- SDL_WM_SetCaption(buf, "QEMU");
+ SDL_WM_SetCaption(win_title, icon_title);
}
static void sdl_hide_cursor(void)
static void toggle_full_screen(DisplayState *ds)
{
gui_fullscreen = !gui_fullscreen;
- do_sdl_resize(real_screen->w, real_screen->h, real_screen->format->BitsPerPixel);
if (gui_fullscreen) {
+ scaling_active = 0;
gui_saved_grab = gui_grab;
sdl_grab_start();
} else {
case SDL_KEYDOWN:
case SDL_KEYUP:
if (ev->type == SDL_KEYDOWN) {
- if (!alt_grab) {
- mod_state = (SDL_GetModState() & gui_grab_code) ==
- gui_grab_code;
- } else {
+ if (alt_grab) {
mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
(gui_grab_code | KMOD_LSHIFT);
+ } else if (ctrl_grab) {
+ mod_state = (SDL_GetModState() & KMOD_RCTRL) == KMOD_RCTRL;
+ } else {
+ mod_state = (SDL_GetModState() & gui_grab_code) ==
+ gui_grab_code;
}
gui_key_modifier_pressed = mod_state;
if (gui_key_modifier_pressed) {
toggle_full_screen(ds);
gui_keysym = 1;
break;
+ case 0x16: /* 'u' key on US keyboard */
+ scaling_active = 0;
+ sdl_resize(ds);
+ vga_hw_invalidate();
+ vga_hw_update();
+ break;
case 0x02 ... 0x0a: /* '1' to '9' keys */
/* Reset the modifiers sent to the current console */
reset_keys();
}
}
break;
+ case SDL_VIDEORESIZE:
+ {
+ SDL_ResizeEvent *rev = &ev->resize;
+ int bpp = real_screen->format->BitsPerPixel;
+ if (bpp != 16 && bpp != 32)
+ bpp = 32;
+ do_sdl_resize(rev->w, rev->h, bpp);
+ scaling_active = 1;
+ if (!is_buffer_shared(ds->surface)) {
+ ds->surface = qemu_resize_displaysurface(ds, ds_get_width(ds), ds_get_height(ds));
+ dpy_resize(ds);
+ }
+ vga_hw_invalidate();
+ vga_hw_update();
+ break;
+ }
default:
break;
}
line = image;
for (x = 0; x < width; x ++, dst ++) {
switch (bpp) {
+ case 32:
+ src = *(line ++); src |= *(line ++); src |= *(line ++); line++;
+ break;
case 24:
src = *(line ++); src |= *(line ++); src |= *(line ++);
break;
exit(1);
}
vi = SDL_GetVideoInfo();
- hostbpp = vi->vfmt->BitsPerPixel;
+ host_format = *(vi->vfmt);
dcl = qemu_mallocz(sizeof(DisplayChangeListener));
dcl->dpy_update = sdl_update;