mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-14 22:40:38 +11:00
Add method to hook xlib error handler
This should help glutin to handle errors coming from GLX and offer multithreading support in a safe way. Fixes #2378.
This commit is contained in:
parent
f10ef5f331
commit
1ec976f95e
3 changed files with 41 additions and 2 deletions
|
@ -73,6 +73,7 @@ And please only add new entries to the top of this list, right below the `# Unre
|
||||||
- On Web, add `with_prevent_default` and `with_focusable` to `WindowBuilderExtWebSys` to control whether events should be propagated.
|
- On Web, add `with_prevent_default` and `with_focusable` to `WindowBuilderExtWebSys` to control whether events should be propagated.
|
||||||
- On Windows, fix focus events being sent to inactive windows.
|
- On Windows, fix focus events being sent to inactive windows.
|
||||||
- **Breaking**, update `raw-window-handle` to `v0.5` and implement `HasRawDisplayHandle` for `Window` and `EventLoopWindowTarget`.
|
- **Breaking**, update `raw-window-handle` to `v0.5` and implement `HasRawDisplayHandle` for `Window` and `EventLoopWindowTarget`.
|
||||||
|
- On X11, add function `register_xlib_error_hook` into `winit::platform::unix` to subscribe for errors comming from Xlib.
|
||||||
|
|
||||||
# 0.26.1 (2022-01-05)
|
# 0.26.1 (2022-01-05)
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
use crate::dpi::Size;
|
use crate::dpi::Size;
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
use crate::platform_impl::x11::{ffi::XVisualInfo, XConnection};
|
use crate::platform_impl::{x11::ffi::XVisualInfo, x11::XConnection, XLIB_ERROR_HOOKS};
|
||||||
use crate::platform_impl::{
|
use crate::platform_impl::{
|
||||||
ApplicationName, Backend, EventLoopWindowTarget as LinuxEventLoopWindowTarget,
|
ApplicationName, Backend, EventLoopWindowTarget as LinuxEventLoopWindowTarget,
|
||||||
Window as LinuxWindow,
|
Window as LinuxWindow,
|
||||||
|
@ -35,6 +35,29 @@ pub use crate::platform_impl::{x11::util::WindowType as XWindowType, XNotSupport
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
pub use crate::window::Theme;
|
pub use crate::window::Theme;
|
||||||
|
|
||||||
|
/// The first argument in the provided hook will be the pointer to XDisplay
|
||||||
|
/// and the second one the pointer to XError. The return `bool` is an indicator
|
||||||
|
/// whether error was handled by the callback.
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
pub type XlibErrorHook =
|
||||||
|
Box<dyn Fn(*mut std::ffi::c_void, *mut std::ffi::c_void) -> bool + Send + Sync>;
|
||||||
|
|
||||||
|
/// Hook to winit's xlib error handling callback.
|
||||||
|
///
|
||||||
|
/// This method is provided as a safe way to handle the errors comming from X11 when using xlib
|
||||||
|
/// in external crates, like glutin for GLX access. Trying to handle errors by speculating with
|
||||||
|
/// `XSetErrorHandler` is [`unsafe`].
|
||||||
|
///
|
||||||
|
/// [`unsafe`]: https://www.remlab.net/op/xlib.shtml
|
||||||
|
#[inline]
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
pub fn register_xlib_error_hook(hook: XlibErrorHook) {
|
||||||
|
// Append new hook.
|
||||||
|
unsafe {
|
||||||
|
XLIB_ERROR_HOOKS.lock().push(hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Additional methods on [`EventLoopWindowTarget`] that are specific to Unix.
|
/// Additional methods on [`EventLoopWindowTarget`] that are specific to Unix.
|
||||||
pub trait EventLoopWindowTargetExtUnix {
|
pub trait EventLoopWindowTargetExtUnix {
|
||||||
/// True if the [`EventLoopWindowTarget`] uses Wayland.
|
/// True if the [`EventLoopWindowTarget`] uses Wayland.
|
||||||
|
|
|
@ -26,6 +26,8 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
||||||
pub use self::x11::XNotSupported;
|
pub use self::x11::XNotSupported;
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
use self::x11::{ffi::XVisualInfo, util::WindowType as XWindowType, XConnection, XError};
|
use self::x11::{ffi::XVisualInfo, util::WindowType as XWindowType, XConnection, XError};
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
use crate::platform::unix::XlibErrorHook;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use crate::window::Theme;
|
use crate::window::Theme;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -583,6 +585,10 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hooks for X11 errors.
|
||||||
|
#[cfg(feature = "x11")]
|
||||||
|
pub(crate) static mut XLIB_ERROR_HOOKS: Mutex<Vec<XlibErrorHook>> = Mutex::new(Vec::new());
|
||||||
|
|
||||||
#[cfg(feature = "x11")]
|
#[cfg(feature = "x11")]
|
||||||
unsafe extern "C" fn x_error_callback(
|
unsafe extern "C" fn x_error_callback(
|
||||||
display: *mut x11::ffi::Display,
|
display: *mut x11::ffi::Display,
|
||||||
|
@ -590,6 +596,12 @@ unsafe extern "C" fn x_error_callback(
|
||||||
) -> c_int {
|
) -> c_int {
|
||||||
let xconn_lock = X11_BACKEND.lock();
|
let xconn_lock = X11_BACKEND.lock();
|
||||||
if let Ok(ref xconn) = *xconn_lock {
|
if let Ok(ref xconn) = *xconn_lock {
|
||||||
|
// Call all the hooks.
|
||||||
|
let mut error_handled = false;
|
||||||
|
for hook in XLIB_ERROR_HOOKS.lock().iter() {
|
||||||
|
error_handled |= hook(display as *mut _, event as *mut _);
|
||||||
|
}
|
||||||
|
|
||||||
// `assume_init` is safe here because the array consists of `MaybeUninit` values,
|
// `assume_init` is safe here because the array consists of `MaybeUninit` values,
|
||||||
// which do not require initialization.
|
// which do not require initialization.
|
||||||
let mut buf: [MaybeUninit<c_char>; 1024] = MaybeUninit::uninit().assume_init();
|
let mut buf: [MaybeUninit<c_char>; 1024] = MaybeUninit::uninit().assume_init();
|
||||||
|
@ -608,7 +620,10 @@ unsafe extern "C" fn x_error_callback(
|
||||||
minor_code: (*event).minor_code,
|
minor_code: (*event).minor_code,
|
||||||
};
|
};
|
||||||
|
|
||||||
error!("X11 error: {:#?}", error);
|
// Don't log error.
|
||||||
|
if !error_handled {
|
||||||
|
error!("X11 error: {:#?}", error);
|
||||||
|
}
|
||||||
|
|
||||||
*xconn.latest_error.lock() = Some(error);
|
*xconn.latest_error.lock() = Some(error);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue