mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	ui: multigrid mouse support
This commit is contained in:
		@@ -525,6 +525,7 @@ tabs.
 | 
			
		||||
 | 
			
		||||
See |ui-linegrid| for grid events.
 | 
			
		||||
See |nvim_ui_try_resize_grid| in |api-ui| to request changing the grid size.
 | 
			
		||||
See |nvim_input_mouse| for sending mouse events to Nvim.
 | 
			
		||||
 | 
			
		||||
==============================================================================
 | 
			
		||||
Popupmenu Events						 *ui-popupmenu*
 | 
			
		||||
 
 | 
			
		||||
@@ -198,6 +198,10 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
 | 
			
		||||
/// @note |keycodes| like <CR> are translated, so "<" is special.
 | 
			
		||||
///       To input a literal "<", send <LT>.
 | 
			
		||||
///
 | 
			
		||||
/// For mouse events use |nvim_input_mouse()|. For back-compat reasons
 | 
			
		||||
/// this method supports mouse input as "<LeftMouse><col,row>". This
 | 
			
		||||
/// usage is deprecated since API level 6, use the dedicated method instead.
 | 
			
		||||
///
 | 
			
		||||
/// @param keys to be typed
 | 
			
		||||
/// @return Number of bytes actually written (can be fewer than
 | 
			
		||||
///         requested if the buffer becomes full).
 | 
			
		||||
@@ -207,6 +211,98 @@ Integer nvim_input(String keys)
 | 
			
		||||
  return (Integer)input_enqueue(keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Send mouse event from GUI
 | 
			
		||||
///
 | 
			
		||||
/// The call is non-blocking. It doesn't wait on any resulting action, but
 | 
			
		||||
/// queues the event to be processed soon by the event loop.
 | 
			
		||||
///
 | 
			
		||||
/// @note Currently this doesn't support "scripting" multiple mouse events
 | 
			
		||||
///       by calling it multiple times in a loop: the intermediate mouse
 | 
			
		||||
///       positions will be ignored. It should be used to implement real-time
 | 
			
		||||
///       mouse input in a GUI. The deprecated pseudokey form
 | 
			
		||||
///       ("<LeftMouse><col,row>") in |nvim_input()| has the same limitiation.
 | 
			
		||||
///
 | 
			
		||||
/// @param button Which mouse button, one of "left", "right", "middle" or
 | 
			
		||||
///               "wheel".
 | 
			
		||||
/// @param action For ordinary buttons, one of "press", "drag" and "release"
 | 
			
		||||
///               For the wheel, use "up", "down", "left" and "right".
 | 
			
		||||
/// @param modifier String of modifiers each represented by a single char.
 | 
			
		||||
///                 The same specifiers are used as for a key press, except
 | 
			
		||||
///                 that the "-" separator is optional, so "C-A-", "c-a"
 | 
			
		||||
///                 and "CA" can all be used to specify Ctrl+Alt+click
 | 
			
		||||
/// @param grid For a client using |ui-multigrid| pass in the grid number.
 | 
			
		||||
///             Other clients should pass in 0 (not 1).
 | 
			
		||||
/// @param row row position of mouse (zero-based, like in redraw events)
 | 
			
		||||
/// @param col column position of mouse (zero-based, like in redraw events)
 | 
			
		||||
void nvim_input_mouse(String button, String action, String modifier,
 | 
			
		||||
                      Integer grid, Integer row, Integer col, Error *err)
 | 
			
		||||
  FUNC_API_SINCE(6) FUNC_API_ASYNC
 | 
			
		||||
{
 | 
			
		||||
  if (button.data == NULL || action.data == NULL) {
 | 
			
		||||
    goto error;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int code = 0;
 | 
			
		||||
 | 
			
		||||
  if (strequal(button.data, "left")) {
 | 
			
		||||
    code = KE_LEFTMOUSE;
 | 
			
		||||
  } else if (strequal(button.data, "middle")) {
 | 
			
		||||
    code = KE_MIDDLEMOUSE;
 | 
			
		||||
  } else if (strequal(button.data, "right")) {
 | 
			
		||||
    code = KE_RIGHTMOUSE;
 | 
			
		||||
  } else if (strequal(button.data, "wheel")) {
 | 
			
		||||
    code = KE_MOUSEDOWN;
 | 
			
		||||
  } else {
 | 
			
		||||
    goto error;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (code == KE_MOUSEDOWN) {
 | 
			
		||||
    if (strequal(action.data, "down")) {
 | 
			
		||||
      code = KE_MOUSEUP;
 | 
			
		||||
    } else if (strequal(action.data, "up")) {
 | 
			
		||||
      code = KE_MOUSEDOWN;
 | 
			
		||||
    } else if (strequal(action.data, "left")) {
 | 
			
		||||
      code = KE_MOUSERIGHT;
 | 
			
		||||
    } else if (strequal(action.data, "right")) {
 | 
			
		||||
      code = KE_MOUSELEFT;
 | 
			
		||||
    } else {
 | 
			
		||||
      goto error;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    if (strequal(action.data, "press")) {
 | 
			
		||||
      // pass
 | 
			
		||||
    } else if (strequal(action.data, "drag")) {
 | 
			
		||||
      code += KE_LEFTDRAG - KE_LEFTMOUSE;
 | 
			
		||||
    } else if (strequal(action.data, "release")) {
 | 
			
		||||
      code += KE_LEFTRELEASE - KE_LEFTMOUSE;
 | 
			
		||||
    } else {
 | 
			
		||||
      goto error;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int modmask = 0;
 | 
			
		||||
  for (size_t i = 0; i < modifier.size; i++) {
 | 
			
		||||
    char byte = modifier.data[i];
 | 
			
		||||
    if (byte == '-') {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    int mod = name_to_mod_mask(byte);
 | 
			
		||||
    if (mod == 0) {
 | 
			
		||||
      api_set_error(err, kErrorTypeValidation,
 | 
			
		||||
                    "invalid modifier %c", byte);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    modmask |= mod;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  input_enqueue_mouse(code, (uint8_t)modmask, (int)grid, (int)row, (int)col);
 | 
			
		||||
  return;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
  api_set_error(err, kErrorTypeValidation,
 | 
			
		||||
                "invalid button or action");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with
 | 
			
		||||
/// the internal representation.
 | 
			
		||||
///
 | 
			
		||||
 
 | 
			
		||||
@@ -7943,11 +7943,10 @@ static void ins_mousescroll(int dir)
 | 
			
		||||
  pos_T tpos = curwin->w_cursor;
 | 
			
		||||
 | 
			
		||||
  if (mouse_row >= 0 && mouse_col >= 0) {
 | 
			
		||||
    int row = mouse_row;
 | 
			
		||||
    int col = mouse_col;
 | 
			
		||||
    int row = mouse_row, col = mouse_col, grid = mouse_grid;
 | 
			
		||||
 | 
			
		||||
    // find the window at the pointer coordinates
 | 
			
		||||
    win_T *const wp = mouse_find_win(&row, &col);
 | 
			
		||||
    win_T *wp = mouse_find_win(&grid, &row, &col);
 | 
			
		||||
    if (wp == NULL) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -9521,6 +9521,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
 | 
			
		||||
    if (is_mouse_key(n)) {
 | 
			
		||||
      int row = mouse_row;
 | 
			
		||||
      int col = mouse_col;
 | 
			
		||||
      int grid = mouse_grid;
 | 
			
		||||
      win_T       *win;
 | 
			
		||||
      linenr_T lnum;
 | 
			
		||||
      win_T       *wp;
 | 
			
		||||
@@ -9529,7 +9530,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
 | 
			
		||||
      if (row >= 0 && col >= 0) {
 | 
			
		||||
        /* Find the window at the mouse coordinates and compute the
 | 
			
		||||
         * text position. */
 | 
			
		||||
        win = mouse_find_win(&row, &col);
 | 
			
		||||
        win = mouse_find_win(&grid, &row, &col);
 | 
			
		||||
        if (win == NULL) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1187,10 +1187,11 @@ void save_typebuf(void)
 | 
			
		||||
  alloc_typebuf();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int old_char = -1;       /* character put back by vungetc() */
 | 
			
		||||
static int old_mod_mask;        /* mod_mask for ungotten character */
 | 
			
		||||
static int old_mouse_row;       /* mouse_row related to old_char */
 | 
			
		||||
static int old_mouse_col;       /* mouse_col related to old_char */
 | 
			
		||||
static int old_char = -1;   // character put back by vungetc()
 | 
			
		||||
static int old_mod_mask;    // mod_mask for ungotten character
 | 
			
		||||
static int old_mouse_grid;  // mouse_grid related to old_char
 | 
			
		||||
static int old_mouse_row;   // mouse_row related to old_char
 | 
			
		||||
static int old_mouse_col;   // mouse_col related to old_char
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -1391,6 +1392,7 @@ int vgetc(void)
 | 
			
		||||
    c = old_char;
 | 
			
		||||
    old_char = -1;
 | 
			
		||||
    mod_mask = old_mod_mask;
 | 
			
		||||
    mouse_grid = old_mouse_grid;
 | 
			
		||||
    mouse_row = old_mouse_row;
 | 
			
		||||
    mouse_col = old_mouse_col;
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -1585,6 +1587,7 @@ vungetc ( /* unget one character (can only be done once!) */
 | 
			
		||||
{
 | 
			
		||||
  old_char = c;
 | 
			
		||||
  old_mod_mask = mod_mask;
 | 
			
		||||
  old_mouse_grid = mouse_grid;
 | 
			
		||||
  old_mouse_row = mouse_row;
 | 
			
		||||
  old_mouse_col = mouse_col;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -394,9 +394,8 @@ EXTERN bufref_T au_new_curbuf INIT(= { NULL, 0, 0 });
 | 
			
		||||
EXTERN buf_T *au_pending_free_buf INIT(= NULL);
 | 
			
		||||
EXTERN win_T *au_pending_free_win INIT(= NULL);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Mouse coordinates, set by check_termcode()
 | 
			
		||||
 */
 | 
			
		||||
// Mouse coordinates, set by handle_mouse_event()
 | 
			
		||||
EXTERN int mouse_grid;
 | 
			
		||||
EXTERN int mouse_row;
 | 
			
		||||
EXTERN int mouse_col;
 | 
			
		||||
EXTERN bool mouse_past_bottom INIT(= false);    /* mouse below last line */
 | 
			
		||||
 
 | 
			
		||||
@@ -70,6 +70,7 @@ int jump_to_mouse(int flags,
 | 
			
		||||
  bool first;
 | 
			
		||||
  int row = mouse_row;
 | 
			
		||||
  int col = mouse_col;
 | 
			
		||||
  int grid = mouse_grid;
 | 
			
		||||
  int mouse_char;
 | 
			
		||||
 | 
			
		||||
  mouse_past_bottom = false;
 | 
			
		||||
@@ -125,20 +126,22 @@ retnomove:
 | 
			
		||||
      return IN_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
    // find the window where the row is in
 | 
			
		||||
    wp = mouse_find_win(&row, &col);
 | 
			
		||||
    wp = mouse_find_win(&grid, &row, &col);
 | 
			
		||||
    if (wp == NULL) {
 | 
			
		||||
      return IN_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
    dragwin = NULL;
 | 
			
		||||
    // winpos and height may change in win_enter()!
 | 
			
		||||
    if (row >= wp->w_height) {                  // In (or below) status line
 | 
			
		||||
    if (grid == DEFAULT_GRID_HANDLE && row >= wp->w_height) {
 | 
			
		||||
      // In (or below) status line
 | 
			
		||||
      on_status_line = row - wp->w_height + 1;
 | 
			
		||||
      dragwin = wp;
 | 
			
		||||
    } else {
 | 
			
		||||
      on_status_line = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (col >= wp->w_width) {           // In separator line
 | 
			
		||||
    if (grid == DEFAULT_GRID_HANDLE && col >= wp->w_width) {
 | 
			
		||||
      // In separator line
 | 
			
		||||
      on_sep_line = col - wp->w_width + 1;
 | 
			
		||||
      dragwin = wp;
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -160,12 +163,10 @@ retnomove:
 | 
			
		||||
        && (wp->w_buffer != curwin->w_buffer
 | 
			
		||||
            || (!on_status_line
 | 
			
		||||
                && !on_sep_line
 | 
			
		||||
                && (
 | 
			
		||||
                  wp->w_p_rl ? col < wp->w_width - wp->w_p_fdc :
 | 
			
		||||
                                     col >= wp->w_p_fdc
 | 
			
		||||
                                             + (cmdwin_type == 0 && wp ==
 | 
			
		||||
                                                curwin ? 0 : 1)
 | 
			
		||||
                  )
 | 
			
		||||
                && (wp->w_p_rl
 | 
			
		||||
                    ? col < wp->w_grid.Columns - wp->w_p_fdc
 | 
			
		||||
                    : col >= wp->w_p_fdc + (cmdwin_type == 0 && wp == curwin
 | 
			
		||||
                                            ? 0 : 1))
 | 
			
		||||
                && (flags & MOUSE_MAY_STOP_VIS)))) {
 | 
			
		||||
      end_visual_mode();
 | 
			
		||||
      redraw_curbuf_later(INVERTED);            // delete the inversion
 | 
			
		||||
@@ -257,7 +258,7 @@ retnomove:
 | 
			
		||||
        ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
 | 
			
		||||
      redraw_later(VALID);
 | 
			
		||||
      row = 0;
 | 
			
		||||
    } else if (row >= curwin->w_height)   {
 | 
			
		||||
    } else if (row >= curwin->w_grid.Rows)   {
 | 
			
		||||
      count = 0;
 | 
			
		||||
      for (first = true; curwin->w_topline < curbuf->b_ml.ml_line_count; ) {
 | 
			
		||||
        if (curwin->w_topfill > 0) {
 | 
			
		||||
@@ -266,7 +267,7 @@ retnomove:
 | 
			
		||||
          count += plines(curwin->w_topline);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!first && count > row - curwin->w_height + 1) {
 | 
			
		||||
        if (!first && count > row - curwin->w_grid.Rows + 1) {
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        first = false;
 | 
			
		||||
@@ -288,7 +289,7 @@ retnomove:
 | 
			
		||||
      redraw_later(VALID);
 | 
			
		||||
      curwin->w_valid &=
 | 
			
		||||
        ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP);
 | 
			
		||||
      row = curwin->w_height - 1;
 | 
			
		||||
      row = curwin->w_grid.Rows - 1;
 | 
			
		||||
    } else if (row == 0)   {
 | 
			
		||||
      // When dragging the mouse, while the text has been scrolled up as
 | 
			
		||||
      // far as it goes, moving the mouse in the top line should scroll
 | 
			
		||||
@@ -303,7 +304,7 @@ retnomove:
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Check for position outside of the fold column.
 | 
			
		||||
  if (curwin->w_p_rl ? col < curwin->w_width - curwin->w_p_fdc :
 | 
			
		||||
  if (curwin->w_p_rl ? col < curwin->w_grid.Columns - curwin->w_p_fdc :
 | 
			
		||||
      col >= curwin->w_p_fdc + (cmdwin_type == 0 ? 0 : 1)) {
 | 
			
		||||
    mouse_char = ' ';
 | 
			
		||||
  }
 | 
			
		||||
@@ -369,8 +370,9 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
 | 
			
		||||
  int off;
 | 
			
		||||
  int count;
 | 
			
		||||
 | 
			
		||||
  if (win->w_p_rl)
 | 
			
		||||
    col = win->w_width - 1 - col;
 | 
			
		||||
  if (win->w_p_rl) {
 | 
			
		||||
    col = win->w_grid.Columns - 1 - col;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  lnum = win->w_topline;
 | 
			
		||||
 | 
			
		||||
@@ -407,7 +409,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
 | 
			
		||||
    off = win_col_off(win) - win_col_off2(win);
 | 
			
		||||
    if (col < off)
 | 
			
		||||
      col = off;
 | 
			
		||||
    col += row * (win->w_width - off);
 | 
			
		||||
    col += row * (win->w_grid.Columns - off);
 | 
			
		||||
    // add skip column (for long wrapping line)
 | 
			
		||||
    col += win->w_skipcol;
 | 
			
		||||
  }
 | 
			
		||||
@@ -428,11 +430,23 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
 | 
			
		||||
  return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Find the window at screen position "*rowp" and "*colp".  The positions are
 | 
			
		||||
// updated to become relative to the top-left of the window.
 | 
			
		||||
// Returns NULL when something is wrong.
 | 
			
		||||
win_T *mouse_find_win(int *rowp, int *colp)
 | 
			
		||||
/// Find the window at "grid" position "*rowp" and "*colp".  The positions are
 | 
			
		||||
/// updated to become relative to the top-left of the window.
 | 
			
		||||
///
 | 
			
		||||
/// @return NULL when something is wrong.
 | 
			
		||||
win_T *mouse_find_win(int *gridp, int *rowp, int *colp)
 | 
			
		||||
{
 | 
			
		||||
  win_T *wp_grid = mouse_find_grid_win(gridp, rowp, colp);
 | 
			
		||||
  if (wp_grid) {
 | 
			
		||||
    return wp_grid;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // TODO(bfredl): grid zero will have floats displayed on it, and will
 | 
			
		||||
  // be adjusted to float grids.
 | 
			
		||||
  if (*gridp == 0) {
 | 
			
		||||
    *gridp = DEFAULT_GRID_HANDLE;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  frame_T     *fp;
 | 
			
		||||
 | 
			
		||||
  fp = topframe;
 | 
			
		||||
@@ -464,6 +478,19 @@ win_T *mouse_find_win(int *rowp, int *colp)
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static win_T *mouse_find_grid_win(int *grid, int *rowp, int *colp)
 | 
			
		||||
{
 | 
			
		||||
  if (*grid > 1) {
 | 
			
		||||
    win_T *wp = get_win_by_grid_handle(*grid);
 | 
			
		||||
    if (wp && wp->w_grid.chars) {
 | 
			
		||||
      *rowp = MIN(*rowp, wp->w_grid.Rows-1);
 | 
			
		||||
      *colp = MIN(*colp, wp->w_grid.Columns-1);
 | 
			
		||||
      return wp;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * setmouse() - switch mouse on/off depending on current mode and 'mouse'
 | 
			
		||||
 */
 | 
			
		||||
@@ -595,7 +622,7 @@ bool mouse_scroll_horiz(int dir)
 | 
			
		||||
 | 
			
		||||
  int step = 6;
 | 
			
		||||
  if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) {
 | 
			
		||||
      step = curwin->w_width;
 | 
			
		||||
      step = curwin->w_grid.Columns;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int leftcol = curwin->w_leftcol + (dir == MSCR_RIGHT ? -step : +step);
 | 
			
		||||
@@ -647,7 +674,7 @@ static int mouse_adjust_click(win_T *wp, int row, int col)
 | 
			
		||||
  // Find the offset where scanning should begin.
 | 
			
		||||
  int offset = wp->w_leftcol;
 | 
			
		||||
  if (row > 0) {
 | 
			
		||||
    offset += row * (wp->w_width - win_col_off(wp) - win_col_off2(wp) -
 | 
			
		||||
    offset += row * (wp->w_grid.Columns - win_col_off(wp) - win_col_off2(wp) -
 | 
			
		||||
                     wp->w_leftcol + wp->w_skipcol);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3997,13 +3997,14 @@ static void nv_mousescroll(cmdarg_T *cap)
 | 
			
		||||
  win_T *old_curwin = curwin;
 | 
			
		||||
 | 
			
		||||
  if (mouse_row >= 0 && mouse_col >= 0) {
 | 
			
		||||
    int row, col;
 | 
			
		||||
    int grid, row, col;
 | 
			
		||||
 | 
			
		||||
    grid = mouse_grid;
 | 
			
		||||
    row = mouse_row;
 | 
			
		||||
    col = mouse_col;
 | 
			
		||||
 | 
			
		||||
    // find the window at the pointer coordinates
 | 
			
		||||
    win_T *const wp = mouse_find_win(&row, &col);
 | 
			
		||||
    win_T *wp = mouse_find_win(&grid, &row, &col);
 | 
			
		||||
    if (wp == NULL) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -236,6 +236,53 @@ size_t input_enqueue(String keys)
 | 
			
		||||
  return rv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t check_multiclick(int code, int grid, int row, int col)
 | 
			
		||||
{
 | 
			
		||||
  static int orig_num_clicks = 0;
 | 
			
		||||
  static int orig_mouse_code = 0;
 | 
			
		||||
  static int orig_mouse_grid = 0;
 | 
			
		||||
  static int orig_mouse_col = 0;
 | 
			
		||||
  static int orig_mouse_row = 0;
 | 
			
		||||
  static uint64_t orig_mouse_time = 0;  // time of previous mouse click
 | 
			
		||||
 | 
			
		||||
  if (code == KE_LEFTRELEASE || code == KE_RIGHTRELEASE
 | 
			
		||||
      || code == KE_MIDDLERELEASE) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  uint64_t mouse_time = os_hrtime();    // time of current mouse click (ns)
 | 
			
		||||
 | 
			
		||||
  // compute the time elapsed since the previous mouse click and
 | 
			
		||||
  // convert p_mouse from ms to ns
 | 
			
		||||
  uint64_t timediff = mouse_time - orig_mouse_time;
 | 
			
		||||
  uint64_t mouset = (uint64_t)p_mouset * 1000000;
 | 
			
		||||
  if (code == orig_mouse_code
 | 
			
		||||
      && timediff < mouset
 | 
			
		||||
      && orig_num_clicks != 4
 | 
			
		||||
      && orig_mouse_grid == grid
 | 
			
		||||
      && orig_mouse_col == col
 | 
			
		||||
      && orig_mouse_row == row) {
 | 
			
		||||
    orig_num_clicks++;
 | 
			
		||||
  } else {
 | 
			
		||||
    orig_num_clicks = 1;
 | 
			
		||||
  }
 | 
			
		||||
  orig_mouse_code = code;
 | 
			
		||||
  orig_mouse_grid = grid;
 | 
			
		||||
  orig_mouse_col = col;
 | 
			
		||||
  orig_mouse_row = row;
 | 
			
		||||
  orig_mouse_time = mouse_time;
 | 
			
		||||
 | 
			
		||||
  uint8_t modifiers = 0;
 | 
			
		||||
  if (orig_num_clicks == 2) {
 | 
			
		||||
    modifiers |= MOD_MASK_2CLICK;
 | 
			
		||||
  } else if (orig_num_clicks == 3) {
 | 
			
		||||
    modifiers |= MOD_MASK_3CLICK;
 | 
			
		||||
  } else if (orig_num_clicks == 4) {
 | 
			
		||||
    modifiers |= MOD_MASK_4CLICK;
 | 
			
		||||
  }
 | 
			
		||||
  return modifiers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Mouse event handling code(Extract row/col if available and detect multiple
 | 
			
		||||
// clicks)
 | 
			
		||||
static unsigned int handle_mouse_event(char **ptr, uint8_t *buf,
 | 
			
		||||
@@ -274,48 +321,16 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf,
 | 
			
		||||
      if (row >= Rows) {
 | 
			
		||||
        row = (int)Rows - 1;
 | 
			
		||||
      }
 | 
			
		||||
      mouse_grid = 0;
 | 
			
		||||
      mouse_row = row;
 | 
			
		||||
      mouse_col = col;
 | 
			
		||||
    }
 | 
			
		||||
    *ptr += advance;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static int orig_num_clicks = 0;
 | 
			
		||||
  if (mouse_code != KE_LEFTRELEASE && mouse_code != KE_RIGHTRELEASE
 | 
			
		||||
      && mouse_code != KE_MIDDLERELEASE) {
 | 
			
		||||
      static int orig_mouse_code = 0;
 | 
			
		||||
      static int orig_mouse_col = 0;
 | 
			
		||||
      static int orig_mouse_row = 0;
 | 
			
		||||
      static uint64_t orig_mouse_time = 0;  // time of previous mouse click
 | 
			
		||||
      uint64_t mouse_time = os_hrtime();    // time of current mouse click (ns)
 | 
			
		||||
  uint8_t modifiers = check_multiclick(mouse_code, mouse_grid,
 | 
			
		||||
                                       mouse_row, mouse_col);
 | 
			
		||||
 | 
			
		||||
      // compute the time elapsed since the previous mouse click and
 | 
			
		||||
      // convert p_mouse from ms to ns
 | 
			
		||||
      uint64_t timediff = mouse_time - orig_mouse_time;
 | 
			
		||||
      uint64_t mouset = (uint64_t)p_mouset * 1000000;
 | 
			
		||||
      if (mouse_code == orig_mouse_code
 | 
			
		||||
          && timediff < mouset
 | 
			
		||||
          && orig_num_clicks != 4
 | 
			
		||||
          && orig_mouse_col == mouse_col
 | 
			
		||||
          && orig_mouse_row == mouse_row) {
 | 
			
		||||
        orig_num_clicks++;
 | 
			
		||||
      } else {
 | 
			
		||||
        orig_num_clicks = 1;
 | 
			
		||||
      }
 | 
			
		||||
      orig_mouse_code = mouse_code;
 | 
			
		||||
      orig_mouse_col = mouse_col;
 | 
			
		||||
      orig_mouse_row = mouse_row;
 | 
			
		||||
      orig_mouse_time = mouse_time;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  uint8_t modifiers = 0;
 | 
			
		||||
  if (orig_num_clicks == 2) {
 | 
			
		||||
    modifiers |= MOD_MASK_2CLICK;
 | 
			
		||||
  } else if (orig_num_clicks == 3) {
 | 
			
		||||
    modifiers |= MOD_MASK_3CLICK;
 | 
			
		||||
  } else if (orig_num_clicks == 4) {
 | 
			
		||||
    modifiers |= MOD_MASK_4CLICK;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (modifiers) {
 | 
			
		||||
    if (buf[1] != KS_MODIFIER) {
 | 
			
		||||
@@ -334,6 +349,30 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf,
 | 
			
		||||
  return bufsize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t input_enqueue_mouse(int code, uint8_t modifier,
 | 
			
		||||
                           int grid, int row, int col)
 | 
			
		||||
{
 | 
			
		||||
  modifier |= check_multiclick(code, grid, row, col);
 | 
			
		||||
  uint8_t buf[7], *p = buf;
 | 
			
		||||
  if (modifier) {
 | 
			
		||||
    p[0] = K_SPECIAL;
 | 
			
		||||
    p[1] = KS_MODIFIER;
 | 
			
		||||
    p[2] = modifier;
 | 
			
		||||
    p += 3;
 | 
			
		||||
  }
 | 
			
		||||
  p[0] = K_SPECIAL;
 | 
			
		||||
  p[1] = KS_EXTRA;
 | 
			
		||||
  p[2] = (uint8_t)code;
 | 
			
		||||
 | 
			
		||||
  mouse_grid = grid;
 | 
			
		||||
  mouse_row = row;
 | 
			
		||||
  mouse_col = col;
 | 
			
		||||
 | 
			
		||||
  size_t written = 3 + (size_t)(p-buf);
 | 
			
		||||
  rbuffer_write(input_buffer, (char *)buf, written);
 | 
			
		||||
  return written;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// @return true if the main loop is blocked and waiting for input.
 | 
			
		||||
bool input_blocking(void)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -981,8 +981,8 @@ static void mouse_action(Terminal *term, int button, int row, int col,
 | 
			
		||||
// terminal should lose focus
 | 
			
		||||
static bool send_mouse_event(Terminal *term, int c)
 | 
			
		||||
{
 | 
			
		||||
  int row = mouse_row, col = mouse_col;
 | 
			
		||||
  win_T *mouse_win = mouse_find_win(&row, &col);
 | 
			
		||||
  int row = mouse_row, col = mouse_col, grid = mouse_grid;
 | 
			
		||||
  win_T *mouse_win = mouse_find_win(&grid, &row, &col);
 | 
			
		||||
 | 
			
		||||
  if (term->forward_mouse && mouse_win->w_buffer->terminal == term) {
 | 
			
		||||
    // event in the terminal window and mouse events was enabled by the
 | 
			
		||||
 
 | 
			
		||||
@@ -454,5 +454,6 @@ void ui_grid_resize(handle_T grid_handle, int width, int height, Error *error)
 | 
			
		||||
 | 
			
		||||
  wp->w_grid.requested_rows = (int)height;
 | 
			
		||||
  wp->w_grid.requested_cols = (int)width;
 | 
			
		||||
  win_inner_width_changed(wp);
 | 
			
		||||
  redraw_win_later(wp, SOME_VALID);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5031,10 +5031,8 @@ void scroll_to_fraction(win_T *wp, int prev_height)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Set the width of a window.
 | 
			
		||||
void win_new_width(win_T *wp, int width)
 | 
			
		||||
void win_inner_width_changed(win_T *wp)
 | 
			
		||||
{
 | 
			
		||||
  wp->w_width = width;
 | 
			
		||||
  wp->w_lines_valid = 0;
 | 
			
		||||
  changed_line_abv_curs_win(wp);
 | 
			
		||||
  invalidate_botline_win(wp);
 | 
			
		||||
@@ -5042,6 +5040,20 @@ void win_new_width(win_T *wp, int width)
 | 
			
		||||
    update_topline();
 | 
			
		||||
    curs_columns(TRUE);         /* validate w_wrow */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Set the width of a window.
 | 
			
		||||
void win_new_width(win_T *wp, int width)
 | 
			
		||||
{
 | 
			
		||||
  wp->w_width = width;
 | 
			
		||||
  // TODO(bfredl): refactor this. There should be some variable
 | 
			
		||||
  // wp->w_inner_width which always contains the final actual width.
 | 
			
		||||
  // Alternatively use wp->w_width for this and introduce wp->w_outer_width
 | 
			
		||||
  // Then use this to fix terminal_resize.
 | 
			
		||||
  if (!ui_is_external(kUIMultigrid) || wp->w_grid.requested_cols == 0) {
 | 
			
		||||
    win_inner_width_changed(wp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  redraw_win_later(wp, NOT_VALID);
 | 
			
		||||
  wp->w_redr_status = TRUE;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -440,16 +440,34 @@ describe('ui/mouse/input', function()
 | 
			
		||||
 | 
			
		||||
      local test_click = function(name, click_str, click_num, mouse_button,
 | 
			
		||||
                                  modifiers)
 | 
			
		||||
        it(name .. ' works', function()
 | 
			
		||||
 | 
			
		||||
        local function doit(do_click)
 | 
			
		||||
          eq(1, funcs.has('tablineat'))
 | 
			
		||||
          feed(click_str .. '<3,0>')
 | 
			
		||||
          do_click(0,3)
 | 
			
		||||
          check_reply({0, click_num, mouse_button, modifiers})
 | 
			
		||||
          feed(click_str .. '<4,0>')
 | 
			
		||||
          do_click(0,4)
 | 
			
		||||
          check_reply({})
 | 
			
		||||
          feed(click_str .. '<6,0>')
 | 
			
		||||
          do_click(0,6)
 | 
			
		||||
          check_reply({5, click_num, mouse_button, modifiers, 2})
 | 
			
		||||
          feed(click_str .. '<13,0>')
 | 
			
		||||
          do_click(0,13)
 | 
			
		||||
          check_reply({5, click_num, mouse_button, modifiers, 2})
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it(name .. ' works (pseudokey)', function()
 | 
			
		||||
          doit(function (row,col)
 | 
			
		||||
              feed(click_str .. '<' .. col .. ',' .. row .. '>')
 | 
			
		||||
          end)
 | 
			
		||||
        end)
 | 
			
		||||
 | 
			
		||||
        it(name .. ' works (nvim_input_mouse)', function()
 | 
			
		||||
          doit(function (row,col)
 | 
			
		||||
            local buttons = {l='left',m='middle',r='right'}
 | 
			
		||||
            local modstr = (click_num > 1) and tostring(click_num) or ''
 | 
			
		||||
            for char in string.gmatch(modifiers, '%w') do
 | 
			
		||||
              modstr = modstr .. char .. '-' -- - not needed but should be accepted
 | 
			
		||||
            end
 | 
			
		||||
            meths.input_mouse(buttons[mouse_button], 'press', modstr, 0, row, col)
 | 
			
		||||
          end)
 | 
			
		||||
        end)
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
@@ -617,7 +635,7 @@ describe('ui/mouse/input', function()
 | 
			
		||||
    feed('<cr>')
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('mouse whell will target the hovered window', function()
 | 
			
		||||
  local function wheel(use_api)
 | 
			
		||||
    feed('ggdG')
 | 
			
		||||
    insert([[
 | 
			
		||||
    Inserting
 | 
			
		||||
@@ -647,7 +665,11 @@ describe('ui/mouse/input', function()
 | 
			
		||||
      {4:[No Name] [+]                                        }|
 | 
			
		||||
      :vsp                                                 |
 | 
			
		||||
    ]])
 | 
			
		||||
    if use_api then
 | 
			
		||||
      meths.input_mouse('wheel', 'down', '', 0, 0, 0)
 | 
			
		||||
    else
 | 
			
		||||
      feed('<ScrollWheelDown><0,0>')
 | 
			
		||||
    end
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      mouse scrolling           {4:│}lines                     |
 | 
			
		||||
      ^                          {4:│}to                        |
 | 
			
		||||
@@ -664,7 +686,11 @@ describe('ui/mouse/input', function()
 | 
			
		||||
      {4:[No Name] [+]                                        }|
 | 
			
		||||
      :vsp                                                 |
 | 
			
		||||
    ]])
 | 
			
		||||
    if use_api then
 | 
			
		||||
      meths.input_mouse('wheel', 'up', '', 0, 0, 27)
 | 
			
		||||
    else
 | 
			
		||||
      feed('<ScrollWheelUp><27,0>')
 | 
			
		||||
    end
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      mouse scrolling           {4:│}text                      |
 | 
			
		||||
      ^                          {4:│}with                      |
 | 
			
		||||
@@ -681,7 +707,12 @@ describe('ui/mouse/input', function()
 | 
			
		||||
      {4:[No Name] [+]                                        }|
 | 
			
		||||
      :vsp                                                 |
 | 
			
		||||
    ]])
 | 
			
		||||
    if use_api then
 | 
			
		||||
      meths.input_mouse('wheel', 'up', '', 0, 7, 27)
 | 
			
		||||
      meths.input_mouse('wheel', 'up', '', 0, 7, 27)
 | 
			
		||||
    else
 | 
			
		||||
      feed('<ScrollWheelUp><27,7><ScrollWheelUp>')
 | 
			
		||||
    end
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      mouse scrolling           {4:│}text                      |
 | 
			
		||||
      ^                          {4:│}with                      |
 | 
			
		||||
@@ -698,9 +729,17 @@ describe('ui/mouse/input', function()
 | 
			
		||||
      {4:[No Name] [+]                                        }|
 | 
			
		||||
      :vsp                                                 |
 | 
			
		||||
    ]])
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  it('mouse wheel will target the hovered window (pseudokey)', function()
 | 
			
		||||
    wheel(false)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('horizontal scrolling', function()
 | 
			
		||||
  it('mouse wheel will target the hovered window (nvim_input_mouse)', function()
 | 
			
		||||
    wheel(true)
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('horizontal scrolling (pseudokey)', function()
 | 
			
		||||
    command('set sidescroll=0')
 | 
			
		||||
    feed("<esc>:set nowrap<cr>")
 | 
			
		||||
 | 
			
		||||
@@ -732,6 +771,39 @@ describe('ui/mouse/input', function()
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('horizontal scrolling (nvim_input_mouse)', function()
 | 
			
		||||
    command('set sidescroll=0')
 | 
			
		||||
    feed("<esc>:set nowrap<cr>")
 | 
			
		||||
 | 
			
		||||
    feed("a <esc>20Ab<esc>")
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
                               |
 | 
			
		||||
                               |
 | 
			
		||||
      bbbbbbbbbbbbbbb^b         |
 | 
			
		||||
      {0:~                        }|
 | 
			
		||||
                               |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('wheel', 'left', '', 0, 0, 27)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
                               |
 | 
			
		||||
                               |
 | 
			
		||||
      n bbbbbbbbbbbbbbbbbbb^b   |
 | 
			
		||||
      {0:~                        }|
 | 
			
		||||
                               |
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    feed("^")
 | 
			
		||||
    meths.input_mouse('wheel', 'right', '', 0, 0, 0)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
      g                        |
 | 
			
		||||
                               |
 | 
			
		||||
      ^t and selection bbbbbbbbb|
 | 
			
		||||
      {0:~                        }|
 | 
			
		||||
                               |
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  describe('on concealed text', function()
 | 
			
		||||
    -- Helpful for reading the test expectations:
 | 
			
		||||
    -- :match Error /\^/
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,11 @@ local Screen = require('test.functional.ui.screen')
 | 
			
		||||
local clear = helpers.clear
 | 
			
		||||
local feed, command, insert = helpers.feed, helpers.command, helpers.insert
 | 
			
		||||
local eq = helpers.eq
 | 
			
		||||
local meths = helpers.meths
 | 
			
		||||
local wait = helpers.wait
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
describe('multigrid screen', function()
 | 
			
		||||
describe('ext_multigrid', function()
 | 
			
		||||
  local screen
 | 
			
		||||
 | 
			
		||||
  before_each(function()
 | 
			
		||||
@@ -1521,4 +1523,337 @@ describe('multigrid screen', function()
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
 | 
			
		||||
  it('supports mouse', function()
 | 
			
		||||
    insert('some text\nto be clicked')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be clicke^d                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('left', 'press', '', 2, 0, 5)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some ^text                                            |
 | 
			
		||||
      to be clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    feed(':new<cr>')
 | 
			
		||||
    insert('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmo')
 | 
			
		||||
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing el|
 | 
			
		||||
      it, sed do eiusm^o                                    |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('left', 'press', '', 2, 1, 6)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be ^clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing el|
 | 
			
		||||
      it, sed do eiusmo                                    |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('left', 'press', '', 3, 1, 4)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing el|
 | 
			
		||||
      it, ^sed do eiusmo                                    |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    screen:try_resize_grid(3, 80, 2)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, ^sed do eiusmo          |
 | 
			
		||||
      {1:~                                                                               }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('left', 'press', '', 3, 0, 64)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do ^eiusmo          |
 | 
			
		||||
      {1:~                                                                               }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('left', 'press', '', 1,6, 20)
 | 
			
		||||
    -- TODO(bfredl): "batching" input_mouse is formally not supported yet.
 | 
			
		||||
    -- Normally it should work fine in async context when nvim is not blocked,
 | 
			
		||||
    -- but add a wait be sure.
 | 
			
		||||
    wait()
 | 
			
		||||
    meths.input_mouse('left', 'drag', '', 1, 4, 20)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {11:[No Name] [+]                                        }|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      [2:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                                            |
 | 
			
		||||
      to be clicked                                        |
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
      {1:~                                                    }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do ^eiusmo          |
 | 
			
		||||
      {1:~                                                                               }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    feed('<c-w><c-w><c-w>v')
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      [4:--------------------------]{12:│}[2:--------------------------]|
 | 
			
		||||
      {11:[No Name] [+]              }{12:[No Name] [+]             }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text                 |
 | 
			
		||||
      to be clicked             |
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmo          |
 | 
			
		||||
      {1:~                                                                               }|
 | 
			
		||||
    ## grid 4
 | 
			
		||||
      some text                 |
 | 
			
		||||
      to be ^clicked             |
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
      {1:~                         }|
 | 
			
		||||
    ]])
 | 
			
		||||
 | 
			
		||||
    meths.input_mouse('left', 'press', '', 1,8, 26)
 | 
			
		||||
    wait()
 | 
			
		||||
    meths.input_mouse('left', 'drag', '', 1, 6, 30)
 | 
			
		||||
    screen:expect([[
 | 
			
		||||
    ## grid 1
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      [3:-----------------------------------------------------]|
 | 
			
		||||
      {12:[No Name] [+]                                        }|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      [4:------------------------------]{12:│}[2:----------------------]|
 | 
			
		||||
      {11:[No Name] [+]                  }{12:[No Name] [+]         }|
 | 
			
		||||
                                                           |
 | 
			
		||||
    ## grid 2
 | 
			
		||||
      some text             |
 | 
			
		||||
      to be clicked         |
 | 
			
		||||
      {1:~                     }|
 | 
			
		||||
      {1:~                     }|
 | 
			
		||||
      {1:~                     }|
 | 
			
		||||
      {1:~                     }|
 | 
			
		||||
      {1:~                     }|
 | 
			
		||||
    ## grid 3
 | 
			
		||||
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmo          |
 | 
			
		||||
      {1:~                                                                               }|
 | 
			
		||||
    ## grid 4
 | 
			
		||||
      some text                     |
 | 
			
		||||
      to be ^clicked                 |
 | 
			
		||||
      {1:~                             }|
 | 
			
		||||
      {1:~                             }|
 | 
			
		||||
      {1:~                             }|
 | 
			
		||||
      {1:~                             }|
 | 
			
		||||
      {1:~                             }|
 | 
			
		||||
    ]])
 | 
			
		||||
  end)
 | 
			
		||||
end)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user