Queued mouse-wheel events on POSIX after fast trackpad scrolling
Description
Hi! While building a text editor with FTXUI 7.0.1 on macOS, I encountered an input-lag issue with fast (read very fast) trackpad scrolling.
After a quick scroll gesture, wheel events sometimes continue arriving after I have stopped scrolling. Input performed afterward (such as clicking a radio entry) is delayed behind those events.
Minimal reproduction
#include <string>
#include <vector>
#include "ftxui/component/component.hpp"
#include "ftxui/component/screen_interactive.hpp"
using namespace ftxui;
int main() {
std::vector<std::string> entries;
for (int i = 0; i < 2000; ++i)
entries.push_back("Item " + std::to_string(i));
int selected = 0;
auto radio = Radiobox(&entries, &selected);
auto view = Renderer(radio, [&] {
return radio->Render() | vscroll_indicator | frame |
size(HEIGHT, LESS_THAN, 12) | border;
});
App::FitComponent().Loop(view);
}Steps to reproduce
- Rapidly (read very very fast) scroll through the radio list using a trackpad.
- Stop scrolling.
- Immediately click a visible radio entry.
Observed behavior
The list may continue scrolling after the gesture has stopped. The click is delayed and can end up selecting a different entry because the list moved before the click was processed.
Expected behavior
Once the gesture has stopped, subsequent input should be handled without waiting for a noticeable backlog of older wheel events.
What I found
Looking through the [POSIX input path](https://github.com/ArthurSonzogni/FTXUI/blob/c100eab535db2283b78d30fcb6d082a1f84fb683/src/ftxui/component/app.cpp#L1391-L1414), I noticed that FetchTerminalEvents() reads at most 128 bytes per loop iteration:
std::array<char, 128> out{};
const ssize_t l = read(tty_fd_, out.data(), out.size());My understanding is that a sufficiently large burst of SGR mouse events can remain in the terminal input buffer across several frames.
I initially tried throttling wheel events in the component using std::chrono::steady_clock, but that did not resolve the issue because the events were already waiting to be processed.
As an experiment, I changed the POSIX path to read a larger, bounded amount of currently available input per iteration. This removed the delayed scrolling and made the following click responsive.
Is the 128-byte limit intentional, or might reading a larger bounded batch of available POSIX input be appropriate here?
Thanks for all the work on FTXUI, it has been a pleasure to use.
Source: ArthurSonzogni/FTXUI