use Proxy;
use event_queue::{EventQueue, create_event_queue};
use generated::client::wl_display::WlDisplay;
use std::ffi::{CStr, CString, OsStr};
use std::io;
use std::os::unix::ffi::OsStrExt;
use wayland_sys::client::*;
#[derive(Debug)]
pub enum ConnectError {
NoWaylandLib,
NoCompositorListening,
}
#[derive(Debug)]
pub enum FatalError {
Io(io::Error),
Protocol {
interface: String,
proxy_id: u32,
error_code: u32,
},
}
pub fn default_connect() -> Result<(WlDisplay, EventQueue), ConnectError> {
if !::wayland_sys::client::is_lib_available() {
return Err(ConnectError::NoWaylandLib);
}
let ptr = unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_connect,
::std::ptr::null()
)
};
if ptr.is_null() {
Err(ConnectError::NoCompositorListening)
} else {
let display = unsafe { WlDisplay::from_ptr_new(ptr as *mut _) };
let eventiter = unsafe { create_event_queue(display.ptr() as *mut wl_display, None) };
Ok((display, eventiter))
}
}
pub fn connect_to(name: &OsStr) -> Result<(WlDisplay, EventQueue), ConnectError> {
if !::wayland_sys::client::is_lib_available() {
return Err(ConnectError::NoWaylandLib);
}
let name = CString::new(name.as_bytes().to_owned()).map_err(|_| {
ConnectError::NoCompositorListening
})?;
let ptr = unsafe { ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_connect, name.as_ptr()) };
if ptr.is_null() {
Err(ConnectError::NoCompositorListening)
} else {
let display = unsafe { WlDisplay::from_ptr_new(ptr as *mut _) };
let eventiter = unsafe { create_event_queue(display.ptr() as *mut wl_display, None) };
Ok((display, eventiter))
}
}
impl WlDisplay {
pub fn flush(&self) -> io::Result<i32> {
let ret = unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_flush,
self.ptr() as *mut _
)
};
if ret >= 0 {
Ok(ret)
} else {
Err(io::Error::last_os_error())
}
}
pub fn create_event_queue(&self) -> EventQueue {
let evq = unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_create_queue,
self.ptr() as *mut _
)
};
unsafe { create_event_queue(self.ptr() as *mut _, Some(evq)) }
}
pub fn last_error(&self) -> Option<FatalError> {
let err = unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_get_error,
self.ptr() as *mut _
)
};
if err == 0 {
None
} else if err == ::libc::EPROTO {
let mut interface = ::std::ptr::null_mut();
let mut id = 0;
let code = unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_get_protocol_error,
self.ptr() as *mut _,
&mut interface,
&mut id
)
};
let interface = if interface.is_null() {
"<unkown interface>".to_owned()
} else {
unsafe { CStr::from_ptr((*interface).name) }
.to_string_lossy()
.into_owned()
};
Some(FatalError::Protocol {
interface: interface,
proxy_id: id,
error_code: code,
})
} else {
Some(FatalError::Io(io::Error::from_raw_os_error(err)))
}
}
pub unsafe fn get_fd(&self) -> ::std::os::unix::io::RawFd {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_get_fd,
self.ptr() as *mut _
)
}
}
impl Drop for WlDisplay {
fn drop(&mut self) {
unsafe {
ffi_dispatch!(
WAYLAND_CLIENT_HANDLE,
wl_display_disconnect,
self.ptr() as *mut _
)
}
}
}