@@ -56,6 +56,7 @@ scroller_state_t *scroller_create(void) {
5656 if (!s )
5757 return NULL ;
5858 s -> view_offset = 0.0 ;
59+ s -> activate_prev_column_on_removal = false;
5960 return s ;
6061}
6162
@@ -172,9 +173,12 @@ bool scroller_add_tile(scroller_state_t *s, client_t *client, bool activate) {
172173 new_col -> tile_count = 1 ;
173174
174175 // adjust active_column_idx
175- if (activate )
176+ if (activate ) {
176177 s -> active_column_idx = insert_col ;
177- else if (s -> active_column_idx >= insert_col )
178+ // Track that we should activate the previous column if this one is
179+ // removed, matching niri's activate_prev_column_on_removal.
180+ s -> activate_prev_column_on_removal = true;
181+ } else if (s -> active_column_idx >= insert_col )
178182 s -> active_column_idx ++ ;
179183
180184 return true;
@@ -238,12 +242,24 @@ void scroller_remove_tile(scroller_state_t *s, client_t *client, struct output_t
238242 // fix active_column_idx
239243 if (s -> column_count == 0 ) {
240244 s -> active_column_idx = 0 ;
245+ s -> activate_prev_column_on_removal = false;
241246 return ;
242247 }
243- if (s -> active_column_idx >= s -> column_count )
244- s -> active_column_idx = s -> column_count - 1 ;
245- if (col_idx <= s -> active_column_idx && s -> active_column_idx > 0 )
248+ if (col_idx == s -> active_column_idx ) {
249+ // The active column was removed.
250+ if (s -> activate_prev_column_on_removal && s -> active_column_idx > 0 ) {
251+ // Activate the previous column (e.g. open-and-immediately-close).
252+ s -> active_column_idx -- ;
253+ } else {
254+ // Activate the next column, clamped to the last available.
255+ if (s -> active_column_idx >= s -> column_count )
256+ s -> active_column_idx = s -> column_count - 1 ;
257+ }
258+ s -> activate_prev_column_on_removal = false;
259+ } else if (col_idx < s -> active_column_idx ) {
260+ // A column to the left was removed; shift the active index.
246261 s -> active_column_idx -- ;
262+ }
247263 } else {
248264 if (tile_idx < col -> active_tile_idx )
249265 col -> active_tile_idx -- ;
@@ -292,6 +308,8 @@ void scroller_arrange(struct output_t *m, desktop_t *d, struct wlr_box available
292308 if (!s )
293309 return ;
294310
311+ s -> working_area = available ;
312+
295313 // populate from BSP tree if scroller state is empty but toplevels exist
296314 if (s -> column_count == 0 && d -> root )
297315 populate_from_tree (s , d );
@@ -417,7 +435,7 @@ void scroller_arrange(struct output_t *m, desktop_t *d, struct wlr_box available
417435 free (col_xs );
418436}
419437
420- static void apply_active_focus (desktop_t * d ) {
438+ void scroller_apply_active_focus (desktop_t * d , struct output_t * m ) {
421439 scroller_state_t * s = d -> scroller_state ;
422440 if (!s || s -> column_count == 0 ) {
423441 d -> focus = NULL ;
@@ -434,8 +452,9 @@ static void apply_active_focus(desktop_t *d) {
434452 if (c && c -> toplevel && c -> toplevel -> node ) {
435453 node_t * target = c -> toplevel -> node ;
436454 d -> focus = target ;
437- if (d -> output )
438- focus_node (d -> output , d , target );
455+ output_t * out = d -> output ? d -> output : m ;
456+ if (out )
457+ focus_node (out , d , target );
439458 }
440459}
441460
@@ -451,7 +470,8 @@ bool scroller_focus_next(desktop_t *d) {
451470 s -> active_column_idx ++ ;
452471 }
453472 s -> view_offset = 0.0 ; // reset scroll for now
454- apply_active_focus (d );
473+ s -> activate_prev_column_on_removal = false;
474+ scroller_apply_active_focus (d , NULL );
455475 return true;
456476}
457477
@@ -467,7 +487,8 @@ bool scroller_focus_prev(desktop_t *d) {
467487 s -> active_column_idx -- ;
468488 }
469489 s -> view_offset = 0.0 ;
470- apply_active_focus (d );
490+ s -> activate_prev_column_on_removal = false;
491+ scroller_apply_active_focus (d , NULL );
471492 return true;
472493}
473494
@@ -483,7 +504,7 @@ bool scroller_focus_down(desktop_t *d) {
483504 return false;
484505
485506 col -> active_tile_idx ++ ;
486- apply_active_focus ( d );
507+ scroller_apply_active_focus ( d , NULL );
487508 return true;
488509}
489510
@@ -499,7 +520,7 @@ bool scroller_focus_up(desktop_t *d) {
499520 return false;
500521
501522 col -> active_tile_idx -- ;
502- apply_active_focus ( d );
523+ scroller_apply_active_focus ( d , NULL );
503524 return true;
504525}
505526
@@ -515,7 +536,8 @@ void scroller_center_window(desktop_t *d, client_t *client) {
515536 s -> active_column_idx = col_idx ;
516537 s -> columns [col_idx ].active_tile_idx = tile_idx ;
517538 s -> view_offset = 0.0 ;
518- apply_active_focus (d );
539+ s -> activate_prev_column_on_removal = false;
540+ scroller_apply_active_focus (d , NULL );
519541}
520542
521543bool scroller_consume_into_column (desktop_t * d ) {
@@ -541,7 +563,12 @@ bool scroller_consume_into_column(desktop_t *d) {
541563 if (target_col >= s -> column_count )
542564 return false;
543565
544- return scroller_add_tile_to_column (s , cl , target_col , true);
566+ bool result = scroller_add_tile_to_column (s , cl , target_col , true);
567+ if (result )
568+ // Track that we should activate the previous column if this one is
569+ // removed, matching niri's activate_prev_column_on_removal.
570+ s -> activate_prev_column_on_removal = true;
571+ return result ;
545572}
546573
547574bool scroller_expel_from_column (desktop_t * d ) {
@@ -577,26 +604,48 @@ void scroller_apply_client_rules(client_t *c, float rule_proportion, float rule_
577604 // TODO: store per-client proportion overrides if needed later.
578605}
579606
580- void scroller_resize_width (client_t * client , float delta ) {
581- if (!client )
582- return ;
583- // Find the client's column in the scroller state (needs desktop_t).
584- // For now, stub – proportion is set via config.
585- // This will be wired through IPC / keybindings properly.
586- (void )delta ;
587- wlr_log (WLR_DEBUG , "scroller_resize_width: stub (client=%p delta=%.2f)" , (void * )client , delta );
607+ bool scroller_resize_width (desktop_t * d , float delta ) {
608+ scroller_state_t * s = d ? d -> scroller_state : NULL ;
609+ if (!s || s -> column_count == 0 )
610+ return false;
611+
612+ int col = s -> active_column_idx ;
613+ double prop = s -> columns [col ].width .value + (double )delta ;
614+ if (prop < 0.1 )
615+ prop = 0.1 ;
616+ if (prop > 1.0 )
617+ prop = 1.0 ;
618+ s -> columns [col ].width .type = SCROLLER_WIDTH_PROPORTION ;
619+ s -> columns [col ].width .value = prop ;
620+ return true;
588621}
589622
590- void scroller_resize_stack (client_t * client , float delta ) {
591- (void )client ;
592- (void )delta ;
593- wlr_log (WLR_DEBUG , "scroller_resize_stack: stub" );
623+ bool scroller_resize_stack (desktop_t * d , float delta ) {
624+ scroller_state_t * s = d ? d -> scroller_state : NULL ;
625+ if (!s || s -> column_count == 0 )
626+ return false;
627+
628+ scroller_column_t * col = & s -> columns [s -> active_column_idx ];
629+ if (col -> tile_count == 0 )
630+ return false;
631+
632+ int tile_idx = col -> active_tile_idx ;
633+ // Convert auto-height to fixed using the last computed rect height.
634+ if (col -> tiles [tile_idx ].height .type == SCROLLER_HEIGHT_AUTO ) {
635+ col -> tiles [tile_idx ].height .type = SCROLLER_HEIGHT_FIXED ;
636+ col -> tiles [tile_idx ].height .value = (double )col -> tiles [tile_idx ].rect .height ;
637+ }
638+
639+ double h = col -> tiles [tile_idx ].height .value + (double )delta ;
640+ if (h < 1.0 )
641+ h = 1.0 ;
642+ col -> tiles [tile_idx ].height .value = h ;
643+ return true;
594644}
595645
596646void scroller_set_proportion (client_t * client , float proportion ) {
597647 if (!client )
598648 return ;
599- // TODO: find column and update its width.
600649 (void )proportion ;
601650 wlr_log (WLR_DEBUG , "scroller_set_proportion: stub (client=%p prop=%.2f)" , (void * )client ,
602651 proportion );
@@ -605,7 +654,6 @@ void scroller_set_proportion(client_t *client, float proportion) {
605654void scroller_cycle_proportion_preset (client_t * client ) {
606655 if (!client || !scroller_proportion_preset || scroller_proportion_preset_count == 0 )
607656 return ;
608- // TODO: find column, cycle through presets.
609657 wlr_log (WLR_DEBUG , "scroller_cycle_proportion_preset: stub" );
610658}
611659
0 commit comments