@@ -6,6 +6,7 @@ use std::{
66 } ,
77 path:: Path ,
88 collections:: HashMap ,
9+ cmp:: min
910} ;
1011use std:: os:: fd:: AsFd ;
1112use cairo:: {
@@ -32,26 +33,31 @@ use serde::Deserialize;
3233
3334mod backlight;
3435mod display;
36+ mod pixel_shift;
3537
3638use backlight:: BacklightManager ;
3739use display:: DrmBackend ;
40+ use pixel_shift:: PixelShiftManager ;
41+ use pixel_shift:: PIXEL_SHIFT_WIDTH_PX ;
3842
3943const DFR_WIDTH : i32 = 2008 ;
4044const DFR_HEIGHT : i32 = 64 ;
4145const BUTTON_COLOR_INACTIVE : f64 = 0.200 ;
4246const BUTTON_COLOR_ACTIVE : f64 = 0.400 ;
43- const TIMEOUT_MS : i32 = 30 * 1000 ;
47+ const TIMEOUT_MS : i32 = 10 * 1000 ;
4448
4549#[ derive( Deserialize ) ]
4650#[ serde( rename_all = "PascalCase" ) ]
4751struct ConfigProxy {
4852 media_layer_default : Option < bool > ,
49- show_button_outlines : Option < bool >
53+ show_button_outlines : Option < bool > ,
54+ enable_pixel_shift : Option < bool >
5055}
5156
5257struct Config {
5358 media_layer_default : bool ,
54- show_button_outlines : bool
59+ show_button_outlines : bool ,
60+ enable_pixel_shift : bool
5561}
5662
5763enum ButtonImage {
@@ -76,12 +82,12 @@ impl Button {
7682 action, image : ButtonImage :: Svg ( svg)
7783 }
7884 }
79- fn render ( & self , c : & Context , left_edge : f64 , button_width : f64 ) {
85+ fn render ( & self , c : & Context , button_left_edge : f64 , button_width : f64 , y_shift : f64 ) {
8086 match & self . image {
8187 ButtonImage :: Text ( text) => {
8288 let extents = c. text_extents ( text) . unwrap ( ) ;
8389 c. move_to (
84- left_edge + button_width / 2.0 - extents. width ( ) / 2.0 ,
90+ button_left_edge + button_width / 2.0 - extents. width ( ) / 2.0 ,
8591 DFR_HEIGHT as f64 / 2.0 + extents. height ( ) / 2.0
8692 ) ;
8793 c. show_text ( text) . unwrap ( ) ;
@@ -90,9 +96,10 @@ impl Button {
9096 let renderer = CairoRenderer :: new ( & svg) ;
9197 let y = 0.12 * DFR_HEIGHT as f64 ;
9298 let size = DFR_HEIGHT as f64 - y * 2.0 ;
93- let x = left_edge + button_width / 2.0 - size / 2.0 ;
99+ let x = button_left_edge + button_width / 2.0 - size / 2.0 ;
100+
94101 renderer. render_document ( c,
95- & Rectangle :: new ( x, y, size, size)
102+ & Rectangle :: new ( x, y + y_shift , size, size)
96103 ) . unwrap ( ) ;
97104 }
98105 }
@@ -104,21 +111,23 @@ struct FunctionLayer {
104111}
105112
106113impl FunctionLayer {
107- fn draw ( & self , config : & Config , surface : & Surface , active_buttons : & [ bool ] ) {
114+ fn draw ( & self , config : & Config , surface : & Surface , active_buttons : & [ bool ] , pixel_shift : ( f64 , f64 ) ) {
108115 let c = Context :: new ( & surface) . unwrap ( ) ;
109116 c. translate ( DFR_HEIGHT as f64 , 0.0 ) ;
110117 c. rotate ( ( 90.0f64 ) . to_radians ( ) ) ;
111- let button_width = DFR_WIDTH as f64 / ( self . buttons . len ( ) + 1 ) as f64 ;
112- let spacing_width = ( DFR_WIDTH as f64 - self . buttons . len ( ) as f64 * button_width) / ( self . buttons . len ( ) - 1 ) as f64 ;
118+ let button_width = ( DFR_WIDTH as u64 - PIXEL_SHIFT_WIDTH_PX ) as f64 / ( self . buttons . len ( ) + 1 ) as f64 ;
119+ let spacing_width = ( ( DFR_WIDTH as u64 - PIXEL_SHIFT_WIDTH_PX ) as f64 - self . buttons . len ( ) as f64 * button_width) / ( self . buttons . len ( ) - 1 ) as f64 ;
113120 let radius = 8.0f64 ;
114121 let bot = ( DFR_HEIGHT as f64 ) * 0.2 ;
115122 let top = ( DFR_HEIGHT as f64 ) * 0.85 ;
123+ let ( pixel_shift_x, pixel_shift_y) = pixel_shift;
124+
116125 c. set_source_rgb ( 0.0 , 0.0 , 0.0 ) ;
117126 c. paint ( ) . unwrap ( ) ;
118127 c. select_font_face ( "sans-serif" , FontSlant :: Normal , FontWeight :: Bold ) ;
119128 c. set_font_size ( 32.0 ) ;
120129 for ( i, button) in self . buttons . iter ( ) . enumerate ( ) {
121- let left_edge = i as f64 * ( button_width + spacing_width) ;
130+ let left_edge = i as f64 * ( button_width + spacing_width) + pixel_shift_x + ( PIXEL_SHIFT_WIDTH_PX / 2 ) as f64 ;
122131 let color = if active_buttons[ i] {
123132 BUTTON_COLOR_ACTIVE
124133 } else if config. show_button_outlines {
@@ -163,7 +172,7 @@ impl FunctionLayer {
163172
164173 c. fill ( ) . unwrap ( ) ;
165174 c. set_source_rgb ( 1.0 , 1.0 , 1.0 ) ;
166- button. render ( & c, left_edge, button_width) ;
175+ button. render ( & c, left_edge, button_width, pixel_shift_y ) ;
167176 }
168177 }
169178}
@@ -222,17 +231,20 @@ fn load_config() -> Config {
222231 if let Ok ( user) = user {
223232 base. media_layer_default = user. media_layer_default . or ( base. media_layer_default ) ;
224233 base. show_button_outlines = user. show_button_outlines . or ( base. show_button_outlines ) ;
234+ base. enable_pixel_shift = user. enable_pixel_shift . or ( base. enable_pixel_shift ) ;
225235 } ;
226236 Config {
227237 media_layer_default : base. media_layer_default . unwrap ( ) ,
228- show_button_outlines : base. show_button_outlines . unwrap ( )
238+ show_button_outlines : base. show_button_outlines . unwrap ( ) ,
239+ enable_pixel_shift : base. enable_pixel_shift . unwrap ( ) ,
229240 }
230241}
231242
232243fn main ( ) {
233244 let mut uinput = UInputHandle :: new ( OpenOptions :: new ( ) . write ( true ) . open ( "/dev/uinput" ) . unwrap ( ) ) ;
234245 let mut backlight = BacklightManager :: new ( ) ;
235246 let config = load_config ( ) ;
247+ let mut pixel_shift = PixelShiftManager :: new ( ) ;
236248
237249 // drop privileges to input and video group
238250 let groups = [ "input" , "video" ] ;
@@ -315,14 +327,31 @@ fn main() {
315327 let mut digitizer: Option < InputDevice > = None ;
316328 let mut touches = HashMap :: new ( ) ;
317329 loop {
330+ let mut next_timeout_ms = TIMEOUT_MS ;
331+
332+ if config. enable_pixel_shift {
333+ let ( pixel_shift_needs_redraw, pixel_shift_next_timeout_ms) = pixel_shift. update ( ) ;
334+ if pixel_shift_needs_redraw {
335+ needs_redraw = true ;
336+ }
337+ next_timeout_ms = min ( next_timeout_ms, pixel_shift_next_timeout_ms) ;
338+ }
339+
340+
318341 if needs_redraw {
319342 needs_redraw = false ;
320- layers[ active_layer] . draw ( & config, & surface, & button_states[ active_layer] ) ;
343+ let shift = if config. enable_pixel_shift {
344+ pixel_shift. get ( )
345+ } else {
346+ ( 0.0 , 0.0 )
347+ } ;
348+ layers[ active_layer] . draw ( & config, & surface, & button_states[ active_layer] , shift) ;
321349 let data = surface. data ( ) . unwrap ( ) ;
322350 drm. map ( ) . unwrap ( ) . as_mut ( ) [ ..data. len ( ) ] . copy_from_slice ( & data) ;
323351 drm. dirty ( & [ ClipRect :: new ( 0 , 0 , DFR_HEIGHT as u16 , DFR_WIDTH as u16 ) ] ) . unwrap ( ) ;
324352 }
325- poll ( & mut [ pollfd_tb, pollfd_main] , TIMEOUT_MS ) . unwrap ( ) ;
353+
354+ poll ( & mut [ pollfd_tb, pollfd_main] , next_timeout_ms) . unwrap ( ) ;
326355 input_tb. dispatch ( ) . unwrap ( ) ;
327356 input_main. dispatch ( ) . unwrap ( ) ;
328357 for event in & mut input_tb. clone ( ) . chain ( input_main. clone ( ) ) {
0 commit comments