summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2024-01-18 16:34:03 +0100
committerRémi Verschelde <rverschelde@gmail.com>2024-01-18 16:34:03 +0100
commit17163886c27ae832472197f7f81f836d54edaefc (patch)
tree066c38479b721667ea1fc3d8c3a75895bcb19a1c /platform/linuxbsd
parent4db2a6801fa2aaae2dd4ec92ff0ef2a92b741edc (diff)
parent64a52e08fe2f53da85f6b30544879aa730e21d5a (diff)
downloadredot-engine-17163886c27ae832472197f7f81f836d54edaefc.tar.gz
Merge pull request #86671 from dsnopek/i3-focus-steal
[X11] Don't re-set input focus if the given window already has it (fixes Godot stealing input focus on i3)
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp22
-rw-r--r--platform/linuxbsd/x11/display_server_x11.h1
2 files changed, 18 insertions, 5 deletions
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 2fff4ce32c..13a0a9f877 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -2011,7 +2011,7 @@ void DisplayServerX11::window_set_transient(WindowID p_window, WindowID p_parent
// a subwindow and its parent are both destroyed.
if (!wd_window.no_focus && !wd_window.is_popup && wd_window.focused) {
if ((xwa.map_state == IsViewable) && !wd_parent.no_focus && !wd_window.is_popup && _window_focus_check()) {
- XSetInputFocus(x11_display, wd_parent.x11_window, RevertToPointerRoot, CurrentTime);
+ _set_input_focus(wd_parent.x11_window, RevertToPointerRoot);
}
}
} else {
@@ -2951,7 +2951,7 @@ void DisplayServerX11::window_set_ime_active(const bool p_active, WindowID p_win
XSync(x11_display, False);
XGetWindowAttributes(x11_display, wd.x11_xim_window, &xwa);
if (xwa.map_state == IsViewable && _window_focus_check()) {
- XSetInputFocus(x11_display, wd.x11_xim_window, RevertToParent, CurrentTime);
+ _set_input_focus(wd.x11_xim_window, RevertToParent);
}
XSetICFocus(wd.xic);
} else {
@@ -4024,6 +4024,18 @@ void DisplayServerX11::_send_window_event(const WindowData &wd, WindowEvent p_ev
}
}
+void DisplayServerX11::_set_input_focus(Window p_window, int p_revert_to) {
+ Window focused_window;
+ int focus_ret_state;
+ XGetInputFocus(x11_display, &focused_window, &focus_ret_state);
+
+ // Only attempt to change focus if the window isn't already focused, in order to
+ // prevent issues with Godot stealing input focus with alternative window managers.
+ if (p_window != focused_window) {
+ XSetInputFocus(x11_display, p_window, p_revert_to, CurrentTime);
+ }
+}
+
void DisplayServerX11::_poll_events_thread(void *ud) {
DisplayServerX11 *display_server = static_cast<DisplayServerX11 *>(ud);
display_server->_poll_events();
@@ -4521,7 +4533,7 @@ void DisplayServerX11::process_events() {
// RevertToPointerRoot is used to make sure we don't lose all focus in case
// a subwindow and its parent are both destroyed.
if ((xwa.map_state == IsViewable) && !wd.no_focus && !wd.is_popup && _window_focus_check()) {
- XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime);
+ _set_input_focus(wd.x11_window, RevertToPointerRoot);
}
// Have we failed to set fullscreen while the window was unmapped?
@@ -4697,7 +4709,7 @@ void DisplayServerX11::process_events() {
// RevertToPointerRoot is used to make sure we don't lose all focus in case
// a subwindow and its parent are both destroyed.
if ((xwa.map_state == IsViewable) && !wd.no_focus && !wd.is_popup && _window_focus_check()) {
- XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime);
+ _set_input_focus(wd.x11_window, RevertToPointerRoot);
}
_window_changed(&event);
@@ -4741,7 +4753,7 @@ void DisplayServerX11::process_events() {
// RevertToPointerRoot is used to make sure we don't lose all focus in case
// a subwindow and its parent are both destroyed.
if (!wd.no_focus && !wd.is_popup) {
- XSetInputFocus(x11_display, wd.x11_window, RevertToPointerRoot, CurrentTime);
+ _set_input_focus(wd.x11_window, RevertToPointerRoot);
}
uint64_t diff = OS::get_singleton()->get_ticks_usec() / 1000 - last_click_ms;
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 3b362e5c22..27bf7951ff 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -359,6 +359,7 @@ class DisplayServerX11 : public DisplayServer {
void _send_window_event(const WindowData &wd, WindowEvent p_event);
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
void _dispatch_input_event(const Ref<InputEvent> &p_event);
+ void _set_input_focus(Window p_window, int p_revert_to);
mutable Mutex events_mutex;
Thread events_thread;