@@ -145,6 +145,11 @@ struct window_copy_mode_data {
145
145
146
146
enum window_copy_input_type jumptype ;
147
147
char jumpchar ;
148
+
149
+ u_char mouse_button ;
150
+ u_int mouse_x ;
151
+ u_int mouse_y ;
152
+ u_char mouse_click ;
148
153
};
149
154
150
155
struct screen *
@@ -180,6 +185,8 @@ window_copy_init(struct window_pane *wp)
180
185
data -> jumptype = WINDOW_COPY_OFF ;
181
186
data -> jumpchar = '\0' ;
182
187
188
+ data -> mouse_click = 0 ;
189
+
183
190
s = & data -> screen ;
184
191
screen_init (s , screen_size_x (& wp -> base ), screen_size_y (& wp -> base ), 0 );
185
192
if (options_get_number (& wp -> window -> options , "mode-mouse" ))
@@ -815,27 +822,49 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
815
822
return 0 ;
816
823
}
817
824
825
+ static int
826
+ window_copy_selection_direction (struct window_pane * wp )
827
+ {
828
+ struct window_copy_mode_data * data = wp -> modedata ;
829
+ struct screen * s = & data -> screen ;
830
+ u_int cy ;
831
+
832
+ if (!s -> sel .flag )
833
+ return 0 ;
834
+ cy = screen_hsize (data -> backing ) + data -> cy - data -> oy ;
835
+ if (cy < data -> sely || (cy == data -> sely && data -> cx < data -> selx ))
836
+ return -1 ;
837
+ return 1 ;
838
+ }
839
+
818
840
/* ARGSUSED */
819
841
void
820
842
window_copy_mouse (
821
843
struct window_pane * wp , struct session * sess , struct mouse_event * m )
822
844
{
823
845
struct window_copy_mode_data * data = wp -> modedata ;
824
846
struct screen * s = & data -> screen ;
825
- u_int i , old_cy ;
847
+ u_int i , old_cy = data -> cy ;
848
+ u_int button , moved ;
849
+ struct screen_sel old_sel = s -> sel ;
826
850
827
851
if (m -> x >= screen_size_x (s ))
828
852
return ;
829
853
if (m -> y >= screen_size_y (s ))
830
854
return ;
831
855
856
+ button = m -> b & MOUSE_BUTTON ;
857
+
858
+ /* filter irrelevant MOUSE_ANY events */
859
+ if (m -> b & MOUSE_DRAG && button == MOUSE_UP )
860
+ return ;
861
+
832
862
/* If mouse wheel (buttons 4 and 5), scroll. */
833
863
if ((m -> b & MOUSE_45 )) {
834
- if (( m -> b & MOUSE_BUTTON ) == MOUSE_1 ) {
864
+ if (button == MOUSE_1 ) {
835
865
for (i = 0 ; i < 5 ; i ++ )
836
866
window_copy_cursor_up (wp , 0 );
837
- } else if ((m -> b & MOUSE_BUTTON ) == MOUSE_2 ) {
838
- old_cy = data -> cy ;
867
+ } else if (button == MOUSE_2 ) {
839
868
for (i = 0 ; i < 5 ; i ++ )
840
869
window_copy_cursor_down (wp , 0 );
841
870
if (old_cy == data -> cy )
@@ -844,28 +873,79 @@ window_copy_mouse(
844
873
return ;
845
874
}
846
875
847
- /*
848
- * If already reading motion, move the cursor while buttons are still
849
- * pressed, or stop the selection on their release.
850
- */
851
- if (s -> mode & MODE_MOUSE_BUTTON ) {
852
- if ((m -> b & MOUSE_BUTTON ) != MOUSE_UP ) {
853
- window_copy_update_cursor (wp , m -> x , m -> y );
854
- if (window_copy_update_selection (wp ))
855
- window_copy_redraw_screen (wp );
856
- return ;
857
- }
876
+ /* ideally would like to copy + paste, but for now just copy + stop */
877
+ if (button == MOUSE_2 )
858
878
goto reset_mode ;
879
+
880
+ moved = m -> x != data -> mouse_x || m -> y != data -> mouse_y ;
881
+ window_copy_update_cursor (wp , m -> x , m -> y );
882
+
883
+ /* new button or click in new location */
884
+ if (data -> mouse_click & 1 &&
885
+ (moved || button != data -> mouse_button ))
886
+ data -> mouse_click = 0 ;
887
+
888
+ switch (data -> mouse_click ) {
889
+ case 1 : /* words */
890
+ window_copy_cursor_previous_word (wp ,
891
+ options_get_string (& sess -> options , "word-separators" ));
892
+ window_copy_start_selection (wp );
893
+ data -> mouse_click ++ ;
894
+ case 2 :
895
+ (window_copy_selection_direction (wp ) < 0 ?
896
+ window_copy_cursor_previous_word :
897
+ window_copy_cursor_next_word_end )(wp ,
898
+ options_get_string (& sess -> options , "word-separators" ));
899
+ break ;
900
+
901
+ case 3 : /* lines */
902
+ window_copy_cursor_start_of_line (wp );
903
+ window_copy_start_selection (wp );
904
+ data -> mouse_click ++ ;
905
+ case 4 :
906
+ (window_copy_selection_direction (wp ) < 0 ?
907
+ window_copy_cursor_start_of_line :
908
+ window_copy_cursor_end_of_line )(wp );
909
+ break ;
910
+
911
+ default : /* reset */
912
+ data -> mouse_click = 0 ;
859
913
}
860
914
861
- /* Otherwise if other buttons pressed, start selection and motion. */
862
- if ((m -> b & MOUSE_BUTTON ) != MOUSE_UP ) {
915
+ if (button == MOUSE_UP ) {
916
+ s -> mode &= ~MODE_MOUSE_BUTTON ;
917
+ s -> mode |= MODE_MOUSE_STANDARD ;
918
+
919
+ if (!moved )
920
+ data -> mouse_click ++ ;
921
+ else if (data -> mouse_button == MOUSE_1 )
922
+ goto reset_mode ;
923
+ else
924
+ data -> mouse_click = 0 ;
925
+ } else if (m -> b & MOUSE_DRAG ) {
926
+ } else if (!(data -> mouse_click & 1 )) {
863
927
s -> mode &= ~MODE_MOUSE_STANDARD ;
864
928
s -> mode |= MODE_MOUSE_BUTTON ;
865
929
866
- window_copy_update_cursor (wp , m -> x , m -> y );
867
- window_copy_start_selection (wp );
868
- window_copy_redraw_screen (wp );
930
+ if (!data -> mouse_click ) {
931
+ data -> mouse_button = button ;
932
+ data -> mouse_x = m -> x ;
933
+ data -> mouse_y = m -> y ;
934
+
935
+ if (button == MOUSE_1 || !s -> sel .flag )
936
+ window_copy_start_selection (wp );
937
+ }
938
+ }
939
+
940
+ if (window_copy_update_selection (wp ) &&
941
+ memcmp (& s -> sel , & old_sel , sizeof (struct screen_sel )))
942
+ {
943
+ if (old_sel .sy != s -> sel .sy )
944
+ window_copy_redraw_screen (wp );
945
+ else if (old_cy < data -> cy )
946
+ window_copy_redraw_lines (wp , old_cy , data -> cy - old_cy + 1 );
947
+ else
948
+ window_copy_redraw_lines (wp , data -> cy , old_cy - data -> cy + 1 );
869
949
}
870
950
871
951
return ;
0 commit comments