@@ -168,6 +168,21 @@ fn preview_scrollbar_target_row(
168168 Some ( target_row. min ( max_scroll) )
169169}
170170
171+ fn handle_preview_scrollbar_drag (
172+ state : & mut SessionState ,
173+ mouse : MouseEvent ,
174+ total_lines : usize ,
175+ ) -> bool {
176+ let Some ( target_row) = preview_scrollbar_target_row ( state, mouse, total_lines) else {
177+ return false ;
178+ } ;
179+ if target_row == state. preview_scroll_row {
180+ return false ;
181+ }
182+ state. preview_scroll_row = target_row;
183+ true
184+ }
185+
171186fn preview_viewport_cols ( state : & SessionState ) -> usize {
172187 let ( _, _, inner_w, _) = state. preview_inner_rect ;
173188 ( inner_w as usize ) . saturating_sub ( state. preview_line_number_cols )
@@ -775,7 +790,7 @@ pub fn process_once(
775790 }
776791 }
777792 }
778- Event :: Mouse ( mouse) => {
793+ Event :: Mouse ( mouse) => {
779794 if state. help_overlay_visible {
780795 return Ok ( ( false , false , false ) ) ;
781796 }
@@ -785,12 +800,14 @@ pub fn process_once(
785800
786801 if !state. divider_drag_active {
787802 state. preview_copy_indicator = false ;
803+ let rendered_total_lines = rendered_preview_total_lines ( state, preview_total_lines) ;
788804 match mouse. kind {
789805 MouseEventKind :: Down ( MouseButton :: Left ) => {
790806 // If we were selecting, finalize the previous selection
791807 if state. preview_selecting {
792808 finalize_selection ( state, preview_doc) ;
793809 }
810+ state. preview_scrollbar_dragging = false ;
794811
795812 let mut tree_clicked = false ;
796813 if let Some ( index) = tree_index_for_click ( state, mouse, nodes. len ( ) ) {
@@ -814,8 +831,6 @@ pub fn process_once(
814831 }
815832 }
816833
817- let rendered_total_lines =
818- rendered_preview_total_lines ( state, preview_total_lines) ;
819834 if !tree_clicked {
820835 if let Some ( target_row) =
821836 preview_scrollbar_target_row ( state, mouse, rendered_total_lines)
@@ -824,6 +839,7 @@ pub fn process_once(
824839 state. preview_selection = None ;
825840 state. preview_selecting = false ;
826841 state. preview_copying_indicator = false ;
842+ state. preview_scrollbar_dragging = true ;
827843 } else if in_preview_panel ( state, mouse) {
828844 let pos = mouse_to_content_position ( state, mouse) ;
829845 state. preview_selection = Some ( PreviewSelection {
@@ -838,13 +854,23 @@ pub fn process_once(
838854 }
839855 }
840856 }
857+ MouseEventKind :: Drag ( MouseButton :: Left ) if state. preview_scrollbar_dragging => {
858+ let _ = handle_preview_scrollbar_drag (
859+ state,
860+ mouse,
861+ rendered_total_lines,
862+ ) ;
863+ }
841864 MouseEventKind :: Drag ( MouseButton :: Left ) if state. preview_selecting => {
842865 let pos = mouse_to_content_position ( state, mouse) ;
843866 if let Some ( sel) = & mut state. preview_selection {
844867 sel. cursor = pos;
845868 }
846869 }
847870 // Some terminals send Moved instead of Drag during button hold
871+ MouseEventKind :: Moved if state. preview_scrollbar_dragging => {
872+ let _ = handle_preview_scrollbar_drag ( state, mouse, rendered_total_lines) ;
873+ }
848874 MouseEventKind :: Moved if state. preview_selecting => {
849875 let pos = mouse_to_content_position ( state, mouse) ;
850876 if let Some ( sel) = & mut state. preview_selection {
@@ -854,6 +880,9 @@ pub fn process_once(
854880 MouseEventKind :: Up ( MouseButton :: Left ) if state. preview_selecting => {
855881 finalize_selection ( state, preview_doc) ;
856882 }
883+ MouseEventKind :: Up ( MouseButton :: Left ) if state. preview_scrollbar_dragging => {
884+ state. preview_scrollbar_dragging = false ;
885+ }
857886 _ => { }
858887 }
859888
@@ -930,7 +959,8 @@ pub fn process_once(
930959#[ cfg( test) ]
931960mod tests {
932961 use super :: {
933- apply_mouse_resize, preview_scrollbar_target_row, tree_index_for_click, tree_panel_area,
962+ apply_mouse_resize, handle_preview_scrollbar_drag, preview_scrollbar_target_row,
963+ tree_index_for_click, tree_panel_area,
934964 } ;
935965 use crate :: app:: state:: { PreviewRenderCache , PreviewRenderCacheKey , SessionState } ;
936966 use crossterm:: event:: { KeyModifiers , MouseButton , MouseEvent , MouseEventKind } ;
@@ -988,6 +1018,24 @@ mod tests {
9881018 assert_eq ! ( preview_scrollbar_target_row( & state, click, 8 ) , None ) ;
9891019 }
9901020
1021+ #[ test]
1022+ fn preview_scrollbar_drag_moves_scroll_row ( ) {
1023+ let mut state = SessionState :: new ( PathBuf :: from ( "." ) ) ;
1024+ state. preview_inner_rect = ( 40 , 2 , 30 , 10 ) ;
1025+ state. preview_scroll_row = 0 ;
1026+ state. preview_scrollbar_dragging = true ;
1027+
1028+ let drag = MouseEvent {
1029+ kind : MouseEventKind :: Drag ( MouseButton :: Left ) ,
1030+ column : 69 ,
1031+ row : 8 ,
1032+ modifiers : KeyModifiers :: NONE ,
1033+ } ;
1034+
1035+ assert_eq ! ( handle_preview_scrollbar_drag( & mut state, drag, 100 ) , true ) ;
1036+ assert_eq ! ( state. preview_scroll_row, 60 ) ;
1037+ }
1038+
9911039 #[ test]
9921040 fn rendered_preview_total_lines_prefers_render_cache ( ) {
9931041 let mut state = SessionState :: new ( PathBuf :: from ( "." ) ) ;
0 commit comments