diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
index 9c0015bf..bdb8245e 100644
--- a/cmd-copy-mode.c
+++ b/cmd-copy-mode.c
@@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = {
 	.name = "copy-mode",
 	.alias = NULL,
 
-	.args = { "eHMt:u", 0, 0 },
-	.usage = "[-eHMu] " CMD_TARGET_PANE_USAGE,
+	.args = { "eHMt:uq", 0, 0 },
+	.usage = "[-eHMuq] " CMD_TARGET_PANE_USAGE,
 
 	.target = { 't', CMD_FIND_PANE, 0 },
 
@@ -61,6 +61,11 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item)
 	struct session		*s;
 	struct window_pane	*wp = item->target.wp;
 
+	if (args_has(args, 'q')) {
+		window_pane_reset_mode_all(wp);
+		return (CMD_RETURN_NORMAL);
+	}
+
 	if (args_has(args, 'M')) {
 		if ((wp = cmd_mouse_pane(&shared->mouse, &s, NULL)) == NULL)
 			return (CMD_RETURN_NORMAL);
diff --git a/format.c b/format.c
index fe8e9c68..ef69b9b7 100644
--- a/format.c
+++ b/format.c
@@ -948,7 +948,6 @@ format_grid_word(struct grid *gd, u_int x, u_int y)
 
 	ws = options_get_string(global_s_options, "word-separators");
 
-	y = gd->hsize + y;
 	for (;;) {
 		grid_get_cell(gd, x, y, &gc);
 		if (gc.flags & GRID_FLAG_PADDING)
@@ -1009,6 +1008,7 @@ static void
 format_cb_mouse_word(struct format_tree *ft, struct format_entry *fe)
 {
 	struct window_pane	*wp;
+	struct grid		*gd;
 	u_int			 x, y;
 	char			*s;
 
@@ -1017,12 +1017,18 @@ format_cb_mouse_word(struct format_tree *ft, struct format_entry *fe)
 	wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 	if (wp == NULL)
 		return;
-	if (!TAILQ_EMPTY (&wp->modes))
-		return;
 	if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
 		return;
 
-	s = format_grid_word(wp->base.grid, x, y);
+	if (!TAILQ_EMPTY(&wp->modes)) {
+		if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode)
+			s = window_copy_get_word(wp, x, y);
+		else
+			s = NULL;
+	} else {
+		gd = wp->base.grid;
+		s = format_grid_word(gd, x, gd->hsize + y);
+	}
 	if (s != NULL)
 		fe->value = s;
 }
@@ -1037,7 +1043,6 @@ format_grid_line(struct grid *gd, u_int y)
 	size_t			 size = 0;
 	char			*s = NULL;
 
-	y = gd->hsize + y;
 	for (x = 0; x < grid_line_length(gd, y); x++) {
 		grid_get_cell(gd, x, y, &gc);
 		if (gc.flags & GRID_FLAG_PADDING)
@@ -1059,6 +1064,7 @@ static void
 format_cb_mouse_line(struct format_tree *ft, struct format_entry *fe)
 {
 	struct window_pane	*wp;
+	struct grid		*gd;
 	u_int			 x, y;
 	char			*s;
 
@@ -1067,12 +1073,18 @@ format_cb_mouse_line(struct format_tree *ft, struct format_entry *fe)
 	wp = cmd_mouse_pane(&ft->m, NULL, NULL);
 	if (wp == NULL)
 		return;
-	if (!TAILQ_EMPTY (&wp->modes))
-		return;
 	if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
 		return;
 
-	s = format_grid_line(wp->base.grid, y);
+	if (!TAILQ_EMPTY(&wp->modes)) {
+		if (TAILQ_FIRST(&wp->modes)->mode == &window_copy_mode)
+			s = window_copy_get_line(wp, y);
+		else
+			s = NULL;
+	} else {
+		gd = wp->base.grid;
+		s = format_grid_line(gd, gd->hsize + y);
+	}
 	if (s != NULL)
 		fe->value = s;
 }
diff --git a/key-bindings.c b/key-bindings.c
index 57b71c0f..a31c338a 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -46,10 +46,13 @@
 	" 'New After' 'w' {new-window -a}" \
 	" 'New At End' 'W' {new-window}"
 #define DEFAULT_PANE_MENU \
+	" '#{?#{==:#{pane_mode},copy-mode},Go To Top,}' '<' {send -X history-top}" \
+	" '#{?#{==:#{pane_mode},copy-mode},Go To Bottom,}' '<' {send -X history-bottom}" \
+	" ''" \
 	" '#{?mouse_word,Search For #[underscore]#{=/9/...:mouse_word},}' 'C-r' {copy-mode -t=; send -Xt= search-backward \"#{q:mouse_word}\"}" \
-	" '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {send-keys -l -- \"#{q:mouse_word}\"}" \
-	" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {set-buffer -- \"#{q:mouse_word}\"}" \
-	" '#{?mouse_line,Copy Line,}' 'l' {set-buffer -- \"#{q:mouse_line}\"}" \
+	" '#{?mouse_word,Type #[underscore]#{=/9/...:mouse_word},}' 'C-y' {copy-mode -q; send-keys -l -- \"#{q:mouse_word}\"}" \
+	" '#{?mouse_word,Copy #[underscore]#{=/9/...:mouse_word},}' 'c' {copy-mode -q; set-buffer -- \"#{q:mouse_word}\"}" \
+	" '#{?mouse_line,Copy Line,}' 'l' {copy-mode -q; set-buffer -- \"#{q:mouse_line}\"}" \
 	" ''" \
 	" 'Horizontal Split' 'h' {split-window -h}" \
 	" 'Vertical Split' 'v' {split-window -v}" \
@@ -354,7 +357,7 @@ key_bindings_init(void)
 		"bind -n MouseDown3Status display-menu -t= -xW -yS -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU,
 
 		/* Mouse button 3 down on pane. */
-		"bind -n MouseDown3Pane if -Ft= '#{||:#{mouse_any_flag},#{pane_in_mode}}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }",
+		"bind -n MouseDown3Pane if -Ft= '#{mouse_any_flag}' { select-pane -t=; send -M } { display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }",
 		"bind -n M-MouseDown3Pane display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU,
 
 		/* Copy mode (emacs) keys. */
diff --git a/tmux.1 b/tmux.1
index dff28144..8cd4841f 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1565,7 +1565,7 @@ The synopsis for the
 command is:
 .Bl -tag -width Ds
 .It Xo Ic copy-mode
-.Op Fl eHMu
+.Op Fl eHMqu
 .Op Fl t Ar target-pane
 .Xc
 Enter copy mode.
@@ -1577,6 +1577,8 @@ begins a mouse drag (only valid if bound to a mouse key binding, see
 .Sx MOUSE SUPPORT ) .
 .Fl H
 hides the position indicator in the top right.
+.Fl q
+cancels copy mode and any other modes.
 .Pp
 .Fl e
 specifies that scrolling to the bottom of the history (to the visible screen)
diff --git a/tmux.h b/tmux.h
index 53372cfe..f202315b 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2636,6 +2636,8 @@ void printflike(2, 3) window_copy_add(struct window_pane *, const char *, ...);
 void		 window_copy_vadd(struct window_pane *, const char *, va_list);
 void		 window_copy_pageup(struct window_pane *, int);
 void		 window_copy_start_drag(struct client *, struct mouse_event *);
+char		*window_copy_get_word(struct window_pane *, u_int, u_int);
+char		*window_copy_get_line(struct window_pane *, u_int);
 
 /* names.c */
 void	 check_window_name(struct window *);
diff --git a/window-copy.c b/window-copy.c
index c6d3612f..9fe4fcef 100644
--- a/window-copy.c
+++ b/window-copy.c
@@ -596,10 +596,31 @@ window_copy_next_paragraph(struct window_mode_entry *wme)
 	window_copy_scroll_to(wme, ox, oy);
 }
 
+char *
+window_copy_get_word(struct window_pane *wp, u_int x, u_int y)
+{
+	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
+	struct window_copy_mode_data	*data = wme->data;
+	struct grid			*gd = data->screen.grid;
+
+	return (format_grid_word(gd, x, gd->hsize + y));
+}
+
+char *
+window_copy_get_line(struct window_pane *wp, u_int y)
+{
+	struct window_mode_entry	*wme = TAILQ_FIRST(&wp->modes);
+	struct window_copy_mode_data	*data = wme->data;
+	struct grid			*gd = data->screen.grid;
+
+	return (format_grid_line(gd, gd->hsize + y));
+}
+
 static void
 window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
 {
 	struct window_copy_mode_data	*data = wme->data;
+	struct grid			*gd = data->screen.grid;
 	char				*s;
 
 	format_add(ft, "scroll_position", "%d", data->oy);
@@ -619,13 +640,13 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
 	} else
 		format_add(ft, "selection_active", "%d", 0);
 
-	s = format_grid_word(data->screen.grid, data->cx, data->cy);
+	s = format_grid_word(gd, data->cx, gd->hsize + data->cy);
 	if (s != NULL) {
 		format_add(ft, "copy_cursor_word", "%s", s);
 		free(s);
 	}
 
-	s = format_grid_line(data->screen.grid, data->cy);
+	s = format_grid_line(gd, gd->hsize + data->cy);
 	if (s != NULL) {
 		format_add(ft, "copy_cursor_line", "%s", s);
 		free(s);