@@ -172,99 +172,106 @@ static uint32_t get_tiled_resizable_edges(node_t *node) {
172172 return edges ;
173173}
174174
175- static void update_scene_positions ( node_t * n , struct wlr_box rect , desktop_t * d ) {
176- if (!n || !d )
175+ static void apply_leaf_positions ( desktop_t * d ) {
176+ if (!d || !d -> root )
177177 return ;
178178
179- n -> pending .rectangle = rect ;
180- n -> current .rectangle = rect ;
181-
182- if (is_leaf (n )) {
183- if (n -> client ) {
184- // apply window gap and border width to leaf nodes
185- struct wlr_box r = rect ;
186- unsigned int bw = effective_border_width (d );
187- int wg = (gapless_monocle && d -> layout == LAYOUT_MONOCLE ) ? 0 : compute_window_gap (d );
188- r = apply_bleed (r , bw , wg );
189-
190- n -> client -> tiled_rectangle = r ;
191- n -> client -> committed_tiled_rectangle = r ;
192-
193- struct wlr_scene_tree * st = client_get_scene_tree (n -> client );
194- if (st ) {
195- wlr_scene_node_set_position (& st -> node , r .x , r .y );
196-
197- if (n -> client -> toplevel )
198- wlr_xdg_toplevel_set_size (n -> client -> toplevel -> xdg_toplevel , r .width , r .height );
199- else if (n -> client -> xwayland_view )
200- wlr_xwayland_surface_configure (n -> client -> xwayland_view -> xwayland_surface , r .x , r .y , r .width ,
201- r .height );
202-
203- if (bw != 0 ) {
204- const struct wlr_box geo = {
205- 0 ,
206- 0 ,
207- r .width ,
208- r .height
209- };
210- update_borders (client_border_tree (n -> client ), client_border_rects (n -> client ), geo , bw );
211- update_border_colors (n -> client );
212- if (n -> client -> border_radius > 0.0f ) {
213- surface_rounded_t * rounded = client_get_rounded (n -> client );
214- if (rounded ) {
215- int new_fw = r .width + 2 * (int )bw ;
216- int new_fh = r .height + 2 * (int )bw ;
217- if (new_fw > 0 && new_fh > 0 && (rounded -> border_shader_buf_w != new_fw ||
218- rounded -> border_shader_buf_h != new_fh )) {
219- rounded -> border_dirty = true;
220- rounded -> corner_mask_dirty = true;
221- }
222- }
179+ for (node_t * n = first_extrema (d -> root ); n ; n = next_leaf (n , d -> root )) {
180+ if (!n -> client )
181+ continue ;
182+
183+ struct wlr_box r = n -> client -> arranged_rectangle ;
184+ if (r .width < 1 || r .height < 1 )
185+ continue ;
186+
187+ struct wlr_scene_tree * st = client_get_scene_tree (n -> client );
188+ if (!st )
189+ continue ;
190+
191+ wlr_scene_node_set_position (& st -> node , r .x , r .y );
192+
193+ if (n -> client -> toplevel )
194+ wlr_xdg_toplevel_set_size (n -> client -> toplevel -> xdg_toplevel , r .width , r .height );
195+ else if (n -> client -> xwayland_view )
196+ wlr_xwayland_surface_configure (n -> client -> xwayland_view -> xwayland_surface , r .x , r .y , r .width ,
197+ r .height );
198+
199+ unsigned int bw = effective_border_width (d );
200+ if (bw != 0 ) {
201+ struct wlr_box geo = {0 , 0 , r .width , r .height };
202+ update_borders (client_border_tree (n -> client ), client_border_rects (n -> client ), geo , bw );
203+ update_border_colors (n -> client );
204+ if (n -> client -> border_radius > 0.0f ) {
205+ surface_rounded_t * rounded = client_get_rounded (n -> client );
206+ if (rounded ) {
207+ int new_fw = r .width + 2 * (int )bw ;
208+ int new_fh = r .height + 2 * (int )bw ;
209+ if (new_fw > 0 && new_fh > 0 && (rounded -> border_shader_buf_w != new_fw ||
210+ rounded -> border_shader_buf_h != new_fh )) {
211+ rounded -> border_dirty = true;
212+ rounded -> corner_mask_dirty = true;
223213 }
224214 }
225215 }
226216 }
227- } else if (n -> split_type == TYPE_VERTICAL ) {
228- int split_x = rect .x + (int )(rect .width * n -> split_ratio );
229- struct wlr_box left = {
230- rect .x ,
231- rect .y ,
232- split_x - rect .x ,
233- rect .height
234- };
235- struct wlr_box right = {
236- split_x ,
237- rect .y ,
238- rect .x + rect .width - split_x ,
239- rect .height
240- };
241- update_scene_positions (n -> first_child , left , d );
242- update_scene_positions (n -> second_child , right , d );
243- } else if (n -> split_type == TYPE_HORIZONTAL ) {
244- int split_y = rect .y + (int )(rect .height * n -> split_ratio );
245- struct wlr_box top = {
246- rect .x ,
247- rect .y ,
248- rect .width ,
249- split_y - rect .y
250- };
251- struct wlr_box bottom = {
252- rect .x ,
253- split_y ,
254- rect .width ,
255- rect .y + rect .height - split_y
256- };
257- update_scene_positions (n -> first_child , top , d );
258- update_scene_positions (n -> second_child , bottom , d );
259217 }
260218}
261219
220+ static int find_scroller_tile_idx (scroller_column_t * col , client_t * c ) {
221+ for (int j = 0 ; j < col -> tile_count ; j ++ )
222+ if (col -> tiles [j ].client == c )
223+ return j ;
224+ return -1 ;
225+ }
226+
227+ static int find_scroller_column (scroller_state_t * s , client_t * c ) {
228+ for (int i = 0 ; i < s -> column_count ; i ++ )
229+ if (find_scroller_tile_idx (& s -> columns [i ], c ) >= 0 )
230+ return i ;
231+ return -1 ;
232+ }
233+
234+ static double max_d (double a , double b ) {
235+ return a > b ? a : b ;
236+ }
237+
262238// process cursor motion for tiled window resizing
263239static void process_cursor_tiled_resize (void ) {
264240 node_t * node = server .tiled_resize_node ;
265241 if (!node || !node -> client )
266242 return ;
267243
244+ desktop_t * d = node -> desktop ;
245+ if (!d )
246+ return ;
247+
248+ // Handle scroller layout
249+ if (d -> layout == LAYOUT_SCROLLER && d -> scroller_state ) {
250+ scroller_state_t * s = d -> scroller_state ;
251+ if (s -> column_count == 0 )
252+ return ;
253+
254+ int col = find_scroller_column (s , node -> client );
255+ if (col < 0 )
256+ return ;
257+
258+ double delta_x = server .cursor -> x - server .grab_x ;
259+
260+ if (server .resize_edges & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT )) {
261+ double area_w = max_d (1.0 , (double )s -> working_area .width );
262+ s -> columns [col ].width .value += delta_x / area_w ;
263+ if (s -> columns [col ].width .value < 0.1 )
264+ s -> columns [col ].width .value = 0.1 ;
265+ if (s -> columns [col ].width .value > 1.0 )
266+ s -> columns [col ].width .value = 1.0 ;
267+ s -> columns [col ].width .type = SCROLLER_WIDTH_PROPORTION ;
268+ }
269+
270+ arrange (node -> output , d , false);
271+ apply_leaf_positions (d );
272+ return ;
273+ }
274+
268275 // handle horizontal resizing
269276 if (server .tiled_resize_parent_vertical &&
270277 (server .resize_edges & (WLR_EDGE_LEFT | WLR_EDGE_RIGHT ))) {
@@ -319,13 +326,10 @@ static void process_cursor_tiled_resize(void) {
319326 parent -> current .split_ratio = new_ratio ;
320327 }
321328
322- if (server .tiled_resize_parent_vertical && node -> desktop ) {
323- update_scene_positions (server .tiled_resize_parent_vertical ,
324- server .tiled_resize_parent_vertical -> rectangle , node -> desktop );
325- }
326- if (server .tiled_resize_parent_horizontal && node -> desktop ) {
327- update_scene_positions (server .tiled_resize_parent_horizontal ,
328- server .tiled_resize_parent_horizontal -> rectangle , node -> desktop );
329+ // Use the proper layout function to recompute all positions
330+ if (node -> output && d ) {
331+ arrange (node -> output , d , false);
332+ apply_leaf_positions (d );
329333 }
330334}
331335
@@ -831,6 +835,7 @@ void cursor_button(struct wl_listener *listener, void *data) {
831835 tiling_drag_begin (toplevel -> node );
832836 } else if (matched_kb -> action == BIND_INTERACTIVE_RESIZE ) {
833837 client_t * c = toplevel -> node -> client ;
838+ desktop_t * d = toplevel -> node -> desktop ;
834839 uint32_t edges = 0 ;
835840
836841 if (c -> state == STATE_FLOATING ) {
@@ -877,61 +882,83 @@ void cursor_button(struct wl_listener *listener, void *data) {
877882 edges = WLR_EDGE_RIGHT ;
878883 }
879884 } else if (IS_TILED (c )) {
880- edges = get_tiled_resizable_edges (toplevel -> node );
881-
882- if (edges != 0 ) {
883- // determine edge
885+ // for scroller layouts, only allow horizontal edges (column width resize)
886+ if (d && d -> layout == LAYOUT_SCROLLER ) {
884887 double wx = c -> tiled_rectangle .x ;
885- double wy = c -> tiled_rectangle .y ;
886888 double ww = c -> tiled_rectangle .width ;
887- double wh = c -> tiled_rectangle .height ;
888889 double cx = server .cursor -> x ;
889- double cy = server .cursor -> y ;
890890
891891 double third_w = ww / 3.0 ;
892- double third_h = wh / 3.0 ;
893892
894893 bool in_left = cx < wx + third_w ;
895894 bool in_right = cx > wx + ww - third_w ;
896- bool in_top = cy < wy + third_h ;
897- bool in_bottom = cy > wy + wh - third_h ;
898-
899- uint32_t clicked_edges = 0 ;
900895
901- if (in_left || in_right )
902- clicked_edges |= in_left ? WLR_EDGE_LEFT : WLR_EDGE_RIGHT ;
903-
904- if (in_top || in_bottom )
905- clicked_edges |= in_top ? WLR_EDGE_TOP : WLR_EDGE_BOTTOM ;
906-
907- if (clicked_edges == 0 ) {
896+ if (in_left )
897+ edges = WLR_EDGE_LEFT ;
898+ else if (in_right )
899+ edges = WLR_EDGE_RIGHT ;
900+ else {
908901 double dist_left = cx - wx ;
909902 double dist_right = (wx + ww ) - cx ;
910- double dist_top = cy - wy ;
911- double dist_bottom = (wy + wh ) - cy ;
912-
913- double min_dist = INFINITY ;
914-
915- if ((edges & WLR_EDGE_LEFT ) && dist_left < min_dist ) {
916- min_dist = dist_left ;
917- clicked_edges = WLR_EDGE_LEFT ;
918- }
919- if ((edges & WLR_EDGE_RIGHT ) && dist_right < min_dist ) {
920- min_dist = dist_right ;
921- clicked_edges = WLR_EDGE_RIGHT ;
922- }
923- if ((edges & WLR_EDGE_TOP ) && dist_top < min_dist ) {
924- min_dist = dist_top ;
925- clicked_edges = WLR_EDGE_TOP ;
926- }
927- if ((edges & WLR_EDGE_BOTTOM ) && dist_bottom < min_dist ) {
928- min_dist = dist_bottom ;
929- clicked_edges = WLR_EDGE_BOTTOM ;
930- }
903+ edges = dist_left < dist_right ? WLR_EDGE_LEFT : WLR_EDGE_RIGHT ;
931904 }
905+ } else {
906+ edges = get_tiled_resizable_edges (toplevel -> node );
907+
908+ if (edges != 0 ) {
909+ // determine edge
910+ double wx = c -> tiled_rectangle .x ;
911+ double wy = c -> tiled_rectangle .y ;
912+ double ww = c -> tiled_rectangle .width ;
913+ double wh = c -> tiled_rectangle .height ;
914+ double cx = server .cursor -> x ;
915+ double cy = server .cursor -> y ;
916+
917+ double third_w = ww / 3.0 ;
918+ double third_h = wh / 3.0 ;
919+
920+ bool in_left = cx < wx + third_w ;
921+ bool in_right = cx > wx + ww - third_w ;
922+ bool in_top = cy < wy + third_h ;
923+ bool in_bottom = cy > wy + wh - third_h ;
924+
925+ uint32_t clicked_edges = 0 ;
926+
927+ if (in_left || in_right )
928+ clicked_edges |= in_left ? WLR_EDGE_LEFT : WLR_EDGE_RIGHT ;
929+
930+ if (in_top || in_bottom )
931+ clicked_edges |= in_top ? WLR_EDGE_TOP : WLR_EDGE_BOTTOM ;
932+
933+ if (clicked_edges == 0 ) {
934+ double dist_left = cx - wx ;
935+ double dist_right = (wx + ww ) - cx ;
936+ double dist_top = cy - wy ;
937+ double dist_bottom = (wy + wh ) - cy ;
938+
939+ double min_dist = INFINITY ;
940+
941+ if ((edges & WLR_EDGE_LEFT ) && dist_left < min_dist ) {
942+ min_dist = dist_left ;
943+ clicked_edges = WLR_EDGE_LEFT ;
944+ }
945+ if ((edges & WLR_EDGE_RIGHT ) && dist_right < min_dist ) {
946+ min_dist = dist_right ;
947+ clicked_edges = WLR_EDGE_RIGHT ;
948+ }
949+ if ((edges & WLR_EDGE_TOP ) && dist_top < min_dist ) {
950+ min_dist = dist_top ;
951+ clicked_edges = WLR_EDGE_TOP ;
952+ }
953+ if ((edges & WLR_EDGE_BOTTOM ) && dist_bottom < min_dist ) {
954+ min_dist = dist_bottom ;
955+ clicked_edges = WLR_EDGE_BOTTOM ;
956+ }
957+ }
932958
933- // intersect clicked edges with resizable edges
934- edges = clicked_edges & edges ;
959+ // intersect clicked edges with resizable edges
960+ edges = clicked_edges & edges ;
961+ }
935962 }
936963 }
937964
0 commit comments