diff options
| author | tomaka <pierre.krieger1708@gmail.com> | 2015-09-20 17:52:53 +0200 | 
|---|---|---|
| committer | tomaka <pierre.krieger1708@gmail.com> | 2015-09-20 17:52:53 +0200 | 
| commit | f51ace4c7885fa25c146c24181c4d87f5632de3e (patch) | |
| tree | fa22f137deaabbc99c2f7bbeb1958b07ab7c2949 /src | |
| parent | 907d7621bc9822c2688d1783a5805f8532a92b42 (diff) | |
| parent | 82bb047fda3912489d024dbf40613168ded50527 (diff) | |
| download | glutin-f51ace4c7885fa25c146c24181c4d87f5632de3e.tar.gz glutin-f51ace4c7885fa25c146c24181c4d87f5632de3e.zip  | |
Merge pull request #602 from tomaka/api-dispatch-error
[Breaking change] Better error handling in Linux's api dispatch
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/x11/ffi.rs | 2 | ||||
| -rw-r--r-- | src/api/x11/mod.rs | 2 | ||||
| -rw-r--r-- | src/api/x11/xdisplay.rs | 53 | ||||
| -rw-r--r-- | src/lib.rs | 11 | ||||
| -rw-r--r-- | src/platform/linux/api_dispatch.rs | 25 | 
5 files changed, 76 insertions, 17 deletions
diff --git a/src/api/x11/ffi.rs b/src/api/x11/ffi.rs index 3d4f0ed..465aa95 100644 --- a/src/api/x11/ffi.rs +++ b/src/api/x11/ffi.rs @@ -5,6 +5,8 @@ pub use x11_dl::xlib::*;  pub use x11_dl::xinput::*;  pub use x11_dl::xinput2::*; +pub use x11_dl::error::OpenError; +  pub use self::glx::types::GLXContext;  /// GLX bindings diff --git a/src/api/x11/mod.rs b/src/api/x11/mod.rs index 39b99f3..a7c997b 100644 --- a/src/api/x11/mod.rs +++ b/src/api/x11/mod.rs @@ -2,7 +2,7 @@  pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor};  pub use self::window::{Window, XWindow, PollEventsIterator, WaitEventsIterator, Context, WindowProxy}; -pub use self::xdisplay::XConnection; +pub use self::xdisplay::{XConnection, XNotSupported};  pub mod ffi; diff --git a/src/api/x11/xdisplay.rs b/src/api/x11/xdisplay.rs index c960c00..2aa5d95 100644 --- a/src/api/x11/xdisplay.rs +++ b/src/api/x11/xdisplay.rs @@ -1,4 +1,6 @@  use std::ptr; +use std::fmt; +use std::error::Error;  use std::ffi::CString;  use libc; @@ -21,17 +23,13 @@ pub struct XConnection {  unsafe impl Send for XConnection {}  unsafe impl Sync for XConnection {} -/// Error returned if this system doesn't have XLib or can't create an X connection. -#[derive(Copy, Clone, Debug)] -pub struct XNotSupported; -  impl XConnection {      pub fn new() -> Result<XConnection, XNotSupported> {          // opening the libraries -        let xlib = try!(ffi::Xlib::open().map_err(|_| XNotSupported)); -        let xcursor = try!(ffi::Xcursor::open().map_err(|_| XNotSupported)); -        let xf86vmode = try!(ffi::Xf86vmode::open().map_err(|_| XNotSupported)); -        let xinput2 = try!(ffi::XInput2::open().map_err(|_| XNotSupported)); +        let xlib = try!(ffi::Xlib::open()); +        let xcursor = try!(ffi::Xcursor::open()); +        let xf86vmode = try!(ffi::Xf86vmode::open()); +        let xinput2 = try!(ffi::XInput2::open());          unsafe extern "C" fn x_error_callback(_: *mut ffi::Display, event: *mut ffi::XErrorEvent)                                                -> libc::c_int @@ -82,7 +80,7 @@ impl XConnection {          let display = unsafe {              let display = (xlib.XOpenDisplay)(ptr::null());              if display.is_null() { -                return Err(XNotSupported); +                return Err(XNotSupported::XOpenDisplayFailed);              }              display          }; @@ -104,3 +102,40 @@ impl Drop for XConnection {          unsafe { (self.xlib.XCloseDisplay)(self.display) };      }  } + +/// Error returned if this system doesn't have XLib or can't create an X connection. +#[derive(Clone, Debug)] +pub enum XNotSupported { +    /// Failed to load one or several shared libraries. +    LibraryOpenError(ffi::OpenError), +    /// Connecting to the X server with `XOpenDisplay` failed. +    XOpenDisplayFailed,     // TODO: add better message +} + +impl From<ffi::OpenError> for XNotSupported { +    fn from(err: ffi::OpenError) -> XNotSupported { +        XNotSupported::LibraryOpenError(err) +    } +} + +impl Error for XNotSupported { +    fn description(&self) -> &str { +        match *self { +            XNotSupported::LibraryOpenError(_) => "Failed to load one of xlib's shared libraries", +            XNotSupported::XOpenDisplayFailed => "Failed to open connection to X server", +        } +    } + +    fn cause(&self) -> Option<&Error> { +        match *self { +            XNotSupported::LibraryOpenError(ref err) => Some(err), +            _ => None +        } +    } +} + +impl fmt::Display for XNotSupported { +    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { +        formatter.write_str(self.description()) +    } +} @@ -106,11 +106,12 @@ pub trait GlContext {  }  /// Error that can happen while creating a window or a headless renderer. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Debug)]  pub enum CreationError {      OsError(String),      /// TODO: remove this error      NotSupported, +    NoBackendAvailable(Box<std::error::Error + Send>),      RobustnessNotSupported,      OpenGlVersionNotSupported,      NoAvailablePixelFormat, @@ -121,6 +122,7 @@ impl CreationError {          match *self {              CreationError::OsError(ref text) => &text,              CreationError::NotSupported => "Some of the requested attributes are not supported", +            CreationError::NoBackendAvailable(_) => "No backend is available",              CreationError::RobustnessNotSupported => "You requested robustness, but it is \                                                        not supported.",              CreationError::OpenGlVersionNotSupported => "The requested OpenGL version is not \ @@ -141,6 +143,13 @@ impl std::error::Error for CreationError {      fn description(&self) -> &str {          self.to_string()      } + +    fn cause(&self) -> Option<&std::error::Error> { +        match *self { +            CreationError::NoBackendAvailable(ref err) => Some(&**err), +            _ => None +        } +    }  }  /// Error that can happen when manipulating an OpenGL context. diff --git a/src/platform/linux/api_dispatch.rs b/src/platform/linux/api_dispatch.rs index e580ab1..f25bda9 100644 --- a/src/platform/linux/api_dispatch.rs +++ b/src/platform/linux/api_dispatch.rs @@ -19,10 +19,12 @@ use libc;  use api::wayland;  use api::x11;  use api::x11::XConnection; +use api::x11::XNotSupported;  enum Backend {      X(Arc<XConnection>), -    Wayland +    Wayland, +    Error(XNotSupported),  }  lazy_static!( @@ -31,7 +33,10 @@ lazy_static!(          if false && wayland::is_available() {              Backend::Wayland          } else { -            Backend::X(Arc::new(XConnection::new().unwrap())) +            match XConnection::new() { +                Ok(x) => Backend::X(Arc::new(x)), +                Err(e) => Backend::Error(e), +            }          }      };  ); @@ -65,7 +70,9 @@ pub enum MonitorID {      #[doc(hidden)]      X(x11::MonitorID),      #[doc(hidden)] -    Wayland(wayland::MonitorID) +    Wayland(wayland::MonitorID), +    #[doc(hidden)] +    None,  }  pub fn get_available_monitors() -> VecDeque<MonitorID> { @@ -78,6 +85,7 @@ pub fn get_available_monitors() -> VecDeque<MonitorID> {                                      .into_iter()                                      .map(MonitorID::X)                                      .collect(), +        Backend::Error(_) => { let mut d = VecDeque::new(); d.push_back(MonitorID::None); d},      }  } @@ -85,6 +93,7 @@ pub fn get_primary_monitor() -> MonitorID {      match *BACKEND {          Backend::Wayland => MonitorID::Wayland(wayland::get_primary_monitor()),          Backend::X(ref connec) => MonitorID::X(x11::get_primary_monitor(connec)), +        Backend::Error(_) => MonitorID::None,      }  } @@ -92,21 +101,24 @@ impl MonitorID {      pub fn get_name(&self) -> Option<String> {          match self {              &MonitorID::X(ref m) => m.get_name(), -            &MonitorID::Wayland(ref m) => m.get_name() +            &MonitorID::Wayland(ref m) => m.get_name(), +            &MonitorID::None => None,          }      }      pub fn get_native_identifier(&self) -> ::native_monitor::NativeMonitorId {          match self {              &MonitorID::X(ref m) => m.get_native_identifier(), -            &MonitorID::Wayland(ref m) => m.get_native_identifier() +            &MonitorID::Wayland(ref m) => m.get_native_identifier(), +            &MonitorID::None => unimplemented!()        // FIXME:           }      }      pub fn get_dimensions(&self) -> (u32, u32) {          match self {              &MonitorID::X(ref m) => m.get_dimensions(), -            &MonitorID::Wayland(ref m) => m.get_dimensions() +            &MonitorID::Wayland(ref m) => m.get_dimensions(), +            &MonitorID::None => (800, 600),     // FIXME:           }      }  } @@ -153,6 +165,7 @@ impl Window {          match *BACKEND {              Backend::Wayland => wayland::Window::new(builder).map(Window::Wayland),              Backend::X(ref connec) => x11::Window::new(connec, builder).map(Window::X), +            Backend::Error(ref error) => Err(CreationError::NoBackendAvailable(Box::new(error.clone())))          }      }  | 
