Repository: godotengine/godot (language: cpp)

Issue:
"Unhandled XServer error" is printed every time the project is stopped when running from the editor with game embedding
### Tested versions

- Reproducible in: 4.4.beta b15b24b08
- Not reproducible in: 4.4.beta1

### System information

Godot v4.4.beta (b15b24b08) - Fedora Linux 41 (KDE Plasma) on X11 - X11 display driver, Multi-window, 1 monitor - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4090 (nvidia; 565.77) - 13th Gen Intel(R) Core(TM) i9-13900K (32 threads)

### Issue description

"Unhandled XServer error" is printed every time the project is stopped when running from the editor with game embedding:

```
ERROR: Unhandled XServer error: BadWindow (invalid Window parameter)
   Major opcode of failed request: 25
   Serial number of failed request: 0
   Current serial number in output stream: 53707
   at: default_window_error_handler (platform/linuxbsd/x11/display_server_x11.cpp:1180)
```

Some notes: 

- This occurs regardless of the game embedding type (within the editor or as a floating window), as long as game embedding is used.
- This does not occur when running the project without the editor, or with game window embedding disabled.
- There appears to be no negative consequences to this error, but it's annoying to see in the Output panel regardless.
- This only occurs when quitting by pressing <kbd>F8</kbd>. Pressing <kbd>Alt + F4</kbd>, pressing the window manager's close button at the top of the window (for the floating window).
- **However**, if you press <kbd>Alt + F4</kbd> with the game window embedded in the editor (not floating) and the game window is focused, the error will also occur. This also occurs if you use `xkill` and target the running project window.

### Steps to reproduce

- Create a new project, add any node and run it with game window embedding enabled.
- Stop the project by pressing <kbd>F8</kbd>.

### Minimal reproduction project (MRP)

N/A


Discussion / hints:

Fix patch:
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index b1945eb47a2e..3a8d6ff6c584 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -5853,16 +5853,20 @@ Error DisplayServerX11::remove_embedded_process(OS::ProcessID p_pid) {
 	// Handle bad window errors silently because just in case the embedded window was closed.
 	int (*oldHandler)(Display *, XErrorEvent *) = XSetErrorHandler(&bad_window_error_handler);
 
-	// Send the message to gracefully close the window.
-	XEvent ev;
-	memset(&ev, 0, sizeof(ev));
-	ev.xclient.type = ClientMessage;
-	ev.xclient.window = ep->process_window;
-	ev.xclient.message_type = XInternAtom(x11_display, "WM_PROTOCOLS", True);
-	ev.xclient.format = 32;
-	ev.xclient.data.l[0] = XInternAtom(x11_display, "WM_DELETE_WINDOW", False);
-	ev.xclient.data.l[1] = CurrentTime;
-	XSendEvent(x11_display, ep->process_window, False, NoEventMask, &ev);
+	// Check if the window is still valid.
+	XWindowAttributes attr;
+	if (XGetWindowAttributes(x11_display, ep->process_window, &attr)) {
+		// Send the message to gracefully close the window.
+		XEvent ev;
+		memset(&ev, 0, sizeof(ev));
+		ev.xclient.type = ClientMessage;
+		ev.xclient.window = ep->process_window;
+		ev.xclient.message_type = XInternAtom(x11_display, "WM_PROTOCOLS", True);
+		ev.xclient.format = 32;
+		ev.xclient.data.l[0] = XInternAtom(x11_display, "WM_DELETE_WINDOW", False);
+		ev.xclient.data.l[1] = CurrentTime;
+		XSendEvent(x11_display, ep->process_window, False, NoEventMask, &ev);
+	}
 
 	// Restore default error handler.
 	XSetErrorHandler(oldHandler);


Test patch: