// 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, } impl Display { pub fn new(name: Option) -> Result { 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::::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 { let events = unsafe {wl_display_dispatch(self.raw.as_ptr()) }; if events == -1 { None } else { Some(events) } } pub fn roundtrip(&self) -> std::io::Result { 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()) }; } }