5

I frequently use gvim on a windows 7 computer with a touch screen. If I flick up or down with the touch screen, it creates a selection (in S mode, not V mode).

I'm not really a fan of this default behavior. It's seems pointless and unintuitive to me. Can I configure flicking to vertically scroll instead of creating a selection? Vertical scrolling is much more important, but if there is a solution that also works with horizontal scrolling, that would be awesome.


Side note: I'm aware the answer might just be no. If you can give a definitive answer about why this is not an option, I'd accept that too (And be a little disappointed) .

2 Answers 2

6

Note: I have not tested this with gvim, only with normal vim

This piece of code allows me to scroll instead of selecting text when I drag using my mouse.

function! MouseScroll()
  "mark b is the current cursor position
  "mark a is the previous cursor position
  norm mb
  let currPos=line('.')
  norm `a
  let prevPos=line('.')
  if currPos>prevPos
    norm `bma
    " norm ^E  (This is hard to typeset)
    " Adopting the following exe command to achieve the same motion.
    exe "normal! \<C-e>"
  elseif currPos<prevPos
    norm `bma
    " norm ^Y
    exe "normal! \<C-y>"
  endif

  " Need this additional line to "scroll" continuously.
  " Otherwise, I was prompted "marker not set" warnings when dragging 
  " for more than 1 line.
  norm ma
endfunction

map <LeftDrag> ma<LeftMouse>:call MouseScroll()<cr>

and add this for insert mode:

imap <LeftDrag> <ESC>ma<LeftMouse>:call MouseScroll()<cr>:norm gi<cr>

Note: ^E and ^Y are not 2 characters each, they are each one character literals

I am using marks to check if I'm dragging up or down. Then accordingly I either scroll up or down.

Explanation

map <LeftDrag> ma<LeftMouse>:call MouseScroll()<cr>

The first thing we do when we map LeftDrag is that we set the cursor's mark (this will be our previous mark) to mark a. Mark a contains the previous position of the cursor to compare with the current position and scroll accordingly. Then we click. This is because we want to get the current position of the mouse in the buffer (because mouse drags don't usually move the mouse to the updated position). Then we call the MouseScroll function.

Inside the function

norm mb
let currPos=line('.')
norm `a
let prevPos=line('.')

Now we get the current position of the cursor using norm mb. Mark b will contain the mark of the current cursor position.

We store the positions of the position of these marks in variables currPos and prevPos

Then inside the if-elseif statement, we compare the currPos with the prevPos. If the current position is more than the previous position, ie the mouse is dragged downwards, we change mark b into mark a and then scroll down using norm ^E. We do a similar thing for the other case when the current position is below the previous position (the mouse is dragged upwards), except that we scroll up.

And that's it :)

Additional Configurations

Sometimes dragging the mouse still enters visual mode (at least for me it does), so I have a set mouse=nic. It's your choice on what you want to set the mouse to. Also, you can swap the ^E and the ^Y depending on your scroll preferences.

1
  • 5
    I've found that a better way of expressing literals here is using exe. For example: exe "normal! \<C-e>"
    – Tumbler41
    Jan 27, 2017 at 17:46
1

Your request is exactly how gvim behaves in Windows. (The os intercepts the vertical drag and sends WM_VSCROLL events directly to vim.)

I've filed https://github.com/vim/vim/issues/9193 to request this feature on gtk.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.