97 lines
3.2 KiB
Rust
97 lines
3.2 KiB
Rust
// SPDX-License-Identifier: GPL-2.0-only
|
|
use std::{env, fmt, io::{Error, ErrorKind}, ptr::NonNull};
|
|
use crate::{display::ffi::{wl_display_dispatch, wl_proxy, wl_proxy_get_version, wl_proxy_marshal_flags, wl_registry_interface}, registry::Registry};
|
|
|
|
mod ffi {
|
|
use std::ffi::{c_char, c_int,c_void};
|
|
|
|
// relevant type definitions
|
|
#[repr(C)]
|
|
#[allow(non_camel_case_types)]
|
|
pub(super) struct wl_display;
|
|
#[repr(C)]
|
|
#[allow(non_camel_case_types)]
|
|
pub(super) struct wl_proxy;
|
|
#[repr(C)]
|
|
#[allow(non_camel_case_types)]
|
|
pub(super) struct wl_interface;
|
|
|
|
#[link(name = "wayland-client")]
|
|
unsafe extern "C" {
|
|
// relevant public static
|
|
pub(crate) unsafe static wl_registry_interface: wl_interface;
|
|
|
|
// relevant function definitions
|
|
pub(super) unsafe fn wl_display_connect(name: *const c_char) -> *mut c_void;
|
|
pub(super) unsafe fn wl_display_disconnect(disp: *mut wl_display);
|
|
pub(super) unsafe fn wl_display_dispatch(disp: *mut wl_display) -> c_int;
|
|
pub(super) unsafe fn wl_display_roundtrip(disp: *mut wl_display) -> c_int;
|
|
pub(super) unsafe fn wl_proxy_marshal_flags(proxy: *mut wl_proxy, opcode: u32, interface: *const wl_interface, version: u32, flags: u32, ptr: *mut c_void) -> *mut c_void;
|
|
pub(super) unsafe fn wl_proxy_get_version(proxy: *mut wl_proxy) -> u32;
|
|
}
|
|
}
|
|
|
|
use ffi::wl_display;
|
|
|
|
// core wayland elemenent: Display
|
|
pub struct Display {
|
|
raw: NonNull<wl_display>,
|
|
}
|
|
impl Display {
|
|
pub fn new(name: Option<String>) -> Result<Self, std::io::Error> {
|
|
let sock_name: String = if name.is_some() {
|
|
name.unwrap()
|
|
} else {
|
|
let env_name = env::var("WAYLAND_DISPLAY");
|
|
if env_name.is_ok() {
|
|
env_name.unwrap()
|
|
} else {
|
|
"wayland-0".into()
|
|
}
|
|
};
|
|
let binding = std::ffi::CString::new(sock_name).unwrap();
|
|
let str = binding.as_c_str();
|
|
let raw = unsafe { ffi::wl_display_connect(str.as_ptr()) };
|
|
|
|
let raw = NonNull::<wl_display>::new(raw as *mut wl_display)
|
|
.expect("Failed to connect to Wayland display.");
|
|
|
|
Ok(Self{raw})
|
|
}
|
|
pub fn get_registry(&self) -> Registry {
|
|
let registry = unsafe {
|
|
wl_proxy_marshal_flags(self.raw.as_ptr() as *mut wl_proxy,
|
|
1,
|
|
&wl_registry_interface,
|
|
wl_proxy_get_version(self.raw.as_ptr() as *mut wl_proxy),
|
|
0,
|
|
std::ptr::null_mut()
|
|
)};
|
|
|
|
return Registry::from(registry);
|
|
}
|
|
pub fn dispatch(&self) -> Option<i32> {
|
|
let events = unsafe {wl_display_dispatch(self.raw.as_ptr()) };
|
|
|
|
if events == -1 {
|
|
None
|
|
} else {
|
|
Some(events)
|
|
}
|
|
}
|
|
pub fn roundtrip(&self) -> std::io::Result<i32> {
|
|
let r = unsafe { ffi::wl_display_roundtrip(self.raw.as_ptr()) };
|
|
|
|
if r >= 0 {
|
|
Ok(r)
|
|
} else {
|
|
Err(Error::new(ErrorKind::Other, "unable to process server messages"))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Drop for Display {
|
|
fn drop(&mut self) {
|
|
unsafe { ffi::wl_display_disconnect(self.raw.as_ptr()) };
|
|
}
|
|
} |