Browse Source

Fix popup closing immediately after showing on some Linux WMs

When a popup is going to be closed, switch focus to the parent only if
the popup is still being focused.

Fixes some cases with specific WMs where due to the order of events, a
new popup could be immediately unfocused because a previously opened
and closed popup is switching focus to the parent.
PouleyKetchoupp 4 years ago
parent
commit
e030360b88
1 changed files with 7 additions and 3 deletions
  1. 7 3
      platform/linuxbsd/display_server_x11.cpp

+ 7 - 3
platform/linuxbsd/display_server_x11.cpp

@@ -871,7 +871,9 @@ DisplayServer::WindowID DisplayServerX11::create_sub_window(WindowMode p_mode, V
 void DisplayServerX11::show_window(WindowID p_id) {
 	_THREAD_SAFE_METHOD_
 
-	WindowData &wd = windows[p_id];
+	const WindowData &wd = windows[p_id];
+
+	DEBUG_LOG_X11("show_window: %lu (%u) \n", wd.x11_window, p_id);
 
 	XMapWindow(x11_display, wd.x11_window);
 }
@@ -1095,6 +1097,8 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
 	WindowID prev_parent = wd_window.transient_parent;
 	ERR_FAIL_COND(prev_parent == p_parent);
 
+	DEBUG_LOG_X11("window_set_transient: %lu (%u), prev_parent=%u, parent=%u\n", wd_window.x11_window, p_window, prev_parent, p_parent);
+
 	ERR_FAIL_COND_MSG(wd_window.on_top, "Windows with the 'on top' can't become transient.");
 	if (p_parent == INVALID_WINDOW_ID) {
 		//remove transient
@@ -1109,10 +1113,10 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
 
 		XSetTransientForHint(x11_display, wd_window.x11_window, None);
 
-		// Set focus to parent sub window to avoid losing all focus with nested menus.
+		// Set focus to parent sub window to avoid losing all focus when closing a nested sub-menu.
 		// RevertToPointerRoot is used to make sure we don't lose all focus in case
 		// a subwindow and its parent are both destroyed.
-		if (wd_window.menu_type && !wd_window.no_focus) {
+		if (wd_window.menu_type && !wd_window.no_focus && wd_window.focused) {
 			if (!wd_parent.no_focus) {
 				XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime);
 			}