macro_rules! offset_of(
($ty:ty, $field:ident) => {
&(*(0 as *const $ty)).$field as *const _ as usize
}
);
macro_rules! container_of (
($ptr: expr, $container: ty, $field: ident) => {
($ptr as *mut u8).offset(-(offset_of!($container, $field) as isize)) as *mut $container
}
);
macro_rules! wl_list_for_each {
($ptr: expr, $field: ident, ($pos: ident : $container: ty) => $body: block) => {
let mut $pos: *mut $container;
$pos = container_of!($ptr.next, $container, $field);
loop {
if &(*$pos).$field as *const _ == &$ptr as *const _ {
break
}
{ $body }
$pos = container_of!((*$pos).$field.next, $container, $field);
}
}
}
#[macro_export]
macro_rules! wlr_log {
($verb: expr, $($msg:tt)*) => {{
macro_rules! c_str {
($s:expr) => {
concat!($s, "\0").as_ptr()
as *const $crate::wlroots_sys::libc::c_char
}
}
use $crate::wlroots_sys::_wlr_log;
use $crate::wlroots_sys::wlr_log_importance::*;
use ::std::ffi::CString;
unsafe {
let fmt = CString::new(format!($($msg)*))
.expect("Could not convert log message to C string");
let raw = fmt.into_raw();
_wlr_log($verb, c_str!("[%s:%lu] %s"),
c_str!(file!()), line!(), raw);
CString::from_raw(raw);
}
}}
}
macro_rules! wayland_listener {
($pub: vis $struct_name: ident, $data: ty, $([
$($listener: ident => $listener_func: ident :
|$($func_arg:ident: $func_type:ty,)*| unsafe $body: block;)*])+) => {
#[repr(C)]
$pub struct $struct_name {
data: $data,
$($($listener: $crate::wlroots_sys::wl_listener),*)*
}
impl $struct_name {
pub(crate) fn new(data: $data) -> Box<$struct_name> {
use $crate::wlroots_sys::server::WAYLAND_SERVER_HANDLE;
Box::new($struct_name {
data,
$($($listener: unsafe {
let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_init,
&mut listener.link as *mut _ as _);
::std::ptr::write(&mut listener.notify, Some($struct_name::$listener_func));
listener
}),*)*
})
}
$($(pub(crate) unsafe extern "C" fn $listener(&mut self)
-> *mut $crate::wlroots_sys::wl_listener {
&mut self.$listener as *mut _
})*)*
$($(pub(crate) unsafe extern "C" fn $listener_func(listener:
*mut $crate::wlroots_sys::wl_listener,
data: *mut $crate::libc::c_void) {
let manager: &mut $struct_name = &mut (*container_of!(listener,
$struct_name,
$listener));
$crate::utils::handle_unwind(
::std::panic::catch_unwind(
::std::panic::AssertUnwindSafe(|| {
(|$($func_arg: $func_type,)*| { $body })(manager, data)
})));
})*)*
}
}
}
macro_rules! wayland_listener_static {
(static mut $static_manager: ident;
$(($manager: ident, $builder: ident):
$([
$(
$([$($extra_callback_name: ident: $extra_callback_type: ty),+])*
($fn_type: ty, $listener: ident, $builder_func: ident) => ($notify: ident, $callback: ident):
|$($func_arg: ident: $func_type: ty,)*| unsafe $body: block;
)*
])+
)+
) => {
$(
#[derive(Default)]
#[allow(dead_code)]
pub struct $builder {
$($(pub(crate) $callback: ::std::option::Option<$fn_type>,)*
$($($($extra_callback_name: ::std::option::Option<$extra_callback_type>,)*)*)*)*
}
impl $builder {
$($(
pub fn $builder_func(mut self, $callback: $fn_type) -> Self {
self.$callback = ::std::option::Option::Some($callback);
self
}
$($(
pub fn $extra_callback_name(mut self, $extra_callback_name: $extra_callback_type) -> Self {
self.$extra_callback_name = ::std::option::Option::Some($extra_callback_name);
self
}
)*)*
)*)*
}
)*
$(
#[repr(C)]
pub(crate) struct $manager {
$($(
pub(crate) $listener: $crate::wlroots_sys::wl_listener,
$callback: ::std::option::Option<$fn_type>,
$($($extra_callback_name: ::std::option::Option<$extra_callback_type>),*)*
)*)*
}
pub(crate) static mut $static_manager: $manager = $manager {
$($(
$listener: $crate::wlroots_sys::wl_listener {
link: {
$crate::wlroots_sys::wl_list {
prev: ::std::ptr::null_mut(),
next: ::std::ptr::null_mut()}},
notify: ::std::option::Option::None },
$callback: ::std::option::Option::None,
$($($extra_callback_name: ::std::option::Option::None),*)*
)*)*
};
impl $manager {
pub(crate) unsafe fn build(builder: $builder) -> &'static mut $manager {
$($(
$static_manager.$listener = {
let mut listener: $crate::wlroots_sys::wl_listener = ::std::mem::zeroed();
use $crate::wlroots_sys::server::WAYLAND_SERVER_HANDLE;
ffi_dispatch!(WAYLAND_SERVER_HANDLE,
wl_list_init,
&mut listener.link as *mut _ as _);
::std::ptr::write(&mut listener.notify, std::option::Option::Some($notify));
listener
};
$static_manager.$callback = builder.$callback;
$($(
$static_manager.$extra_callback_name = builder.$extra_callback_name;
)*)*
)*)*
&mut $static_manager
}
}
)*
$(
$(
$(
unsafe extern "C" fn $notify(listener: *mut $crate::wlroots_sys::wl_listener,
data: *mut $crate::libc::c_void) {
let manager: &mut $manager = &mut *container_of!(listener,
$manager,
$listener);
$crate::utils::handle_unwind(
::std::panic::catch_unwind(
::std::panic::AssertUnwindSafe(|| {
(|$($func_arg: $func_type,)*| { $body })(manager, data)
})))
}
)*
)*
)*
}
}
#[cfg(feature = "unstable")]
#[macro_export]
macro_rules! with_handles {
([($handle_name: ident: $unhandle_name: block)] => $body: block) => {
$unhandle_name.run(|$handle_name| {
$body
})
};
([($handle_name1: ident: $unhandle_name1: block),
($handle_name2: ident: $unhandle_name2: block),
$($rest: tt)*] => $body: block) => {
$unhandle_name1.run(|$handle_name1| {
with_handles!([($handle_name2: $unhandle_name2), $($rest)*] => $body)
}).and_then(|n: $crate::utils::HandleResult<_>| n)
};
([($handle_name: ident: $unhandle_name: block), $($rest: tt)*] => $body: block) => {
$unhandle_name.run(|$handle_name| {
with_handles!([$($rest)*] => $body)
}).and_then(|n: $crate::utils::HandleResult<_>| n)
};
}