summaryrefslogtreecommitdiff
path: root/platform/linuxbsd
diff options
context:
space:
mode:
authorPouleyKetchoupp <pouleyketchoup@gmail.com>2020-10-08 17:21:51 +0200
committerPouleyKetchoupp <pouleyketchoup@gmail.com>2020-10-08 17:22:03 +0200
commit48a0d44e6716661247832b76c2a6480918e05cc5 (patch)
treebea339171eef38f10d8f8a98b847f60d2f40bbab /platform/linuxbsd
parente46159ab4d0300ca514121f7844888bbfe4a8875 (diff)
Fix x11 display server crash when deleting popup window when unfocused
On FocusOut events, the window could be destroyed while propagating WINDOW_EVENT_FOCUS_OUT event, which causes the WindowData to be invalidated, and still used for calls to XUnsetICFocus. This change moves calls to XUnsetICFocus, and also XSetICFocus in FocusIn events, before propagating the change of focus event to the engine, to be safe in any case. Also setting xic member to nullptr after all calls to XDestroyIC to keep things clean and consistent. Fixes #42645
Diffstat (limited to 'platform/linuxbsd')
-rw-r--r--platform/linuxbsd/display_server_x11.cpp37
1 files changed, 21 insertions, 16 deletions
diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp
index 8b0d08d1cb..176878bc12 100644
--- a/platform/linuxbsd/display_server_x11.cpp
+++ b/platform/linuxbsd/display_server_x11.cpp
@@ -737,6 +737,7 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
XDestroyWindow(x11_display, wd.x11_window);
if (wd.xic) {
XDestroyIC(wd.xic);
+ wd.xic = nullptr;
}
windows.erase(p_id);
@@ -2784,6 +2785,13 @@ void DisplayServerX11::process_events() {
wd.focused = true;
+ if (wd.xic) {
+ // Block events polling while changing input focus
+ // because it triggers some event polling internally.
+ MutexLock mutex_lock(events_mutex);
+ XSetICFocus(wd.xic);
+ }
+
// Keep track of focus order for overlapping windows.
static unsigned int focus_order = 0;
wd.focus_order = ++focus_order;
@@ -2812,12 +2820,6 @@ void DisplayServerX11::process_events() {
XIGrabDevice(x11_display, xi.touch_devices[i], x11_window, CurrentTime, None, XIGrabModeAsync, XIGrabModeAsync, False, &xi.touch_event_mask);
}*/
#endif
- if (wd.xic) {
- // Block events polling while changing input focus
- // because it triggers some event polling internally.
- MutexLock mutex_lock(events_mutex);
- XSetICFocus(wd.xic);
- }
if (!app_focused) {
if (OS::get_singleton()->get_main_loop()) {
@@ -2834,6 +2836,13 @@ void DisplayServerX11::process_events() {
wd.focused = false;
+ if (wd.xic) {
+ // Block events polling while changing input focus
+ // because it triggers some event polling internally.
+ MutexLock mutex_lock(events_mutex);
+ XUnsetICFocus(wd.xic);
+ }
+
Input::get_singleton()->release_pressed_events();
_send_window_event(wd, WINDOW_EVENT_FOCUS_OUT);
@@ -2864,12 +2873,6 @@ void DisplayServerX11::process_events() {
}
xi.state.clear();
#endif
- if (wd.xic) {
- // Block events polling while changing input focus
- // because it triggers some event polling internally.
- MutexLock mutex_lock(events_mutex);
- XUnsetICFocus(wd.xic);
- }
} break;
case ConfigureNotify: {
@@ -4044,11 +4047,13 @@ DisplayServerX11::~DisplayServerX11() {
}
#endif
- if (E->get().xic) {
- XDestroyIC(E->get().xic);
+ WindowData &wd = E->get();
+ if (wd.xic) {
+ XDestroyIC(wd.xic);
+ wd.xic = nullptr;
}
- XUnmapWindow(x11_display, E->get().x11_window);
- XDestroyWindow(x11_display, E->get().x11_window);
+ XUnmapWindow(x11_display, wd.x11_window);
+ XDestroyWindow(x11_display, wd.x11_window);
}
//destroy drivers