Patch 8.0.1598
Problem:    Cannot select text in a terminal with the mouse.
Solution:   When a job in a terminal is not consuming mouse events, use them
            for modeless selection.  Also stop Insert mode when clicking in a
            terminal window.
Files:      src/libvterm/include/vterm.h, src/libvterm/src/state.c,
            src/libvterm/src/vterm_internal.h, src/terminal.c,
            src/proto/terminal.pro, src/ui.c


*** ../vim-8.0.1597/src/libvterm/include/vterm.h        2017-11-29 
22:33:31.051416026 +0100
--- src/libvterm/include/vterm.h        2018-03-11 17:54:21.447062569 +0100
***************
*** 259,264 ****
--- 259,277 ----
    int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const 
VTermLineInfo *oldinfo, void *user);
  } VTermStateCallbacks;
  
+ typedef struct {
+   VTermPos pos;
+   int    buttons;
+ #define MOUSE_BUTTON_LEFT 0x01
+ #define MOUSE_BUTTON_MIDDLE 0x02
+ #define MOUSE_BUTTON_RIGHT 0x04
+   int      flags;
+ #define MOUSE_WANT_CLICK 0x01
+ #define MOUSE_WANT_DRAG  0x02
+ #define MOUSE_WANT_MOVE  0x04
+   /* useful to add protocol? */
+ } VTermMouseState;
+ 
  VTermState *vterm_obtain_state(VTerm *vt);
  
  void  vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks 
*callbacks, void *user);
***************
*** 272,277 ****
--- 285,291 ----
  void vterm_state_reset(VTermState *state, int hard);
  
  void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos);
+ void vterm_state_get_mousestate(const VTermState *state, VTermMouseState 
*mousestate);
  void vterm_state_get_default_colors(const VTermState *state, VTermColor 
*default_fg, VTermColor *default_bg);
  void vterm_state_get_palette_color(const VTermState *state, int index, 
VTermColor *col);
  void vterm_state_set_default_colors(VTermState *state, const VTermColor 
*default_fg, const VTermColor *default_bg);
*** ../vim-8.0.1597/src/libvterm/src/state.c    2018-02-24 14:03:49.748678084 
+0100
--- src/libvterm/src/state.c    2018-03-11 18:12:34.052424018 +0100
***************
*** 1793,1798 ****
--- 1793,1806 ----
    *cursorpos = state->pos;
  }
  
+ void vterm_state_get_mousestate(const VTermState *state, VTermMouseState 
*mousestate)
+ {
+   mousestate->pos.col = state->mouse_col;
+   mousestate->pos.row = state->mouse_row;
+   mousestate->buttons = state->mouse_buttons;
+   mousestate->flags = state->mouse_flags;
+ }
+ 
  void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks 
*callbacks, void *user)
  {
    if(callbacks) {
*** ../vim-8.0.1597/src/libvterm/src/vterm_internal.h   2018-02-24 
14:03:49.748678084 +0100
--- src/libvterm/src/vterm_internal.h   2018-03-11 17:49:52.268699591 +0100
***************
*** 95,103 ****
    int mouse_col, mouse_row;
    int mouse_buttons;
    int mouse_flags;
- #define MOUSE_WANT_CLICK 0x01
- #define MOUSE_WANT_DRAG  0x02
- #define MOUSE_WANT_MOVE  0x04
  
    enum { MOUSE_X10, MOUSE_UTF8, MOUSE_SGR, MOUSE_RXVT } mouse_protocol;
  
--- 95,100 ----
*** ../vim-8.0.1597/src/terminal.c      2018-03-11 16:55:30.008616433 +0100
--- src/terminal.c      2018-03-11 19:24:19.510441852 +0100
***************
*** 38,45 ****
   * in tl_scrollback are no longer used.
   *
   * TODO:
-  * - if the job in the terminal does not support the mouse, we can use the
-  *   mouse in the Terminal window for copy/paste and scrolling.
   * - When using 'termguicolors' still use the 16 ANSI colors as-is.  Helps for
   * - In the GUI use a terminal emulator for :!cmd.  Make the height the same 
as
   *   the window and position it higher up when it gets filled, so it looks 
like
--- 38,43 ----
***************
*** 900,905 ****
--- 898,1002 ----
      return TRUE;
  }
  
+ static int enter_mouse_col = -1;
+ static int enter_mouse_row = -1;
+ 
+ /*
+  * Handle a mouse click, drag or release.
+  * Return TRUE when a mouse event is sent to the terminal.
+  */
+     static int
+ term_mouse_click(VTerm *vterm, int key)
+ {
+ #if defined(FEAT_CLIPBOARD)
+     /* For modeless selection mouse drag and release events are ignored, 
unless
+      * they are preceded with a mouse down event */
+     static int            ignore_drag_release = TRUE;
+     VTermMouseState mouse_state;
+ 
+     vterm_state_get_mousestate(vterm_obtain_state(vterm), &mouse_state);
+     if (mouse_state.flags == 0)
+     {
+       /* Terminal is not using the mouse, use modeless selection. */
+       switch (key)
+       {
+       case K_LEFTDRAG:
+       case K_LEFTRELEASE:
+       case K_RIGHTDRAG:
+       case K_RIGHTRELEASE:
+               /* Ignore drag and release events when the button-down wasn't
+                * seen before. */
+               if (ignore_drag_release)
+               {
+                   int save_mouse_col, save_mouse_row;
+ 
+                   if (enter_mouse_col < 0)
+                       break;
+ 
+                   /* mouse click in the window gave us focus, handle that
+                    * click now */
+                   save_mouse_col = mouse_col;
+                   save_mouse_row = mouse_row;
+                   mouse_col = enter_mouse_col;
+                   mouse_row = enter_mouse_row;
+                   clip_modeless(MOUSE_LEFT, TRUE, FALSE);
+                   mouse_col = save_mouse_col;
+                   mouse_row = save_mouse_row;
+               }
+               /* FALLTHROUGH */
+       case K_LEFTMOUSE:
+       case K_RIGHTMOUSE:
+               if (key == K_LEFTRELEASE || key == K_RIGHTRELEASE)
+                   ignore_drag_release = TRUE;
+               else
+                   ignore_drag_release = FALSE;
+               /* Should we call mouse_has() here? */
+               if (clip_star.available)
+               {
+                   int     button, is_click, is_drag;
+ 
+                   button = get_mouse_button(KEY2TERMCAP1(key),
+                                                        &is_click, &is_drag);
+                   if (mouse_model_popup() && button == MOUSE_LEFT
+                                              && (mod_mask & MOD_MASK_SHIFT))
+                   {
+                       /* Translate shift-left to right button. */
+                       button = MOUSE_RIGHT;
+                       mod_mask &= ~MOD_MASK_SHIFT;
+                   }
+                   clip_modeless(button, is_click, is_drag);
+               }
+               break;
+ 
+       case K_MIDDLEMOUSE:
+               if (clip_star.available)
+                   insert_reg('*', TRUE);
+               break;
+       }
+       enter_mouse_col = -1;
+       return FALSE;
+     }
+ #endif
+     enter_mouse_col = -1;
+ 
+     switch (key)
+     {
+       case K_LEFTMOUSE:
+       case K_LEFTMOUSE_NM:    term_send_mouse(vterm, 1, 1); break;
+       case K_LEFTDRAG:        term_send_mouse(vterm, 1, 1); break;
+       case K_LEFTRELEASE:
+       case K_LEFTRELEASE_NM:  term_send_mouse(vterm, 1, 0); break;
+       case K_MOUSEMOVE:       term_send_mouse(vterm, 0, 0); break;
+       case K_MIDDLEMOUSE:     term_send_mouse(vterm, 2, 1); break;
+       case K_MIDDLEDRAG:      term_send_mouse(vterm, 2, 1); break;
+       case K_MIDDLERELEASE:   term_send_mouse(vterm, 2, 0); break;
+       case K_RIGHTMOUSE:      term_send_mouse(vterm, 3, 1); break;
+       case K_RIGHTDRAG:       term_send_mouse(vterm, 3, 1); break;
+       case K_RIGHTRELEASE:    term_send_mouse(vterm, 3, 0); break;
+     }
+     return TRUE;
+ }
+ 
  /*
   * Convert typed key "c" into bytes to send to the job.
   * Return the number of bytes in "buf".
***************
*** 995,1011 ****
        case K_MOUSERIGHT:      /* TODO */ return 0;
  
        case K_LEFTMOUSE:
!       case K_LEFTMOUSE_NM:    other = term_send_mouse(vterm, 1, 1); break;
!       case K_LEFTDRAG:        other = term_send_mouse(vterm, 1, 1); break;
        case K_LEFTRELEASE:
!       case K_LEFTRELEASE_NM:  other = term_send_mouse(vterm, 1, 0); break;
!       case K_MOUSEMOVE:       other = term_send_mouse(vterm, 0, 0); break;
!       case K_MIDDLEMOUSE:     other = term_send_mouse(vterm, 2, 1); break;
!       case K_MIDDLEDRAG:      other = term_send_mouse(vterm, 2, 1); break;
!       case K_MIDDLERELEASE:   other = term_send_mouse(vterm, 2, 0); break;
!       case K_RIGHTMOUSE:      other = term_send_mouse(vterm, 3, 1); break;
!       case K_RIGHTDRAG:       other = term_send_mouse(vterm, 3, 1); break;
!       case K_RIGHTRELEASE:    other = term_send_mouse(vterm, 3, 0); break;
        case K_X1MOUSE:         /* TODO */ return 0;
        case K_X1DRAG:          /* TODO */ return 0;
        case K_X1RELEASE:       /* TODO */ return 0;
--- 1092,1112 ----
        case K_MOUSERIGHT:      /* TODO */ return 0;
  
        case K_LEFTMOUSE:
!       case K_LEFTMOUSE_NM:
!       case K_LEFTDRAG:
        case K_LEFTRELEASE:
!       case K_LEFTRELEASE_NM:
!       case K_MOUSEMOVE:
!       case K_MIDDLEMOUSE:
!       case K_MIDDLEDRAG:
!       case K_MIDDLERELEASE:
!       case K_RIGHTMOUSE:
!       case K_RIGHTDRAG:
!       case K_RIGHTRELEASE:    if (!term_mouse_click(vterm, c))
!                                   return 0;
!                               other = TRUE;
!                               break;
! 
        case K_X1MOUSE:         /* TODO */ return 0;
        case K_X1DRAG:          /* TODO */ return 0;
        case K_X1RELEASE:       /* TODO */ return 0;
***************
*** 1473,1478 ****
--- 1574,1581 ----
      return c;
  }
  
+ static int    mouse_was_outside = FALSE;
+ 
  /*
   * Send keys to terminal.
   * Return FAIL when the key needs to be handled in Normal mode.
***************
*** 1483,1489 ****
  {
      char      msg[KEY_BUF_LEN];
      size_t    len;
-     static int        mouse_was_outside = FALSE;
      int               dragging_outside = FALSE;
  
      /* Catch keys that need to be handled as in Normal mode. */
--- 1586,1591 ----
***************
*** 1732,1737 ****
--- 1834,1862 ----
  }
  
  /*
+  * Called when entering a window with the mouse.  If this is a terminal window
+  * we may want to change state.
+  */
+     void
+ term_win_entered()
+ {
+     term_T *term = curbuf->b_term;
+ 
+     if (term != NULL)
+     {
+       if (term_use_loop())
+       {
+           reset_VIsual_and_resel();
+           if (State & INSERT)
+               stop_insert_mode = TRUE;
+       }
+       mouse_was_outside = FALSE;
+       enter_mouse_col = mouse_col;
+       enter_mouse_row = mouse_row;
+     }
+ }
+ 
+ /*
   * Returns TRUE if the current window contains a terminal and we are sending
   * keys to the job.
   */
*** ../vim-8.0.1597/src/proto/terminal.pro      2018-03-10 20:27:32.071757661 
+0100
--- src/proto/terminal.pro      2018-03-11 18:43:41.941098461 +0100
***************
*** 12,17 ****
--- 12,18 ----
  int send_keys_to_term(term_T *term, int c, int typed);
  int terminal_is_active(void);
  cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg);
+ void term_win_entered(void);
  int term_use_loop(void);
  int terminal_loop(int blocking);
  void term_job_ended(job_T *job);
*** ../vim-8.0.1597/src/ui.c    2018-03-04 18:07:04.284592244 +0100
--- src/ui.c    2018-03-11 18:36:56.139560777 +0100
***************
*** 2827,2837 ****
         * (MOUSE_FOCUS was set above if we dragged first). */
        if (dragwin == NULL || (flags & MOUSE_RELEASED))
            win_enter(wp, TRUE);                /* can make wp invalid! */
! #ifdef CHECK_DOUBLE_CLICK
!       /* set topline, to be able to check for double click ourselves */
        if (curwin != old_curwin)
            set_mouse_topline(curwin);
  #endif
        if (on_status_line)                     /* In (or below) status line */
        {
            /* Don't use start_arrow() if we're in the same window */
--- 2827,2844 ----
         * (MOUSE_FOCUS was set above if we dragged first). */
        if (dragwin == NULL || (flags & MOUSE_RELEASED))
            win_enter(wp, TRUE);                /* can make wp invalid! */
! 
        if (curwin != old_curwin)
+       {
+ #ifdef CHECK_DOUBLE_CLICK
+           /* set topline, to be able to check for double click ourselves */
            set_mouse_topline(curwin);
  #endif
+ #ifdef FEAT_TERMINAL
+           /* when entering a terminal window may change state */
+           term_win_entered();
+ #endif
+       }
        if (on_status_line)                     /* In (or below) status line */
        {
            /* Don't use start_arrow() if we're in the same window */
*** ../vim-8.0.1597/src/version.c       2018-03-11 17:02:07.310194396 +0100
--- src/version.c       2018-03-11 19:28:41.804859926 +0100
***************
*** 768,769 ****
--- 768,771 ----
  {   /* Add new patch number below this line */
+ /**/
+     1598,
  /**/

-- 
Normal people believe that if it ain't broke, don't fix it.  Engineers believe
that if it ain't broke, it doesn't have enough features yet.
                                (Scott Adams - The Dilbert principle)

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui