Skip to content

Commit 41dc432

Browse files
committed
Use cosmic-config for input configuration; allow dynamic changes
1 parent c958820 commit 41dc432

File tree

5 files changed

+94
-60
lines changed

5 files changed

+94
-60
lines changed

Cargo.lock

+17-14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ ron = "0.7"
3030
libsystemd = { version = "0.5", optional = true }
3131
wayland-backend = "0.1.0"
3232
wayland-scanner = "0.30.0"
33+
cosmic-config = { git = "https://github.com/pop-os/libcosmic/", rev = "4895b0c", features = ["calloop"] }
3334
cosmic-protocols = { git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"] }
34-
libcosmic = { git = "https://github.com/pop-os/libcosmic/", rev = "42d7baf", default-features = false }
35-
iced_tiny_skia = { git = "https://github.com/pop-os/libcosmic/", rev = "42d7baf" }
35+
libcosmic = { git = "https://github.com/pop-os/libcosmic/", rev = "4895b0c", default-features = false }
36+
iced_tiny_skia = { git = "https://github.com/pop-os/libcosmic/", rev = "4895b0c" }
3637
tiny-skia = "0.9"
3738
ordered-float = "3.0"
3839
glow = "0.11.2"

src/backend/kms/mod.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use smithay::{
5757
control::{connector, crtc, Device as ControlDevice, ModeTypeFlags},
5858
Device as _,
5959
},
60-
input::Libinput,
60+
input::{self, Libinput},
6161
nix::{fcntl::OFlag, sys::stat::dev_t},
6262
wayland_protocols::wp::{
6363
linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1,
@@ -97,6 +97,7 @@ const MIN_RENDER_TIME: Duration = Duration::from_millis(3);
9797
#[derive(Debug)]
9898
pub struct KmsState {
9999
devices: HashMap<DrmNode, Device>,
100+
pub input_devices: HashMap<String, input::Device>,
100101
pub api: GpuManager<GbmGlesBackend<GlowRenderer>>,
101102
pub primary: DrmNode,
102103
session: LibSeatSession,
@@ -171,8 +172,15 @@ pub fn init_backend(
171172
let libinput_event_source = event_loop
172173
.handle()
173174
.insert_source(libinput_backend, move |mut event, _, data| {
174-
if let &mut InputEvent::DeviceAdded { ref mut device } = &mut event {
175+
if let InputEvent::DeviceAdded { ref mut device } = &mut event {
175176
data.state.common.config.read_device(device);
177+
data.state
178+
.backend
179+
.kms()
180+
.input_devices
181+
.insert(device.name().into(), device.clone());
182+
} else if let InputEvent::DeviceRemoved { device } = &event {
183+
data.state.backend.kms().input_devices.remove(device.name());
176184
}
177185
data.state.process_input_event(event, true);
178186
for output in data.state.common.shell.outputs() {
@@ -362,6 +370,7 @@ pub fn init_backend(
362370
primary,
363371
session,
364372
devices: HashMap::new(),
373+
input_devices: HashMap::new(),
365374
});
366375

367376
// Create relative pointer global

src/config/mod.rs

+62-41
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
state::{BackendData, Data, State},
66
wayland::protocols::output_configuration::OutputConfigurationState,
77
};
8+
use cosmic_config::{ConfigGet, ConfigSet};
89
use serde::{Deserialize, Serialize};
910
use smithay::input::Seat;
1011
pub use smithay::{
@@ -34,6 +35,9 @@ pub use self::types::*;
3435
pub struct Config {
3536
pub static_conf: StaticConfig,
3637
pub dynamic_conf: DynamicConfig,
38+
pub config: cosmic_config::Config,
39+
pub xkb: XkbConfig,
40+
pub input_devices: HashMap<String, InputConfig>,
3741
}
3842

3943
#[derive(Debug, Deserialize)]
@@ -65,7 +69,6 @@ pub enum WorkspaceLayout {
6569
#[derive(Debug)]
6670
pub struct DynamicConfig {
6771
outputs: (Option<PathBuf>, OutputsConfig),
68-
inputs: (Option<PathBuf>, InputsConfig),
6972
}
7073

7174
#[derive(Debug, Deserialize, Serialize)]
@@ -152,18 +155,22 @@ impl OutputConfig {
152155
}
153156
}
154157

155-
#[derive(Debug, Deserialize, Serialize)]
156-
pub struct InputsConfig {
157-
xkb: XkbConfig,
158-
devices: HashMap<String, InputConfig>,
159-
}
160-
161158
impl Config {
162-
pub fn load() -> Config {
159+
pub fn load(loop_handle: &LoopHandle<'_, Data>) -> Config {
160+
let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap();
161+
let source = cosmic_config::calloop::ConfigWatchSource::new(&config).unwrap();
162+
loop_handle
163+
.insert_source(source, |(config, keys), (), shared_data| {
164+
config_changed(config, keys, &mut shared_data.state);
165+
})
166+
.expect("Failed to add cosmic-config to the event loop");
163167
let xdg = xdg::BaseDirectories::new().ok();
164168
Config {
165169
static_conf: Self::load_static(xdg.as_ref()),
166170
dynamic_conf: Self::load_dynamic(xdg.as_ref()),
171+
xkb: get_config(&config, "xkb-config"),
172+
input_devices: get_config(&config, "input-devices"),
173+
config,
167174
}
168175
}
169176

@@ -218,12 +225,8 @@ impl Config {
218225
xdg.and_then(|base| base.place_state_file("cosmic-comp/outputs.ron").ok());
219226
let outputs = Self::load_outputs(&output_path);
220227

221-
let input_path = xdg.and_then(|base| base.place_state_file("cosmic-comp/inputs.ron").ok());
222-
let inputs = Self::load_inputs(&input_path);
223-
224228
DynamicConfig {
225229
outputs: (output_path, outputs),
226-
inputs: (input_path, inputs),
227230
}
228231
}
229232

@@ -247,27 +250,6 @@ impl Config {
247250
}
248251
}
249252

250-
fn load_inputs(path: &Option<PathBuf>) -> InputsConfig {
251-
if let Some(path) = path.as_ref() {
252-
if path.exists() {
253-
match ron::de::from_reader(OpenOptions::new().read(true).open(path).unwrap()) {
254-
Ok(config) => return config,
255-
Err(err) => {
256-
warn!(?err, "Failed to read input_config, resetting..");
257-
if let Err(err) = std::fs::remove_file(path) {
258-
error!(?err, "Failed to remove input_config.");
259-
}
260-
}
261-
};
262-
}
263-
}
264-
265-
InputsConfig {
266-
xkb: XkbConfig::default(),
267-
devices: HashMap::new(),
268-
}
269-
}
270-
271253
pub fn read_outputs(
272254
&mut self,
273255
output_state: &mut OutputConfigurationState<State>,
@@ -422,17 +404,23 @@ impl Config {
422404
}
423405

424406
pub fn xkb_config(&self) -> XkbConfig {
425-
self.dynamic_conf.inputs().xkb.clone()
407+
self.xkb.clone()
426408
}
427409

428410
pub fn read_device(&mut self, device: &mut InputDevice) {
429411
use std::collections::hash_map::Entry;
430412

431-
let mut inputs = self.dynamic_conf.inputs_mut();
432-
match inputs.devices.entry(device.name().into()) {
413+
let mut config_changed = false;
414+
match self.input_devices.entry(device.name().into()) {
433415
Entry::Occupied(entry) => entry.get().update_device(device),
434416
Entry::Vacant(entry) => {
435417
entry.insert(InputConfig::for_device(device));
418+
config_changed = true;
419+
}
420+
}
421+
if config_changed {
422+
if let Err(err) = self.config.set("input-devices", &self.input_devices) {
423+
error!(?err, "Failed to write config 'input-devices'");
436424
}
437425
}
438426
}
@@ -483,12 +471,45 @@ impl DynamicConfig {
483471
pub fn outputs_mut<'a>(&'a mut self) -> PersistenceGuard<'a, OutputsConfig> {
484472
PersistenceGuard(self.outputs.0.clone(), &mut self.outputs.1)
485473
}
474+
}
486475

487-
pub fn inputs(&self) -> &InputsConfig {
488-
&self.inputs.1
489-
}
476+
fn get_config<T: Default + serde::de::DeserializeOwned>(
477+
config: &cosmic_config::Config,
478+
key: &str,
479+
) -> T {
480+
config.get(key).unwrap_or_else(|err| {
481+
error!(?err, "Failed to read config '{}'", key);
482+
T::default()
483+
})
484+
}
490485

491-
pub fn inputs_mut<'a>(&'a mut self) -> PersistenceGuard<'a, InputsConfig> {
492-
PersistenceGuard(self.inputs.0.clone(), &mut self.inputs.1)
486+
fn config_changed(config: cosmic_config::Config, keys: Vec<String>, state: &mut State) {
487+
for key in &keys {
488+
match key.as_str() {
489+
"xkb-config" => {
490+
let value = get_config::<XkbConfig>(&config, "xkb-config");
491+
for seat in state.common.seats().cloned().collect::<Vec<_>>().iter() {
492+
if let Some(keyboard) = seat.get_keyboard() {
493+
if let Err(err) = keyboard.set_xkb_config(state, (&value).into()) {
494+
error!(?err, "Failed to load provided xkb config");
495+
// TODO Revert to default?
496+
}
497+
}
498+
}
499+
state.common.config.xkb = value;
500+
}
501+
"input-devices" => {
502+
let value = get_config::<HashMap<String, InputConfig>>(&config, "input-devices");
503+
if let BackendData::Kms(ref mut kms_state) = &mut state.backend {
504+
for (name, device) in kms_state.input_devices.iter_mut() {
505+
if let Some(input_config) = value.get(name) {
506+
input_config.update_device(device);
507+
}
508+
}
509+
}
510+
state.common.config.input_devices = value;
511+
}
512+
_ => {}
513+
}
493514
}
494515
}

src/state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ impl State {
274274
.unwrap();
275275

276276
let clock = Clock::new().expect("Failed to initialize clock");
277-
let config = Config::load();
277+
let config = Config::load(&handle);
278278
let compositor_state = CompositorState::new::<Self>(dh);
279279
let data_device_state = DataDeviceState::new::<Self>(dh);
280280
let dmabuf_state = DmabufState::new();

0 commit comments

Comments
 (0)