Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging

ui/ fixes for 8.0

# -----BEGIN PGP SIGNATURE-----
#
# iQJQBAABCAA6FiEEh6m9kz+HxgbSdvYt2ujhCXWWnOUFAmQZcpUcHG1hcmNhbmRy
# ZS5sdXJlYXVAcmVkaGF0LmNvbQAKCRDa6OEJdZac5VI/D/48GzUBrNuA8lep7/K4
# Mw1Ec7X3nn6KZbHsbvCASJuMH3wKYKZJS4JQuXvpHLxpDnzycYKpbrdEG8WrNo50
# 7tmahsZfA7rs5U3GToBgSdsTUlruvUoU4ycWLKfOJD0A47jaLprAFsBWvY3cYVO6
# 37EzCdzgV+FA/btaceNwdANItIGGUNPyXKSAdOebyDRD/3J4zTgSh3eG4ux86hzf
# P5Vo/m/hsqLc3S+M840XBABPitrmo+P7kS8NP8a5uifyE+bAbTBVV8WypMXK3lcX
# GMZh4LTfUPaABqBAhGZh/Bf3wOJ7P4w8+AXiMLBbxTYQmmSwwLZ0kwVcEIhrw7tK
# 8TLLz1hrVC88KQLCJ5m99w4xa0DEFZIwh6qEaStA+/TeJR02k49HpWiWkwa/yn55
# qRjaPV9mMhGaNCD9+E2ipX0krx6f03/TqE70IpyhDKuvQbjPv/4Q48gvF7R9IcuI
# mK45CAakudRjGE+2ZygGRvJQnZ/rRQX/spCbipOtd9Ay9yWFyrXj9zbkb97OUe6G
# 5HhhcfWAKXmRKh/V+xFIyBpN30XJwMxn6UJVacQwDRZamJMMmVi0rvZ7L1zhjbq5
# ZBjY6mZhufDk8YUTZiLz3BzDPcw+PWjkaGetFeoVkY7YDHajo0P5c3o23XJvberI
# 8Gaz61t7YB5uXq9WxKjyoRE23A==
# =npHn
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 21 Mar 2023 09:02:13 GMT
# gpg:                using RSA key 87A9BD933F87C606D276F62DDAE8E10975969CE5
# gpg:                issuer "marcandre.lureau@redhat.com"
# gpg: Good signature from "Marc-André Lureau <marcandre.lureau@redhat.com>" [full]
# gpg:                 aka "Marc-André Lureau <marcandre.lureau@gmail.com>" [full]
# Primary key fingerprint: 87A9 BD93 3F87 C606 D276  F62D DAE8 E109 7596 9CE5

* tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu:
  ui: fix crash on serial reset, during init
  ui/sdl2: remove workaround forcing x11
  ui: return the default console cursor when con == NULL
  ui/gtk: fix cursor moved to left corner
  ui/dbus: fix passing SOCKET to GSocket API & leak
  ui/spice: fix SOCKET handling regression
  win32: add qemu_close_socket_osfhandle()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h
index e2849f8..15c296e 100644
--- a/include/sysemu/os-win32.h
+++ b/include/sysemu/os-win32.h
@@ -171,10 +171,21 @@
 
 bool qemu_socket_unselect(int sockfd, Error **errp);
 
-/* We wrap all the sockets functions so that we can
- * set errno based on WSAGetLastError()
+/* We wrap all the sockets functions so that we can set errno based on
+ * WSAGetLastError(), and use file-descriptors instead of SOCKET.
  */
 
+/*
+ * qemu_close_socket_osfhandle:
+ * @fd: a file descriptor associated with a SOCKET
+ *
+ * Close only the C run-time file descriptor, leave the SOCKET opened.
+ *
+ * Returns zero on success. On error, -1 is returned, and errno is set to
+ * indicate the error.
+ */
+int qemu_close_socket_osfhandle(int fd);
+
 #undef close
 #define close qemu_close_wrap
 int qemu_close_wrap(int fd);
diff --git a/ui/console.c b/ui/console.c
index f378302..6e8a3cd 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -2303,6 +2303,9 @@
 
 QEMUCursor *qemu_console_get_cursor(QemuConsole *con)
 {
+    if (con == NULL) {
+        con = active_console;
+    }
     return con->cursor;
 }
 
diff --git a/ui/dbus.c b/ui/dbus.c
index 0513de9..b9e9698 100644
--- a/ui/dbus.c
+++ b/ui/dbus.c
@@ -304,11 +304,20 @@
         g_cancellable_cancel(dbus_display->add_client_cancellable);
     }
 
+#ifdef WIN32
+    socket = g_socket_new_from_fd(_get_osfhandle(csock), &err);
+#else
     socket = g_socket_new_from_fd(csock, &err);
+#endif
     if (!socket) {
         error_setg(errp, "Failed to setup D-Bus socket: %s", err->message);
+        close(csock);
         return false;
     }
+#ifdef WIN32
+    /* socket owns the SOCKET handle now, so release our osf handle */
+    qemu_close_socket_osfhandle(csock);
+#endif
 
     conn = g_socket_connection_factory_create_connection(socket);
 
diff --git a/ui/gtk.c b/ui/gtk.c
index fd82e9b..f16e0f8 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -450,7 +450,8 @@
     GdkDisplay *dpy;
     gint x_root, y_root;
 
-    if (qemu_input_is_absolute()) {
+    if (!gtk_widget_get_realized(vc->gfx.drawing_area) ||
+        qemu_input_is_absolute()) {
         return;
     }
 
@@ -1783,7 +1784,9 @@
     VCChardev *vcd = VC_CHARDEV(chr);
     VirtualConsole *vc = vcd->console;
 
-    gd_vc_send_chars(vc);
+    if (vc) {
+        gd_vc_send_chars(vc);
+    }
 }
 
 static void gd_vc_chr_set_echo(Chardev *chr, bool echo)
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 35c58c1..b12dec4 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -843,22 +843,6 @@
 
     assert(o->type == DISPLAY_TYPE_SDL);
 
-#ifdef __linux__
-    /* on Linux, SDL may use fbcon|directfb|svgalib when run without
-     * accessible $DISPLAY to open X11 window.  This is often the case
-     * when qemu is run using sudo.  But in this case, and when actually
-     * run in X11 environment, SDL fights with X11 for the video card,
-     * making current display unavailable, often until reboot.
-     * So make x11 the default SDL video driver if this variable is unset.
-     * This is a bit hackish but saves us from bigger problem.
-     * Maybe it's a good idea to fix this in SDL instead.
-     */
-    if (!g_setenv("SDL_VIDEODRIVER", "x11", 0)) {
-        fprintf(stderr, "Could not set SDL_VIDEODRIVER environment variable\n");
-        exit(1);
-    }
-#endif
-
     if (SDL_GetHintBoolean("QEMU_ENABLE_SDL_LOGGING", SDL_FALSE)) {
         SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
     }
diff --git a/ui/spice-core.c b/ui/spice-core.c
index b05c830..67cfd3c 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -90,13 +90,23 @@
 static void watch_read(void *opaque)
 {
     SpiceWatch *watch = opaque;
-    watch->func(watch->fd, SPICE_WATCH_EVENT_READ, watch->opaque);
+    int fd = watch->fd;
+
+#ifdef WIN32
+    fd = _get_osfhandle(fd);
+#endif
+    watch->func(fd, SPICE_WATCH_EVENT_READ, watch->opaque);
 }
 
 static void watch_write(void *opaque)
 {
     SpiceWatch *watch = opaque;
-    watch->func(watch->fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
+    int fd = watch->fd;
+
+#ifdef WIN32
+    fd = _get_osfhandle(fd);
+#endif
+    watch->func(fd, SPICE_WATCH_EVENT_WRITE, watch->opaque);
 }
 
 static void watch_update_mask(SpiceWatch *watch, int event_mask)
@@ -117,6 +127,14 @@
 {
     SpiceWatch *watch;
 
+#ifdef WIN32
+    fd = _open_osfhandle(fd, _O_BINARY);
+    if (fd < 0) {
+        error_setg_win32(&error_warn, WSAGetLastError(), "Couldn't associate a FD with the SOCKET");
+        return NULL;
+    }
+#endif
+
     watch = g_malloc0(sizeof(*watch));
     watch->fd     = fd;
     watch->func   = func;
@@ -129,6 +147,10 @@
 static void watch_remove(SpiceWatch *watch)
 {
     qemu_set_fd_handler(watch->fd, NULL, NULL, NULL);
+#ifdef WIN32
+    /* SOCKET is owned by spice */
+    qemu_close_to_socket(watch->fd);
+#endif
     g_free(watch);
 }
 
@@ -908,6 +930,9 @@
 
 static int qemu_spice_display_add_client(int csock, int skipauth, int tls)
 {
+#ifdef WIN32
+    csock = qemu_close_socket_osfhandle(csock);
+#endif
     if (tls) {
         return spice_server_add_ssl_client(spice_server, csock, skipauth);
     } else {
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index 16f8a67..a986387 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -479,40 +479,27 @@
     return ret;
 }
 
-
 #undef close
-int qemu_close_wrap(int fd)
+int qemu_close_socket_osfhandle(int fd)
 {
-    int ret;
+    SOCKET s = _get_osfhandle(fd);
     DWORD flags = 0;
-    SOCKET s = INVALID_SOCKET;
 
-    if (fd_is_socket(fd)) {
-        s = _get_osfhandle(fd);
-
-        /*
-         * If we were to just call _close on the descriptor, it would close the
-         * HANDLE, but it wouldn't free any of the resources associated to the
-         * SOCKET, and we can't call _close after calling closesocket, because
-         * closesocket has already closed the HANDLE, and _close would attempt to
-         * close the HANDLE again, resulting in a double free. We can however
-         * protect the HANDLE from actually being closed long enough to close the
-         * file descriptor, then close the socket itself.
-         */
-        if (!GetHandleInformation((HANDLE)s, &flags)) {
-            errno = EACCES;
-            return -1;
-        }
-
-        if (!SetHandleInformation((HANDLE)s, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE)) {
-            errno = EACCES;
-            return -1;
-        }
+    /*
+     * If we were to just call _close on the descriptor, it would close the
+     * HANDLE, but it wouldn't free any of the resources associated to the
+     * SOCKET, and we can't call _close after calling closesocket, because
+     * closesocket has already closed the HANDLE, and _close would attempt to
+     * close the HANDLE again, resulting in a double free. We can however
+     * protect the HANDLE from actually being closed long enough to close the
+     * file descriptor, then close the socket itself.
+     */
+    if (!GetHandleInformation((HANDLE)s, &flags)) {
+        errno = EACCES;
+        return -1;
     }
 
-    ret = close(fd);
-
-    if (s != INVALID_SOCKET && !SetHandleInformation((HANDLE)s, flags, flags)) {
+    if (!SetHandleInformation((HANDLE)s, HANDLE_FLAG_PROTECT_FROM_CLOSE, HANDLE_FLAG_PROTECT_FROM_CLOSE)) {
         errno = EACCES;
         return -1;
     }
@@ -521,15 +508,33 @@
      * close() returns EBADF since we PROTECT_FROM_CLOSE the underlying handle,
      * but the FD is actually freed
      */
-    if (ret < 0 && (s == INVALID_SOCKET || errno != EBADF)) {
-        return ret;
+    if (close(fd) < 0 && errno != EBADF) {
+        return -1;
     }
 
-    if (s != INVALID_SOCKET) {
-        ret = closesocket(s);
-        if (ret < 0) {
-            errno = socket_error();
-        }
+    if (!SetHandleInformation((HANDLE)s, flags, flags)) {
+        errno = EACCES;
+        return -1;
+    }
+
+    return 0;
+}
+
+int qemu_close_wrap(int fd)
+{
+    SOCKET s = INVALID_SOCKET;
+    int ret = -1;
+
+    if (!fd_is_socket(fd)) {
+        return close(fd);
+    }
+
+    s = _get_osfhandle(fd);
+    qemu_close_socket_osfhandle(fd);
+
+    ret = closesocket(s);
+    if (ret < 0) {
+        errno = socket_error();
     }
 
     return ret;