Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vt mouse refactoring #2651

Merged
merged 4 commits into from
Feb 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions far2l/src/vt/IVTShell.h
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
#pragma once
#include <string>

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;
82 changes: 41 additions & 41 deletions far2l/src/vt/vtansi.cpp
Original file line number Diff line number Diff line change
@@ -183,14 +183,14 @@ [email protected]

#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
@@ -207,7 +207,7 @@ struct VTAnsiState
memset(&csbi, 0, sizeof(csbi));
memset(&cci, 0, sizeof(cci));
}

void InitFromConsole(HANDLE con)
{
WINPORT(GetConsoleScreenBufferInfo)( con, &csbi );
@@ -405,7 +405,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
@@ -780,21 +780,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:
@@ -870,7 +870,7 @@ struct VTAnsiContext
// Ignore any other private sequences.
if (prefix2 != 0) {
LogFailedEscSeq(StrPrintf("bad prefix2 %c", prefix2));
return;
return;
}

WINPORT(GetConsoleScreenBufferInfo)( con_hnd, &Info );
@@ -974,7 +974,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;
@@ -985,16 +985,16 @@ 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];

CI_SET_WCATTR(CharInfo, blank_character, Info.wAttributes);
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;
@@ -1227,14 +1227,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’’)
@@ -1336,32 +1336,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;

@@ -1547,8 +1547,8 @@ struct VTAnsiContext
}

if (done) {
if (state == 6)
InterpretControlString();
if (state == 6)
InterpretControlString();
else
InterpretEscSeq();
state = 1;
@@ -1595,7 +1595,7 @@ struct VTAnsiContext
VTAnsiContext()
: alternative_screen_buffer(*this)
{
}
}
};


@@ -1606,9 +1606,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();
}

74 changes: 37 additions & 37 deletions far2l/src/vt/vtshell.cpp
Original file line number Diff line number Diff line change
@@ -18,10 +18,10 @@
#include <errno.h>
#include <iostream>
#include <fstream>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <condition_variable>
#include <base64.h>
#include <base64.h>
#include <StackSerializer.h>
#include <ScopeHelpers.h>
#include "dirmix.hpp"
@@ -34,8 +34,8 @@
#include "vtshell_ioreaders.h"
#include "vtshell_mouse.h"
#include "../WinPort/src/SavedScreen.h"
#define __USE_BSD
#include <termios.h>
#define __USE_BSD
#include <termios.h>
#include "farcolors.hpp"
#include "AnsiEsc.hpp"
#include "TestPath.h"
@@ -57,13 +57,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);
@@ -124,7 +124,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
std::unique_ptr<VTFar2lExtensios> _far2l_exts;
std::unique_ptr<VTMouse> _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;
@@ -236,37 +236,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);
}
@@ -288,7 +288,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];
@@ -323,7 +323,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
{
if (!InitTerminal())
return false;

int r = ExecLeaderProcess();
if (r == -1) {
perror("VT: exec leader");
@@ -334,7 +334,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
{
@@ -359,7 +359,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
}
return !_exit_marker.empty();
}

virtual void OnTerminalResized()
{
if (!_slavename.empty())
@@ -373,7 +373,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);
@@ -451,10 +451,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
@@ -479,7 +479,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);
}
@@ -521,7 +521,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell

//called in input thread context
//we're input, stop output and remember _vta state

StopAndStart<VTOutputReader> sas(_output_reader);
VTAnsiSuspend vta_suspend(_vta);
if (!vta_suspend)
@@ -548,20 +548,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<std::mutex> 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));
}
}

@@ -737,7 +737,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
}
CopyToClipboard(ws.c_str());
}

virtual void InjectInput(const char *str)
{
_input_reader.InjectInput(str, strlen(str));
@@ -770,7 +770,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell

return out;
}

std::string TranslateKeyEvent(const KEY_EVENT_RECORD &KeyEvent)
{
if (KeyEvent.wVirtualKeyCode) {
@@ -842,10 +842,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) {
@@ -864,7 +864,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));
@@ -1002,7 +1002,7 @@ class VTShell : VTOutputReader::IProcessor, VTInputReader::IProcessor, IVTShell
if (!Startup())
return;
}

virtual ~VTShell()
{
fprintf(stderr, "~VTShell this=%p\n", this);
@@ -1111,7 +1111,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
@@ -1189,7 +1189,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);
138 changes: 51 additions & 87 deletions far2l/src/vt/vtshell_mouse.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
}
9 changes: 8 additions & 1 deletion far2l/src/vt/vtshell_mouse.h
Original file line number Diff line number Diff line change
@@ -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);