From 54ea8f74ae4ae3bff6df3f09ce8a8cdd148e51e5 Mon Sep 17 00:00:00 2001
From: nicm <nicm>
Date: Tue, 1 Mar 2016 12:04:43 +0000
Subject: [PATCH] When a mouse drag is finished, fire a MouseUp key press,
 instead of doing the drag end in code. From Stephen Coakley.

---
 mode-key.c      |  2 ++
 server-client.c | 42 ++++++++++++++++++++++++++++++++++++++++--
 window-copy.c   | 15 +--------------
 3 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/mode-key.c b/mode-key.c
index f38ebf66..a9b15bb9 100644
--- a/mode-key.c
+++ b/mode-key.c
@@ -347,6 +347,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
 	{ KEYC_WHEELUP_PANE,        0, MODEKEYCOPY_SCROLLUP },
 	{ KEYC_WHEELDOWN_PANE,      0, MODEKEYCOPY_SCROLLDOWN },
 	{ KEYC_MOUSEDRAG1_PANE,     0, MODEKEYCOPY_STARTSELECTION },
+	{ KEYC_MOUSEUP1_PANE,       0, MODEKEYCOPY_COPYSELECTION },
 
 	{ 0,			   -1, 0 }
 };
@@ -495,6 +496,7 @@ const struct mode_key_entry mode_key_emacs_copy[] = {
 	{ KEYC_WHEELUP_PANE,        0, MODEKEYCOPY_SCROLLUP },
 	{ KEYC_WHEELDOWN_PANE,      0, MODEKEYCOPY_SCROLLDOWN },
 	{ KEYC_MOUSEDRAG1_PANE,     0, MODEKEYCOPY_STARTSELECTION },
+	{ KEYC_MOUSEUP1_PANE,       0, MODEKEYCOPY_COPYSELECTION },
 
 	{ 0,			   -1, 0 }
 };
diff --git a/server-client.c b/server-client.c
index bb54643a..9111eb82 100644
--- a/server-client.c
+++ b/server-client.c
@@ -384,8 +384,42 @@ server_client_check_mouse(struct client *c)
 		c->tty.mouse_drag_update = NULL;
 		c->tty.mouse_drag_release = NULL;
 
+		/*
+		 * End a mouse drag by passing a MouseUp key corresponding to
+		 * the button that started the drag.
+		 */
+		switch (c->tty.mouse_drag_flag) {
+		case 1:
+			if (where == PANE)
+				key = KEYC_MOUSEUP1_PANE;
+			if (where == STATUS)
+				key = KEYC_MOUSEUP1_STATUS;
+			if (where == BORDER)
+				key = KEYC_MOUSEUP1_BORDER;
+			break;
+		case 2:
+			if (where == PANE)
+				key = KEYC_MOUSEUP2_PANE;
+			if (where == STATUS)
+				key = KEYC_MOUSEUP2_STATUS;
+			if (where == BORDER)
+				key = KEYC_MOUSEUP2_BORDER;
+			break;
+		case 3:
+			if (where == PANE)
+				key = KEYC_MOUSEUP3_PANE;
+			if (where == STATUS)
+				key = KEYC_MOUSEUP3_STATUS;
+			if (where == BORDER)
+				key = KEYC_MOUSEUP3_BORDER;
+			break;
+		default:
+			key = KEYC_MOUSE;
+			break;
+		}
 		c->tty.mouse_drag_flag = 0;
-		return (KEYC_MOUSE); /* not a key, but still may want to pass */
+
+		return (key);
 	}
 
 	/* Convert to a key binding. */
@@ -425,7 +459,11 @@ server_client_check_mouse(struct client *c)
 			}
 		}
 
-		c->tty.mouse_drag_flag = 1;
+		/*
+		 * Begin a drag by setting the flag to a non-zero value that
+		 * corresponds to the mouse button in use.
+		 */
+		c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
 		break;
 	case WHEEL:
 		if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) {
diff --git a/window-copy.c b/window-copy.c
index 009ed246..d345f246 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -2248,7 +2248,7 @@ window_copy_start_drag(struct client *c, struct mouse_event *m)
 		return;
 
 	c->tty.mouse_drag_update = window_copy_drag_update;
-	c->tty.mouse_drag_release = window_copy_drag_release;
+	c->tty.mouse_drag_release = NULL; /* will fire MouseUp key */
 
 	window_copy_update_cursor(wp, x, y);
 	window_copy_start_selection(wp);
@@ -2275,16 +2275,3 @@ window_copy_drag_update(__unused struct client *c, struct mouse_event *m)
 	if (window_copy_update_selection(wp, 1))
 		window_copy_redraw_selection(wp, old_cy);
 }
-
-void
-window_copy_drag_release(__unused struct client *c, struct mouse_event *m)
-{
-	struct window_pane	*wp;
-
-	wp = cmd_mouse_pane(m, NULL, NULL);
-	if (wp == NULL || wp->mode != &window_copy_mode)
-		return;
-
-	window_copy_copy_selection(wp, NULL);
-	window_pane_reset_mode(wp);
-}