Can you do these separately? Ie the double/triple click bit separate
from the right drag bit.

Cheers


On Sat, May 24, 2014 at 04:36:04PM +0100, Balazs Kezes wrote:
> So I used tmux with my mouse changes for a week. There are two
> annoyances with the previous patch. When you single click in pane which
> is not listening for mouse events it automatically enters the copy mode.
> This is very annoying because I often use mouse to select a pane. So
> I've made modifications so that a single click doesn't enter the copy
> mode but if you start dragging or double click on a word it will do what
> you'd expect.
> 
> The other problem is that when you enter the copy via other means (mouse
> wheel or ^B-[) and then you click via mouse then it will quit the copy
> mode first. This is very annoying when you scroll up a bit and then you
> want to double click on a word to select it. You would not expect it to
> quit the copy mode and put you at the bottom of the history. So I've
> fixed this as well.
> 
> Also, previously I kept counting the number of clicks myself in order to
> determine that a click was double or triple click. I've noticed tmux is
> already counting this but albeit a bit buggily so I've fixed that and
> started to use that mechanism which simplified some parts of my change.
> 
> I've attached the new patch which replaces my previous attempt.
> 
> -- 
> Balazs

> From cc474a2d97e9062761b2a5a74b95044b4f845ef8 Mon Sep 17 00:00:00 2001
> From: Balazs Kezes <rlblas...@gmail.com>
> Date: Sat, 17 May 2014 10:47:33 +0100
> Subject: [PATCH] Implement new mouse selection mechanism
> 
> Left button starts the selection. You can double/triple click in order
> to select full words/lines. Right button will extend the selection from
> the original starting point to the mouse position. You can quit the copy
> mode via the middle button which will copy the current selection. Note
> that the word separating characters are coming from the
> "word-separators" option.
> ---
>  CHANGES         |   6 +++
>  cmd-copy-mode.c |   2 +-
>  input-keys.c    |  24 ++++++----
>  tmux.1          |   6 +++
>  tmux.h          |   2 +-
>  tty-keys.c      |  16 +++----
>  window-copy.c   | 143 
> ++++++++++++++++++++++++++++++++++++++++++++++++--------
>  7 files changed, 161 insertions(+), 38 deletions(-)
> 
> diff --git a/CHANGES b/CHANGES
> index abd1ac0..3bfc8bd 100644
> --- a/CHANGES
> +++ b/CHANGES
> @@ -8,6 +8,12 @@ Normal Changes
>  
>  * Fix crash due to uninitialized lastwp member of layout_cell
>  * Fix -fg/-bg/-style with 256 colour terminals.  
> +* New mouse selection mechanism: Left button starts the selection. You can
> +  double/triple click in order to select full words/lines. Right button will
> +  extend the selection from the original starting point to the mouse 
> position.
> +  You can quit the copy mode via the middle button which will copy the 
> current
> +  selection. Note that the word separating characters are coming from the
> +  "word-separators" option.
>  
>  CHANGES FROM 1.8 to 1.9, 20 February 2014
>  
> diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c
> index f11c7af..7e1a995 100644
> --- a/cmd-copy-mode.c
> +++ b/cmd-copy-mode.c
> @@ -56,7 +56,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmd_q *cmdq)
>       if (wp->mode != &window_copy_mode) {
>               if (window_pane_set_mode(wp, &window_copy_mode) != 0)
>                       return (CMD_RETURN_NORMAL);
> -             window_copy_init_from_pane(wp);
> +             window_copy_init_from_pane(wp, 0);
>       }
>       if (wp->mode == &window_copy_mode && args_has(self->args, 'u'))
>               window_copy_pageup(wp);
> diff --git a/input-keys.c b/input-keys.c
> index 7531f22..52d81a1 100644
> --- a/input-keys.c
> +++ b/input-keys.c
> @@ -205,6 +205,7 @@ input_mouse(struct window_pane *wp, struct session *s, 
> struct mouse_event *m)
>       size_t                   len;
>       struct paste_buffer     *pb;
>       u_int                    i;
> +     int                      wheel;
>  
>       /*
>        * If the alternate screen is active and hasn't enabled the mouse, send
> @@ -252,17 +253,22 @@ input_mouse(struct window_pane *wp, struct session *s, 
> struct mouse_event *m)
>               return;
>       }
>  
> -     if (m->button == 1 && (m->event & MOUSE_EVENT_CLICK) &&
> -         options_get_number(&wp->window->options, "mode-mouse") == 1) {
> -             pb = paste_get_top();
> -             if (pb != NULL) {
> -                     paste_send_pane(pb, wp, "\r",
> -                         wp->screen->mode & MODE_BRACKETPASTE);
> +     if (options_get_number(&wp->window->options, "mode-mouse") != 1)
> +             return;
> +
> +     /* We don't care about m->button in case of wheel events. */
> +     wheel = (m->event & MOUSE_EVENT_WHEEL);
> +     if (wp->mode == NULL && !wheel && m->button == 1) {
> +             if (m->event & MOUSE_EVENT_DOWN) {
> +                     pb = paste_get_top();
> +                     if (pb != NULL) {
> +                             paste_send_pane(pb, wp, "\r",
> +                                     wp->screen->mode & MODE_BRACKETPASTE);
> +                     }
>               }
> -     } else if (m->button != 1 &&
> -         options_get_number(&wp->window->options, "mode-mouse") == 1) {
> +     } else {
>               if (window_pane_set_mode(wp, &window_copy_mode) == 0) {
> -                     window_copy_init_from_pane(wp);
> +                     window_copy_init_from_pane(wp, !wheel);
>                       if (wp->mode->mouse != NULL)
>                               wp->mode->mouse(wp, s, m);
>               }
> diff --git a/tmux.1 b/tmux.1
> index 30447ed..5b537ff 100644
> --- a/tmux.1
> +++ b/tmux.1
> @@ -2821,6 +2821,12 @@ If set to
>  .Em copy-mode ,
>  the mouse behaves as set to on, but cannot be used to enter copy
>  mode.
> +
> +When in copy mode left button starts the selection. You can double/triple 
> click
> +in order to select full words/lines. Right button will extend the selection 
> from
> +the original starting point to the mouse position. You can quit the copy mode
> +via the middle button which will copy the current selection. Note that the 
> word
> +separating characters are coming from the "word-separators" option.
>  .Pp
>  .It Ic mode-style Ar style
>  Set window modes style.
> diff --git a/tmux.h b/tmux.h
> index 3de1da6..128b67c 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -2246,7 +2246,7 @@ extern const char window_clock_table[14][5][5];
>  
>  /* window-copy.c */
>  extern const struct window_mode window_copy_mode;
> -void          window_copy_init_from_pane(struct window_pane *);
> +void          window_copy_init_from_pane(struct window_pane *, int);
>  void          window_copy_init_for_output(struct window_pane *);
>  void printflike2 window_copy_add(struct window_pane *, const char *, ...);
>  void          window_copy_vadd(struct window_pane *, const char *, va_list);
> diff --git a/tty-keys.c b/tty-keys.c
> index 37b8960..95bd2cd 100644
> --- a/tty-keys.c
> +++ b/tty-keys.c
> @@ -765,25 +765,25 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t 
> len, size_t *size)
>                       m->wheel = MOUSE_WHEEL_DOWN;
>               m->event = MOUSE_EVENT_WHEEL;
>       } 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);
>  }
> diff --git a/window-copy.c b/window-copy.c
> index 3ac6b82..3f08b85 100644
> --- a/window-copy.c
> +++ b/window-copy.c
> @@ -155,6 +155,10 @@ struct window_copy_mode_data {
>  
>       enum window_copy_input_type jumptype;
>       char            jumpchar;
> +
> +     int             quit_on_mouse_release;
> +     u_int           mouse_sx, mouse_sy; /* the starting point of dragging */
> +     u_int           mouse_x0, mouse_x1; /* possible starting points */
>  };
>  
>  struct screen *
> @@ -190,6 +194,8 @@ window_copy_init(struct window_pane *wp)
>       data->jumptype = WINDOW_COPY_OFF;
>       data->jumpchar = '\0';
>  
> +     data->quit_on_mouse_release = 0;
> +
>       s = &data->screen;
>       screen_init(s, screen_size_x(&wp->base), screen_size_y(&wp->base), 0);
>       if (options_get_number(&wp->window->options, "mode-mouse"))
> @@ -207,7 +213,7 @@ window_copy_init(struct window_pane *wp)
>  }
>  
>  void
> -window_copy_init_from_pane(struct window_pane *wp)
> +window_copy_init_from_pane(struct window_pane *wp, int quit_on_mouse_release)
>  {
>       struct window_copy_mode_data    *data = wp->modedata;
>       struct screen                   *s = &data->screen;
> @@ -220,6 +226,7 @@ window_copy_init_from_pane(struct window_pane *wp)
>       data->backing = &wp->base;
>       data->cx = data->backing->cx;
>       data->cy = data->backing->cy;
> +     data->quit_on_mouse_release = quit_on_mouse_release;
>  
>       s->cx = data->cx;
>       s->cy = data->cy;
> @@ -870,13 +877,65 @@ 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, 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);
> +}
> +
>  void
>  window_copy_mouse(
>      struct window_pane *wp, struct session *sess, struct mouse_event *m)
>  {
>       struct window_copy_mode_data    *data = wp->modedata;
>       struct screen                   *s = &data->screen;
> -     u_int                            i;
> +     u_int                            i, mouse_backing_y;
> +     int                              pressed, released, dragged;
> +     const char                      *sep;
>  
>       if (m->x >= screen_size_x(s))
>               return;
> @@ -902,35 +961,81 @@ window_copy_mouse(
>               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;
> -     }
> +     pressed = (m->event & MOUSE_EVENT_DOWN);
> +     released = (m->event & MOUSE_EVENT_UP);
> +     dragged = (m->event & MOUSE_EVENT_DRAG);
> +     mouse_backing_y = screen_hsize(data->backing) + m->y - data->oy;
> +     sep = options_get_string(&sess->options, "word-separators");
>  
> -     /* 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 (data->quit_on_mouse_release && m->clicks == 1 && released) {
> +             if (sess != NULL)
> +                     window_pane_reset_mode(wp);
> +             return;
> +        } else if (!pressed) {
> +             /* Let's reset this on release, dragged or wheel events. */
> +             data->quit_on_mouse_release = 0;
> +        }
> +
> +     if (pressed && m->button == 1) {
> +             goto reset_mode;
> +     }
> +     
> +     if (pressed && m->button == 0 && !s->sel.flag) {
>               window_copy_update_cursor(wp, m->x, m->y);
> +             data->mouse_sx = m->x;
> +             data->mouse_sy = mouse_backing_y;
> +             data->mouse_x0 = m->x;
> +             data->mouse_x1 = m->x;
>               window_copy_start_selection(wp);
>               window_copy_redraw_screen(wp);
>       }
>  
> +     if (dragged || (pressed && m->button == 2)) {
> +             window_copy_select_via_mouse(wp, m, sep);
> +     } else if (pressed && m->button == 0) {
> +             /*
> +              * Single click: normal selection.
> +              * Double click: word selection.
> +              * Triple click: line selection.
> +              */
> +
> +             window_copy_update_cursor(wp, m->x, m->y);
> +             data->mouse_sx = m->x;
> +             data->mouse_sy = mouse_backing_y;
> +             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);
> +             }
> +             window_copy_select_via_mouse(wp, m, sep);
> +     }
> +
>       return;
>  
>  reset_mode:
> -     s->mode &= ~MODE_MOUSE_BUTTON;
> -     s->mode |= MODE_MOUSE_STANDARD;
>       if (sess != NULL) {
>               window_copy_copy_selection(wp, NULL);
>               window_pane_reset_mode(wp);
> -- 
> 1.9.3
> 


------------------------------------------------------------------------------
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to