From 042f5fe4b39204b8bf74f257fd4db181ec9f4fd6 Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Mon, 18 Jun 2018 00:44:38 +0000 Subject: [PATCH] Shares the XConnection between all event loops instead of just all event (#572) loops on the same thread. This is needed for adding shared context support to glutin, as contexts must be made with the same native display (and therefore the same connection.) Signed-off-by: Hal Gentz --- CHANGELOG.md | 1 + src/platform/linux/mod.rs | 61 +++++++++++++++++++-------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e44e4c..bd8812a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ - `EventsLoop::get_available_monitors` and `EventsLoop::get_primary_monitor` now have identical counterparts on `Window`, so this information can be acquired without an `EventsLoop` borrow. - `AvailableMonitorsIter` now implements `Debug`. - Fixed quirk on macOS where certain keys would generate characters at twice the normal rate when held down. +- On X11, all event loops now share the same `XConnection`. # Version 0.15.1 (2018-06-13) diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 83f0869d..9e209521 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -6,6 +6,7 @@ use std::ffi::CStr; use std::os::raw::*; use std::sync::Arc; +use parking_lot::Mutex; use sctk::reexports::client::ConnectError; use { @@ -50,9 +51,9 @@ pub struct PlatformSpecificWindowBuilderAttributes { pub x11_window_type: x11::util::WindowType, } -thread_local!( - pub static X11_BACKEND: Result, XNotSupported> = { - XConnection::new(Some(x_error_callback)).map(Arc::new) +lazy_static!( + pub static ref X11_BACKEND: Mutex, XNotSupported>> = { + Mutex::new(XConnection::new(Some(x_error_callback)).map(Arc::new)) }; ); @@ -357,29 +358,28 @@ unsafe extern "C" fn x_error_callback( display: *mut x11::ffi::Display, event: *mut x11::ffi::XErrorEvent, ) -> c_int { - X11_BACKEND.with(|result| { - if let &Ok(ref xconn) = result { - let mut buf: [c_char; 1024] = mem::uninitialized(); - (xconn.xlib.XGetErrorText)( - display, - (*event).error_code as c_int, - buf.as_mut_ptr(), - buf.len() as c_int, - ); - let description = CStr::from_ptr(buf.as_ptr()).to_string_lossy(); + let xconn_lock = X11_BACKEND.lock(); + if let Ok(ref xconn) = *xconn_lock { + let mut buf: [c_char; 1024] = mem::uninitialized(); + (xconn.xlib.XGetErrorText)( + display, + (*event).error_code as c_int, + buf.as_mut_ptr(), + buf.len() as c_int, + ); + let description = CStr::from_ptr(buf.as_ptr()).to_string_lossy(); - let error = XError { - description: description.into_owned(), - error_code: (*event).error_code, - request_code: (*event).request_code, - minor_code: (*event).minor_code, - }; + let error = XError { + description: description.into_owned(), + error_code: (*event).error_code, + request_code: (*event).request_code, + minor_code: (*event).minor_code, + }; - eprintln!("[winit X11 error] {:#?}", error); + eprintln!("[winit X11 error] {:#?}", error); - *xconn.latest_error.lock() = Some(error); - } - }); + *xconn.latest_error.lock() = Some(error); + } // Fun fact: this return value is completely ignored. 0 } @@ -441,14 +441,13 @@ r#"Failed to initialize any backend! } pub fn new_x11() -> Result { - X11_BACKEND.with(|result| { - result - .as_ref() - .map(Arc::clone) - .map(x11::EventsLoop::new) - .map(EventsLoop::X) - .map_err(|err| err.clone()) - }) + X11_BACKEND + .lock() + .as_ref() + .map(Arc::clone) + .map(x11::EventsLoop::new) + .map(EventsLoop::X) + .map_err(|err| err.clone()) } #[inline]