11use std:: {
2- fs:: { File , OpenOptions , read_to_string } ,
2+ fs:: { File , OpenOptions } ,
33 os:: {
44 fd:: { AsRawFd , AsFd } ,
55 unix:: { io:: OwnedFd , fs:: OpenOptionsExt }
@@ -9,10 +9,10 @@ use std::{
99 cmp:: min,
1010 panic:: { self , AssertUnwindSafe }
1111} ;
12- use cairo:: { ImageSurface , Format , Context , Surface , Rectangle , FontFace , Antialias } ;
12+ use cairo:: { ImageSurface , Format , Context , Surface , Rectangle , Antialias } ;
1313use rsvg:: { Loader , CairoRenderer , SvgHandle } ;
1414use drm:: control:: ClipRect ;
15- use anyhow:: { Error , Result } ;
15+ use anyhow:: Result ;
1616use input:: {
1717 Libinput , LibinputInterface , Device as InputDevice ,
1818 event:: {
@@ -26,25 +26,21 @@ use input_linux::{uinput::UInputHandle, EventKind, Key, SynchronizeKind};
2626use input_linux_sys:: { uinput_setup, input_id, timeval, input_event} ;
2727use nix:: {
2828 poll:: { poll, PollFd , PollFlags } ,
29- sys:: {
30- signal:: { Signal , SigSet } ,
31- inotify:: { AddWatchFlags , InitFlags , Inotify , WatchDescriptor }
32- } ,
33- errno:: Errno
29+ sys:: signal:: { Signal , SigSet } ,
3430} ;
3531use privdrop:: PrivDrop ;
36- use serde:: Deserialize ;
37- use freetype:: Library as FtLibrary ;
3832
3933mod backlight;
4034mod display;
4135mod pixel_shift;
4236mod fonts;
37+ mod config;
4338
4439use backlight:: BacklightManager ;
4540use display:: DrmBackend ;
4641use pixel_shift:: { PixelShiftManager , PIXEL_SHIFT_WIDTH_PX } ;
47- use fonts:: { FontConfig , Pattern } ;
42+ use config:: { ButtonConfig , Config } ;
43+ use crate :: config:: ConfigManager ;
4844
4945const DFR_WIDTH : i32 = 2008 ;
5046const DFR_HEIGHT : i32 = 60 ;
@@ -54,33 +50,6 @@ const BUTTON_COLOR_INACTIVE: f64 = 0.200;
5450const BUTTON_COLOR_ACTIVE : f64 = 0.400 ;
5551const ICON_SIZE : i32 = 48 ;
5652const TIMEOUT_MS : i32 = 10 * 1000 ;
57- const USER_CFG_PATH : & ' static str = "/etc/tiny-dfr/config.toml" ;
58-
59- #[ derive( Deserialize ) ]
60- #[ serde( rename_all = "PascalCase" ) ]
61- struct ConfigProxy {
62- media_layer_default : Option < bool > ,
63- show_button_outlines : Option < bool > ,
64- enable_pixel_shift : Option < bool > ,
65- font_template : Option < String > ,
66- primary_layer_keys : Option < Vec < ButtonConfig > > ,
67- media_layer_keys : Option < Vec < ButtonConfig > >
68- }
69-
70- #[ derive( Deserialize ) ]
71- #[ serde( rename_all = "PascalCase" ) ]
72- struct ButtonConfig {
73- #[ serde( alias = "Svg" ) ]
74- icon : Option < String > ,
75- text : Option < String > ,
76- action : Key
77- }
78-
79- struct Config {
80- show_button_outlines : bool ,
81- enable_pixel_shift : bool ,
82- font_face : FontFace ,
83- }
8453
8554enum ButtonImage {
8655 Text ( String ) ,
@@ -184,7 +153,7 @@ impl Button {
184153}
185154
186155#[ derive( Default ) ]
187- struct FunctionLayer {
156+ pub struct FunctionLayer {
188157 buttons : Vec < Button >
189158}
190159
@@ -338,41 +307,6 @@ fn toggle_key<F>(uinput: &mut UInputHandle<F>, code: Key, value: i32) where F: A
338307 emit ( uinput, EventKind :: Synchronize , SynchronizeKind :: Report as u16 , 0 ) ;
339308}
340309
341- fn load_font ( name : & str ) -> FontFace {
342- let fontconfig = FontConfig :: new ( ) ;
343- let mut pattern = Pattern :: new ( name) ;
344- fontconfig. perform_substitutions ( & mut pattern) ;
345- let pat_match = fontconfig. match_pattern ( & pattern) ;
346- let file_name = pat_match. get_file_name ( ) ;
347- let file_idx = pat_match. get_font_index ( ) ;
348- let ft_library = FtLibrary :: init ( ) . unwrap ( ) ;
349- let face = ft_library. new_face ( file_name, file_idx) . unwrap ( ) ;
350- FontFace :: create_from_ft ( & face) . unwrap ( )
351- }
352-
353- fn load_config ( ) -> ( Config , [ FunctionLayer ; 2 ] ) {
354- let mut base = toml:: from_str :: < ConfigProxy > ( & read_to_string ( "/usr/share/tiny-dfr/config.toml" ) . unwrap ( ) ) . unwrap ( ) ;
355- let user = read_to_string ( USER_CFG_PATH ) . map_err :: < Error , _ > ( |e| e. into ( ) )
356- . and_then ( |r| Ok ( toml:: from_str :: < ConfigProxy > ( & r) ?) ) ;
357- if let Ok ( user) = user {
358- base. media_layer_default = user. media_layer_default . or ( base. media_layer_default ) ;
359- base. show_button_outlines = user. show_button_outlines . or ( base. show_button_outlines ) ;
360- base. enable_pixel_shift = user. enable_pixel_shift . or ( base. enable_pixel_shift ) ;
361- base. font_template = user. font_template . or ( base. font_template ) ;
362- base. media_layer_keys = user. media_layer_keys . or ( base. media_layer_keys ) ;
363- base. primary_layer_keys = user. primary_layer_keys . or ( base. primary_layer_keys ) ;
364- } ;
365- let media_layer = FunctionLayer :: with_config ( base. media_layer_keys . unwrap ( ) ) ;
366- let fkey_layer = FunctionLayer :: with_config ( base. primary_layer_keys . unwrap ( ) ) ;
367- let layers = if base. media_layer_default . unwrap ( ) { [ media_layer, fkey_layer] } else { [ fkey_layer, media_layer] } ;
368- let cfg = Config {
369- show_button_outlines : base. show_button_outlines . unwrap ( ) ,
370- enable_pixel_shift : base. enable_pixel_shift . unwrap ( ) ,
371- font_face : load_font ( & base. font_template . unwrap ( ) ) ,
372- } ;
373- ( cfg, layers)
374- }
375-
376310fn main ( ) {
377311 let mut drm = DrmBackend :: open_card ( ) . unwrap ( ) ;
378312 let _ = panic:: catch_unwind ( AssertUnwindSafe ( || {
@@ -400,15 +334,11 @@ fn main() {
400334 sigset. wait ( ) . unwrap ( ) ;
401335}
402336
403- fn arm_inotify ( inotify_fd : & Inotify ) -> WatchDescriptor {
404- let flags = AddWatchFlags :: IN_MOVED_TO | AddWatchFlags :: IN_CLOSE | AddWatchFlags :: IN_ONESHOT ;
405- inotify_fd. add_watch ( USER_CFG_PATH , flags) . unwrap ( )
406- }
407-
408337fn real_main ( drm : & mut DrmBackend ) {
409338 let mut uinput = UInputHandle :: new ( OpenOptions :: new ( ) . write ( true ) . open ( "/dev/uinput" ) . unwrap ( ) ) ;
410339 let mut backlight = BacklightManager :: new ( ) ;
411- let ( mut cfg, mut layers) = load_config ( ) ;
340+ let mut cfg_mgr = ConfigManager :: new ( ) ;
341+ let ( mut cfg, mut layers) = cfg_mgr. load_config ( ) ;
412342 let mut pixel_shift = PixelShiftManager :: new ( ) ;
413343
414344 // drop privileges to input and video group
@@ -438,9 +368,6 @@ fn real_main(drm: &mut DrmBackend) {
438368 uinput. set_keybit ( button. action ) . unwrap ( ) ;
439369 }
440370 }
441- let inotify_fd = Inotify :: init ( InitFlags :: IN_NONBLOCK ) . unwrap ( ) ;
442- let mut cfg_watch_desc = arm_inotify ( & inotify_fd) ;
443- let pollfd_notify = PollFd :: new ( & inotify_fd, PollFlags :: POLLIN ) ;
444371 let mut dev_name_c = [ 0 as c_char ; 80 ] ;
445372 let dev_name = "Dynamic Function Row Virtual Input Device" . as_bytes ( ) ;
446373 for i in 0 ..dev_name. len ( ) {
@@ -461,19 +388,9 @@ fn real_main(drm: &mut DrmBackend) {
461388 let mut digitizer: Option < InputDevice > = None ;
462389 let mut touches = HashMap :: new ( ) ;
463390 loop {
464- let evts = match inotify_fd. read_events ( ) {
465- Ok ( e) => e,
466- Err ( Errno :: EAGAIN ) => Vec :: new ( ) ,
467- r => r. unwrap ( ) ,
468- } ;
469- for evt in evts {
470- if evt. wd != cfg_watch_desc {
471- continue
472- }
473- ( cfg, layers) = load_config ( ) ;
391+ if cfg_mgr. update_config ( & mut cfg, & mut layers) {
474392 active_layer = 0 ;
475393 needs_complete_redraw = true ;
476- cfg_watch_desc = arm_inotify ( & inotify_fd) ;
477394 }
478395
479396 let mut next_timeout_ms = TIMEOUT_MS ;
@@ -498,7 +415,7 @@ fn real_main(drm: &mut DrmBackend) {
498415 needs_complete_redraw = false ;
499416 }
500417
501- poll ( & mut [ pollfd_tb, pollfd_main, pollfd_notify ] , next_timeout_ms) . unwrap ( ) ;
418+ poll ( & mut [ pollfd_tb, pollfd_main, cfg_mgr . pollfd ( ) ] , next_timeout_ms) . unwrap ( ) ;
502419 input_tb. dispatch ( ) . unwrap ( ) ;
503420 input_main. dispatch ( ) . unwrap ( ) ;
504421 for event in & mut input_tb. clone ( ) . chain ( input_main. clone ( ) ) {
0 commit comments