defining first Display and Registry structs. Added Callback support for Registry.
This commit is contained in:
+125
@@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::{ffi::{c_char,c_void}, ptr::NonNull};
|
||||
|
||||
use crate::registry::ffi::{wl_proxy, wl_proxy_add_listener, wl_registry, wl_registry_listener};
|
||||
|
||||
mod ffi {
|
||||
use std::ffi::{c_char, c_void};
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub(super) struct wl_registry;
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub(super) struct wl_proxy;
|
||||
|
||||
// function types
|
||||
#[allow(non_camel_case_types)]
|
||||
pub(super) type registry_global_callback = unsafe extern "C" fn(*mut c_void, *mut wl_registry, u32, *const c_char, u32);
|
||||
#[allow(non_camel_case_types)]
|
||||
pub(super) type registry_global_remove_callback = unsafe extern "C" fn(*mut c_void, *mut wl_registry, u32);
|
||||
#[allow(non_camel_case_types)]
|
||||
pub(super) type cb_implementation = unsafe extern "C" fn();
|
||||
|
||||
#[repr(C)]
|
||||
pub(super) struct wl_registry_listener {
|
||||
pub global: Option<registry_global_callback>,
|
||||
pub global_remove: Option<registry_global_remove_callback>
|
||||
}
|
||||
#[link(name = "wayland-client")]
|
||||
unsafe extern "C" {
|
||||
pub(super) unsafe fn wl_proxy_add_listener(proxy: *mut wl_proxy, implementation: *const cb_implementation, data: *mut c_void);
|
||||
}
|
||||
}
|
||||
|
||||
// C->Rust trampoline functions
|
||||
unsafe extern "C" fn registry_handle_global(
|
||||
data: *mut c_void,
|
||||
_registry: *mut wl_registry,
|
||||
name: u32,
|
||||
interface: *const c_char,
|
||||
version: u32,
|
||||
) {
|
||||
let registry = unsafe {
|
||||
&mut *(data as *mut RegistryListener)
|
||||
};
|
||||
let interface = unsafe {
|
||||
CStr::from_ptr(interface)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
};
|
||||
|
||||
if let Some(callback) = registry.global.as_mut() {
|
||||
callback(interface, name, version)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn registry_handle_global_remove(
|
||||
data: *mut c_void,
|
||||
_registry: *mut wl_registry,
|
||||
name: u32,
|
||||
) {
|
||||
let registry = unsafe {
|
||||
&mut *(data as *mut RegistryListener)
|
||||
};
|
||||
|
||||
if let Some(callback) = registry.global_remove.as_mut() {
|
||||
callback(name)
|
||||
}
|
||||
}
|
||||
|
||||
// callback holder cell
|
||||
pub struct RegistryListener {
|
||||
global: Option<Box<dyn FnMut(String, u32, u32) + 'static>>,
|
||||
global_remove: Option<Box<dyn FnMut(u32) + 'static>>,
|
||||
}
|
||||
|
||||
// the main registry cell
|
||||
pub struct Registry {
|
||||
raw: NonNull<wl_registry>,
|
||||
|
||||
callbacks: Box<RegistryListener>,
|
||||
|
||||
listener: Box<wl_registry_listener>,
|
||||
}
|
||||
impl Registry {
|
||||
pub fn on_global<F>(&mut self, global: F)
|
||||
where
|
||||
F: FnMut(String, u32, u32) + 'static
|
||||
{
|
||||
self.callbacks.global = Some(Box::new(global));
|
||||
}
|
||||
pub fn on_global_remove<F>(&mut self, global_remove: F)
|
||||
where
|
||||
F: FnMut(u32) + 'static
|
||||
{
|
||||
self.callbacks.global_remove = Some(Box::new(global_remove));
|
||||
}
|
||||
pub fn registry_listener(&mut self) {
|
||||
unsafe {
|
||||
wl_proxy_add_listener(
|
||||
self.raw.as_ptr() as *mut wl_proxy,
|
||||
&*self.listener as *const _ as *const ffi::cb_implementation,
|
||||
self.callbacks.as_mut() as *mut _ as *mut c_void)
|
||||
};
|
||||
}
|
||||
}
|
||||
impl From<*mut c_void> for Registry {
|
||||
fn from(value: *mut c_void) -> Self {
|
||||
let raw = NonNull::new(value as *mut wl_registry)
|
||||
.expect("unable to get display registry");
|
||||
|
||||
Self {
|
||||
raw,
|
||||
callbacks: Box::new(
|
||||
RegistryListener { global: None, global_remove: None }
|
||||
),
|
||||
listener: Box::new(ffi::wl_registry_listener {
|
||||
global: Some(registry_handle_global),
|
||||
global_remove: Some(registry_handle_global_remove),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user