diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c906d89..1c83ca65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ Unreleased` header. - **Breaking:** Removed `EventLoopBuilder::with_user_event`, the functionality is now available in `EventLoop::with_user_event`. - Add `Window::default_attributes` to get default `WindowAttributes`. - `log` has been replaced with `tracing`. The old behavior can be emulated by setting the `log` feature on the `tracing` crate. +- On X11, fix crash due to xsettings query on systems with incomplete xsettings. # 0.29.14 diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 52399d37..72b9a5c9 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -887,6 +887,9 @@ pub enum X11Error { /// Unable to parse xsettings. XsettingsParse(xsettings::ParserError), + + /// Failed to get property. + GetProperty(util::GetPropertyError), } impl fmt::Display for X11Error { @@ -896,6 +899,7 @@ impl fmt::Display for X11Error { X11Error::Connect(e) => write!(f, "X11 connection error: {}", e), X11Error::Connection(e) => write!(f, "X11 connection error: {}", e), X11Error::XidsExhausted(e) => write!(f, "XID range exhausted: {}", e), + X11Error::GetProperty(e) => write!(f, "Failed to get X property {}", e), X11Error::X11(e) => write!(f, "X11 error: {:?}", e), X11Error::UnexpectedNull(s) => write!(f, "Xlib function returned null: {}", s), X11Error::InvalidActivationToken(s) => write!( @@ -988,6 +992,12 @@ impl From for X11Error { } } +impl From for X11Error { + fn from(value: util::GetPropertyError) -> Self { + Self::GetProperty(value) + } +} + /// Type alias for a void cookie. type VoidCookie<'a> = x11rb::cookie::VoidCookie<'a, X11rbConnection>; diff --git a/src/platform_impl/linux/x11/util/randr.rs b/src/platform_impl/linux/x11/util/randr.rs index c466fb17..e55c042c 100644 --- a/src/platform_impl/linux/x11/util/randr.rs +++ b/src/platform_impl/linux/x11/util/randr.rs @@ -53,6 +53,7 @@ impl XConnection { .get_string("Xft.dpi", "") .and_then(|s| f64::from_str(s).ok()) } + pub fn get_output_info( &self, resources: &monitor::ScreenResources, diff --git a/src/platform_impl/linux/x11/util/window_property.rs b/src/platform_impl/linux/x11/util/window_property.rs index 1f6a6b4c..eb5f6cb5 100644 --- a/src/platform_impl/linux/x11/util/window_property.rs +++ b/src/platform_impl/linux/x11/util/window_property.rs @@ -1,13 +1,18 @@ -use super::*; -use bytemuck::{NoUninit, Pod}; +use std::error::Error; +use std::fmt; use std::sync::Arc; +use bytemuck::{NoUninit, Pod}; + use x11rb::connection::Connection; use x11rb::errors::ReplyError; -pub type Cardinal = u32; +use super::*; + pub const CARDINAL_SIZE: usize = mem::size_of::(); +pub type Cardinal = u32; + #[derive(Debug, Clone)] pub enum GetPropertyError { X11rbError(Arc), @@ -15,12 +20,6 @@ pub enum GetPropertyError { FormatMismatch(c_int), } -impl> From for GetPropertyError { - fn from(e: T) -> Self { - Self::X11rbError(Arc::new(e.into())) - } -} - impl GetPropertyError { pub fn is_actual_property_type(&self, t: xproto::Atom) -> bool { if let GetPropertyError::TypeMismatch(actual_type) = *self { @@ -31,6 +30,24 @@ impl GetPropertyError { } } +impl> From for GetPropertyError { + fn from(e: T) -> Self { + Self::X11rbError(Arc::new(e.into())) + } +} + +impl fmt::Display for GetPropertyError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + GetPropertyError::X11rbError(err) => err.fmt(f), + GetPropertyError::TypeMismatch(err) => write!(f, "type mismatch: {err}"), + GetPropertyError::FormatMismatch(err) => write!(f, "format mismatch: {err}"), + } + } +} + +impl Error for GetPropertyError {} + // Number of 32-bit chunks to retrieve per iteration of get_property's inner loop. // To test if `get_property` works correctly, set this to 1. const PROPERTY_BUFFER_SIZE: u32 = 1024; // 4k of RAM ought to be enough for anyone! diff --git a/src/platform_impl/linux/x11/xsettings.rs b/src/platform_impl/linux/x11/xsettings.rs index a96d85fb..f820c2fe 100644 --- a/src/platform_impl/linux/x11/xsettings.rs +++ b/src/platform_impl/linux/x11/xsettings.rs @@ -33,13 +33,11 @@ impl XConnection { .reply()?; // Read the _XSETTINGS_SETTINGS property. - let data: Vec = self - .get_property( - owner.owner, - atoms[_XSETTINGS_SETTINGS], - atoms[_XSETTINGS_SETTINGS], - ) - .unwrap(); + let data: Vec = self.get_property( + owner.owner, + atoms[_XSETTINGS_SETTINGS], + atoms[_XSETTINGS_SETTINGS], + )?; // Parse the property. let dpi_setting = read_settings(&data)?