@@ -3046,21 +3046,24 @@ impl ConfigProxyHandler {
30463046 Ok ( ( ) )
30473047 }
30483048
3049- fn handle_set_window_size (
3049+ fn handle_set_window_position (
30503050 & self ,
30513051 window : Window ,
3052- width : i32 ,
3053- height : i32 ,
3052+ x1 : Option < i32 > ,
3053+ y1 : Option < i32 > ,
3054+ x2 : Option < i32 > ,
3055+ y2 : Option < i32 > ,
3056+ width : Option < i32 > ,
3057+ height : Option < i32 > ,
30543058 ) -> Result < ( ) , CphError > {
3055- if width <= 0 || height <= 0 {
3056- return Err ( CphError :: InvalidWindowSize ( width, height) ) ;
3059+ let tl = self . get_window ( window) ?;
3060+ let pos = tl. node_absolute_position ( LiveTL ) ;
3061+ let ( x1, x2) = resolve_geometry_axis ( x1, x2, width, pos. x1 ( ) , pos. x2 ( ) ) ?;
3062+ let ( y1, y2) = resolve_geometry_axis ( y1, y2, height, pos. y1 ( ) , pos. y2 ( ) ) ?;
3063+ if x2 - x1 <= 0 || y2 - y1 <= 0 {
3064+ return Err ( CphError :: InvalidWindowSize ( x2 - x1, y2 - y1) ) ;
30573065 }
3058- self . get_window ( window) ?. tl_set_size ( width, height) ;
3059- Ok ( ( ) )
3060- }
3061-
3062- fn handle_set_window_position ( & self , window : Window , x : i32 , y : i32 ) -> Result < ( ) , CphError > {
3063- self . get_window ( window) ?. tl_set_position ( x, y) ;
3066+ tl. tl_set_geometry ( x1, y1, x2, y2) ;
30643067 Ok ( ( ) )
30653068 }
30663069
@@ -3995,15 +3998,16 @@ impl ConfigProxyHandler {
39953998 ClientMessage :: GetWindowSize { window } => {
39963999 self . handle_get_window_size ( window) . wrn ( "get_window_size" ) ?
39974000 }
3998- ClientMessage :: SetWindowSize {
4001+ ClientMessage :: SetWindowPosition {
39994002 window,
4003+ x1,
4004+ y1,
4005+ x2,
4006+ y2,
40004007 width,
40014008 height,
40024009 } => self
4003- . handle_set_window_size ( window, width, height)
4004- . wrn ( "set_window_size" ) ?,
4005- ClientMessage :: SetWindowPosition { window, x, y } => self
4006- . handle_set_window_position ( window, x, y)
4010+ . handle_set_window_position ( window, x1, y1, x2, y2, width, height)
40074011 . wrn ( "set_window_position" ) ?,
40084012 ClientMessage :: GetWorkspacePosition { workspace } => self
40094013 . handle_get_workspace_position ( workspace)
@@ -4175,6 +4179,42 @@ impl ConfigProxyHandler {
41754179 }
41764180}
41774181
4182+ /// Resolves the constraints on a single axis (x1/x2/width or y1/y2/height) of
4183+ /// [`ConfigProxyHandler::handle_set_window_position`] into a concrete `(c1, c2)` pair.
4184+ ///
4185+ /// `c1`, `c2` and `size` are constrained to their contained value if they are `Some(_)` and
4186+ /// are otherwise unconstrained.
4187+ ///
4188+ /// If two of the three are constrained, the third is derived from them. If only one is
4189+ /// constrained, the window keeps its current size (if `c1` or `c2` is constrained) or its
4190+ /// current position (if only `size` is constrained). If none are constrained, the axis is
4191+ /// left unchanged. If all three are constrained but not self-consistent, an error is returned.
4192+ fn resolve_geometry_axis (
4193+ c1 : Option < i32 > ,
4194+ c2 : Option < i32 > ,
4195+ size : Option < i32 > ,
4196+ cur_c1 : i32 ,
4197+ cur_c2 : i32 ,
4198+ ) -> Result < ( i32 , i32 ) , CphError > {
4199+ let cur_size = cur_c2. saturating_sub ( cur_c1) ;
4200+ let res = match ( c1, c2, size) {
4201+ ( Some ( c1) , Some ( c2) , Some ( size) ) => {
4202+ if c2. saturating_sub ( c1) != size {
4203+ return Err ( CphError :: InconsistentWindowGeometry ) ;
4204+ }
4205+ ( c1, c2)
4206+ }
4207+ ( Some ( c1) , Some ( c2) , None ) => ( c1, c2) ,
4208+ ( Some ( c1) , None , Some ( size) ) => ( c1, c1. saturating_add ( size) ) ,
4209+ ( None , Some ( c2) , Some ( size) ) => ( c2. saturating_sub ( size) , c2) ,
4210+ ( Some ( c1) , None , None ) => ( c1, c1. saturating_add ( cur_size) ) ,
4211+ ( None , Some ( c2) , None ) => ( c2. saturating_sub ( cur_size) , c2) ,
4212+ ( None , None , Some ( size) ) => ( cur_c1, cur_c1. saturating_add ( size) ) ,
4213+ ( None , None , None ) => ( cur_c1, cur_c2) ,
4214+ } ;
4215+ Ok ( res)
4216+ }
4217+
41784218#[ derive( Debug , Error ) ]
41794219enum CphError {
41804220 #[ error( "Tried to set an unknown accel profile: {}" , ( . 0 ) . 0 ) ]
@@ -4207,6 +4247,8 @@ enum CphError {
42074247 InvalidConnectorPosition ( i32 , i32 ) ,
42084248 #[ error( "{0}x{1} is not a valid window size" ) ]
42094249 InvalidWindowSize ( i32 , i32 ) ,
4250+ #[ error( "The given x1/x2/width or y1/y2/height constraints are not self-consistent" ) ]
4251+ InconsistentWindowGeometry ,
42104252 #[ error( "Keymap {0:?} does not exist" ) ]
42114253 KeymapDoesNotExist ( Keymap ) ,
42124254 #[ error( "Seat {0:?} does not exist" ) ]
0 commit comments