autocommit 2022-03-02 14:24:07 CET
This commit is contained in:
parent
0e9afcbfa5
commit
aa0cb94143
30 changed files with 1059 additions and 123 deletions
|
|
@ -1,3 +1,5 @@
|
|||
extern crate core;
|
||||
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::BufWriter;
|
||||
use std::path::PathBuf;
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
128
src/backends/metal.rs
Normal 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.");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
pub mod dummy;
|
||||
pub mod metal;
|
||||
pub mod xorg;
|
||||
|
|
|
|||
78
src/dbus.rs
78
src/dbus.rs
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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())),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()?),
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>),
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
84
src/libinput.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>);
|
||||
|
|
|
|||
45
src/main.rs
45
src/main.rs
|
|
@ -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
317
src/udev.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
28
src/utils/bitfield.rs
Normal 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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?;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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() => { },
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
fn Hello() {
|
||||
name: string,
|
||||
}
|
||||
|
||||
fn AddMatch(rule: string) { }
|
||||
|
||||
fn RemoveMatch(rule: string) { }
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@ fn GetSession(
|
|||
}
|
||||
|
||||
prop BootLoaderEntries = array(string)
|
||||
prop ScheduledShutdown = struct(string, u64)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue