[+Michael (OP)] in case he has some opinions.

On 2014-06-23 10:59 +0100, Nicholas Marriott wrote:
> I like copy-on-release and it is how xterm works (it preserves the
> selection too, but we don't really have an option of doing that).

Right, I shouldn't be changing behavior.

> Maybe instead you could make a right- or middle-button drag select but
> not exit copy mode?

Ah, this didn't occur me. :)

I'm still not sure what is the best behavior. I've left the left click
as it is currently. Double/triple clicks will work only for right
clicks.

Then I was thinking about what should I be doing with the right click.
One approach is just to make it same as the left click but without the
exiting the copy mode. Then you can exit the copy mode with the middle
mouse button.

But this way you cannot "extend" via the mouse. Not sure that is useful
or not. To get feel of the answer I've implemented the following RFC for
this iteration: you can start a new selection with the right click.
Subsequent right clicks extend the current selection rather than start
anew. You can cancel the selection via the middle button which also
copies the selection. Then you need press the middle button again to
quit the copy mode. So you need two middle buttons to quit the copy
mode. The reason I did this is to easily be able start a selection anew
from another position without exiting the copy mode. Please give it a
shot, the patches are attached.

But in any case, I'm open to suggestions.

Thanks!

-- 
Balazs
>From 1aeaf576993fa3773593ad36a3f4aed41aa06ada Mon Sep 17 00:00:00 2001
From: Balazs Kezes <rlblas...@gmail.com>
Date: Sat, 21 Jun 2014 12:37:06 +0100
Subject: [PATCH 1/3] Fix mouse click counting

At this point this isn't used anywhere so this results in no functionality
change.
---
 tty-keys.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/tty-keys.c b/tty-keys.c
index 97b49a2..72eeb16 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -786,25 +786,25 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
 
 		m->button = 3;
 	} else if ((b & MOUSE_MASK_BUTTONS) == 3) {
-		if (~m->event & MOUSE_EVENT_DRAG && x == m->x && y == m->y)
+		if (~m->event & MOUSE_EVENT_DRAG && x == m->sx && y == m->sy) {
 			m->event = MOUSE_EVENT_CLICK;
-		else
+			m->clicks = (m->clicks + 1) % 3;
+		} else {
 			m->event = MOUSE_EVENT_DRAG;
+		}
 		m->event |= MOUSE_EVENT_UP;
 	} else {
 		if (b & MOUSE_MASK_DRAG)
 			m->event = MOUSE_EVENT_DRAG;
 		else {
-			if (m->event & MOUSE_EVENT_UP && x == m->x && y == m->y)
-				m->clicks = (m->clicks + 1) % 3;
-			else
-				m->clicks = 0;
-			m->sx = x;
-			m->sy = y;
 			m->event = MOUSE_EVENT_DOWN;
+			if (x != m->sx || y != m->sy)
+				m->clicks = 0;
 		}
 		m->button = (b & MOUSE_MASK_BUTTONS);
 	}
+	m->sx = x;
+	m->sy = y;
 
 	return (0);
 }
-- 
2.0.0.526.g5318336

>From 19478a4767f00766b92bbb8b30897b479ae5008f Mon Sep 17 00:00:00 2001
From: Balazs Kezes <rlblas...@gmail.com>
Date: Mon, 23 Jun 2014 21:12:50 +0100
Subject: [PATCH 2/3] Selecting via right click shouldn't leave copy mode

Currently if we start selecting via the mouse, the copy mode will exit
immediately after we release the mouse button. This way we cannot adjust the
selection via the keys for instance. This patch allows to start a selection with
the right click and that way tmux won't exit the copy mode.

Also, when we are already in copy mode, right click won't start the selection
anew -- rather it will extend the current selection to the current position of
the mouse.

To copy the selection press the middle button. It will copy the selection and
cancel it. Clicking it again, when there's no selection, will exit the copy
mode. Basically you need to click the middle button twice.
---
 window-copy.c | 74 ++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 48 insertions(+), 26 deletions(-)

diff --git a/window-copy.c b/window-copy.c
index 0775bcb..ea5ed85 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -869,6 +869,14 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
 	return (0);
 }
 
+static void
+window_copy_select_via_mouse(struct window_pane *wp, struct mouse_event *m)
+{
+	window_copy_update_cursor(wp, m->x, m->y);
+	if (window_copy_update_selection(wp, 1))
+		window_copy_redraw_screen(wp);
+}
+
 void
 window_copy_mouse(
     struct window_pane *wp, struct session *sess, struct mouse_event *m)
@@ -876,6 +884,9 @@ window_copy_mouse(
 	struct window_copy_mode_data	*data = wp->modedata;
 	struct screen			*s = &data->screen;
 	u_int				 i;
+	int				 dragged, pressed, released;
+
+	(void) sess;
 
 	if (m->x >= screen_size_x(s))
 		return;
@@ -894,44 +905,55 @@ window_copy_mouse(
 				 * We reached the bottom, leave copy mode, but
 				 * only if no selection is in progress.
 				 */
-				if (data->oy == 0 && !s->sel.flag)
-					goto reset_mode;
+				if (data->oy == 0 && !s->sel.flag) {
+					window_copy_copy_selection(wp, NULL);
+					window_pane_reset_mode(wp);
+					return;
+				}
 			}
 		}
 		return;
 	}
 
-	/*
-	 * If already reading motion, move the cursor while buttons are still
-	 * pressed, or stop the selection on their release.
-	 */
-	if (s->mode & MODE_MOUSE_BUTTON) {
-		if (~m->event & MOUSE_EVENT_UP) {
-			window_copy_update_cursor(wp, m->x, m->y);
-			if (window_copy_update_selection(wp, 1))
-				window_copy_redraw_screen(wp);
-			return;
-		}
-		goto reset_mode;
-	}
+	dragged = (m->event & MOUSE_EVENT_DRAG);
+	pressed = (m->event & MOUSE_EVENT_DOWN);
+	released = (m->event & MOUSE_EVENT_UP);
 
-	/* Otherwise if other buttons pressed, start selection and motion. */
-	if (~m->event & MOUSE_EVENT_UP) {
+	if (!(s->mode & MODE_MOUSE_BUTTON) && pressed) {
 		s->mode &= ~MODE_MOUSE_STANDARD;
 		s->mode |= MODE_MOUSE_BUTTON;
+	} else if ((s->mode & MODE_MOUSE_BUTTON) && released) {
+		s->mode &= ~MODE_MOUSE_BUTTON;
+		s->mode |= MODE_MOUSE_STANDARD;
+	}
 
+	if (m->button == 1) {
+		if (released) {
+			if (s->sel.flag) {
+				window_copy_copy_selection(wp, NULL);
+				window_copy_clear_selection(wp);
+				window_copy_redraw_screen(wp);
+			} else {
+				window_pane_reset_mode(wp);
+			}
+		}
+		return;
+	}
+
+	if (pressed && (!s->sel.flag || m->button == 0)) {
 		window_copy_update_cursor(wp, m->x, m->y);
 		window_copy_start_selection(wp);
-		window_copy_redraw_screen(wp);
 	}
-
-	return;
-
-reset_mode:
-	s->mode &= ~MODE_MOUSE_BUTTON;
-	s->mode |= MODE_MOUSE_STANDARD;
-	if (sess != NULL) {
-		window_copy_copy_selection(wp, NULL);
+	window_copy_select_via_mouse(wp, m);
+
+	if (released && m->button == 0) {
+		if (dragged) {
+			// A single click is usually means just selecting a pane
+			// with the mouse. So to avoid copying a single
+			// character in the vi mode, only copy when we actually
+			// dragged the mouse.
+			window_copy_copy_selection(wp, NULL);
+		}
 		window_pane_reset_mode(wp);
 	}
 }
-- 
2.0.0.526.g5318336

>From 0cfd9698619370daf5111f67edbcf6e5772f7809 Mon Sep 17 00:00:00 2001
From: Balazs Kezes <rlblas...@gmail.com>
Date: Mon, 23 Jun 2014 23:01:27 +0100
Subject: [PATCH 3/3] Select words/lines on double/triple right clicks in copy
 mode

---
 window-copy.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 89 insertions(+), 3 deletions(-)

diff --git a/window-copy.c b/window-copy.c
index ea5ed85..953e842 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -154,6 +154,9 @@ struct window_copy_mode_data {
 
 	enum window_copy_input_type jumptype;
 	char		jumpchar;
+
+	u_int		mouse_sx, mouse_sy; /* the starting point of dragging */
+	u_int		mouse_x0, mouse_x1; /* possible starting points */
 };
 
 struct screen *
@@ -870,9 +873,51 @@ window_copy_key_numeric_prefix(struct window_pane *wp, int key)
 }
 
 static void
-window_copy_select_via_mouse(struct window_pane *wp, struct mouse_event *m)
+window_copy_select_via_mouse(
+	struct window_pane *wp, struct mouse_event *m, const char *sep)
 {
+	struct window_copy_mode_data	*data = wp->modedata;
+	int				 dir;
+	u_int				 my, by;
+
+	/*
+	 * Based on where the user pressed when they started the selection and
+	 * where is the current mouse position, extend the selection. Care needs
+	 * to be taken to ensure character/word/line modes are respected.
+	 */
+
+	/* Make sure the starting place is correct. */
 	window_copy_update_cursor(wp, m->x, m->y);
+	my = data->mouse_sy;
+	by = screen_hsize(data->backing) + data->cy - data->oy;
+	if (by < my || (by == my && data->cx < data->mouse_sx)) {
+		dir = -1;
+		data->selx = data->mouse_x1;
+	} else {
+		dir = +1;
+		data->selx = data->mouse_x0;
+	}
+
+	if (m->clicks == 0) {
+		window_copy_update_cursor(wp, m->x, m->y);
+		if (window_copy_update_selection(wp, 1))
+			window_copy_redraw_screen(wp);
+	} else if (m->clicks == 1) {
+		if (dir < 0) {
+			data->cx += 1; /* Handle first letter clicks. */
+			window_copy_cursor_previous_word(wp, sep);
+		} else {
+			if (data->cx > 0)
+				data->cx -= 1; /* Handle last letter clicks. */
+			window_copy_cursor_next_word_end(wp, sep);
+		}
+	} else if (m->clicks == 2) {
+		if (dir < 0)
+			window_copy_cursor_start_of_line(wp);
+		else
+			window_copy_cursor_end_of_line(wp);
+	}
+
 	if (window_copy_update_selection(wp, 1))
 		window_copy_redraw_screen(wp);
 }
@@ -883,8 +928,9 @@ window_copy_mouse(
 {
 	struct window_copy_mode_data	*data = wp->modedata;
 	struct screen			*s = &data->screen;
-	u_int				 i;
+	u_int				 i, bmy;
 	int				 dragged, pressed, released;
+	const char			*sep;
 
 	(void) sess;
 
@@ -918,6 +964,8 @@ window_copy_mouse(
 	dragged = (m->event & MOUSE_EVENT_DRAG);
 	pressed = (m->event & MOUSE_EVENT_DOWN);
 	released = (m->event & MOUSE_EVENT_UP);
+	bmy = screen_hsize(data->backing) + m->y - data->oy;
+	sep = options_get_string(&sess->options, "word-separators");
 
 	if (!(s->mode & MODE_MOUSE_BUTTON) && pressed) {
 		s->mode &= ~MODE_MOUSE_STANDARD;
@@ -942,9 +990,47 @@ window_copy_mouse(
 
 	if (pressed && (!s->sel.flag || m->button == 0)) {
 		window_copy_update_cursor(wp, m->x, m->y);
+		data->mouse_sx = m->x;
+		data->mouse_sy = bmy;
+		data->mouse_x0 = m->x;
+		data->mouse_x1 = m->x;
 		window_copy_start_selection(wp);
+	} else if (pressed && m->x == data->mouse_sx && bmy == data->mouse_sy) {
+		/*
+		 * Single click: normal selection.
+		 * Double click: word selection.
+		 * Triple click: line selection.
+		 */
+
+		window_copy_update_cursor(wp, m->x, m->y);
+		window_copy_start_selection(wp);
+		data->mouse_sx = m->x;
+		data->mouse_sy = bmy;
+		if (m->clicks == 0) {
+			window_copy_start_selection(wp);
+			data->mouse_x0 = m->x;
+			data->mouse_x1 = m->x;
+		} else if (m->clicks == 1) {
+			if (data->cx > 0)
+				data->cx -= 1; /* Handle last letter clicks. */
+			window_copy_cursor_next_word_end(wp, sep);
+			data->mouse_x1 = data->cx;
+			data->cx += 1; /* Handle single letter words. */
+			window_copy_cursor_previous_word(wp, sep);
+			data->mouse_x0 = data->cx;
+			window_copy_start_selection(wp);
+		} else if (m->clicks == 2) {
+			window_copy_cursor_end_of_line(wp);
+			data->mouse_x1 = data->cx;
+			window_copy_cursor_start_of_line(wp);
+			data->mouse_x0 = data->cx;
+			window_copy_start_selection(wp);
+		}
+	}
+
+	if (pressed || dragged) {
+		window_copy_select_via_mouse(wp, m, sep);
 	}
-	window_copy_select_via_mouse(wp, m);
 
 	if (released && m->button == 0) {
 		if (dragged) {
-- 
2.0.0.526.g5318336

------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to