diff --git a/CHANGELOG.md b/CHANGELOG.md index 6548f581..b3e39009 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Unreleased - On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. +- On X11, fix deadlock on window state when handling certain window events. # 0.20.0 (2020-01-05) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 014b9b02..14fc1b1f 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -2,6 +2,8 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc, slice, sync::Arc}; use libc::{c_char, c_int, c_long, c_uint, c_ulong}; +use parking_lot::MutexGuard; + use super::{ events, ffi, get_xtarget, mkdid, mkwid, monitor, util, Device, DeviceId, DeviceInfo, Dnd, DndState, GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, @@ -384,9 +386,12 @@ impl EventProcessor { .inner_pos_to_outer(new_inner_position.0, new_inner_position.1); shared_state_lock.position = Some(outer); if moved { - callback(Event::WindowEvent { - window_id, - event: WindowEvent::Moved(outer.into()), + // Temporarily unlock shared state to prevent deadlock + MutexGuard::unlocked(&mut shared_state_lock, || { + callback(Event::WindowEvent { + window_id, + event: WindowEvent::Moved(outer.into()), + }); }); } outer @@ -426,12 +431,15 @@ impl EventProcessor { let old_inner_size = PhysicalSize::new(width, height); let mut new_inner_size = PhysicalSize::new(new_width, new_height); - callback(Event::WindowEvent { - window_id, - event: WindowEvent::ScaleFactorChanged { - scale_factor: new_scale_factor, - new_inner_size: &mut new_inner_size, - }, + // Temporarily unlock shared state to prevent deadlock + MutexGuard::unlocked(&mut shared_state_lock, || { + callback(Event::WindowEvent { + window_id, + event: WindowEvent::ScaleFactorChanged { + scale_factor: new_scale_factor, + new_inner_size: &mut new_inner_size, + }, + }); }); if new_inner_size != old_inner_size { @@ -461,6 +469,9 @@ impl EventProcessor { } if resized { + // Drop the shared state lock to prevent deadlock + drop(shared_state_lock); + callback(Event::WindowEvent { window_id, event: WindowEvent::Resized(new_inner_size.into()),