Skip to content

Commit 14ad102

Browse files
committed
improve mode-mouse copy interface to be more like xterm
1 parent 2894991 commit 14ad102

File tree

2 files changed

+112
-28
lines changed

2 files changed

+112
-28
lines changed

input-keys.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,6 @@ input_mouse(struct window_pane *wp, struct mouse_event *m)
203203
{
204204
char buf[10];
205205
size_t len;
206-
int value;
207206

208207
if (wp->screen->mode & ALL_MOUSE_MODES) {
209208
if (wp->screen->mode & MODE_MOUSE_UTF8) {
@@ -220,13 +219,18 @@ input_mouse(struct window_pane *wp, struct mouse_event *m)
220219
buf[len++] = m->y + 33;
221220
}
222221
bufferevent_write(wp->event, buf, len);
223-
} else if ((m->b & MOUSE_BUTTON) != MOUSE_2) {
224-
value = options_get_number(&wp->window->options, "mode-mouse");
225-
if (value == 1 &&
226-
window_pane_set_mode(wp, &window_copy_mode) == 0) {
227-
window_copy_init_from_pane(wp);
228-
if (wp->mode->mouse != NULL)
229-
wp->mode->mouse(wp, NULL, m);
222+
}
223+
else if (options_get_number(&wp->window->options, "mode-mouse") == 1) {
224+
if ((m->b & MOUSE_BUTTON) != MOUSE_UP) {
225+
if ((m->b & MOUSE_BUTTON) == MOUSE_2) {
226+
/* TODO: paste or some more generic binding;
227+
* unfortunately we don't have client here */
228+
}
229+
else if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
230+
window_copy_init_from_pane(wp);
231+
if (wp->mode->mouse != NULL)
232+
wp->mode->mouse(wp, NULL, m);
233+
}
230234
}
231235
}
232236
}

window-copy.c

Lines changed: 100 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ struct window_copy_mode_data {
145145

146146
enum window_copy_input_type jumptype;
147147
char jumpchar;
148+
149+
u_char mouse_button;
150+
u_int mouse_x;
151+
u_int mouse_y;
152+
u_char mouse_click;
148153
};
149154

150155
struct screen *
@@ -180,6 +185,8 @@ window_copy_init(struct window_pane *wp)
180185
data->jumptype = WINDOW_COPY_OFF;
181186
data->jumpchar = '\0';
182187

188+
data->mouse_click = 0;
189+
183190
s = &data->screen;
184191
screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
185192
if (options_get_number(&wp->window->options, "mode-mouse"))
@@ -815,27 +822,49 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
815822
return 0;
816823
}
817824

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+
818840
/* ARGSUSED */
819841
void
820842
window_copy_mouse(
821843
struct window_pane *wp, struct session *sess, struct mouse_event *m)
822844
{
823845
struct window_copy_mode_data *data = wp->modedata;
824846
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;
826850

827851
if (m->x >= screen_size_x(s))
828852
return;
829853
if (m->y >= screen_size_y(s))
830854
return;
831855

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+
832862
/* If mouse wheel (buttons 4 and 5), scroll. */
833863
if ((m->b & MOUSE_45)) {
834-
if ((m->b & MOUSE_BUTTON) == MOUSE_1) {
864+
if (button == MOUSE_1) {
835865
for (i = 0; i < 5; i++)
836866
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) {
839868
for (i = 0; i < 5; i++)
840869
window_copy_cursor_down(wp, 0);
841870
if (old_cy == data->cy)
@@ -844,28 +873,79 @@ window_copy_mouse(
844873
return;
845874
}
846875

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)
858878
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;
859913
}
860914

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)) {
863927
s->mode &= ~MODE_MOUSE_STANDARD;
864928
s->mode |= MODE_MOUSE_BUTTON;
865929

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);
869949
}
870950

871951
return;

0 commit comments

Comments
 (0)