Skip to content

Commit

Permalink
finaly fix elfmz#2072 mouse input in win32-input mode
Browse files Browse the repository at this point in the history
 * cleanup code
 * disable logs
 * correct parsing for win32-input mode
 * documented workflow of this fix as well as standard parsing procedure
  • Loading branch information
anton committed Mar 19, 2024
1 parent 8628607 commit 34edbb1
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 30 deletions.
7 changes: 1 addition & 6 deletions WinPort/src/Backend/TTY/TTYInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,7 @@ void TTYInput::OnBufUpdated(bool idle)

//work-around for double encoded mouse events in win32-input mode
//here we parse mouse sequence from accumulated buffer
if (_parser._win_mouse_buffer.size() > 5) {
_parser._win32_accumulate = false;
_parser.Parse(&_parser._win_mouse_buffer[0], _parser._win_mouse_buffer.size(), idle);
_parser._win_mouse_buffer.clear();
fprintf(stderr, "!!!parsed accumulated mouse sequence \n");
}
_parser.ParseWinMouseBuffer(idle);

switch (decoded) {
case TTY_PARSED_PLAINCHARS:
Expand Down
28 changes: 24 additions & 4 deletions WinPort/src/Backend/TTY/TTYInputSequenceParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,18 @@ size_t TTYInputSequenceParser::ParseEscapeSequence(const char *s, size_t l)
return r;
}

//win32-input-mode must be checked before kitty
//TODO: need to check for private mode sequence been recived somewhere here
//for win32-input-mode -- "\x1B[?9001h"
//for kitty -- "\x1B[>1u"
if (l > 1 && s[0] == '[') {
r = TryParseAsWinTermEscapeSequence(s, l);
if (r != TTY_PARSED_BADSEQUENCE) {
fprintf(stderr, "valid win32 input: = %ld\n", r);
return r;
}
}

if (l > 1 && s[0] == '[') {
r = TryParseAsKittyEscapeSequence(s, l);
if (r != TTY_PARSED_BADSEQUENCE) {
Expand Down Expand Up @@ -455,7 +459,6 @@ size_t TTYInputSequenceParser::ParseIntoPending(const char *s, size_t l)
return 1;

default:
fprintf(stderr, "PARSED_PLAINCHARS ");
return (size_t)TTY_PARSED_PLAINCHARS;
}

Expand All @@ -466,17 +469,21 @@ size_t TTYInputSequenceParser::Parse(const char *s, size_t l, bool idle_expired)
{
//work-around for double encoded mouse events in win32-input mode
//we encountered sequence \x1B[0;0;27;1;0;1_ it is \x1B encoded in win32 input
//following codes are part of X10 mouse command and must be parsed in separate buffer
//following codes are part of X10 input sequence and must be parsed in separate buffer
if ((l > 6 && s[1] == '[' && s[2] == '0' && s[3] == ';' && s[4] == '0' && s[5] == ';') || _win32_accumulate) {
/*
fprintf(stderr, "Parsing win-32 mouse: ");
for (size_t i = 0; i < l && s[i] != '\0'; i++) {
fprintf(stderr, "%c", s[i]);
}
fprintf(stderr, " lenght: %ld\n", l);
*/

size_t r = TryUnwrappWinMouseEscapeSequence(s, l);

fprintf(stderr, "parsed lenght: %ld------------------\n", r);
//fprintf(stderr, "parsed lenght: %ld------------------\n", r);
//now we check if _win_mouse_buffer has enough characters for X10 mouse input sequence
//in future we may also need to check for SGR extended mouse reporting
_win32_accumulate = _win_mouse_buffer.size() > 5 ? false : true;
return r;
}
Expand Down Expand Up @@ -647,4 +654,17 @@ void TTYInputSequenceParser::OnBracketedPaste(bool start)
_ir_pending.emplace_back(ir);
}

//work-around for double encoded mouse events in win32-input mode
void TTYInputSequenceParser::ParseWinMouseBuffer(bool idle)
{
if (_win_mouse_buffer.size() > 5) {
_win32_accumulate = false;
Parse(&_win_mouse_buffer[0], _win_mouse_buffer.size(), idle);
_win_mouse_buffer.clear();
fprintf(stderr, "!!!parsed accumulated mouse sequence \n");
} else {
return;
}
}

//////////////////
26 changes: 21 additions & 5 deletions WinPort/src/Backend/TTY/TTYInputSequenceParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ struct ITTYInputSpecialSequenceHandler
virtual void OnInputBroken() = 0;
};

//wait for more characters from input buffer
#define TTY_PARSED_WANTMORE ((size_t)0)
//no sequence encountered, plain text recognized
#define TTY_PARSED_PLAINCHARS ((size_t)-1)
//unrecognized sequence, skip ESC char (0x1b) and continue
#define TTY_PARSED_BADSEQUENCE ((size_t)-2)

class TTYInputSequenceParser
Expand Down Expand Up @@ -104,6 +107,9 @@ class TTYInputSequenceParser
bool _kitty_right_ctrl_down = false;
int _iterm_last_flags = 0;
char _using_extension = 0;
//work-around for double encoded mouse events in win32-input mode
std::vector<char> _win_mouse_buffer; // buffer for accumulate unpacked chras
bool _win32_accumulate = false; // flag for parse win32-input sequence into _win_mouse_buffer

void AssertNoConflicts();

Expand Down Expand Up @@ -131,13 +137,23 @@ class TTYInputSequenceParser


public:
//work-around for double encoded mouse events in win32-input mode
std::vector<char> _win_mouse_buffer; // buffer for accumulate unpacked chras
bool _win32_accumulate = false; // flag for parse win32-input sequence into _win_mouse_buffer
int _skip_two_sequence = 0; // counter for skip unwanted sequences after mouse input

TTYInputSequenceParser(ITTYInputSpecialSequenceHandler *handler);

size_t Parse(const char *s, size_t l, bool idle_expired); // 0 - need more, -1 - not sequence, -2 - unrecognized sequence, >0 - sequence
/**
* parse and schedule input from recognized sequence.
* returns number of parsed bytes, numbers below 1 is error flags of following meaning:
* + 0 - (TTY_PARSED_WANTMORE) wait for more characters from input buffer
* + -1 - (TTY_PARSED_PLAINCHARS) no sequence encountered, plain text recognized
* + -2 - (TTY_PARSED_BADSEQUENCE) unrecognized sequence, skip ESC char (0x1b) and continue
*/
size_t Parse(const char *s, size_t l, bool idle_expired);

/**
* parse and schedule mouse sequence from _win_mouse_buffer.
* executed only if _win_mouse_buffer contains valid number of characters
* for X10 mouse sequence
*/
void ParseWinMouseBuffer(bool idle_expired);
char UsingExtension() const { return _using_extension; };
};
25 changes: 10 additions & 15 deletions WinPort/src/Backend/TTY/TTYInputSequenceParserExts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,13 +303,6 @@ size_t TTYInputSequenceParser::TryParseAsWinTermEscapeSequence(const char *s, si
int args[6] = {0};
int args_cnt = 0;

//skip two sequences for WSL double encoded mouse work-around
if (_skip_two_sequence < 2) {
fprintf(stderr, "skipped...");
++_skip_two_sequence;
return l;
}

size_t n;
for (size_t i = n = 1;; ++i) {
if (i == l) {
Expand All @@ -321,8 +314,8 @@ size_t TTYInputSequenceParser::TryParseAsWinTermEscapeSequence(const char *s, si
}
if (i > n) {
args[args_cnt] = atoi(&s[n]);
++args_cnt;
}
++args_cnt;
n = i + 1;
if (s[i] == '_') {
break;
Expand All @@ -335,6 +328,8 @@ size_t TTYInputSequenceParser::TryParseAsWinTermEscapeSequence(const char *s, si



//do not create invalid input event
//wVirtualKeyCode, wVirtualScanCode 0 with bKeyDown 1 doesn't make sense
if ( !((args[0] == 0) && (args[1] == 0) && (args[3] == 1) && (args[4] == 0)) )
{
INPUT_RECORD ir = {};
Expand All @@ -356,7 +351,10 @@ size_t TTYInputSequenceParser::TryParseAsWinTermEscapeSequence(const char *s, si
return n;
}

//work-around for double encoded mouse events in win32-input mode
//work-around for double encoded mouse events in win32-input mode.
//maybe it will be better not copy/paste TryParseAsWinTermEscapeSequence here
//but passing yet another flag to it is less readable.
//so keep it this way until microsoft fix their stuff in the win32-input protocol
size_t TTYInputSequenceParser::TryUnwrappWinMouseEscapeSequence(const char *s, size_t l)
{
int args[6] = {0};
Expand All @@ -365,7 +363,7 @@ size_t TTYInputSequenceParser::TryUnwrappWinMouseEscapeSequence(const char *s, s
size_t n;
for (size_t i = n = 1;; ++i) {
if (i == l) {
fprintf(stderr, "\nwant mooore characters... \n");
//fprintf(stderr, "\nwant mooore characters... \n");
return LIKELY(l < 32) ? TTY_PARSED_WANTMORE : TTY_PARSED_BADSEQUENCE;
}
if (s[i] == '_' || s[i] == ';') {
Expand All @@ -374,8 +372,8 @@ size_t TTYInputSequenceParser::TryUnwrappWinMouseEscapeSequence(const char *s, s
}
if (i > n) {
args[args_cnt] = atoi(&s[n]);
++args_cnt;
}
++args_cnt;
n = i + 1;
if (s[i] == '_') {
break;
Expand All @@ -387,13 +385,10 @@ size_t TTYInputSequenceParser::TryUnwrappWinMouseEscapeSequence(const char *s, s
}

if(args[2] > 0 && args[3] == 1){ // only KeyDown and valid char should pass
fprintf(stderr, "Parsed: ==%c==\n", (unsigned char)(args[2]));
//fprintf(stderr, "Parsed: ==%c==\n", (unsigned char)(args[2]));
_win_mouse_buffer.push_back((unsigned char)args[2]);
}

//counter for skip two win32 codes in end of input
_skip_two_sequence = 0;

return n;
}

Expand Down

0 comments on commit 34edbb1

Please sign in to comment.