diff --git a/src/input.cpp b/src/input.cpp index ccba673e5..e34eef107 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -485,56 +485,41 @@ maybe_t inputter_t::find_mapping() { return generic ? maybe_t(*generic) : none(); } -template +/// A class which allows accumulating input events, or return them to the queue. class event_queue_peeker_t { - private: - input_event_queue_t &event_queue_; - std::array peeked_; - size_t count = 0; - bool consumed_ = false; + public: + explicit event_queue_peeker_t(input_event_queue_t &event_queue) : event_queue_(event_queue) {} - public: - event_queue_peeker_t(input_event_queue_t &event_queue) - : event_queue_(event_queue) { - } + /// \return the next event, optionally waiting for it. + char_event_t next(bool timed = false) { + auto event = timed ? event_queue_.readch_timed() : event_queue_.readch(); + peeked_.push_back(event); + return event; + } - char_event_t next(bool timed = false) { - assert(count < N && "Insufficient backing array size!"); - auto event = timed ? event_queue_.readch_timed() : event_queue_.readch(); - peeked_[count++] = event; - return event; - } + /// \return how many events are currently stored. + size_t len() const { return peeked_.size(); } - size_t len() { - return count; - } + /// Consume all events that have been peeked, leaving this empty. + void consume() { peeked_.clear(); } - constexpr size_t max_len() const { - return N; - } + /// Return all peeked events to the queue. + void restart() { + event_queue_.insert_front(peeked_.cbegin(), peeked_.cend()); + peeked_.clear(); + } - void consume() { - consumed_ = true; - } + ~event_queue_peeker_t() { restart(); } - void restart() { - if (count > 0) { - event_queue_.insert_front(peeked_.cbegin(), peeked_.cbegin() + count); - count = 0; - } - } - - ~event_queue_peeker_t() { - if (!consumed_) { - restart(); - } - } + private: + std::vector peeked_; + input_event_queue_t &event_queue_; }; bool inputter_t::have_mouse_tracking_csi() { // Maximum length of any CSI is NPAR (which is nominally 16), although this does not account for // user input intermixed with pseudo input generated by the tty emulator. - event_queue_peeker_t<16> peeker(event_queue_); + event_queue_peeker_t peeker(event_queue_); // Check for the CSI first if (peeker.next().maybe_char() != L'\x1B' @@ -576,11 +561,11 @@ bool inputter_t::have_mouse_tracking_csi() { // Consume however many characters it takes to prevent the mouse tracking sequence from reaching // the prompt, dependent on the class of mouse reporting as detected above. - peeker.consume(); - while (peeker.len() != length) { - auto _ = peeker.next(); + while (peeker.len() < length) { + (void)peeker.next(); } + peeker.consume(); return true; } diff --git a/tests/pexpects/disable_mouse.py b/tests/pexpects/disable_mouse.py new file mode 100644 index 000000000..14e40f37a --- /dev/null +++ b/tests/pexpects/disable_mouse.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +from pexpect_helper import SpawnedProc +import subprocess +import sys +import time + +sp = SpawnedProc(args=["-d", "reader"]) +sp.expect_prompt() + +# Verify we correctly diable mouse tracking. + +# Five char sequence. +sp.send("\x1b[tDE") +sp.expect_str("reader: Disabling mouse tracking") + +# Six char sequence. +sp.send("\x1b[MABC") +sp.expect_str("reader: Disabling mouse tracking") + +# Nine char sequences. +sp.send("\x1b[TABCDEF") +sp.expect_str("reader: Disabling mouse tracking") + +# Extended SGR sequences. +sp.send("\x1b[