diff --git a/src/lib.rs b/src/lib.rs index 16df4172..1466574e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -349,7 +349,8 @@ where native::linux_wayland::run(&conf, f).expect("Wayland backend failed") } conf::LinuxBackend::X11WithWaylandFallback => { - if native::linux_x11::run(&conf, f).is_none() { + if let Err(err) = native::linux_x11::run(&conf, f) { + eprintln!("{err:?}"); eprintln!("Failed to initialize through X11! Trying wayland instead"); native::linux_wayland::run(&conf, f); } @@ -357,7 +358,7 @@ where conf::LinuxBackend::WaylandWithX11Fallback => { if native::linux_wayland::run(&conf, f).is_none() { eprintln!("Failed to initialize through wayland! Trying X11 instead"); - native::linux_x11::run(&conf, f); + native::linux_x11::run(&conf, f).unwrap() } } } diff --git a/src/native/linux_x11.rs b/src/native/linux_x11.rs index 0216e75b..03bf5b84 100644 --- a/src/native/linux_x11.rs +++ b/src/native/linux_x11.rs @@ -10,7 +10,7 @@ mod xi_input; use crate::{ event::EventHandler, - native::{egl, gl, NativeDisplayData, Request}, + native::{egl, gl, NativeDisplayData, Request, module}, CursorIcon, }; @@ -18,6 +18,23 @@ use libx11::*; use std::collections::HashMap; +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum X11Error { + LibraryNotFound(module::Error), + GLXError(String), +} +impl std::fmt::Display for X11Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} +impl From for X11Error { + fn from(error: module::Error) -> X11Error { + X11Error::LibraryNotFound(error) + } +} +impl std::error::Error for X11Error {} + pub struct X11Display { libx11: LibX11, libxkbcommon: LibXkbCommon, @@ -352,7 +369,7 @@ where F: 'static + FnOnce() -> Box, { let mut glx = match glx::Glx::init(&mut display.libx11, display.display, screen, conf) { - Some(glx) => glx, + Ok(glx) => glx, _ => return Err(display), }; let visual = glx.visual; @@ -543,7 +560,7 @@ where Ok(()) } -pub fn run(conf: &crate::conf::Conf, f: &mut Option) -> Option<()> +pub fn run(conf: &crate::conf::Conf, f: &mut Option) -> Result<(), X11Error> where F: 'static + FnOnce() -> Box, { @@ -614,5 +631,5 @@ where } } } - Some(()) + Ok(()) } diff --git a/src/native/linux_x11/glx.rs b/src/native/linux_x11/glx.rs index 4b66e448..0a6438c3 100644 --- a/src/native/linux_x11/glx.rs +++ b/src/native/linux_x11/glx.rs @@ -1,6 +1,6 @@ #![allow(dead_code, non_snake_case)] -use super::libx11::*; +use super::{libx11::*, X11Error}; use crate::native::module; @@ -128,7 +128,7 @@ pub struct LibGlx { } impl LibGlx { - pub fn try_load() -> Option { + pub fn try_load() -> Result { module::Module::load("libGL.so") .or_else(|_| module::Module::load("libGL.so.1")) .map(|module| LibGlx { @@ -149,7 +149,6 @@ impl LibGlx { glxGetVisualFromFBConfig: module.get_symbol("glXGetVisualFromFBConfig").ok(), module, }) - .ok() } pub unsafe fn get_procaddr(&self, procname: &str) -> Option ()> { @@ -217,27 +216,24 @@ impl Glx { display: *mut Display, screen: i32, conf: &crate::conf::Conf, - ) -> Option { + ) -> Result { let mut libgl = LibGlx::try_load()?; let mut errorbase = 0; let mut eventbase = 0; if (libgl.glxQueryExtension.unwrap())(display, &mut errorbase, &mut eventbase) == 0 { - eprintln!("GLX: GLX extension not found"); - return None; + return Err(X11Error::GLXError("GLX extension not found".to_string())); } let mut glx_major = 0; let mut glx_minor = 0; if (libgl.glxQueryVersion.unwrap())(display, &mut glx_major, &mut glx_minor) == 0 { - eprintln!("GLX: Failed to query GLX version"); - return None; + return Err(X11Error::GLXError("Failed to query GLX version".to_string())); } if glx_major == 1 && glx_minor < 3 { - eprintln!("GLX: GLX version 1.3 is required"); - return None; + return Err(X11Error::GLXError("GLX version 1.3 is required".to_string())); } let exts = (libgl.glxQueryExtensionsString.unwrap())(display, screen); @@ -303,7 +299,7 @@ impl Glx { std::mem::transmute_copy(&libgl.get_procaddr("glXCreateContextAttribsARB")) }; - Some(Glx { + Ok(Glx { libgl, multisample, visual, diff --git a/src/native/linux_x11/libx11.rs b/src/native/linux_x11/libx11.rs index ad817393..e9c45e71 100644 --- a/src/native/linux_x11/libx11.rs +++ b/src/native/linux_x11/libx11.rs @@ -1041,7 +1041,7 @@ pub struct LibX11 { } impl LibX11 { - pub fn try_load() -> Option { + pub fn try_load() -> Result { crate::native::module::Module::load("libX11.so") .or_else(|_| crate::native::module::Module::load("libX11.so.6")) .map(|module| LibX11 { @@ -1095,7 +1095,6 @@ impl LibX11 { extensions: X11Extensions::default(), module: std::rc::Rc::new(module), }) - .ok() } pub unsafe fn load_extensions(&mut self, display: *mut Display) { @@ -1143,14 +1142,14 @@ pub struct LibXkbCommon { } impl LibXkbCommon { - pub fn try_load() -> Option { + pub fn try_load() -> Result { crate::native::module::Module::load("libxkbcommon.so") .or_else(|_| crate::native::module::Module::load("libxkbcommon.so.0")) + .or_else(|_| crate::native::module::Module::load("libxkbcommon.so.0.0.0")) .or_else(|_| crate::native::module::Module::load("libxkbcommon.so.0.0.0.0")) .map(|module| LibXkbCommon { xkb_keysym_to_utf32: module.get_symbol("xkb_keysym_to_utf32").unwrap(), module: std::rc::Rc::new(module), }) - .ok() } } diff --git a/src/native/linux_x11/xi_input.rs b/src/native/linux_x11/xi_input.rs index a677b618..92060cf9 100644 --- a/src/native/linux_x11/xi_input.rs +++ b/src/native/linux_x11/xi_input.rs @@ -1,5 +1,6 @@ #![allow(non_upper_case_globals, non_snake_case)] +use crate::native::module; use super::{ libx11::{self, Display, Window, _XPrivDisplay}, xi_input, @@ -64,7 +65,7 @@ type XFreeEventData = fn(_: *mut Display, _: *mut libx11::XGenericEventCookie); #[derive(Clone)] pub struct LibXi { - _module: std::rc::Rc, + _module: std::rc::Rc, _XQueryExtension: XQueryExtension, XIQueryVersion: XIQueryVersion, XISelectEvents: XISelectEvents, @@ -74,9 +75,9 @@ pub struct LibXi { } impl LibXi { - pub fn try_load() -> Option { - crate::native::module::Module::load("libXi.so") - .or_else(|_| crate::native::module::Module::load("libXi.so.6")) + pub fn try_load() -> Result { + module::Module::load("libXi.so") + .or_else(|_| module::Module::load("libXi.so.6")) .map(|module| LibXi { _XQueryExtension: module.get_symbol("XQueryExtension").unwrap(), XIQueryVersion: module.get_symbol("XIQueryVersion").unwrap(), @@ -86,7 +87,6 @@ impl LibXi { xi_extension_opcode: None, _module: std::rc::Rc::new(module), }) - .ok() } pub unsafe fn query_xi_extension( diff --git a/src/native/module.rs b/src/native/module.rs index 6b78a7b8..ddd91f56 100644 --- a/src/native/module.rs +++ b/src/native/module.rs @@ -1,7 +1,7 @@ -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Clone)] pub enum Error { - DlOpenError, - DlSymError, + DlOpenError(String), + DlSymError(String), } #[cfg(any(target_os = "linux", target_os = "android"))] @@ -17,25 +17,21 @@ pub mod linux { impl Module { pub fn load(path: &str) -> Result { - let path = CString::new(path).unwrap(); - - let module = unsafe { dlopen(path.as_ptr(), RTLD_LAZY | RTLD_LOCAL) }; + let cpath = CString::new(path).unwrap(); + let module = unsafe { dlopen(cpath.as_ptr(), RTLD_LAZY | RTLD_LOCAL) }; if module.is_null() { - Err(Error::DlOpenError) + Err(Error::DlOpenError(path.to_string())) } else { Ok(Module(unsafe { NonNull::new_unchecked(module) })) } } pub fn get_symbol(&self, name: &str) -> Result { - let name = CString::new(name).unwrap(); - - let symbol = unsafe { dlsym(self.0.as_ptr(), name.as_ptr()) }; - + let cname = CString::new(name).unwrap(); + let symbol = unsafe { dlsym(self.0.as_ptr(), cname.as_ptr()) }; if symbol.is_null() { - return Err(Error::DlSymError); + return Err(Error::DlSymError(name.to_string())); } - Ok(unsafe { std::mem::transmute_copy::<_, F>(&symbol) }) } } @@ -59,20 +55,18 @@ mod windows { impl Module { pub fn load(path: &str) -> Result { - let path = std::ffi::CString::new(path).unwrap(); - let library = unsafe { LoadLibraryA(path.as_ptr()) }; - + let cpath = std::ffi::CString::new(path).unwrap(); + let library = unsafe { LoadLibraryA(cpath.as_ptr()) }; if library.is_null() { - return Err(Error::DlOpenError); + return Err(Error::DlOpenError(path.to_string())); } Ok(Self(library)) } pub fn get_symbol(&self, name: &str) -> Result { - let name = std::ffi::CString::new(name).unwrap(); - let proc = unsafe { GetProcAddress(self.0, name.as_ptr() as *const _) }; - + let cname = std::ffi::CString::new(name).unwrap(); + let proc = unsafe { GetProcAddress(self.0, cname.as_ptr() as *const _) }; if proc.is_null() { - return Err(Error::DlSymError); + return Err(Error::DlSymError(name.to_string())); } return Ok(unsafe { std::mem::transmute_copy(&proc) }); }