Compare commits

..
5 Commits
Author SHA1 Message Date
neo 0a73abdbc6 resolving merge conflicts 2026-08-25 20:15:19 +02:00
neo 61cfcf283f declared interfaces and more wrappers 2026-08-25 17:55:57 +02:00
neo aeab2375c8 license SPDX line, implementing first global state 2026-08-25 13:48:33 +02:00
neo_1993 215362f1bb first display run, simple-compd example 2026-08-25 12:37:41 +02:00
neo_1993 e692e4837d started display structure 2026-08-25 12:13:27 +02:00
11 changed files with 413 additions and 21 deletions
+6
View File
@@ -2,6 +2,12 @@
name = "wayland_server" name = "wayland_server"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
license = "GPL-2.0-only"
keywords = ["ffi", "wayland"]
[[example]]
name = "simple_compd"
path = "examples/simple_compd.rs"
[dependencies] [dependencies]
libc = "*" libc = "*"
+44
View File
@@ -0,0 +1,44 @@
// SPDX: GPL-2.0-only
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<Output>,
}
impl State {
pub fn new() -> Self {
Self { output_interface: Interface::<Output>::new() }
}
}
impl GlobalState for State {
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::new();
// 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()?;
// clean-up
drop(display);
Ok(())
}
+2
View File
@@ -1,3 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
use std::io::{Error, ErrorKind, Result}; use std::io::{Error, ErrorKind, Result};
use std::ptr::NonNull; use std::ptr::NonNull;
use crate::ffi::wl_array; use crate::ffi::wl_array;
+22
View File
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-only
use std::io;
use std::ptr::NonNull;
use crate::Wrapper;
use crate::ffi::wl_client;
pub struct Client {
raw: NonNull<wl_client>
}
impl Client {
pub(crate) fn from_raw(raw: *mut wl_client) -> Option<Self> {
NonNull::new(raw).map(| raw| Self { raw })
}
}
impl Wrapper for Client {
type T = wl_client;
fn get_raw(&self) -> std::ptr::NonNull<Self::T> {
self.raw
}
}
+61
View File
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0-only
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,
wl_display_add_destroy_listener, wl_display_add_global, wl_display_add_protocol_logger, wl_display_add_shm_format,
wl_display_add_socket, wl_display_add_socket_auto, wl_display_add_socket_fd, wl_display_flush_clients, wl_display_run,
wl_display_get_client_list, wl_display_get_destroy_listener, wl_display_get_event_loop, wl_display_get_serial,
wl_display_init_shm, wl_display_next_serial, wl_display_remove_global, wl_display_set_global_filter, wl_display_terminate
};
pub struct Display<'disp> {
raw: NonNull<wl_display>,
name: &'disp str,
}
impl<'disp> Display<'disp> {
pub fn new() -> Result<Self> {
let ptr = unsafe { wl_display_create() };
if ptr.is_null() {
return Err(Error::new(ErrorKind::Other, "cannot create wayland display"))
}
let raw = match NonNull::<wl_display>::new(ptr) {
Some(raw) => raw,
None => return Err(Error::new(ErrorKind::AddrNotAvailable, "cannot create display")),
};
let name = unsafe { wl_display_add_socket_auto(ptr) };
let name = unsafe {
let name = std::ffi::CStr::from_ptr(name as *mut i8);
name.to_str().expect("cannot get a socket name")
};
Ok(Self { raw, name })
}
pub fn get_name(&self) -> &str {
self.name
}
pub fn run(&self) -> Result<()> {
unsafe { wl_display_run(self.raw.as_ptr()) };
Ok(())
}
}
impl<'disp> Drop for Display<'disp> {
fn drop(&mut self) {
unsafe {
wl_display_destroy_clients(self.raw.as_ptr());
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::T> {
self.raw
}
}
+47 -18
View File
@@ -1,34 +1,36 @@
// SPDX-License-Identifier: GPL-2.0-only
use std::{ffi::CStr, os::fd::RawFd}; use std::{ffi::CStr, os::fd::RawFd};
use libc::epoll_event; use libc::epoll_event;
// ffi function types // ffi function types
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_event_loop_fd_func_t = fn(fd: i32, mask: u32, data: *mut libc::c_void) -> i32; pub(crate) type wl_event_loop_fd_func_t = unsafe extern "C" fn(fd: i32, mask: u32, data: *mut libc::c_void) -> i32;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_event_loop_timer_func_t = fn(data: *mut libc::c_void) -> i32; pub(crate) type wl_event_loop_timer_func_t = unsafe extern "C" fn(data: *mut libc::c_void) -> i32;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_event_loop_signal_func_t = fn(signal_number: i32, data: *mut libc::c_void) -> i32; pub(crate) type wl_event_loop_signal_func_t = unsafe extern "C" fn(signal_number: i32, data: *mut libc::c_void) -> i32;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_event_loop_idle_func_t = fn(data: *mut libc::c_void); pub(crate) type wl_event_loop_idle_func_t = unsafe extern "C" fn(data: *mut libc::c_void);
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_notify_func_t = fn(listener: *mut wl_listener, data: *mut libc::c_void); pub(crate) type wl_notify_func_t = unsafe extern "C" fn(listener: *mut wl_listener, data: *mut libc::c_void);
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_global_bind_func_t = fn(client: *mut wl_client, data: *mut libc::c_void, version: u32, id: u32); pub(crate) type wl_global_bind_func_t = unsafe extern "C" fn(client: *mut wl_client, data: *mut libc::c_void, version: u32, id: u32);
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_display_global_filter_func_t = fn(client: *const wl_client, global: *const wl_global, data: *mut libc::c_void) -> bool; pub(crate) type wl_display_global_filter_func_t = unsafe extern "C" fn(client: *const wl_client, global: *const wl_global, data: *mut libc::c_void) -> bool;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_client_for_each_resource_iterator_func_t = fn(resource: *mut wl_resource, user_data: *mut libc::c_void) -> wl_iterator_result; pub(crate) type wl_client_for_each_resource_iterator_func_t = unsafe extern "C" fn(resource: *mut wl_resource, user_data: *mut libc::c_void) -> wl_iterator_result;
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_user_data_destroy_func_t = fn(data: *mut libc::c_void); pub(crate) type wl_user_data_destroy_func_t = unsafe extern "C" fn(data: *mut libc::c_void);
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_resource_destroy_func_t = fn(resource: *mut wl_resource); pub(crate) type wl_resource_destroy_func_t = unsafe extern "C" fn(resource: *mut wl_resource);
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_protocol_logger_func_t = fn(user_data: *mut libc::c_void, direction: wl_protocol_logger_type, message: *const wl_protocol_logger_message); pub(crate) type wl_protocol_logger_func_t = unsafe extern "C" fn(user_data: *mut libc::c_void, direction: wl_protocol_logger_type, message: *const wl_protocol_logger_message);
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) type wl_dispatcher_func_t = fn(user_data: *const libc::c_void, target: *mut libc::c_void, opcode: u32, msg: *const wl_message, args: *mut wl_argument) -> i32; 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)] #[allow(non_camel_case_types)]
pub(crate) type wl_log_func_t = 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 // ffi data types and struct
const UNIX_PATH_MAX: usize = 108; const UNIX_PATH_MAX: usize = 108;
@@ -187,7 +189,7 @@ pub(crate) struct wl_message {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub(crate) struct wl_interface { pub(crate) struct wl_interface {
name: *const libc::c_char, name: *const libc::c_char,
version: i32, pub version: i32,
method_count: i32, method_count: i32,
method: *const wl_message, method: *const wl_message,
event_count: i32, event_count: i32,
@@ -338,6 +340,33 @@ pub(crate) struct wl_shm_pool {
sigbus_is_impossible: bool sigbus_is_impossible: bool
} }
// 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")] #[link(name = "wayland-server")]
unsafe extern "C" { unsafe extern "C" {
pub(crate) unsafe fn wl_array_add(array: *mut wl_array, size: usize) -> *mut libc::c_void; pub(crate) unsafe fn wl_array_add(array: *mut wl_array, size: usize) -> *mut libc::c_void;
@@ -371,7 +400,7 @@ unsafe extern "C" {
pub(crate) unsafe fn wl_display_add_global(); pub(crate) unsafe fn wl_display_add_global();
pub(crate) unsafe fn wl_display_add_protocol_logger(disp: *mut wl_display, func: wl_protocol_logger_func_t, user_data: *mut libc::c_void) -> *mut wl_protocol_logger; pub(crate) unsafe fn wl_display_add_protocol_logger(disp: *mut wl_display, func: wl_protocol_logger_func_t, user_data: *mut libc::c_void) -> *mut wl_protocol_logger;
pub(crate) unsafe fn wl_display_add_shm_format(disp: *mut wl_display, format: u32) -> u32; pub(crate) unsafe fn wl_display_add_shm_format(disp: *mut wl_display, format: u32) -> u32;
pub(crate) unsafe fn wl_display_add_socket_auto(disp: *mut wl_display) -> std::ffi::CStr; pub(crate) unsafe fn wl_display_add_socket_auto(disp: *mut wl_display) -> *mut u8;
pub(crate) unsafe fn wl_display_add_socket(disp: *mut wl_display, name: *const libc::c_char); pub(crate) unsafe fn wl_display_add_socket(disp: *mut wl_display, name: *const libc::c_char);
pub(crate) unsafe fn wl_display_add_socket_fd(disp: *mut wl_display, sock_fd: RawFd) -> i32; pub(crate) unsafe fn wl_display_add_socket_fd(disp: *mut wl_display, sock_fd: RawFd) -> i32;
pub(crate) unsafe fn wl_display_create() -> *mut wl_display; pub(crate) unsafe fn wl_display_create() -> *mut wl_display;
@@ -406,7 +435,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_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_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_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_display(global: *const wl_global) -> *mut wl_display;
pub(crate) unsafe fn wl_global_get_interface(global: *const wl_global) -> *const wl_interface; pub(crate) unsafe fn wl_global_get_interface(global: *const wl_global) -> *const wl_interface;
@@ -416,11 +445,11 @@ unsafe extern "C" {
pub(crate) unsafe fn wl_global_remove(global: *mut wl_global); 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_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_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: *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_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_list_remove(elm: *mut wl_list);
pub(crate) unsafe fn wl_log_set_handler_server(handler: wl_log_func_t); pub(crate) unsafe fn wl_log_set_handler_server(handler: wl_log_func_t);
+61
View File
@@ -0,0 +1,61 @@
// SPDX-License-Identifier: GPL-2.0-only
use std::io;
use std::ptr::NonNull;
use crate::Wrapper;
use crate::client::Client;
use crate::display::Display;
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) -> 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 = unsafe { &*(data as *const GlobalStateHolder) };
let _ = holder.state.handle_output_bind(&client, version, id);
}
struct GlobalStateHolder {
state: Box<dyn GlobalState>,
}
pub struct Global {
raw: NonNull<wl_global>,
state: Box<GlobalStateHolder>,
}
impl Global
{
pub fn new<S>(disp: &Display, state: S) -> io::Result<Self>
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 interface = Interface::<GlobalInterface>::new();
let ptr = unsafe {
wl_global_create(disp.as_raw_ptr(),
interface.get_raw().as_ptr(),
1,
data,
trampoline_handle_output_bind
)
};
let raw = NonNull::new(ptr)
.ok_or_else(||io::Error::last_os_error())?;
Ok(Self{raw,state})
}
}
impl Wrapper for Global {
type T = wl_global;
fn get_raw(&self) -> std::ptr::NonNull<Self::T> {
self.raw
}
}
+64
View File
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: 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<wl_interface>;
}
macro_rules! define_interface {
($name:ident, $raw:ident) => {
pub struct $name;
impl WaylandInterface for $name {
#[inline]
fn raw_interface() -> NonNull<wl_interface> {
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<T: WaylandInterface> {
_marker: PhantomData<T>
}
impl<T: WaylandInterface> Interface<T> {
pub const fn new() -> Self {
Self {
_marker: PhantomData
}
}
pub(crate) fn get_raw(&self) -> NonNull<wl_interface> {
T::raw_interface()
}
}
+16 -1
View File
@@ -1,6 +1,21 @@
#![feature(c_variadic)] // SPDX-License-Identifier: GPL-2.0-only
pub(crate) mod ffi; pub(crate) mod ffi;
// public api // public api
pub mod array; pub mod array;
pub mod client;
pub mod display;
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<Self::T>;
fn as_raw_ptr(&self) -> *mut Self::T {
self.get_raw().as_ptr()
}
}
+49
View File
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: 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<wl_list>,
}
impl List {
pub fn new() -> io::Result<Self> {
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::T> {
self.raw
}
}
+39
View File
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: 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<wl_resource>,
}
impl Resource {
pub(crate) fn from_raw(raw: *mut wl_resource) -> Option<Self> {
NonNull::new(raw).map(| raw| Self { raw })
}
pub fn new<I: WaylandInterface>(client: &Client, id: u32, interface: &Interface<I>) -> io::Result<Self> {
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::T> {
self.raw
}
}