blob: d5c338708f44faa1ad4a9c78c3dbffdd8e939160 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(unused_macros)]
use std::convert::{From, Into};
use std::marker::PhantomData;
use std::ops;
// Put these uglies here
macro_rules! offset_of {
($container:ty, $( $field:ident ).+) => ({
let base = std::mem::MaybeUninit::<$container>::uninit();
let base_ptr = base.as_ptr();
let field_ptr = std::ptr::addr_of!((*base_ptr).$( $field ).+);
(field_ptr as usize) - (base_ptr as usize)
})
}
macro_rules! container_of {
($ptr:expr, $container:ty, $( $field:ident ).+) => ({
(($ptr as usize) - offset_of!($container, $( $field ).+)) as *const $container
})
}
macro_rules! container_of_mut {
($ptr:expr, $container:ty, $( $field:ident ).+) => ({
(($ptr as usize) - offset_of!($container, $( $field ).+)) as *mut $container
})
}
#[derive(Clone)]
pub struct WlListIter<'a, T: 'a> {
offset: usize,
head: *const wl_list,
next: *const wl_list,
phantom: PhantomData<&'a T>,
}
impl<'a, T> Iterator for WlListIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.next == self.head {
None
} else {
let current = self.next;
self.next = unsafe { (*self.next).next };
unsafe { Some(&*(((current as usize) - self.offset) as *mut T)) }
}
}
}
impl<'a, T> DoubleEndedIterator for WlListIter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.next == self.head {
None
} else {
self.head = unsafe { (*self.head).prev };
let current = self.head;
unsafe { Some(&*(((current as usize) - self.offset) as *mut T)) }
}
}
}
#[derive(Clone)]
pub struct WlListIterMut<'a, T: 'a> {
offset: usize,
head: *mut wl_list,
next: *mut wl_list,
phantom: PhantomData<&'a T>,
}
impl<'a, T> Iterator for WlListIterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.next == self.head {
None
} else {
let current = self.next;
self.next = unsafe { (*self.next).next };
unsafe { Some(&mut *(((current as usize) - self.offset) as *mut T)) }
}
}
}
impl<'a, T> DoubleEndedIterator for WlListIterMut<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.next == self.head {
None
} else {
self.head = unsafe { (*self.head).prev };
let current = self.head;
unsafe { Some(&mut *(((current as usize) - self.offset) as *mut T)) }
}
}
}
impl wl_list {
pub fn zeroed() -> Self {
unsafe { std::mem::zeroed() }
}
pub fn init(&mut self) {
self.next = self as *mut _;
self.prev = self as *mut _;
}
pub fn remove(&mut self) {
unsafe { wl_list_remove(self) }
}
pub fn insert(&mut self, other: &mut wl_list) {
unsafe { wl_list_insert(self, other) }
}
pub fn iter<'a, T>(&self, offset: usize) -> WlListIter<'a, T> {
WlListIter {
offset: offset,
head: self as *const wl_list,
next: self.next as *const wl_list,
phantom: PhantomData,
}
}
pub fn iter_mut<'a, T>(&mut self, offset: usize) -> WlListIterMut<'a, T> {
WlListIterMut {
offset: offset,
head: self as *mut wl_list,
next: self.next as *mut wl_list,
phantom: PhantomData,
}
}
}
macro_rules! wl_list_iter {
($ptr:expr, $container:ty, $( $field:ident ).+) => ({
let offset = unsafe { offset_of!($container, $( $field ).+) };
$ptr.iter::<$container>(offset)
})
}
macro_rules! wl_list_iter_mut {
($ptr:expr, $container:ty, $( $field:ident ).+) => ({
let offset = unsafe { offset_of!($container, $( $field ).+) };
$ptr.iter_mut::<$container>(offset)
})
}
#[cfg(test)]
mod tests {
use super::wl_list;
#[derive(Debug)]
#[repr(C)]
struct Element<T> {
value: T,
link: wl_list,
}
fn add_array<T>(head: &mut wl_list, array: &[T])
where
T: std::fmt::Debug + Copy,
{
for value in array {
let mut e = Box::new(Element { value: *value, link: wl_list::zeroed() });
unsafe {
(*head.prev).insert(&mut e.link);
}
Box::into_raw(e);
}
}
fn drop(head: &mut wl_list) {
unsafe {
use crate::ffi::wl_list_empty;
use std::convert::TryFrom;
while wl_list_empty(head) != 1 {
let current = head.next;
wl_list::remove(&mut *head.next);
let offset : isize = unsafe { isize::try_from(offset_of!(Element<i32>, link)).unwrap() };
// Move back to from raw for garbage collection.
Box::from_raw(&mut *(((current as isize) - offset) as *mut Element<i32>));
}
}
}
fn compare<'a, I, T>(iter: I, array: &'a [T])
where
T: std::fmt::Debug + Copy + Eq,
I: Iterator<Item = &'a Element<T>>,
{
for (e, v) in iter.zip(array) {
assert_eq!(e.value, *v);
}
}
#[test]
fn iterator_test() {
let mut list = wl_list::zeroed();
list.init();
let array = [1, 2, 3];
add_array(&mut list, &array);
let iter = wl_list_iter!(list, Element<i32>, link);
compare(iter, &[1, 2, 3]);
let iter = wl_list_iter!(list, Element<i32>, link).rev();
compare(iter, &[3, 2, 1]);
let mut iter = wl_list_iter!(list, Element<i32>, link);
iter.next();
let iter = iter.rev();
compare(iter, &[3, 2]);
// clean up to avoid memory leaks
drop(&mut list);
}
}
include!(concat!(env!("OUT_DIR"), "/croscomp_weston.rs"));
type NotifyFunc =
unsafe extern "C" fn(listener: *mut wl_listener, data: *mut ::std::os::raw::c_void);
impl wl_listener {
pub fn new(notify: NotifyFunc) -> Self {
wl_listener {
link: wl_list::zeroed(),
notify: Some(notify),
}
}
pub fn zeroed() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl wl_client {
pub fn create_resource(
&mut self,
interface: &wl_interface,
version: u32,
id: u32,
) -> *mut wl_resource {
unsafe { wl_resource_create(self, interface, version as i32, id) }
}
pub fn get_credentials(&mut self) -> (pid_t, uid_t, gid_t) {
let mut pid = 0;
let mut uid = 0;
let mut gid = 0;
unsafe {
wl_client_get_credentials(
self,
&mut pid as *mut _,
&mut uid as *mut _,
&mut gid as *mut _,
)
};
(pid, uid, gid)
}
}
impl pixman_box32 {
pub fn new() -> Self {
Self { x1: 0, y1: 0, x2: 0, y2: 0 }
}
}
impl wl_array {
pub fn new() -> Self {
Self {
size: 0,
alloc: 0,
data: std::ptr::null_mut(),
}
}
}
impl weston_pointer_grab {
pub fn new() -> Self {
Self {
interface: std::ptr::null(),
pointer: std::ptr::null_mut(),
}
}
}
impl weston_keyboard_grab {
pub fn new() -> Self {
Self {
interface: std::ptr::null(),
keyboard: std::ptr::null_mut(),
}
}
}
impl weston_keyboard_modifier {
pub fn is_set(&self, bit: weston_keyboard_modifier) -> bool {
(*self & bit) == bit
}
}
impl weston_layer {
pub fn init(&mut self, compositor: *mut weston_compositor) {
self.compositor = compositor;
self.link.init();
self.view_list.link.init();
self.set_mask_infinite();
}
pub fn set_position(&mut self, position: weston_layer_position) {
unsafe { weston_layer_set_position(self, position) }
}
pub fn set_mask_infinite(&mut self) {
self.mask.x1 = i32::MIN;
self.mask.y1 = i32::MIN;
self.mask.x2 = i32::MAX;
self.mask.y2 = i32::MAX;
for view in wl_list_iter_mut!(&mut self.view_list.link, weston_view, layer_link.link) {
unsafe { weston_view_geometry_dirty(view as *mut _) }
}
}
pub fn zeroed() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl wl_signal {
pub fn init(&mut self) {
self.listener_list.init()
}
pub fn zeroed() -> Self {
unsafe { std::mem::zeroed() }
}
fn iter_mut<'a>(&'a mut self) -> WlListIterMut<'a, wl_listener> {
wl_list_iter_mut!(&mut self.listener_list, wl_listener, link)
}
extern "C" fn destroy_notify<T>(listener: *mut wl_listener, _data: *mut ::std::os::raw::c_void)
where
T: From<*mut wl_listener>,
{
unsafe { (*listener).link.remove() };
let _ = T::from(listener);
}
pub fn add<'a, T>(&mut self, item: &'a mut T)
where
T: From<*mut wl_listener>,
&'a mut T: Into<&'a mut wl_listener>,
{
let listener: &'a mut wl_listener = item.into();
listener.notify = Some(Self::destroy_notify::<T>);
unsafe {
wl_list_insert(self.listener_list.prev, &mut listener.link as *mut _);
}
}
pub fn get<T>(&mut self) -> Option<T>
where
T: From<*mut wl_listener>,
{
self.iter_mut()
.find(|listener| listener.notify == Some(Self::destroy_notify::<T>))
.map(|listener| T::from(listener))
}
pub fn remove<T>(&mut self) -> Option<T>
where
T: From<*mut wl_listener>,
{
self.iter_mut()
.find(|listener| listener.notify == Some(Self::destroy_notify::<T>))
.map(|listener| {
listener.link.remove();
T::from(listener)
})
}
pub fn emit<T>(&mut self, data: &mut T) {
let data = data as *mut _;
for l in self.iter_mut() {
if let Some(notify) = l.notify {
unsafe {
notify(l as *mut _, data as *mut _);
}
}
}
}
}
pub struct WlListener<F> {
listener: wl_listener,
f: F,
}
impl<F> Drop for WlListener<F> {
fn drop(&mut self) {
unsafe { wl_list_remove(&mut self.listener.link) };
}
}
impl<F> WlListener<F>
where
F: Fn(*mut std::os::raw::c_void),
{
pub fn new(signal: &wl_signal, f: F) -> Box<Self> {
extern "C" fn call_closure<F>(listener: *mut wl_listener, data: *mut ::std::os::raw::c_void)
where
F: Fn(*mut std::os::raw::c_void),
{
let fbox = unsafe { &mut *container_of_mut!(listener, WlListener<F>, listener) };
(fbox.f)(data);
}
let mut fbox = Box::new(Self { listener: wl_listener::zeroed(), f: f });
fbox.listener.notify = Some(call_closure::<F>);
unsafe {
wl_list_insert(signal.listener_list.prev, &mut fbox.listener.link as *mut _);
}
fbox
}
}
impl weston_head {
pub fn is_enabled(&self) -> bool {
unsafe { self.output.as_ref().map_or(false, |output| output.enabled) }
}
}
impl weston_compositor {
pub fn schedule_repaint(&mut self) {
unsafe { weston_compositor_schedule_repaint(self) }
}
pub fn create_output(&mut self, name: &str) -> &mut weston_output {
unsafe { &mut *weston_compositor_create_output(self, name.as_ptr() as *const _) }
}
pub fn create_output_with_head(&mut self, head: *mut weston_head) -> &mut weston_output {
unsafe { &mut *weston_compositor_create_output_with_head(self, head) }
}
pub fn seat_iter_mut<'a>(&'a mut self) -> WlListIterMut<'a, weston_seat> {
wl_list_iter_mut!(&mut self.seat_list, weston_seat, link)
}
}
impl weston_surface {
pub fn create_view(&mut self) -> *mut weston_view {
unsafe { weston_view_create(self) }
}
pub fn set_color(&mut self, r: f32, g: f32, b: f32, a: f32) {
unsafe {
weston_surface_set_color(self, r, g, b, a);
}
}
pub fn set_size(&mut self, width: i32, height: i32) {
unsafe { weston_surface_set_size(self, width, height) }
}
pub fn damage(&mut self) {
unsafe { weston_surface_damage(self) }
}
pub fn is_mapped(&mut self) -> bool {
unsafe { weston_surface_is_mapped(self) }
}
pub fn view_iter_mut<'a>(&'a mut self) -> WlListIterMut<'a, weston_view> {
wl_list_iter_mut!(&mut self.views, weston_view, surface_link)
}
pub fn get_main_surface(&mut self) -> *mut weston_surface {
unsafe { weston_surface_get_main_surface(self) }
}
}
impl weston_output {
pub fn attach_head(&mut self, head: &mut weston_head) -> i32 {
unsafe { weston_output_attach_head(self, head) }
}
pub fn set_scale(&mut self, scale: i32) {
unsafe { weston_output_set_scale(self, scale) }
}
pub fn set_transform(&mut self, transform: u32) {
unsafe { weston_output_set_transform(self, transform as u32) }
}
pub fn enable(&mut self) -> i32 {
unsafe { weston_output_enable(self) }
}
}
impl weston_view {
pub fn set_position(&mut self, x: f32, y: f32) {
unsafe { weston_view_set_position(self, x, y) }
}
pub fn set_output(&mut self, output: *mut weston_output) {
unsafe { weston_view_set_output(self, output) }
}
pub fn geometry_dirty(&mut self) {
unsafe { weston_view_geometry_dirty(self) }
}
pub fn update_transform(&mut self) {
unsafe { weston_view_update_transform(self) }
}
pub fn is_mapped(&self) -> bool {
self.is_mapped
}
pub fn activate(&mut self, seat: *mut weston_seat, flags: u32) {
unsafe { weston_view_activate(self, seat, flags) }
}
pub fn damage_below(&mut self) {
unsafe { weston_view_damage_below(self) }
}
pub fn from_global<T: Into<f32>, U: From<f32>>(&mut self, x: T, y: T) -> (U, U) {
let local = if self.transform.enabled {
let global = weston_vector { f: [x.into(), y.into(), 0.0, 1.0] };
let local = self.transform.inverse.transform(&global);
((local.f[0] / local.f[3]), (local.f[1] / local.f[3]))
} else {
(x.into() - self.geometry.x, y.into() - self.geometry.y)
};
(local.0.into(), local.1.into())
}
pub fn to_global<T: Into<f32>, U: From<f32>>(&self, x: T, y: T) -> (U, U) {
let global = if self.transform.enabled {
let local = weston_vector { f: [x.into(), y.into(), 0.0, 1.0] };
let global = self.transform.matrix.transform(&local);
(global.f[0] / global.f[3], global.f[1] / global.f[3])
} else {
(x.into() + self.geometry.x, y.into() + self.geometry.y)
};
(global.0.into(), global.1.into())
}
}
impl weston_seat {
pub fn get_keyboard(&mut self) -> Option<&mut weston_keyboard> {
if self.keyboard_device_count > 0 {
unsafe { Some(&mut *(self.keyboard_state)) }
} else {
None
}
}
pub fn get_pointer(&mut self) -> Option<&mut weston_pointer> {
if self.pointer_device_count > 0 {
unsafe { Some(&mut *(self.pointer_state)) }
} else {
None
}
}
pub fn get_touch(&mut self) -> Option<&mut weston_touch> {
if self.touch_device_count > 0 {
unsafe { Some(&mut *(self.touch_state)) }
} else {
None
}
}
}
impl weston_keyboard {
pub fn start_grab(&mut self, grab: *mut weston_keyboard_grab) {
unsafe { weston_keyboard_start_grab(self, grab) }
}
pub fn set_focus(&mut self, surface: *mut weston_surface) {
unsafe { weston_keyboard_set_focus(self, surface) }
}
}
impl weston_pointer {
pub fn r#move(&mut self, event: *mut weston_pointer_motion_event) {
unsafe { weston_pointer_move(self, event) }
}
}
impl weston_transform {
pub fn new() -> Self {
Self {
matrix: weston_matrix::new(),
link: wl_list::zeroed(),
}
}
}
impl weston_matrix {
pub fn new() -> weston_matrix {
Self {
d: [
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
],
type_: 0,
}
}
pub fn multiply(&mut self, other: &Self) {
unsafe { weston_matrix_multiply(self, other) }
}
pub fn scale(mut self, x: f32, y: f32, z: f32) -> Self {
let m = weston_matrix {
d: [
x, 0.0, 0.0, 0.0, 0.0, y, 0.0, 0.0, 0.0, 0.0, z, 0.0, 0.0, 0.0, 0.0, 1.0,
],
type_: weston_matrix_transform_type::WESTON_MATRIX_TRANSFORM_SCALE as u32,
};
self.multiply(&m);
self
}
pub fn rotate(mut self, cos: f32, sin: f32) -> Self {
let m = weston_matrix {
d: [
cos, sin, 0.0, 0.0, -sin, cos, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
],
type_: weston_matrix_transform_type::WESTON_MATRIX_TRANSFORM_ROTATE as u32,
};
self.multiply(&m);
self
}
pub fn translate(mut self, x: f32, y: f32, z: f32) -> Self {
let m = weston_matrix {
d: [
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, x, y, z, 1.0,
],
type_: weston_matrix_transform_type::WESTON_MATRIX_TRANSFORM_TRANSLATE as u32,
};
self.multiply(&m);
self
}
pub fn transform(&self, v: &weston_vector) -> weston_vector {
let mut r = weston_vector { f: [0.0; 4] };
for i in 0..4_usize {
r.f[i] = (0..4_usize).map(|j| v.f[j] * self.d[i + j * 4]).sum()
}
r
}
}
impl From<f32> for wl_fixed_t {
fn from(item: f32) -> Self {
wl_fixed_t((item * 256.0) as i32)
}
}
impl From<wl_fixed_t> for f32 {
fn from(item: wl_fixed_t) -> Self {
item.0 as f32 / 256.0
}
}
impl From<i32> for wl_fixed_t {
fn from(item: i32) -> Self {
wl_fixed_t(item << 8)
}
}
impl From<wl_fixed_t> for i32 {
fn from(item: wl_fixed_t) -> Self {
item.0 >> 8
}
}
impl ops::Add<wl_fixed_t> for wl_fixed_t {
type Output = wl_fixed_t;
fn add(self, rhs: wl_fixed_t) -> wl_fixed_t {
wl_fixed_t(self.0 + rhs.0)
}
}
impl ops::Sub<wl_fixed_t> for wl_fixed_t {
type Output = wl_fixed_t;
fn sub(self, rhs: wl_fixed_t) -> wl_fixed_t {
wl_fixed_t(self.0 - rhs.0)
}
}
pub mod evdev {
include!(concat!(env!("OUT_DIR"), "/input.rs"));
}