Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No mouse release events in terminal mode #16371

Closed
Kavantix opened this issue Nov 19, 2021 · 6 comments · Fixed by #16373
Closed

No mouse release events in terminal mode #16371

Kavantix opened this issue Nov 19, 2021 · 6 comments · Fixed by #16373
Labels
bug issues reporting wrong behavior mouse terminal built-in :terminal or :shell

Comments

@Kavantix
Copy link

Kavantix commented Nov 19, 2021

Neovim version (nvim -v)

NVIM v0.6.0-dev+600-gf71be1f87

Vim (not Nvim) behaves the same?

no, vim 8.2 does send mouse release events

Operating system/version

macOS 11.3.1

Terminal name/version

kitty but tested on many

$TERM environment variable

xterm-kitty but tested on many

Installation

brew neovim-nightly

How to reproduce the issue

  1. install go
  2. download tcell mouse demo
  3. run :set mouse=a
  4. open a terminal in nvim using :term
  5. run go run mouse.go
  6. select an area with the mouse

Expected behavior

After releasing the mouse button the selected area should be green.
In both vim and a plain terminal this behaviour can be observed

Actual behavior

The area only becomes green after triggering some other mouse event (tcell assumes that event is a mouse release)

@Kavantix
Copy link
Author

Some extra info can be found in: awesome-gocui/gocui#99

@zeertzjq zeertzjq added mouse tui terminal built-in :terminal or :shell and removed tui labels Nov 19, 2021
@zeertzjq
Copy link
Member

I can reproduce this in both TUI and GUI.

@Kavantix
Copy link
Author

Updated the OP indeed I have mouse enabled and yes it also indeed happens in GUI (tried goneovim)

@zeertzjq
Copy link
Member

zeertzjq commented Nov 19, 2021

I can also reproduce this when running Nvim inside Nvim terminal.
In outer Nvim:

set mouse=a

In inner Nvim:

set mouse=a
set noshowmode
noremap <LeftRelease> <Cmd>echomsg 'LeftRelease' .. localtime()<CR>

Message doesn't change at the end of mouse drag, only at next mouse event. Even if I press some keys after releasing mouse, message still only changes at next mouse event.

@zeertzjq
Copy link
Member

zeertzjq commented Nov 19, 2021

The following diff seems to solve the problem:

diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 35c68fa1f..a78b10299 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -1211,7 +1211,7 @@ static VTermKey convert_key(int key, VTermModifier *statep)
 
 static void mouse_action(Terminal *term, int button, int row, int col, bool drag, VTermModifier mod)
 {
-  if (term->pressed_button && (term->pressed_button != button || !drag)) {
+  if (button && term->pressed_button && term->pressed_button != button) {
     // release the previous button
     vterm_mouse_button(term->vt, term->pressed_button, 0, mod);
     term->pressed_button = 0;
@@ -1220,10 +1220,11 @@ static void mouse_action(Terminal *term, int button, int row, int col, bool drag
   // move the mouse
   vterm_mouse_move(term->vt, row, col, mod);
 
-  if (!term->pressed_button) {
-    // press the button if not already pressed
-    vterm_mouse_button(term->vt, button, 1, mod);
-    term->pressed_button = button;
+  if (button) {
+    vterm_mouse_button(term->vt, button, drag, mod);
+    if (drag) {
+      term->pressed_button = button;
+    }
   }
 }
 
@@ -1246,23 +1247,26 @@ static bool send_mouse_event(Terminal *term, int c)
 
     switch (c) {
     case K_LEFTDRAG:
-      drag = true;   FALLTHROUGH;
     case K_LEFTMOUSE:
+      drag = true;   FALLTHROUGH;
+    case K_LEFTRELEASE:
       button = 1; break;
     case K_MOUSEMOVE:
-      drag = true; button = 0; break;
+      button = 0; break;
     case K_MIDDLEDRAG:
-      drag = true; FALLTHROUGH;
     case K_MIDDLEMOUSE:
+      drag = true; FALLTHROUGH;
+    case K_MIDDLERELEASE:
       button = 2; break;
     case K_RIGHTDRAG:
-      drag = true;  FALLTHROUGH;
     case K_RIGHTMOUSE:
+      drag = true;  FALLTHROUGH;
+    case K_RIGHTRELEASE:
       button = 3; break;
     case K_MOUSEDOWN:
-      button = 4; break;
+      drag = true; button = 4; break;
     case K_MOUSEUP:
-      button = 5; break;
+      drag = true; button = 5; break;
     default:
       return false;
     }

@zeertzjq
Copy link
Member

zeertzjq commented Nov 20, 2021

Or maybe pressed_button should even be removed, as there can be multiple buttons down at the same time (e.g. scrolling while dragging):

diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 35c68fa1f..9880099a3 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -135,7 +135,6 @@ struct terminal {
     int row, col;
     bool visible;
   } cursor;
-  int pressed_button;               // which mouse button is pressed
   bool pending_resize;              // pending width/height
 
   bool color_set[16];
@@ -1211,19 +1210,9 @@ static VTermKey convert_key(int key, VTermModifier *statep)
 
 static void mouse_action(Terminal *term, int button, int row, int col, bool drag, VTermModifier mod)
 {
-  if (term->pressed_button && (term->pressed_button != button || !drag)) {
-    // release the previous button
-    vterm_mouse_button(term->vt, term->pressed_button, 0, mod);
-    term->pressed_button = 0;
-  }
-
-  // move the mouse
   vterm_mouse_move(term->vt, row, col, mod);
-
-  if (!term->pressed_button) {
-    // press the button if not already pressed
-    vterm_mouse_button(term->vt, button, 1, mod);
-    term->pressed_button = button;
+  if (button) {
+    vterm_mouse_button(term->vt, button, drag, mod);
   }
 }
 
@@ -1246,23 +1235,26 @@ static bool send_mouse_event(Terminal *term, int c)
 
     switch (c) {
     case K_LEFTDRAG:
-      drag = true;   FALLTHROUGH;
     case K_LEFTMOUSE:
+      drag = true;   FALLTHROUGH;
+    case K_LEFTRELEASE:
       button = 1; break;
     case K_MOUSEMOVE:
-      drag = true; button = 0; break;
+      button = 0; break;
     case K_MIDDLEDRAG:
-      drag = true; FALLTHROUGH;
     case K_MIDDLEMOUSE:
+      drag = true; FALLTHROUGH;
+    case K_MIDDLERELEASE:
       button = 2; break;
     case K_RIGHTDRAG:
-      drag = true;  FALLTHROUGH;
     case K_RIGHTMOUSE:
+      drag = true;  FALLTHROUGH;
+    case K_RIGHTRELEASE:
       button = 3; break;
     case K_MOUSEDOWN:
-      button = 4; break;
+      drag = true; button = 4; break;
     case K_MOUSEUP:
-      button = 5; break;
+      drag = true; button = 5; break;
     default:
       return false;
     }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug issues reporting wrong behavior mouse terminal built-in :terminal or :shell
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants