all: split reusable components into workspace crates
This commit is contained in:
parent
2a079ed800
commit
657e7ce2f7
225 changed files with 7422 additions and 17602 deletions
124
src/config.rs
124
src/config.rs
|
|
@ -5,18 +5,14 @@ use crate::it::test_config::TEST_CONFIG_ENTRY;
|
|||
use {
|
||||
crate::{
|
||||
backend::{ConnectorId, DrmDeviceId, InputDeviceId},
|
||||
client::{Client, ClientCaps},
|
||||
config::handler::ConfigProxyHandler,
|
||||
ifs::wl_seat::SeatId,
|
||||
state::State,
|
||||
tree::{TileState, ToplevelData, ToplevelIdentifier},
|
||||
utils::{
|
||||
clonecell::CloneCell,
|
||||
nice::{JAY_NO_REALTIME, dont_allow_config_so},
|
||||
numcell::NumCell,
|
||||
ptr_ext::PtrExt,
|
||||
unlink_on_drop::UnlinkOnDrop,
|
||||
xrd::xrd,
|
||||
},
|
||||
},
|
||||
bincode::Options,
|
||||
|
|
@ -30,27 +26,9 @@ use {
|
|||
video::{Connector, DrmDevice},
|
||||
window::{self},
|
||||
},
|
||||
libloading::Library,
|
||||
std::{cell::Cell, io, mem, path::Path, ptr, rc::Rc},
|
||||
thiserror::Error,
|
||||
std::{cell::Cell, mem, ptr, rc::Rc},
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ConfigError {
|
||||
#[error("Could not load the config library")]
|
||||
CouldNotLoadLibrary(#[source] libloading::Error),
|
||||
#[error("Config library does not contain the entry symbol")]
|
||||
LibraryDoesNotContainEntry(#[source] libloading::Error),
|
||||
#[error("Could not determine the config directory")]
|
||||
ConfigDirNotSet,
|
||||
#[error("Could not copy the config file")]
|
||||
CopyConfigFile(#[source] io::Error),
|
||||
#[error("XDG_RUNTIME_DIR is not set")]
|
||||
XrdNotSet,
|
||||
#[error("Custom config.so is not permitted")]
|
||||
NotPermitted,
|
||||
}
|
||||
|
||||
pub struct ConfigProxy {
|
||||
handler: CloneCell<Option<Rc<ConfigProxyHandler>>>,
|
||||
}
|
||||
|
|
@ -181,16 +159,6 @@ impl ConfigProxy {
|
|||
self.handler.get()?.initial_tile_state(data)
|
||||
}
|
||||
|
||||
pub fn update_capabilities(
|
||||
&self,
|
||||
data: &Rc<Client>,
|
||||
bounding_caps: ClientCaps,
|
||||
set_bounding_caps: bool,
|
||||
) {
|
||||
if let Some(handler) = self.handler.get() {
|
||||
handler.update_capabilities(data, bounding_caps, set_bounding_caps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ConfigProxy {
|
||||
|
|
@ -215,18 +183,11 @@ unsafe extern "C" fn default_client_init(
|
|||
}
|
||||
|
||||
impl ConfigProxy {
|
||||
fn new(
|
||||
lib: Option<Library>,
|
||||
entry: &ConfigEntry,
|
||||
state: &Rc<State>,
|
||||
path: Option<String>,
|
||||
) -> Self {
|
||||
fn new(entry: &ConfigEntry, state: &Rc<State>) -> Self {
|
||||
let version = entry.version.min(VERSION);
|
||||
let data = Rc::new(ConfigProxyHandler {
|
||||
path,
|
||||
client_data: Cell::new(ptr::null()),
|
||||
dropped: Cell::new(false),
|
||||
_lib: lib,
|
||||
_version: version,
|
||||
unref: entry.unref,
|
||||
handle_msg: entry.handle_msg,
|
||||
|
|
@ -249,8 +210,6 @@ impl ConfigProxy {
|
|||
client_matchers: Default::default(),
|
||||
client_matcher_cache: Default::default(),
|
||||
client_matcher_leafs: Default::default(),
|
||||
client_matcher_capabilities: Default::default(),
|
||||
client_matcher_bounding_capabilities: Default::default(),
|
||||
window_matcher_ids: NumCell::new(1),
|
||||
window_matchers: Default::default(),
|
||||
window_matcher_cache: Default::default(),
|
||||
|
|
@ -291,75 +250,12 @@ impl ConfigProxy {
|
|||
unref: jay_config::_private::client::unref,
|
||||
handle_msg: jay_config::_private::client::handle_msg,
|
||||
};
|
||||
Self::new(None, &entry, state, None)
|
||||
Self::new(&entry, state)
|
||||
}
|
||||
|
||||
#[cfg(feature = "it")]
|
||||
pub fn for_test(state: &Rc<State>) -> Self {
|
||||
Self::new(None, &TEST_CONFIG_ENTRY, state, None)
|
||||
}
|
||||
|
||||
pub fn from_config_dir(state: &Rc<State>) -> Result<Self, ConfigError> {
|
||||
if dont_allow_config_so() {
|
||||
if have_config_so(state.config_dir.as_deref()) {
|
||||
log::warn!("Not loading config.so because");
|
||||
log::warn!(" 1. Jay was started with CAP_SYS_NICE");
|
||||
log::warn!(" 2. Jay was not started with {}=1", JAY_NO_REALTIME);
|
||||
log::warn!(" 3. The scheduler was elevated to SCHED_RR");
|
||||
log::warn!(
|
||||
" 4. Jay was not compiled with {}=1",
|
||||
jay_allow_realtime_config_so!(),
|
||||
);
|
||||
}
|
||||
return Err(ConfigError::NotPermitted);
|
||||
}
|
||||
let dir = match state.config_dir.as_deref() {
|
||||
Some(d) => d,
|
||||
_ => return Err(ConfigError::ConfigDirNotSet),
|
||||
};
|
||||
let file = format!("{}/{CONFIG_SO}", dir);
|
||||
unsafe { Self::from_file(&file, state) }
|
||||
}
|
||||
|
||||
pub unsafe fn from_file(path: &str, state: &Rc<State>) -> Result<Self, ConfigError> {
|
||||
// Here we have to do a bit of a dance to support reloading. glibc will
|
||||
// never load a library twice unless it has been unloaded in between.
|
||||
// glibc identifies libraries by their file path and by their inode
|
||||
// number. If either of those match, glibc considers the libraries
|
||||
// identical. If the inode has not changed then this is not a problem
|
||||
// for us since we don't want glibc to do any unnecessary work.
|
||||
// However, if the user has created a new config with a new inode, then
|
||||
// glibc will still not reload the library if we try to load it from
|
||||
// the canonical location ~/.config/jay/config.so since it already has
|
||||
// a library with that path loaded. To work around this, create a
|
||||
// temporary copy with an incrementing number and load the library
|
||||
// from there.
|
||||
let xrd = match xrd() {
|
||||
Some(x) => x,
|
||||
_ => return Err(ConfigError::XrdNotSet),
|
||||
};
|
||||
let copy = format!(
|
||||
"{}/.jay_config.so.{}.{}",
|
||||
xrd,
|
||||
uapi::getpid(),
|
||||
state.config_file_id.fetch_add(1)
|
||||
);
|
||||
let _ = uapi::unlink(copy.as_str());
|
||||
if let Err(e) = std::fs::copy(path, ©) {
|
||||
return Err(ConfigError::CopyConfigFile(e));
|
||||
}
|
||||
let unlink = UnlinkOnDrop(©);
|
||||
let lib = match unsafe { Library::new(©) } {
|
||||
Ok(l) => l,
|
||||
Err(e) => return Err(ConfigError::CouldNotLoadLibrary(e)),
|
||||
};
|
||||
let entry = unsafe { lib.get::<&'static ConfigEntry>(b"JAY_CONFIG_ENTRY_V1\0") };
|
||||
let entry = match entry {
|
||||
Ok(e) => *e,
|
||||
Err(e) => return Err(ConfigError::LibraryDoesNotContainEntry(e)),
|
||||
};
|
||||
mem::forget(unlink);
|
||||
Ok(Self::new(Some(lib), entry, state, Some(copy)))
|
||||
Self::new(&TEST_CONFIG_ENTRY, state)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -388,15 +284,3 @@ pub struct InvokedShortcut {
|
|||
pub effective_mods: Modifiers,
|
||||
pub sym: KeySym,
|
||||
}
|
||||
|
||||
const CONFIG_SO: &str = "config.so";
|
||||
|
||||
pub fn have_config_so(config_dir: Option<&str>) -> bool {
|
||||
let Some(dir) = config_dir else {
|
||||
return false;
|
||||
};
|
||||
let mut dir = dir.to_owned();
|
||||
dir.push_str("/");
|
||||
dir.push_str(CONFIG_SO);
|
||||
Path::new(&dir).exists()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue