X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/c35734b2a6f9b028edacd5813ff271728ce2a9e3..7743e588395535f1bc13f4f747069bae43935432:/sdl.c diff --git a/sdl.c b/sdl.c index aa5c669929..cac1a03655 100644 --- a/sdl.c +++ b/sdl.c @@ -1,8 +1,8 @@ /* * 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 @@ -44,6 +44,9 @@ static int width, height; 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) { @@ -84,7 +87,7 @@ static void sdl_resize(DisplayState *ds, 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; @@ -220,8 +223,12 @@ static void sdl_update_caption(void) 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); @@ -233,6 +240,9 @@ static void sdl_update_caption(void) static void sdl_hide_cursor(void) { + if (!cursor_hide) + return; + if (kbd_mouse_is_absolute()) { SDL_ShowCursor(1); SDL_SetCursor(sdl_cursor_hidden); @@ -243,15 +253,26 @@ static void sdl_hide_cursor(void) 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); @@ -262,8 +283,8 @@ static void sdl_grab_start(void) static void sdl_grab_end(void) { SDL_WM_GrabInput(SDL_GRAB_OFF); - sdl_show_cursor(); gui_grab = 0; + sdl_show_cursor(); sdl_update_caption(); } @@ -294,6 +315,12 @@ static void sdl_send_mouse_event(int dz) } 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); @@ -318,7 +345,7 @@ static void sdl_refresh(DisplayState *ds) { SDL_Event ev1, *ev = &ev1; int mod_state; - + if (last_vm_running != vm_running) { last_vm_running = vm_running; sdl_update_caption(); @@ -334,8 +361,13 @@ static void sdl_refresh(DisplayState *ds) 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; @@ -345,7 +377,7 @@ static void sdl_refresh(DisplayState *ds) 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); @@ -384,7 +416,8 @@ static void sdl_refresh(DisplayState *ds) 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; } } @@ -395,7 +428,12 @@ static void sdl_refresh(DisplayState *ds) } } } 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; @@ -422,12 +460,13 @@ static void sdl_refresh(DisplayState *ds) } } } - 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: @@ -455,7 +494,7 @@ static void sdl_refresh(DisplayState *ds) } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) { dz = 1; } -#endif +#endif sdl_send_mouse_event(dz); } } @@ -472,8 +511,77 @@ static void sdl_refresh(DisplayState *ds) } } -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(); } @@ -510,6 +618,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) 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();