sgr mode 1006

This commit is contained in:
Adam D. Ruppe 2025-12-15 16:49:20 -05:00
parent 26acaaae99
commit f494fcf9ca
1 changed files with 56 additions and 41 deletions

View File

@ -111,6 +111,13 @@ struct ScopeBuffer(T, size_t maxSize, bool allowGrowth = false) {
size_t length; size_t length;
bool isNull = true; bool isNull = true;
T[] opSlice() { return isNull ? null : buffer[0 .. length]; } T[] opSlice() { return isNull ? null : buffer[0 .. length]; }
static if(is(T == char))
void appendIntAsString(int n) {
import std.conv;
this ~= to!string(n);
}
void opOpAssign(string op : "~")(in T rhs) { void opOpAssign(string op : "~")(in T rhs) {
if(buffer is null) buffer = bufferInternal[]; if(buffer is null) buffer = bufferInternal[];
isNull = false; isNull = false;
@ -327,6 +334,7 @@ class TerminalEmulator {
if(termY >= screenHeight) if(termY >= screenHeight)
termY = screenHeight - 1; termY = screenHeight - 1;
/+
version(Windows) { version(Windows) {
// I'm swapping these because my laptop doesn't have a middle button, // I'm swapping these because my laptop doesn't have a middle button,
// and putty swaps them too by default so whatevs. // and putty swaps them too by default so whatevs.
@ -335,6 +343,7 @@ class TerminalEmulator {
else if(button == MouseButton.middle) else if(button == MouseButton.middle)
button = MouseButton.right; button = MouseButton.right;
} }
+/
int baseEventCode() { int baseEventCode() {
int b; int b;
@ -360,6 +369,9 @@ class TerminalEmulator {
if(alt) // sending alt as meta if(alt) // sending alt as meta
b |= 8; b |= 8;
if(!sgrMouseMode)
b |= 32; // it just always does this
return b; return b;
} }
@ -411,14 +423,9 @@ class TerminalEmulator {
dragging = false; dragging = false;
if(mouseButtonReleaseTracking) { if(mouseButtonReleaseTracking) {
int b = baseEventCode; int b = baseEventCode;
b |= 3; // always send none / button released if(!sgrMouseMode)
ScopeBuffer!(char, 16) buffer; b |= 3; // always send none / button released
buffer ~= "\033[M"; sendMouseEvent(b, termX, termY, true);
buffer ~= cast(char) (b | 32);
addMouseCoordinates(buffer, termX, termY);
//buffer ~= cast(char) (termX+1 + 32);
//buffer ~= cast(char) (termY+1 + 32);
sendToApplication(buffer[]);
} }
} }
@ -428,13 +435,7 @@ class TerminalEmulator {
lastDragX = termX; lastDragX = termX;
if(mouseMotionTracking || (mouseButtonMotionTracking && button)) { if(mouseMotionTracking || (mouseButtonMotionTracking && button)) {
int b = baseEventCode; int b = baseEventCode;
ScopeBuffer!(char, 16) buffer; sendMouseEvent(b + 32, termX, termY);
buffer ~= "\033[M";
buffer ~= cast(char) ((b | 32) + 32);
addMouseCoordinates(buffer, termX, termY);
//buffer ~= cast(char) (termX+1 + 32);
//buffer ~= cast(char) (termY+1 + 32);
sendToApplication(buffer[]);
} }
if(dragging) { if(dragging) {
@ -511,18 +512,9 @@ class TerminalEmulator {
int b = baseEventCode; int b = baseEventCode;
int x = termX; sendMouseEvent(b, termX, termY);
int y = termY; //buffer ~= cast(char) (x + 32);
x++; y++; // applications expect it to be one-based //buffer ~= cast(char) (y + 32);
ScopeBuffer!(char, 16) buffer;
buffer ~= "\033[M";
buffer ~= cast(char) (b | 32);
addMouseCoordinates(buffer, termX, termY);
//buffer ~= cast(char) (x + 32);
//buffer ~= cast(char) (y + 32);
sendToApplication(buffer[]);
} else { } else {
do_default_behavior: do_default_behavior:
if(button == MouseButton.middle) { if(button == MouseButton.middle) {
@ -623,24 +615,42 @@ class TerminalEmulator {
return false; return false;
} }
private void addMouseCoordinates(ref ScopeBuffer!(char, 16) buffer, int x, int y) { private void sendMouseEvent(int b, int x, int y, bool isRelease = false) {
// 1-based stuff and 32 is the base value
x += 1 + 32;
y += 1 + 32;
if(utf8MouseMode) { ScopeBuffer!(char, 16) buffer;
import std.utf;
char[4] str;
foreach(char ch; str[0 .. encode(str, x)]) if(sgrMouseMode) {
buffer ~= ch; buffer ~= "\033[<";
buffer.appendIntAsString(b);
foreach(char ch; str[0 .. encode(str, y)]) buffer ~= ";";
buffer ~= ch; buffer.appendIntAsString(x + 1);
buffer ~= ";";
buffer.appendIntAsString(y + 1);
buffer ~= isRelease ? "m" : "M";
} else { } else {
buffer ~= cast(char) x; buffer ~= "\033[M";
buffer ~= cast(char) y; buffer ~= cast(char) b;
// 1-based stuff and 32 is the base value
x += 1 + 32;
y += 1 + 32;
if(utf8MouseMode) {
import std.utf;
char[4] str;
foreach(char ch; str[0 .. encode(str, x)])
buffer ~= ch;
foreach(char ch; str[0 .. encode(str, y)])
buffer ~= ch;
} else {
buffer ~= cast(char) x;
buffer ~= cast(char) y;
}
} }
sendToApplication(buffer[]);
} }
protected void returnToNormalScreen() { protected void returnToNormalScreen() {
@ -1983,6 +1993,7 @@ class TerminalEmulator {
bool mouseButtonTracking; bool mouseButtonTracking;
private bool _mouseMotionTracking; private bool _mouseMotionTracking;
bool utf8MouseMode; bool utf8MouseMode;
bool sgrMouseMode;
bool mouseButtonReleaseTracking; bool mouseButtonReleaseTracking;
bool mouseButtonMotionTracking; bool mouseButtonMotionTracking;
bool selectiveMouseTracking; bool selectiveMouseTracking;
@ -3223,7 +3234,10 @@ SGR (1006)
The highlight tracking responses are also modified to an SGR- The highlight tracking responses are also modified to an SGR-
like format, using the same SGR-style scheme and button-encod- like format, using the same SGR-style scheme and button-encod-
ings. ings.
Note that M is used for motion; m is only release
*/ */
sgrMouseMode = true;
break; break;
case 1014: case 1014:
// ARSD extension: it is 1002 but selective, only // ARSD extension: it is 1002 but selective, only
@ -3300,6 +3314,7 @@ URXVT (1015)
break; break;
case 1006: case 1006:
// turn off sgr mouse // turn off sgr mouse
sgrMouseMode = false;
break; break;
case 1015: case 1015:
// turn off urxvt mouse // turn off urxvt mouse