From aeab2375c8c0e39b762f86bf694f602ec0230c2a Mon Sep 17 00:00:00 2001 From: neo Date: Tue, 25 Aug 2026 13:48:33 +0200 Subject: [PATCH] license SPDX line, implementing first global state --- Cargo.toml | 6 +++++ examples/simple_compd.rs | 20 ++++++++++++++++ src/array.rs | 2 ++ src/client.rs | 15 ++++++++++++ src/display.rs | 7 +++++- src/ffi.rs | 9 ++++++- src/global.rs | 52 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 6 ++++- 8 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 src/client.rs create mode 100644 src/global.rs diff --git a/Cargo.toml b/Cargo.toml index b7ce215..2299bcb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,12 @@ name = "wayland_server" version = "0.1.0" edition = "2024" +license = "GPL-2.0-only" +keywords = ["ffi", "wayland"] + +[[example]] +name = "simple_compd" +path = "examples/simple_compd.rs" [dependencies] libc = "*" \ No newline at end of file diff --git a/examples/simple_compd.rs b/examples/simple_compd.rs index 33a7462..36db29c 100644 --- a/examples/simple_compd.rs +++ b/examples/simple_compd.rs @@ -1,9 +1,29 @@ +// SPDX: GPL-2.0-only use std::io; +use wayland_server::client::Client; use wayland_server::display::Display; +use wayland_server::global::{Global, GlobalState}; + + +struct State { + +} +impl GlobalState for State { + fn handle_output_bind(&self, client: Client, version: u32, id: u32) { + todo!() + } +} fn main() -> io::Result<()> { + // Creating a compositor State + let state = State {}; + + // create a wayland display let display = Display::new()?; + // get the global registry + let global = Global::new(&display, state)?; + println!("Running wayland_display on {}", display.get_name()); display.run()?; diff --git a/src/array.rs b/src/array.rs index fa6fa6d..acdccdc 100644 --- a/src/array.rs +++ b/src/array.rs @@ -1,3 +1,5 @@ +// SPDX: GPL-2.0-only + use std::io::{Error, ErrorKind, Result}; use std::ptr::NonNull; use crate::ffi::wl_array; diff --git a/src/client.rs b/src/client.rs new file mode 100644 index 0000000..570b202 --- /dev/null +++ b/src/client.rs @@ -0,0 +1,15 @@ +// SPDX: GPL-2.0-only + +use std::io; +use std::ptr::NonNull; + +use crate::ffi::wl_client; + +pub struct Client { + raw: NonNull +} +impl Client { + pub(crate) fn from_raw(raw: *mut wl_client) -> Option { + NonNull::new(raw).map(| raw| Self { raw }) + } +} \ No newline at end of file diff --git a/src/display.rs b/src/display.rs index 16afab3..99e293e 100644 --- a/src/display.rs +++ b/src/display.rs @@ -1,3 +1,5 @@ +// SPDX: GPL-2.0-only + use std::{io::Error, ptr::NonNull}; use std::io::{ErrorKind, Result}; @@ -37,7 +39,10 @@ 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(()) diff --git a/src/ffi.rs b/src/ffi.rs index a4c1ee9..9380f96 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -1,3 +1,5 @@ +// SPDX: GPL-2.0-only + use std::{ffi::CStr, os::fd::RawFd}; use libc::epoll_event; @@ -338,6 +340,11 @@ pub(crate) struct wl_shm_pool { sigbus_is_impossible: bool } +// public static interfaces +unsafe extern "C" { + pub(crate) unsafe static wl_output_interface: wl_interface; +} + #[link(name = "wayland-server")] unsafe extern "C" { pub(crate) unsafe fn wl_array_add(array: *mut wl_array, size: usize) -> *mut libc::c_void; @@ -406,7 +413,7 @@ unsafe extern "C" { pub(crate) unsafe fn wl_event_source_remove(source: *mut wl_event_source) -> i32; pub(crate) unsafe fn wl_event_source_timer_update(source: *mut wl_event_source, ms_delay: i32) -> i32; - pub(crate) unsafe fn wl_global_create(disp: *mut wl_display, interface: *const wl_interface) -> *mut wl_global; + pub(crate) unsafe fn wl_global_create(disp: *mut wl_display, interface: *const wl_interface, version: i32, data: *mut libc::c_void, bind: wl_global_bind_func_t) -> *mut wl_global; pub(crate) unsafe fn wl_global_destroy(global: *mut wl_global); pub(crate) unsafe fn wl_global_get_display(global: *const wl_global) -> *mut wl_display; pub(crate) unsafe fn wl_global_get_interface(global: *const wl_global) -> *const wl_interface; diff --git a/src/global.rs b/src/global.rs new file mode 100644 index 0000000..4f66fb8 --- /dev/null +++ b/src/global.rs @@ -0,0 +1,52 @@ +// SPDX: GPL-2.0-only + +use std::io; +use std::ptr::NonNull; +use crate::client::Client; +use crate::display::Display; +use crate::ffi::{wl_client, wl_display, wl_global, wl_output_interface}; +use crate::ffi::wl_global_create; + +pub trait GlobalState { + fn handle_output_bind(&self, client: Client, version: u32, id: u32); +} + +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); +} + +struct GlobalStateHolder { + state: Box, +} + +pub struct Global { + raw: NonNull, + state: Box, +} +impl Global +{ + pub fn new(disp: &Display, state: S) -> io::Result + where + S: GlobalState + 'static, + { + let state = Box::new(GlobalStateHolder { state: Box::new(state) }); + let data = state.as_ref() as *const GlobalStateHolder as *mut libc::c_void; + + let ptr = unsafe { + wl_global_create(disp.get_raw_ptr(), + &wl_output_interface, + 1, + data, + trampoline_handle_output_bind + ) + }; + let raw = NonNull::new(ptr) + .ok_or_else(||io::Error::last_os_error())?; + + Ok(Self{raw,state}) + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 39aaded..b8f2b9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,11 @@ +// SPDX: GPL-2.0-only + #![feature(c_variadic)] pub(crate) mod ffi; // public api pub mod array; -pub mod display; \ No newline at end of file +pub mod client; +pub mod display; +pub mod global; \ No newline at end of file