diff --git a/CHANGELOG.md b/CHANGELOG.md index c30d1c8a5..e889475e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ Unreleased` header. # Unreleased +- On X11, fix crash due to xsettings query on systems with incomplete xsettings. + # 0.29.14 - On X11/Wayland, fix `text` and `text_with_all_modifiers` not being `None` during compose. diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index d882bcf7e..965aa2f70 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -891,6 +891,9 @@ pub enum X11Error { /// Unable to parse xsettings. XsettingsParse(xsettings::ParserError), + + /// Failed to get property. + GetProperty(util::GetPropertyError), } impl fmt::Display for X11Error { @@ -900,6 +903,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!( @@ -992,6 +996,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 9f1640933..327cc9f7d 100644 --- a/src/platform_impl/linux/x11/util/randr.rs +++ b/src/platform_impl/linux/x11/util/randr.rs @@ -52,6 +52,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 2a2ed5234..d2c506597 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 a96d85fbe..f820c2fed 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)?