diff --git a/configure b/configure index c37fc5fe75..bbf900543e 100755 --- a/configure +++ b/configure @@ -207,7 +207,7 @@ fdt="" netmap="no" pixman="" sdl="" -sdlabi="1.2" +sdlabi="" virtfs="" vnc="yes" sparse="no" @@ -2157,6 +2157,7 @@ if test "$gtk" != "no"; then if $pkg_config --exists "$gtkpackage >= $gtkversion"; then gtk_cflags=`$pkg_config --cflags $gtkpackage` gtk_libs=`$pkg_config --libs $gtkpackage` + gtk_version=`$pkg_config --modversion $gtkpackage` if $pkg_config --exists "$gtkx11package >= $gtkversion"; then gtk_cflags="$gtk_cflags $x11_cflags" gtk_libs="$gtk_libs $x11_libs" @@ -2392,20 +2393,25 @@ fi if test "$vte" != "no"; then if test "$gtkabi" = "3.0"; then - vtepackage="vte-2.90" - vteversion="0.32.0" + vteminversion="0.32.0" + if $pkg_config --exists "vte-2.91"; then + vtepackage="vte-2.91" + else + vtepackage="vte-2.90" + fi else vtepackage="vte" - vteversion="0.24.0" + vteminversion="0.24.0" fi - if $pkg_config --exists "$vtepackage >= $vteversion"; then + if $pkg_config --exists "$vtepackage >= $vteminversion"; then vte_cflags=`$pkg_config --cflags $vtepackage` vte_libs=`$pkg_config --libs $vtepackage` + vteversion=`$pkg_config --modversion $vtepackage` libs_softmmu="$vte_libs $libs_softmmu" vte="yes" elif test "$vte" = "yes"; then if test "$gtkabi" = "3.0"; then - feature_not_found "vte" "Install libvte-2.90 devel" + feature_not_found "vte" "Install libvte-2.90/2.91 devel" else feature_not_found "vte" "Install libvte devel" fi @@ -2420,13 +2426,25 @@ fi # Look for sdl configuration program (pkg-config or sdl-config). Try # sdl-config even without cross prefix, and favour pkg-config over sdl-config. +if test "$sdlabi" = ""; then + if $pkg_config --exists "sdl"; then + sdlabi=1.2 + elif $pkg_config --exists "sdl2"; then + sdlabi=2.0 + else + sdlabi=1.2 + fi +fi + if test $sdlabi = "2.0"; then sdl_config=$sdl2_config sdlname=sdl2 sdlconfigname=sdl2_config -else +elif test $sdlabi = "1.2"; then sdlname=sdl sdlconfigname=sdl_config +else + error_exit "Unknown sdlabi $sdlabi, must be 1.2 or 2.0" fi if test "`basename $sdl_config`" != $sdlconfigname && ! has ${sdl_config}; then @@ -2435,10 +2453,10 @@ fi if $pkg_config $sdlname --exists; then sdlconfig="$pkg_config $sdlname" - _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'` + sdlversion=`$sdlconfig --modversion 2>/dev/null` elif has ${sdl_config}; then sdlconfig="$sdl_config" - _sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'` + sdlversion=`$sdlconfig --version` else if test "$sdl" = "yes" ; then feature_not_found "sdl" "Install SDL devel" @@ -2463,7 +2481,7 @@ EOF sdl_libs=`$sdlconfig --libs 2> /dev/null` fi if compile_prog "$sdl_cflags" "$sdl_libs" ; then - if test "$_sdlversion" -lt 121 ; then + if test `echo $sdlversion | sed 's/[^0-9]//g'` -lt 121 ; then sdl_too_old=yes else sdl=yes @@ -4718,6 +4736,12 @@ EOF fi fi +echo_version() { + if test "$1" = "yes" ; then + echo "($2)" + fi +} + # prepend pixman and ftd flags after all config tests are done QEMU_CFLAGS="$pixman_cflags $fdt_cflags $QEMU_CFLAGS" libs_softmmu="$pixman_libs $libs_softmmu" @@ -4767,22 +4791,18 @@ if test "$darwin" = "yes" ; then echo "Cocoa support $cocoa" fi echo "pixman $pixman" -echo "SDL support $sdl" -echo "GTK support $gtk" +echo "SDL support $sdl `echo_version $sdl $sdlversion`" +echo "GTK support $gtk `echo_version $gtk $gtk_version`" echo "GTK GL support $gtk_gl" +echo "VTE support $vte `echo_version $vte $vteversion`" echo "GNUTLS support $gnutls" echo "GNUTLS hash $gnutls_hash" echo "GNUTLS rnd $gnutls_rnd" echo "libgcrypt $gcrypt" echo "libgcrypt kdf $gcrypt_kdf" -if test "$nettle" = "yes"; then - echo "nettle $nettle ($nettle_version)" -else - echo "nettle $nettle" -fi +echo "nettle $nettle `echo_version $nettle $nettle_version`" echo "nettle kdf $nettle_kdf" echo "libtasn1 $tasn1" -echo "VTE support $vte" echo "curses support $curses" echo "virgl support $virglrenderer" echo "curl support $curl" @@ -4831,11 +4851,7 @@ echo "Trace backends $trace_backends" if have_backend "simple"; then echo "Trace output file $trace_file-" fi -if test "$spice" = "yes"; then -echo "spice support $spice ($spice_protocol_version/$spice_server_version)" -else -echo "spice support $spice" -fi +echo "spice support $spice `echo_version $spice $spice_protocol_version/$spice_server_version`" echo "rbd support $rbd" echo "xfsctl support $xfs" echo "smartcard support $smartcard" diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h index 30ccfe3dab..568b64a0f6 100644 --- a/include/ui/spice-display.h +++ b/include/ui/spice-display.h @@ -71,6 +71,7 @@ typedef struct QXLCookie { QXLRect area; int redraw; } render; + void *data; } u; } QXLCookie; diff --git a/ui/egl-helpers.c b/ui/egl-helpers.c index 558edfdeb7..22835c0626 100644 --- a/ui/egl-helpers.c +++ b/ui/egl-helpers.c @@ -49,18 +49,15 @@ int qemu_egl_rendernode_open(void) continue; } - r = asprintf(&p, "/dev/dri/%s", e->d_name); - if (r < 0) { - return -1; - } + p = g_strdup_printf("/dev/dri/%s", e->d_name); r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK); if (r < 0) { - free(p); + g_free(p); continue; } fd = r; - free(p); + g_free(p); break; } diff --git a/ui/gtk.c b/ui/gtk.c index f372a6d5ae..7572cec8c5 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -139,6 +139,7 @@ struct GtkDisplayState { GtkWidget *view_menu_item; GtkWidget *view_menu; GtkWidget *full_screen_item; + GtkWidget *copy_item; GtkWidget *zoom_in_item; GtkWidget *zoom_out_item; GtkWidget *zoom_fixed_item; @@ -328,7 +329,23 @@ static void gd_update_geometry_hints(VirtualConsole *vc) #if defined(CONFIG_VTE) } else if (vc->type == GD_VC_VTE) { VteTerminal *term = VTE_TERMINAL(vc->vte.terminal); - GtkBorder *ib; + GtkBorder padding = { 0 }; + +#if VTE_CHECK_VERSION(0, 37, 0) + gtk_style_context_get_padding( + gtk_widget_get_style_context(vc->vte.terminal), + gtk_widget_get_state_flags(vc->vte.terminal), + &padding); +#else + { + GtkBorder *ib = NULL; + gtk_widget_style_get(vc->vte.terminal, "inner-border", &ib, NULL); + if (ib) { + padding = *ib; + gtk_border_free(ib); + } + } +#endif geo.width_inc = vte_terminal_get_char_width(term); geo.height_inc = vte_terminal_get_char_height(term); @@ -339,11 +356,11 @@ static void gd_update_geometry_hints(VirtualConsole *vc) geo.min_width = geo.width_inc * VC_TERM_X_MIN; geo.min_height = geo.height_inc * VC_TERM_Y_MIN; mask |= GDK_HINT_MIN_SIZE; - gtk_widget_style_get(vc->vte.terminal, "inner-border", &ib, NULL); - geo.base_width += ib->left + ib->right; - geo.base_height += ib->top + ib->bottom; - geo.min_width += ib->left + ib->right; - geo.min_height += ib->top + ib->bottom; + + geo.base_width += padding.left + padding.right; + geo.base_height += padding.top + padding.bottom; + geo.min_width += padding.left + padding.right; + geo.min_height += padding.top + padding.bottom; geo_widget = vc->vte.terminal; #endif } @@ -463,12 +480,21 @@ static void gd_refresh(DisplayChangeListener *dcl) } #if GTK_CHECK_VERSION(3, 0, 0) +static GdkDevice *gd_get_pointer(GdkDisplay *dpy) +{ +#if GTK_CHECK_VERSION(3, 20, 0) + return gdk_seat_get_pointer(gdk_display_get_default_seat(dpy)); +#else + return gdk_device_manager_get_client_pointer( + gdk_display_get_device_manager(dpy)); +#endif +} + static void gd_mouse_set(DisplayChangeListener *dcl, int x, int y, int visible) { VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl); GdkDisplay *dpy; - GdkDeviceManager *mgr; gint x_root, y_root; if (qemu_input_is_absolute()) { @@ -476,10 +502,9 @@ static void gd_mouse_set(DisplayChangeListener *dcl, } dpy = gtk_widget_get_display(vc->gfx.drawing_area); - mgr = gdk_display_get_device_manager(dpy); gdk_window_get_root_coords(gtk_widget_get_window(vc->gfx.drawing_area), x, y, &x_root, &y_root); - gdk_device_warp(gdk_device_manager_get_client_pointer(mgr), + gdk_device_warp(gd_get_pointer(dpy), gtk_widget_get_screen(vc->gfx.drawing_area), x_root, y_root); vc->s->last_x = x; @@ -1307,7 +1332,31 @@ static void gd_menu_zoom_fit(GtkMenuItem *item, void *opaque) gd_update_full_redraw(vc); } -#if GTK_CHECK_VERSION(3, 0, 0) +#if GTK_CHECK_VERSION(3, 20, 0) +static void gd_grab_update(VirtualConsole *vc, bool kbd, bool ptr) +{ + GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area); + GdkSeat *seat = gdk_display_get_default_seat(display); + GdkWindow *window = gtk_widget_get_window(vc->gfx.drawing_area); + GdkSeatCapabilities caps = 0; + GdkCursor *cursor = NULL; + + if (kbd) { + caps |= GDK_SEAT_CAPABILITY_KEYBOARD; + } + if (ptr) { + caps |= GDK_SEAT_CAPABILITY_ALL_POINTING; + cursor = vc->s->null_cursor; + } + + if (caps) { + gdk_seat_grab(seat, window, caps, false, cursor, + NULL, NULL, NULL); + } else { + gdk_seat_ungrab(seat); + } +} +#elif GTK_CHECK_VERSION(3, 0, 0) static void gd_grab_devices(VirtualConsole *vc, bool grab, GdkInputSource source, GdkEventMask mask, GdkCursor *cursor) @@ -1344,7 +1393,9 @@ static void gd_grab_keyboard(VirtualConsole *vc, const char *reason) } } -#if GTK_CHECK_VERSION(3, 0, 0) +#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, true, vc->s->ptr_owner == vc); +#elif GTK_CHECK_VERSION(3, 0, 0) gd_grab_devices(vc, true, GDK_SOURCE_KEYBOARD, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL); @@ -1367,7 +1418,9 @@ static void gd_ungrab_keyboard(GtkDisplayState *s) } s->kbd_owner = NULL; -#if GTK_CHECK_VERSION(3, 0, 0) +#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, false, vc->s->ptr_owner == vc); +#elif GTK_CHECK_VERSION(3, 0, 0) gd_grab_devices(vc, false, GDK_SOURCE_KEYBOARD, 0, NULL); #else gdk_keyboard_ungrab(GDK_CURRENT_TIME); @@ -1388,8 +1441,11 @@ static void gd_grab_pointer(VirtualConsole *vc, const char *reason) } } -#if GTK_CHECK_VERSION(3, 0, 0) - GdkDeviceManager *mgr = gdk_display_get_device_manager(display); +#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, vc->s->kbd_owner == vc, true); + gdk_device_get_position(gd_get_pointer(display), + NULL, &vc->s->grab_x_root, &vc->s->grab_y_root); +#elif GTK_CHECK_VERSION(3, 0, 0) gd_grab_devices(vc, true, GDK_SOURCE_MOUSE, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | @@ -1397,7 +1453,7 @@ static void gd_grab_pointer(VirtualConsole *vc, const char *reason) GDK_BUTTON_MOTION_MASK | GDK_SCROLL_MASK, vc->s->null_cursor); - gdk_device_get_position(gdk_device_manager_get_client_pointer(mgr), + gdk_device_get_position(gd_get_pointer(display), NULL, &vc->s->grab_x_root, &vc->s->grab_y_root); #else gdk_pointer_grab(gtk_widget_get_window(vc->gfx.drawing_area), @@ -1421,17 +1477,21 @@ static void gd_grab_pointer(VirtualConsole *vc, const char *reason) static void gd_ungrab_pointer(GtkDisplayState *s) { VirtualConsole *vc = s->ptr_owner; + GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area); if (vc == NULL) { return; } s->ptr_owner = NULL; - GdkDisplay *display = gtk_widget_get_display(vc->gfx.drawing_area); -#if GTK_CHECK_VERSION(3, 0, 0) - GdkDeviceManager *mgr = gdk_display_get_device_manager(display); +#if GTK_CHECK_VERSION(3, 20, 0) + gd_grab_update(vc, vc->s->kbd_owner == vc, false); + gdk_device_warp(gd_get_pointer(display), + gtk_widget_get_screen(vc->gfx.drawing_area), + vc->s->grab_x_root, vc->s->grab_y_root); +#elif GTK_CHECK_VERSION(3, 0, 0) gd_grab_devices(vc, false, GDK_SOURCE_MOUSE, 0, NULL); - gdk_device_warp(gdk_device_manager_get_client_pointer(mgr), + gdk_device_warp(gd_get_pointer(display), gtk_widget_get_screen(vc->gfx.drawing_area), vc->s->grab_x_root, vc->s->grab_y_root); #else @@ -1570,6 +1630,14 @@ static GSList *gd_vc_menu_init(GtkDisplayState *s, VirtualConsole *vc, } #if defined(CONFIG_VTE) +static void gd_menu_copy(GtkMenuItem *item, void *opaque) +{ + GtkDisplayState *s = opaque; + VirtualConsole *vc = gd_vc_find_current(s); + + vte_terminal_copy_clipboard(VTE_TERMINAL(vc->vte.terminal)); +} + static void gd_vc_adjustment_changed(GtkAdjustment *adjustment, void *opaque) { VirtualConsole *vc = opaque; @@ -1806,6 +1874,10 @@ static void gd_connect_signals(GtkDisplayState *s) G_CALLBACK(gd_menu_powerdown), s); g_signal_connect(s->quit_item, "activate", G_CALLBACK(gd_menu_quit), s); +#if defined(CONFIG_VTE) + g_signal_connect(s->copy_item, "activate", + G_CALLBACK(gd_menu_copy), s); +#endif g_signal_connect(s->full_screen_item, "activate", G_CALLBACK(gd_menu_full_screen), s); g_signal_connect(s->zoom_in_item, "activate", @@ -1939,6 +2011,11 @@ static GtkWidget *gd_create_menu_view(GtkDisplayState *s) s->full_screen_item = gtk_menu_item_new_with_mnemonic(_("_Fullscreen")); +#if defined(CONFIG_VTE) + s->copy_item = gtk_menu_item_new_with_mnemonic(_("_Copy")); + gtk_menu_shell_append(GTK_MENU_SHELL(view_menu), s->copy_item); +#endif + gtk_accel_group_connect(s->accel_group, GDK_KEY_f, HOTKEY_MODIFIERS, 0, g_cclosure_new_swap(G_CALLBACK(gd_accel_full_screen), s, NULL)); #if GTK_CHECK_VERSION(3, 8, 0) diff --git a/ui/sdl2.c b/ui/sdl2.c index d0424421ec..909038f81d 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -357,6 +357,10 @@ static void handle_keydown(SDL_Event *ev) case SDL_SCANCODE_7: case SDL_SCANCODE_8: case SDL_SCANCODE_9: + if (gui_grab) { + sdl_grab_end(scon); + } + win = ev->key.keysym.scancode - SDL_SCANCODE_1; if (win < sdl2_num_outputs) { sdl2_console[win].hidden = !sdl2_console[win].hidden; diff --git a/ui/shader.c b/ui/shader.c index 9264009b80..1ffddbef3b 100644 --- a/ui/shader.c +++ b/ui/shader.c @@ -83,12 +83,12 @@ GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src) glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (!status) { glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); - errmsg = malloc(length); + errmsg = g_malloc(length); glGetShaderInfoLog(shader, length, &length, errmsg); fprintf(stderr, "%s: compile %s error\n%s\n", __func__, (type == GL_VERTEX_SHADER) ? "vertex" : "fragment", errmsg); - free(errmsg); + g_free(errmsg); return 0; } return shader; @@ -108,10 +108,10 @@ GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag) glGetProgramiv(program, GL_LINK_STATUS, &status); if (!status) { glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); - errmsg = malloc(length); + errmsg = g_malloc(length); glGetProgramInfoLog(program, length, &length, errmsg); fprintf(stderr, "%s: link program: %s\n", __func__, errmsg); - free(errmsg); + g_free(errmsg); return 0; } return program; diff --git a/ui/spice-display.c b/ui/spice-display.c index 242ab5f468..0553c5e5b0 100644 --- a/ui/spice-display.c +++ b/ui/spice-display.c @@ -660,6 +660,11 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie_token) qemu_bh_schedule(ssd->gl_unblock_bh); break; } + case QXL_COOKIE_TYPE_IO: + if (cookie->io == QXL_IO_MONITORS_CONFIG_ASYNC) { + g_free(cookie->u.data); + } + break; #endif default: /* should never be called, used in qxl native mode only */ @@ -769,9 +774,7 @@ static void display_mouse_define(DisplayChangeListener *dcl, SimpleSpiceDisplay *ssd = container_of(dcl, SimpleSpiceDisplay, dcl); qemu_mutex_lock(&ssd->lock); - if (c) { - cursor_get(c); - } + cursor_get(c); cursor_put(ssd->cursor); ssd->cursor = c; ssd->hot_x = c->hot_x; @@ -795,6 +798,29 @@ static const DisplayChangeListenerOps display_listener_ops = { #ifdef HAVE_SPICE_GL +static void qemu_spice_gl_monitor_config(SimpleSpiceDisplay *ssd, + int x, int y, int w, int h) +{ + QXLMonitorsConfig *config; + QXLCookie *cookie; + + config = g_malloc0(sizeof(QXLMonitorsConfig) + sizeof(QXLHead)); + config->count = 1; + config->max_allowed = 1; + config->heads[0].x = x; + config->heads[0].y = y; + config->heads[0].width = w; + config->heads[0].height = h; + cookie = qxl_cookie_new(QXL_COOKIE_TYPE_IO, + QXL_IO_MONITORS_CONFIG_ASYNC); + cookie->u.data = config; + + spice_qxl_monitors_config_async(&ssd->qxl, + (uintptr_t)config, + MEMSLOT_GROUP_HOST, + (uintptr_t)cookie); +} + static void qemu_spice_gl_block(SimpleSpiceDisplay *ssd, bool block) { uint64_t timeout; @@ -858,6 +884,8 @@ static void qemu_spice_gl_scanout(DisplayChangeListener *dcl, surface_width(ssd->ds), surface_height(ssd->ds), stride, fourcc, y_0_top); + + qemu_spice_gl_monitor_config(ssd, x, y, w, h); } static void qemu_spice_gl_update(DisplayChangeListener *dcl,