/*
* QEMU SDL display driver
- *
+ *
* 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
static SDL_Cursor *sdl_cursor_normal;
static SDL_Cursor *sdl_cursor_hidden;
static int absolute_enabled = 0;
+static int guest_cursor = 0;
+static int guest_x, guest_y;
+static SDL_Cursor *guest_sprite = 0;
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
{
ds->data = screen->pixels;
ds->linesize = screen->pitch;
ds->depth = screen->format->BitsPerPixel;
- if (ds->depth == 32 && screen->format->Rshift == 0) {
+ if (screen->format->Bshift > screen->format->Rshift) {
ds->bgr = 1;
} else {
ds->bgr = 0;
if (!vm_running)
status = " [Stopped]";
- else if (gui_grab)
- status = " - Press Ctrl-Alt to exit grab";
+ else if (gui_grab) {
+ if (!alt_grab)
+ status = " - Press Ctrl-Alt to exit grab";
+ else
+ status = " - Press Ctrl-Alt-Shift to exit grab";
+ }
if (qemu_name)
snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
static void sdl_hide_cursor(void)
{
+ if (!cursor_hide)
+ return;
+
if (kbd_mouse_is_absolute()) {
SDL_ShowCursor(1);
SDL_SetCursor(sdl_cursor_hidden);
static void sdl_show_cursor(void)
{
+ if (!cursor_hide)
+ return;
+
if (!kbd_mouse_is_absolute()) {
SDL_ShowCursor(1);
- SDL_SetCursor(sdl_cursor_normal);
+ if (guest_cursor &&
+ (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
+ SDL_SetCursor(guest_sprite);
+ else
+ SDL_SetCursor(sdl_cursor_normal);
}
}
static void sdl_grab_start(void)
{
- sdl_hide_cursor();
+ if (guest_cursor) {
+ SDL_SetCursor(guest_sprite);
+ SDL_WarpMouse(guest_x, guest_y);
+ } else
+ sdl_hide_cursor();
SDL_WM_GrabInput(SDL_GRAB_ON);
/* dummy read to avoid moving the mouse */
SDL_GetRelativeMouseState(NULL, NULL);
static void sdl_grab_end(void)
{
SDL_WM_GrabInput(SDL_GRAB_OFF);
- sdl_show_cursor();
gui_grab = 0;
+ sdl_show_cursor();
sdl_update_caption();
}
} else if (absolute_enabled) {
sdl_show_cursor();
absolute_enabled = 0;
+ } else if (guest_cursor) {
+ SDL_GetMouseState(&dx, &dy);
+ dx -= guest_x;
+ dy -= guest_y;
+ guest_x += dx;
+ guest_y += dy;
}
kbd_mouse_event(dx, dy, dz, buttons);
{
SDL_Event ev1, *ev = &ev1;
int mod_state;
-
+
if (last_vm_running != vm_running) {
last_vm_running = vm_running;
sdl_update_caption();
case SDL_KEYDOWN:
case SDL_KEYUP:
if (ev->type == SDL_KEYDOWN) {
- mod_state = (SDL_GetModState() & gui_grab_code) ==
- gui_grab_code;
+ if (!alt_grab) {
+ mod_state = (SDL_GetModState() & gui_grab_code) ==
+ gui_grab_code;
+ } else {
+ mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
+ (gui_grab_code | KMOD_LSHIFT);
+ }
gui_key_modifier_pressed = mod_state;
if (gui_key_modifier_pressed) {
int keycode;
toggle_full_screen(ds);
gui_keysym = 1;
break;
- case 0x02 ... 0x0a: /* '1' to '9' keys */
+ case 0x02 ... 0x0a: /* '1' to '9' keys */
/* Reset the modifiers sent to the current console */
reset_keys();
console_select(keycode - 0x02);
case SDLK_END: keysym = QEMU_KEY_END; break;
case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
- case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
+ case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break;
+ case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
default: break;
}
}
}
}
} else if (ev->type == SDL_KEYUP) {
- mod_state = (ev->key.keysym.mod & gui_grab_code);
+ if (!alt_grab) {
+ mod_state = (ev->key.keysym.mod & gui_grab_code);
+ } else {
+ mod_state = (ev->key.keysym.mod &
+ (gui_grab_code | KMOD_LSHIFT));
+ }
if (!mod_state) {
if (gui_key_modifier_pressed) {
gui_key_modifier_pressed = 0;
}
}
}
- if (is_graphic_console() && !gui_keysym)
+ if (is_graphic_console() && !gui_keysym)
sdl_process_key(&ev->key);
break;
case SDL_QUIT:
if (!no_quit) {
- qemu_system_shutdown_request();
+ qemu_system_shutdown_request();
+ vm_start(); /* In case we're paused */
}
break;
case SDL_MOUSEMOTION:
} else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
dz = 1;
}
-#endif
+#endif
sdl_send_mouse_event(dz);
}
}
}
}
-static void sdl_cleanup(void)
+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(screen, &dst, c);
+}
+
+static void sdl_mouse_warp(int x, int y, int on)
+{
+ if (on) {
+ if (!guest_cursor)
+ sdl_show_cursor();
+ if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
+ SDL_SetCursor(guest_sprite);
+ SDL_WarpMouse(x, y);
+ }
+ } else if (gui_grab)
+ sdl_hide_cursor();
+ guest_cursor = on;
+ guest_x = x, guest_y = y;
+}
+
+static void sdl_mouse_define(int width, int height, int bpp,
+ int hot_x, int hot_y,
+ uint8_t *image, uint8_t *mask)
+{
+ uint8_t sprite[256], *line;
+ int x, y, dst, bypl, src = 0;
+ if (guest_sprite)
+ SDL_FreeCursor(guest_sprite);
+
+ memset(sprite, 0, 256);
+ bypl = ((width * bpp + 31) >> 5) << 2;
+ for (y = 0, dst = 0; y < height; y ++, image += bypl) {
+ line = image;
+ for (x = 0; x < width; x ++, dst ++) {
+ switch (bpp) {
+ case 24:
+ src = *(line ++); src |= *(line ++); src |= *(line ++);
+ break;
+ case 16:
+ case 15:
+ src = *(line ++); src |= *(line ++);
+ break;
+ case 8:
+ src = *(line ++);
+ break;
+ case 4:
+ src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
+ break;
+ case 2:
+ src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
+ break;
+ case 1:
+ src = 1 & (line[x >> 3] >> (x & 7));
+ break;
+ }
+ if (!src)
+ sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
+ }
+ }
+ guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
+
+ if (guest_cursor &&
+ (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
+ SDL_SetCursor(guest_sprite);
+}
+
+static void sdl_cleanup(void)
{
+ if (guest_sprite)
+ SDL_FreeCursor(guest_sprite);
SDL_Quit();
}
ds->dpy_update = sdl_update;
ds->dpy_resize = sdl_resize;
ds->dpy_refresh = sdl_refresh;
+ ds->dpy_fill = sdl_fill;
+ ds->mouse_set = sdl_mouse_warp;
+ ds->cursor_define = sdl_mouse_define;
sdl_resize(ds, 640, 400);
sdl_update_caption();