1
0
Fork 0
forked from wry/wry

autocommit 2022-02-15 22:53:12 CET

This commit is contained in:
Julian Orth 2022-02-15 22:53:12 +01:00
parent 290225190a
commit cacd49d15a
33 changed files with 884 additions and 220 deletions

99
Cargo.lock generated
View file

@ -320,6 +320,7 @@ dependencies = [
"num-derive", "num-derive",
"num-traits", "num-traits",
"once_cell", "once_cell",
"parking_lot",
"rand", "rand",
"renderdoc", "renderdoc",
"repc", "repc",
@ -366,6 +367,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "lock_api"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.14" version = "0.4.14"
@ -436,6 +446,29 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
[[package]]
name = "parking_lot"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.8" version = "0.2.8"
@ -512,6 +545,15 @@ dependencies = [
"rand_core", "rand_core",
] ]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.5.4" version = "1.5.4"
@ -577,6 +619,12 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.5" version = "0.4.5"
@ -642,9 +690,9 @@ dependencies = [
[[package]] [[package]]
name = "uapi" name = "uapi"
version = "0.2.4" version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c72d8c426678584cd311d3b8e9538778fd7d024de641b440850e458d50621fd" checksum = "ea2a608d845b3ddcf7769250f94124d29e346c0f8fdb935756c6b758ac5d9b59"
dependencies = [ dependencies = [
"cc", "cc",
"cfg-if 0.1.10", "cfg-if 0.1.10",
@ -654,9 +702,9 @@ dependencies = [
[[package]] [[package]]
name = "uapi-proc" name = "uapi-proc"
version = "0.0.3" version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16121f38f4afe754d6726ed388f1fb3e669c4594a3d29e1bdab1e795a450921f" checksum = "54de46f980cea7b2ae8d8f7f9f1c35cf7062c68343e99345ef73758f8e60975a"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
@ -721,6 +769,49 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
[[package]] [[package]]
name = "wio" name = "wio"
version = "0.2.2" version = "0.2.2"

View file

@ -15,7 +15,8 @@ panic = "abort"
codegen-units = 1 codegen-units = 1
[dependencies] [dependencies]
uapi = "0.2.4" uapi = "0.2.7"
parking_lot = "0.12.0"
thiserror = "1.0.30" thiserror = "1.0.30"
ahash = "0.7.6" ahash = "0.7.6"
log = "0.4.14" log = "0.4.14"

View file

@ -1,7 +1,7 @@
use i4config::keyboard::mods::{ALT, CTRL, Modifiers, SHIFT}; use i4config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT};
use i4config::keyboard::syms::{SYM_Super_L, SYM_h, SYM_j, SYM_k, SYM_l, SYM_plus, SYM_minus, SYM_r, SYM_t}; use i4config::keyboard::syms::{SYM_Super_L, SYM_h, SYM_j, SYM_k, SYM_l, SYM_r, SYM_t, SYM_x};
use i4config::Direction::{Down, Left, Right, Up}; use i4config::Direction::{Down, Left, Right, Up};
use i4config::{config, shell, Seat, create_seat, input_devices, on_new_input_device}; use i4config::{config, create_seat, input_devices, on_new_input_device, Seat, Command};
const MOD: Modifiers = ALT; const MOD: Modifiers = ALT;
@ -15,8 +15,8 @@ fn configure_seat(s: Seat) {
s.set_repeat_rate(new_rate, new_delay); s.set_repeat_rate(new_rate, new_delay);
}; };
s.bind(CTRL | SYM_l, move || change_rate(-1)); s.bind(CTRL | SHIFT | SYM_l, move || change_rate(-1));
s.bind(CTRL | SYM_r, move || change_rate(1)); s.bind(CTRL | SHIFT | SYM_r, move || change_rate(1));
s.bind(CTRL | SYM_h, move || s.focus(Left)); s.bind(CTRL | SYM_h, move || s.focus(Left));
s.bind(CTRL | SYM_j, move || s.focus(Down)); s.bind(CTRL | SYM_j, move || s.focus(Down));
@ -32,7 +32,9 @@ fn configure_seat(s: Seat) {
s.bind(MOD | SHIFT | SYM_k, move || s.move_(Up)); s.bind(MOD | SHIFT | SYM_k, move || s.move_(Up));
s.bind(MOD | SHIFT | SYM_l, move || s.move_(Right)); s.bind(MOD | SHIFT | SYM_l, move || s.move_(Right));
s.bind(SYM_Super_L, || shell("alacritty")); s.bind(SYM_x, || {
Command::new("alacritty").spawn()
});
} }
pub fn configure() { pub fn configure() {

View file

@ -1,13 +1,13 @@
use crate::_private::ipc::{InitMessage, Request, Response}; use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage};
use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION}; use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION};
use crate::{Axis, Direction, InputDevice, LogLevel, ModifiedKeySym, Seat}; use crate::keyboard::keymap::Keymap;
use crate::{Axis, Command, Direction, InputDevice, LogLevel, ModifiedKeySym, Seat};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use std::{ptr, slice}; use std::{ptr, slice};
use crate::keyboard::keymap::Keymap;
pub(crate) struct Client { pub(crate) struct Client {
configure: extern "C" fn(), configure: extern "C" fn(),
@ -117,7 +117,7 @@ pub unsafe extern "C" fn handle_msg(data: *const u8, msg: *const u8, size: usize
} }
impl Client { impl Client {
fn send(&self, msg: &Request) { fn send(&self, msg: &ClientMessage) {
let mut buf = self.bufs.borrow_mut().pop().unwrap_or_default(); let mut buf = self.bufs.borrow_mut().pop().unwrap_or_default();
buf.clear(); buf.clear();
bincode::encode_into_std_write(msg, &mut buf, bincode_ops()).unwrap(); bincode::encode_into_std_write(msg, &mut buf, bincode_ops()).unwrap();
@ -127,16 +127,21 @@ impl Client {
self.bufs.borrow_mut().push(buf); self.bufs.borrow_mut().push(buf);
} }
pub fn shell(&self, shell: &str) { pub fn spawn(&self, command: &Command) {
self.send(&Request::Shell { script: shell }); let env = command.env.iter().map(|(a, b)| (a.to_string(), b.to_string())).collect();
self.send(&ClientMessage::Run {
prog: &command.prog,
args: command.args.clone(),
env,
});
} }
pub fn focus(&self, seat: Seat, direction: Direction) { pub fn focus(&self, seat: Seat, direction: Direction) {
self.send(&Request::Focus { seat, direction }); self.send(&ClientMessage::Focus { seat, direction });
} }
pub fn move_(&self, seat: Seat, direction: Direction) { pub fn move_(&self, seat: Seat, direction: Direction) {
self.send(&Request::Move { seat, direction }); self.send(&ClientMessage::Move { seat, direction });
} }
pub fn unbind<T: Into<ModifiedKeySym>>(&self, seat: Seat, mod_sym: T) { pub fn unbind<T: Into<ModifiedKeySym>>(&self, seat: Seat, mod_sym: T) {
@ -147,7 +152,7 @@ impl Client {
.remove(&(seat, mod_sym)) .remove(&(seat, mod_sym))
.is_some(); .is_some();
if deregister { if deregister {
self.send(&Request::RemoveShortcut { self.send(&ClientMessage::RemoveShortcut {
seat, seat,
mods: mod_sym.mods, mods: mod_sym.mods,
sym: mod_sym.sym, sym: mod_sym.sym,
@ -161,7 +166,7 @@ impl Client {
} }
pub fn seats(&self) -> Vec<Seat> { pub fn seats(&self) -> Vec<Seat> {
let response = self.with_response(|| self.send(&Request::GetSeats)); let response = self.with_response(|| self.send(&ClientMessage::GetSeats));
match response { match response {
Response::GetSeats { seats } => seats, Response::GetSeats { seats } => seats,
_ => { _ => {
@ -172,22 +177,22 @@ impl Client {
} }
pub fn split(&self, seat: Seat) -> Axis { pub fn split(&self, seat: Seat) -> Axis {
let res = self.with_response(|| self.send(&Request::GetSplit { seat })); let res = self.with_response(|| self.send(&ClientMessage::GetSplit { seat }));
match res { match res {
Response::GetSplit { axis } => axis, Response::GetSplit { axis } => axis,
_ => { _ => {
log::error!("Server did not send a response to a get_split request"); log::error!("Server did not send a response to a get_split request");
Axis::Horizontal Axis::Horizontal
}, }
} }
} }
pub fn set_split(&self, seat: Seat, axis: Axis) { pub fn set_split(&self, seat: Seat, axis: Axis) {
self.send(&Request::SetSplit { seat, axis }); self.send(&ClientMessage::SetSplit { seat, axis });
} }
pub fn create_seat(&self, name: &str) -> Seat { pub fn create_seat(&self, name: &str) -> Seat {
let response = self.with_response(|| self.send(&Request::CreateSeat { name })); let response = self.with_response(|| self.send(&ClientMessage::CreateSeat { name }));
match response { match response {
Response::CreateSeat { seat } => seat, Response::CreateSeat { seat } => seat,
_ => { _ => {
@ -198,12 +203,12 @@ impl Client {
} }
pub fn get_input_devices(&self) -> Vec<InputDevice> { pub fn get_input_devices(&self) -> Vec<InputDevice> {
let res = self.with_response(|| self.send(&Request::GetInputDevices)); let res = self.with_response(|| self.send(&ClientMessage::GetInputDevices));
match res { match res {
Response::GetInputDevices { devices } => devices, Response::GetInputDevices { devices } => devices,
_ => { _ => {
log::error!("Server did not send a response to a get_input_devices request"); log::error!("Server did not send a response to a get_input_devices request");
vec!() vec![]
} }
} }
} }
@ -217,19 +222,19 @@ impl Client {
} }
pub fn set_seat(&self, device: InputDevice, seat: Seat) { pub fn set_seat(&self, device: InputDevice, seat: Seat) {
self.send(&Request::SetSeat { device, seat }) self.send(&ClientMessage::SetSeat { device, seat })
} }
pub fn seat_set_keymap(&self, seat: Seat, keymap: Keymap) { pub fn seat_set_keymap(&self, seat: Seat, keymap: Keymap) {
self.send(&Request::SeatSetKeymap { seat, keymap }) self.send(&ClientMessage::SeatSetKeymap { seat, keymap })
} }
pub fn seat_set_repeat_rate(&self, seat: Seat, rate: i32, delay: i32) { pub fn seat_set_repeat_rate(&self, seat: Seat, rate: i32, delay: i32) {
self.send(&Request::SeatSetRepeatRate { seat, rate, delay }) self.send(&ClientMessage::SeatSetRepeatRate { seat, rate, delay })
} }
pub fn seat_get_repeat_rate(&self, seat: Seat) -> (i32, i32) { pub fn seat_get_repeat_rate(&self, seat: Seat) -> (i32, i32) {
let res = self.with_response(|| self.send(&Request::SeatGetRepeatRate { seat })); let res = self.with_response(|| self.send(&ClientMessage::SeatGetRepeatRate { seat }));
match res { match res {
Response::GetRepeatRate { rate, delay } => (rate, delay), Response::GetRepeatRate { rate, delay } => (rate, delay),
_ => { _ => {
@ -240,7 +245,7 @@ impl Client {
} }
pub fn parse_keymap(&self, keymap: &str) -> Keymap { pub fn parse_keymap(&self, keymap: &str) -> Keymap {
let res = self.with_response(|| self.send(&Request::ParseKeymap { keymap })); let res = self.with_response(|| self.send(&ClientMessage::ParseKeymap { keymap }));
match res { match res {
Response::ParseKeymap { keymap } => keymap, Response::ParseKeymap { keymap } => keymap,
_ => { _ => {
@ -267,7 +272,7 @@ impl Client {
} }
}; };
if register { if register {
self.send(&Request::AddShortcut { self.send(&ClientMessage::AddShortcut {
seat, seat,
mods: mod_sym.mods, mods: mod_sym.mods,
sym: mod_sym.sym, sym: mod_sym.sym,
@ -276,7 +281,7 @@ impl Client {
} }
pub fn log(&self, level: LogLevel, msg: &str, file: Option<&str>, line: Option<u32>) { pub fn log(&self, level: LogLevel, msg: &str, file: Option<&str>, line: Option<u32>) {
self.send(&Request::Log { self.send(&ClientMessage::Log {
level, level,
msg, msg,
file, file,
@ -285,7 +290,7 @@ impl Client {
} }
fn handle_msg(&self, msg: &[u8]) { fn handle_msg(&self, msg: &[u8]) {
let res = bincode::decode_from_slice::<Request, _>(msg, bincode_ops()); let res = bincode::decode_from_slice::<ServerMessage, _>(msg, bincode_ops());
let (msg, _) = match res { let (msg, _) = match res {
Ok(msg) => msg, Ok(msg) => msg,
Err(e) => { Err(e) => {
@ -295,30 +300,26 @@ impl Client {
} }
}; };
match msg { match msg {
Request::Configure => { ServerMessage::Configure => {
(self.configure)(); (self.configure)();
} }
Request::Response { response } => { ServerMessage::Response { response } => {
self.response.borrow_mut().push(response); self.response.borrow_mut().push(response);
} }
Request::InvokeShortcut { seat, mods, sym } => { ServerMessage::InvokeShortcut { seat, mods, sym } => {
let ms = ModifiedKeySym { mods, sym }; let ms = ModifiedKeySym { mods, sym };
let handler = self.key_handlers.borrow_mut().get(&(seat, ms)).cloned(); let handler = self.key_handlers.borrow_mut().get(&(seat, ms)).cloned();
if let Some(handler) = handler { if let Some(handler) = handler {
handler(); handler();
} }
} }
Request::NewInputDevice { device } => { ServerMessage::NewInputDevice { device } => {
let handler = self.on_new_input_device.borrow_mut().clone(); let handler = self.on_new_input_device.borrow_mut().clone();
if let Some(handler) = handler { if let Some(handler) = handler {
handler(device); handler(device);
} }
} }
m => { ServerMessage::DelInputDevice { .. } => {}
let err = format!("unexpected message: {:?}", m);
self.log(LogLevel::Error, &err, None, None);
return;
}
} }
} }

View file

@ -1,21 +1,36 @@
use crate::keyboard::keymap::Keymap;
use crate::keyboard::mods::Modifiers; use crate::keyboard::mods::Modifiers;
use crate::keyboard::syms::KeySym; use crate::keyboard::syms::KeySym;
use crate::{Axis, Direction, InputDevice, LogLevel, Seat}; use crate::{Axis, Direction, InputDevice, LogLevel, Seat};
use bincode::{BorrowDecode, Decode, Encode}; use bincode::{BorrowDecode, Decode, Encode};
use crate::keyboard::keymap::Keymap;
#[derive(Encode, BorrowDecode, Debug)] #[derive(Encode, BorrowDecode, Debug)]
pub enum Request<'a> { pub enum ServerMessage {
Configure, Configure,
Response {
response: Response,
},
NewInputDevice {
device: InputDevice,
},
DelInputDevice {
device: InputDevice,
},
InvokeShortcut {
seat: Seat,
mods: Modifiers,
sym: KeySym,
},
}
#[derive(Encode, BorrowDecode, Debug)]
pub enum ClientMessage<'a> {
Log { Log {
level: LogLevel, level: LogLevel,
msg: &'a str, msg: &'a str,
file: Option<&'a str>, file: Option<&'a str>,
line: Option<u32>, line: Option<u32>,
}, },
Response {
response: Response,
},
CreateSeat { CreateSeat {
name: &'a str, name: &'a str,
}, },
@ -50,12 +65,6 @@ pub enum Request<'a> {
}, },
GetSeats, GetSeats,
GetInputDevices, GetInputDevices,
NewInputDevice {
device: InputDevice,
},
DelInputDevice {
device: InputDevice,
},
AddShortcut { AddShortcut {
seat: Seat, seat: Seat,
mods: Modifiers, mods: Modifiers,
@ -66,13 +75,10 @@ pub enum Request<'a> {
mods: Modifiers, mods: Modifiers,
sym: KeySym, sym: KeySym,
}, },
InvokeShortcut { Run {
seat: Seat, prog: &'a str,
mods: Modifiers, args: Vec<String>,
sym: KeySym, env: Vec<(String, String)>,
},
Shell {
script: &'a str,
}, },
Focus { Focus {
seat: Seat, seat: Seat,
@ -90,7 +96,7 @@ pub enum Response {
GetSeats { seats: Vec<Seat> }, GetSeats { seats: Vec<Seat> },
GetSplit { axis: Axis }, GetSplit { axis: Axis },
GetRepeatRate { rate: i32, delay: i32 }, GetRepeatRate { rate: i32, delay: i32 },
ParseKeymap { keymap: Keymap, }, ParseKeymap { keymap: Keymap },
CreateSeat { seat: Seat }, CreateSeat { seat: Seat },
GetInputDevices { devices: Vec<InputDevice> }, GetInputDevices { devices: Vec<InputDevice> },
} }

View file

@ -3,9 +3,9 @@ use crate::keyboard::syms::KeySym;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use std::ops::{BitOr, BitOrAssign}; use std::ops::{BitOr, BitOrAssign};
pub mod keymap;
pub mod mods; pub mod mods;
pub mod syms; pub mod syms;
pub mod keymap;
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash)] #[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash)]
pub struct ModifiedKeySym { pub struct ModifiedKeySym {

View file

@ -1,8 +1,9 @@
#![feature(thread_local_const_init)] #![feature(thread_local_const_init)]
use std::collections::HashMap;
use crate::keyboard::keymap::Keymap;
use crate::keyboard::ModifiedKeySym; use crate::keyboard::ModifiedKeySym;
use bincode::{Decode, Encode}; use bincode::{Decode, Encode};
use crate::keyboard::keymap::Keymap;
#[macro_use] #[macro_use]
mod macros; mod macros;
@ -151,6 +152,32 @@ pub fn on_new_input_device<F: Fn(InputDevice) + 'static>(f: F) {
get!().on_new_input_device(f) get!().on_new_input_device(f)
} }
pub fn shell(shell: &str) { pub struct Command {
get!().shell(shell) prog: String,
args: Vec<String>,
env: HashMap<String, String>,
}
impl Command {
pub fn new(prog: &str) -> Self {
Self {
prog: prog.to_string(),
args: vec![],
env: Default::default(),
}
}
pub fn arg(&mut self, arg: &str) -> &mut Self {
self.args.push(arg.to_string());
self
}
pub fn env(&mut self, key: &str, val: &str) -> &mut Self {
self.env.insert(key.to_string(), val.to_string());
self
}
pub fn spawn(&self) {
get!().spawn(self);
}
} }

View file

@ -71,7 +71,7 @@ fn bind_socket(fd: i32, xdr: &str) -> Result<u32, AcceptorError> {
} }
impl Acceptor { 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") { let xrd = match std::env::var("XDG_RUNTIME_DIR") {
Ok(d) => d, Ok(d) => d,
Err(_) => return Err(AcceptorError::XrdNotSet), Err(_) => return Err(AcceptorError::XrdNotSet),
@ -87,7 +87,7 @@ impl Acceptor {
let socket_id = bind_socket(fd.raw(), &xrd)?; let socket_id = bind_socket(fd.raw(), &xrd)?;
let socket_path = socket_path(&xrd, socket_id); let socket_path = socket_path(&xrd, socket_id);
log::info!("bound to socket {}", socket_path); 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) { if let Err(e) = uapi::listen(fd.raw(), 4096) {
return Err(AcceptorError::ListenFailed(e.into())); return Err(AcceptorError::ListenFailed(e.into()));
} }
@ -99,7 +99,7 @@ impl Acceptor {
global: global.clone(), global: global.clone(),
}); });
global.el.insert(id, Some(acc.fd.raw()), c::EPOLLIN, acc)?; global.el.insert(id, Some(acc.fd.raw()), c::EPOLLIN, acc)?;
Ok(()) Ok(socket_path)
} }
} }

View file

@ -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::drm::{Drm, DrmError};
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING}; use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
use crate::drm::{ModifiedFormat, INVALID_MODIFIER}; use crate::drm::{ModifiedFormat, INVALID_MODIFIER};

View file

@ -1,19 +1,19 @@
mod handler; mod handler;
use crate::backend::{KeyboardId, MouseId}; use crate::backend::{KeyboardId, MouseId};
use crate::config::handler::ConfigProxyHandler;
use crate::ifs::wl_seat::SeatId;
use crate::utils::ptr_ext::PtrExt; use crate::utils::ptr_ext::PtrExt;
use crate::{NumCell, State}; 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::_private::{bincode_ops, ConfigEntry, VERSION};
use i4config::keyboard::ModifiedKeySym; use i4config::keyboard::ModifiedKeySym;
use i4config::{InputDevice, Keyboard, Mouse, Seat};
use libloading::Library; use libloading::Library;
use std::cell::Cell; use std::cell::Cell;
use std::ptr; use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use i4config::{InputDevice, Keyboard, Mouse, Seat};
use crate::config::handler::ConfigProxyHandler;
use crate::ifs::wl_seat::{SeatId};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum ConfigError { pub enum ConfigError {
@ -29,7 +29,7 @@ pub struct ConfigProxy {
impl ConfigProxy { impl ConfigProxy {
pub fn invoke_shortcut(&self, seat: SeatId, modsym: &ModifiedKeySym) { pub fn invoke_shortcut(&self, seat: SeatId, modsym: &ModifiedKeySym) {
self.handler.send(&Request::InvokeShortcut { self.handler.send(&ServerMessage::InvokeShortcut {
seat: Seat(seat.raw() as _), seat: Seat(seat.raw() as _),
mods: modsym.mods, mods: modsym.mods,
sym: modsym.sym, sym: modsym.sym,
@ -37,25 +37,25 @@ impl ConfigProxy {
} }
pub fn new_keyboard(&self, kb: KeyboardId) { pub fn new_keyboard(&self, kb: KeyboardId) {
self.handler.send(&Request::NewInputDevice { self.handler.send(&ServerMessage::NewInputDevice {
device: InputDevice::Keyboard(Keyboard(kb.raw() as _)), device: InputDevice::Keyboard(Keyboard(kb.raw() as _)),
}); });
} }
pub fn new_mouse(&self, mouse: MouseId) { pub fn new_mouse(&self, mouse: MouseId) {
self.handler.send(&Request::NewInputDevice { self.handler.send(&ServerMessage::NewInputDevice {
device: InputDevice::Mouse(Mouse(mouse.raw() as _)), device: InputDevice::Mouse(Mouse(mouse.raw() as _)),
}); });
} }
pub fn del_keyboard(&self, kb: KeyboardId) { pub fn del_keyboard(&self, kb: KeyboardId) {
self.handler.send(&Request::DelInputDevice { self.handler.send(&ServerMessage::DelInputDevice {
device: InputDevice::Keyboard(Keyboard(kb.raw() as _)), device: InputDevice::Keyboard(Keyboard(kb.raw() as _)),
}); });
} }
pub fn del_mouse(&self, mouse: MouseId) { pub fn del_mouse(&self, mouse: MouseId) {
self.handler.send(&Request::DelInputDevice { self.handler.send(&ServerMessage::DelInputDevice {
device: InputDevice::Mouse(Mouse(mouse.raw() as _)), device: InputDevice::Mouse(Mouse(mouse.raw() as _)),
}); });
} }
@ -110,7 +110,7 @@ impl ConfigProxy {
); );
data.client_data.set(client_data); data.client_data.set(client_data);
} }
data.send(&Request::Configure); data.send(&ServerMessage::Configure);
Self { handler: data } Self { handler: data }
} }

View file

@ -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::backend::{KeyboardId, MouseId};
use crate::ifs::wl_seat::WlSeatGlobal; use crate::ifs::wl_seat::WlSeatGlobal;
use crate::state::DeviceHandlerData; use crate::state::DeviceHandlerData;
@ -19,6 +6,19 @@ use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::debug_fn::debug_fn; use crate::utils::debug_fn::debug_fn;
use crate::utils::stack::Stack; use crate::utils::stack::Stack;
use crate::xkbcommon::XkbKeymap; 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(super) struct ConfigProxyHandler {
pub client_data: Cell<*const u8>, pub client_data: Cell<*const u8>,
@ -34,7 +34,7 @@ pub(super) struct ConfigProxyHandler {
} }
impl ConfigProxyHandler { impl ConfigProxyHandler {
pub fn send(&self, msg: &Request) { pub fn send(&self, msg: &ServerMessage) {
let mut buf = self.bufs.pop().unwrap_or_default(); let mut buf = self.bufs.pop().unwrap_or_default();
buf.clear(); buf.clear();
bincode::encode_into_std_write(msg, &mut buf, bincode_ops()).unwrap(); bincode::encode_into_std_write(msg, &mut buf, bincode_ops()).unwrap();
@ -48,7 +48,13 @@ impl ConfigProxyHandler {
self.next_id.fetch_add(1) 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 { let level = match level {
LogLevel::Error => Level::Error, LogLevel::Error => Level::Error,
LogLevel::Warn => Level::Warn, LogLevel::Warn => Level::Warn,
@ -75,10 +81,10 @@ impl ConfigProxyHandler {
let global_name = self.state.globals.name(); let global_name = self.state.globals.name();
let seat = WlSeatGlobal::new(global_name, name, &self.state); let seat = WlSeatGlobal::new(global_name, name, &self.state);
self.state.globals.add_global(&self.state, &seat); self.state.globals.add_global(&self.state, &seat);
self.send(&Request::Response { self.send(&ServerMessage::Response {
response: Response::CreateSeat { response: Response::CreateSeat {
seat: Seat(seat.id().raw() as _), seat: Seat(seat.id().raw() as _),
} },
}); });
Ok(()) Ok(())
} }
@ -90,11 +96,11 @@ impl ConfigProxyHandler {
self.keymaps.set(id, keymap); self.keymaps.set(id, keymap);
(id, Ok(())) (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 res
} }
@ -118,16 +124,18 @@ impl ConfigProxyHandler {
fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> { fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> {
let seat = self.get_seat(seat)?; let seat = self.get_seat(seat)?;
let (rate, delay) = seat.get_rate(); let (rate, delay) = seat.get_rate();
self.send(&Request::Response { self.send(&ServerMessage::Response {
response: Response::GetRepeatRate { response: Response::GetRepeatRate { rate, delay },
rate,
delay,
},
}); });
Ok(()) 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)?; let seat = self.get_seat(seat)?;
if rate < 0 { if rate < 0 {
return Err(SeatSetRepeatRateError::NegativeRate); return Err(SeatSetRepeatRateError::NegativeRate);
@ -139,14 +147,23 @@ impl ConfigProxyHandler {
Ok(()) 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 { let data = match device {
InputDevice::Keyboard(kb) => { InputDevice::Keyboard(kb) => self
self.state.kb_handlers.borrow_mut().get(&KeyboardId::from_raw(kb.0 as _)).map(|d| d.data.clone()) .state
}, .kb_handlers
InputDevice::Mouse(mouse) => { .borrow_mut()
self.state.mouse_handlers.borrow_mut().get(&MouseId::from_raw(mouse.0 as _)).map(|d| d.data.clone()) .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 { match data {
Some(d) => Ok(d), Some(d) => Ok(d),
@ -184,10 +201,13 @@ impl ConfigProxyHandler {
fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> { fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> {
let seat = self.get_seat(seat)?; let seat = self.get_seat(seat)?;
self.send(&Request::Response { self.send(&ServerMessage::Response {
response: Response::GetSplit { response: Response::GetSplit {
axis: seat.get_split().unwrap_or(ContainerSplit::Horizontal).into(), axis: seat
} .get_split()
.unwrap_or(ContainerSplit::Horizontal)
.into(),
},
}); });
Ok(()) Ok(())
} }
@ -198,14 +218,19 @@ impl ConfigProxyHandler {
Ok(()) 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)?; let seat = self.get_seat(seat)?;
seat.add_shortcut(mods, sym); seat.add_shortcut(mods, sym);
Ok(()) Ok(())
} }
fn handle_get_input_devices(&self) -> Result<(), GetInputDevicesError> { fn handle_get_input_devices(&self) -> Result<(), GetInputDevicesError> {
let mut res = vec!(); let mut res = vec![];
{ {
let devs = self.state.kb_handlers.borrow_mut(); let devs = self.state.kb_handlers.borrow_mut();
for dev in devs.values() { for dev in devs.values() {
@ -218,7 +243,7 @@ impl ConfigProxyHandler {
res.push(InputDevice::Mouse(Mouse(dev.id.raw() as _))); res.push(InputDevice::Mouse(Mouse(dev.id.raw() as _)));
} }
} }
self.send(&Request::Response { self.send(&ServerMessage::Response {
response: Response::GetInputDevices { devices: res }, response: Response::GetInputDevices { devices: res },
}); });
Ok(()) Ok(())
@ -232,12 +257,21 @@ impl ConfigProxyHandler {
.map(|seat| Seat::from_raw(seat.id().raw() as _)) .map(|seat| Seat::from_raw(seat.id().raw() as _))
.collect() .collect()
}; };
self.send(&Request::Response { self.send(&ServerMessage::Response {
response: Response::GetSeats { seats }, response: Response::GetSeats { seats },
}); });
Ok(()) 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]) { pub fn handle_request(&self, msg: &[u8]) {
if let Err(e) = self.handle_request_(msg) { if let Err(e) = self.handle_request_(msg) {
log::error!("Could not handle client request: {}", ErrorFmt(e)); log::error!("Could not handle client request: {}", ErrorFmt(e));
@ -245,36 +279,40 @@ impl ConfigProxyHandler {
} }
fn handle_request_(&self, msg: &[u8]) -> Result<(), CphError> { 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, Ok(msg) => msg,
Err(e) => return Err(CphError::ParsingFailed(e)), Err(e) => return Err(CphError::ParsingFailed(e)),
}; };
match request { match request {
Request::Log { ClientMessage::Log {
level, level,
msg, msg,
file, file,
line, line,
} => self.handle_log_request(level, msg, file, line)?, } => self.handle_log_request(level, msg, file, line)?,
Request::CreateSeat { name } => self.handle_create_seat(name)?, ClientMessage::CreateSeat { name } => self.handle_create_seat(name)?,
Request::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?, ClientMessage::ParseKeymap { keymap } => self.handle_parse_keymap(keymap)?,
Request::SeatSetKeymap { seat, keymap } => self.handle_set_keymap(seat, keymap)?, ClientMessage::SeatSetKeymap { seat, keymap } => {
Request::SeatGetRepeatRate { seat } => self.handle_get_repeat_rate(seat)?, self.handle_set_keymap(seat, keymap)?
Request::SeatSetRepeatRate { seat, rate, delay } => self.handle_set_repeat_rate(seat, rate, delay)?, }
Request::SetSeat { device, seat } => self.handle_set_seat(device, seat)?, ClientMessage::SeatGetRepeatRate { seat } => self.handle_get_repeat_rate(seat)?,
Request::GetSplit { seat } => self.handle_get_split(seat)?, ClientMessage::SeatSetRepeatRate { seat, rate, delay } => {
Request::SetSplit { seat, axis } => self.handle_set_split(seat, axis)?, self.handle_set_repeat_rate(seat, rate, delay)?
Request::AddShortcut { }
seat, ClientMessage::SetSeat { device, seat } => self.handle_set_seat(device, seat)?,
mods, ClientMessage::GetSplit { seat } => self.handle_get_split(seat)?,
sym, ClientMessage::SetSplit { seat, axis } => self.handle_set_split(seat, axis)?,
} => self.handle_add_shortcut(seat, mods, sym)?, ClientMessage::AddShortcut { seat, mods, sym } => {
Request::RemoveShortcut { .. } => {} self.handle_add_shortcut(seat, mods, sym)?
Request::Focus { seat, direction } => self.handle_focus(seat, direction)?, }
Request::Move { seat, direction } => {} ClientMessage::RemoveShortcut { .. } => {}
Request::GetInputDevices => self.handle_get_input_devices()?, ClientMessage::Focus { seat, direction } => self.handle_focus(seat, direction)?,
Request::GetSeats => self.handle_get_seats()?, ClientMessage::Move { seat, direction } => {}
m => return Err(CphError::UnexpectedMessage(format!("{:?}", m))), 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(()) Ok(())
} }
@ -308,6 +346,8 @@ enum CphError {
SetSplitError(#[from] SetSplitError), SetSplitError(#[from] SetSplitError),
#[error("Could not process a `get_split` request")] #[error("Could not process a `get_split` request")]
GetSplitError(#[from] GetSplitError), GetSplitError(#[from] GetSplitError),
#[error("Could not process a `run` request")]
RunError(#[from] RunError),
#[error("Device {0:?} does not exist")] #[error("Device {0:?} does not exist")]
DeviceDoesNotExist(InputDevice), DeviceDoesNotExist(InputDevice),
#[error("Device {0:?} does not exist")] #[error("Device {0:?} does not exist")]
@ -321,14 +361,10 @@ enum CphError {
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum LogError { enum LogError {}
}
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum CreateSeatError { enum CreateSeatError {}
}
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum ParseKeymapError { enum ParseKeymapError {
@ -351,14 +387,10 @@ enum AddShortcutError {
efrom!(AddShortcutError, CphError); efrom!(AddShortcutError, CphError);
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum GetInputDevicesError { enum GetInputDevicesError {}
}
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum GetSeatsError { enum GetSeatsError {}
}
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum SeatSetKeymapError { enum SeatSetKeymapError {
@ -405,3 +437,9 @@ enum GetSplitError {
CphError(#[from] Box<CphError>), CphError(#[from] Box<CphError>),
} }
efrom!(GetSplitError, CphError); efrom!(GetSplitError, CphError);
#[derive(Debug, Error)]
enum RunError {
#[error("The ol' forker is not available")]
NoForker,
}

344
src/forker.rs Normal file
View 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
View 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)
}
}

View file

@ -4,6 +4,7 @@ pub mod wl_keyboard;
pub mod wl_pointer; pub mod wl_pointer;
pub mod wl_touch; pub mod wl_touch;
use crate::async_engine::SpawnedFuture;
use crate::client::{Client, ClientError, ClientId}; use crate::client::{Client, ClientError, ClientId};
use crate::cursor::{Cursor, KnownCursor}; use crate::cursor::{Cursor, KnownCursor};
use crate::fixed::Fixed; use crate::fixed::Fixed;
@ -38,6 +39,7 @@ use crate::{ErrorFmt, NumCell, State};
use ahash::{AHashMap, AHashSet}; use ahash::{AHashMap, AHashSet};
pub use event_handling::NodeSeatState; pub use event_handling::NodeSeatState;
use i4config::keyboard::mods::Modifiers; use i4config::keyboard::mods::Modifiers;
use i4config::Direction;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::mem; use std::mem;
@ -45,8 +47,6 @@ use std::ops::DerefMut;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use uapi::{c, Errno, OwnedFd}; use uapi::{c, Errno, OwnedFd};
use i4config::{ Direction};
use crate::async_engine::SpawnedFuture;
const POINTER: u32 = 1; const POINTER: u32 = 1;
const KEYBOARD: u32 = 2; const KEYBOARD: u32 = 2;
@ -119,11 +119,7 @@ pub struct WlSeatGlobal {
} }
impl WlSeatGlobal { impl WlSeatGlobal {
pub fn new( pub fn new(name: GlobalName, seat_name: &str, state: &Rc<State>) -> Rc<Self> {
name: GlobalName,
seat_name: &str,
state: &Rc<State>,
) -> Rc<Self> {
let slf = Rc::new(Self { let slf = Rc::new(Self {
id: state.seat_ids.next(), id: state.seat_ids.next(),
name, name,
@ -167,7 +163,8 @@ impl WlSeatGlobal {
} }
pub fn mark_last_active(self: &Rc<Self>) { 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>) { pub fn set_keymap(&self, keymap: &Rc<XkbKeymap>) {
@ -464,7 +461,11 @@ impl WlSeat {
self.client.add_client_obj(&p)?; self.client.add_client_obj(&p)?;
self.keyboards.set(req.id, p.clone()); self.keyboards.set(req.id, p.clone());
let keymap = self.global.kb_map.get(); 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 { if self.version >= REPEAT_INFO_SINCE {
let (rate, delay) = self.global.repeat_rate.get(); let (rate, delay) = self.global.repeat_rate.get();
p.send_repeat_info(rate, delay); p.send_repeat_info(rate, delay);
@ -484,12 +485,7 @@ impl WlSeat {
let mut pos = 0; let mut pos = 0;
while pos < target { while pos < target {
let rem = target - pos; let rem = target - pos;
let res = uapi::sendfile( let res = uapi::sendfile(fd.raw(), keymap.map.raw(), Some(&mut pos), rem as usize);
fd.raw(),
keymap.map.raw(),
Some(&mut pos),
rem as usize,
);
match res { match res {
Ok(_) | Err(Errno(c::EINTR)) => {} Ok(_) | Err(Errno(c::EINTR)) => {}
Err(e) => return Err(WlKeyboardError::KeymapCopy(e.into())), Err(e) => return Err(WlKeyboardError::KeymapCopy(e.into())),

View file

@ -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::client::{Client, ClientId};
use crate::fixed::Fixed; use crate::fixed::Fixed;
use crate::ifs::ipc; 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::ipc::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
use crate::ifs::wl_seat::wl_keyboard::WlKeyboard; 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_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_popup::XdgPopup;
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel; use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
use crate::ifs::wl_surface::xdg_surface::XdgSurface; use crate::ifs::wl_surface::xdg_surface::XdgSurface;

View file

@ -8,7 +8,7 @@ use crate::wire::wl_keyboard::*;
use crate::wire::{WlKeyboardId, WlSurfaceId}; use crate::wire::{WlKeyboardId, WlSurfaceId};
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use uapi::{OwnedFd}; use uapi::OwnedFd;
pub const REPEAT_INFO_SINCE: u32 = 4; pub const REPEAT_INFO_SINCE: u32 = 4;

View file

@ -2,6 +2,7 @@ pub mod cursor;
pub mod wl_subsurface; pub mod wl_subsurface;
pub mod xdg_surface; pub mod xdg_surface;
use crate::backend::{KeyState, ScrollAxis};
use crate::client::{Client, ClientError, RequestParser}; use crate::client::{Client, ClientError, RequestParser};
use crate::fixed::Fixed; use crate::fixed::Fixed;
use crate::ifs::wl_buffer::WlBuffer; use crate::ifs::wl_buffer::WlBuffer;
@ -25,14 +26,13 @@ use crate::wire::{WlOutputId, WlSurfaceId};
use crate::xkbcommon::ModifierState; use crate::xkbcommon::ModifierState;
use crate::NumCell; use crate::NumCell;
use ahash::AHashMap; use ahash::AHashMap;
use i4config::Direction;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use i4config::{ Direction};
use crate::backend::{KeyState, ScrollAxis};
#[allow(dead_code)] #[allow(dead_code)]
const INVALID_SCALE: u32 = 0; const INVALID_SCALE: u32 = 0;

View file

@ -21,11 +21,11 @@ use crate::utils::smallmap::SmallMap;
use crate::wire::xdg_surface::*; use crate::wire::xdg_surface::*;
use crate::wire::{WlSurfaceId, XdgPopupId, XdgSurfaceId}; use crate::wire::{WlSurfaceId, XdgPopupId, XdgSurfaceId};
use crate::NumCell; use crate::NumCell;
use i4config::Direction;
use std::cell::Cell; use std::cell::Cell;
use std::fmt::Debug; use std::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use i4config::{Direction};
#[allow(dead_code)] #[allow(dead_code)]
const NOT_CONSTRUCTED: u32 = 1; const NOT_CONSTRUCTED: u32 = 1;

View file

@ -19,6 +19,7 @@ use crate::wire::xdg_toplevel::*;
use crate::wire::XdgToplevelId; use crate::wire::XdgToplevelId;
use crate::{bugs, NumCell}; use crate::{bugs, NumCell};
use ahash::{AHashMap, AHashSet}; use ahash::{AHashMap, AHashSet};
use i4config::Direction;
use num_derive::FromPrimitive; use num_derive::FromPrimitive;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
@ -26,7 +27,6 @@ use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use i4config::{Direction};
#[derive(Copy, Clone, Debug, FromPrimitive)] #[derive(Copy, Clone, Debug, FromPrimitive)]
pub enum ResizeEdge { pub enum ResizeEdge {

View file

@ -13,6 +13,7 @@ use crate::backends::xorg::{XorgBackend, XorgBackendError};
use crate::client::Clients; use crate::client::Clients;
use crate::clientmem::ClientMemError; use crate::clientmem::ClientMemError;
use crate::event_loop::EventLoopError; use crate::event_loop::EventLoopError;
use crate::forker::ForkerError;
use crate::globals::Globals; use crate::globals::Globals;
use crate::ifs::wl_compositor::WlCompositorGlobal; use crate::ifs::wl_compositor::WlCompositorGlobal;
use crate::ifs::wl_shm::WlShmGlobal; use crate::ifs::wl_shm::WlShmGlobal;
@ -29,6 +30,7 @@ use crate::utils::errorfmt::ErrorFmt;
use crate::utils::numcell::NumCell; use crate::utils::numcell::NumCell;
use crate::utils::queue::AsyncQueue; use crate::utils::queue::AsyncQueue;
use crate::wheel::WheelError; use crate::wheel::WheelError;
use crate::xkbcommon::XkbContext;
use acceptor::Acceptor; use acceptor::Acceptor;
use async_engine::AsyncEngine; use async_engine::AsyncEngine;
use event_loop::EventLoop; use event_loop::EventLoop;
@ -38,7 +40,6 @@ use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use wheel::Wheel; use wheel::Wheel;
use crate::xkbcommon::XkbContext;
#[macro_use] #[macro_use]
mod macros; mod macros;
@ -56,6 +57,7 @@ mod cursor;
mod drm; mod drm;
mod event_loop; mod event_loop;
mod fixed; mod fixed;
mod forker;
mod format; mod format;
mod globals; mod globals;
mod ifs; mod ifs;
@ -104,9 +106,12 @@ enum MainError {
XorgBackendError(#[from] XorgBackendError), XorgBackendError(#[from] XorgBackendError),
#[error("The render backend caused an error")] #[error("The render backend caused an error")]
RenderError(#[from] RenderError), RenderError(#[from] RenderError),
#[error("The ol' forker caused an error")]
ForkerError(#[from] ForkerError),
} }
fn main_() -> Result<(), MainError> { fn main_() -> Result<(), MainError> {
let forker = Rc::new(forker::ForkerProxy::create()?);
leaks::init(); leaks::init();
render::init()?; render::init()?;
clientmem::init()?; clientmem::init()?;
@ -119,6 +124,7 @@ fn main_() -> Result<(), MainError> {
let node_ids = NodeIds::default(); let node_ids = NodeIds::default();
let state = Rc::new(State { let state = Rc::new(State {
xkb_ctx, xkb_ctx,
forker: Default::default(),
default_keymap: xkb_keymap, default_keymap: xkb_keymap,
eng: engine.clone(), eng: engine.clone(),
el: el.clone(), el: el.clone(),
@ -145,11 +151,13 @@ fn main_() -> Result<(), MainError> {
mouse_ids: Default::default(), mouse_ids: Default::default(),
kb_handlers: Default::default(), kb_handlers: Default::default(),
}); });
forker.install(&state);
let config = config::ConfigProxy::default(&state); let config = config::ConfigProxy::default(&state);
state.config.set(Some(Rc::new(config))); state.config.set(Some(Rc::new(config)));
let _global_event_handler = engine.spawn(tasks::handle_backend_events(state.clone())); let _global_event_handler = engine.spawn(tasks::handle_backend_events(state.clone()));
let _slow_client_handler = engine.spawn(tasks::handle_slow_clients(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)?; let _backend = XorgBackend::new(&state)?;
el.run()?; el.run()?;
state.clients.clear(); state.clients.clear();

View file

@ -1,9 +1,12 @@
use crate::async_engine::{AsyncEngine, SpawnedFuture}; 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::client::{Client, Clients};
use crate::config::ConfigProxy; use crate::config::ConfigProxy;
use crate::cursor::ServerCursors; use crate::cursor::ServerCursors;
use crate::event_loop::EventLoop; use crate::event_loop::EventLoop;
use crate::forker::ForkerProxy;
use crate::globals::{Globals, GlobalsError, WaylandGlobal}; use crate::globals::{Globals, GlobalsError, WaylandGlobal};
use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_output::WlOutputGlobal;
use crate::ifs::wl_seat::{SeatIds, WlSeatGlobal}; use crate::ifs::wl_seat::{SeatIds, WlSeatGlobal};
@ -15,14 +18,15 @@ use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::linkedlist::LinkedList; use crate::utils::linkedlist::LinkedList;
use crate::utils::numcell::NumCell; use crate::utils::numcell::NumCell;
use crate::utils::queue::AsyncQueue; use crate::utils::queue::AsyncQueue;
use crate::xkbcommon::XkbKeymap;
use crate::{ErrorFmt, Wheel, XkbContext}; use crate::{ErrorFmt, Wheel, XkbContext};
use ahash::AHashMap; use ahash::AHashMap;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::rc::Rc; use std::rc::Rc;
use crate::xkbcommon::XkbKeymap;
pub struct State { pub struct State {
pub xkb_ctx: XkbContext, pub xkb_ctx: XkbContext,
pub forker: CloneCell<Option<Rc<ForkerProxy>>>,
pub default_keymap: Rc<XkbKeymap>, pub default_keymap: Rc<XkbKeymap>,
pub eng: Rc<AsyncEngine>, pub eng: Rc<AsyncEngine>,
pub el: Rc<EventLoop>, pub el: Rc<EventLoop>,
@ -53,13 +57,13 @@ pub struct State {
pub struct MouseData { pub struct MouseData {
pub handler: SpawnedFuture<()>, pub handler: SpawnedFuture<()>,
pub id: MouseId, pub id: MouseId,
pub data: Rc<DeviceHandlerData> pub data: Rc<DeviceHandlerData>,
} }
pub struct KeyboardData { pub struct KeyboardData {
pub handler: SpawnedFuture<()>, pub handler: SpawnedFuture<()>,
pub id: KeyboardId, pub id: KeyboardId,
pub data: Rc<DeviceHandlerData> pub data: Rc<DeviceHandlerData>,
} }
pub struct DeviceHandlerData { pub struct DeviceHandlerData {

View file

@ -1,8 +1,8 @@
use crate::backend::{BackendEvent, Output}; use crate::backend::{BackendEvent, Output};
use crate::tasks::device;
use crate::tasks::output::OutputHandler; use crate::tasks::output::OutputHandler;
use crate::State; use crate::State;
use std::rc::Rc; use std::rc::Rc;
use crate::tasks::device;
pub struct BackendEventHandler { pub struct BackendEventHandler {
pub state: Rc<State>, pub state: Rc<State>,

View file

@ -1,11 +1,11 @@
use crate::async_engine::SpawnedFuture;
use crate::backend::{Keyboard, KeyboardEvent, Mouse, MouseEvent}; use crate::backend::{Keyboard, KeyboardEvent, Mouse, MouseEvent};
use crate::config::ConfigProxy;
use crate::ifs::wl_seat::WlSeatGlobal; use crate::ifs::wl_seat::WlSeatGlobal;
use crate::state::{DeviceHandlerData, KeyboardData, MouseData};
use crate::utils::asyncevent::AsyncEvent; use crate::utils::asyncevent::AsyncEvent;
use crate::State; use crate::State;
use std::rc::Rc; use std::rc::Rc;
use crate::async_engine::SpawnedFuture;
use crate::config::ConfigProxy;
use crate::state::{DeviceHandlerData, KeyboardData, MouseData};
pub trait DeviceApi: 'static { pub trait DeviceApi: 'static {
type Event; type Event;
@ -40,11 +40,14 @@ impl DeviceApi for dyn Keyboard {
} }
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) { fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
state.kb_handlers.borrow_mut().insert(self.id(), KeyboardData { state.kb_handlers.borrow_mut().insert(
handler, self.id(),
id: self.id(), KeyboardData {
data, handler,
}); id: self.id(),
data,
},
);
} }
fn remove(&self, state: &State) { fn remove(&self, state: &State) {
@ -80,11 +83,14 @@ impl DeviceApi for dyn Mouse {
} }
fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) { fn add(&self, state: &State, handler: SpawnedFuture<()>, data: Rc<DeviceHandlerData>) {
state.mouse_handlers.borrow_mut().insert(self.id(), MouseData { state.mouse_handlers.borrow_mut().insert(
handler, self.id(),
id: self.id(), MouseData {
data, handler,
}); id: self.id(),
data,
},
);
} }
fn remove(&self, state: &State) { fn remove(&self, state: &State) {

View file

@ -1,7 +1,7 @@
mod backend; mod backend;
mod device;
mod output; mod output;
mod slow_clients; mod slow_clients;
mod device;
use crate::tasks::backend::BackendEventHandler; use crate::tasks::backend::BackendEventHandler;
use crate::tasks::slow_clients::SlowClientHandler; use crate::tasks::slow_clients::SlowClientHandler;

View file

@ -1,7 +1,7 @@
use crate::backend::{KeyState}; use crate::backend::KeyState;
use crate::cursor::KnownCursor; use crate::cursor::KnownCursor;
use crate::fixed::Fixed; 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::rect::Rect;
use crate::render::Renderer; use crate::render::Renderer;
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode}; 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::utils::linkedlist::{LinkedList, LinkedNode, NodeRef};
use crate::{NumCell, State}; use crate::{NumCell, State};
use ahash::AHashMap; use ahash::AHashMap;
use i4config::{Axis, Direction};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Formatter}; use std::fmt::{Debug, Formatter};
use std::mem; use std::mem;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::rc::Rc; use std::rc::Rc;
use i4config::{Axis, Direction};
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[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 children = self.child_nodes.borrow_mut();
let child = match children.get(&child.id()) { let child = match children.get(&child.id()) {
Some(c) => c, Some(c) => c,
@ -473,7 +478,9 @@ impl Node for ContainerNode {
ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down), ContainerSplit::Vertical => matches!(direction, Direction::Up | Direction::Down),
}; };
if !in_line { if !in_line {
self.parent.get().move_focus_from_child(seat, self, direction); self.parent
.get()
.move_focus_from_child(seat, self, direction);
return; return;
} }
let prev = match direction { let prev = match direction {
@ -484,12 +491,14 @@ impl Node for ContainerNode {
}; };
let sibling = match prev { let sibling = match prev {
true => child.prev(), true => child.prev(),
false => child.next() false => child.next(),
}; };
let sibling = match sibling { let sibling = match sibling {
Some(s) => s, Some(s) => s,
None => { None => {
self.parent.get().move_focus_from_child(seat, self, direction); self.parent
.get()
.move_focus_from_child(seat, self, direction);
return; return;
} }
}; };

View file

@ -13,11 +13,11 @@ use crate::utils::linkedlist::{LinkedList, LinkedNode};
use crate::xkbcommon::ModifierState; use crate::xkbcommon::ModifierState;
use crate::NumCell; use crate::NumCell;
pub use container::*; pub use container::*;
use i4config::Direction;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Display, Formatter}; use std::fmt::{Debug, Display, Formatter};
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use i4config::{Direction};
pub use workspace::*; pub use workspace::*;
mod container; mod container;
@ -93,7 +93,12 @@ pub trait Node {
let _ = direction; 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 _ = seat;
let _ = direction; let _ = direction;
let _ = child; let _ = child;

View file

@ -94,7 +94,6 @@ impl BufFdOut {
) -> Result<(), BufFdError> { ) -> Result<(), BufFdError> {
while buf.read_pos < buf.write_pos { while buf.read_pos < buf.write_pos {
if self.flush_sync(buf)? { if self.flush_sync(buf)? {
self.fd.writable().await?;
if timeout.is_none() { if timeout.is_none() {
*timeout = Some(self.fd.eng().timeout(5000)?.fuse()); *timeout = Some(self.fd.eng().timeout(5000)?.fuse());
} }
@ -157,6 +156,60 @@ impl BufFdOut {
} }
Ok(false) 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 { impl Drop for OutBuffer {

View file

@ -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 { pub fn new() -> Self {
Self::default() Self::default()
} }
@ -24,7 +24,10 @@ impl<K: Eq + Hash, V: Clone> CopyHashMap<K, V> {
self.map.borrow_mut().insert(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() self.map.borrow_mut().get(k).cloned()
} }

View file

@ -219,7 +219,8 @@ impl<T> NodeRef<T> {
} }
fn peer<F>(&self, peer: F) -> Option<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 { unsafe {
let data = self.data.as_ref(); let data = self.data.as_ref();

View file

@ -10,5 +10,5 @@ pub mod numcell;
pub mod ptr_ext; pub mod ptr_ext;
pub mod queue; pub mod queue;
pub mod smallmap; pub mod smallmap;
pub mod vec_ext;
pub mod stack; pub mod stack;
pub mod vec_ext;

View file

@ -10,6 +10,12 @@ pub struct AsyncQueue<T> {
waiters: RefCell<Vec<Waker>>, waiters: RefCell<Vec<Waker>>,
} }
impl<T> Default for AsyncQueue<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> AsyncQueue<T> { impl<T> AsyncQueue<T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {

View file

@ -1,5 +1,5 @@
use std::cell::UnsafeCell;
use crate::utils::ptr_ext::MutPtrExt; use crate::utils::ptr_ext::MutPtrExt;
use std::cell::UnsafeCell;
pub struct Stack<T> { pub struct Stack<T> {
vec: UnsafeCell<Vec<T>>, vec: UnsafeCell<Vec<T>>,
@ -21,8 +21,6 @@ impl<T> Stack<T> {
} }
pub fn pop(&self) -> Option<T> { pub fn pop(&self) -> Option<T> {
unsafe { unsafe { self.vec.get().deref_mut().pop() }
self.vec.get().deref_mut().pop()
}
} }
} }

View file

@ -124,8 +124,7 @@ impl XkbContext {
} }
fn raw_to_map(raw: *mut xkb_keymap) -> Result<Rc<XkbKeymap>, XkbCommonError> { fn raw_to_map(raw: *mut xkb_keymap) -> Result<Rc<XkbKeymap>, XkbCommonError> {
let res = let res = unsafe { xkb_keymap_get_as_string(raw, XKB_KEYMAP_FORMAT_TEXT_V1.raw() as _) };
unsafe { xkb_keymap_get_as_string(raw, XKB_KEYMAP_FORMAT_TEXT_V1.raw() as _) };
if res.is_null() { if res.is_null() {
unsafe { unsafe {
xkb_keymap_unref(raw); xkb_keymap_unref(raw);
@ -143,7 +142,8 @@ impl XkbContext {
uapi::fcntl_add_seals( uapi::fcntl_add_seals(
memfd.raw(), memfd.raw(),
c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE, c::F_SEAL_SEAL | c::F_SEAL_GROW | c::F_SEAL_SHRINK | c::F_SEAL_WRITE,
).unwrap(); )
.unwrap();
Ok(Rc::new(XkbKeymap { Ok(Rc::new(XkbKeymap {
keymap: raw, keymap: raw,
map: Rc::new(memfd), map: Rc::new(memfd),
@ -153,7 +153,13 @@ impl XkbContext {
pub fn keymap_from_str(&self, s: &str) -> Result<Rc<XkbKeymap>, XkbCommonError> { pub fn keymap_from_str(&self, s: &str) -> Result<Rc<XkbKeymap>, XkbCommonError> {
unsafe { 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() { if keymap.is_null() {
return Err(XkbCommonError::KeymapFromBuffer); return Err(XkbCommonError::KeymapFromBuffer);
} }