Use cosmic-config for input configuration; allow dynamic changes

This commit is contained in:
Ian Douglas Scott 2023-07-28 12:54:02 -07:00
parent 75912df270
commit 0f5d654535
5 changed files with 94 additions and 60 deletions

31
Cargo.lock generated
View file

@ -481,6 +481,7 @@ dependencies = [
"bitflags 1.3.2",
"bytemuck",
"calloop",
"cosmic-config",
"cosmic-protocols",
"edid-rs",
"egui",
@ -524,9 +525,10 @@ dependencies = [
[[package]]
name = "cosmic-config"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"atomicwrites",
"calloop",
"cosmic-config-derive",
"dirs 5.0.1",
"iced_futures",
@ -538,7 +540,7 @@ dependencies = [
[[package]]
name = "cosmic-config-derive"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"quote",
"syn 1.0.109",
@ -578,7 +580,7 @@ dependencies = [
[[package]]
name = "cosmic-theme"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"anyhow",
"cosmic-config",
@ -1746,7 +1748,7 @@ dependencies = [
[[package]]
name = "iced"
version = "0.9.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"iced_core",
"iced_futures",
@ -1759,7 +1761,7 @@ dependencies = [
[[package]]
name = "iced_core"
version = "0.9.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"bitflags 1.3.2",
"instant",
@ -1772,7 +1774,7 @@ dependencies = [
[[package]]
name = "iced_futures"
version = "0.6.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"futures",
"iced_core",
@ -1784,7 +1786,7 @@ dependencies = [
[[package]]
name = "iced_graphics"
version = "0.8.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"bitflags 1.3.2",
"bytemuck",
@ -1801,7 +1803,7 @@ dependencies = [
[[package]]
name = "iced_renderer"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"iced_graphics",
"iced_tiny_skia",
@ -1813,7 +1815,7 @@ dependencies = [
[[package]]
name = "iced_runtime"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"iced_core",
"iced_futures",
@ -1823,7 +1825,7 @@ dependencies = [
[[package]]
name = "iced_style"
version = "0.8.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"iced_core",
"once_cell",
@ -1833,7 +1835,7 @@ dependencies = [
[[package]]
name = "iced_tiny_skia"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"bytemuck",
"cosmic-text",
@ -1851,7 +1853,7 @@ dependencies = [
[[package]]
name = "iced_wgpu"
version = "0.10.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"bitflags 1.3.2",
"bytemuck",
@ -1872,7 +1874,7 @@ dependencies = [
[[package]]
name = "iced_widget"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"iced_renderer",
"iced_runtime",
@ -2167,7 +2169,7 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
[[package]]
name = "libcosmic"
version = "0.1.0"
source = "git+https://github.com/pop-os/libcosmic/?rev=42d7baf#42d7baf0d5cb14ab476120be9dfcaea9bd1d0be4"
source = "git+https://github.com/pop-os/libcosmic/?rev=4895b0c#4895b0c9bda9e46fc7db173e239d155dac957186"
dependencies = [
"apply",
"cosmic-config",
@ -2186,6 +2188,7 @@ dependencies = [
"lazy_static",
"palette",
"slotmap",
"thiserror",
"tracing",
]

View file

@ -30,9 +30,10 @@ ron = "0.7"
libsystemd = { version = "0.5", optional = true }
wayland-backend = "0.1.0"
wayland-scanner = "0.30.0"
cosmic-config = { git = "https://github.com/pop-os/libcosmic/", rev = "4895b0c", features = ["calloop"] }
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"] }
libcosmic = { git = "https://github.com/pop-os/libcosmic/", rev = "42d7baf", default-features = false }
iced_tiny_skia = { git = "https://github.com/pop-os/libcosmic/", rev = "42d7baf" }
libcosmic = { git = "https://github.com/pop-os/libcosmic/", rev = "4895b0c", default-features = false }
iced_tiny_skia = { git = "https://github.com/pop-os/libcosmic/", rev = "4895b0c" }
tiny-skia = "0.9"
ordered-float = "3.0"
glow = "0.11.2"

View file

@ -57,7 +57,7 @@ use smithay::{
control::{connector, crtc, Device as ControlDevice, ModeTypeFlags},
Device as _,
},
input::Libinput,
input::{self, Libinput},
nix::{fcntl::OFlag, sys::stat::dev_t},
wayland_protocols::wp::{
linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1,
@ -97,6 +97,7 @@ const MIN_RENDER_TIME: Duration = Duration::from_millis(3);
#[derive(Debug)]
pub struct KmsState {
devices: HashMap<DrmNode, Device>,
pub input_devices: HashMap<String, input::Device>,
pub api: GpuManager<GbmGlesBackend<GlowRenderer>>,
pub primary: DrmNode,
session: LibSeatSession,
@ -172,8 +173,15 @@ pub fn init_backend(
let libinput_event_source = event_loop
.handle()
.insert_source(libinput_backend, move |mut event, _, data| {
if let &mut InputEvent::DeviceAdded { ref mut device } = &mut event {
if let InputEvent::DeviceAdded { ref mut device } = &mut event {
data.state.common.config.read_device(device);
data.state
.backend
.kms()
.input_devices
.insert(device.name().into(), device.clone());
} else if let InputEvent::DeviceRemoved { device } = &event {
data.state.backend.kms().input_devices.remove(device.name());
}
data.state.process_input_event(event, true);
for output in data.state.common.shell.outputs() {
@ -363,6 +371,7 @@ pub fn init_backend(
primary,
session,
devices: HashMap::new(),
input_devices: HashMap::new(),
});
// Create relative pointer global

View file

@ -5,6 +5,7 @@ use crate::{
state::{BackendData, Data, State},
wayland::protocols::output_configuration::OutputConfigurationState,
};
use cosmic_config::{ConfigGet, ConfigSet};
use serde::{Deserialize, Serialize};
use smithay::input::Seat;
pub use smithay::{
@ -34,6 +35,9 @@ pub use self::types::*;
pub struct Config {
pub static_conf: StaticConfig,
pub dynamic_conf: DynamicConfig,
pub config: cosmic_config::Config,
pub xkb: XkbConfig,
pub input_devices: HashMap<String, InputConfig>,
}
#[derive(Debug, Deserialize)]
@ -65,7 +69,6 @@ pub enum WorkspaceLayout {
#[derive(Debug)]
pub struct DynamicConfig {
outputs: (Option<PathBuf>, OutputsConfig),
inputs: (Option<PathBuf>, InputsConfig),
}
#[derive(Debug, Deserialize, Serialize)]
@ -152,18 +155,22 @@ impl OutputConfig {
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct InputsConfig {
xkb: XkbConfig,
devices: HashMap<String, InputConfig>,
}
impl Config {
pub fn load() -> Config {
pub fn load(loop_handle: &LoopHandle<'_, Data>) -> Config {
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
let source = cosmic_config::calloop::ConfigWatchSource::new(&config).unwrap();
loop_handle
.insert_source(source, |(config, keys), (), shared_data| {
config_changed(config, keys, &mut shared_data.state);
})
.expect("Failed to add cosmic-config to the event loop");
let xdg = xdg::BaseDirectories::new().ok();
Config {
static_conf: Self::load_static(xdg.as_ref()),
dynamic_conf: Self::load_dynamic(xdg.as_ref()),
xkb: get_config(&config, "xkb-config"),
input_devices: get_config(&config, "input-devices"),
config,
}
}
@ -218,12 +225,8 @@ impl Config {
xdg.and_then(|base| base.place_state_file("cosmic-comp/outputs.ron").ok());
let outputs = Self::load_outputs(&output_path);
let input_path = xdg.and_then(|base| base.place_state_file("cosmic-comp/inputs.ron").ok());
let inputs = Self::load_inputs(&input_path);
DynamicConfig {
outputs: (output_path, outputs),
inputs: (input_path, inputs),
}
}
@ -247,27 +250,6 @@ impl Config {
}
}
fn load_inputs(path: &Option<PathBuf>) -> InputsConfig {
if let Some(path) = path.as_ref() {
if path.exists() {
match ron::de::from_reader(OpenOptions::new().read(true).open(path).unwrap()) {
Ok(config) => return config,
Err(err) => {
warn!(?err, "Failed to read input_config, resetting..");
if let Err(err) = std::fs::remove_file(path) {
error!(?err, "Failed to remove input_config.");
}
}
};
}
}
InputsConfig {
xkb: XkbConfig::default(),
devices: HashMap::new(),
}
}
pub fn read_outputs(
&mut self,
output_state: &mut OutputConfigurationState<State>,
@ -422,17 +404,23 @@ impl Config {
}
pub fn xkb_config(&self) -> XkbConfig {
self.dynamic_conf.inputs().xkb.clone()
self.xkb.clone()
}
pub fn read_device(&mut self, device: &mut InputDevice) {
use std::collections::hash_map::Entry;
let mut inputs = self.dynamic_conf.inputs_mut();
match inputs.devices.entry(device.name().into()) {
let mut config_changed = false;
match self.input_devices.entry(device.name().into()) {
Entry::Occupied(entry) => entry.get().update_device(device),
Entry::Vacant(entry) => {
entry.insert(InputConfig::for_device(device));
config_changed = true;
}
}
if config_changed {
if let Err(err) = self.config.set("input-devices", &self.input_devices) {
error!(?err, "Failed to write config 'input-devices'");
}
}
}
@ -483,12 +471,45 @@ impl DynamicConfig {
pub fn outputs_mut<'a>(&'a mut self) -> PersistenceGuard<'a, OutputsConfig> {
PersistenceGuard(self.outputs.0.clone(), &mut self.outputs.1)
}
}
pub fn inputs(&self) -> &InputsConfig {
&self.inputs.1
fn get_config<T: Default + serde::de::DeserializeOwned>(
config: &cosmic_config::Config,
key: &str,
) -> T {
config.get(key).unwrap_or_else(|err| {
error!(?err, "Failed to read config '{}'", key);
T::default()
})
}
fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut State) {
for key in &keys {
match key.as_str() {
"xkb-config" => {
let value = get_config::<XkbConfig>(&config, "xkb-config");
for seat in state.common.seats().cloned().collect::<Vec<_>>().iter() {
if let Some(keyboard) = seat.get_keyboard() {
if let Err(err) = keyboard.set_xkb_config(state, (&value).into()) {
error!(?err, "Failed to load provided xkb config");
// TODO Revert to default?
}
}
}
state.common.config.xkb = value;
}
"input-devices" => {
let value = get_config::<HashMap<String, InputConfig>>(&config, "input-devices");
if let BackendData::Kms(ref mut kms_state) = &mut state.backend {
for (name, device) in kms_state.input_devices.iter_mut() {
if let Some(input_config) = value.get(name) {
input_config.update_device(device);
}
}
}
state.common.config.input_devices = value;
}
_ => {}
}
pub fn inputs_mut<'a>(&'a mut self) -> PersistenceGuard<'a, InputsConfig> {
PersistenceGuard(self.inputs.0.clone(), &mut self.inputs.1)
}
}

View file

@ -278,7 +278,7 @@ impl State {
.unwrap();
let clock = Clock::new().expect("Failed to initialize clock");
let config = Config::load();
let config = Config::load(&handle);
let compositor_state = CompositorState::new::<Self>(dh);
let data_device_state = DataDeviceState::new::<Self>(dh);
let dmabuf_state = DmabufState::new();