11use 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 ;
1612use cairo:: { ImageSurface , Format , Context , Surface , Rectangle , FontFace } ;
1713use rsvg:: { Loader , CairoRenderer , SvgHandle } ;
1814use drm:: control:: ClipRect ;
@@ -30,7 +26,11 @@ use input_linux::{uinput::UInputHandle, EventKind, Key, SynchronizeKind};
3026use input_linux_sys:: { uinput_setup, input_id, timeval, input_event} ;
3127use 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} ;
3535use privdrop:: PrivDrop ;
3636use serde:: Deserialize ;
@@ -43,8 +43,7 @@ mod fonts;
4343
4444use backlight:: BacklightManager ;
4545use display:: DrmBackend ;
46- use pixel_shift:: PixelShiftManager ;
47- use pixel_shift:: PIXEL_SHIFT_WIDTH_PX ;
46+ use pixel_shift:: { PixelShiftManager , PIXEL_SHIFT_WIDTH_PX } ;
4847use fonts:: { FontConfig , Pattern } ;
4948
5049const DFR_WIDTH : i32 = 2008 ;
@@ -55,6 +54,7 @@ const BUTTON_COLOR_INACTIVE: f64 = 0.200;
5554const BUTTON_COLOR_ACTIVE : f64 = 0.400 ;
5655const ICON_SIZE : i32 = 48 ;
5756const 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
8584enum 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
354346fn main ( ) {
@@ -381,7 +373,7 @@ fn main() {
381373fn 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