Skip to content

Commit 6689b2c

Browse files
Use inotify for config change notifications
1 parent 4094e5c commit 6689b2c

2 files changed

Lines changed: 32 additions & 35 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ input = "0.8"
1818
libc = "0.2"
1919
input-linux = { version = "0.6", features = ["serde"] }
2020
input-linux-sys = "0.8"
21-
nix = { version = "0.27", features = ["poll", "signal"] }
21+
nix = { version = "0.27", features = ["poll", "signal", "inotify"] }
2222
privdrop = "0.5.3"
2323
serde = { version = "1", features = ["derive"] }
2424
toml = "0.8"

src/main.rs

Lines changed: 31 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
use std::{
2-
fs::{File, OpenOptions, read_to_string, self},
2+
fs::{File, OpenOptions, read_to_string},
33
os::{
4-
fd::AsRawFd,
4+
fd::{AsRawFd, AsFd},
55
unix::{io::OwnedFd, fs::OpenOptionsExt}
66
},
77
path::Path,
8-
time::SystemTime,
98
collections::HashMap,
109
cmp::min,
11-
mem,
12-
panic
10+
panic::{self, AssertUnwindSafe}
1311
};
14-
use std::os::fd::AsFd;
15-
use std::panic::AssertUnwindSafe;
1612
use cairo::{ImageSurface, Format, Context, Surface, Rectangle, FontFace};
1713
use rsvg::{Loader, CairoRenderer, SvgHandle};
1814
use drm::control::ClipRect;
@@ -30,7 +26,11 @@ use input_linux::{uinput::UInputHandle, EventKind, Key, SynchronizeKind};
3026
use input_linux_sys::{uinput_setup, input_id, timeval, input_event};
3127
use nix::{
3228
poll::{poll, PollFd, PollFlags},
33-
sys::signal::{Signal, SigSet}
29+
sys::{
30+
signal::{Signal, SigSet},
31+
inotify::{AddWatchFlags, InitFlags, Inotify}
32+
},
33+
errno::Errno
3434
};
3535
use privdrop::PrivDrop;
3636
use serde::Deserialize;
@@ -43,8 +43,7 @@ mod fonts;
4343

4444
use backlight::BacklightManager;
4545
use display::DrmBackend;
46-
use pixel_shift::PixelShiftManager;
47-
use pixel_shift::PIXEL_SHIFT_WIDTH_PX;
46+
use pixel_shift::{PixelShiftManager, PIXEL_SHIFT_WIDTH_PX};
4847
use fonts::{FontConfig, Pattern};
4948

5049
const DFR_WIDTH: i32 = 2008;
@@ -55,6 +54,7 @@ const BUTTON_COLOR_INACTIVE: f64 = 0.200;
5554
const BUTTON_COLOR_ACTIVE: f64 = 0.400;
5655
const ICON_SIZE: i32 = 48;
5756
const TIMEOUT_MS: i32 = 10 * 1000;
57+
const USER_CFG_PATH: &'static str = "/etc/tiny-dfr/config.toml";
5858

5959
#[derive(Deserialize)]
6060
#[serde(rename_all = "PascalCase")]
@@ -79,7 +79,6 @@ struct Config {
7979
show_button_outlines: bool,
8080
enable_pixel_shift: bool,
8181
font_face: FontFace,
82-
layers: [FunctionLayer; 2]
8382
}
8483

8584
enum ButtonImage {
@@ -321,9 +320,9 @@ fn load_font(name: &str) -> FontFace {
321320
FontFace::create_from_ft(&face).unwrap()
322321
}
323322

324-
fn load_config() -> Config {
323+
fn load_config() -> (Config, [FunctionLayer; 2]) {
325324
let mut base = toml::from_str::<ConfigProxy>(&read_to_string("/usr/share/tiny-dfr/config.toml").unwrap()).unwrap();
326-
let user = read_to_string("/etc/tiny-dfr/config.toml").map_err::<Error, _>(|e| e.into())
325+
let user = read_to_string(USER_CFG_PATH).map_err::<Error, _>(|e| e.into())
327326
.and_then(|r| Ok(toml::from_str::<ConfigProxy>(&r)?));
328327
if let Ok(user) = user {
329328
base.media_layer_default = user.media_layer_default.or(base.media_layer_default);
@@ -336,19 +335,12 @@ fn load_config() -> Config {
336335
let media_layer = FunctionLayer::with_config(base.media_layer_keys.unwrap());
337336
let fkey_layer = FunctionLayer::with_config(base.primary_layer_keys.unwrap());
338337
let layers = if base.media_layer_default.unwrap(){ [media_layer, fkey_layer] } else { [fkey_layer, media_layer] };
339-
Config {
338+
let cfg = Config {
340339
show_button_outlines: base.show_button_outlines.unwrap(),
341340
enable_pixel_shift: base.enable_pixel_shift.unwrap(),
342341
font_face: load_font(&base.font_template.unwrap()),
343-
layers
344-
}
345-
}
346-
347-
fn get_file_modified_time(path: &str) -> Option<SystemTime> {
348-
fs::metadata(path)
349-
.ok()
350-
.map(|metadata| metadata.modified().ok())
351-
.flatten()
342+
};
343+
(cfg, layers)
352344
}
353345

354346
fn main() {
@@ -381,7 +373,7 @@ fn main() {
381373
fn real_main(drm: &mut DrmBackend) {
382374
let mut uinput = UInputHandle::new(OpenOptions::new().write(true).open("/dev/uinput").unwrap());
383375
let mut backlight = BacklightManager::new();
384-
let mut cfg = load_config();
376+
let (mut cfg, mut layers) = load_config();
385377
let mut pixel_shift = PixelShiftManager::new();
386378

387379
// drop privileges to input and video group
@@ -406,14 +398,15 @@ fn real_main(drm: &mut DrmBackend) {
406398
let pollfd_tb = PollFd::new(&fd_tb, PollFlags::POLLIN);
407399
let pollfd_main = PollFd::new(&fd_main, PollFlags::POLLIN);
408400
uinput.set_evbit(EventKind::Key).unwrap();
409-
let config_path = "/etc/tiny-dfr/config.toml";
410-
let mut last_modified_time = get_file_modified_time(config_path);
411-
let mut layers = mem::take(&mut cfg.layers);
412401
for layer in &layers {
413402
for button in &layer.buttons {
414403
uinput.set_keybit(button.action).unwrap();
415404
}
416405
}
406+
let inotify_fd = Inotify::init(InitFlags::IN_NONBLOCK).unwrap();
407+
let flags = AddWatchFlags::IN_MOVED_TO | AddWatchFlags::IN_CLOSE;
408+
let cfg_watch_desc = inotify_fd.add_watch(USER_CFG_PATH, flags).unwrap();
409+
let pollfd_notify = PollFd::new(&inotify_fd, PollFlags::POLLIN);
417410
let mut dev_name_c = [0 as c_char; 80];
418411
let dev_name = "Dynamic Function Row Virtual Input Device".as_bytes();
419412
for i in 0..dev_name.len() {
@@ -434,17 +427,21 @@ fn real_main(drm: &mut DrmBackend) {
434427
let mut digitizer: Option<InputDevice> = None;
435428
let mut touches = HashMap::new();
436429
loop {
437-
let current_modified_time = get_file_modified_time(config_path);
438-
if current_modified_time != last_modified_time {
439-
cfg = load_config();
440-
layers = mem::take(&mut cfg.layers);
430+
let evts = match inotify_fd.read_events() {
431+
Ok(e) => e,
432+
Err(Errno::EAGAIN) => Vec::new(),
433+
r => r.unwrap(),
434+
};
435+
for evt in evts {
436+
if evt.wd != cfg_watch_desc {
437+
continue
438+
}
439+
(cfg, layers) = load_config();
441440
active_layer = 0;
442-
last_modified_time = current_modified_time;
443441
needs_complete_redraw = true;
444442
}
445443

446444
let mut next_timeout_ms = TIMEOUT_MS;
447-
448445
if cfg.enable_pixel_shift {
449446
let (pixel_shift_needs_redraw, pixel_shift_next_timeout_ms) = pixel_shift.update();
450447
if pixel_shift_needs_redraw {
@@ -466,7 +463,7 @@ fn real_main(drm: &mut DrmBackend) {
466463
needs_complete_redraw = false;
467464
}
468465

469-
poll(&mut [pollfd_tb, pollfd_main], next_timeout_ms).unwrap();
466+
poll(&mut [pollfd_tb, pollfd_main, pollfd_notify], next_timeout_ms).unwrap();
470467
input_tb.dispatch().unwrap();
471468
input_main.dispatch().unwrap();
472469
for event in &mut input_tb.clone().chain(input_main.clone()) {

0 commit comments

Comments
 (0)