using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace Terminal.Gui {
///
/// Provides a platform-independent API for managing ANSI escape sequence codes.
///
public static class EscSeqUtils {
///
/// Represents the escape key.
///
public static readonly char KeyEsc = (char)Key.Esc;
///
/// Represents the CSI (Control Sequence Introducer).
///
public static readonly string KeyCSI = $"{KeyEsc}[";
///
/// Represents the CSI for enable any mouse event tracking.
///
public static readonly string CSI_EnableAnyEventMouse = KeyCSI + "?1003h";
///
/// Represents the CSI for enable SGR (Select Graphic Rendition).
///
public static readonly string CSI_EnableSgrExtModeMouse = KeyCSI + "?1006h";
///
/// Represents the CSI for enable URXVT (Unicode Extended Virtual Terminal).
///
public static readonly string CSI_EnableUrxvtExtModeMouse = KeyCSI + "?1015h";
///
/// Represents the CSI for disable any mouse event tracking.
///
public static readonly string CSI_DisableAnyEventMouse = KeyCSI + "?1003l";
///
/// Represents the CSI for disable SGR (Select Graphic Rendition).
///
public static readonly string CSI_DisableSgrExtModeMouse = KeyCSI + "?1006l";
///
/// Represents the CSI for disable URXVT (Unicode Extended Virtual Terminal).
///
public static readonly string CSI_DisableUrxvtExtModeMouse = KeyCSI + "?1015l";
///
/// Control sequence for enable mouse events.
///
public static string EnableMouseEvents { get; set; } =
CSI_EnableAnyEventMouse + CSI_EnableUrxvtExtModeMouse + CSI_EnableSgrExtModeMouse;
///
/// Control sequence for disable mouse events.
///
public static string DisableMouseEvents { get; set; } =
CSI_DisableAnyEventMouse + CSI_DisableUrxvtExtModeMouse + CSI_DisableSgrExtModeMouse;
///
/// Ensures a console key is mapped to one that works correctly with ANSI escape sequences.
///
/// The .
/// The modified.
public static ConsoleKeyInfo GetConsoleInputKey (ConsoleKeyInfo consoleKeyInfo)
{
ConsoleKeyInfo newConsoleKeyInfo = consoleKeyInfo;
ConsoleKey key;
var keyChar = consoleKeyInfo.KeyChar;
switch ((uint)keyChar) {
case 0:
if (consoleKeyInfo.Key == (ConsoleKey)64) { // Ctrl+Space in Windows.
newConsoleKeyInfo = new ConsoleKeyInfo (' ', ConsoleKey.Spacebar,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0);
}
break;
case uint n when (n >= '\u0001' && n <= '\u001a'):
if (consoleKeyInfo.Key == 0 && consoleKeyInfo.KeyChar == '\r') {
key = ConsoleKey.Enter;
newConsoleKeyInfo = new ConsoleKeyInfo (consoleKeyInfo.KeyChar,
key,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0);
} else if (consoleKeyInfo.Key == 0) {
key = (ConsoleKey)(char)(consoleKeyInfo.KeyChar + (uint)ConsoleKey.A - 1);
newConsoleKeyInfo = new ConsoleKeyInfo ((char)key,
key,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0,
true);
}
break;
case 127:
newConsoleKeyInfo = new ConsoleKeyInfo (consoleKeyInfo.KeyChar, ConsoleKey.Backspace,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Shift) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Alt) != 0,
(consoleKeyInfo.Modifiers & ConsoleModifiers.Control) != 0);
break;
default:
newConsoleKeyInfo = consoleKeyInfo;
break;
}
return newConsoleKeyInfo;
}
///
/// A helper to resize the as needed.
///
/// The .
/// The array to resize.
/// The resized.
public static ConsoleKeyInfo [] ResizeArray (ConsoleKeyInfo consoleKeyInfo, ConsoleKeyInfo [] cki)
{
Array.Resize (ref cki, cki == null ? 1 : cki.Length + 1);
cki [cki.Length - 1] = consoleKeyInfo;
return cki;
}
///
/// Decodes a escape sequence to been processed in the appropriate manner.
///
/// The which may contain a request.
/// The which may changes.
/// The which may changes.
/// The array.
/// The which may changes.
/// The control returned by the method.
/// The code returned by the method.
/// The values returned by the method.
/// The terminating returned by the method.
/// Indicates if the escape sequence is a mouse key.
/// The button state.
/// The position.
/// Indicates if the escape sequence is a response to a request.
/// The handler that will process the event.
public static void DecodeEscSeq (EscSeqReqProc escSeqReqProc, ref ConsoleKeyInfo newConsoleKeyInfo, ref ConsoleKey key, ConsoleKeyInfo [] cki, ref ConsoleModifiers mod, out string c1Control, out string code, out string [] values, out string terminating, out bool isKeyMouse, out List buttonState, out Point pos, out bool isReq, Action continuousButtonPressedHandler)
{
char [] kChars = GetKeyCharArray (cki);
(c1Control, code, values, terminating) = GetEscapeResult (kChars);
isKeyMouse = false;
buttonState = new List () { 0 };
pos = default;
isReq = false;
switch (c1Control) {
case "ESC":
if (values == null && string.IsNullOrEmpty (terminating)) {
key = ConsoleKey.Escape;
newConsoleKeyInfo = new ConsoleKeyInfo (cki [0].KeyChar, key,
(mod & ConsoleModifiers.Shift) != 0,
(mod & ConsoleModifiers.Alt) != 0,
(mod & ConsoleModifiers.Control) != 0);
} else if ((uint)cki [1].KeyChar >= 1 && (uint)cki [1].KeyChar <= 26) {
key = (ConsoleKey)(char)(cki [1].KeyChar + (uint)ConsoleKey.A - 1);
newConsoleKeyInfo = new ConsoleKeyInfo (cki [1].KeyChar,
key,
false,
true,
true);
} else {
if (cki [1].KeyChar >= 97 && cki [1].KeyChar <= 122) {
key = (ConsoleKey)cki [1].KeyChar.ToString ().ToUpper () [0];
} else {
key = (ConsoleKey)cki [1].KeyChar;
}
newConsoleKeyInfo = new ConsoleKeyInfo ((char)key,
(ConsoleKey)Math.Min ((uint)key, 255),
false,
true,
false);
}
break;
case "SS3":
key = GetConsoleKey (terminating [0], values [0], ref mod);
newConsoleKeyInfo = new ConsoleKeyInfo ('\0',
key,
(mod & ConsoleModifiers.Shift) != 0,
(mod & ConsoleModifiers.Alt) != 0,
(mod & ConsoleModifiers.Control) != 0);
break;
case "CSI":
if (!string.IsNullOrEmpty (code) && code == "<") {
GetMouse (cki, out buttonState, out pos, continuousButtonPressedHandler);
isKeyMouse = true;
return;
} else if (escSeqReqProc != null && escSeqReqProc.Requested (terminating)) {
isReq = true;
escSeqReqProc.Remove (terminating);
return;
}
key = GetConsoleKey (terminating [0], values [0], ref mod);
if (key != 0 && values.Length > 1) {
mod |= GetConsoleModifiers (values [1]);
}
newConsoleKeyInfo = new ConsoleKeyInfo ('\0',
key,
(mod & ConsoleModifiers.Shift) != 0,
(mod & ConsoleModifiers.Alt) != 0,
(mod & ConsoleModifiers.Control) != 0);
break;
}
}
///
/// Gets all the needed information about a escape sequence.
///
/// The array with all chars.
///
/// The c1Control returned by , code, values and terminating.
///
public static (string c1Control, string code, string [] values, string terminating) GetEscapeResult (char [] kChar)
{
if (kChar == null || kChar.Length == 0) {
return (null, null, null, null);
}
if (kChar [0] != '\x1b') {
throw new InvalidOperationException ("Invalid escape character!");
}
if (kChar.Length == 1) {
return ("ESC", null, null, null);
}
if (kChar.Length == 2) {
return ("ESC", null, null, kChar [1].ToString ());
}
string c1Control = GetC1ControlChar (kChar [1]);
string code = null;
int nSep = kChar.Count (x => x == ';') + 1;
string [] values = new string [nSep];
int valueIdx = 0;
string terminating = "";
for (int i = 2; i < kChar.Length; i++) {
var c = kChar [i];
if (char.IsDigit (c)) {
values [valueIdx] += c.ToString ();
} else if (c == ';') {
valueIdx++;
} else if (valueIdx == nSep - 1 || i == kChar.Length - 1) {
terminating += c.ToString ();
} else {
code += c.ToString ();
}
}
return (c1Control, code, values, terminating);
}
///
/// Gets the c1Control used in the called escape sequence.
///
/// The char used.
/// The c1Control.
public static string GetC1ControlChar (char c)
{
// These control characters are used in the vtXXX emulation.
switch (c) {
case 'D':
return "IND"; // Index
case 'E':
return "NEL"; // Next Line
case 'H':
return "HTS"; // Tab Set
case 'M':
return "RI"; // Reverse Index
case 'N':
return "SS2"; // Single Shift Select of G2 Character Set: affects next character only
case 'O':
return "SS3"; // Single Shift Select of G3 Character Set: affects next character only
case 'P':
return "DCS"; // Device Control String
case 'V':
return "SPA"; // Start of Guarded Area
case 'W':
return "EPA"; // End of Guarded Area
case 'X':
return "SOS"; // Start of String
case 'Z':
return "DECID"; // Return Terminal ID Obsolete form of CSI c (DA)
case '[':
return "CSI"; // Control Sequence Introducer
case '\\':
return "ST"; // String Terminator
case ']':
return "OSC"; // Operating System Command
case '^':
return "PM"; // Privacy Message
case '_':
return "APC"; // Application Program Command
default:
return ""; // Not supported
}
}
///
/// Gets the from the value.
///
/// The value.
/// The or zero.
public static ConsoleModifiers GetConsoleModifiers (string value)
{
switch (value) {
case "2":
return ConsoleModifiers.Shift;
case "3":
return ConsoleModifiers.Alt;
case "4":
return ConsoleModifiers.Shift | ConsoleModifiers.Alt;
case "5":
return ConsoleModifiers.Control;
case "6":
return ConsoleModifiers.Shift | ConsoleModifiers.Control;
case "7":
return ConsoleModifiers.Alt | ConsoleModifiers.Control;
case "8":
return ConsoleModifiers.Shift | ConsoleModifiers.Alt | ConsoleModifiers.Control;
default:
return 0;
}
}
///
/// Gets the depending on terminating and value.
///
/// The terminating.
/// The value.
/// The which may changes.
/// The and probably the .
public static ConsoleKey GetConsoleKey (char terminating, string value, ref ConsoleModifiers mod)
{
ConsoleKey key;
switch (terminating) {
case 'A':
key = ConsoleKey.UpArrow;
break;
case 'B':
key = ConsoleKey.DownArrow;
break;
case 'C':
key = ConsoleKey.RightArrow;
break;
case 'D':
key = ConsoleKey.LeftArrow;
break;
case 'F':
key = ConsoleKey.End;
break;
case 'H':
key = ConsoleKey.Home;
break;
case 'P':
key = ConsoleKey.F1;
break;
case 'Q':
key = ConsoleKey.F2;
break;
case 'R':
key = ConsoleKey.F3;
break;
case 'S':
key = ConsoleKey.F4;
break;
case 'Z':
key = ConsoleKey.Tab;
mod |= ConsoleModifiers.Shift;
break;
case '~':
switch (value) {
case "2":
key = ConsoleKey.Insert;
break;
case "3":
key = ConsoleKey.Delete;
break;
case "5":
key = ConsoleKey.PageUp;
break;
case "6":
key = ConsoleKey.PageDown;
break;
case "15":
key = ConsoleKey.F5;
break;
case "17":
key = ConsoleKey.F6;
break;
case "18":
key = ConsoleKey.F7;
break;
case "19":
key = ConsoleKey.F8;
break;
case "20":
key = ConsoleKey.F9;
break;
case "21":
key = ConsoleKey.F10;
break;
case "23":
key = ConsoleKey.F11;
break;
case "24":
key = ConsoleKey.F12;
break;
default:
key = 0;
break;
}
break;
default:
key = 0;
break;
}
return key;
}
///
/// A helper to get only the from the array.
///
///
/// The char array of the escape sequence.
public static char [] GetKeyCharArray (ConsoleKeyInfo [] cki)
{
char [] kChar = new char [] { };
var length = 0;
foreach (var kc in cki) {
length++;
Array.Resize (ref kChar, length);
kChar [length - 1] = kc.KeyChar;
}
return kChar;
}
private static MouseFlags? lastMouseButtonPressed;
//private static MouseFlags? lastMouseButtonReleased;
private static bool isButtonPressed;
//private static bool isButtonReleased;
private static bool isButtonClicked;
private static bool isButtonDoubleClicked;
private static bool isButtonTripleClicked;
private static Point point;
///
/// Gets the mouse button flags and the position.
///
/// The array.
/// The mouse button flags.
/// The mouse position.
/// The handler that will process the event.
public static void GetMouse (ConsoleKeyInfo [] cki, out List mouseFlags, out Point pos, Action continuousButtonPressedHandler)
{
MouseFlags buttonState = 0;
pos = new Point ();
int buttonCode = 0;
bool foundButtonCode = false;
int foundPoint = 0;
string value = "";
var kChar = GetKeyCharArray (cki);
//System.Diagnostics.Debug.WriteLine ($"kChar: {new string (kChar)}");
for (int i = 0; i < kChar.Length; i++) {
var c = kChar [i];
if (c == '<') {
foundButtonCode = true;
} else if (foundButtonCode && c != ';') {
value += c.ToString ();
} else if (c == ';') {
if (foundButtonCode) {
foundButtonCode = false;
buttonCode = int.Parse (value);
}
if (foundPoint == 1) {
pos.X = int.Parse (value) - 1;
}
value = "";
foundPoint++;
} else if (foundPoint > 0 && c != 'm' && c != 'M') {
value += c.ToString ();
} else if (c == 'm' || c == 'M') {
//pos.Y = int.Parse (value) + Console.WindowTop - 1;
pos.Y = int.Parse (value) - 1;
switch (buttonCode) {
case 0:
case 8:
case 16:
case 24:
case 32:
case 36:
case 40:
case 48:
case 56:
buttonState = c == 'M' ? MouseFlags.Button1Pressed
: MouseFlags.Button1Released;
break;
case 1:
case 9:
case 17:
case 25:
case 33:
case 37:
case 41:
case 45:
case 49:
case 53:
case 57:
case 61:
buttonState = c == 'M' ? MouseFlags.Button2Pressed
: MouseFlags.Button2Released;
break;
case 2:
case 10:
case 14:
case 18:
case 22:
case 26:
case 30:
case 34:
case 42:
case 46:
case 50:
case 54:
case 58:
case 62:
buttonState = c == 'M' ? MouseFlags.Button3Pressed
: MouseFlags.Button3Released;
break;
case 35:
//// Needed for Windows OS
//if (isButtonPressed && c == 'm'
// && (lastMouseEvent.ButtonState == MouseFlags.Button1Pressed
// || lastMouseEvent.ButtonState == MouseFlags.Button2Pressed
// || lastMouseEvent.ButtonState == MouseFlags.Button3Pressed)) {
// switch (lastMouseEvent.ButtonState) {
// case MouseFlags.Button1Pressed:
// buttonState = MouseFlags.Button1Released;
// break;
// case MouseFlags.Button2Pressed:
// buttonState = MouseFlags.Button2Released;
// break;
// case MouseFlags.Button3Pressed:
// buttonState = MouseFlags.Button3Released;
// break;
// }
//} else {
// buttonState = MouseFlags.ReportMousePosition;
//}
//break;
case 39:
case 43:
case 47:
case 51:
case 55:
case 59:
case 63:
buttonState = MouseFlags.ReportMousePosition;
break;
case 64:
buttonState = MouseFlags.WheeledUp;
break;
case 65:
buttonState = MouseFlags.WheeledDown;
break;
case 68:
case 72:
case 80:
buttonState = MouseFlags.WheeledLeft; // Shift/Ctrl+WheeledUp
break;
case 69:
case 73:
case 81:
buttonState = MouseFlags.WheeledRight; // Shift/Ctrl+WheeledDown
break;
}
// Modifiers.
switch (buttonCode) {
case 8:
case 9:
case 10:
case 43:
buttonState |= MouseFlags.ButtonAlt;
break;
case 14:
case 47:
buttonState |= MouseFlags.ButtonAlt | MouseFlags.ButtonShift;
break;
case 16:
case 17:
case 18:
case 51:
buttonState |= MouseFlags.ButtonCtrl;
break;
case 22:
case 55:
buttonState |= MouseFlags.ButtonCtrl | MouseFlags.ButtonShift;
break;
case 24:
case 25:
case 26:
case 59:
buttonState |= MouseFlags.ButtonCtrl | MouseFlags.ButtonAlt;
break;
case 30:
case 63:
buttonState |= MouseFlags.ButtonCtrl | MouseFlags.ButtonShift | MouseFlags.ButtonAlt;
break;
case 32:
case 33:
case 34:
buttonState |= MouseFlags.ReportMousePosition;
break;
case 36:
case 37:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonShift;
break;
case 39:
case 68:
case 69:
buttonState |= MouseFlags.ButtonShift;
break;
case 40:
case 41:
case 42:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonAlt;
break;
case 45:
case 46:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonAlt | MouseFlags.ButtonShift;
break;
case 48:
case 49:
case 50:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl;
break;
case 53:
case 54:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl | MouseFlags.ButtonShift;
break;
case 56:
case 57:
case 58:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl | MouseFlags.ButtonAlt;
break;
case 61:
case 62:
buttonState |= MouseFlags.ReportMousePosition | MouseFlags.ButtonCtrl | MouseFlags.ButtonShift | MouseFlags.ButtonAlt;
break;
}
}
}
mouseFlags = new List () { MouseFlags.AllEvents };
if (lastMouseButtonPressed != null && !isButtonPressed && !buttonState.HasFlag (MouseFlags.ReportMousePosition)
&& !buttonState.HasFlag (MouseFlags.Button1Released)
&& !buttonState.HasFlag (MouseFlags.Button2Released)
&& !buttonState.HasFlag (MouseFlags.Button3Released)
&& !buttonState.HasFlag (MouseFlags.Button4Released)) {
lastMouseButtonPressed = null;
isButtonPressed = false;
}
if (!isButtonClicked && !isButtonDoubleClicked && ((buttonState == MouseFlags.Button1Pressed || buttonState == MouseFlags.Button2Pressed ||
buttonState == MouseFlags.Button3Pressed || buttonState == MouseFlags.Button4Pressed) && lastMouseButtonPressed == null) ||
isButtonPressed && lastMouseButtonPressed != null && buttonState.HasFlag (MouseFlags.ReportMousePosition)) {
mouseFlags [0] = buttonState;
lastMouseButtonPressed = buttonState;
isButtonPressed = true;
if ((mouseFlags [0] & MouseFlags.ReportMousePosition) == 0) {
point = new Point () {
X = pos.X,
Y = pos.Y
};
Application.MainLoop.AddIdle (() => {
Task.Run (async () => await ProcessContinuousButtonPressedAsync (buttonState, continuousButtonPressedHandler));
return false;
});
} else if (mouseFlags [0] == MouseFlags.ReportMousePosition) {
isButtonPressed = false;
}
} else if (isButtonDoubleClicked && (buttonState == MouseFlags.Button1Pressed || buttonState == MouseFlags.Button2Pressed ||
buttonState == MouseFlags.Button3Pressed || buttonState == MouseFlags.Button4Pressed)) {
mouseFlags [0] = GetButtonTripleClicked (buttonState);
isButtonDoubleClicked = false;
isButtonTripleClicked = true;
} else if (isButtonClicked && (buttonState == MouseFlags.Button1Pressed || buttonState == MouseFlags.Button2Pressed ||
buttonState == MouseFlags.Button3Pressed || buttonState == MouseFlags.Button4Pressed)) {
mouseFlags [0] = GetButtonDoubleClicked (buttonState);
isButtonClicked = false;
isButtonDoubleClicked = true;
Application.MainLoop.AddIdle (() => {
Task.Run (async () => await ProcessButtonDoubleClickedAsync ());
return false;
});
}
//else if (isButtonReleased && !isButtonClicked && buttonState == MouseFlags.ReportMousePosition) {
// mouseFlag [0] = GetButtonClicked ((MouseFlags)lastMouseButtonReleased);
// lastMouseButtonReleased = null;
// isButtonReleased = false;
// isButtonClicked = true;
// Application.MainLoop.AddIdle (() => {
// Task.Run (async () => await ProcessButtonClickedAsync ());
// return false;
// });
//}
else if (!isButtonClicked && !isButtonDoubleClicked && (buttonState == MouseFlags.Button1Released || buttonState == MouseFlags.Button2Released ||
buttonState == MouseFlags.Button3Released || buttonState == MouseFlags.Button4Released)) {
mouseFlags [0] = buttonState;
isButtonPressed = false;
if (isButtonTripleClicked) {
isButtonTripleClicked = false;
} else if (pos.X == point.X && pos.Y == point.Y) {
mouseFlags.Add (GetButtonClicked (buttonState));
isButtonClicked = true;
Application.MainLoop.AddIdle (() => {
Task.Run (async () => await ProcessButtonClickedAsync ());
return false;
});
}
point = pos;
//if ((lastMouseButtonPressed & MouseFlags.ReportMousePosition) == 0) {
// lastMouseButtonReleased = buttonState;
// isButtonPressed = false;
// isButtonReleased = true;
//} else {
// lastMouseButtonPressed = null;
// isButtonPressed = false;
//}
} else if (buttonState == MouseFlags.WheeledUp) {
mouseFlags [0] = MouseFlags.WheeledUp;
} else if (buttonState == MouseFlags.WheeledDown) {
mouseFlags [0] = MouseFlags.WheeledDown;
} else if (buttonState == MouseFlags.WheeledLeft) {
mouseFlags [0] = MouseFlags.WheeledLeft;
} else if (buttonState == MouseFlags.WheeledRight) {
mouseFlags [0] = MouseFlags.WheeledRight;
} else if (buttonState == MouseFlags.ReportMousePosition) {
mouseFlags [0] = MouseFlags.ReportMousePosition;
} else {
mouseFlags [0] = buttonState;
//foreach (var flag in buttonState.GetUniqueFlags()) {
// mouseFlag [0] |= flag;
//}
}
mouseFlags [0] = SetControlKeyStates (buttonState, mouseFlags [0]);
//buttonState = mouseFlags;
//System.Diagnostics.Debug.WriteLine ($"buttonState: {buttonState} X: {pos.X} Y: {pos.Y}");
//foreach (var mf in mouseFlags) {
// System.Diagnostics.Debug.WriteLine ($"mouseFlags: {mf} X: {pos.X} Y: {pos.Y}");
//}
}
private static async Task ProcessContinuousButtonPressedAsync (MouseFlags mouseFlag, Action continuousButtonPressedHandler)
{
while (isButtonPressed) {
await Task.Delay (100);
//var me = new MouseEvent () {
// X = point.X,
// Y = point.Y,
// Flags = mouseFlag
//};
var view = Application.WantContinuousButtonPressedView;
if (view == null)
break;
if (isButtonPressed && lastMouseButtonPressed != null && (mouseFlag & MouseFlags.ReportMousePosition) == 0) {
Application.MainLoop.Invoke (() => continuousButtonPressedHandler (mouseFlag, point));
}
}
}
private static async Task ProcessButtonClickedAsync ()
{
await Task.Delay (300);
isButtonClicked = false;
}
private static async Task ProcessButtonDoubleClickedAsync ()
{
await Task.Delay (300);
isButtonDoubleClicked = false;
}
private static MouseFlags GetButtonClicked (MouseFlags mouseFlag)
{
MouseFlags mf = default;
switch (mouseFlag) {
case MouseFlags.Button1Released:
mf = MouseFlags.Button1Clicked;
break;
case MouseFlags.Button2Released:
mf = MouseFlags.Button2Clicked;
break;
case MouseFlags.Button3Released:
mf = MouseFlags.Button3Clicked;
break;
}
return mf;
}
private static MouseFlags GetButtonDoubleClicked (MouseFlags mouseFlag)
{
MouseFlags mf = default;
switch (mouseFlag) {
case MouseFlags.Button1Pressed:
mf = MouseFlags.Button1DoubleClicked;
break;
case MouseFlags.Button2Pressed:
mf = MouseFlags.Button2DoubleClicked;
break;
case MouseFlags.Button3Pressed:
mf = MouseFlags.Button3DoubleClicked;
break;
}
return mf;
}
private static MouseFlags GetButtonTripleClicked (MouseFlags mouseFlag)
{
MouseFlags mf = default;
switch (mouseFlag) {
case MouseFlags.Button1Pressed:
mf = MouseFlags.Button1TripleClicked;
break;
case MouseFlags.Button2Pressed:
mf = MouseFlags.Button2TripleClicked;
break;
case MouseFlags.Button3Pressed:
mf = MouseFlags.Button3TripleClicked;
break;
}
return mf;
}
private static MouseFlags SetControlKeyStates (MouseFlags buttonState, MouseFlags mouseFlag)
{
if ((buttonState & MouseFlags.ButtonCtrl) != 0 && (mouseFlag & MouseFlags.ButtonCtrl) == 0)
mouseFlag |= MouseFlags.ButtonCtrl;
if ((buttonState & MouseFlags.ButtonShift) != 0 && (mouseFlag & MouseFlags.ButtonShift) == 0)
mouseFlag |= MouseFlags.ButtonShift;
if ((buttonState & MouseFlags.ButtonAlt) != 0 && (mouseFlag & MouseFlags.ButtonAlt) == 0)
mouseFlag |= MouseFlags.ButtonAlt;
return mouseFlag;
}
///
/// Get the terminal that holds the console driver.
///
/// The process.
/// If supported the executable console process, null otherwise.
public static Process GetParentProcess (Process process)
{
if (!RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) {
return null;
}
string query = "SELECT ParentProcessId FROM Win32_Process WHERE ProcessId = " + process.Id;
using (ManagementObjectSearcher mos = new ManagementObjectSearcher (query)) {
foreach (ManagementObject mo in mos.Get ()) {
if (mo ["ParentProcessId"] != null) {
try {
var id = Convert.ToInt32 (mo ["ParentProcessId"]);
return Process.GetProcessById (id);
} catch {
}
}
}
}
return null;
}
}
}