浏览代码

Prevent pending input event callbacks from erasing the window in the middle of a loop.

Pāvels Nadtočajevs 8 月之前
父节点
当前提交
f710781b16

+ 6 - 2
platform/linuxbsd/x11/display_server_x11.cpp

@@ -4227,13 +4227,17 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
 			}
 		}
 	} else {
-		// Send to all windows.
+		// Send to all windows. Copy all pending callbacks, since callback can erase window.
+		Vector<Callable> cbs;
 		for (KeyValue<WindowID, WindowData> &E : windows) {
 			Callable callable = E.value.input_event_callback;
 			if (callable.is_valid()) {
-				callable.call(p_event);
+				cbs.push_back(callable);
 			}
 		}
+		for (const Callable &cb : cbs) {
+			cb.call(p_event);
+		}
 	}
 }
 

+ 6 - 2
platform/macos/display_server_macos.mm

@@ -411,13 +411,17 @@ void DisplayServerMacOS::_dispatch_input_event(const Ref<InputEvent> &p_event) {
 				}
 			}
 		} else {
-			// Send to all windows.
+			// Send to all windows. Copy all pending callbacks, since callback can erase window.
+			Vector<Callable> cbs;
 			for (KeyValue<WindowID, WindowData> &E : windows) {
 				Callable callable = E.value.input_event_callback;
 				if (callable.is_valid()) {
-					callable.call(p_event);
+					cbs.push_back(callable);
 				}
 			}
+			for (const Callable &cb : cbs) {
+				cb.call(p_event);
+			}
 		}
 		in_dispatch_input_event = false;
 	}

+ 8 - 4
platform/windows/display_server_windows.cpp

@@ -4253,13 +4253,17 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
 			}
 		}
 	} else {
-		// Send to all windows.
-		for (const KeyValue<WindowID, WindowData> &E : windows) {
-			const Callable callable = E.value.input_event_callback;
+		// Send to all windows. Copy all pending callbacks, since callback can erase window.
+		Vector<Callable> cbs;
+		for (KeyValue<WindowID, WindowData> &E : windows) {
+			Callable callable = E.value.input_event_callback;
 			if (callable.is_valid()) {
-				callable.call(p_event);
+				cbs.push_back(callable);
 			}
 		}
+		for (const Callable &cb : cbs) {
+			cb.call(p_event);
+		}
 	}
 
 	in_dispatch_input_event = false;