@@ -3,6 +3,7 @@ extern crate tracing;
33
44use std:: collections:: HashSet ;
55use std:: ffi:: OsStr ;
6+ use std:: ops:: Mul ;
67use std:: path:: { Path , PathBuf } ;
78use std:: str:: FromStr ;
89use std:: time:: Duration ;
@@ -436,6 +437,8 @@ pub struct Layout {
436437 #[ knuffel( child, default ) ]
437438 pub border : Border ,
438439 #[ knuffel( child, default ) ]
440+ pub shadow : Shadow ,
441+ #[ knuffel( child, default ) ]
439442 pub insert_hint : InsertHint ,
440443 #[ knuffel( child, unwrap( children) , default ) ]
441444 pub preset_column_widths : Vec < PresetSize > ,
@@ -460,6 +463,7 @@ impl Default for Layout {
460463 Self {
461464 focus_ring : Default :: default ( ) ,
462465 border : Default :: default ( ) ,
466+ shadow : Default :: default ( ) ,
463467 insert_hint : Default :: default ( ) ,
464468 preset_column_widths : Default :: default ( ) ,
465469 default_column_width : Default :: default ( ) ,
@@ -608,6 +612,49 @@ impl From<FocusRing> for Border {
608612 }
609613}
610614
615+ #[ derive( knuffel:: Decode , Debug , Clone , Copy , PartialEq ) ]
616+ pub struct Shadow {
617+ #[ knuffel( child) ]
618+ pub on : bool ,
619+ #[ knuffel( child, default = Self :: default ( ) . offset) ]
620+ pub offset : ShadowOffset ,
621+ #[ knuffel( child, unwrap( argument) , default = Self :: default ( ) . softness) ]
622+ pub softness : FloatOrInt < 0 , 1024 > ,
623+ #[ knuffel( child, unwrap( argument) , default = Self :: default ( ) . spread) ]
624+ pub spread : FloatOrInt < 0 , 1024 > ,
625+ #[ knuffel( child, unwrap( argument) , default = Self :: default ( ) . draw_behind_window) ]
626+ pub draw_behind_window : bool ,
627+ #[ knuffel( child, default = Self :: default ( ) . color) ]
628+ pub color : Color ,
629+ #[ knuffel( child) ]
630+ pub inactive_color : Option < Color > ,
631+ }
632+
633+ impl Default for Shadow {
634+ fn default ( ) -> Self {
635+ Self {
636+ on : false ,
637+ offset : ShadowOffset {
638+ x : FloatOrInt ( 0. ) ,
639+ y : FloatOrInt ( 5. ) ,
640+ } ,
641+ softness : FloatOrInt ( 30. ) ,
642+ spread : FloatOrInt ( 5. ) ,
643+ draw_behind_window : false ,
644+ color : Color :: from_rgba8_unpremul ( 0 , 0 , 0 , 0x70 ) ,
645+ inactive_color : None ,
646+ }
647+ }
648+ }
649+
650+ #[ derive( knuffel:: Decode , Debug , Clone , Copy , PartialEq ) ]
651+ pub struct ShadowOffset {
652+ #[ knuffel( property, default ) ]
653+ pub x : FloatOrInt < -65535 , 65535 > ,
654+ #[ knuffel( property, default ) ]
655+ pub y : FloatOrInt < -65535 , 65535 > ,
656+ }
657+
611658#[ derive( knuffel:: Decode , Debug , Clone , Copy , PartialEq ) ]
612659pub struct InsertHint {
613660 #[ knuffel( child) ]
@@ -679,6 +726,15 @@ impl Color {
679726 }
680727}
681728
729+ impl Mul < f32 > for Color {
730+ type Output = Self ;
731+
732+ fn mul ( mut self , rhs : f32 ) -> Self :: Output {
733+ self . a *= rhs;
734+ self
735+ }
736+ }
737+
682738#[ derive( knuffel:: Decode , Debug , PartialEq ) ]
683739pub struct Cursor {
684740 #[ knuffel( child, unwrap( argument) , default = String :: from( "default" ) ) ]
@@ -1007,6 +1063,8 @@ pub struct WindowRule {
10071063 pub focus_ring : BorderRule ,
10081064 #[ knuffel( child, default ) ]
10091065 pub border : BorderRule ,
1066+ #[ knuffel( child, default ) ]
1067+ pub shadow : ShadowRule ,
10101068 #[ knuffel( child, unwrap( argument) ) ]
10111069 pub draw_border_with_background : Option < bool > ,
10121070 #[ knuffel( child, unwrap( argument) ) ]
@@ -1084,6 +1142,26 @@ pub struct BorderRule {
10841142 pub inactive_gradient : Option < Gradient > ,
10851143}
10861144
1145+ #[ derive( knuffel:: Decode , Debug , Default , Clone , Copy , PartialEq ) ]
1146+ pub struct ShadowRule {
1147+ #[ knuffel( child) ]
1148+ pub off : bool ,
1149+ #[ knuffel( child) ]
1150+ pub on : bool ,
1151+ #[ knuffel( child) ]
1152+ pub offset : Option < ShadowOffset > ,
1153+ #[ knuffel( child, unwrap( argument) ) ]
1154+ pub softness : Option < FloatOrInt < 0 , 1024 > > ,
1155+ #[ knuffel( child, unwrap( argument) ) ]
1156+ pub spread : Option < FloatOrInt < 0 , 1024 > > ,
1157+ #[ knuffel( child, unwrap( argument) ) ]
1158+ pub draw_behind_window : Option < bool > ,
1159+ #[ knuffel( child) ]
1160+ pub color : Option < Color > ,
1161+ #[ knuffel( child) ]
1162+ pub inactive_color : Option < Color > ,
1163+ }
1164+
10871165#[ derive( knuffel:: Decode , Debug , Clone , Copy , PartialEq ) ]
10881166pub struct FloatingPosition {
10891167 #[ knuffel( property) ]
@@ -1803,6 +1881,67 @@ impl BorderRule {
18031881 }
18041882}
18051883
1884+ impl ShadowRule {
1885+ pub fn merge_with ( & mut self , other : & Self ) {
1886+ if other. off {
1887+ self . off = true ;
1888+ self . on = false ;
1889+ }
1890+
1891+ if other. on {
1892+ self . off = false ;
1893+ self . on = true ;
1894+ }
1895+
1896+ if let Some ( x) = other. offset {
1897+ self . offset = Some ( x) ;
1898+ }
1899+ if let Some ( x) = other. softness {
1900+ self . softness = Some ( x) ;
1901+ }
1902+ if let Some ( x) = other. spread {
1903+ self . spread = Some ( x) ;
1904+ }
1905+ if let Some ( x) = other. draw_behind_window {
1906+ self . draw_behind_window = Some ( x) ;
1907+ }
1908+ if let Some ( x) = other. color {
1909+ self . color = Some ( x) ;
1910+ }
1911+ if let Some ( x) = other. inactive_color {
1912+ self . inactive_color = Some ( x) ;
1913+ }
1914+ }
1915+
1916+ pub fn resolve_against ( & self , mut config : Shadow ) -> Shadow {
1917+ config. on |= self . on ;
1918+ if self . off {
1919+ config. on = false ;
1920+ }
1921+
1922+ if let Some ( x) = self . offset {
1923+ config. offset = x;
1924+ }
1925+ if let Some ( x) = self . softness {
1926+ config. softness = x;
1927+ }
1928+ if let Some ( x) = self . spread {
1929+ config. spread = x;
1930+ }
1931+ if let Some ( x) = self . draw_behind_window {
1932+ config. draw_behind_window = x;
1933+ }
1934+ if let Some ( x) = self . color {
1935+ config. color = x;
1936+ }
1937+ if let Some ( x) = self . inactive_color {
1938+ config. inactive_color = Some ( x) ;
1939+ }
1940+
1941+ config
1942+ }
1943+ }
1944+
18061945impl CornerRadius {
18071946 pub fn fit_to ( self , width : f32 , height : f32 ) -> Self {
18081947 // Like in CSS: https://drafts.csswg.org/css-backgrounds/#corner-overlap
@@ -3221,6 +3360,10 @@ mod tests {
32213360 inactive-color "rgba(255, 200, 100, 0.0)"
32223361 }
32233362
3363+ shadow {
3364+ offset x=10 y=-20
3365+ }
3366+
32243367 preset-column-widths {
32253368 proportion 0.25
32263369 proportion 0.5
@@ -3460,6 +3603,13 @@ mod tests {
34603603 active_gradient : None ,
34613604 inactive_gradient : None ,
34623605 } ,
3606+ shadow : Shadow {
3607+ offset : ShadowOffset {
3608+ x : FloatOrInt ( 10. ) ,
3609+ y : FloatOrInt ( -20. ) ,
3610+ } ,
3611+ ..Default :: default ( )
3612+ } ,
34633613 insert_hint : InsertHint {
34643614 off : false ,
34653615 color : Color :: from_rgba8_unpremul ( 255 , 200 , 127 , 255 ) ,
0 commit comments