@@ -81,20 +81,17 @@ void EmbeddedProcess::_notification(int p_what) {
81
81
} break ;
82
82
case NOTIFICATION_APPLICATION_FOCUS_IN: {
83
83
application_has_focus = true ;
84
- if (embedded_process_was_focused) {
85
- embedded_process_was_focused = false ;
86
- // Refocus the embedded process if it was focused when the application lost focus,
87
- // but do not refocus if the embedded process is currently focused (indicating it just lost focus)
88
- // or if the current window is a different popup or secondary window.
89
- if (embedding_completed && current_process_id != focused_process_id && window && window->has_focus ()) {
90
- grab_focus ();
91
- queue_update_embedded_process ();
92
- }
93
- }
94
84
} break ;
95
85
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
96
86
application_has_focus = false ;
97
- embedded_process_was_focused = embedding_completed && current_process_id == focused_process_id;
87
+
88
+ // Refocus the current model when focusing the embedded process.
89
+ if (embedding_completed && current_process_id == DisplayServer::get_singleton ()->get_focused_process_id ()) {
90
+ Window *modal_window = _get_current_modal_window ();
91
+ if (modal_window) {
92
+ callable_mp (modal_window, &Window::grab_focus).call_deferred ();
93
+ }
94
+ }
98
95
} break ;
99
96
}
100
97
}
@@ -266,7 +263,6 @@ void EmbeddedProcess::_update_embedded_process() {
266
263
}
267
264
last_updated_embedded_process_focused = focus;
268
265
}
269
-
270
266
DisplayServer::get_singleton ()->embed_process (window->get_window_id (), current_process_id, get_screen_embedded_window_rect (), is_visible_in_tree (), must_grab_focus);
271
267
emit_signal (SNAME (" embedded_process_updated" ));
272
268
}
@@ -287,14 +283,19 @@ void EmbeddedProcess::_check_mouse_over() {
287
283
// This method checks if the mouse is over the embedded process while the current application is focused.
288
284
// The goal is to give focus to the embedded process as soon as the mouse hovers over it,
289
285
// allowing the user to interact with it immediately without needing to click first.
290
- if (!is_visible_in_tree () || !embedding_completed || !application_has_focus || !window || !window->has_focus () || Input::get_singleton ()->is_mouse_button_pressed (MouseButton::LEFT) || Input::get_singleton ()->is_mouse_button_pressed (MouseButton::RIGHT)) {
286
+ if (!embedding_completed || !application_has_focus || !window || has_focus () || ! is_visible_in_tree () || !window->has_focus () || Input::get_singleton ()->is_mouse_button_pressed (MouseButton::LEFT) || Input::get_singleton ()->is_mouse_button_pressed (MouseButton::RIGHT)) {
291
287
return ;
292
288
}
293
289
294
- bool focused = has_focus ();
290
+ // Input::is_mouse_button_pressed is not sufficient to detect the mouse button state
291
+ // while the floating game window is being resized.
292
+ BitField<MouseButtonMask> mouse_button_mask = DisplayServer::get_singleton ()->mouse_get_button_state ();
293
+ if (!mouse_button_mask.is_empty ()) {
294
+ return ;
295
+ }
295
296
296
297
// Not stealing focus from a textfield.
297
- if (!focused && get_viewport ()->gui_get_focus_owner () && get_viewport ()->gui_get_focus_owner ()->is_text_field ()) {
298
+ if (get_viewport ()->gui_get_focus_owner () && get_viewport ()->gui_get_focus_owner ()->is_text_field ()) {
298
299
return ;
299
300
}
300
301
@@ -310,14 +311,17 @@ void EmbeddedProcess::_check_mouse_over() {
310
311
return ;
311
312
}
312
313
313
- // When we already have the focus and the user moves the mouse over the embedded process,
314
- // we just need to refocus the process.
315
- if (focused) {
316
- queue_update_embedded_process ();
317
- } else {
318
- grab_focus ();
319
- queue_redraw ();
314
+ // When there's a modal window, we don't want to grab the focus to prevent
315
+ // the game window to go in front of the modal window.
316
+ if (_get_current_modal_window ()) {
317
+ return ;
320
318
}
319
+
320
+ // Force "regrabbing" the game window focus.
321
+ last_updated_embedded_process_focused = false ;
322
+
323
+ grab_focus ();
324
+ queue_redraw ();
321
325
}
322
326
323
327
void EmbeddedProcess::_check_focused_process_id () {
@@ -326,19 +330,41 @@ void EmbeddedProcess::_check_focused_process_id() {
326
330
focused_process_id = process_id;
327
331
if (focused_process_id == current_process_id) {
328
332
// The embedded process got the focus.
329
- emit_signal (SNAME (" embedded_process_focused" ));
330
- if (has_focus ()) {
331
- // Redraw to updated the focus style.
332
- queue_redraw ();
333
+
334
+ // Refocus the current model when focusing the embedded process.
335
+ Window *modal_window = _get_current_modal_window ();
336
+ if (modal_window) {
337
+ callable_mp (modal_window, &Window::grab_focus).call_deferred ();
333
338
} else {
334
- grab_focus ();
339
+ emit_signal (SNAME (" embedded_process_focused" ));
340
+ if (has_focus ()) {
341
+ // Redraw to updated the focus style.
342
+ queue_redraw ();
343
+ } else {
344
+ grab_focus ();
345
+ }
335
346
}
336
347
} else if (has_focus ()) {
337
348
release_focus ();
338
349
}
339
350
}
340
351
}
341
352
353
+ Window *EmbeddedProcess::_get_current_modal_window () {
354
+ Vector<DisplayServer::WindowID> wl = DisplayServer::get_singleton ()->get_window_list ();
355
+ for (const DisplayServer::WindowID &window_id : wl) {
356
+ Window *w = Window::get_from_id (window_id);
357
+ if (!w) {
358
+ continue ;
359
+ }
360
+
361
+ if (w->is_exclusive ()) {
362
+ return w;
363
+ }
364
+ }
365
+ return nullptr ;
366
+ }
367
+
342
368
void EmbeddedProcess::_bind_methods () {
343
369
ADD_SIGNAL (MethodInfo (" embedding_completed" ));
344
370
ADD_SIGNAL (MethodInfo (" embedding_failed" ));
0 commit comments