From 800223a04314319cbf569f359c5131d2595f0e29 Mon Sep 17 00:00:00 2001 From: norepro Date: Fri, 8 May 2026 00:41:20 -0700 Subject: [PATCH] Release X11 pressed events on true focus loss There are two "focus lost" signals in the Godot X11 display server: 1. `FocusOut` - native X11 signal 2. `NOTIFICATION_APPLICATION_FOCUS_OUT` - Godot signal after 250ms of no other window getting focus. When focus is lost, the intent is to clear any input pressed events so that, when focus returns, we have a clean slate. The bug is that the pressed events are (attempted to be) cleared on the first signal, X11's `FocusOut`. This is always a no-op because it returns early if the application still has focus. Godot's X11 server only sets that flag after the second signal, not the first. Move the pressed event clearing from the first signal handler to the second. This makes clearing pressed events do what it says. This does not affect Wayland because it does not have the 250ms grace period. Simple repro is to load any 3D scene, hold 'W' and, while 'W' is held, click on any non-Godot window. Release 'W', click back to Godot, and hold RMB. It will zoom forward as if 'W' is still pressed. After the fix, the same test has RMB look around as expected when no other keys are pressed. Fixes #118897 --- platform/linuxbsd/x11/display_server_x11.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 212cbe0435..65c9a3eda4 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -4915,6 +4915,9 @@ void DisplayServerX11::process_events() { OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); } app_focused = false; + + // Release pressed events here instead of FocusOut because it's a no-op until NOTIFICATION_APPLICATION_FOCUS_OUT is processed. + Input::get_singleton()->release_pressed_events(); } } else { time_since_no_focus = OS::get_singleton()->get_ticks_msec(); @@ -5275,8 +5278,6 @@ void DisplayServerX11::process_events() { } wd.focused = false; - Input::get_singleton()->release_pressed_events(); - AccessibilityServer::get_singleton()->set_window_focused(window_id, false); _send_window_event(wd, DisplayServerEnums::WINDOW_EVENT_FOCUS_OUT);