262 lines
8.8 KiB
Rust
262 lines
8.8 KiB
Rust
use std::{
|
|
os::{
|
|
raw::{c_char, c_int},
|
|
unix::{
|
|
net::UnixStream,
|
|
prelude::{AsRawFd, IntoRawFd},
|
|
},
|
|
},
|
|
thread::JoinHandle,
|
|
};
|
|
|
|
use smithay::reexports::calloop::channel::{channel, Sender};
|
|
use wayland_sys::{
|
|
client::*,
|
|
common::{wl_fixed_t, wl_fixed_to_double},
|
|
ffi_dispatch,
|
|
};
|
|
|
|
use crate::{ffi_api::*, WlcsEvent};
|
|
|
|
macro_rules! container_of(
|
|
($ptr: expr, $container: ident, $field: ident) => {
|
|
($ptr as *mut u8).offset(-(memoffset::offset_of!($container, $field) as isize)) as *mut $container
|
|
}
|
|
);
|
|
|
|
#[no_mangle]
|
|
pub static wlcs_server_integration: WlcsServerIntegration = WlcsServerIntegration {
|
|
version: 1,
|
|
create_server,
|
|
destroy_server,
|
|
};
|
|
|
|
unsafe extern "C" fn create_server(_argc: c_int, _argv: *mut *const c_char) -> *mut WlcsDisplayServer {
|
|
// block the SIGPIPE signal here, we are a cdylib so Rust does not do it for us
|
|
use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal};
|
|
sigaction(
|
|
Signal::SIGPIPE,
|
|
&SigAction::new(SigHandler::SigIgn, SaFlags::empty(), SigSet::empty()),
|
|
)
|
|
.unwrap();
|
|
let handle = Box::into_raw(Box::new(DisplayServerHandle::new()));
|
|
&mut (*handle).wlcs_display_server
|
|
}
|
|
|
|
unsafe extern "C" fn destroy_server(ptr: *mut WlcsDisplayServer) {
|
|
let _server = Box::from_raw(container_of!(ptr, DisplayServerHandle, wlcs_display_server));
|
|
}
|
|
|
|
struct DisplayServerHandle {
|
|
wlcs_display_server: WlcsDisplayServer,
|
|
server: Option<(Sender<WlcsEvent>, JoinHandle<()>)>,
|
|
next_device_id: u32,
|
|
}
|
|
|
|
impl DisplayServerHandle {
|
|
fn new() -> DisplayServerHandle {
|
|
DisplayServerHandle {
|
|
wlcs_display_server: WlcsDisplayServer {
|
|
version: 3,
|
|
start: Self::start,
|
|
stop: Self::stop,
|
|
create_client_socket: Self::create_client_socket,
|
|
position_window_absolute: Self::position_window_absolute,
|
|
create_pointer: Self::create_pointer,
|
|
create_touch: Self::create_touch,
|
|
get_descriptor: Self::get_descriptor,
|
|
start_on_this_thread: None,
|
|
},
|
|
server: None,
|
|
next_device_id: 1,
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn start(ptr: *mut WlcsDisplayServer) {
|
|
let me = &mut *container_of!(ptr, DisplayServerHandle, wlcs_display_server);
|
|
let (tx, rx) = channel();
|
|
let join = crate::start_anvil(rx);
|
|
me.server = Some((tx, join));
|
|
}
|
|
|
|
unsafe extern "C" fn stop(ptr: *mut WlcsDisplayServer) {
|
|
let me = &mut *container_of!(ptr, DisplayServerHandle, wlcs_display_server);
|
|
if let Some((sender, join)) = me.server.take() {
|
|
let _ = sender.send(WlcsEvent::Exit);
|
|
let _ = join.join();
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn create_client_socket(ptr: *mut WlcsDisplayServer) -> c_int {
|
|
let me = &mut *container_of!(ptr, DisplayServerHandle, wlcs_display_server);
|
|
if let Some((ref sender, _)) = me.server {
|
|
if let Ok((client_side, server_side)) = UnixStream::pair() {
|
|
if sender
|
|
.send(WlcsEvent::NewClient {
|
|
stream: server_side,
|
|
client_id: client_side.as_raw_fd(),
|
|
})
|
|
.is_err()
|
|
{
|
|
return -1;
|
|
}
|
|
return client_side.into_raw_fd();
|
|
}
|
|
}
|
|
-1
|
|
}
|
|
|
|
unsafe extern "C" fn position_window_absolute(
|
|
ptr: *mut WlcsDisplayServer,
|
|
display: *mut wl_display,
|
|
surface: *mut wl_proxy,
|
|
x: c_int,
|
|
y: c_int,
|
|
) {
|
|
let me = &mut *container_of!(ptr, DisplayServerHandle, wlcs_display_server);
|
|
let client_id = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_get_fd, display);
|
|
let surface_id = ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_proxy_get_id, surface);
|
|
if let Some((ref sender, _)) = me.server {
|
|
let _ = sender.send(WlcsEvent::PositionWindow {
|
|
client_id,
|
|
surface_id,
|
|
location: (x, y).into(),
|
|
});
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn create_pointer(ptr: *mut WlcsDisplayServer) -> *mut WlcsPointer {
|
|
let me = &mut *container_of!(ptr, DisplayServerHandle, wlcs_display_server);
|
|
if let Some((ref sender, _)) = me.server {
|
|
let pointer = Box::into_raw(Box::new(PointerHandle::new(me.next_device_id, sender.clone())));
|
|
me.next_device_id += 1;
|
|
&mut (*pointer).wlcs_pointer
|
|
} else {
|
|
std::ptr::null_mut()
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn create_touch(ptr: *mut WlcsDisplayServer) -> *mut WlcsTouch {
|
|
let me = &mut *container_of!(ptr, DisplayServerHandle, wlcs_display_server);
|
|
if let Some((ref sender, _)) = me.server {
|
|
let pointer = Box::into_raw(Box::new(TouchHandle::new(me.next_device_id, sender.clone())));
|
|
me.next_device_id += 1;
|
|
&mut (*pointer).wlcs_touch
|
|
} else {
|
|
std::ptr::null_mut()
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn get_descriptor(_: *const WlcsDisplayServer) -> *const WlcsIntegrationDescriptor {
|
|
&crate::DESCRIPTOR
|
|
}
|
|
}
|
|
|
|
struct PointerHandle {
|
|
wlcs_pointer: WlcsPointer,
|
|
device_id: u32,
|
|
sender: Sender<WlcsEvent>,
|
|
}
|
|
|
|
impl PointerHandle {
|
|
fn new(device_id: u32, sender: Sender<WlcsEvent>) -> PointerHandle {
|
|
PointerHandle {
|
|
wlcs_pointer: WlcsPointer {
|
|
version: 1,
|
|
move_absolute: Self::move_absolute,
|
|
move_relative: Self::move_relative,
|
|
button_down: Self::button_down,
|
|
button_up: Self::button_up,
|
|
destroy: Self::destroy,
|
|
},
|
|
device_id,
|
|
sender,
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn move_absolute(ptr: *mut WlcsPointer, x: wl_fixed_t, y: wl_fixed_t) {
|
|
let me = &mut *container_of!(ptr, PointerHandle, wlcs_pointer);
|
|
let _ = me.sender.send(WlcsEvent::PointerMoveAbsolute {
|
|
device_id: me.device_id,
|
|
location: (wl_fixed_to_double(x), wl_fixed_to_double(y)).into(),
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn move_relative(ptr: *mut WlcsPointer, x: wl_fixed_t, y: wl_fixed_t) {
|
|
let me = &mut *container_of!(ptr, PointerHandle, wlcs_pointer);
|
|
let _ = me.sender.send(WlcsEvent::PointerMoveRelative {
|
|
device_id: me.device_id,
|
|
delta: (wl_fixed_to_double(x), wl_fixed_to_double(y)).into(),
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn button_up(ptr: *mut WlcsPointer, button_id: i32) {
|
|
let me = &mut *container_of!(ptr, PointerHandle, wlcs_pointer);
|
|
let _ = me.sender.send(WlcsEvent::PointerButtonUp {
|
|
device_id: me.device_id,
|
|
button_id,
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn button_down(ptr: *mut WlcsPointer, button_id: i32) {
|
|
let me = &mut *container_of!(ptr, PointerHandle, wlcs_pointer);
|
|
let _ = me.sender.send(WlcsEvent::PointerButtonDown {
|
|
device_id: me.device_id,
|
|
button_id,
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn destroy(ptr: *mut WlcsPointer) {
|
|
let _me = Box::from_raw(container_of!(ptr, PointerHandle, wlcs_pointer));
|
|
}
|
|
}
|
|
|
|
struct TouchHandle {
|
|
wlcs_touch: WlcsTouch,
|
|
device_id: u32,
|
|
sender: Sender<WlcsEvent>,
|
|
}
|
|
|
|
impl TouchHandle {
|
|
fn new(device_id: u32, sender: Sender<WlcsEvent>) -> TouchHandle {
|
|
TouchHandle {
|
|
wlcs_touch: WlcsTouch {
|
|
version: 1,
|
|
touch_down: Self::touch_down,
|
|
touch_move: Self::touch_move,
|
|
touch_up: Self::touch_up,
|
|
destroy: Self::destroy,
|
|
},
|
|
device_id,
|
|
sender,
|
|
}
|
|
}
|
|
|
|
unsafe extern "C" fn touch_down(ptr: *mut WlcsTouch, x: wl_fixed_t, y: wl_fixed_t) {
|
|
let me = &mut *container_of!(ptr, TouchHandle, wlcs_touch);
|
|
let _ = me.sender.send(WlcsEvent::TouchDown {
|
|
device_id: me.device_id,
|
|
location: (wl_fixed_to_double(x), wl_fixed_to_double(y)).into(),
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn touch_move(ptr: *mut WlcsTouch, x: wl_fixed_t, y: wl_fixed_t) {
|
|
let me = &mut *container_of!(ptr, TouchHandle, wlcs_touch);
|
|
let _ = me.sender.send(WlcsEvent::TouchMove {
|
|
device_id: me.device_id,
|
|
location: (wl_fixed_to_double(x), wl_fixed_to_double(y)).into(),
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn touch_up(ptr: *mut WlcsTouch) {
|
|
let me = &mut *container_of!(ptr, TouchHandle, wlcs_touch);
|
|
let _ = me.sender.send(WlcsEvent::TouchUp {
|
|
device_id: me.device_id,
|
|
});
|
|
}
|
|
|
|
unsafe extern "C" fn destroy(ptr: *mut WlcsTouch) {
|
|
let _me = Box::from_raw(container_of!(ptr, TouchHandle, wlcs_touch));
|
|
}
|
|
}
|