1
0
Fork 0
forked from wry/wry

autocommit 2022-03-02 14:24:07 CET

This commit is contained in:
Julian Orth 2022-03-02 14:24:07 +01:00
parent 0e9afcbfa5
commit aa0cb94143
30 changed files with 1059 additions and 123 deletions

View file

@ -1,3 +1,5 @@
extern crate core;
use std::fs::{File, OpenOptions};
use std::io::BufWriter;
use std::path::PathBuf;

View file

@ -47,6 +47,12 @@ struct Property {
ty: Type,
}
#[derive(Debug)]
struct Signal {
name: BString,
fields: Vec<Field>,
}
struct Parser<'a> {
pos: usize,
tokens: &'a [Token<'a>],
@ -57,12 +63,14 @@ impl<'a> Parser<'a> {
let mut res = Component {
functions: vec![],
properties: vec![],
signals: vec![],
};
while !self.eof() {
let (line, ty) = self.expect_ident()?;
match ty.as_bytes() {
b"fn" => res.functions.push(self.parse_fn()?.val),
b"prop" => res.properties.push(self.parse_prop()?.val),
b"sig" => res.signals.push(self.parse_signal()?.val),
_ => bail!("In line {}: Unexpected entry {:?}", line, ty),
}
}
@ -96,6 +104,29 @@ impl<'a> Parser<'a> {
res.with_context(|| format!("While parsing property starting at line {}", line))
}
fn parse_signal(&mut self) -> Result<Lined<Signal>> {
let (line, name) = self.expect_ident()?;
let res: Result<_> = (|| {
let (_, body) = self.expect_tree(TreeDelim::Brace)?;
let mut parser = Parser {
pos: 0,
tokens: body,
};
let mut fields = vec![];
while !parser.eof() {
fields.push(parser.parse_field()?);
}
Ok(Lined {
line,
val: Signal {
name: name.to_owned(),
fields,
},
})
})();
res.with_context(|| format!("While parsing signal starting at line {}", line))
}
fn parse_fn(&mut self) -> Result<Lined<Function>> {
let (line, name) = self.expect_ident()?;
let res: Result<_> = (|| {
@ -379,9 +410,9 @@ fn write_type2<W: Write>(f: &mut W, lt: &str, ty: &Type) -> Result<()> {
Type::U16 => "u16",
Type::I32 => "i32",
Type::U32 => "u32",
Type::I64 => "AlignedI64",
Type::U64 => "AlignedU64",
Type::F64 => "AlignedF64",
Type::I64 => "i64",
Type::U64 => "u64",
Type::F64 => "f64",
Type::String => {
write!(f, "Cow<{}, str>", lt)?;
return Ok(());
@ -432,7 +463,7 @@ fn write_type2<W: Write>(f: &mut W, lt: &str, ty: &Type) -> Result<()> {
fn write_message<W: Write>(
f: &mut W,
el: &Element,
fun: &Function,
msg_name: &BStr,
name: &str,
indent: &str,
fields: &[Field],
@ -474,7 +505,7 @@ fn write_message<W: Write>(
writeln!(
f,
"{} const MEMBER: &'static str = \"{}\";",
indent, fun.name
indent, msg_name,
)?;
writeln!(f, "{} type Generic<'b> = {}{};", indent, name, ltb,)?;
writeln!(f)?;
@ -540,6 +571,9 @@ fn write_component<W: Write>(
for prop in &component.properties {
write_property(f, element, prop, indent)?;
}
for sig in &component.signals {
write_signal(f, element, sig, indent)?;
}
Ok(())
}
@ -570,6 +604,25 @@ fn write_property<W: Write>(
Ok(())
}
fn write_signal<W: Write>(f: &mut W, element: &Element, sig: &Signal, indent: &str) -> Result<()> {
let name = format!("{}", sig.name);
write_message(
f,
element,
sig.name.as_bstr(),
&name,
indent,
&sig.fields,
None,
false,
)?;
let has_lt = sig.fields.iter().any(|f| needs_lifetime(&f.ty));
let lt = if has_lt { "<'a>" } else { "" };
writeln!(f)?;
writeln!(f, "{}impl<'a> Signal<'a> for {}{} {{ }}", indent, name, lt)?;
Ok(())
}
fn write_function<W: Write>(
f: &mut W,
element: &Element,
@ -582,7 +635,7 @@ fn write_function<W: Write>(
write_message(
f,
element,
fun,
fun.name.as_bstr(),
&in_name,
indent,
&fun.in_fields,
@ -592,7 +645,7 @@ fn write_function<W: Write>(
write_message(
f,
element,
fun,
fun.name.as_bstr(),
&out_name,
indent,
&fun.out_fields,
@ -630,6 +683,7 @@ fn write_element<W: Write>(f: &mut W, element: Element, indent: &str) -> Result<
struct Component {
functions: Vec<Function>,
properties: Vec<Property>,
signals: Vec<Signal>,
}
#[derive(Debug)]

View file

@ -3,7 +3,7 @@ use crate::event_loop::{EventLoop, EventLoopError};
use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::numcell::NumCell;
use crate::wheel::{Wheel, WheelError};
pub use fd::AsyncFd;
pub use fd::{AsyncFd, FdStatus};
use fd::AsyncFdData;
use queue::{DispatchQueue, Dispatcher};
use std::cell::{Cell, RefCell};
@ -21,6 +21,8 @@ pub enum AsyncError {
WheelError(#[from] WheelError),
#[error("The event loop caused an error: {0}")]
EventLoopError(#[from] EventLoopError),
#[error("The file descriptor is in an error state")]
FdError,
}
#[derive(Copy, Clone, Eq, PartialEq)]
@ -90,7 +92,6 @@ impl AsyncEngine {
read_registered: Cell::new(false),
readers: RefCell::new(vec![]),
writers: RefCell::new(vec![]),
erroneous: Cell::new(false),
});
self.el.insert(id, Some(fd.raw()), 0, afd.clone())?;
afd
@ -198,6 +199,7 @@ mod task {
use std::rc::Rc;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
#[must_use]
pub struct SpawnedFuture<T: 'static> {
vtable: &'static SpawnedFutureVtable<T>,
data: *mut u8,
@ -535,7 +537,7 @@ mod fd {
use std::task::{Context, Poll, Waker};
use uapi::{c, OwnedFd};
type Queue = RefCell<Vec<(Waker, Rc<Cell<bool>>)>>;
type Queue = RefCell<Vec<(Waker, Rc<Cell<Option<FdStatus>>>)>>;
pub(super) struct AsyncFdData {
pub(super) ref_count: NumCell<u64>,
@ -546,7 +548,6 @@ mod fd {
pub(super) read_registered: Cell<bool>,
pub(super) readers: Queue,
pub(super) writers: Queue,
pub(super) erroneous: Cell<bool>,
}
impl AsyncFdData {
@ -560,21 +561,23 @@ mod fd {
}
let res = self.el.modify(self.id, events);
if res.is_err() {
self.erroneous.set(true);
let _ = self.el.remove(self.id);
if let Err(e) = self.el.remove(self.id) {
log::error!("Fatal error: Cannot remove file descriptor from event loop: {:?}", e);
self.el.stop();
}
}
res
}
fn poll(
&self,
woken: &Rc<Cell<bool>>,
woken: &Rc<Cell<Option<FdStatus>>>,
cx: &mut Context<'_>,
registered: impl Fn(&AsyncFdData) -> &Cell<bool>,
queue: impl Fn(&AsyncFdData) -> &Queue,
) -> Poll<Result<(), AsyncError>> {
if woken.get() || self.erroneous.get() {
return Poll::Ready(Ok(()));
) -> Poll<Result<FdStatus, AsyncError>> {
if let Some(status) = woken.get() {
return Poll::Ready(Ok(status));
}
if !registered(self).get() {
registered(self).set(true);
@ -591,30 +594,31 @@ mod fd {
impl EventLoopDispatcher for AsyncFdData {
fn dispatch(self: Rc<Self>, events: i32) -> Result<(), Box<dyn Error>> {
let mut status = FdStatus::Ok;
if events & (c::EPOLLERR | c::EPOLLHUP) != 0 {
self.erroneous.set(true);
status = FdStatus::Err;
if let Err(e) = self.el.remove(self.id) {
return Err(Box::new(e));
}
}
let mut woke_any = false;
if events & c::EPOLLIN != 0 || self.erroneous.get() {
if events & c::EPOLLIN != 0 || status == FdStatus::Err {
let mut readers = self.readers.borrow_mut();
woke_any |= !readers.is_empty();
for (waker, woken) in readers.drain(..) {
woken.set(true);
woken.set(Some(status));
waker.wake();
}
}
if events & c::EPOLLOUT != 0 || self.erroneous.get() {
if events & c::EPOLLOUT != 0 || status == FdStatus::Err {
let mut writers = self.writers.borrow_mut();
woke_any |= !writers.is_empty();
for (waker, woken) in writers.drain(..) {
woken.set(true);
woken.set(Some(status));
waker.wake();
}
}
if !woke_any && !self.erroneous.get() {
if !woke_any && status == FdStatus::Ok {
self.read_registered.set(false);
self.write_registered.set(false);
if let Err(e) = self.update_interests() {
@ -666,25 +670,31 @@ mod fd {
pub fn readable(&self) -> AsyncFdReadable {
AsyncFdReadable {
fd: self,
woken: Rc::new(Cell::new(false)),
woken: Rc::new(Cell::new(None)),
}
}
pub fn writable(&self) -> AsyncFdWritable {
AsyncFdWritable {
fd: self,
woken: Rc::new(Cell::new(false)),
woken: Rc::new(Cell::new(None)),
}
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum FdStatus {
Ok,
Err,
}
pub struct AsyncFdReadable<'a> {
fd: &'a AsyncFd,
woken: Rc<Cell<bool>>,
woken: Rc<Cell<Option<FdStatus>>>,
}
impl<'a> Future for AsyncFdReadable<'a> {
type Output = Result<(), AsyncError>;
type Output = Result<FdStatus, AsyncError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let data = &self.fd.data;
@ -694,11 +704,11 @@ mod fd {
pub struct AsyncFdWritable<'a> {
fd: &'a AsyncFd,
woken: Rc<Cell<bool>>,
woken: Rc<Cell<Option<FdStatus>>>,
}
impl<'a> Future for AsyncFdWritable<'a> {
type Output = Result<(), AsyncError>;
type Output = Result<FdStatus, AsyncError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let data = &self.fd.data;

128
src/backends/metal.rs Normal file
View file

@ -0,0 +1,128 @@
use crate::dbus::DbusError;
use crate::logind::{LogindError, Session};
use crate::{AsyncQueue, ErrorFmt, State, Udev};
use std::rc::Rc;
use thiserror::Error;
use uapi::OwnedFd;
use crate::async_engine::{AsyncFd, FdStatus};
use crate::libinput::{LibInput, LibInputError};
use crate::udev::{UdevError, UdevMonitor};
#[derive(Debug, Error)]
pub enum MetalError {
#[error("Could not connect to the dbus system socket")]
DbusSystemSocket(#[source] DbusError),
#[error("Could not retrieve the logind session")]
LogindSession(#[source] LogindError),
#[error("Could not take control of the logind session")]
TakeControl(#[source] LogindError),
#[error(transparent)]
Udev(#[from] UdevError),
#[error(transparent)]
LibInput(#[from] LibInputError),
#[error("Dupfd failed")]
Dup(#[source] std::io::Error),
}
pub async fn run(state: Rc<State>) {
if let Err(e) = run_(state).await {
log::error!("{}", ErrorFmt(e));
}
}
async fn run_(state: Rc<State>) -> Result<(), MetalError> {
let socket = match state.dbus.system() {
Ok(s) => s,
Err(e) => return Err(MetalError::DbusSystemSocket(e)),
};
let session = match Session::get(&socket).await {
Ok(s) => s,
Err(e) => return Err(MetalError::LogindSession(e)),
};
// if let Err(e) = session.take_control().await {
// return Err(MetalError::TakeControl(e));
// }
let udev = Rc::new(Udev::new()?);
let monitor = Rc::new(udev.create_monitor()?);
monitor.add_match_subsystem_devtype(Some("input"), None)?;
monitor.enable_receiving()?;
let libinput = Rc::new(LibInput::new()?);
let monitor_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
Ok(m) => state.eng.fd(&Rc::new(m)).unwrap(),
Err(e) => return Err(MetalError::Dup(e.into())),
};
let metal = Rc::new(MetalBackend {
state: state.clone(),
udev,
monitor,
monitor_fd,
libinput,
});
let _monitor = state.eng.spawn(metal.clone().monitor_devices());
let mut queue = AsyncQueue::<String>::new();
queue.pop().await;
Ok(())
// let libinput_fd = match uapi::fcntl_dupfd_cloexec(monitor.fd(), 0) {
// Ok(m) => m,
// Err(e) => Err(MetalError::Dup(e.into())),
// };
// let mut enumerate = udev.create_enumerate()?;
// enumerate.add_match_subsystem("input")?;
// enumerate.scan_devices()?;
// let mut entry_opt = enumerate.get_list_entry()?;
// while let Some(entry) = entry_opt {
// let device = udev.create_device_from_syspath(entry.name()?)?;
// if device.sysname()?.to_bytes().starts_with(b"event") {
// let devnode = device.devnode()?;
// }
// }
}
struct MetalBackend {
state: Rc<State>,
udev: Rc<Udev>,
monitor: Rc<UdevMonitor>,
monitor_fd: AsyncFd,
libinput: Rc<LibInput>,
libinput_fd: AsyncFd,
}
impl MetalBackend {
async fn monitor_devices(self: Rc<Self>) {
loop {
match self.monitor_fd.readable().await {
Err(e) => {
log::error!("Cannot wait for udev_monitor to become readable: {}", ErrorFmt(e));
break;
}
Ok(FdStatus::Err) => {
log::error!("udev_monitor fd is in an error state");
break;
}
_ => { },
}
while let Some(dev) = self.monitor.receive_device() {
log::info!("x {:?}", dev.devnode());
}
}
log::error!("Monitor task exited. Future hotplug events will be ignored.");
}
async fn handle_libinput_events(self: Rc<Self>) {
loop {
match self.libinput_fd.readable().await {
Err(e) => {
log::error!("Cannot wait for udev_monitor to become readable: {}", ErrorFmt(e));
break;
}
Ok(FdStatus::Err) => {
log::error!("udev_monitor fd is in an error state");
break;
}
_ => { },
}
self.libinput.fd()
}
log::error!("Monitor task exited. Future hotplug events will be ignored.");
}
}

View file

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

View file

@ -5,10 +5,12 @@ use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::stack::Stack;
use crate::utils::vecstorage::VecStorage;
use crate::{AsyncEngine, AsyncError, AsyncQueue, CloneCell, NumCell, RunToplevel};
use ahash::AHashMap;
use std::borrow::Cow;
use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Display};
use std::future::Future;
use std::marker::PhantomData;
use std::mem;
use std::pin::Pin;
use std::rc::Rc;
@ -52,6 +54,8 @@ pub enum DbusError {
Closed,
#[error("Function call reply does not contain a reply serial")]
NoReplySerial,
#[error("Signal message contains no interface or member or path")]
MissingSignalHeaders,
#[error("Error has no error name")]
NoErrorName,
#[error("The socket was killed")]
@ -102,6 +106,8 @@ pub enum DbusError {
InvalidProtocol,
#[error("Signature contains an invalid type")]
InvalidSignatureType,
#[error("The signal already has a handler")]
AlreadyHandled,
}
efrom!(DbusError, AsyncError);
@ -151,6 +157,7 @@ pub struct DbusSocket {
dead: Cell<bool>,
headers: RefCell<VecStorage<(u8, Variant<'static>)>>,
run_toplevel: Rc<RunToplevel>,
signal_handlers: RefCell<AHashMap<(&'static str, &'static str), InterfaceSignalHandlers>>,
}
const TY_BYTE: u8 = b'y';
@ -188,6 +195,9 @@ const NO_REPLY_EXPECTED: u8 = 0x1;
const NO_AUTO_START: u8 = 0x2;
const ALLOW_INTERACTIVE_AUTHORIZATION: u8 = 0x4;
pub const BUS_DEST: &'static str = "org.freedesktop.DBus";
pub const BUS_PATH: &'static str = "/org/freedesktop/dbus";
#[derive(Default, Debug)]
struct Headers<'a> {
path: Option<ObjectPath<'a>>,
@ -279,6 +289,8 @@ pub trait Property {
type Type: DbusType<'static>;
}
pub trait Signal<'a>: Message<'a> {}
pub trait MethodCall<'a>: Message<'a> {
type Reply: Message<'static>;
}
@ -391,10 +403,74 @@ impl<T: Property> Future for AsyncProperty<T> {
}
}
struct SignalHandlerData<T, F> {
path: Option<String>,
rule: String,
handler: F,
_phantom: PhantomData<T>,
}
trait SignalHandlerApi {
fn interface(&self) -> &'static str;
fn member(&self) -> &'static str;
fn signature(&self) -> &'static str;
fn path(&self) -> Option<&str>;
fn rule(&self) -> &str;
fn handle(&self, parser: &mut Parser) -> Result<(), DbusError>;
}
impl<T, F> SignalHandlerApi for SignalHandlerData<T, F>
where
T: Signal<'static>,
F: for<'a> Fn(T::Generic<'a>),
{
fn interface(&self) -> &'static str {
T::INTERFACE
}
fn member(&self) -> &'static str {
T::MEMBER
}
fn signature(&self) -> &'static str {
T::SIGNATURE
}
fn path(&self) -> Option<&str> {
self.path.as_deref()
}
fn rule(&self) -> &str {
&self.rule
}
fn handle<'a>(&self, parser: &mut Parser<'a>) -> Result<(), DbusError> {
(self.handler)(T::Generic::<'a>::unmarshal(parser)?);
Ok(())
}
}
#[must_use]
pub struct SignalHandler {
socket: Rc<DbusSocket>,
data: Rc<dyn SignalHandlerApi>,
}
impl Drop for SignalHandler {
fn drop(&mut self) {
self.socket.remove_signal_handler(&*self.data);
}
}
struct InterfaceSignalHandlers {
unconditional: Option<Rc<dyn SignalHandlerApi>>,
conditional: AHashMap<String, Rc<dyn SignalHandlerApi>>,
}
pub mod prelude {
pub use super::{
types::{Bool, DictEntry, ObjectPath, Signature, Variant},
DbusError, DbusType, Formatter, Message, MethodCall, Parser, Property,
DbusError, DbusType, Formatter, Message, MethodCall, Parser, Property, Signal,
};
pub use std::borrow::Cow;
pub use std::rc::Rc;

View file

@ -86,7 +86,7 @@ impl Auth {
match uapi::read(self.socket.fd.raw(), &mut self.buf[..]) {
Ok(n) => self.buf_stop = n.len(),
Err(Errno(c::EAGAIN)) => {
let _ = self.socket.fd.readable().await;
self.socket.fd.readable().await?;
}
Err(e) => return Err(DbusError::ReadError(e.into())),
}
@ -99,7 +99,7 @@ impl Auth {
match uapi::write(self.socket.fd.raw(), &buf[start..]) {
Ok(n) => start += n,
Err(Errno(c::EAGAIN)) => {
let _ = self.socket.fd.writable().await;
self.socket.fd.writable().await?;
}
Err(e) => return Err(DbusError::WriteError(e.into())),
}

View file

@ -137,7 +137,7 @@ impl DynamicType {
DynamicType::U32 => Variant::U32(parser.read_pod()?),
DynamicType::I64 => Variant::I64(parser.read_pod()?),
DynamicType::U64 => Variant::U64(parser.read_pod()?),
DynamicType::F64 => Variant::F64(parser.read_pod()?),
DynamicType::F64 => Variant::F64(f64::from_bits(parser.read_pod()?)),
DynamicType::String => Variant::String(parser.read_string()?),
DynamicType::ObjectPath => Variant::ObjectPath(parser.read_object_path()?),
DynamicType::Signature => Variant::Signature(parser.read_signature()?),

View file

@ -61,6 +61,7 @@ fn connect(
dead: Cell::new(false),
headers: Default::default(),
run_toplevel: run_toplevel.clone(),
signal_handlers: Default::default(),
});
let skt = socket.clone();
socket.call(

View file

@ -3,7 +3,7 @@ use super::{
HDR_SENDER, HDR_SIGNATURE, HDR_UNIX_FDS,
};
use crate::dbus::{
CallError, DbusError, DbusSocket, Headers, Parser, MSG_ERROR, MSG_METHOD_RETURN,
CallError, DbusError, DbusSocket, Headers, Parser, MSG_ERROR, MSG_METHOD_RETURN, MSG_SIGNAL,
};
use crate::utils::ptr_ext::{MutPtrExt, PtrExt};
use crate::ErrorFmt;
@ -119,8 +119,8 @@ impl Incoming {
log::error!(
"{}: Message reply has an invalid signature: expected: {}, actual: {}",
self.socket.bus_name,
reply.signature(),
sig,
reply.signature()
);
} else {
let buf = unsafe { std::mem::take(msg_buf_data.get().deref_mut()) };
@ -135,6 +135,39 @@ impl Incoming {
}
}
}
MSG_SIGNAL => {
let (interface, member, path) =
match (&headers.interface, &headers.member, &headers.path) {
(Some(i), Some(m), Some(p)) => (i, m, p),
_ => return Err(DbusError::MissingSignalHeaders),
};
let handlers = self.socket.signal_handlers.borrow_mut();
if let Some(handler) = handlers.get(&(interface.deref(), member.deref())) {
let handler = handler
.conditional
.get(path.deref())
.or(handler.unconditional.as_ref());
if let Some(handler) = handler {
let sig = headers.signature.as_deref().unwrap_or("");
if sig != handler.signature() {
log::error!(
"{}: Signal has an invalid signature: expected: {}, actual: {}",
self.socket.bus_name,
handler.signature(),
sig,
);
} else {
if let Err(e) = handler.handle(&mut parser) {
log::error!(
"{}: Could not handle signal: {}",
self.socket.bus_name,
ErrorFmt(e)
);
}
}
}
}
}
_ => {}
}
let msg_buf = msg_buf_data.into_inner();
@ -174,7 +207,7 @@ impl Incoming {
if e.0 != c::EAGAIN {
return Err(DbusError::ReadError(e.into()));
}
let _ = self.socket.fd.readable().await;
self.socket.fd.readable().await?;
}
if self.buf_start == self.buf_end {
return Err(DbusError::Closed);

View file

@ -48,7 +48,11 @@ impl Outgoing {
self.socket.kill();
return;
}
let _ = self.socket.fd.writable().await;
if let Err(e) = self.socket.fd.writable().await {
log::error!("{}: Cannot wait for fd to become readable: {}", self.socket.bus_name, ErrorFmt(e));
self.socket.kill();
return;
}
}
}
}

View file

@ -2,11 +2,15 @@ use crate::dbus::property::Get;
use crate::dbus::types::{ObjectPath, Signature, Variant};
use crate::dbus::{
AsyncProperty, AsyncReply, AsyncReplySlot, DbusError, DbusMessage, DbusSocket, DbusType,
Formatter, Headers, Message, MethodCall, Parser, Property, Reply, ReplyHandler,
Formatter, Headers, InterfaceSignalHandlers, Message, MethodCall, Parser, Property, Reply,
ReplyHandler, Signal, SignalHandler, SignalHandlerApi, SignalHandlerData, BUS_DEST, BUS_PATH,
HDR_DESTINATION, HDR_INTERFACE, HDR_MEMBER, HDR_PATH, HDR_SIGNATURE, HDR_UNIX_FDS,
MSG_METHOD_CALL, NO_REPLY_EXPECTED,
};
use crate::{org, ErrorFmt};
use std::cell::Cell;
use std::collections::hash_map::Entry;
use std::fmt::Write;
use std::marker::PhantomData;
use std::mem;
use std::ops::DerefMut;
@ -116,6 +120,118 @@ impl DbusSocket {
}
}
pub fn handle_signal<T, F>(
self: &Rc<Self>,
sender: Option<&str>,
path: Option<&str>,
handler: F,
) -> Result<SignalHandler, DbusError>
where
T: Signal<'static>,
F: for<'a> Fn(T::Generic<'a>) + 'static,
{
let mut rule = format!(
"type='signal',interface='{}',member='{}'",
T::INTERFACE,
T::MEMBER
);
if let Some(sender) = sender {
let _ = write!(rule, ",sender='{}'", sender);
}
if let Some(path) = path {
let _ = write!(rule, ",path='{}'", path);
}
let shd: SignalHandlerData<T, _> = SignalHandlerData {
path: path.map(|s| s.to_owned()),
rule,
handler,
_phantom: Default::default(),
};
self.handle_signal_dyn(Rc::new(shd))
}
fn handle_signal_dyn(
self: &Rc<Self>,
handler: Rc<dyn SignalHandlerApi>,
) -> Result<SignalHandler, DbusError> {
let mut sh = self.signal_handlers.borrow_mut();
let entry = sh
.entry((handler.interface(), handler.member()))
.or_insert_with(|| InterfaceSignalHandlers {
unconditional: Default::default(),
conditional: Default::default(),
});
match handler.path() {
Some(p) => match entry.conditional.entry(p.to_owned()) {
Entry::Occupied(_) => return Err(DbusError::AlreadyHandled),
Entry::Vacant(v) => {
v.insert(handler.clone());
}
},
_ if entry.unconditional.is_some() => return Err(DbusError::AlreadyHandled),
_ => entry.unconditional = Some(handler.clone()),
}
self.call(
BUS_DEST,
BUS_PATH,
org::freedesktop::dbus::AddMatch {
rule: handler.rule().into(),
},
{
let slf = self.clone();
move |res| {
if let Err(e) = res {
log::error!(
"{}: Could not register a signal handler: {}",
slf.bus_name,
ErrorFmt(e)
);
}
}
},
);
Ok(SignalHandler {
socket: self.clone(),
data: handler,
})
}
pub(super) fn remove_signal_handler(self: &Rc<Self>, handler: &dyn SignalHandlerApi) {
let mut sh = self.signal_handlers.borrow_mut();
let mut entry = match sh.entry((handler.interface(), handler.member())) {
Entry::Occupied(o) => o,
Entry::Vacant(_) => return,
};
match handler.path() {
Some(p) => {
entry.get_mut().conditional.remove(p);
}
_ => entry.get_mut().unconditional = None,
}
if entry.get().unconditional.is_none() && entry.get().conditional.is_empty() {
entry.remove();
}
self.call(
BUS_DEST,
BUS_PATH,
org::freedesktop::dbus::RemoveMatch {
rule: handler.rule().into(),
},
{
let slf = self.clone();
move |res| {
if let Err(e) = res {
log::error!(
"{}: Could not unregister a signal handler: {}",
slf.bus_name,
ErrorFmt(e)
);
}
}
},
);
}
fn send_call<'a, T: Message<'a>>(
&self,
path: &str,

View file

@ -3,7 +3,6 @@ use crate::dbus::{
TY_INT16, TY_INT32, TY_INT64, TY_OBJECT_PATH, TY_SIGNATURE, TY_STRING, TY_UINT16, TY_UINT32,
TY_UINT64, TY_UNIX_FD, TY_VARIANT,
};
use crate::utils::aligned::{AlignedF64, AlignedI64, AlignedU64};
use std::borrow::Cow;
use std::ops::Deref;
use std::rc::Rc;
@ -139,7 +138,7 @@ unsafe impl<'a> DbusType<'a> for u32 {
}
}
unsafe impl<'a> DbusType<'a> for AlignedI64 {
unsafe impl<'a> DbusType<'a> for i64 {
const ALIGNMENT: usize = 8;
const IS_POD: bool = true;
type Generic<'b> = Self;
@ -155,7 +154,7 @@ unsafe impl<'a> DbusType<'a> for AlignedI64 {
}
}
unsafe impl<'a> DbusType<'a> for AlignedU64 {
unsafe impl<'a> DbusType<'a> for u64 {
const ALIGNMENT: usize = 8;
const IS_POD: bool = true;
type Generic<'b> = Self;
@ -171,7 +170,7 @@ unsafe impl<'a> DbusType<'a> for AlignedU64 {
}
}
unsafe impl<'a> DbusType<'a> for AlignedF64 {
unsafe impl<'a> DbusType<'a> for f64 {
const ALIGNMENT: usize = 8;
const IS_POD: bool = true;
type Generic<'b> = Self;
@ -179,11 +178,11 @@ unsafe impl<'a> DbusType<'a> for AlignedF64 {
signature!(TY_DOUBLE);
fn marshal(&self, fmt: &mut Formatter) {
fmt.write_packed(self);
fmt.write_packed(&self.to_bits());
}
fn unmarshal(parser: &mut Parser<'a>) -> Result<Self, DbusError> {
parser.read_pod()
Ok(f64::from_bits(parser.read_pod()?))
}
}
@ -417,9 +416,9 @@ pub enum Variant<'a> {
U16(u16),
I32(i32),
U32(u32),
I64(AlignedI64),
U64(AlignedU64),
F64(AlignedF64),
I64(i64),
U64(u64),
F64(f64),
String(Cow<'a, str>),
ObjectPath(ObjectPath<'a>),
Signature(Signature<'a>),

View file

@ -128,7 +128,9 @@ impl EventLoop {
};
if let Some(fd) = entry.fd {
if let Err(e) = uapi::epoll_ctl(self.epoll.raw(), c::EPOLL_CTL_DEL, fd, None) {
return Err(EventLoopError::RemoveFailed(e.into()));
if e.0 != c::ENOENT {
return Err(EventLoopError::RemoveFailed(e.into()));
}
}
}
Ok(())

View file

@ -234,8 +234,11 @@ impl ForkerProxy {
async fn check_process(self: Rc<Self>, state: Rc<State>) {
let pidfd = state.eng.fd(&self.pidfd).unwrap();
let _ = pidfd.readable().await;
let _ = uapi::waitpid(self.pid, 0);
if let Err(e) = pidfd.readable().await {
log::error!("Cannot wait for the forker pidfd to become readable: {}", ErrorFmt(e));
} else {
let _ = uapi::waitpid(self.pid, 0);
}
log::error!("The ol' forker died. Cannot spawn further processes.");
state.forker.set(None);
self.task_out.take();
@ -413,14 +416,17 @@ impl Forker {
let slf = self.clone();
let spawn = self.ae.spawn(async move {
let read = slf.ae.fd(&Rc::new(read)).unwrap();
let _ = read.readable().await;
let mut s = String::new();
let _ = Fd::new(read.raw()).read_to_string(&mut s);
if s.len() > 0 {
slf.outgoing.push(ForkerMessage::Log {
level: log::Level::Error as _,
msg: format!("Could not spawn `{}`: {}", prog, s),
});
if let Err(e) = read.readable().await {
log::error!("Cannot wait for the child fd to become readable: {}", ErrorFmt(e));
} else {
let mut s = String::new();
let _ = Fd::new(read.raw()).read_to_string(&mut s);
if s.len() > 0 {
slf.outgoing.push(ForkerMessage::Log {
level: log::Level::Error as _,
msg: format!("Could not spawn `{}`: {}", prog, s),
});
}
}
slf.pending_spawns.remove(&pid);
});

View file

@ -157,13 +157,14 @@ impl WlSeatGlobal {
tree_changed_handler: Cell::new(None),
});
let seat = slf.clone();
state.eng.spawn(async move {
let future = state.eng.spawn(async move {
loop {
seat.tree_changed.triggered().await;
seat.state.tree_changed_sent.set(false);
seat.tree_changed();
}
});
slf.tree_changed_handler.set(Some(future));
slf
}

84
src/libinput.rs Normal file
View file

@ -0,0 +1,84 @@
use crate::udev::Udev;
use crate::utils::ptr_ext::PtrExt;
use std::ops::DerefMut;
use std::rc::Rc;
use thiserror::Error;
use uapi::{c, OwnedFd};
#[link(name = "input")]
extern "C" {
type libinput;
fn libinput_path_create_context(
interface: *const libinput_interface,
user_data: *mut c::c_void,
) -> *mut libinput;
fn libinput_unref(libinput: *mut libinput) -> *mut libinput;
fn libinput_get_fd(libinput: *mut libinput) -> c::c_int;
}
#[repr(C)]
struct libinput_interface {
open_restricted: unsafe extern "C" fn(
path: *const c::c_char,
flags: c::c_int,
user_data: *mut c::c_void,
) -> c::c_int,
close_restricted: unsafe extern "C" fn(fd: c::c_int, user_data: *mut c::c_void),
}
static INTERFACE: libinput_interface = libinput_interface {
open_restricted,
close_restricted,
};
unsafe extern "C" fn open_restricted(
path: *const c::c_char,
flags: c::c_int,
user_data: *mut c::c_void,
) -> c::c_int {
let ud = (user_data as *const UserData).deref();
-1
}
unsafe extern "C" fn close_restricted(fd: c::c_int, _user_data: *mut c::c_void) {
drop(OwnedFd::new(fd));
}
struct UserData {}
#[derive(Debug, Error)]
pub enum LibInputError {
#[error("Could not create a libinput instance")]
New,
}
pub struct LibInput {
data: Box<UserData>,
li: *mut libinput,
}
impl LibInput {
pub fn new() -> Result<Self, LibInputError> {
let mut ud = Box::new(UserData {});
let li = unsafe {
libinput_path_create_context(&INTERFACE, &mut *ud as *mut _ as *mut c::c_void)
};
if li.is_null() {
return Err(LibInputError::New);
}
Ok(Self { data: ud, li })
}
pub fn fd(&self) -> c::c_int {
unsafe { libinput_get_fd(self.li) }
}
}
impl Drop for LibInput {
fn drop(&mut self) {
unsafe {
libinput_unref(self.li);
}
}
}

View file

@ -1 +1,79 @@
use crate::dbus::{DbusError, DbusSocket, Reply};
use crate::org::freedesktop::login1::session::TakeControlReply;
use crate::{org, FALSE};
use std::rc::Rc;
use thiserror::Error;
const LOGIND_NAME: &str = "org.freedesktop.login1";
const MANAGER_PATH: &str = "/org/freedesktop/login1";
#[derive(Debug, Error)]
pub enum LogindError {
#[error("XDG_SESSION_ID is not set")]
XdgSessionId,
#[error("Could not retrieve the session dbus path")]
GetSession(DbusError),
#[error("Could not retrieve the session's seat name")]
GetSeatName(DbusError),
#[error(transparent)]
TakeControl(DbusError),
}
pub struct Session {
socket: Rc<DbusSocket>,
seat: String,
session_path: String,
}
impl Session {
pub async fn get(socket: &Rc<DbusSocket>) -> Result<Self, LogindError> {
let session_id = match std::env::var("XDG_SESSION_ID") {
Ok(id) => id,
_ => return Err(LogindError::XdgSessionId),
};
let session_path = {
let session = socket
.call_async(
LOGIND_NAME,
MANAGER_PATH,
org::freedesktop::login1::manager::GetSession {
session_id: session_id.as_str().into(),
},
)
.await;
match session {
Ok(s) => s.get().object_path.to_string(),
Err(e) => return Err(LogindError::GetSession(e)),
}
};
let seat = {
let seat = socket
.get_async::<org::freedesktop::login1::session::Seat>(LOGIND_NAME, &session_path)
.await;
match seat {
Ok(s) => s.get().0.to_string(),
Err(e) => return Err(LogindError::GetSeatName(e)),
}
};
Ok(Self {
socket: socket.clone(),
seat,
session_path,
})
}
pub async fn take_control(&self) -> Result<(), LogindError> {
let res = self
.socket
.call_async(
LOGIND_NAME,
&self.session_path,
org::freedesktop::login1::session::TakeControl { force: FALSE },
)
.await;
match res {
Ok(r) => Ok(()),
Err(e) => Err(LogindError::TakeControl(e)),
}
}
}

View file

@ -330,6 +330,21 @@ macro_rules! assert_size_eq {
}};
}
macro_rules! assert_size_le {
($t:ty, $u:ty) => {{
struct AssertLeSize<T, U>(std::marker::PhantomData<T>, std::marker::PhantomData<U>);
impl<T, U> AssertLeSize<T, U> {
const VAL: usize = {
if std::mem::size_of::<T>() > std::mem::size_of::<U>() {
panic!("Left type has size larger than right type");
}
1
};
}
let _ = AssertLeSize::<$t, $u>::VAL;
}};
}
macro_rules! assert_align_eq {
($t:ty, $u:ty) => {{
struct AssertEqAlign<T, U>(std::marker::PhantomData<T>, std::marker::PhantomData<U>);

View file

@ -3,7 +3,8 @@
thread_local,
label_break_value,
try_blocks,
generic_associated_types
generic_associated_types,
extern_types
)]
#![allow(
clippy::len_zero,
@ -19,7 +20,7 @@ use crate::backends::dummy::DummyBackend;
use crate::backends::xorg::{XorgBackend, XorgBackendError};
use crate::client::Clients;
use crate::clientmem::ClientMemError;
use crate::dbus::{Dbus, FALSE};
use crate::dbus::{Dbus, FALSE, TRUE};
use crate::event_loop::EventLoopError;
use crate::forker::ForkerError;
use crate::globals::Globals;
@ -36,6 +37,7 @@ use crate::state::State;
use crate::tree::{
container_layout, container_titles, float_layout, float_titles, DisplayNode, NodeIds,
};
use crate::udev::Udev;
use crate::utils::clonecell::CloneCell;
use crate::utils::errorfmt::ErrorFmt;
use crate::utils::numcell::NumCell;
@ -53,6 +55,7 @@ use std::ops::Deref;
use std::rc::Rc;
use thiserror::Error;
use wheel::Wheel;
use crate::backends::metal;
#[macro_use]
mod macros;
@ -75,6 +78,7 @@ mod forker;
mod format;
mod globals;
mod ifs;
mod libinput;
mod logind;
mod object;
mod pixman;
@ -88,6 +92,7 @@ mod text;
mod theme;
mod time;
mod tree;
mod udev;
mod utils;
mod wheel;
mod wire;
@ -178,40 +183,10 @@ fn main_() -> Result<(), MainError> {
pending_float_titles: Default::default(),
dbus: Dbus::new(&engine, &run_toplevel),
});
let _future = state.eng.spawn({
let dbus = state.dbus.system().unwrap();
async move {
const LOGIND: &str = "org.freedesktop.login1";
let reply = dbus
.call_async(
LOGIND,
"/org/freedesktop/login1",
org::freedesktop::login1::manager::GetSession {
session_id: std::env::var("XDG_SESSION_ID").unwrap().into(),
},
)
.await
.unwrap();
let reply = dbus
.call_async(
LOGIND,
&reply.get().object_path,
org::freedesktop::login1::session::TakeControl { force: FALSE },
)
.await;
log::info!("{:?}", reply);
let reply = dbus
.get_async::<org::freedesktop::login1::manager::BootLoaderEntries>(
LOGIND,
"/org/freedesktop/login1",
)
.await;
log::info!("{:?}", reply);
}
});
let _future = state.eng.spawn(metal::run(state.clone()));
forker.install(&state);
let backend = XorgBackend::new(&state)?;
state.backend.set(backend);
// let backend = XorgBackend::new(&state)?;
// state.backend.set(backend);
let config = config::ConfigProxy::default(&state);
state.config.set(Some(Rc::new(config)));
let _global_event_handler = engine.spawn(tasks::handle_backend_events(state.clone()));

317
src/udev.rs Normal file
View file

@ -0,0 +1,317 @@
use crate::dbus::DbusError;
use std::ffi::CStr;
use std::marker::PhantomData;
use std::ptr;
use std::rc::Rc;
use thiserror::Error;
use uapi::{c, Errno, IntoUstr, Ustr};
#[link(name = "udev")]
extern "C" {
type udev;
type udev_monitor;
type udev_enumerate;
type udev_list_entry;
type udev_device;
fn udev_new() -> *mut udev;
fn udev_unref(udev: *mut udev) -> *mut udev;
fn udev_monitor_new_from_netlink(udev: *mut udev, name: *const c::c_char) -> *mut udev_monitor;
fn udev_monitor_get_fd(udev_monitor: *mut udev_monitor) -> c::c_int;
fn udev_monitor_unref(udev_monitor: *mut udev_monitor) -> *mut udev_monitor;
fn udev_monitor_enable_receiving(udev_monitor: *mut udev_monitor) -> c::c_int;
fn udev_monitor_filter_add_match_subsystem_devtype(
udev_monitor: *mut udev_monitor,
subsystem: *const c::c_char,
devtype: *const c::c_char,
) -> c::c_int;
fn udev_monitor_receive_device(udev_monitor: *mut udev_monitor) -> *mut udev_device;
fn udev_enumerate_new(udev: *mut udev) -> *mut udev_enumerate;
fn udev_enumerate_unref(udev_enumerate: *mut udev_enumerate) -> *mut udev_enumerate;
fn udev_enumerate_add_match_subsystem(
udev_enumerate: *mut udev_enumerate,
subsystem: *const c::c_char,
) -> c::c_int;
fn udev_enumerate_scan_devices(udev_enumerate: *mut udev_enumerate) -> c::c_int;
fn udev_enumerate_get_list_entry(udev_enumerate: *mut udev_enumerate) -> *mut udev_list_entry;
fn udev_list_entry_get_next(list_entry: *mut udev_list_entry) -> *mut udev_list_entry;
fn udev_list_entry_get_name(list_entry: *mut udev_list_entry) -> *const c::c_char;
fn udev_list_entry_get_value(list_entry: *mut udev_list_entry) -> *const c::c_char;
fn udev_device_new_from_syspath(udev: *mut udev, syspath: *const c::c_char)
-> *mut udev_device;
fn udev_device_unref(udev_device: *mut udev_device) -> *mut udev_device;
fn udev_device_get_sysname(udev_device: *mut udev_device) -> *const c::c_char;
fn udev_device_get_is_initialized(udev_device: *mut udev_device) -> c::c_int;
fn udev_device_get_devnode(udev_device: *mut udev_device) -> *const c::c_char;
}
#[derive(Debug, Error)]
pub enum UdevError {
#[error("Could not create a new udev instance")]
New(#[source] std::io::Error),
#[error("Could not create a new udev_monitor instance")]
NewMonitor(#[source] std::io::Error),
#[error("Could not create a new udev_enumerate instance")]
NewEnumerate(#[source] std::io::Error),
#[error("Could not enable receiving on a udev_monitor")]
EnableReceiving(#[source] std::io::Error),
#[error("Could not add a match rule to a udev_monitor")]
MonitorAddMatch(#[source] std::io::Error),
#[error("Could not add a match rule to a udev_enumerate")]
EnumerateAddMatch(#[source] std::io::Error),
#[error("Could not list devices of a udev_enumerate")]
EnumerateGetListEntry(#[source] std::io::Error),
#[error("Could not scan devices of a udev_enumerate")]
ScanDevices(#[source] std::io::Error),
#[error("Could not create a udev_device from a syspath")]
DeviceFromSyspath(#[source] std::io::Error),
#[error("Could not retrieve the sysname of a udev_device")]
GetSysname(#[source] std::io::Error),
#[error("Could not retrieve the devnode of a udev_device")]
GetDevnode(#[source] std::io::Error),
}
pub struct Udev {
udev: *mut udev,
}
pub struct UdevMonitor {
udev: Rc<Udev>,
monitor: *mut udev_monitor,
}
pub struct UdevEnumerate {
udev: Rc<Udev>,
enumerate: *mut udev_enumerate,
}
pub struct UdevListEntry<'a> {
list_entry: *mut udev_list_entry,
_phantom: PhantomData<&'a mut ()>,
}
pub struct UdevDevice {
udev: Rc<Udev>,
device: *mut udev_device,
}
impl Udev {
pub fn new() -> Result<Self, UdevError> {
let res = unsafe { udev_new() };
if res.is_null() {
return Err(UdevError::New(Errno::default().into()));
}
Ok(Self { udev: res })
}
pub fn create_monitor(self: &Rc<Self>) -> Result<UdevMonitor, UdevError> {
let res = unsafe { udev_monitor_new_from_netlink(self.udev, "udev\0".as_ptr() as _) };
if res.is_null() {
return Err(UdevError::NewMonitor(Errno::default().into()));
}
Ok(UdevMonitor {
udev: self.clone(),
monitor: res,
})
}
pub fn create_enumerate(self: &Rc<Self>) -> Result<UdevEnumerate, UdevError> {
let res = unsafe { udev_enumerate_new(self.udev) };
if res.is_null() {
return Err(UdevError::NewEnumerate(Errno::default().into()));
}
Ok(UdevEnumerate {
udev: self.clone(),
enumerate: res,
})
}
pub fn create_device_from_syspath<'a>(
self: &Rc<Self>,
syspath: impl IntoUstr<'a>,
) -> Result<UdevDevice, UdevError> {
let syspath = syspath.into_ustr();
let res = unsafe { udev_device_new_from_syspath(self.udev, syspath.as_ptr()) };
if res.is_null() {
return Err(UdevError::DeviceFromSyspath(Errno::default().into()));
}
Ok(UdevDevice {
udev: self.clone(),
device: res,
})
}
}
impl Drop for Udev {
fn drop(&mut self) {
unsafe {
udev_unref(self.udev);
}
}
}
impl UdevMonitor {
pub fn fd(&self) -> c::c_int {
unsafe { udev_monitor_get_fd(self.monitor) }
}
pub fn enable_receiving(&self) -> Result<(), UdevError> {
let res = unsafe { udev_monitor_enable_receiving(self.monitor) };
if res < 0 {
Err(UdevError::EnableReceiving(Errno(-res).into()))
} else {
Ok(())
}
}
pub fn add_match_subsystem_devtype(
&self,
subsystem: Option<&str>,
devtype: Option<&str>,
) -> Result<(), UdevError> {
let subsystem = subsystem.map(|s| s.into_ustr());
let devtype = devtype.map(|s| s.into_ustr());
let res = unsafe {
udev_monitor_filter_add_match_subsystem_devtype(
self.monitor,
subsystem
.as_ref()
.map(|s| s.as_ptr())
.unwrap_or(ptr::null()),
devtype.as_ref().map(|s| s.as_ptr()).unwrap_or(ptr::null()),
)
};
if res < 0 {
Err(UdevError::MonitorAddMatch(Errno(-res).into()))
} else {
Ok(())
}
}
pub fn receive_device(&self) -> Option<UdevDevice> {
let res = unsafe {
udev_monitor_receive_device(self.monitor)
};
if res.is_null() {
None
} else {
Some(UdevDevice {
udev: self.udev.clone(),
device: res,
})
}
}
}
impl Drop for UdevMonitor {
fn drop(&mut self) {
unsafe {
udev_monitor_unref(self.monitor);
}
}
}
impl UdevEnumerate {
pub fn add_match_subsystem(&self, subsystem: &str) -> Result<(), UdevError> {
let subsystem = subsystem.into_ustr();
let res = unsafe { udev_enumerate_add_match_subsystem(self.enumerate, subsystem.as_ptr()) };
if res < 0 {
Err(UdevError::EnumerateAddMatch(Errno(-res).into()))
} else {
Ok(())
}
}
pub fn scan_devices(&self) -> Result<(), UdevError> {
let res = unsafe { udev_enumerate_scan_devices(self.enumerate) };
if res < 0 {
Err(UdevError::ScanDevices(Errno(-res).into()))
} else {
Ok(())
}
}
pub fn get_list_entry(&mut self) -> Result<Option<UdevListEntry>, UdevError> {
let res = unsafe { udev_enumerate_get_list_entry(self.enumerate) };
if res.is_null() {
let err = Errno::default();
if err.0 == c::ENODATA {
Ok(None)
} else {
Err(UdevError::EnumerateGetListEntry(err.into()))
}
} else {
Ok(Some(UdevListEntry {
list_entry: res,
_phantom: Default::default(),
}))
}
}
}
impl Drop for UdevEnumerate {
fn drop(&mut self) {
unsafe {
udev_enumerate_unref(self.enumerate);
}
}
}
impl<'a> UdevListEntry<'a> {
pub fn next(self) -> Option<Self> {
unsafe {
let res = udev_list_entry_get_next(self.list_entry);
if res.is_null() {
None
} else {
Some(Self {
list_entry: res,
_phantom: Default::default(),
})
}
}
}
pub fn name(&self) -> &CStr {
unsafe {
let s = udev_list_entry_get_name(self.list_entry);
CStr::from_ptr(s)
}
}
}
impl UdevDevice {
pub fn sysname(&self) -> Result<&CStr, UdevError> {
let res = unsafe { udev_device_get_sysname(self.device) };
if res.is_null() {
Err(UdevError::GetSysname(Errno::default().into()))
} else {
unsafe { Ok(CStr::from_ptr(res)) }
}
}
pub fn devnode(&self) -> Result<&CStr, UdevError> {
let res = unsafe { udev_device_get_devnode(self.device) };
if res.is_null() {
Err(UdevError::GetDevnode(Errno::default().into()))
} else {
unsafe { Ok(CStr::from_ptr(res)) }
}
}
pub fn is_initialized(&self) -> bool {
unsafe { udev_device_get_is_initialized(self.device) != 0 }
}
}
impl Drop for UdevDevice {
fn drop(&mut self) {
unsafe {
udev_device_unref(self.device);
}
}
}

View file

@ -1,22 +0,0 @@
use uapi::{Packed, Pod};
#[repr(C, align(8))]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AlignedI64(pub i64);
unsafe impl Pod for AlignedI64 {}
unsafe impl Packed for AlignedI64 {}
#[repr(C, align(8))]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct AlignedU64(pub u64);
unsafe impl Pod for AlignedU64 {}
unsafe impl Packed for AlignedU64 {}
#[repr(C, align(8))]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct AlignedF64(pub f64);
unsafe impl Pod for AlignedF64 {}
unsafe impl Packed for AlignedF64 {}

28
src/utils/bitfield.rs Normal file
View file

@ -0,0 +1,28 @@
use std::mem;
const SEG_SIZE: usize = 8 * mem::size_of::<usize>();
#[derive(Default)]
pub struct Bitfield {
vals: Vec<usize>,
}
impl Bitfield {
pub fn acquire(&mut self) -> u32 {
for (idx, n) in self.vals.iter_mut().enumerate() {
if *n != 0 {
let pos = n.trailing_zeros();
*n &= !(1 << pos);
return (idx * SEG_SIZE) as u32 + pos;
}
}
self.vals.push(!1);
((self.vals.len() - 1) * SEG_SIZE) as u32
}
pub fn release(&mut self, val: u32) {
let idx = val as usize / SEG_SIZE;
let pos = val as usize % SEG_SIZE;
self.vals[idx] |= 1 << pos;
}
}

View file

@ -101,7 +101,9 @@ impl BufFdOut {
_ = timeout.as_mut().unwrap() => {
return Err(BufFdError::Timeout);
},
res = self.fd.writable().fuse() => res?,
res = self.fd.writable().fuse() => {
res?;
},
}
}
}

View file

@ -1,4 +1,3 @@
pub mod aligned;
pub mod array;
pub mod asyncevent;
pub mod bitflags;
@ -18,3 +17,4 @@ pub mod stack;
pub mod tri;
pub mod vec_ext;
pub mod vecstorage;
pub mod bitfield;

View file

@ -100,7 +100,7 @@ pub async fn manage(state: Rc<State>) {
log::info!("Allocated display :{} for Xwayland", xsocket.id);
log::info!("Waiting for connection attempt");
let res = XWaylandError::tria(async {
let _ = state.eng.fd(&socket)?.readable().await;
state.eng.fd(&socket)?.readable().await?;
Ok(())
})
.await;
@ -168,13 +168,13 @@ async fn run(
Ok(c) => c,
Err(e) => return Err(XWaylandError::SpawnClient(e)),
};
let _ = state.eng.fd(&Rc::new(dfdread))?.readable().await;
state.eng.fd(&Rc::new(dfdread))?.readable().await?;
let wm = match Wm::get(state, client, wm1, queue.clone()) {
Ok(w) => w,
Err(e) => return Err(XWaylandError::CreateWm(Box::new(e))),
};
let wm = state.eng.spawn(wm.run());
let _ = state.eng.fd(&Rc::new(pidfd))?.readable().await;
state.eng.fd(&Rc::new(pidfd))?.readable().await?;
drop(wm);
queue.clear();
stderr_read.await;
@ -223,7 +223,10 @@ async fn log_xwayland(state: Rc<State>, stderr: OwnedFd) {
let mut buf2 = [0; 128];
let mut done = false;
while !done {
let _ = afd.readable().await;
if let Err(e) = afd.readable().await {
log::error!("Cannot wait for the xwayland stderr to become readable: {}", ErrorFmt(e));
return;
}
loop {
match uapi::read(afd.raw(), &mut buf2[..]) {
Ok(buf2) if buf2.len() > 0 => {

View file

@ -247,7 +247,12 @@ impl Wm {
return;
}
futures::select! {
_ = self.socket.readable().fuse() => { },
res = self.socket.readable().fuse() => {
if let Err(e) = res {
log::error!("Cannot wait for xwm fd to become readable: {}", ErrorFmt(e));
return;
}
}
_ = self.queue.non_empty().fuse() => { },
}
}

View file

@ -1,3 +1,7 @@
fn Hello() {
name: string,
}
fn AddMatch(rule: string) { }
fn RemoveMatch(rule: string) { }

View file

@ -5,3 +5,4 @@ fn GetSession(
}
prop BootLoaderEntries = array(string)
prop ScheduledShutdown = struct(string, u64)

View file

@ -8,3 +8,16 @@ fn TakeDevice(major: u32, minor: u32) {
fn PauseDeviceComplete(major: u32, minor: u32) { }
prop Seat = struct(string, object_path)
sig PauseDevice {
major: u32,
minor: u32,
ty: string,
}
sig ResumeDevice {
major: u32,
minor: u32,
fd: fd,
}