private void ResetMouseTracking(MouseTrackingState newState) { if (newState != MouseTrackingState.Off) { if (_mouseTrackingState == MouseTrackingState.Off) { SetDocumentCursor(Cursors.Arrow); } } else { if (_mouseTrackingState != MouseTrackingState.Off) { ResetDocumentCursor(); } } _mouseTrackingState = newState; }
private void ResetMouseTracking(MouseTrackingState newState) { if (newState != MouseTrackingState.Off) { if (_mouseTrackingState == MouseTrackingState.Off) { _prevMouseRow = -1; _prevMouseCol = -1; _mouseButton = MouseButtons.None; SetDocumentCursor(Cursors.Arrow); } } else { if (_mouseTrackingState != MouseTrackingState.Off) { ResetDocumentCursor(); } } _mouseTrackingState = newState; }
public override bool ProcessMouse(TerminalMouseAction action, MouseButtons button, Keys modKeys, int row, int col) { MouseTrackingState currentState = _mouseTrackingState; // copy value because _mouseTrackingState may be changed in another thread. if (currentState == MouseTrackingState.Off) { return(false); } // Note: from here, return value must be true even if nothing has been processed actually. MouseTrackingProtocol protocol = _mouseTrackingProtocol; // copy value because _mouseTrackingProtocol may be changed in another thread. int posLimit = protocol == MouseTrackingProtocol.Normal ? MOUSE_POS_LIMIT : MOUSE_POS_EXT_LIMIT; if (row < 0) { row = 0; } else if (row > posLimit) { row = posLimit; } if (col < 0) { col = 0; } else if (col > posLimit) { col = posLimit; } int statBits; switch (action) { case TerminalMouseAction.ButtonDown: if (_mouseButton != MouseButtons.None) { return(true); // another button is already pressed } switch (button) { case MouseButtons.Left: statBits = 0x00; break; case MouseButtons.Middle: statBits = 0x01; break; case MouseButtons.Right: statBits = 0x02; break; default: return(true); // unsupported button } _mouseButton = button; break; case TerminalMouseAction.ButtonUp: if (button != _mouseButton) { return(true); // ignore } if (protocol == MouseTrackingProtocol.Sgr) { switch (button) { case MouseButtons.Left: statBits = 0x00; break; case MouseButtons.Middle: statBits = 0x01; break; case MouseButtons.Right: statBits = 0x02; break; default: return(true); // unsupported button } } else { statBits = 0x03; } _mouseButton = MouseButtons.None; break; case TerminalMouseAction.WheelUp: statBits = 0x40; break; case TerminalMouseAction.WheelDown: statBits = 0x41; break; case TerminalMouseAction.MouseMove: if (currentState != MouseTrackingState.Any && currentState != MouseTrackingState.Drag) { return(true); // no need to send } if (currentState == MouseTrackingState.Drag && _mouseButton == MouseButtons.None) { return(true); // no need to send } if (row == _prevMouseRow && col == _prevMouseCol) { return(true); // no need to send } switch (_mouseButton) { case MouseButtons.Left: statBits = 0x20; break; case MouseButtons.Middle: statBits = 0x21; break; case MouseButtons.Right: statBits = 0x22; break; default: statBits = 0x20; break; } break; default: return(true); // unknown action } if ((modKeys & Keys.Shift) != Keys.None) { statBits |= 0x04; } if ((modKeys & Keys.Alt) != Keys.None) { statBits |= 0x08; // Meta key } if ((modKeys & Keys.Control) != Keys.None) { statBits |= 0x10; } if (protocol != MouseTrackingProtocol.Sgr) { statBits += 0x20; } _prevMouseRow = row; _prevMouseCol = col; byte[] data; int dataLen; switch (protocol) { case MouseTrackingProtocol.Normal: data = new byte[] { (byte)27, // ESCAPE (byte)91, // [ (byte)77, // M (byte)statBits, (col == posLimit) ? (byte)0 : // emulate xterm's bug (byte)(col + (1 + 0x20)), // column 0 --> send as 1 (row == posLimit) ? (byte)0 : // emulate xterm's bug (byte)(row + (1 + 0x20)), // row 0 --> send as 1 }; dataLen = 6; break; case MouseTrackingProtocol.Utf8: data = new byte[8] { (byte)27, // ESCAPE (byte)91, // [ (byte)77, // M (byte)statBits, 0, 0, 0, 0, }; dataLen = 4; if (col < MOUSE_POS_EXT_START) { data[dataLen++] = (byte)(col + (1 + 0x20)); // column 0 --> send as 1 } else // encode in UTF-8 { int val = col + 1 + 0x20; data[dataLen++] = (byte)(0xc0 + (val >> 6)); data[dataLen++] = (byte)(0x80 + (val & 0x3f)); } if (row < MOUSE_POS_EXT_START) { data[dataLen++] = (byte)(row + (1 + 0x20)); // row 0 --> send as 1 } else // encode in UTF-8 { int val = row + (1 + 0x20); data[dataLen++] = (byte)(0xc0 + (val >> 6)); data[dataLen++] = (byte)(0x80 + (val & 0x3f)); } break; case MouseTrackingProtocol.Urxvt: data = Encoding.ASCII.GetBytes( new StringBuilder() .Append("\x1b[") .Append(statBits.ToString(NumberFormatInfo.InvariantInfo)) .Append(';') .Append(col.ToString(NumberFormatInfo.InvariantInfo)) .Append(';') .Append(row.ToString(NumberFormatInfo.InvariantInfo)) .Append("M") .ToString()); dataLen = data.Length; break; case MouseTrackingProtocol.Sgr: data = Encoding.ASCII.GetBytes( new StringBuilder() .Append("\x1b[<") .Append(statBits.ToString(NumberFormatInfo.InvariantInfo)) .Append(';') .Append(col.ToString(NumberFormatInfo.InvariantInfo)) .Append(';') .Append(row.ToString(NumberFormatInfo.InvariantInfo)) .Append(action == TerminalMouseAction.ButtonUp ? 'm' : 'M') .ToString()); dataLen = data.Length; break; default: return(true); // unknown protocol } TransmitDirect(data, 0, dataLen); return(true); }