diff options
| -rw-r--r-- | runtime/doc/ui.txt | 8 | ||||
| -rw-r--r-- | src/nvim/edit.c | 3 | ||||
| -rw-r--r-- | src/nvim/ex_getln.c | 7 | ||||
| -rw-r--r-- | src/nvim/message.c | 10 | ||||
| -rw-r--r-- | src/nvim/mouse.c | 46 | ||||
| -rw-r--r-- | src/nvim/normal.c | 15 | ||||
| -rw-r--r-- | src/nvim/option.c | 12 | ||||
| -rw-r--r-- | src/nvim/ui.c | 63 | ||||
| -rw-r--r-- | test/functional/ui/mouse_spec.lua | 22 | ||||
| -rw-r--r-- | test/functional/ui/screen.lua | 13 | 
10 files changed, 106 insertions, 93 deletions
| diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index e5c6b9b1b7..0a8584927e 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -213,11 +213,9 @@ the editor.  ["mouse_on"]  ["mouse_off"] -	|'mouse'| was enabled/disabled in the current editor mode. Useful for -	a terminal UI, or other situations where Nvim mouse would conflict -	with other usages of the mouse. UIs may ignore this and always send -	mouse input, because 'mouse' decides the behavior of |nvim_input()| -	implicitly. +	'mouse' was enabled/disabled in the current editor mode. Useful for +	a terminal UI, or embedding into an application where Nvim mouse would +	conflict with other usages of the mouse. Other UI:s may ignore this event.  ["busy_start"]  ["busy_stop"] diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 45bd84261d..2d9dba839d 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -8328,9 +8328,6 @@ static void ins_mouse(int c)    pos_T tpos;    win_T       *old_curwin = curwin; -  if (!mouse_has(MOUSE_INSERT)) -    return; -    undisplay_dollar();    tpos = curwin->w_cursor;    if (do_mouse(NULL, c, BACKWARD, 1, 0)) { diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 129cb323ea..53dd2776c1 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1880,9 +1880,6 @@ static int command_line_handle_key(CommandLineState *s)      return command_line_not_changed(s);                 // Ignore mouse    case K_MIDDLEMOUSE: -    if (!mouse_has(MOUSE_COMMAND)) { -      return command_line_not_changed(s);                   // Ignore mouse -    }      cmdline_paste(eval_has_provider("clipboard") ? '*' : 0, true, true);      redrawcmd();      return command_line_changed(s); @@ -1906,10 +1903,6 @@ static int command_line_handle_key(CommandLineState *s)        s->ignore_drag_release = false;      } -    if (!mouse_has(MOUSE_COMMAND)) { -      return command_line_not_changed(s);                   // Ignore mouse -    } -      ccline.cmdspos = cmd_startcol();      for (ccline.cmdpos = 0; ccline.cmdpos < ccline.cmdlen;           ccline.cmdpos++) { diff --git a/src/nvim/message.c b/src/nvim/message.c index 02a7732f5c..f94529c687 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -1157,15 +1157,7 @@ void wait_return(int redraw)               || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE               || c == K_RIGHTDRAG  || c == K_RIGHTRELEASE               || c == K_MOUSELEFT  || c == K_MOUSERIGHT -             || c == K_MOUSEDOWN  || c == K_MOUSEUP -             || (!mouse_has(MOUSE_RETURN) -                 && mouse_row < msg_row -                 && (c == K_LEFTMOUSE -                     || c == K_MIDDLEMOUSE -                     || c == K_RIGHTMOUSE -                     || c == K_X1MOUSE -                     || c == K_X2MOUSE)) -             ); +             || c == K_MOUSEDOWN  || c == K_MOUSEUP);      os_breakcheck();      /*       * Avoid that the mouse-up event causes visual mode to start. diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index f05dade73f..ff471ea978 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -526,53 +526,9 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)  void setmouse(void)  {    ui_cursor_shape(); - -  // Be quick when mouse is off. -  if (*p_mouse == NUL) { -    return; -  } - -  int checkfor = MOUSE_NORMAL;  // assume normal mode -  if (VIsual_active) { -    checkfor = MOUSE_VISUAL; -  } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) { -    checkfor = MOUSE_RETURN; -  } else if (State & INSERT) { -    checkfor = MOUSE_INSERT; -  } else if (State & CMDLINE) { -    checkfor = MOUSE_COMMAND; -  } else if (State == CONFIRM || State == EXTERNCMD) { -    checkfor = ' ';  // don't use mouse for ":confirm" or ":!cmd" -  } - -  if (mouse_has(checkfor)) { -    ui_call_mouse_on(); -  } else { -    ui_call_mouse_off(); -  } +  ui_check_mouse();  } -/* - * Return true if - * - "c" is in 'mouse', or - * - 'a' is in 'mouse' and "c" is in MOUSE_A, or - * - the current buffer is a help file and 'h' is in 'mouse' and we are in a - *   normal editing mode (not at hit-return message). - */ -int mouse_has(int c) -{ -  for (char_u *p = p_mouse; *p; ++p) -    switch (*p) { -    case 'a': if (vim_strchr((char_u *)MOUSE_A, c) != NULL) -        return true; -      break; -    case MOUSE_HELP: if (c != MOUSE_RETURN && curbuf->b_help) -        return true; -      break; -    default: if (c == *p) return true; break; -    } -  return false; -}  // Set orig_topline.  Used when jumping to another window, so that a double  // click still works. diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 4b81a22f55..3ecac615b3 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2375,10 +2375,10 @@ do_mouse (       * Also paste at the cursor if the current mode isn't in 'mouse' (only       * happens for the GUI).       */ -    if ((State & INSERT) || !mouse_has(MOUSE_NORMAL)) { -      if (regname == '.') +    if ((State & INSERT)) { +      if (regname == '.') {          insert_reg(regname, true); -      else { +      } else {          if (regname == 0 && eval_has_provider("clipboard")) {            regname = '*';          } @@ -2558,8 +2558,9 @@ do_mouse (           * on a status line */          if (VIsual_active)            jump_flags |= MOUSE_MAY_STOP_VIS; -      } else if (mouse_has(MOUSE_VISUAL)) +      } else {          jump_flags |= MOUSE_MAY_VIS; +      }      } else if (which_button == MOUSE_RIGHT) {        if (is_click && VIsual_active) {          /* @@ -2575,8 +2576,7 @@ do_mouse (          }        }        jump_flags |= MOUSE_FOCUS; -      if (mouse_has(MOUSE_VISUAL)) -        jump_flags |= MOUSE_MAY_VIS; +      jump_flags |= MOUSE_MAY_VIS;      }    } @@ -2790,8 +2790,7 @@ do_mouse (    /* Handle double clicks, unless on status line */    else if (in_status_line) {    } else if (in_sep_line) { -  } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)) -             && mouse_has(MOUSE_VISUAL)) { +  } else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT))) {      if (is_click || !VIsual_active) {        if (VIsual_active) {          orig_cursor = VIsual; diff --git a/src/nvim/option.c b/src/nvim/option.c index bac289a959..7786feddf3 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3210,11 +3210,7 @@ ambw_end:    }    if (varp == &p_mouse) { -    if (*p_mouse == NUL) { -      ui_call_mouse_off(); -    } else { -      setmouse();  // in case 'mouse' changed -    } +    setmouse();  // in case 'mouse' changed    }    if (curwin->w_curswant != MAXCOL @@ -4983,11 +4979,7 @@ void ui_refresh_options(void)      ui_call_option_set(name, value);    }    if (p_mouse != NULL) { -    if (*p_mouse == NUL) { -      ui_call_mouse_off(); -    } else { -      setmouse(); -    } +    setmouse();    }  } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 685da77b39..c6c09c80d7 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -61,6 +61,9 @@ static bool pending_mode_info_update = false;  static bool pending_mode_update = false;  static handle_T cursor_grid_handle = DEFAULT_GRID_HANDLE; +static bool has_mouse = false; +static int pending_has_mouse = -1; +  #if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL  # define UI_LOG(funname)  #else @@ -220,6 +223,7 @@ void ui_refresh(void)    ui_mode_info_set();    pending_mode_update = true;    ui_cursor_shape(); +  pending_has_mouse = -1;  }  int ui_pum_get_height(void) @@ -459,10 +463,69 @@ void ui_flush(void)      ui_call_mode_change(cstr_as_string(full_name), ui_mode_idx);      pending_mode_update = false;    } +  if (pending_has_mouse != has_mouse) { +    (has_mouse ? ui_call_mouse_on : ui_call_mouse_off)(); +    pending_has_mouse = has_mouse; +  }    ui_call_flush();  } + +/// Check if 'mouse' is active for the current mode +/// +/// TODO(bfredl): precompute the State -> active mapping when 'mouse' changes, +/// then this can be checked directly in ui_flush() +void ui_check_mouse(void) +{ +  has_mouse = false; +  // Be quick when mouse is off. +  if (*p_mouse == NUL) { +    return; +  } + +  int checkfor = MOUSE_NORMAL;  // assume normal mode +  if (VIsual_active) { +    checkfor = MOUSE_VISUAL; +  } else if (State == HITRETURN || State == ASKMORE || State == SETWSIZE) { +    checkfor = MOUSE_RETURN; +  } else if (State & INSERT) { +    checkfor = MOUSE_INSERT; +  } else if (State & CMDLINE) { +    checkfor = MOUSE_COMMAND; +  } else if (State == CONFIRM || State == EXTERNCMD) { +    checkfor = ' ';  // don't use mouse for ":confirm" or ":!cmd" +  } + +  // mouse should be active if at least one of the following is true: +  // - "c" is in 'mouse', or +  // - 'a' is in 'mouse' and "c" is in MOUSE_A, or +  // - the current buffer is a help file and 'h' is in 'mouse' and we are in a +  //   normal editing mode (not at hit-return message). +  for (char_u *p = p_mouse; *p; p++) { +    switch (*p) { +      case 'a': +        if (vim_strchr((char_u *)MOUSE_A, checkfor) != NULL) { +          has_mouse = true; +          return; +        } +        break; +      case MOUSE_HELP: +        if (checkfor != MOUSE_RETURN && curbuf->b_help) { +          has_mouse = true; +          return; +        } +        break; +      default: +        if (checkfor == *p) { +          has_mouse = true; +          return; +        } +    } +  } +} +  /// Check if current mode has changed. +///  /// May update the shape of the cursor.  void ui_cursor_shape(void)  { diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index a741136111..7bca741ae3 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -45,13 +45,33 @@ describe('ui/mouse/input', function()    it('single left click moves cursor', function()      feed('<LeftMouse><2,1>') -    screen:expect([[ +    screen:expect{grid=[[        testing                  |        mo^use                    |        support and selection    |        {0:~                        }|                                 | +    ]], mouse_enabled=true} +    feed('<LeftMouse><0,0>') +    screen:expect([[ +      ^testing                  | +      mouse                    | +      support and selection    | +      {0:~                        }| +                               |      ]]) +  end) + +  it("in external ui works with unset 'mouse'", function() +    meths.set_option('mouse', '') +    feed('<LeftMouse><2,1>') +    screen:expect{grid=[[ +      testing                  | +      mo^use                    | +      support and selection    | +      {0:~                        }| +                               | +    ]], mouse_enabled=false}      feed('<LeftMouse><0,0>')      screen:expect([[        ^testing                  | diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 8fa9fcc42f..fcf6926433 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -170,7 +170,7 @@ function Screen.new(width, height)      ruler = {},      hl_groups = {},      _default_attr_ids = nil, -    _mouse_enabled = true, +    mouse_enabled = true,      _attrs = {},      _hl_info = {[0]={}},      _attr_table = {[0]={{},{}}}, @@ -318,7 +318,7 @@ function Screen:expect(expected, attr_ids, ...)    assert(next({...}) == nil, "invalid args to expect()")    if type(expected) == "table" then      assert(not (attr_ids ~= nil)) -    local is_key = {grid=true, attr_ids=true, condition=true, +    local is_key = {grid=true, attr_ids=true, condition=true, mouse_enabled=true,                      any=true, mode=true, unchanged=true, intermediate=true,                      reset=true, timeout=true, request_cb=true, hl_groups=true}      for _, v in ipairs(ext_keys) do @@ -422,12 +422,15 @@ screen:redraw_debug() to show all intermediate screen states.  ]])      if expected.mode ~= nil then        extstate.mode = self.mode      end +    if expected.mouse_enabled ~= nil then +      extstate.mouse_enabled = self.mouse_enabled +    end      if expected.win_viewport == nil then        extstate.win_viewport = nil      end      -- Convert assertion errors into invalid screen state descriptions. -    for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do +    for _, k in ipairs(concat_tables(ext_keys, {'mode', 'mouse_enabled'})) do        -- Empty states are considered the default and need not be mentioned.        if (not (expected[k] == nil and isempty(extstate[k]))) then          local status, res = pcall(eq, expected[k], extstate[k], k) @@ -799,11 +802,11 @@ function Screen:_handle_busy_stop()  end  function Screen:_handle_mouse_on() -  self._mouse_enabled = true +  self.mouse_enabled = true  end  function Screen:_handle_mouse_off() -  self._mouse_enabled = false +  self.mouse_enabled = false  end  function Screen:_handle_mode_change(mode, idx) | 
