From 61cfcf283f22509aeb545d59da88b64e5b89161e Mon Sep 17 00:00:00 2001 From: neo Date: Tue, 25 Aug 2026 17:55:57 +0200 Subject: [PATCH] declared interfaces and more wrappers --- examples/simple_compd.rs | 21 +++++++++---- src/client.rs | 7 +++++ src/display.rs | 11 ++++--- src/ffi.rs | 30 ++++++++++++++++--- src/global.rs | 21 +++++++++---- src/interface.rs | 64 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 16 ++++++++-- src/list.rs | 49 ++++++++++++++++++++++++++++++ src/resource.rs | 39 ++++++++++++++++++++++++ 9 files changed, 235 insertions(+), 23 deletions(-) create mode 100644 src/interface.rs create mode 100644 src/list.rs create mode 100644 src/resource.rs diff --git a/examples/simple_compd.rs b/examples/simple_compd.rs index 36db29c..07d3a56 100644 --- a/examples/simple_compd.rs +++ b/examples/simple_compd.rs @@ -3,26 +3,35 @@ use std::io; use wayland_server::client::Client; use wayland_server::display::Display; use wayland_server::global::{Global, GlobalState}; - +use wayland_server::interface::{Interface, Output}; +use wayland_server::resource::Resource; struct State { - + output_interface: Interface, +} +impl State { + pub fn new() -> Self { + Self { output_interface: Interface::::new() } + } } impl GlobalState for State { - fn handle_output_bind(&self, client: Client, version: u32, id: u32) { - todo!() + fn handle_output_bind(&self, client: &Client, _version: u32, id: u32) -> io::Result<()>{ + let resource = Resource::new(&client, id, &self.output_interface)?; + + + Ok(()) } } fn main() -> io::Result<()> { // Creating a compositor State - let state = State {}; + let state = State::new(); // create a wayland display let display = Display::new()?; // get the global registry - let global = Global::new(&display, state)?; + let _global = Global::new(&display, state)?; println!("Running wayland_display on {}", display.get_name()); diff --git a/src/client.rs b/src/client.rs index 570b202..fe51c89 100644 --- a/src/client.rs +++ b/src/client.rs @@ -3,6 +3,7 @@ use std::io; use std::ptr::NonNull; +use crate::Wrapper; use crate::ffi::wl_client; pub struct Client { @@ -12,4 +13,10 @@ impl Client { pub(crate) fn from_raw(raw: *mut wl_client) -> Option { NonNull::new(raw).map(| raw| Self { raw }) } +} +impl Wrapper for Client { + type T = wl_client; + fn get_raw(&self) -> std::ptr::NonNull { + self.raw + } } \ No newline at end of file diff --git a/src/display.rs b/src/display.rs index 99e293e..c064f9f 100644 --- a/src/display.rs +++ b/src/display.rs @@ -3,6 +3,7 @@ use std::{io::Error, ptr::NonNull}; use std::io::{ErrorKind, Result}; +use crate::Wrapper; // pull in the ffi-bindings use crate::ffi::{wl_display, wl_display_create, wl_display_destroy, wl_display_destroy_clients, wl_display_add_client_created_listener, @@ -39,10 +40,6 @@ impl<'disp> Display<'disp> { pub fn get_name(&self) -> &str { self.name } - - pub(crate) fn get_raw_ptr(&self) -> *mut wl_display { - self.raw.as_ptr() - } pub fn run(&self) -> Result<()> { unsafe { wl_display_run(self.raw.as_ptr()) }; Ok(()) @@ -55,4 +52,10 @@ impl<'disp> Drop for Display<'disp> { wl_display_destroy(self.raw.as_ptr()); } } +} +impl<'disp> Wrapper for Display<'disp> { + type T = wl_display; + fn get_raw(&self) -> std::ptr::NonNull { + self.raw + } } \ No newline at end of file diff --git a/src/ffi.rs b/src/ffi.rs index 9380f96..84642ee 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -30,7 +30,7 @@ pub(crate) type wl_protocol_logger_func_t = unsafe extern "C" fn(user_data: *mut #[allow(non_camel_case_types)] pub(crate) type wl_dispatcher_func_t = unsafe extern "C" fn(user_data: *const libc::c_void, target: *mut libc::c_void, opcode: u32, msg: *const wl_message, args: *mut wl_argument) -> i32; #[allow(non_camel_case_types)] -pub(crate) type wl_log_func_t = unsafe extern "C" fn(fmt: *const libc::c_char, args: std::ffi::VaList); +pub(crate) type wl_log_func_t = unsafe extern "C" fn(fmt: *const libc::c_char, ...); // ffi data types and struct const UNIX_PATH_MAX: usize = 108; @@ -189,7 +189,7 @@ pub(crate) struct wl_message { #[allow(non_camel_case_types)] pub(crate) struct wl_interface { name: *const libc::c_char, - version: i32, + pub version: i32, method_count: i32, method: *const wl_message, event_count: i32, @@ -342,7 +342,29 @@ pub(crate) struct wl_shm_pool { // public static interfaces unsafe extern "C" { + pub(crate) unsafe static wl_buffer_interface: wl_interface; + pub(crate) unsafe static wl_callback_interface: wl_interface; + pub(crate) unsafe static wl_compositor_interface: wl_interface; + pub(crate) unsafe static wl_data_device_interface: wl_interface; + pub(crate) unsafe static wl_data_device_manager_interface: wl_interface; + pub(crate) unsafe static wl_data_offer_interface: wl_interface; + pub(crate) unsafe static wl_data_source_interface: wl_interface; + pub(crate) unsafe static wl_display_interface: wl_interface; + pub(crate) unsafe static wl_global_interface: wl_interface; + pub(crate) unsafe static wl_keyboard_interface: wl_interface; pub(crate) unsafe static wl_output_interface: wl_interface; + pub(crate) unsafe static wl_pointer_interface: wl_interface; + pub(crate) unsafe static wl_region_interface: wl_interface; + pub(crate) unsafe static wl_registry_interface: wl_interface; + pub(crate) unsafe static wl_seat_interface: wl_interface; + pub(crate) unsafe static wl_shell_interface: wl_interface; + pub(crate) unsafe static wl_shell_surface_interface: wl_interface; + pub(crate) unsafe static wl_shm_interface: wl_interface; + pub(crate) unsafe static wl_shm_pool_interface: wl_interface; + pub(crate) unsafe static wl_subcompositor_interface: wl_interface; + pub(crate) unsafe static wl_subsurface_interface: wl_interface; + pub(crate) unsafe static wl_surface_interface: wl_interface; + pub(crate) unsafe static wl_touch_interface: wl_interface; } #[link(name = "wayland-server")] @@ -423,11 +445,11 @@ unsafe extern "C" { pub(crate) unsafe fn wl_global_remove(global: *mut wl_global); pub(crate) unsafe fn wl_global_set_user_data(global: *mut wl_global, data: *mut libc::c_void); - pub(crate) unsafe fn wl_list_empty(list: *const wl_list); + pub(crate) unsafe fn wl_list_empty(list: *const wl_list)->bool; pub(crate) unsafe fn wl_list_init(list: *mut wl_list); pub(crate) unsafe fn wl_list_insert(list: *mut wl_list, elm: *mut wl_list); pub(crate) unsafe fn wl_list_insert_list(list: *mut wl_list, other: *mut wl_list); - pub(crate) unsafe fn wl_list_length(list: *const wl_list); + pub(crate) unsafe fn wl_list_length(list: *const wl_list) -> usize; pub(crate) unsafe fn wl_list_remove(elm: *mut wl_list); pub(crate) unsafe fn wl_log_set_handler_server(handler: wl_log_func_t); diff --git a/src/global.rs b/src/global.rs index 4f66fb8..fd9e4f6 100644 --- a/src/global.rs +++ b/src/global.rs @@ -2,21 +2,23 @@ use std::io; use std::ptr::NonNull; +use crate::Wrapper; use crate::client::Client; use crate::display::Display; -use crate::ffi::{wl_client, wl_display, wl_global, wl_output_interface}; +use crate::interface::{Interface,Global as GlobalInterface}; +use crate::ffi::{wl_client, wl_global,}; use crate::ffi::wl_global_create; pub trait GlobalState { - fn handle_output_bind(&self, client: Client, version: u32, id: u32); + fn handle_output_bind(&self, client: &Client, version: u32, id: u32) -> std::io::Result<()>; } unsafe extern "C" fn trampoline_handle_output_bind(client: *mut wl_client, data: *mut libc::c_void, version: u32, id: u32) { let Some(client) = Client::from_raw(client) else { return; }; - let holder = &*(data as *const GlobalStateHolder); - holder.state.handle_output_bind(client, version, id); + let holder = unsafe { &*(data as *const GlobalStateHolder) }; + let _ = holder.state.handle_output_bind(&client, version, id); } struct GlobalStateHolder { @@ -35,10 +37,11 @@ impl Global { let state = Box::new(GlobalStateHolder { state: Box::new(state) }); let data = state.as_ref() as *const GlobalStateHolder as *mut libc::c_void; + let interface = Interface::::new(); let ptr = unsafe { - wl_global_create(disp.get_raw_ptr(), - &wl_output_interface, + wl_global_create(disp.as_raw_ptr(), + interface.get_raw().as_ptr(), 1, data, trampoline_handle_output_bind @@ -49,4 +52,10 @@ impl Global Ok(Self{raw,state}) } +} +impl Wrapper for Global { + type T = wl_global; + fn get_raw(&self) -> std::ptr::NonNull { + self.raw + } } \ No newline at end of file diff --git a/src/interface.rs b/src/interface.rs new file mode 100644 index 0000000..be390c7 --- /dev/null +++ b/src/interface.rs @@ -0,0 +1,64 @@ +// SPDX: GPL-2.0-only + +use std::io; +use std::marker::PhantomData; +use std::ptr::{addr_of,NonNull}; +use crate::Wrapper; +use crate::ffi::{wl_buffer_interface, wl_callback_interface, wl_compositor_interface, wl_data_device_interface, wl_data_device_manager_interface, wl_data_offer_interface, wl_data_source_interface, wl_display_interface, wl_global_interface, wl_interface, wl_keyboard_interface, wl_output_interface, wl_pointer_interface, wl_region_interface, wl_registry_interface, wl_seat_interface, wl_shell_interface, wl_shell_surface_interface, wl_shm_interface, wl_shm_pool_interface, wl_subcompositor_interface, wl_subsurface_interface, wl_surface_interface, wl_touch_interface}; + +pub trait WaylandInterface { + fn raw_interface() -> NonNull; +} + +macro_rules! define_interface { + ($name:ident, $raw:ident) => { + pub struct $name; + + impl WaylandInterface for $name { + #[inline] + fn raw_interface() -> NonNull { + unsafe { NonNull::from(&$raw) } + } + } + }; +} + +// defining wayland interfaces +define_interface!(Buffer, wl_buffer_interface); +define_interface!(Calback, wl_callback_interface); +define_interface!(Compositor, wl_compositor_interface); +define_interface!(DataDevice, wl_data_device_interface); +define_interface!(DataDeviceManager, wl_data_device_manager_interface); +define_interface!(DataOffer, wl_data_offer_interface); +define_interface!(DataSource, wl_data_source_interface); +define_interface!(Display, wl_display_interface); +define_interface!(Global, wl_global_interface); +define_interface!(Keyboard, wl_keyboard_interface); +define_interface!(Output, wl_output_interface); +define_interface!(Pointer, wl_pointer_interface); +define_interface!(Region, wl_region_interface); +define_interface!(Registry, wl_registry_interface); +define_interface!(Seat, wl_seat_interface); +define_interface!(Shell, wl_shell_interface); +define_interface!(ShellSurface, wl_shell_surface_interface); +define_interface!(Shm, wl_shm_interface); +define_interface!(ShmPool, wl_shm_pool_interface); +define_interface!(Subcompositor, wl_subcompositor_interface); +define_interface!(Subsurface, wl_subsurface_interface); +define_interface!(Surface, wl_surface_interface); +define_interface!(Touch, wl_touch_interface); + +pub struct Interface { + _marker: PhantomData +} +impl Interface { + pub const fn new() -> Self { + Self { + _marker: PhantomData + } + } + + pub(crate) fn get_raw(&self) -> NonNull { + T::raw_interface() + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b8f2b9e..67a5bd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,21 @@ // SPDX: GPL-2.0-only -#![feature(c_variadic)] - pub(crate) mod ffi; // public api pub mod array; pub mod client; pub mod display; -pub mod global; \ No newline at end of file +pub mod global; +pub mod interface; +pub mod list; +pub mod resource; + +pub(crate) trait Wrapper { + type T; + + fn get_raw(&self) -> std::ptr::NonNull; + fn as_raw_ptr(&self) -> *mut Self::T { + self.get_raw().as_ptr() + } +} \ No newline at end of file diff --git a/src/list.rs b/src/list.rs new file mode 100644 index 0000000..d212beb --- /dev/null +++ b/src/list.rs @@ -0,0 +1,49 @@ +// SPDX: GPL-2.0-only + +use std::io; +use std::ptr::NonNull; +use crate::Wrapper; +use crate::ffi::wl_list; +use crate::ffi::{ + wl_list_init, wl_list_insert, wl_list_insert_list, + wl_list_empty, wl_list_length, wl_list_remove, +}; + +pub struct List { + raw: NonNull, +} +impl List { + pub fn new() -> io::Result { + let list = std::ptr::null_mut(); + unsafe { wl_list_init(list) }; + + let Some(raw) = NonNull::new(list) else { + return Err(io::Error::last_os_error()); + }; + + Ok(Self { raw }) + } + pub fn insert(&self, elm: &List) { + unsafe { wl_list_insert(self.as_raw_ptr(), elm.as_raw_ptr()) }; + } + pub fn insert_list(&self, other: &List) { + unsafe { wl_list_insert_list(self.as_raw_ptr(), other.as_raw_ptr()) }; + } + pub fn length(&self) -> usize { + let length = unsafe { wl_list_length(self.as_raw_ptr())}; + length + } + pub fn empty(&self) -> bool { + let ret: bool = unsafe { wl_list_empty(self.as_raw_ptr()) }; + ret + } + pub fn remove(&self, elm: &List) { + unsafe { wl_list_remove(elm.as_raw_ptr()) }; + } +} +impl Wrapper for List { + type T = wl_list; + fn get_raw(&self) -> std::ptr::NonNull { + self.raw + } +} \ No newline at end of file diff --git a/src/resource.rs b/src/resource.rs new file mode 100644 index 0000000..95dc2b0 --- /dev/null +++ b/src/resource.rs @@ -0,0 +1,39 @@ +//SPDX: GPL-2.0-only + +use std::io; +use std::ptr::NonNull; + +use crate::Wrapper; +use crate::client::Client; +use crate::ffi::{wl_resource, wl_resource_create,wl_interface}; +use crate::interface::{WaylandInterface,Interface}; + +pub struct Resource { + raw: NonNull, +} +impl Resource { + pub(crate) fn from_raw(raw: *mut wl_resource) -> Option { + NonNull::new(raw).map(| raw| Self { raw }) + } + + pub fn new(client: &Client, id: u32, interface: &Interface) -> io::Result { + let ptr = unsafe { wl_resource_create( + client.as_raw_ptr(), + interface.get_raw().as_ptr(), + interface.get_raw().read().version, + id + )}; + + let Some(raw) = NonNull::new(ptr) else { + return Err(io::Error::last_os_error()); + }; + Ok(Self { raw }) + } +} +impl Wrapper for Resource { + type T = wl_resource; + + fn get_raw(&self) -> std::ptr::NonNull { + self.raw + } +} \ No newline at end of file