diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h new file mode 100644 index 0000000000..f56c596e31 --- /dev/null +++ b/include/ui/sdl2.h @@ -0,0 +1,32 @@ +#ifndef SDL2_H +#define SDL2_H + +struct sdl2_console { + DisplayChangeListener dcl; + DisplaySurface *surface; + SDL_Texture *texture; + SDL_Window *real_window; + SDL_Renderer *real_renderer; + int idx; + int last_vm_running; /* per console for caption reasons */ + int x, y; + int hidden; +}; + +void sdl2_window_create(struct sdl2_console *scon); +void sdl2_window_destroy(struct sdl2_console *scon); +void sdl2_window_resize(struct sdl2_console *scon); +void sdl2_poll_events(struct sdl2_console *scon); + +void sdl2_reset_keys(struct sdl2_console *scon); +void sdl2_process_key(struct sdl2_console *scon, + SDL_KeyboardEvent *ev); + +void sdl2_2d_update(DisplayChangeListener *dcl, + int x, int y, int w, int h); +void sdl2_2d_switch(DisplayChangeListener *dcl, + DisplaySurface *new_surface); +void sdl2_2d_refresh(DisplayChangeListener *dcl); +void sdl2_2d_redraw(struct sdl2_console *scon); + +#endif /* SDL2_H */ diff --git a/ui/Makefile.objs b/ui/Makefile.objs index 801cba2675..13b5cfbe41 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -16,7 +16,12 @@ common-obj-$(CONFIG_CURSES) += curses.o common-obj-$(CONFIG_VNC) += $(vnc-obj-y) common-obj-$(CONFIG_GTK) += gtk.o x_keymap.o -sdl.mo-objs := sdl.o sdl_zoom.o sdl2.o +ifeq ($(CONFIG_SDLABI),1.2) +sdl.mo-objs := sdl.o sdl_zoom.o +endif +ifeq ($(CONFIG_SDLABI),2.0) +sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o +endif sdl.mo-cflags := $(SDL_CFLAGS) gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS) diff --git a/ui/sdl.c b/ui/sdl.c index 94c1d9dc3a..3e9d81076b 100644 --- a/ui/sdl.c +++ b/ui/sdl.c @@ -26,8 +26,6 @@ #undef WIN32_LEAN_AND_MEAN #include - -#if SDL_MAJOR_VERSION == 1 #include #include "qemu-common.h" @@ -958,4 +956,3 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) atexit(sdl_cleanup); } -#endif diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c new file mode 100644 index 0000000000..9264817e76 --- /dev/null +++ b/ui/sdl2-2d.c @@ -0,0 +1,122 @@ +/* + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */ + +/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */ +#undef WIN32_LEAN_AND_MEAN + +#include +#include + +#include "qemu-common.h" +#include "ui/console.h" +#include "ui/input.h" +#include "ui/sdl2.h" +#include "sysemu/sysemu.h" + +void sdl2_2d_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + DisplaySurface *surf = qemu_console_surface(dcl->con); + SDL_Rect rect; + + if (!surf) { + return; + } + if (!scon->texture) { + return; + } + + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + + SDL_UpdateTexture(scon->texture, NULL, surface_data(surf), + surface_stride(surf)); + SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect); + SDL_RenderPresent(scon->real_renderer); +} + +void sdl2_2d_switch(DisplayChangeListener *dcl, + DisplaySurface *new_surface) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + DisplaySurface *old_surface = scon->surface; + int format = 0; + + scon->surface = new_surface; + + if (scon->texture) { + SDL_DestroyTexture(scon->texture); + scon->texture = NULL; + } + + if (!new_surface) { + sdl2_window_destroy(scon); + return; + } + + if (!scon->real_window) { + sdl2_window_create(scon); + } else if (old_surface && + ((surface_width(old_surface) != surface_width(new_surface)) || + (surface_height(old_surface) != surface_height(new_surface)))) { + sdl2_window_resize(scon); + } + + SDL_RenderSetLogicalSize(scon->real_renderer, + surface_width(new_surface), + surface_height(new_surface)); + + if (surface_bits_per_pixel(scon->surface) == 16) { + format = SDL_PIXELFORMAT_RGB565; + } else if (surface_bits_per_pixel(scon->surface) == 32) { + format = SDL_PIXELFORMAT_ARGB8888; + } + scon->texture = SDL_CreateTexture(scon->real_renderer, format, + SDL_TEXTUREACCESS_STREAMING, + surface_width(new_surface), + surface_height(new_surface)); + sdl2_2d_redraw(scon); +} + +void sdl2_2d_refresh(DisplayChangeListener *dcl) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + graphic_hw_update(dcl->con); + sdl2_poll_events(scon); +} + +void sdl2_2d_redraw(struct sdl2_console *scon) +{ + if (!scon->surface) { + return; + } + sdl2_2d_update(&scon->dcl, 0, 0, + surface_width(scon->surface), + surface_height(scon->surface)); +} diff --git a/ui/sdl2-input.c b/ui/sdl2-input.c new file mode 100644 index 0000000000..a1973fc2e0 --- /dev/null +++ b/ui/sdl2-input.c @@ -0,0 +1,106 @@ +/* + * 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 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */ + +/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */ +#undef WIN32_LEAN_AND_MEAN + +#include +#include + +#include "qemu-common.h" +#include "ui/console.h" +#include "ui/input.h" +#include "ui/sdl2.h" +#include "sysemu/sysemu.h" + +#include "sdl2-keymap.h" + +static uint8_t modifiers_state[SDL_NUM_SCANCODES]; + +void sdl2_reset_keys(struct sdl2_console *scon) +{ + QemuConsole *con = scon ? scon->dcl.con : NULL; + int i; + + for (i = 0; i < SDL_NUM_SCANCODES; i++) { + if (modifiers_state[i]) { + int qcode = sdl2_scancode_to_qcode[i]; + qemu_input_event_send_key_qcode(con, qcode, false); + modifiers_state[i] = 0; + } + } +} + +void sdl2_process_key(struct sdl2_console *scon, + SDL_KeyboardEvent *ev) +{ + int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode]; + QemuConsole *con = scon ? scon->dcl.con : NULL; + + if (!qemu_console_is_graphic(con)) { + if (ev->type == SDL_KEYDOWN) { + switch (ev->keysym.scancode) { + case SDL_SCANCODE_RETURN: + kbd_put_keysym_console(con, '\n'); + break; + case SDL_SCANCODE_BACKSPACE: + kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE); + break; + default: + kbd_put_qcode_console(con, qcode); + break; + } + } + return; + } + + switch (ev->keysym.scancode) { +#if 0 + case SDL_SCANCODE_NUMLOCKCLEAR: + case SDL_SCANCODE_CAPSLOCK: + /* SDL does not send the key up event, so we generate it */ + qemu_input_event_send_key_qcode(con, qcode, true); + qemu_input_event_send_key_qcode(con, qcode, false); + return; +#endif + case SDL_SCANCODE_LCTRL: + case SDL_SCANCODE_LSHIFT: + case SDL_SCANCODE_LALT: + case SDL_SCANCODE_LGUI: + case SDL_SCANCODE_RCTRL: + case SDL_SCANCODE_RSHIFT: + case SDL_SCANCODE_RALT: + case SDL_SCANCODE_RGUI: + if (ev->type == SDL_KEYUP) { + modifiers_state[ev->keysym.scancode] = 0; + } else { + modifiers_state[ev->keysym.scancode] = 1; + } + /* fall though */ + default: + qemu_input_event_send_key_qcode(con, qcode, + ev->type == SDL_KEYDOWN); + } +} diff --git a/ui/sdl2.c b/ui/sdl2.c index 1ad74baafc..1ae2781624 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -27,55 +27,37 @@ #undef WIN32_LEAN_AND_MEAN #include - -#if SDL_MAJOR_VERSION == 2 #include #include "qemu-common.h" #include "ui/console.h" #include "ui/input.h" +#include "ui/sdl2.h" #include "sysemu/sysemu.h" -#include "sdl2-keymap.h" - static int sdl2_num_outputs; -static struct sdl2_state { - DisplayChangeListener dcl; - DisplaySurface *surface; - SDL_Texture *texture; - SDL_Window *real_window; - SDL_Renderer *real_renderer; - int idx; - int last_vm_running; /* per console for caption reasons */ - int x, y; - int hidden; -} *sdl2_console; +static struct sdl2_console *sdl2_console; static SDL_Surface *guest_sprite_surface; static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ -static bool gui_saved_scaling; -static int gui_saved_width; -static int gui_saved_height; static int gui_saved_grab; static int gui_fullscreen; static int gui_noframe; static int gui_key_modifier_pressed; static int gui_keysym; static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; -static uint8_t modifiers_state[SDL_NUM_SCANCODES]; static SDL_Cursor *sdl_cursor_normal; static SDL_Cursor *sdl_cursor_hidden; static int absolute_enabled; static int guest_cursor; static int guest_x, guest_y; static SDL_Cursor *guest_sprite; -static int scaling_active; static Notifier mouse_mode_notifier; -static void sdl_update_caption(struct sdl2_state *scon); +static void sdl_update_caption(struct sdl2_console *scon); -static struct sdl2_state *get_scon_from_window(uint32_t window_id) +static struct sdl2_console *get_scon_from_window(uint32_t window_id) { int i; for (i = 0; i < sdl2_num_outputs; i++) { @@ -86,180 +68,57 @@ static struct sdl2_state *get_scon_from_window(uint32_t window_id) return NULL; } -static void sdl_update(DisplayChangeListener *dcl, - int x, int y, int w, int h) +void sdl2_window_create(struct sdl2_console *scon) { - struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl); - SDL_Rect rect; - DisplaySurface *surf = qemu_console_surface(dcl->con); + int flags = 0; - if (!surf) { - return; - } - if (!scon->texture) { + if (!scon->surface) { return; } + assert(!scon->real_window); - rect.x = x; - rect.y = y; - rect.w = w; - rect.h = h; - - SDL_UpdateTexture(scon->texture, NULL, surface_data(surf), - surface_stride(surf)); - SDL_RenderCopy(scon->real_renderer, scon->texture, &rect, &rect); - SDL_RenderPresent(scon->real_renderer); -} - -static void do_sdl_resize(struct sdl2_state *scon, int width, int height, - int bpp) -{ - int flags; - - if (scon->real_window && scon->real_renderer) { - if (width && height) { - SDL_RenderSetLogicalSize(scon->real_renderer, width, height); - SDL_SetWindowSize(scon->real_window, width, height); - } else { - SDL_DestroyRenderer(scon->real_renderer); - SDL_DestroyWindow(scon->real_window); - scon->real_renderer = NULL; - scon->real_window = NULL; - } + if (gui_fullscreen) { + flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } else { - if (!width || !height) { - return; - } - flags = 0; - if (gui_fullscreen) { - flags |= SDL_WINDOW_FULLSCREEN; - } else { - flags |= SDL_WINDOW_RESIZABLE; - } - if (scon->hidden) { - flags |= SDL_WINDOW_HIDDEN; - } - - scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - width, height, flags); - scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); - sdl_update_caption(scon); + flags |= SDL_WINDOW_RESIZABLE; } + if (scon->hidden) { + flags |= SDL_WINDOW_HIDDEN; + } + + scon->real_window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + surface_width(scon->surface), + surface_height(scon->surface), + flags); + scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); + sdl_update_caption(scon); } -static void sdl_switch(DisplayChangeListener *dcl, - DisplaySurface *new_surface) +void sdl2_window_destroy(struct sdl2_console *scon) { - struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl); - int format = 0; - int idx = scon->idx; - DisplaySurface *old_surface = scon->surface; - - /* temporary hack: allows to call sdl_switch to handle scaling changes */ - if (new_surface) { - scon->surface = new_surface; - } - - if (!new_surface && idx > 0) { - scon->surface = NULL; - } - - if (new_surface == NULL) { - do_sdl_resize(scon, 0, 0, 0); - } else { - do_sdl_resize(scon, surface_width(scon->surface), - surface_height(scon->surface), 0); - } - - if (old_surface && scon->texture) { - SDL_DestroyTexture(scon->texture); - scon->texture = NULL; - } - - if (new_surface) { - if (!scon->texture) { - if (surface_bits_per_pixel(scon->surface) == 16) { - format = SDL_PIXELFORMAT_RGB565; - } else if (surface_bits_per_pixel(scon->surface) == 32) { - format = SDL_PIXELFORMAT_ARGB8888; - } - - scon->texture = SDL_CreateTexture(scon->real_renderer, format, - SDL_TEXTUREACCESS_STREAMING, - surface_width(new_surface), - surface_height(new_surface)); - } - } -} - -static void reset_keys(struct sdl2_state *scon) -{ - QemuConsole *con = scon ? scon->dcl.con : NULL; - int i; - - for (i = 0; i < 256; i++) { - if (modifiers_state[i]) { - int qcode = sdl2_scancode_to_qcode[i]; - qemu_input_event_send_key_qcode(con, qcode, false); - modifiers_state[i] = 0; - } - } -} - -static void sdl_process_key(struct sdl2_state *scon, - SDL_KeyboardEvent *ev) -{ - int qcode = sdl2_scancode_to_qcode[ev->keysym.scancode]; - QemuConsole *con = scon ? scon->dcl.con : NULL; - - if (!qemu_console_is_graphic(con)) { - if (ev->type == SDL_KEYDOWN) { - switch (ev->keysym.scancode) { - case SDL_SCANCODE_RETURN: - kbd_put_keysym_console(con, '\n'); - break; - case SDL_SCANCODE_BACKSPACE: - kbd_put_keysym_console(con, QEMU_KEY_BACKSPACE); - break; - default: - kbd_put_qcode_console(con, qcode); - break; - } - } + if (!scon->real_window) { return; } - switch (ev->keysym.scancode) { -#if 0 - case SDL_SCANCODE_NUMLOCKCLEAR: - case SDL_SCANCODE_CAPSLOCK: - /* SDL does not send the key up event, so we generate it */ - qemu_input_event_send_key_qcode(con, qcode, true); - qemu_input_event_send_key_qcode(con, qcode, false); - return; -#endif - case SDL_SCANCODE_LCTRL: - case SDL_SCANCODE_LSHIFT: - case SDL_SCANCODE_LALT: - case SDL_SCANCODE_LGUI: - case SDL_SCANCODE_RCTRL: - case SDL_SCANCODE_RSHIFT: - case SDL_SCANCODE_RALT: - case SDL_SCANCODE_RGUI: - if (ev->type == SDL_KEYUP) { - modifiers_state[ev->keysym.scancode] = 0; - } else { - modifiers_state[ev->keysym.scancode] = 1; - } - /* fall though */ - default: - qemu_input_event_send_key_qcode(con, qcode, - ev->type == SDL_KEYDOWN); - } + SDL_DestroyRenderer(scon->real_renderer); + scon->real_renderer = NULL; + SDL_DestroyWindow(scon->real_window); + scon->real_window = NULL; } -static void sdl_update_caption(struct sdl2_state *scon) +void sdl2_window_resize(struct sdl2_console *scon) +{ + if (!scon->real_window) { + return; + } + + SDL_SetWindowSize(scon->real_window, + surface_width(scon->surface), + surface_height(scon->surface)); +} + +static void sdl_update_caption(struct sdl2_console *scon) { char win_title[1024]; char icon_title[1024]; @@ -269,11 +128,11 @@ static void sdl_update_caption(struct sdl2_state *scon) status = " [Stopped]"; } else if (gui_grab) { if (alt_grab) { - status = " - Press Ctrl-Alt-Shift to exit mouse grab"; + status = " - Press Ctrl-Alt-Shift to exit grab"; } else if (ctrl_grab) { - status = " - Press Right-Ctrl to exit mouse grab"; + status = " - Press Right-Ctrl to exit grab"; } else { - status = " - Press Ctrl-Alt to exit mouse grab"; + status = " - Press Ctrl-Alt to exit grab"; } } @@ -323,7 +182,7 @@ static void sdl_show_cursor(void) } } -static void sdl_grab_start(struct sdl2_state *scon) +static void sdl_grab_start(struct sdl2_console *scon) { QemuConsole *con = scon ? scon->dcl.con : NULL; @@ -351,7 +210,7 @@ static void sdl_grab_start(struct sdl2_state *scon) sdl_update_caption(scon); } -static void sdl_grab_end(struct sdl2_state *scon) +static void sdl_grab_end(struct sdl2_console *scon) { SDL_SetWindowGrab(scon->real_window, SDL_FALSE); gui_grab = 0; @@ -359,7 +218,7 @@ static void sdl_grab_end(struct sdl2_state *scon) sdl_update_caption(scon); } -static void absolute_mouse_grab(struct sdl2_state *scon) +static void absolute_mouse_grab(struct sdl2_console *scon) { int mouse_x, mouse_y; int scr_w, scr_h; @@ -386,7 +245,7 @@ static void sdl_mouse_mode_change(Notifier *notify, void *data) } } -static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy, +static void sdl_send_mouse_event(struct sdl2_console *scon, int dx, int dy, int x, int y, int state) { static uint32_t bmap[INPUT_BUTTON_MAX] = { @@ -409,7 +268,7 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy, int i; for (i = 0; i < sdl2_num_outputs; i++) { - struct sdl2_state *thiscon = &sdl2_console[i]; + struct sdl2_console *thiscon = &sdl2_console[i]; if (thiscon->real_window && thiscon->surface) { SDL_GetWindowSize(thiscon->real_window, &scr_w, &scr_h); cur_off_x = thiscon->x; @@ -443,48 +302,27 @@ static void sdl_send_mouse_event(struct sdl2_state *scon, int dx, int dy, qemu_input_event_sync(); } -static void sdl_scale(struct sdl2_state *scon, int width, int height) +static void toggle_full_screen(struct sdl2_console *scon) { - int bpp = 0; - do_sdl_resize(scon, width, height, bpp); - scaling_active = 1; -} - -static void toggle_full_screen(struct sdl2_state *scon) -{ - int width = surface_width(scon->surface); - int height = surface_height(scon->surface); - int bpp = surface_bits_per_pixel(scon->surface); - gui_fullscreen = !gui_fullscreen; if (gui_fullscreen) { - SDL_GetWindowSize(scon->real_window, - &gui_saved_width, &gui_saved_height); - gui_saved_scaling = scaling_active; - - do_sdl_resize(scon, width, height, bpp); - scaling_active = 0; - + SDL_SetWindowFullscreen(scon->real_window, + SDL_WINDOW_FULLSCREEN_DESKTOP); gui_saved_grab = gui_grab; sdl_grab_start(scon); } else { - if (gui_saved_scaling) { - sdl_scale(scon, gui_saved_width, gui_saved_height); - } else { - do_sdl_resize(scon, width, height, 0); - } if (!gui_saved_grab) { sdl_grab_end(scon); } + SDL_SetWindowFullscreen(scon->real_window, 0); } - graphic_hw_invalidate(scon->dcl.con); - graphic_hw_update(scon->dcl.con); + sdl2_2d_redraw(scon); } static void handle_keydown(SDL_Event *ev) { int mod_state, win; - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); if (alt_grab) { mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) == @@ -524,14 +362,13 @@ static void handle_keydown(SDL_Event *ev) gui_keysym = 1; break; case SDL_SCANCODE_U: - if (scaling_active) { - scaling_active = 0; - sdl_switch(&scon->dcl, NULL); - graphic_hw_invalidate(scon->dcl.con); - graphic_hw_update(scon->dcl.con); - } + sdl2_window_destroy(scon); + sdl2_window_create(scon); + /* re-create texture */ + sdl2_2d_switch(&scon->dcl, scon->surface); gui_keysym = 1; break; +#if 0 case SDL_SCANCODE_KP_PLUS: case SDL_SCANCODE_KP_MINUS: if (!gui_fullscreen) { @@ -544,25 +381,26 @@ static void handle_keydown(SDL_Event *ev) 160); height = (surface_height(scon->surface) * width) / surface_width(scon->surface); - + fprintf(stderr, "%s: scale to %dx%d\n", + __func__, width, height); sdl_scale(scon, width, height); - graphic_hw_invalidate(NULL); - graphic_hw_update(NULL); + sdl2_2d_redraw(scon); gui_keysym = 1; } +#endif default: break; } } if (!gui_keysym) { - sdl_process_key(scon, &ev->key); + sdl2_process_key(scon, &ev->key); } } static void handle_keyup(SDL_Event *ev) { int mod_state; - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); if (!alt_grab) { mod_state = (ev->key.keysym.mod & gui_grab_code); @@ -580,19 +418,19 @@ static void handle_keyup(SDL_Event *ev) } /* SDL does not send back all the modifiers key, so we must * correct it. */ - reset_keys(scon); + sdl2_reset_keys(scon); return; } gui_keysym = 0; } if (!gui_keysym) { - sdl_process_key(scon, &ev->key); + sdl2_process_key(scon, &ev->key); } } static void handle_textinput(SDL_Event *ev) { - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); QemuConsole *con = scon ? scon->dcl.con : NULL; if (qemu_console_is_graphic(con)) { @@ -604,7 +442,7 @@ static void handle_textinput(SDL_Event *ev) static void handle_mousemotion(SDL_Event *ev) { int max_x, max_y; - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); if (qemu_input_is_absolute() || absolute_enabled) { int scr_w, scr_h; @@ -631,7 +469,7 @@ static void handle_mousebutton(SDL_Event *ev) { int buttonstate = SDL_GetMouseState(NULL, NULL); SDL_MouseButtonEvent *bev; - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); bev = &ev->button; if (!gui_grab && !qemu_input_is_absolute()) { @@ -651,7 +489,7 @@ static void handle_mousebutton(SDL_Event *ev) static void handle_mousewheel(SDL_Event *ev) { - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->key.windowID); SDL_MouseWheelEvent *wev = &ev->wheel; InputButton btn; @@ -669,14 +507,12 @@ static void handle_mousewheel(SDL_Event *ev) qemu_input_event_sync(); } -static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev) +static void handle_windowevent(SDL_Event *ev) { - int w, h; - struct sdl2_state *scon = get_scon_from_window(ev->key.windowID); + struct sdl2_console *scon = get_scon_from_window(ev->window.windowID); switch (ev->window.event) { case SDL_WINDOWEVENT_RESIZED: - sdl_scale(scon, ev->window.data1, ev->window.data2); { QemuUIInfo info; memset(&info, 0, sizeof(info)); @@ -684,12 +520,10 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev) info.height = ev->window.data2; dpy_set_ui_info(scon->dcl.con, &info); } - graphic_hw_invalidate(scon->dcl.con); - graphic_hw_update(scon->dcl.con); + sdl2_2d_redraw(scon); break; case SDL_WINDOWEVENT_EXPOSED: - SDL_GetWindowSize(SDL_GetWindowFromID(ev->window.windowID), &w, &h); - sdl_update(dcl, 0, 0, w, h); + sdl2_2d_redraw(scon); break; case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_ENTER: @@ -703,10 +537,10 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev) } break; case SDL_WINDOWEVENT_RESTORED: - update_displaychangelistener(dcl, GUI_REFRESH_INTERVAL_DEFAULT); + update_displaychangelistener(&scon->dcl, GUI_REFRESH_INTERVAL_DEFAULT); break; case SDL_WINDOWEVENT_MINIMIZED: - update_displaychangelistener(dcl, 500); + update_displaychangelistener(&scon->dcl, 500); break; case SDL_WINDOWEVENT_CLOSE: if (!no_quit) { @@ -714,12 +548,21 @@ static void handle_windowevent(DisplayChangeListener *dcl, SDL_Event *ev) qemu_system_shutdown_request(); } break; + case SDL_WINDOWEVENT_SHOWN: + if (scon->hidden) { + SDL_HideWindow(scon->real_window); + } + break; + case SDL_WINDOWEVENT_HIDDEN: + if (!scon->hidden) { + SDL_ShowWindow(scon->real_window); + } + break; } } -static void sdl_refresh(DisplayChangeListener *dcl) +void sdl2_poll_events(struct sdl2_console *scon) { - struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl); SDL_Event ev1, *ev = &ev1; if (scon->last_vm_running != runstate_is_running()) { @@ -727,8 +570,6 @@ static void sdl_refresh(DisplayChangeListener *dcl) sdl_update_caption(scon); } - graphic_hw_update(dcl->con); - while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_KEYDOWN: @@ -757,7 +598,7 @@ static void sdl_refresh(DisplayChangeListener *dcl) handle_mousewheel(ev); break; case SDL_WINDOWEVENT: - handle_windowevent(dcl, ev); + handle_windowevent(ev); break; default: break; @@ -768,7 +609,7 @@ static void sdl_refresh(DisplayChangeListener *dcl) static void sdl_mouse_warp(DisplayChangeListener *dcl, int x, int y, int on) { - struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl); + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); if (on) { if (!guest_cursor) { sdl_show_cursor(); @@ -826,11 +667,11 @@ static void sdl_cleanup(void) SDL_QuitSubSystem(SDL_INIT_VIDEO); } -static const DisplayChangeListenerOps dcl_ops = { - .dpy_name = "sdl", - .dpy_gfx_update = sdl_update, - .dpy_gfx_switch = sdl_switch, - .dpy_refresh = sdl_refresh, +static const DisplayChangeListenerOps dcl_2d_ops = { + .dpy_name = "sdl2-2d", + .dpy_gfx_update = sdl2_2d_update, + .dpy_gfx_switch = sdl2_2d_switch, + .dpy_refresh = sdl2_2d_refresh, .dpy_mouse_set = sdl_mouse_warp, .dpy_cursor_define = sdl_mouse_define, }; @@ -865,6 +706,7 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) SDL_GetError()); exit(1); } + SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1"); for (i = 0;; i++) { QemuConsole *con = qemu_console_lookup_by_index(i); @@ -873,13 +715,13 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) } } sdl2_num_outputs = i; - sdl2_console = g_new0(struct sdl2_state, sdl2_num_outputs); + sdl2_console = g_new0(struct sdl2_console, sdl2_num_outputs); for (i = 0; i < sdl2_num_outputs; i++) { QemuConsole *con = qemu_console_lookup_by_index(i); if (!qemu_console_is_graphic(con)) { sdl2_console[i].hidden = true; } - sdl2_console[i].dcl.ops = &dcl_ops; + sdl2_console[i].dcl.ops = &dcl_2d_ops; sdl2_console[i].dcl.con = con; register_displaychangelistener(&sdl2_console[i].dcl); sdl2_console[i].idx = i; @@ -912,4 +754,3 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) atexit(sdl_cleanup); } -#endif