diff --git a/far2l/src/vt/IVTShell.h b/far2l/src/vt/IVTShell.h index 6257a9e9b..633ae0835 100644 --- a/far2l/src/vt/IVTShell.h +++ b/far2l/src/vt/IVTShell.h @@ -1,19 +1,19 @@ #pragma once #include -enum MouseExpectation +enum MouseMode { - MEX_X10_MOUSE = 0x00001, - MEX_VT200_MOUSE = 0x00002, -// MEX_VT200_HIGHLIGHT_MOUSE = 0x00004, irrelevant??? - MEX_BTN_EVENT_MOUSE = 0x00008, - MEX_ANY_EVENT_MOUSE = 0x00010, - MEX_SGR_EXT_MOUSE = 0x00020 + MODE_X10_MOUSE = 0x00001, + MODE_VT200_MOUSE = 0x00002, +// MODE_VT200_HIGHLIGHT_MOUSE = 0x00004, not used + MODE_BTN_EVENT_MOUSE = 0x00008, + MODE_ANY_EVENT_MOUSE = 0x00010, + MODE_SGR_EXT_MOUSE = 0x00020 }; struct IVTShell { - virtual void OnMouseExpectation(MouseExpectation mex, bool enabled) = 0; + virtual void OnMouseExpectation(MouseMode mex, bool enabled) = 0; virtual void OnBracketedPasteExpectation(bool enabled) = 0; virtual void OnFocusChangeExpectation(bool enabled) = 0; virtual void OnWin32InputMode(bool enabled) = 0; diff --git a/far2l/src/vt/vtansi.cpp b/far2l/src/vt/vtansi.cpp index 3617ff2be..ee2d5ebcf 100644 --- a/far2l/src/vt/vtansi.cpp +++ b/far2l/src/vt/vtansi.cpp @@ -182,14 +182,14 @@ jadoxa@yahoo.com.au #include "vtlog.h" -enum AnsiMouseExpectation +enum AnsiMouseModes { - AMEX_X10_MOUSE = 9, - AMEX_VT200_MOUSE = 1000, - AMEX_VT200_HIGHLIGHT_MOUSE = 1001, - AMEX_BTN_EVENT_MOUSE = 1002, - AMEX_ANY_EVENT_MOUSE = 1003, - AMEX_SGR_EXT_MOUSE = 1006 + SET_X10_MOUSE = 9, + SET_VT200_MOUSE = 1000, + SET_VT200_HIGHLIGHT_MOUSE = 1001, + SET_BTN_EVENT_MOUSE = 1002, + SET_ANY_EVENT_MOUSE = 1003, + SET_SGR_EXT_MODE_MOUSE = 1006 }; struct VTAnsiState @@ -206,7 +206,7 @@ struct VTAnsiState memset(&csbi, 0, sizeof(csbi)); memset(&cci, 0, sizeof(cci)); } - + void InitFromConsole(HANDLE con) { WINPORT(GetConsoleScreenBufferInfo)( con, &csbi ); @@ -404,7 +404,7 @@ struct VTAnsiContext } while (++b, --chars_in_buffer); } else { fprintf(stderr, "TODODODODO\n"); - + // To detect wrapping of multiple characters, create a new buffer, write // to the top of it and see if the cursor changes line. This doesn't @@ -779,21 +779,21 @@ struct VTAnsiContext if (prefix2 == '?' && (suffix == 'h' || suffix == 'l')) { for (i = 0; i < es_argc; ++i) { switch (es_argv[i]) { - case AMEX_X10_MOUSE: - vt_shell->OnMouseExpectation(MEX_X10_MOUSE, suffix == 'h'); + case SET_X10_MOUSE: + vt_shell->OnMouseExpectation(MODE_X10_MOUSE, suffix == 'h'); break; - case AMEX_VT200_MOUSE: - case AMEX_VT200_HIGHLIGHT_MOUSE: - vt_shell->OnMouseExpectation(MEX_VT200_MOUSE, suffix == 'h'); + case SET_VT200_MOUSE: + case SET_VT200_HIGHLIGHT_MOUSE: + vt_shell->OnMouseExpectation(MODE_VT200_MOUSE, suffix == 'h'); break; - case AMEX_BTN_EVENT_MOUSE: - vt_shell->OnMouseExpectation(MEX_BTN_EVENT_MOUSE, suffix == 'h'); + case SET_BTN_EVENT_MOUSE: + vt_shell->OnMouseExpectation(MODE_BTN_EVENT_MOUSE, suffix == 'h'); break; - case AMEX_ANY_EVENT_MOUSE: - vt_shell->OnMouseExpectation(MEX_ANY_EVENT_MOUSE, suffix == 'h'); + case SET_ANY_EVENT_MOUSE: + vt_shell->OnMouseExpectation(MODE_ANY_EVENT_MOUSE, suffix == 'h'); break; - case AMEX_SGR_EXT_MOUSE: - vt_shell->OnMouseExpectation(MEX_SGR_EXT_MOUSE, suffix == 'h'); + case SET_SGR_EXT_MODE_MOUSE: + vt_shell->OnMouseExpectation(MODE_SGR_EXT_MOUSE, suffix == 'h'); break; // case 47: case 1047: @@ -868,7 +868,7 @@ struct VTAnsiContext // Ignore any other private sequences. if (prefix2 != 0) { LogFailedEscSeq(StrPrintf("bad prefix2 %c", prefix2)); - return; + return; } WINPORT(GetConsoleScreenBufferInfo)( con_hnd, &Info ); @@ -972,7 +972,7 @@ struct VTAnsiContext WINPORT(ScrollConsoleScreenBuffer)( con_hnd, &Rect, &Info.srWindow, Pos, &CharInfo ); } return; - + case 'T': // ESC[#T Scroll down if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[T == ESC[1T if (es_argc != 1) return; @@ -983,7 +983,7 @@ struct VTAnsiContext Rect.Right = Info.srWindow.Right = (Info.dwSize.X - 1); Rect.Top = Info.srWindow.Top; Rect.Bottom = Info.srWindow.Bottom - es_argv[0]; - + Pos.X = 0; Pos.Y = Rect.Top + es_argv[0]; @@ -991,8 +991,8 @@ struct VTAnsiContext WINPORT(ScrollConsoleScreenBuffer)( con_hnd, &Rect, &Info.srWindow, Pos, &CharInfo ); } return; - - + + case 'M': // ESC[#M Delete # lines. if (es_argc == 0) es_argv[es_argc++] = 1; // ESC[M == ESC[1M if (es_argc != 1) return; @@ -1225,14 +1225,14 @@ struct VTAnsiContext case 'r': if (es_argc < 2) { es_argv[1] = MAXSHORT; - if (es_argc < 1) + if (es_argc < 1) es_argv[0] = 1; } - fprintf(stderr, "VTAnsi: SET SCROLL REGION: %d %d (limits %d %d)\n", + fprintf(stderr, "VTAnsi: SET SCROLL REGION: %d %d (limits %d %d)\n", es_argv[0] - 1, es_argv[1] - 1, Info.srWindow.Top, Info.srWindow.Bottom); WINPORT(SetConsoleScrollRegion)(con_hnd, es_argv[0] - 1, es_argv[1] - 1); return; - + case 'c': // CSI P s c Send Device Attributes (Primary DA) if (prefix2 == 0 && (es_argc < 1 || es_argv[0] == 0)) { SendSequence("\e[?1;2c"); // → CSI ? 1 ; 2 c (‘‘VT100 with Advanced Video Option’’) @@ -1333,32 +1333,32 @@ struct VTAnsiContext void ForwardIndex() { fprintf(stderr, "ANSI: ForwardIndex\n"); - FlushBuffer(); + FlushBuffer(); } void ReverseIndex() { fprintf(stderr, "ANSI: ReverseIndex\n"); FlushBuffer(); - HANDLE con_hnd = vt_shell->ConsoleHandle(); + HANDLE con_hnd = vt_shell->ConsoleHandle(); CONSOLE_SCREEN_BUFFER_INFO info; WINPORT(GetConsoleScreenBufferInfo)( con_hnd, &info ); SHORT scroll_top = 0, scroll_bottom = 0x7fff; WINPORT(GetConsoleScrollRegion)(con_hnd, &scroll_top, &scroll_bottom); - + if (scroll_top < info.srWindow.Top) scroll_top = info.srWindow.Top; if (scroll_bottom < info.srWindow.Top) scroll_bottom = info.srWindow.Top; - + if (scroll_top > info.srWindow.Bottom) scroll_top = info.srWindow.Bottom; - + if (scroll_bottom > info.srWindow.Bottom) scroll_bottom = info.srWindow.Bottom; - - if (info.dwCursorPosition.Y != scroll_top) { + + if (info.dwCursorPosition.Y != scroll_top) { info.dwCursorPosition.Y--; WINPORT(SetConsoleCursorPosition)(con_hnd, info.dwCursorPosition); return; } - + if (scroll_top>=scroll_bottom) return; @@ -1540,8 +1540,8 @@ struct VTAnsiContext } if (done) { - if (state == 6) - InterpretControlString(); + if (state == 6) + InterpretControlString(); else InterpretEscSeq(); state = 1; @@ -1587,7 +1587,7 @@ struct VTAnsiContext VTAnsiContext() : alternative_screen_buffer(*this) { - } + } }; @@ -1598,9 +1598,9 @@ VTAnsi::VTAnsi(IVTShell *vtsh) _ctx->ResetTerminal(); _ctx->saved_state.InitFromConsole(_ctx->vt_shell->ConsoleHandle()); _ctx->ansi_state.font_state.FromConsoleAttributes(_ctx->saved_state.csbi.wAttributes); - + VTLog::Start(); - + // get_state(); } diff --git a/far2l/src/vt/vtshell.cpp b/far2l/src/vt/vtshell.cpp index 88d7c6ee3..1d86ca0a5 100644 --- a/far2l/src/vt/vtshell.cpp +++ b/far2l/src/vt/vtshell.cpp @@ -18,10 +18,10 @@ #include #include #include -#include -#include +#include +#include #include -#include +#include #include #include #include "dirmix.hpp" @@ -34,8 +34,8 @@ #include "vtshell_ioreaders.h" #include "vtshell_mouse.h" #include "../WinPort/src/SavedScreen.h" -#define __USE_BSD -#include +#define __USE_BSD +#include #include "palette.hpp" #include "AnsiEsc.hpp" #include "TestPath.h" @@ -59,13 +59,13 @@ static void DbgPrintEscaped(const char *info, const char *s, size_t l) } else if (c <= 32 || c > 127) { char zz[64]; sprintf(zz, "\\%02x", (unsigned int)(unsigned char)c); msg+= zz; - } else + } else msg+= (char)(unsigned char)c; } fprintf(stderr, "VT %s: '%s'\n", info, msg.c_str()); } #else -# define DbgPrintEscaped(i, s, l) +# define DbgPrintEscaped(i, s, l) #endif int VTShell_Leader(char *const shell_argv[], const char *pty); @@ -126,7 +126,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell std::unique_ptr _far2l_exts; std::unique_ptr _mouse; std::mutex _read_state_mutex, _write_term_mutex; - uint32_t _mouse_expectations{0}; + uint32_t _mouse_mode{0}; std::string _start_marker, _exit_marker; std::string _host_id; @@ -238,37 +238,37 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell exit(err); return -1; } - + void UpdateTerminalSize(int fd_term) { CONSOLE_SCREEN_BUFFER_INFO csbi = { }; if (WINPORT(GetConsoleScreenBufferInfo)(ConsoleHandle(), &csbi ) && csbi.dwSize.X && csbi.dwSize.Y) { fprintf(stderr, "UpdateTerminalSize: %u x %u\n", csbi.dwSize.X, csbi.dwSize.Y); - struct winsize ws = {(unsigned short)csbi.dwSize.Y, + struct winsize ws = {(unsigned short)csbi.dwSize.Y, (unsigned short)csbi.dwSize.X, 0, 0}; if (ioctl( fd_term, TIOCSWINSZ, &ws )==-1) perror("VT: ioctl(TIOCSWINSZ)"); } } - + bool InitTerminal() { int fd_term = posix_openpt( O_RDWR | O_NOCTTY ); //use -1 to verify pipes fallback functionality _slavename.clear(); if (fd_term!=-1) { MakeFDCloexec(fd_term); - + if (grantpt(fd_term)==0 && unlockpt(fd_term)==0) { UpdateTerminalSize(fd_term); const char *slavename = ptsname(fd_term); if (slavename && *slavename) _slavename = slavename; else - perror("VT: ptsname"); + perror("VT: ptsname"); } else perror("VT: grantpt/unlockpt"); - + if (_slavename.empty()) { CheckedCloseFD(fd_term); } @@ -290,7 +290,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell } MakeFDCloexec(fd_in[1]); MakeFDCloexec(fd_out[0]); - + _pipes_fallback_in = fd_in[0]; _pipes_fallback_out = fd_out[1]; _fd_in = fd_in[1]; @@ -325,7 +325,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell { if (!InitTerminal()) return false; - + int r = ExecLeaderProcess(); if (r == -1) { perror("VT: exec leader"); @@ -336,7 +336,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell usleep(300000);//give it time to initialize, otherwise additional command copy will be echoed return true; } - + virtual bool OnProcessOutput(const char *buf, int len) //called from worker thread { @@ -361,7 +361,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell } return !_exit_marker.empty(); } - + virtual void OnTerminalResized() { if (!_slavename.empty()) @@ -375,7 +375,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell OnTerminalResized(); _last_window_info_ir = ir; } - + virtual void OnInputMouse(const MOUSE_EVENT_RECORD &MouseEvent) { //fprintf(stderr, "OnInputMouse: %x\n", MouseEvent.dwEventFlags); @@ -453,10 +453,10 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell fprintf(stderr, "VT: OnInputKeyDown - write error %d\n", errno); } } else { - fprintf(stderr, "VT: not translated keydown: VK=0x%x MODS=0x%x char=0x%x\n", + fprintf(stderr, "VT: not translated keydown: VK=0x%x MODS=0x%x char=0x%x\n", KeyEvent.wVirtualKeyCode, KeyEvent.dwControlKeyState, KeyEvent.uChar.UnicodeChar ); - } + } } virtual void OnFocusChanged() // called from worker thread @@ -481,7 +481,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell fprintf(stderr, "VT: Ctrl+Alt+C - killing them hardly...\n"); SendSignalToVT(SIGKILL); DetachTerminal(); - + } else if (_slavename.empty()) {//pipes fallback SendSignalToVT(SIGINT); } @@ -523,7 +523,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell //called in input thread context //we're input, stop output and remember _vta state - + StopAndStart sas(_output_reader); VTAnsiSuspend vta_suspend(_vta); if (!vta_suspend) @@ -550,20 +550,20 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell _keypad = keypad; } - virtual void OnMouseExpectation(MouseExpectation mex, bool enable) + virtual void OnMouseExpectation(MouseMode mex, bool enable) { fprintf(stderr, "VT::OnMouseExpectation: %u\n", mex); std::lock_guard lock(_read_state_mutex); - const auto prev_mouse_expectations = _mouse_expectations; + const auto prev_mouse_mode = _mouse_mode; if (enable) { - _mouse_expectations|= mex; + _mouse_mode|= mex; } else { - _mouse_expectations&= ~(uint32_t)mex; + _mouse_mode&= ~(uint32_t)mex; } - if (prev_mouse_expectations != _mouse_expectations) { + if (prev_mouse_mode != _mouse_mode) { _mouse.reset(); - _mouse.reset(new VTMouse(this, _mouse_expectations)); + _mouse.reset(new VTMouse(this, _mouse_mode)); } } @@ -739,7 +739,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell } CopyToClipboard(ws.c_str()); } - + virtual void InjectInput(const char *str) { _input_reader.InjectInput(str, strlen(str)); @@ -772,7 +772,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell return out; } - + std::string TranslateKeyEvent(const KEY_EVENT_RECORD &KeyEvent) { if (KeyEvent.wVirtualKeyCode) { @@ -840,10 +840,10 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell wchar_t wz[3] = {KeyEvent.uChar.UnicodeChar, 0}; if (_slavename.empty() && wz[0] == '\r') //pipes fallback wz[0] = '\n'; - + return Wide2MB(&wz[0]); } - + void SendSignalToVT(int sig) { if (_leader_pid == -1) { @@ -862,7 +862,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell fprintf(stderr, "%s: kill(%d, %d) -> %d errno=%d\n", __FUNCTION__, _leader_pid, sig, r, errno); } } - + void DetachTerminal() { FDScope dev_null(open("/dev/null", O_RDWR)); @@ -1000,7 +1000,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell if (!Startup()) return; } - + virtual ~VTShell() { fprintf(stderr, "~VTShell this=%p\n", this); @@ -1109,7 +1109,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell _win32_input_mode_expected = false; _focus_change_expected = false; _kitty_kb_flags = 0; - _mouse_expectations = 0; + _mouse_mode = 0; _far2l_exts.reset(); _mouse.reset(); // cleanup also NetRocks per-session identifier @@ -1187,7 +1187,7 @@ static int VTShell_ExecuteCommonTail(bool completed) } int VTShell_Execute(const char *cmd, bool need_sudo, bool may_bgnd, bool may_notify) -{ +{ VTShell_BusyScope vts_bs; if (!vts_bs.owner) { fprintf(stderr, "%s('%s') - not owner\n", __FUNCTION__, cmd); diff --git a/far2l/src/vt/vtshell_mouse.cpp b/far2l/src/vt/vtshell_mouse.cpp index 3c9c86cd9..e2719c3c3 100644 --- a/far2l/src/vt/vtshell_mouse.cpp +++ b/far2l/src/vt/vtshell_mouse.cpp @@ -3,111 +3,75 @@ #define BUTTONS_PRESS_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | FROM_LEFT_2ND_BUTTON_PRESSED | RIGHTMOST_BUTTON_PRESSED) -VTMouse::VTMouse(IVTShell *vtshell, uint32_t mex) - : _vtshell(vtshell), _mex(mex) +VTMouse::VTMouse(IVTShell *vtshell, uint32_t mode) + : _vtshell(vtshell), _mode(mode) { } -static constexpr char sClickMatrix[4][4] { // [Button] [Mods: none, ctrl, alt, ctrl+alt] - {'#', '3', '+', ';'}, // B_NONE (button released) - {' ', '0', '(', '8'}, // B_LEFT - {'!', '1', ')', '9'}, // B_MID - {'"', '2', '*', ':'}, // B_RIGHT -}; - -static constexpr char sMoveMatrix[4][4] { // [Button] [Mods: none, ctrl, alt, ctrl+alt] - {'C', 'S', 'K', '['}, // B_NONE (no button pressed) - {'@', 'P', 'H', 'X'}, // B_LEFT - {'A', 'Q', 'I', 'Y'}, // B_MID - {'B', 'R', 'J', 'Z'}, // B_RIGHT -}; - -static constexpr char sWheelMatrix[2][2] { // [Direction] [Mods: none, ctrl] - {'`', 'p'}, // UP - {'a', 'q'}, // DOWN -}; - bool VTMouse::OnInputMouse(const MOUSE_EVENT_RECORD &MouseEvent) { - if (MouseEvent.dwControlKeyState & SHIFT_PRESSED) { - return false; // shift combinations reserved by VT + //mode == 0 means that all mouse handling is disabled + //shift combinations reserved by VT + if (MouseEvent.dwControlKeyState & SHIFT_PRESSED || _mode == 0) { + return false; } - if (MouseEvent.dwEventFlags & MOUSE_MOVED) { - if ((_mex & (MEX_BTN_EVENT_MOUSE | MEX_ANY_EVENT_MOUSE)) == 0) - return true; - - if ((MouseEvent.dwButtonState & BUTTONS_PRESS_MASK) == 0 - && (_mex & MEX_ANY_EVENT_MOUSE) == 0) { - return true; - } - } - unsigned int imod = 0, ibut = 0; - - if (MouseEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) imod|= 1; - if (MouseEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) imod|= 2; - - if (MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) ibut = 1; - else if (MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) ibut = 2; - else if (MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) ibut = 3; - - if (_mex & MEX_SGR_EXT_MOUSE) { - int action; - char suffix = 'M'; - if (MouseEvent.dwEventFlags & MOUSE_MOVED) { - action = 35; - if (ibut) { - action = (ibut == 1) ? 0 : ((ibut == 2) ? 1 : 2); - action|= 32; - } + bool no_pressed = ((MouseEvent.dwButtonState & BUTTONS_PRESS_MASK) == 0) && !(MouseEvent.dwEventFlags & MOUSE_WHEELED); - } else if (MouseEvent.dwEventFlags & MOUSE_WHEELED) { - action = (SHORT(MouseEvent.dwButtonState >> 16) > 0) ? 64 : 65; - - } else { - int abut = ibut; - if (ibut == 0 && _sgr_prev_ibut != 0) { - suffix = 'm'; - abut = _sgr_prev_ibut; - } - _sgr_prev_ibut = ibut; - action = (abut == 1) ? 0 : ((abut == 2) ? 1 : 2); - } - if (imod & 1) action|= 16; - if (imod & 2) action|= 8; - if (MouseEvent.dwControlKeyState & SHIFT_PRESSED) action|= 4; - - char seq[64]; seq[sizeof(seq) - 1] = 0; - snprintf(seq, sizeof(seq) - 1, "\x1b[<%d;%d;%d%c", action, - MouseEvent.dwMousePosition.X + 1, MouseEvent.dwMousePosition.Y + 1, - suffix); - _vtshell->InjectInput(seq); + //send MOUSE_MOVED if only MODE_ANY_EVENT_MOUSE present + if ((MouseEvent.dwEventFlags & MOUSE_MOVED) && + (no_pressed && (_mode & MODE_ANY_EVENT_MOUSE) == 0)) { return true; } - if ( MouseEvent.dwMousePosition.X < 0 || MouseEvent.dwMousePosition.X > SHORT(0xff - '!') - || MouseEvent.dwMousePosition.Y < 0 || MouseEvent.dwMousePosition.Y > SHORT(0xff - '!') ) - { - // mouse out of encodeable region - skip events to avoid misclicks - fprintf(stderr, "VTMouse: far away - %d:%d\n", MouseEvent.dwMousePosition.X, MouseEvent.dwMousePosition.Y); - return true; + // 3 means no button pressed + unsigned int button = 3; + if (MouseEvent.dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) button = 0; + if (MouseEvent.dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) button = 1; + if (MouseEvent.dwButtonState & RIGHTMOST_BUTTON_PRESSED) button = 2; + if (MouseEvent.dwEventFlags & MOUSE_WHEELED) button = (SHORT(MouseEvent.dwButtonState >> 16) > 0) ? 0x40 : 0x41; + + //track previos button for proper released event in SGR + if (no_pressed && (_mode & MODE_SGR_EXT_MOUSE) && _sgr_prev_ibut != 0) { + button = _sgr_prev_ibut; + _sgr_prev_ibut = 0; + } else { + _sgr_prev_ibut = button; } - char seq[] = {0x1b, '[', 'M', 0 /* action */, - char('!' + MouseEvent.dwMousePosition.X), - char('!' + MouseEvent.dwMousePosition.Y), - 0}; + if (MouseEvent.dwEventFlags & MOUSE_MOVED) button |= 0x20; - if (MouseEvent.dwEventFlags & MOUSE_WHEELED) { - seq[3] = sWheelMatrix[ (SHORT(MouseEvent.dwButtonState >> 16) > 0) ? 0 : 1 ][ (imod & 1) ? 1 : 0 ]; + if (MouseEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) button |= _ctrl_ind; + if (MouseEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) button |= _alt_ind; + if (MouseEvent.dwControlKeyState & SHIFT_PRESSED) button |= _shift_ind; - } else if (MouseEvent.dwEventFlags & MOUSE_MOVED) { - seq[3] = sMoveMatrix[ibut][imod]; + char seq[64]; seq[sizeof(seq) - 1] = 0; + if (_mode & MODE_SGR_EXT_MOUSE) { + //in SGR pressed or released state is enocoded by suffix + snprintf(seq, sizeof(seq) - 1, "\x1b[<%d;%d;%d%c", + button, + MouseEvent.dwMousePosition.X + 1, + MouseEvent.dwMousePosition.Y + 1, + (no_pressed ? 'm' : 'M') + ); } else { - seq[3] = sClickMatrix[ibut][imod]; + if(MouseEvent.dwMousePosition.X < SHORT(0xff - 33) && MouseEvent.dwMousePosition.Y < SHORT(0xff - 33)) { + //in X10 Encoding button release and no button pressed are the same and 32 (0x20) is added to all values + button |= 0x20; + + snprintf(seq, sizeof(seq) - 1, "\x1b[M%c%c%c", + char(button), + char(MouseEvent.dwMousePosition.X + 33), + char(MouseEvent.dwMousePosition.Y + 33) + ); + } else { + // mouse out of encodeable region - skip events to avoid misclicks + fprintf(stderr, "VTMouse: far away - %d:%d\n", MouseEvent.dwMousePosition.X, MouseEvent.dwMousePosition.Y); + return true; + } } _vtshell->InjectInput(seq); return true; -} +} \ No newline at end of file diff --git a/far2l/src/vt/vtshell_mouse.h b/far2l/src/vt/vtshell_mouse.h index 2f5ff7154..65e855ea6 100644 --- a/far2l/src/vt/vtshell_mouse.h +++ b/far2l/src/vt/vtshell_mouse.h @@ -3,10 +3,17 @@ class VTMouse { + //bit indicators for modifier keys in mouse input sequence + const unsigned int + _shift_ind = 0x04, + _alt_ind = 0x08, + _ctrl_ind = 0x10; + IVTShell *_vtshell; - uint32_t _mex; + uint32_t _mode; unsigned int _sgr_prev_ibut{0}; + public: VTMouse(IVTShell *vtshell, uint32_t mex); bool OnInputMouse(const MOUSE_EVENT_RECORD &MouseEvent);