/// <summary> /// Hande mouse action. /// </summary> /// <param name="action">Action type</param> /// <param name="button">Which mouse button caused the event</param> /// <param name="modifierKeys">Modifier keys (Shift, Ctrl or Alt) being pressed</param> /// <param name="row">Row index (zero based)</param> /// <param name="col">Column index (zero based)</param> /// <returns>True if mouse action was processed.</returns> public virtual bool ProcessMouse(TerminalMouseAction action, MouseButtons button, Keys modifierKeys, int row, int col) { return(false); }
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); }
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+1).ToString(NumberFormatInfo.InvariantInfo)) .Append(';') .Append((row+1).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+1).ToString(NumberFormatInfo.InvariantInfo)) .Append(';') .Append((row+1).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; }
/// <summary> /// Hande mouse action. /// </summary> /// <param name="action">Action type</param> /// <param name="button">Which mouse button caused the event</param> /// <param name="modifierKeys">Modifier keys (Shift, Ctrl or Alt) being pressed</param> /// <param name="row">Row index (zero based)</param> /// <param name="col">Column index (zero based)</param> /// <returns>True if mouse action was processed.</returns> public virtual bool ProcessMouse(TerminalMouseAction action, MouseButtons button, Keys modifierKeys, int row, int col) { return false; }