On Wed, Feb 11, 2026 at 03:56:00PM +0100, Gabriel Ravier wrote:
> On 2/11/26 10:28 AM, Thomas Dickey wrote:
> > On Mon, Feb 09, 2026 at 03:24:02PM +0100, Vincent Lefevre wrote:
> > > mouseinterval(0);
> > >
> > > // Don't mask any mouse events
> > > mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
> > >
> > > printf("\033[?1003h\n"); // Makes the terminal report mouse movement
> > > events
> > There's no fflush here, so the program behavior is indeterminate.
> >
> > For instance, this bug could account for the behavior you're reporting.
> > > for (;;) {
> > > int c = wgetch(stdscr);
> > >
> > > // Exit the program on new line fed
> > > if (c == '\n')
> > > break;
> > >
> > > char buffer[512];
> > > size_t max_size = sizeof(buffer);
> > > if (c == ERR) {
> > > snprintf(buffer, max_size, "Nothing happened.");
> > > }
> > > else if (c == KEY_MOUSE) {
> > > MEVENT event;
> > > if (getmouse(&event) == OK) {
> > > snprintf(buffer, max_size, "Mouse at row=%d, column=%d
> > > bstate=0x%08lx",
> > > event.y, event.x, (unsigned long) event.bstate);
> > > }
> > > else {
> > > snprintf(buffer, max_size, "Got bad mouse event.");
> > > }
> > > }
> > > else {
> > > snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));
> > > }
> > >
> > > move(0, 0);
> > > insertln();
> > > addstr(buffer);
> > > clrtoeol();
> > > move(0, 0);
> > > }
> > >
> > > printf("\033[?1003l\n"); // Disable mouse movement events, as l = low
> > same bug here.
>
> I'm pretty sure this is guaranteed to result in an `fflush`, since `printf`
> here outputs to a terminal, and the C standard (not even POSIX, the C
> standard itself) guarantees that stdout has at least line-buffering (it may
> be unbuffered too, but that would be fine here too) if connected to an
> interactive output device (e.g. a terminal), meaning in these cases it will
> output the line given to `printf` immediately since a line-buffering FILE
> flushes its buffer upon being told to add a newline to it (although it is
> probably not very wise to rely on this, and I would certainly recommend use
> of `fflush` here, the behavior should be consistent in this particular case
> given the testing appears to have been done with the output connected to a
> terminal)I see (actually in looking at the code, I didn't notice the trailing \n). In actually running it, I found the output a little confusing, and added a counter to see how the output goes - and saw that it's not enabling scrolling (not an issue if it prints error messages). But with xterm tweaked to omit button-release responses to mimic the behavior that Vincent described, I don't see any problems. I'm seeing the same behavior with ncurses 6.5 and 6.6: the button state shows only one "press" event, and the rest correspond to "position" -- no hanging, no bad-mouse-event, etc. Without release-events, of course, there would be no click resolution. With scrolling, it's easier to see that the oldest lines are pushed to the bottom of the screen, so after a while only the updated position would affect the output. I ran the (modified) program through more than a thousand position-events without noticing a problem. In my own testing, I'd configure ncurses with trace enabled, but suppose that's not easily done with the Android system. But that could show the state of the mouse queue, and give some clues about the reported problem. fwiw, attaching the modified program and a little file from running it in "script" (I renamed it "dots_curses" to put it in my development tree's test-directory). -- Thomas E. Dickey <[email protected]> https://invisible-island.net
/*
With ncurses 6.6, mouseinterval(0) causes getmouse errors in Termux,
as shown by the following example:
*/
#include <test.priv.h>
int main(void)
{
char buffer[512];
size_t max_size = sizeof(buffer);
int counter = 0;
initscr();
cbreak();
noecho();
// Enables keypad mode. This makes (at least for me) mouse events getting
// reported as KEY_MOUSE, instead as of random letters.
keypad(stdscr, TRUE);
// See https://github.com/termux/termux-packages/issues/28372
mouseinterval(0);
// Don't mask any mouse events
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
printf("\033[?1003h\n"); // Makes the terminal report mouse movement events
scrollok(stdscr, TRUE);
for (;;) {
int c = wgetch(stdscr);
// Exit the program on new line fed
if (c == '\n')
break;
if (c == ERR) {
snprintf(buffer, max_size, "Nothing happened.");
}
else if (c == KEY_MOUSE) {
MEVENT event;
if (getmouse(&event) == OK) {
snprintf(buffer, max_size, "Mouse at row=%d, column=%d bstate=0x%08lx",
event.y, event.x, (unsigned long) event.bstate);
}
else {
snprintf(buffer, max_size, "Got bad mouse event.");
}
}
else {
snprintf(buffer, max_size, "Pressed key %d (%s)", c, keyname(c));
}
move(0, 0);
insertln();
printw("[%04d] ", ++counter);
addstr(buffer);
clrtoeol();
move(0, 0);
}
printf("\033[?1003l\n"); // Disable mouse movement events, as l = low
endwin();
return 0;
}
/*
This is the program from
https://gist.github.com/sylt/93d3f7b77e7f3a881603
where "mouseinterval(0);" has been added as instructed at
https://github.com/termux/termux-packages/issues/28372
To reproduce the error, run this program directly in the Termux
terminal (no ssh), and tap (click) several times on the screen.
In my case, a "Got bad mouse event." message appears at the 7th
time (periodically). Note: make sure that they correspond to
clicks, i.e. do not generate mouse movements (the problem still
seems to be reproducible if there are mouse movements between
the clicks, though).
In the above termux-packages issue, Robert Kirkman bisected it to
https://github.com/ThomasDickey/ncurses-snapshots/commit/04b97b07ab93bac2ba9ab92a2c3776ddae75bfaa#r169954711
There is a mention of a problem in htop
https://github.com/htop-dev/htop/issues/1769
due to this commit, but I cannot reproduce it, even though I get
"Got bad mouse event." messages with the above test program.
--
Vincent Lef??vre <[email protected]> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Pascaline project (LIP, ENS-Lyon)
*/
Script started on 2026-02-12 19:16:05-05:00 [COMMAND="./dots_curses" TERM="xterm-new" TTY="/dev/pts/3" COLUMNS="80" LINES="24"] [?1049h[22;0;0t[1;24r(B[m[4l[?7h[?1h=[?1006;1000h[?1003h [H[2J[0001] Mouse at row=7, column=37 bstate=0x0[6b2 M[0002] Mouse at row=7, column=37 bstate=0x10[6b M[0003] Mouse at row=7, column=37 bstate=0x10[6b M[0004] Mouse at row=7, column=37 bstate=0x10[6b M[0005] Mouse at row=7, column=37 bstate=0x10[6b M[0006] Mouse at row=7, column=37 bstate=0x10[6b M[0007] Mouse at row=7, column=37 bstate=0x10[6b M[0008] Mouse at row=7, column=37 bstate=0x10[6b M[0009] Mouse at row=7, column=37 bstate=0x10[6b M[0010] Mouse at row=7, column=37 bstate=0x10[6b M[0011] Mouse at row=7, column=37 bstate=0x10[6b M[0012] Mouse at row=7, column=37 bstate=0x10[6b [?1003l [?1006;1000l[24;1H[?1049l[23;0;0t [?1l> Script done on 2026-02-12 19:16:10-05:00 [COMMAND_EXIT_CODE="0"]
signature.asc
Description: PGP signature
