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
99
Cargo.lock
generated
99
Cargo.lock
generated
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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> },
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
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_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())),
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -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();
|
||||||
|
|
|
||||||
12
src/state.rs
12
src/state.rs
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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>,
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue