1
0
Fork 0
forked from wry/wry

autocommit 2022-03-09 17:51:17 CET

This commit is contained in:
Julian Orth 2022-03-09 17:51:17 +01:00
parent 4df6b559b7
commit 0399772467
35 changed files with 429 additions and 423 deletions

View file

@ -1,12 +0,0 @@
use crate::backend::Backend;
use std::rc::Rc;
pub struct DummyBackend {}
impl DummyBackend {
pub fn new() -> Rc<Self> {
Rc::new(Self {})
}
}
impl Backend for DummyBackend {}

View file

@ -8,12 +8,15 @@ use crate::libinput::{LibInput, LibInputAdapter, LibInputError};
use crate::logind::{LogindError, Session};
use crate::udev::{UdevError, UdevMonitor};
use crate::utils::copyhashmap::CopyHashMap;
use crate::{AsyncQueue, CloneCell, ErrorFmt, NumCell, State, Udev};
use crate::{CloneCell, State, Udev};
use std::cell::{Cell, RefCell};
use std::ffi::{CStr, CString};
use std::future::pending;
use std::rc::Rc;
use thiserror::Error;
use uapi::{c, OwnedFd};
use crate::backend::{Backend, InputDevice, InputDeviceId, InputEvent};
use crate::utils::syncqueue::SyncQueue;
#[derive(Debug, Error)]
pub enum MetalError {
@ -31,11 +34,14 @@ pub enum MetalError {
LibInput(#[from] LibInputError),
#[error("Dupfd failed")]
Dup(#[source] crate::utils::oserror::OsError),
#[error("Metal backend terminated unexpectedly")]
UnexpectedTermination,
}
pub async fn run(state: Rc<State>) {
if let Err(e) = run_(state).await {
log::error!("{}", ErrorFmt(e));
pub async fn run(state: Rc<State>) -> MetalError {
match run_(state).await {
Err(e) => e,
_ => MetalError::UnexpectedTermination,
}
}
@ -48,7 +54,10 @@ struct MetalBackend {
libinput_fd: AsyncFd,
device_holder: Rc<DeviceHolder>,
session: Session,
ids: NumCell<u64>,
}
impl Backend for MetalBackend {
}
async fn run_(state: Rc<State>) -> Result<(), MetalError> {
@ -89,26 +98,26 @@ async fn run_(state: Rc<State>) -> Result<(), MetalError> {
libinput_fd,
device_holder,
session,
ids: Default::default(),
});
let _monitor = state.eng.spawn(metal.clone().monitor_devices());
let _events = state.eng.spawn(metal.clone().handle_libinput_events());
if let Err(e) = metal.enumerate_devices() {
return Err(MetalError::Enumerate(Box::new(e)));
}
let queue = AsyncQueue::<String>::new();
queue.pop().await;
Ok(())
pending().await
}
struct MetalDevice {
slot: usize,
device_id: u64,
id: InputDeviceId,
devnum: c::dev_t,
fd: CloneCell<Option<Rc<OwnedFd>>>,
inputdev: Cell<Option<RegisteredDevice>>,
devnode: CString,
sysname: CString,
_sysname: CString,
removed: Cell<bool>,
events: SyncQueue<InputEvent>,
cb: CloneCell<Option<Rc<dyn Fn()>>>,
}
struct DeviceHolder {
@ -135,8 +144,33 @@ impl LibInputAdapter for DeviceHolder {
}
}
impl MetalBackend {
fn id(&self) -> u64 {
self.ids.fetch_add(1)
impl InputDevice for MetalDevice {
fn id(&self) -> InputDeviceId {
self.id
}
fn removed(&self) -> bool {
self.removed.get()
}
fn event(&self) -> Option<InputEvent> {
self.events.pop()
}
fn on_change(&self, cb: Rc<dyn Fn()>) {
self.cb.set(Some(cb));
}
fn grab(&self, _grab: bool) {
log::warn!("Metal backend does not support grabbing devices");
}
}
impl MetalDevice {
fn event(&self, event: InputEvent) {
self.events.push(event);
if let Some(cb) = self.cb.get() {
cb();
}
}
}

View file

@ -1,9 +1,36 @@
use crate::async_engine::FdStatus;
use crate::libinput::consts::LIBINPUT_EVENT_KEYBOARD_KEY;
use crate::libinput::event::LibInputEvent;
use crate::metal::MetalBackend;
use crate::ErrorFmt;
use std::rc::Rc;
use crate::backend::{InputEvent, KeyState};
use crate::libinput::consts::LIBINPUT_KEY_STATE_PRESSED;
macro_rules! unpack {
($slf:expr, $ev:expr) => {
{
let slot = match $ev.device().slot() {
Some(s) => s,
_ => return,
};
let data = match $slf.device_holder.input_devices_.borrow_mut().get(slot).cloned().and_then(|v| v) {
Some(d) => d,
_ => return,
};
data
}
};
($slf:expr, $ev:expr, $conv:ident) => {
{
let event = match $ev.$conv() {
Some(e) => e,
_ => return,
};
let data = unpack!($slf, $ev);
(event, data)
}
};
}
impl MetalBackend {
pub async fn handle_libinput_events(self: Rc<Self>) {
@ -34,22 +61,40 @@ impl MetalBackend {
}
fn handle_event(self: &Rc<Self>, event: LibInputEvent) {
use crate::libinput::consts as c;
match event.ty() {
LIBINPUT_EVENT_KEYBOARD_KEY => self.handle_keyboard_event(event),
c::LIBINPUT_EVENT_DEVICE_ADDED => self.handle_device_added(event),
c::LIBINPUT_EVENT_DEVICE_REMOVED => self.handle_device_removed(event),
c::LIBINPUT_EVENT_KEYBOARD_KEY => self.handle_keyboard_key(event),
c::LIBINPUT_EVENT_POINTER_MOTION => self.handle_pointer_motion(event),
_ => {}
}
}
fn handle_keyboard_event(self: &Rc<Self>, event: LibInputEvent) {
let event = match event.keyboard_event() {
Some(event) => event,
_ => return,
fn handle_device_added(self: &Rc<Self>, _event: LibInputEvent) {
// let dev = unpack!(self, event);
}
fn handle_device_removed(self: &Rc<Self>, event: LibInputEvent) {
let dev = unpack!(self, event);
self.device_holder.input_devices.remove(&dev.devnum);
self.device_holder.input_devices_.borrow_mut()[dev.slot] = None;
event.device().unset_slot();
}
fn handle_keyboard_key(self: &Rc<Self>, event: LibInputEvent) {
let (event, dev) = unpack!(self, event, keyboard_event);
let state = if event.key_state() == LIBINPUT_KEY_STATE_PRESSED {
KeyState::Pressed
} else {
KeyState::Released
};
log::info!(
"key: {}, state: {:?}, time: {}",
event.key(),
event.key_state(),
event.time_usec()
);
dev.event(InputEvent::Key(event.key(), state));
}
fn handle_pointer_motion(self: &Rc<Self>, event: LibInputEvent) {
let (event, dev) = unpack!(self, event, pointer_event);
dev.event(InputEvent::Motion(event.dx().into(), event.dy().into()));
}
}

View file

@ -1,9 +1,11 @@
use std::cell::Cell;
use crate::async_engine::FdStatus;
use crate::dbus::TRUE;
use crate::metal::{MetalBackend, MetalDevice, MetalError};
use crate::udev::UdevDevice;
use crate::ErrorFmt;
use std::rc::Rc;
use crate::backend::BackendEvent;
impl MetalBackend {
pub async fn monitor_devices(self: Rc<Self>) {
@ -54,8 +56,11 @@ impl MetalBackend {
}
fn add_input_device(self: &Rc<Self>, dev: &UdevDevice) {
if !dev.is_initialized() {
return;
}
let slf = self.clone();
let device_id = self.id();
let device_id = self.state.input_device_ids.next();
let devnum = dev.devnum();
let devnode = match dev.devnode() {
Ok(n) => n,
@ -83,12 +88,15 @@ impl MetalBackend {
};
let dev = Rc::new(MetalDevice {
slot,
device_id,
id: device_id,
devnum,
fd: Default::default(),
inputdev: Default::default(),
devnode: devnode.to_owned(),
sysname: sysname.to_owned(),
_sysname: sysname.to_owned(),
removed: Cell::new(false),
events: Default::default(),
cb: Default::default(),
});
slots[slot] = Some(dev.clone());
self.device_holder.input_devices.set(devnum, dev);
@ -97,7 +105,7 @@ impl MetalBackend {
let mut slots = slf.device_holder.input_devices_.borrow_mut();
let dev = 'dev: {
if let Some(dev) = id.get(&devnum) {
if dev.device_id == device_id {
if dev.id == device_id {
break 'dev dev;
}
}
@ -126,6 +134,7 @@ impl MetalBackend {
};
inputdev.device().set_slot(slot);
dev.inputdev.set(Some(inputdev));
slf.state.backend_events.push(BackendEvent::NewInputDevice(dev.clone()));
});
}
}

View file

@ -1,3 +1,2 @@
pub mod dummy;
pub mod metal;
pub mod xorg;

View file

@ -1,7 +1,4 @@
use crate::backend::{
Backend, BackendEvent, KeyState, Keyboard, KeyboardEvent, KeyboardId, Mouse, MouseEvent,
MouseId, Output, OutputId, ScrollAxis,
};
use crate::backend::{Backend, BackendEvent, KeyState, InputEvent, Output, OutputId, ScrollAxis, InputDeviceId, InputDevice};
use crate::drm::drm::{Drm, DrmError};
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
@ -26,11 +23,13 @@ use thiserror::Error;
use uapi::{c, OwnedFd};
use xcb_dl::{ffi, Xcb, XcbDri3, XcbPresent, XcbRender, XcbXinput, XcbXkb};
use xcb_dl_util::cursor::{XcbCursorContext, XcbCursorImage};
use xcb_dl_util::error::{XcbError, XcbErrorParser};
use xcb_dl_util::error::{XcbConnectionError, XcbError, XcbErrorParser};
use xcb_dl_util::xcb_box::XcbBox;
#[derive(Debug, Error)]
pub enum XorgBackendError {
#[error("Could not connect to the X server")]
CannotConnect(#[source] XcbConnectionError),
#[error("The xcb connection is in an error state")]
ErrorEvent,
#[error("The drm subsystem returned an error")]
@ -97,6 +96,10 @@ impl XcbCon {
let render = Box::new(XcbRender::load_loose()?);
let c = xcb.xcb_connect(ptr::null(), ptr::null_mut());
match xcb.xcb_connection_has_error(c) {
0 => { },
n => return Err(XorgBackendError::CannotConnect(n.into())),
}
let errors = XcbErrorParser::new(&xcb, c);
let mut con = Self {
@ -554,8 +557,8 @@ impl XorgBackend {
);
}
let seat = Rc::new(XorgSeat {
kb_id: self.state.kb_ids.next(),
mouse_id: self.state.mouse_ids.next(),
kb_id: self.state.input_device_ids.next(),
mouse_id: self.state.input_device_ids.next(),
backend: self.clone(),
kb: info.deviceid,
mouse: info.attachment,
@ -571,10 +574,10 @@ impl XorgBackend {
self.mouse_seats.set(info.attachment, seat.clone());
self.state
.backend_events
.push(BackendEvent::NewMouse(seat.clone()));
.push(BackendEvent::NewInputDevice(Rc::new(XorgSeatMouse(seat.clone()))));
self.state
.backend_events
.push(BackendEvent::NewKeyboard(seat.clone()));
.push(BackendEvent::NewInputDevice(Rc::new(XorgSeatKeyboard(seat.clone()))));
}
}
@ -766,7 +769,7 @@ impl XorgBackend {
7 => (ScrollAxis::Horizontal, 15),
_ => unreachable!(),
};
seat.mouse_event(MouseEvent::Scroll(val, axis));
seat.mouse_event(InputEvent::Scroll(val, axis));
}
} else {
const BTN_LEFT: u32 = 0x110;
@ -780,7 +783,7 @@ impl XorgBackend {
3 => BTN_RIGHT,
n => BTN_SIDE + n - 8,
};
seat.mouse_event(MouseEvent::Button(button, state));
seat.mouse_event(InputEvent::Button(button, state));
}
}
Ok(())
@ -800,7 +803,7 @@ impl XorgBackend {
let event =
unsafe { (event as *const _ as *const ffi::xcb_input_key_press_event_t).deref() };
if let Some(seat) = self.seats.get(&event.deviceid) {
seat.kb_event(KeyboardEvent::Key(event.detail - 8, state));
seat.kb_event(InputEvent::Key(event.detail - 8, state));
}
Ok(())
}
@ -843,7 +846,7 @@ impl XorgBackend {
self.outputs.get(&event.event),
self.mouse_seats.get(&event.deviceid),
) {
seat.mouse_event(MouseEvent::OutputPosition(
seat.mouse_event(InputEvent::OutputPosition(
win.id,
Fixed::from_1616(event.event_x),
Fixed::from_1616(event.event_y),
@ -864,7 +867,7 @@ impl XorgBackend {
(Some(a), Some(b)) => (a, b),
_ => return Ok(()),
};
seat.mouse_event(MouseEvent::OutputPosition(
seat.mouse_event(InputEvent::OutputPosition(
win.id,
Fixed::from_1616(event.event_x),
Fixed::from_1616(event.event_y),
@ -997,19 +1000,23 @@ impl Output for XorgOutput {
}
struct XorgSeat {
kb_id: KeyboardId,
mouse_id: MouseId,
kb_id: InputDeviceId,
mouse_id: InputDeviceId,
backend: Rc<XorgBackend>,
kb: ffi::xcb_input_device_id_t,
mouse: ffi::xcb_input_device_id_t,
removed: Cell<bool>,
kb_cb: CloneCell<Option<Rc<dyn Fn()>>>,
mouse_cb: CloneCell<Option<Rc<dyn Fn()>>>,
kb_events: RefCell<VecDeque<KeyboardEvent>>,
mouse_events: RefCell<VecDeque<MouseEvent>>,
kb_events: RefCell<VecDeque<InputEvent>>,
mouse_events: RefCell<VecDeque<InputEvent>>,
button_map: CopyHashMap<u32, u32>,
}
struct XorgSeatKeyboard(Rc<XorgSeat>);
struct XorgSeatMouse(Rc<XorgSeat>);
impl XorgSeat {
fn kb_changed(&self) {
if let Some(cb) = self.kb_cb.get() {
@ -1023,12 +1030,12 @@ impl XorgSeat {
}
}
fn mouse_event(&self, event: MouseEvent) {
fn mouse_event(&self, event: InputEvent) {
self.mouse_events.borrow_mut().push_back(event);
self.mouse_changed();
}
fn kb_event(&self, event: KeyboardEvent) {
fn kb_event(&self, event: InputEvent) {
self.kb_events.borrow_mut().push_back(event);
self.kb_changed();
}
@ -1066,26 +1073,26 @@ impl XorgSeat {
}
}
impl Keyboard for XorgSeat {
fn id(&self) -> KeyboardId {
self.kb_id
impl InputDevice for XorgSeatKeyboard {
fn id(&self) -> InputDeviceId {
self.0.kb_id
}
fn removed(&self) -> bool {
self.removed.get()
self.0.removed.get()
}
fn event(&self) -> Option<KeyboardEvent> {
self.kb_events.borrow_mut().pop_front()
fn event(&self) -> Option<InputEvent> {
self.0.kb_events.borrow_mut().pop_front()
}
fn on_change(&self, cb: Rc<dyn Fn()>) {
self.kb_cb.set(Some(cb));
self.0.kb_cb.set(Some(cb));
}
fn grab(&self, grab: bool) {
unsafe {
let con = &self.backend.con;
let con = &self.0.backend.con;
let mut err = ptr::null_mut();
if grab {
let res = con.input.xcb_input_xi_grab_device(
@ -1093,7 +1100,7 @@ impl Keyboard for XorgSeat {
con.screen.root,
0,
0,
self.kb,
self.0.kb,
ffi::XCB_GRAB_MODE_ASYNC as _,
ffi::XCB_GRAB_MODE_ASYNC as _,
1,
@ -1106,39 +1113,43 @@ impl Keyboard for XorgSeat {
let res = match con.check(res, err) {
Ok(r) => r,
Err(e) => {
log::error!("Could not grab device {}: {}", self.kb, ErrorFmt(e));
log::error!("Could not grab device {}: {}", self.0.kb, ErrorFmt(e));
return;
}
};
if res.status != ffi::XCB_GRAB_STATUS_SUCCESS as _ {
log::error!("Could not grab device {}: status = {}", self.kb, res.status);
log::error!("Could not grab device {}: status = {}", self.0.kb, res.status);
}
} else {
let cookie = con
.input
.xcb_input_xi_ungrab_device_checked(con.c, 0, self.kb);
.xcb_input_xi_ungrab_device_checked(con.c, 0, self.0.kb);
if let Err(e) = con.check_cookie(cookie) {
log::error!("Could not ungrab device {}: {}", self.kb, ErrorFmt(e));
log::error!("Could not ungrab device {}: {}", self.0.kb, ErrorFmt(e));
}
}
}
}
}
impl Mouse for XorgSeat {
fn id(&self) -> MouseId {
self.mouse_id
impl InputDevice for XorgSeatMouse {
fn id(&self) -> InputDeviceId {
self.0.mouse_id
}
fn removed(&self) -> bool {
self.removed.get()
self.0.removed.get()
}
fn event(&self) -> Option<MouseEvent> {
self.mouse_events.borrow_mut().pop_front()
fn event(&self) -> Option<InputEvent> {
self.0.mouse_events.borrow_mut().pop_front()
}
fn on_change(&self, cb: Rc<dyn Fn()>) {
self.mouse_cb.set(Some(cb));
self.0.mouse_cb.set(Some(cb));
}
fn grab(&self, _grab: bool) {
log::error!("Cannot grab xorg mouse");
}
}