autocommit 2022-02-15 22:53:12 CET
This commit is contained in:
parent
290225190a
commit
cacd49d15a
33 changed files with 884 additions and 220 deletions
|
|
@ -71,7 +71,7 @@ fn bind_socket(fd: i32, xdr: &str) -> Result<u32, AcceptorError> {
|
|||
}
|
||||
|
||||
impl Acceptor {
|
||||
pub fn install(global: &Rc<State>) -> Result<(), AcceptorError> {
|
||||
pub fn install(global: &Rc<State>) -> Result<String, AcceptorError> {
|
||||
let xrd = match std::env::var("XDG_RUNTIME_DIR") {
|
||||
Ok(d) => d,
|
||||
Err(_) => return Err(AcceptorError::XrdNotSet),
|
||||
|
|
@ -87,7 +87,7 @@ impl Acceptor {
|
|||
let socket_id = bind_socket(fd.raw(), &xrd)?;
|
||||
let socket_path = socket_path(&xrd, socket_id);
|
||||
log::info!("bound to socket {}", socket_path);
|
||||
let unlinker = Unlinker(socket_path);
|
||||
let unlinker = Unlinker(socket_path.clone());
|
||||
if let Err(e) = uapi::listen(fd.raw(), 4096) {
|
||||
return Err(AcceptorError::ListenFailed(e.into()));
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ impl Acceptor {
|
|||
global: global.clone(),
|
||||
});
|
||||
global.el.insert(id, Some(acc.fd.raw()), c::EPOLLIN, acc)?;
|
||||
Ok(())
|
||||
Ok(socket_path)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
use crate::backend::{BackendEvent, Keyboard, KeyboardEvent, KeyboardId, KeyState, Mouse, MouseEvent, MouseId, Output, OutputId, ScrollAxis};
|
||||
use crate::backend::{
|
||||
BackendEvent, KeyState, Keyboard, KeyboardEvent, KeyboardId, Mouse, MouseEvent, MouseId,
|
||||
Output, OutputId, ScrollAxis,
|
||||
};
|
||||
use crate::drm::drm::{Drm, DrmError};
|
||||
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
|
||||
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
mod handler;
|
||||
|
||||
use crate::backend::{KeyboardId, MouseId};
|
||||
use crate::config::handler::ConfigProxyHandler;
|
||||
use crate::ifs::wl_seat::SeatId;
|
||||
use crate::utils::ptr_ext::PtrExt;
|
||||
use crate::{NumCell, State};
|
||||
use i4config::_private::ipc::{InitMessage, Request, V1InitMessage};
|
||||
use i4config::_private::ipc::{InitMessage, ServerMessage, V1InitMessage};
|
||||
use i4config::_private::{bincode_ops, ConfigEntry, VERSION};
|
||||
use i4config::keyboard::ModifiedKeySym;
|
||||
use i4config::{InputDevice, Keyboard, Mouse, Seat};
|
||||
use libloading::Library;
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use i4config::{InputDevice, Keyboard, Mouse, Seat};
|
||||
use crate::config::handler::ConfigProxyHandler;
|
||||
use crate::ifs::wl_seat::{SeatId};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ConfigError {
|
||||
|
|
@ -29,7 +29,7 @@ pub struct ConfigProxy {
|
|||
|
||||
impl ConfigProxy {
|
||||
pub fn invoke_shortcut(&self, seat: SeatId, modsym: &ModifiedKeySym) {
|
||||
self.handler.send(&Request::InvokeShortcut {
|
||||
self.handler.send(&ServerMessage::InvokeShortcut {
|
||||
seat: Seat(seat.raw() as _),
|
||||
mods: modsym.mods,
|
||||
sym: modsym.sym,
|
||||
|
|
@ -37,25 +37,25 @@ impl ConfigProxy {
|
|||
}
|
||||
|
||||
pub fn new_keyboard(&self, kb: KeyboardId) {
|
||||
self.handler.send(&Request::NewInputDevice {
|
||||
self.handler.send(&ServerMessage::NewInputDevice {
|
||||
device: InputDevice::Keyboard(Keyboard(kb.raw() as _)),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn new_mouse(&self, mouse: MouseId) {
|
||||
self.handler.send(&Request::NewInputDevice {
|
||||
self.handler.send(&ServerMessage::NewInputDevice {
|
||||
device: InputDevice::Mouse(Mouse(mouse.raw() as _)),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn del_keyboard(&self, kb: KeyboardId) {
|
||||
self.handler.send(&Request::DelInputDevice {
|
||||
self.handler.send(&ServerMessage::DelInputDevice {
|
||||
device: InputDevice::Keyboard(Keyboard(kb.raw() as _)),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn del_mouse(&self, mouse: MouseId) {
|
||||
self.handler.send(&Request::DelInputDevice {
|
||||
self.handler.send(&ServerMessage::DelInputDevice {
|
||||
device: InputDevice::Mouse(Mouse(mouse.raw() as _)),
|
||||
});
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ impl ConfigProxy {
|
|||
);
|
||||
data.client_data.set(client_data);
|
||||
}
|
||||
data.send(&Request::Configure);
|
||||
data.send(&ServerMessage::Configure);
|
||||
Self { handler: data }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,3 @@
|
|||
use std::cell::{Cell};
|
||||
use std::rc::Rc;
|
||||
use bincode::error::DecodeError;
|
||||
use libloading::Library;
|
||||
use log::Level;
|
||||
use thiserror::Error;
|
||||
use i4config::_private::bincode_ops;
|
||||
use i4config::_private::ipc::{Request, Response};
|
||||
use i4config::keyboard::keymap::Keymap;
|
||||
use i4config::{Axis, Direction, InputDevice, Keyboard, LogLevel, Mouse, Seat};
|
||||
use i4config::keyboard::mods::Modifiers;
|
||||
use i4config::keyboard::syms::KeySym;
|
||||
use crate::{ErrorFmt, NumCell, State};
|
||||
use crate::backend::{KeyboardId, MouseId};
|
||||
use crate::ifs::wl_seat::WlSeatGlobal;
|
||||
use crate::state::DeviceHandlerData;
|
||||
|
|
@ -19,6 +6,19 @@ use crate::utils::copyhashmap::CopyHashMap;
|
|||
use crate::utils::debug_fn::debug_fn;
|
||||
use crate::utils::stack::Stack;
|
||||
use crate::xkbcommon::XkbKeymap;
|
||||
use crate::{ErrorFmt, NumCell, State};
|
||||
use bincode::error::DecodeError;
|
||||
use i4config::_private::bincode_ops;
|
||||
use i4config::_private::ipc::{ClientMessage, Response, ServerMessage};
|
||||
use i4config::keyboard::keymap::Keymap;
|
||||
use i4config::keyboard::mods::Modifiers;
|
||||
use i4config::keyboard::syms::KeySym;
|
||||
use i4config::{Axis, Direction, InputDevice, Keyboard, LogLevel, Mouse, Seat};
|
||||
use libloading::Library;
|
||||
use log::Level;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
pub(super) struct ConfigProxyHandler {
|
||||
pub client_data: Cell<*const u8>,
|
||||
|
|
@ -34,7 +34,7 @@ pub(super) struct ConfigProxyHandler {
|
|||
}
|
||||
|
||||
impl ConfigProxyHandler {
|
||||
pub fn send(&self, msg: &Request) {
|
||||
pub fn send(&self, msg: &ServerMessage) {
|
||||
let mut buf = self.bufs.pop().unwrap_or_default();
|
||||
buf.clear();
|
||||
bincode::encode_into_std_write(msg, &mut buf, bincode_ops()).unwrap();
|
||||
|
|
@ -48,7 +48,13 @@ impl ConfigProxyHandler {
|
|||
self.next_id.fetch_add(1)
|
||||
}
|
||||
|
||||
fn handle_log_request(&self, level: LogLevel, msg: &str, file: Option<&str>, line: Option<u32>) -> Result<(), LogError> {
|
||||
fn handle_log_request(
|
||||
&self,
|
||||
level: LogLevel,
|
||||
msg: &str,
|
||||
file: Option<&str>,
|
||||
line: Option<u32>,
|
||||
) -> Result<(), LogError> {
|
||||
let level = match level {
|
||||
LogLevel::Error => Level::Error,
|
||||
LogLevel::Warn => Level::Warn,
|
||||
|
|
@ -75,10 +81,10 @@ impl ConfigProxyHandler {
|
|||
let global_name = self.state.globals.name();
|
||||
let seat = WlSeatGlobal::new(global_name, name, &self.state);
|
||||
self.state.globals.add_global(&self.state, &seat);
|
||||
self.send(&Request::Response {
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::CreateSeat {
|
||||
seat: Seat(seat.id().raw() as _),
|
||||
}
|
||||
},
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -90,11 +96,11 @@ impl ConfigProxyHandler {
|
|||
self.keymaps.set(id, keymap);
|
||||
(id, Ok(()))
|
||||
}
|
||||
_ => {
|
||||
(Keymap::INVALID, Err(ParseKeymapError::ParsingFailed))
|
||||
}
|
||||
_ => (Keymap::INVALID, Err(ParseKeymapError::ParsingFailed)),
|
||||
};
|
||||
self.send(&Request::Response { response: Response::ParseKeymap { keymap } });
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::ParseKeymap { keymap },
|
||||
});
|
||||
res
|
||||
}
|
||||
|
||||
|
|
@ -118,16 +124,18 @@ impl ConfigProxyHandler {
|
|||
fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
let (rate, delay) = seat.get_rate();
|
||||
self.send(&Request::Response {
|
||||
response: Response::GetRepeatRate {
|
||||
rate,
|
||||
delay,
|
||||
},
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetRepeatRate { rate, delay },
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_set_repeat_rate(&self, seat: Seat, rate: i32, delay: i32) -> Result<(), SeatSetRepeatRateError> {
|
||||
fn handle_set_repeat_rate(
|
||||
&self,
|
||||
seat: Seat,
|
||||
rate: i32,
|
||||
delay: i32,
|
||||
) -> Result<(), SeatSetRepeatRateError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
if rate < 0 {
|
||||
return Err(SeatSetRepeatRateError::NegativeRate);
|
||||
|
|
@ -139,14 +147,23 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_device_handler_data(&self, device: InputDevice) -> Result<Rc<DeviceHandlerData>, CphError> {
|
||||
fn get_device_handler_data(
|
||||
&self,
|
||||
device: InputDevice,
|
||||
) -> Result<Rc<DeviceHandlerData>, CphError> {
|
||||
let data = match device {
|
||||
InputDevice::Keyboard(kb) => {
|
||||
self.state.kb_handlers.borrow_mut().get(&KeyboardId::from_raw(kb.0 as _)).map(|d| d.data.clone())
|
||||
},
|
||||
InputDevice::Mouse(mouse) => {
|
||||
self.state.mouse_handlers.borrow_mut().get(&MouseId::from_raw(mouse.0 as _)).map(|d| d.data.clone())
|
||||
}
|
||||
InputDevice::Keyboard(kb) => self
|
||||
.state
|
||||
.kb_handlers
|
||||
.borrow_mut()
|
||||
.get(&KeyboardId::from_raw(kb.0 as _))
|
||||
.map(|d| d.data.clone()),
|
||||
InputDevice::Mouse(mouse) => self
|
||||
.state
|
||||
.mouse_handlers
|
||||
.borrow_mut()
|
||||
.get(&MouseId::from_raw(mouse.0 as _))
|
||||
.map(|d| d.data.clone()),
|
||||
};
|
||||
match data {
|
||||
Some(d) => Ok(d),
|
||||
|
|
@ -184,10 +201,13 @@ impl ConfigProxyHandler {
|
|||
|
||||
fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
self.send(&Request::Response {
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetSplit {
|
||||
axis: seat.get_split().unwrap_or(ContainerSplit::Horizontal).into(),
|
||||
}
|
||||
axis: seat
|
||||
.get_split()
|
||||
.unwrap_or(ContainerSplit::Horizontal)
|
||||
.into(),
|
||||
},
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -198,14 +218,19 @@ impl ConfigProxyHandler {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_add_shortcut(&self, seat: Seat, mods: Modifiers, sym: KeySym) -> Result<(), AddShortcutError> {
|
||||
fn handle_add_shortcut(
|
||||
&self,
|
||||
seat: Seat,
|
||||
mods: Modifiers,
|
||||
sym: KeySym,
|
||||
) -> Result<(), AddShortcutError> {
|
||||
let seat = self.get_seat(seat)?;
|
||||
seat.add_shortcut(mods, sym);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_get_input_devices(&self) -> Result<(), GetInputDevicesError> {
|
||||
let mut res = vec!();
|
||||
let mut res = vec![];
|
||||
{
|
||||
let devs = self.state.kb_handlers.borrow_mut();
|
||||
for dev in devs.values() {
|
||||
|
|
@ -218,7 +243,7 @@ impl ConfigProxyHandler {
|
|||
res.push(InputDevice::Mouse(Mouse(dev.id.raw() as _)));
|
||||
}
|
||||
}
|
||||
self.send(&Request::Response {
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetInputDevices { devices: res },
|
||||
});
|
||||
Ok(())
|
||||
|
|
@ -232,12 +257,21 @@ impl ConfigProxyHandler {
|
|||
.map(|seat| Seat::from_raw(seat.id().raw() as _))
|
||||
.collect()
|
||||
};
|
||||
self.send(&Request::Response {
|
||||
self.send(&ServerMessage::Response {
|
||||
response: Response::GetSeats { seats },
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_run(&self, prog: &str, args: Vec<String>, env: Vec<(String, String)>) -> Result<(), RunError> {
|
||||
let forker = match self.state.forker.get() {
|
||||
Some(f) => f,
|
||||
_ => return Err(RunError::NoForker),
|
||||
};
|
||||
forker.spawn(prog.to_string(), args, env);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_request(&self, msg: &[u8]) {
|
||||
if let Err(e) = self.handle_request_(msg) {
|
||||
log::error!("Could not handle client request: {}", ErrorFmt(e));
|
||||
|
|
@ -245,36 +279,40 @@ impl ConfigProxyHandler {
|
|||
}
|
||||
|
||||
fn handle_request_(&self, msg: &[u8]) -> Result<(), CphError> {
|
||||
let (request, _) = match bincode::decode_from_slice::<Request, _>(msg, bincode_ops()) {
|
||||
let (request, _) = match bincode::decode_from_slice::<ClientMessage, _>(msg, bincode_ops())
|
||||
{
|
||||
Ok(msg) => msg,
|
||||
Err(e) => return Err(CphError::ParsingFailed(e)),
|
||||
};
|
||||
match request {
|
||||
Request::Log {
|
||||
ClientMessage::Log {
|
||||
level,
|
||||
msg,
|
||||
file,
|
||||
line,
|
||||
} => self.handle_log_request(level, msg, file, line)?,
|
||||
Request::CreateSeat { name } => self.handle_create_seat(name)?,
|
||||
Request::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?,
|
||||
Request::SeatSetKeymap { seat, keymap } => self.handle_set_keymap(seat, keymap)?,
|
||||
Request::SeatGetRepeatRate { seat } => self.handle_get_repeat_rate(seat)?,
|
||||
Request::SeatSetRepeatRate { seat, rate, delay } => self.handle_set_repeat_rate(seat, rate, delay)?,
|
||||
Request::SetSeat { device, seat } => self.handle_set_seat(device, seat)?,
|
||||
Request::GetSplit { seat } => self.handle_get_split(seat)?,
|
||||
Request::SetSplit { seat, axis } => self.handle_set_split(seat, axis)?,
|
||||
Request::AddShortcut {
|
||||
seat,
|
||||
mods,
|
||||
sym,
|
||||
} => self.handle_add_shortcut(seat, mods, sym)?,
|
||||
Request::RemoveShortcut { .. } => {}
|
||||
Request::Focus { seat, direction } => self.handle_focus(seat, direction)?,
|
||||
Request::Move { seat, direction } => {}
|
||||
Request::GetInputDevices => self.handle_get_input_devices()?,
|
||||
Request::GetSeats => self.handle_get_seats()?,
|
||||
m => return Err(CphError::UnexpectedMessage(format!("{:?}", m))),
|
||||
ClientMessage::CreateSeat { name } => self.handle_create_seat(name)?,
|
||||
ClientMessage::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?,
|
||||
ClientMessage::SeatSetKeymap { seat, keymap } => {
|
||||
self.handle_set_keymap(seat, keymap)?
|
||||
}
|
||||
ClientMessage::SeatGetRepeatRate { seat } => self.handle_get_repeat_rate(seat)?,
|
||||
ClientMessage::SeatSetRepeatRate { seat, rate, delay } => {
|
||||
self.handle_set_repeat_rate(seat, rate, delay)?
|
||||
}
|
||||
ClientMessage::SetSeat { device, seat } => self.handle_set_seat(device, seat)?,
|
||||
ClientMessage::GetSplit { seat } => self.handle_get_split(seat)?,
|
||||
ClientMessage::SetSplit { seat, axis } => self.handle_set_split(seat, axis)?,
|
||||
ClientMessage::AddShortcut { seat, mods, sym } => {
|
||||
self.handle_add_shortcut(seat, mods, sym)?
|
||||
}
|
||||
ClientMessage::RemoveShortcut { .. } => {}
|
||||
ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?,
|
||||
ClientMessage::Move { seat, direction } => {}
|
||||
ClientMessage::GetInputDevices => self.handle_get_input_devices()?,
|
||||
ClientMessage::GetSeats => self.handle_get_seats()?,
|
||||
ClientMessage::RemoveSeat { .. } => {}
|
||||
ClientMessage::Run { prog, args, env } => self.handle_run(prog, args, env)?,
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -308,6 +346,8 @@ enum CphError {
|
|||
SetSplitError(#[from] SetSplitError),
|
||||
#[error("Could not process a `get_split` request")]
|
||||
GetSplitError(#[from] GetSplitError),
|
||||
#[error("Could not process a `run` request")]
|
||||
RunError(#[from] RunError),
|
||||
#[error("Device {0:?} does not exist")]
|
||||
DeviceDoesNotExist(InputDevice),
|
||||
#[error("Device {0:?} does not exist")]
|
||||
|
|
@ -321,14 +361,10 @@ enum CphError {
|
|||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum LogError {
|
||||
|
||||
}
|
||||
enum LogError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum CreateSeatError {
|
||||
|
||||
}
|
||||
enum CreateSeatError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum ParseKeymapError {
|
||||
|
|
@ -351,14 +387,10 @@ enum AddShortcutError {
|
|||
efrom!(AddShortcutError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum GetInputDevicesError {
|
||||
|
||||
}
|
||||
enum GetInputDevicesError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum GetSeatsError {
|
||||
|
||||
}
|
||||
enum GetSeatsError {}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum SeatSetKeymapError {
|
||||
|
|
@ -405,3 +437,9 @@ enum GetSplitError {
|
|||
CphError(#[from] Box<CphError>),
|
||||
}
|
||||
efrom!(GetSplitError, CphError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
enum RunError {
|
||||
#[error("The ol' forker is not available")]
|
||||
NoForker,
|
||||
}
|
||||
|
|
|
|||
344
src/forker.rs
Normal file
344
src/forker.rs
Normal file
|
|
@ -0,0 +1,344 @@
|
|||
mod clone3;
|
||||
|
||||
use crate::async_engine::{AsyncFd, SpawnedFuture};
|
||||
use crate::forker::clone3::{fork_with_pidfd, Forked};
|
||||
use crate::utils::buffd::{BufFdIn, BufFdOut};
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::vec_ext::VecExt;
|
||||
use crate::{AsyncEngine, AsyncQueue, ErrorFmt, EventLoop, State, Wheel};
|
||||
use bincode::{Decode, Encode};
|
||||
use i4config::_private::bincode_ops;
|
||||
use log::Level;
|
||||
use parking_lot::Mutex;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::OsStr;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, pipe2, IntoUstr, OwnedFd, UstrPtr};
|
||||
|
||||
pub struct ForkerProxy {
|
||||
pidfd: Rc<OwnedFd>,
|
||||
pid: c::pid_t,
|
||||
socket: Rc<OwnedFd>,
|
||||
task_in: Cell<Option<SpawnedFuture<()>>>,
|
||||
task_out: Cell<Option<SpawnedFuture<()>>>,
|
||||
task_proc: Cell<Option<SpawnedFuture<()>>>,
|
||||
outgoing: AsyncQueue<ServerMessage>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ForkerError {
|
||||
#[error("Could not create a socketpair")]
|
||||
Socketpair(#[source] std::io::Error),
|
||||
#[error("Could not fork")]
|
||||
Fork(#[source] std::io::Error),
|
||||
}
|
||||
|
||||
impl ForkerProxy {
|
||||
pub fn create() -> Result<Self, ForkerError> {
|
||||
let (parent, child) = match uapi::socketpair(
|
||||
c::AF_UNIX,
|
||||
c::SOCK_STREAM | c::SOCK_CLOEXEC | c::SOCK_NONBLOCK,
|
||||
0,
|
||||
) {
|
||||
Ok(o) => o,
|
||||
Err(e) => return Err(ForkerError::Socketpair(e.into())),
|
||||
};
|
||||
match fork_with_pidfd(false)? {
|
||||
Forked::Parent { pid, pidfd } => Ok(ForkerProxy {
|
||||
pidfd: Rc::new(pidfd),
|
||||
pid,
|
||||
socket: Rc::new(parent),
|
||||
task_in: Cell::new(None),
|
||||
task_out: Cell::new(None),
|
||||
task_proc: Cell::new(None),
|
||||
outgoing: Default::default(),
|
||||
}),
|
||||
Forked::Child { .. } => Forker::handle(child),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(self: &Rc<Self>, state: &Rc<State>) {
|
||||
state.forker.set(Some(self.clone()));
|
||||
let socket = state.eng.fd(&self.socket).unwrap();
|
||||
self.task_proc.set(Some(
|
||||
state.eng.spawn(self.clone().check_process(state.clone())),
|
||||
));
|
||||
self.task_in
|
||||
.set(Some(state.eng.spawn(self.clone().incoming(socket.clone()))));
|
||||
self.task_out.set(Some(
|
||||
state
|
||||
.eng
|
||||
.spawn(self.clone().outgoing(state.clone(), socket.clone())),
|
||||
));
|
||||
}
|
||||
|
||||
pub fn setenv(&self, key: &[u8], val: &[u8]) {
|
||||
self.outgoing.push(ServerMessage::SetEnv {
|
||||
var: key.to_vec(),
|
||||
val: val.to_vec(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn spawn(&self, prog: String, args: Vec<String>, env: Vec<(String, String)>) {
|
||||
self.outgoing.push(ServerMessage::Spawn {
|
||||
prog,
|
||||
args,
|
||||
env,
|
||||
})
|
||||
}
|
||||
|
||||
async fn incoming(self: Rc<Self>, socket: AsyncFd) {
|
||||
let mut buffd = BufFdIn::new(socket);
|
||||
let mut buf = vec![];
|
||||
loop {
|
||||
let mut len = 0usize;
|
||||
if let Err(e) = buffd.read_full(&mut len).await {
|
||||
log::error!("Cannot read from the ol' forker: {}", ErrorFmt(e));
|
||||
self.task_in.take();
|
||||
return;
|
||||
}
|
||||
buf.clear();
|
||||
buf.reserve(len);
|
||||
let space = buf.split_at_spare_mut_ext().1;
|
||||
buffd.read_full(&mut space[..len]).await.unwrap();
|
||||
unsafe {
|
||||
buf.set_len(len);
|
||||
}
|
||||
let (msg, _) =
|
||||
bincode::decode_from_slice::<ForkerMessage, _>(&buf, bincode_ops()).unwrap();
|
||||
self.handle_msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_msg(&self, msg: ForkerMessage) {
|
||||
match msg {
|
||||
ForkerMessage::Log { level, msg } => self.handle_log(level, &msg),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_log(&self, level: usize, msg: &str) {
|
||||
let level = match level {
|
||||
1 => Level::Error,
|
||||
2 => Level::Warn,
|
||||
3 => Level::Info,
|
||||
4 => Level::Debug,
|
||||
5 => Level::Trace,
|
||||
_ => Level::Error,
|
||||
};
|
||||
log::log!(level, "{}", msg);
|
||||
}
|
||||
|
||||
async fn outgoing(self: Rc<Self>, state: Rc<State>, socket: AsyncFd) {
|
||||
let mut buffd = BufFdOut::new(socket);
|
||||
let mut buf = vec![];
|
||||
let mut fds = vec![];
|
||||
loop {
|
||||
let msg = self.outgoing.pop().await;
|
||||
buf.clear();
|
||||
buf.extend_from_slice(uapi::as_bytes(&0usize));
|
||||
let len = bincode::encode_into_std_write(&msg, &mut buf, bincode_ops()).unwrap();
|
||||
let _ = (&mut buf[..]).write_all(uapi::as_bytes(&len));
|
||||
if let Err(e) = buffd.flush2(&buf, &mut fds).await {
|
||||
log::error!("Could not write to the ol' forker: {}", ErrorFmt(e));
|
||||
state.forker.set(None);
|
||||
self.task_out.take();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
log::error!("The ol' forker died. Cannot spawn further processes.");
|
||||
state.forker.set(None);
|
||||
self.task_out.take();
|
||||
self.task_proc.take();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode)]
|
||||
enum ServerMessage {
|
||||
SetEnv { var: Vec<u8>, val: Vec<u8> },
|
||||
Spawn { prog: String, args: Vec<String>, env: Vec<(String, String)> },
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode)]
|
||||
enum ForkerMessage {
|
||||
Log { level: usize, msg: String },
|
||||
}
|
||||
|
||||
struct Forker {
|
||||
socket: AsyncFd,
|
||||
ae: Rc<AsyncEngine>,
|
||||
outgoing: AsyncQueue<ForkerMessage>,
|
||||
pending_spawns: CopyHashMap<c::pid_t, SpawnedFuture<()>>,
|
||||
}
|
||||
|
||||
impl Forker {
|
||||
fn handle(mut socket: OwnedFd) -> ! {
|
||||
std::env::set_var("XDG_SESSION_TYPE", "wayland");
|
||||
std::env::remove_var("DISPLAY");
|
||||
std::env::remove_var("WAYLAND_DISPLAY");
|
||||
setup_deathsig();
|
||||
reset_signals();
|
||||
socket = setup_fds(socket);
|
||||
std::panic::set_hook({
|
||||
let socket = Mutex::new(uapi::fcntl_dupfd_cloexec(socket.raw(), 0).unwrap());
|
||||
Box::new(move |pi| {
|
||||
let msg = ForkerMessage::Log {
|
||||
level: log::Level::Error as _,
|
||||
msg: format!("The ol' forker panicked: {}", pi),
|
||||
};
|
||||
let msg = bincode::encode_to_vec(&msg, bincode_ops()).unwrap();
|
||||
let _ = socket.lock().write_all(&msg);
|
||||
})
|
||||
});
|
||||
let el = EventLoop::new().unwrap();
|
||||
let wheel = Wheel::install(&el).unwrap();
|
||||
let ae = AsyncEngine::install(&el, &wheel).unwrap();
|
||||
let forker = Rc::new(Forker {
|
||||
socket: ae.fd(&Rc::new(socket)).unwrap(),
|
||||
ae: ae.clone(),
|
||||
outgoing: Default::default(),
|
||||
pending_spawns: Default::default(),
|
||||
});
|
||||
let _f1 = ae.spawn(forker.clone().incoming());
|
||||
let _f2 = ae.spawn(forker.clone().outgoing());
|
||||
let _ = el.run();
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
async fn outgoing(self: Rc<Self>) {
|
||||
let mut buffd = BufFdOut::new(self.socket.clone());
|
||||
let mut buf = vec![];
|
||||
let mut fds = vec![];
|
||||
loop {
|
||||
let msg = self.outgoing.pop().await;
|
||||
buf.clear();
|
||||
buf.extend_from_slice(uapi::as_bytes(&0usize));
|
||||
let len = bincode::encode_into_std_write(&msg, &mut buf, bincode_ops()).unwrap();
|
||||
let _ = (&mut buf[..]).write_all(uapi::as_bytes(&len));
|
||||
buffd.flush2(&buf, &mut fds).await.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
async fn incoming(self: Rc<Self>) {
|
||||
let mut buffd = BufFdIn::new(self.socket.clone());
|
||||
let mut buf = vec![];
|
||||
loop {
|
||||
let mut len = 0usize;
|
||||
buffd.read_full(&mut len).await.unwrap();
|
||||
buf.clear();
|
||||
buf.reserve(len);
|
||||
let space = buf.split_at_spare_mut_ext().1;
|
||||
buffd.read_full(&mut space[..len]).await.unwrap();
|
||||
unsafe {
|
||||
buf.set_len(len);
|
||||
}
|
||||
let (msg, _) =
|
||||
bincode::decode_from_slice::<ServerMessage, _>(&buf, bincode_ops()).unwrap();
|
||||
self.handle_msg(msg);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_msg(self: &Rc<Self>, msg: ServerMessage) {
|
||||
match msg {
|
||||
ServerMessage::SetEnv { var, val } => self.handle_set_env(&var, &val),
|
||||
ServerMessage::Spawn { prog, args, env } => self.handle_spawn(prog, args, env),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_set_env(self: &Rc<Self>, var: &[u8], val: &[u8]) {
|
||||
std::env::set_var(OsStr::from_bytes(var), OsStr::from_bytes(val));
|
||||
}
|
||||
|
||||
fn handle_spawn(self: &Rc<Self>, prog: String, args: Vec<String>, env: Vec<(String, String)>) {
|
||||
let (mut read, mut write) = pipe2(c::O_CLOEXEC).unwrap();
|
||||
let res = match fork_with_pidfd(false) {
|
||||
Ok(o) => o,
|
||||
Err(e) => {
|
||||
self.outgoing.push(ForkerMessage::Log {
|
||||
level: log::Level::Error as usize,
|
||||
msg: ErrorFmt(e).to_string(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
match res {
|
||||
Forked::Parent { pidfd, pid } => {
|
||||
drop(write);
|
||||
let slf = self.clone();
|
||||
let spawn = self.ae.spawn(async move {
|
||||
let pidfd = slf.ae.fd(&Rc::new(pidfd)).unwrap();
|
||||
let _ = pidfd.readable().await;
|
||||
let mut s = String::new();
|
||||
let _ = read.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);
|
||||
});
|
||||
self.pending_spawns.set(pid, spawn);
|
||||
}
|
||||
Forked::Child { .. } => {
|
||||
unsafe {
|
||||
c::signal(c::SIGCHLD, c::SIG_DFL);
|
||||
}
|
||||
for (key, val) in env {
|
||||
std::env::set_var(&key, &val);
|
||||
}
|
||||
let prog = prog.into_ustr();
|
||||
let mut argsnt = UstrPtr::new();
|
||||
argsnt.push(&prog);
|
||||
for arg in args {
|
||||
argsnt.push(arg);
|
||||
}
|
||||
if let Err(e) = uapi::execvp(&prog, &argsnt) {
|
||||
let _ = write.write_all(std::io::Error::from(e).to_string().as_bytes());
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_fds(mut socket: OwnedFd) -> OwnedFd {
|
||||
if socket.raw() != 0 {
|
||||
uapi::dup3(socket.unwrap(), 0, 0).unwrap();
|
||||
socket = OwnedFd::new(0);
|
||||
}
|
||||
uapi::close_range(1, c::c_uint::MAX, 0).unwrap();
|
||||
uapi::dup3(socket.raw(), 3, c::O_CLOEXEC).unwrap();
|
||||
socket = OwnedFd::new(3);
|
||||
let fd = uapi::open("/dev/null", c::O_RDWR, 0).unwrap().unwrap();
|
||||
assert!(fd == 0);
|
||||
uapi::dup2(0, 1).unwrap();
|
||||
uapi::dup2(0, 2).unwrap();
|
||||
socket
|
||||
}
|
||||
|
||||
fn reset_signals() {
|
||||
const NSIG: c::c_int = 64;
|
||||
unsafe {
|
||||
for sig in 1..=NSIG {
|
||||
c::signal(sig, c::SIG_DFL);
|
||||
}
|
||||
c::signal(c::SIGCHLD, c::SIG_IGN);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_deathsig() {
|
||||
unsafe {
|
||||
let res = c::prctl(c::PR_SET_PDEATHSIG, c::SIGKILL as c::c_ulong);
|
||||
uapi::map_err!(res).unwrap();
|
||||
}
|
||||
}
|
||||
56
src/forker/clone3.rs
Normal file
56
src/forker/clone3.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use crate::forker::ForkerError;
|
||||
use std::mem;
|
||||
use uapi::{c, OwnedFd};
|
||||
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[allow(non_camel_case_types, dead_code)]
|
||||
struct clone_args {
|
||||
flags: u64,
|
||||
pidfd: u64,
|
||||
child_tid: u64,
|
||||
parent_tid: u64,
|
||||
exit_signal: u64,
|
||||
stack: u64,
|
||||
stack_size: u64,
|
||||
tls: u64,
|
||||
set_tid: u64,
|
||||
set_tid_size: u64,
|
||||
cgroup: u64,
|
||||
}
|
||||
|
||||
pub enum Forked {
|
||||
Parent { pid: c::pid_t, pidfd: OwnedFd },
|
||||
Child { pidfd: Option<OwnedFd> },
|
||||
}
|
||||
|
||||
pub fn fork_with_pidfd(pidfd_for_child: bool) -> Result<Forked, ForkerError> {
|
||||
let mut pidfd: c::c_int = 0;
|
||||
let mut args = clone_args {
|
||||
flags: c::CLONE_PIDFD as u64,
|
||||
pidfd: (&mut pidfd as *mut c::c_int) as _,
|
||||
..Default::default()
|
||||
};
|
||||
let mut child_pidfd = None;
|
||||
if pidfd_for_child {
|
||||
child_pidfd = Some(uapi::pidfd_open(uapi::getpid(), 0).unwrap());
|
||||
}
|
||||
unsafe {
|
||||
let pid = c::syscall(
|
||||
c::SYS_clone3,
|
||||
&mut args as *const _ as usize,
|
||||
mem::size_of::<clone_args>(),
|
||||
);
|
||||
if let Err(e) = uapi::map_err!(pid) {
|
||||
return Err(ForkerError::Fork(e.into()));
|
||||
}
|
||||
let res = if pid == 0 {
|
||||
Forked::Child { pidfd: child_pidfd }
|
||||
} else {
|
||||
Forked::Parent {
|
||||
pid: pid as _,
|
||||
pidfd: OwnedFd::new(pidfd),
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ pub mod wl_keyboard;
|
|||
pub mod wl_pointer;
|
||||
pub mod wl_touch;
|
||||
|
||||
use crate::async_engine::SpawnedFuture;
|
||||
use crate::client::{Client, ClientError, ClientId};
|
||||
use crate::cursor::{Cursor, KnownCursor};
|
||||
use crate::fixed::Fixed;
|
||||
|
|
@ -38,6 +39,7 @@ use crate::{ErrorFmt, NumCell, State};
|
|||
use ahash::{AHashMap, AHashSet};
|
||||
pub use event_handling::NodeSeatState;
|
||||
use i4config::keyboard::mods::Modifiers;
|
||||
use i4config::Direction;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::mem;
|
||||
|
|
@ -45,8 +47,6 @@ use std::ops::DerefMut;
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, Errno, OwnedFd};
|
||||
use i4config::{ Direction};
|
||||
use crate::async_engine::SpawnedFuture;
|
||||
|
||||
const POINTER: u32 = 1;
|
||||
const KEYBOARD: u32 = 2;
|
||||
|
|
@ -119,11 +119,7 @@ pub struct WlSeatGlobal {
|
|||
}
|
||||
|
||||
impl WlSeatGlobal {
|
||||
pub fn new(
|
||||
name: GlobalName,
|
||||
seat_name: &str,
|
||||
state: &Rc<State>,
|
||||
) -> Rc<Self> {
|
||||
pub fn new(name: GlobalName, seat_name: &str, state: &Rc<State>) -> Rc<Self> {
|
||||
let slf = Rc::new(Self {
|
||||
id: state.seat_ids.next(),
|
||||
name,
|
||||
|
|
@ -167,7 +163,8 @@ impl WlSeatGlobal {
|
|||
}
|
||||
|
||||
pub fn mark_last_active(self: &Rc<Self>) {
|
||||
self.queue_link.set(Some(self.state.seat_queue.add_last(self.clone())));
|
||||
self.queue_link
|
||||
.set(Some(self.state.seat_queue.add_last(self.clone())));
|
||||
}
|
||||
|
||||
pub fn set_keymap(&self, keymap: &Rc<XkbKeymap>) {
|
||||
|
|
@ -464,7 +461,11 @@ impl WlSeat {
|
|||
self.client.add_client_obj(&p)?;
|
||||
self.keyboards.set(req.id, p.clone());
|
||||
let keymap = self.global.kb_map.get();
|
||||
p.send_keymap(wl_keyboard::XKB_V1, self.keymap_fd(&keymap)?, keymap.map_len as _);
|
||||
p.send_keymap(
|
||||
wl_keyboard::XKB_V1,
|
||||
self.keymap_fd(&keymap)?,
|
||||
keymap.map_len as _,
|
||||
);
|
||||
if self.version >= REPEAT_INFO_SINCE {
|
||||
let (rate, delay) = self.global.repeat_rate.get();
|
||||
p.send_repeat_info(rate, delay);
|
||||
|
|
@ -484,12 +485,7 @@ impl WlSeat {
|
|||
let mut pos = 0;
|
||||
while pos < target {
|
||||
let rem = target - pos;
|
||||
let res = uapi::sendfile(
|
||||
fd.raw(),
|
||||
keymap.map.raw(),
|
||||
Some(&mut pos),
|
||||
rem as usize,
|
||||
);
|
||||
let res = uapi::sendfile(fd.raw(), keymap.map.raw(), Some(&mut pos), rem as usize);
|
||||
match res {
|
||||
Ok(_) | Err(Errno(c::EINTR)) => {}
|
||||
Err(e) => return Err(WlKeyboardError::KeymapCopy(e.into())),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::backend::{KeyboardEvent, KeyState, MouseEvent, OutputId, ScrollAxis};
|
||||
use crate::backend::{KeyState, KeyboardEvent, MouseEvent, OutputId, ScrollAxis};
|
||||
use crate::client::{Client, ClientId};
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::ipc;
|
||||
|
|
@ -6,7 +6,7 @@ use crate::ifs::ipc::wl_data_device::WlDataDevice;
|
|||
use crate::ifs::ipc::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
|
||||
use crate::ifs::wl_seat::wl_keyboard::WlKeyboard;
|
||||
use crate::ifs::wl_seat::wl_pointer::{WlPointer, POINTER_FRAME_SINCE_VERSION};
|
||||
use crate::ifs::wl_seat::{wl_keyboard, wl_pointer, Dnd, WlSeat, WlSeatGlobal, SeatId};
|
||||
use crate::ifs::wl_seat::{wl_keyboard, wl_pointer, Dnd, SeatId, WlSeat, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopup;
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use crate::wire::wl_keyboard::*;
|
|||
use crate::wire::{WlKeyboardId, WlSurfaceId};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{OwnedFd};
|
||||
use uapi::OwnedFd;
|
||||
|
||||
pub const REPEAT_INFO_SINCE: u32 = 4;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ pub mod cursor;
|
|||
pub mod wl_subsurface;
|
||||
pub mod xdg_surface;
|
||||
|
||||
use crate::backend::{KeyState, ScrollAxis};
|
||||
use crate::client::{Client, ClientError, RequestParser};
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_buffer::WlBuffer;
|
||||
|
|
@ -25,14 +26,13 @@ use crate::wire::{WlOutputId, WlSurfaceId};
|
|||
use crate::xkbcommon::ModifierState;
|
||||
use crate::NumCell;
|
||||
use ahash::AHashMap;
|
||||
use i4config::Direction;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use i4config::{ Direction};
|
||||
use crate::backend::{KeyState, ScrollAxis};
|
||||
|
||||
#[allow(dead_code)]
|
||||
const INVALID_SCALE: u32 = 0;
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@ use crate::utils::smallmap::SmallMap;
|
|||
use crate::wire::xdg_surface::*;
|
||||
use crate::wire::{WlSurfaceId, XdgPopupId, XdgSurfaceId};
|
||||
use crate::NumCell;
|
||||
use i4config::Direction;
|
||||
use std::cell::Cell;
|
||||
use std::fmt::Debug;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use i4config::{Direction};
|
||||
|
||||
#[allow(dead_code)]
|
||||
const NOT_CONSTRUCTED: u32 = 1;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use crate::wire::xdg_toplevel::*;
|
|||
use crate::wire::XdgToplevelId;
|
||||
use crate::{bugs, NumCell};
|
||||
use ahash::{AHashMap, AHashSet};
|
||||
use i4config::Direction;
|
||||
use num_derive::FromPrimitive;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
|
@ -26,7 +27,6 @@ use std::mem;
|
|||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use i4config::{Direction};
|
||||
|
||||
#[derive(Copy, Clone, Debug, FromPrimitive)]
|
||||
pub enum ResizeEdge {
|
||||
|
|
|
|||
12
src/main.rs
12
src/main.rs
|
|
@ -13,6 +13,7 @@ use crate::backends::xorg::{XorgBackend, XorgBackendError};
|
|||
use crate::client::Clients;
|
||||
use crate::clientmem::ClientMemError;
|
||||
use crate::event_loop::EventLoopError;
|
||||
use crate::forker::ForkerError;
|
||||
use crate::globals::Globals;
|
||||
use crate::ifs::wl_compositor::WlCompositorGlobal;
|
||||
use crate::ifs::wl_shm::WlShmGlobal;
|
||||
|
|
@ -29,6 +30,7 @@ use crate::utils::errorfmt::ErrorFmt;
|
|||
use crate::utils::numcell::NumCell;
|
||||
use crate::utils::queue::AsyncQueue;
|
||||
use crate::wheel::WheelError;
|
||||
use crate::xkbcommon::XkbContext;
|
||||
use acceptor::Acceptor;
|
||||
use async_engine::AsyncEngine;
|
||||
use event_loop::EventLoop;
|
||||
|
|
@ -38,7 +40,6 @@ use std::ops::Deref;
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use wheel::Wheel;
|
||||
use crate::xkbcommon::XkbContext;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
|
@ -56,6 +57,7 @@ mod cursor;
|
|||
mod drm;
|
||||
mod event_loop;
|
||||
mod fixed;
|
||||
mod forker;
|
||||
mod format;
|
||||
mod globals;
|
||||
mod ifs;
|
||||
|
|
@ -104,9 +106,12 @@ enum MainError {
|
|||
XorgBackendError(#[from] XorgBackendError),
|
||||
#[error("The render backend caused an error")]
|
||||
RenderError(#[from] RenderError),
|
||||
#[error("The ol' forker caused an error")]
|
||||
ForkerError(#[from] ForkerError),
|
||||
}
|
||||
|
||||
fn main_() -> Result<(), MainError> {
|
||||
let forker = Rc::new(forker::ForkerProxy::create()?);
|
||||
leaks::init();
|
||||
render::init()?;
|
||||
clientmem::init()?;
|
||||
|
|
@ -119,6 +124,7 @@ fn main_() -> Result<(), MainError> {
|
|||
let node_ids = NodeIds::default();
|
||||
let state = Rc::new(State {
|
||||
xkb_ctx,
|
||||
forker: Default::default(),
|
||||
default_keymap: xkb_keymap,
|
||||
eng: engine.clone(),
|
||||
el: el.clone(),
|
||||
|
|
@ -145,11 +151,13 @@ fn main_() -> Result<(), MainError> {
|
|||
mouse_ids: Default::default(),
|
||||
kb_handlers: Default::default(),
|
||||
});
|
||||
forker.install(&state);
|
||||
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()));
|
||||
let _slow_client_handler = engine.spawn(tasks::handle_slow_clients(state.clone()));
|
||||
Acceptor::install(&state)?;
|
||||
let socket_path = Acceptor::install(&state)?;
|
||||
forker.setenv(b"WAYLAND_DISPLAY", socket_path.as_bytes());
|
||||
let _backend = XorgBackend::new(&state)?;
|
||||
el.run()?;
|
||||
state.clients.clear();
|
||||
|
|
|
|||
12
src/state.rs
12
src/state.rs
|
|
@ -1,9 +1,12 @@
|
|||
use crate::async_engine::{AsyncEngine, SpawnedFuture};
|
||||
use crate::backend::{BackendEvent, KeyboardId, KeyboardIds, MouseId, MouseIds, OutputId, OutputIds};
|
||||
use crate::backend::{
|
||||
BackendEvent, KeyboardId, KeyboardIds, MouseId, MouseIds, OutputId, OutputIds,
|
||||
};
|
||||
use crate::client::{Client, Clients};
|
||||
use crate::config::ConfigProxy;
|
||||
use crate::cursor::ServerCursors;
|
||||
use crate::event_loop::EventLoop;
|
||||
use crate::forker::ForkerProxy;
|
||||
use crate::globals::{Globals, GlobalsError, WaylandGlobal};
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_seat::{SeatIds, WlSeatGlobal};
|
||||
|
|
@ -15,14 +18,15 @@ use crate::utils::copyhashmap::CopyHashMap;
|
|||
use crate::utils::linkedlist::LinkedList;
|
||||
use crate::utils::numcell::NumCell;
|
||||
use crate::utils::queue::AsyncQueue;
|
||||
use crate::xkbcommon::XkbKeymap;
|
||||
use crate::{ErrorFmt, Wheel, XkbContext};
|
||||
use ahash::AHashMap;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::rc::Rc;
|
||||
use crate::xkbcommon::XkbKeymap;
|
||||
|
||||
pub struct State {
|
||||
pub xkb_ctx: XkbContext,
|
||||
pub forker: CloneCell<Option<Rc<ForkerProxy>>>,
|
||||
pub default_keymap: Rc<XkbKeymap>,
|
||||
pub eng: Rc<AsyncEngine>,
|
||||
pub el: Rc<EventLoop>,
|
||||
|
|
@ -53,13 +57,13 @@ pub struct State {
|
|||
pub struct MouseData {
|
||||
pub handler: SpawnedFuture<()>,
|
||||
pub id: MouseId,
|
||||
pub data: Rc<DeviceHandlerData>
|
||||
pub data: Rc<DeviceHandlerData>,
|
||||
}
|
||||
|
||||
pub struct KeyboardData {
|
||||
pub handler: SpawnedFuture<()>,
|
||||
pub id: KeyboardId,
|
||||
pub data: Rc<DeviceHandlerData>
|
||||
pub data: Rc<DeviceHandlerData>,
|
||||
}
|
||||
|
||||
pub struct DeviceHandlerData {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use crate::backend::{BackendEvent, Output};
|
||||
use crate::tasks::device;
|
||||
use crate::tasks::output::OutputHandler;
|
||||
use crate::State;
|
||||
use std::rc::Rc;
|
||||
use crate::tasks::device;
|
||||
|
||||
pub struct BackendEventHandler {
|
||||
pub state: Rc<State>,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use crate::async_engine::SpawnedFuture;
|
||||
use crate::backend::{Keyboard, KeyboardEvent, Mouse, MouseEvent};
|
||||
use crate::config::ConfigProxy;
|
||||
use crate::ifs::wl_seat::WlSeatGlobal;
|
||||
use crate::state::{DeviceHandlerData, KeyboardData, MouseData};
|
||||
use crate::utils::asyncevent::AsyncEvent;
|
||||
use crate::State;
|
||||
use std::rc::Rc;
|
||||
use crate::async_engine::SpawnedFuture;
|
||||
use crate::config::ConfigProxy;
|
||||
use crate::state::{DeviceHandlerData, KeyboardData, MouseData};
|
||||
|
||||
pub trait DeviceApi: 'static {
|
||||
type Event;
|
||||
|
|
@ -40,11 +40,14 @@ impl DeviceApi for dyn Keyboard {
|
|||
}
|
||||
|
||||
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
|
||||
state.kb_handlers.borrow_mut().insert(self.id(), KeyboardData {
|
||||
handler,
|
||||
id: self.id(),
|
||||
data,
|
||||
});
|
||||
state.kb_handlers.borrow_mut().insert(
|
||||
self.id(),
|
||||
KeyboardData {
|
||||
handler,
|
||||
id: self.id(),
|
||||
data,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn remove(&self, state: &State) {
|
||||
|
|
@ -80,11 +83,14 @@ impl DeviceApi for dyn Mouse {
|
|||
}
|
||||
|
||||
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
|
||||
state.mouse_handlers.borrow_mut().insert(self.id(), MouseData {
|
||||
handler,
|
||||
id: self.id(),
|
||||
data,
|
||||
});
|
||||
state.mouse_handlers.borrow_mut().insert(
|
||||
self.id(),
|
||||
MouseData {
|
||||
handler,
|
||||
id: self.id(),
|
||||
data,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn remove(&self, state: &State) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
mod backend;
|
||||
mod device;
|
||||
mod output;
|
||||
mod slow_clients;
|
||||
mod device;
|
||||
|
||||
use crate::tasks::backend::BackendEventHandler;
|
||||
use crate::tasks::slow_clients::SlowClientHandler;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::backend::{KeyState};
|
||||
use crate::backend::KeyState;
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal, BTN_LEFT, SeatId};
|
||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT};
|
||||
use crate::rect::Rect;
|
||||
use crate::render::Renderer;
|
||||
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
|
||||
|
|
@ -9,12 +9,12 @@ use crate::utils::clonecell::CloneCell;
|
|||
use crate::utils::linkedlist::{LinkedList, LinkedNode, NodeRef};
|
||||
use crate::{NumCell, State};
|
||||
use ahash::AHashMap;
|
||||
use i4config::{Axis, Direction};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::rc::Rc;
|
||||
use i4config::{Axis, Direction};
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
|
|
@ -462,7 +462,12 @@ impl Node for ContainerNode {
|
|||
}
|
||||
}
|
||||
|
||||
fn move_focus_from_child(&self, seat: &Rc<WlSeatGlobal>, child: &dyn Node, direction: Direction) {
|
||||
fn move_focus_from_child(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
child: &dyn Node,
|
||||
direction: Direction,
|
||||
) {
|
||||
let children = self.child_nodes.borrow_mut();
|
||||
let child = match children.get(&child.id()) {
|
||||
Some(c) => c,
|
||||
|
|
@ -473,7 +478,9 @@ impl Node for ContainerNode {
|
|||
ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down),
|
||||
};
|
||||
if !in_line {
|
||||
self.parent.get().move_focus_from_child(seat, self, direction);
|
||||
self.parent
|
||||
.get()
|
||||
.move_focus_from_child(seat, self, direction);
|
||||
return;
|
||||
}
|
||||
let prev = match direction {
|
||||
|
|
@ -484,12 +491,14 @@ impl Node for ContainerNode {
|
|||
};
|
||||
let sibling = match prev {
|
||||
true => child.prev(),
|
||||
false => child.next()
|
||||
false => child.next(),
|
||||
};
|
||||
let sibling = match sibling {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
self.parent.get().move_focus_from_child(seat, self, direction);
|
||||
self.parent
|
||||
.get()
|
||||
.move_focus_from_child(seat, self, direction);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ use crate::utils::linkedlist::{LinkedList, LinkedNode};
|
|||
use crate::xkbcommon::ModifierState;
|
||||
use crate::NumCell;
|
||||
pub use container::*;
|
||||
use i4config::Direction;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use i4config::{Direction};
|
||||
pub use workspace::*;
|
||||
|
||||
mod container;
|
||||
|
|
@ -93,7 +93,12 @@ pub trait Node {
|
|||
let _ = direction;
|
||||
}
|
||||
|
||||
fn move_focus_from_child(&self, seat: &Rc<WlSeatGlobal>, child: &dyn Node, direction: Direction) {
|
||||
fn move_focus_from_child(
|
||||
&self,
|
||||
seat: &Rc<WlSeatGlobal>,
|
||||
child: &dyn Node,
|
||||
direction: Direction,
|
||||
) {
|
||||
let _ = seat;
|
||||
let _ = direction;
|
||||
let _ = child;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ impl BufFdOut {
|
|||
) -> Result<(), BufFdError> {
|
||||
while buf.read_pos < buf.write_pos {
|
||||
if self.flush_sync(buf)? {
|
||||
self.fd.writable().await?;
|
||||
if timeout.is_none() {
|
||||
*timeout = Some(self.fd.eng().timeout(5000)?.fuse());
|
||||
}
|
||||
|
|
@ -157,6 +156,60 @@ impl BufFdOut {
|
|||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub async fn flush2(&mut self, buf: &[u8], fds: &mut Vec<OwnedFd>) -> Result<(), BufFdError> {
|
||||
let mut read_pos = 0;
|
||||
while read_pos < buf.len() {
|
||||
if self.flush_sync2(&mut read_pos, buf, fds)? {
|
||||
self.fd.writable().await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn flush_sync2(
|
||||
&mut self,
|
||||
read_pos: &mut usize,
|
||||
buf: &[u8],
|
||||
fds: &mut Vec<OwnedFd>,
|
||||
) -> Result<bool, BufFdError> {
|
||||
let mut cmsg_len = 0;
|
||||
let mut fds_opt = None;
|
||||
if fds.len() > 0 {
|
||||
self.fd_ids.clear();
|
||||
self.fd_ids.extend(fds.iter().map(|f| f.raw()));
|
||||
let hdr = c::cmsghdr {
|
||||
cmsg_len: 0,
|
||||
cmsg_level: c::SOL_SOCKET,
|
||||
cmsg_type: c::SCM_RIGHTS,
|
||||
};
|
||||
let mut cmsg_buf = &mut self.cmsg_buf[..];
|
||||
cmsg_len = uapi::cmsg_write(&mut cmsg_buf, hdr, &self.fd_ids[..]).unwrap();
|
||||
fds_opt = Some(fds);
|
||||
}
|
||||
while *read_pos < buf.len() {
|
||||
let buf = &buf[*read_pos..];
|
||||
let hdr = uapi::Msghdr {
|
||||
iov: slice::from_ref(&buf),
|
||||
control: Some(&self.cmsg_buf[..cmsg_len]),
|
||||
name: uapi::sockaddr_none_ref(),
|
||||
};
|
||||
let bytes_sent =
|
||||
match uapi::sendmsg(self.fd.raw(), &hdr, c::MSG_DONTWAIT | c::MSG_NOSIGNAL) {
|
||||
Ok(b) => {
|
||||
if let Some(fds) = fds_opt.take() {
|
||||
fds.clear();
|
||||
}
|
||||
b
|
||||
}
|
||||
Err(Errno(c::EAGAIN)) => return Ok(true),
|
||||
Err(Errno(c::ECONNRESET)) => return Err(BufFdError::Closed),
|
||||
Err(e) => return Err(BufFdError::Io(e.into())),
|
||||
};
|
||||
*read_pos += bytes_sent;
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OutBuffer {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl<K, V> Default for CopyHashMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash, V: Clone> CopyHashMap<K, V> {
|
||||
impl<K: Eq + Hash, V> CopyHashMap<K, V> {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
|
@ -24,7 +24,10 @@ impl<K: Eq + Hash, V: Clone> CopyHashMap<K, V> {
|
|||
self.map.borrow_mut().insert(k, v);
|
||||
}
|
||||
|
||||
pub fn get(&self, k: &K) -> Option<V> {
|
||||
pub fn get(&self, k: &K) -> Option<V>
|
||||
where
|
||||
V: Clone,
|
||||
{
|
||||
self.map.borrow_mut().get(k).cloned()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -219,7 +219,8 @@ impl<T> NodeRef<T> {
|
|||
}
|
||||
|
||||
fn peer<F>(&self, peer: F) -> Option<NodeRef<T>>
|
||||
where F: FnOnce(&NodeData<T>) -> &Cell<NonNull<NodeData<T>>>,
|
||||
where
|
||||
F: FnOnce(&NodeData<T>) -> &Cell<NonNull<NodeData<T>>>,
|
||||
{
|
||||
unsafe {
|
||||
let data = self.data.as_ref();
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@ pub mod numcell;
|
|||
pub mod ptr_ext;
|
||||
pub mod queue;
|
||||
pub mod smallmap;
|
||||
pub mod vec_ext;
|
||||
pub mod stack;
|
||||
pub mod vec_ext;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ pub struct AsyncQueue<T> {
|
|||
waiters: RefCell<Vec<Waker>>,
|
||||
}
|
||||
|
||||
impl<T> Default for AsyncQueue<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsyncQueue<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::cell::UnsafeCell;
|
||||
use crate::utils::ptr_ext::MutPtrExt;
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
pub struct Stack<T> {
|
||||
vec: UnsafeCell<Vec<T>>,
|
||||
|
|
@ -21,8 +21,6 @@ impl<T> Stack<T> {
|
|||
}
|
||||
|
||||
pub fn pop(&self) -> Option<T> {
|
||||
unsafe {
|
||||
self.vec.get().deref_mut().pop()
|
||||
}
|
||||
unsafe { self.vec.get().deref_mut().pop() }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,8 +124,7 @@ impl XkbContext {
|
|||
}
|
||||
|
||||
fn raw_to_map(raw: *mut xkb_keymap) -> Result<Rc<XkbKeymap>, XkbCommonError> {
|
||||
let res =
|
||||
unsafe { xkb_keymap_get_as_string(raw, XKB_KEYMAP_FORMAT_TEXT_V1.raw() as _) };
|
||||
let res = unsafe { xkb_keymap_get_as_string(raw, XKB_KEYMAP_FORMAT_TEXT_V1.raw() as _) };
|
||||
if res.is_null() {
|
||||
unsafe {
|
||||
xkb_keymap_unref(raw);
|
||||
|
|
@ -143,7 +142,8 @@ impl XkbContext {
|
|||
uapi::fcntl_add_seals(
|
||||
memfd.raw(),
|
||||
c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
Ok(Rc::new(XkbKeymap {
|
||||
keymap: raw,
|
||||
map: Rc::new(memfd),
|
||||
|
|
@ -153,7 +153,13 @@ impl XkbContext {
|
|||
|
||||
pub fn keymap_from_str(&self, s: &str) -> Result<Rc<XkbKeymap>, XkbCommonError> {
|
||||
unsafe {
|
||||
let keymap = xkb_keymap_new_from_buffer(self.context, s.as_bytes().as_ptr(), s.len(), XKB_KEYMAP_FORMAT_TEXT_V1.raw(), 0);
|
||||
let keymap = xkb_keymap_new_from_buffer(
|
||||
self.context,
|
||||
s.as_bytes().as_ptr(),
|
||||
s.len(),
|
||||
XKB_KEYMAP_FORMAT_TEXT_V1.raw(),
|
||||
0,
|
||||
);
|
||||
if keymap.is_null() {
|
||||
return Err(XkbCommonError::KeymapFromBuffer);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue