Added mouse features in the Unix version. Supports xterm-1006.

This commit is contained in:
BDisp
2020-05-17 18:15:43 +01:00
parent b8450e2d31
commit eb37e776e8
2 changed files with 226 additions and 36 deletions

View File

@@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Mono.Terminal;
using NStack;
using Unix.Terminal;
@@ -182,12 +183,185 @@ namespace Terminal.Gui {
}
}
static MouseEvent ToDriverMouse (Curses.MouseEvent cev)
Curses.Event? LastMouseButtonPressed = null;
bool IsButtonPressed = false;
bool cancelButtonClicked = false;
Point point;
MouseEvent ToDriverMouse (Curses.MouseEvent cev)
{
MouseFlags mouseFlag = MouseFlags.AllEvents;
if (LastMouseButtonPressed != null && cev.ButtonState != Curses.Event.ReportMousePosition) {
LastMouseButtonPressed = null;
IsButtonPressed = false;
}
if ((cev.ButtonState == Curses.Event.Button1Clicked || cev.ButtonState == Curses.Event.Button2Clicked ||
cev.ButtonState == Curses.Event.Button3Clicked) &&
LastMouseButtonPressed == null) {
IsButtonPressed = false;
mouseFlag = ProcessButtonClickedEvent (cev, mouseFlag);
} else if (((cev.ButtonState == Curses.Event.Button1Pressed || cev.ButtonState == Curses.Event.Button2Pressed ||
cev.ButtonState == Curses.Event.Button3Pressed) && LastMouseButtonPressed == null) ||
IsButtonPressed && cev.ButtonState == Curses.Event.ReportMousePosition) {
mouseFlag = (MouseFlags)cev.ButtonState;
if (cev.ButtonState != Curses.Event.ReportMousePosition)
LastMouseButtonPressed = cev.ButtonState;
IsButtonPressed = true;
if (cev.ButtonState == Curses.Event.ReportMousePosition) {
mouseFlag = (MouseFlags)LastMouseButtonPressed | MouseFlags.ReportMousePosition;
point = new Point ();
cancelButtonClicked = true;
} else {
point = new Point () {
X = cev.X,
Y = cev.Y
};
}
if ((mouseFlag & MouseFlags.ReportMousePosition) == 0) {
Task.Run (async () => {
while (IsButtonPressed && LastMouseButtonPressed != null) {
await Task.Delay (200);
var me = new MouseEvent () {
X = cev.X,
Y = cev.Y,
Flags = mouseFlag
};
var view = Application.wantContinuousButtonPressedView;
if (view == null)
break;
if (IsButtonPressed && LastMouseButtonPressed != null && (mouseFlag & MouseFlags.ReportMousePosition) == 0) {
mouseHandler (me);
mainLoop.Driver.Wakeup ();
}
}
});
}
} else if ((cev.ButtonState == Curses.Event.Button1Released || cev.ButtonState == Curses.Event.Button2Released ||
cev.ButtonState == Curses.Event.Button3Released)) {
mouseFlag = ProcessButtonReleasedEvent (cev, mouseFlag);
IsButtonPressed = false;
} else if (cev.ButtonState == Curses.Event.Button4Pressed) {
mouseFlag = MouseFlags.WheeledUp;
} else if (cev.ButtonState == Curses.Event.ReportMousePosition && cev.X == point.X && cev.Y == point.Y) {
mouseFlag = MouseFlags.WheeledDown;
}
else if (cev.ButtonState == Curses.Event.ReportMousePosition) {
mouseFlag = MouseFlags.ReportMousePosition;
} else {
mouseFlag = (MouseFlags)cev.ButtonState;
}
point = new Point () {
X = cev.X,
Y = cev.Y
};
if (cev.ID != 0)
mouseFlag = MouseFlags.WheeledDown;
return new MouseEvent () {
X = cev.X,
Y = cev.Y,
//Flags = (MouseFlags)cev.ButtonState
Flags = mouseFlag
};
}
private MouseFlags ProcessButtonClickedEvent (Curses.MouseEvent cev, MouseFlags mf)
{
LastMouseButtonPressed = cev.ButtonState;
mf = GetButtonState (cev, true);
mouseHandler (ProcessButtonState (cev, mf));
if (LastMouseButtonPressed != null && LastMouseButtonPressed == cev.ButtonState) {
mf = GetButtonState (cev, false);
mouseHandler (ProcessButtonState (cev, mf));
if (LastMouseButtonPressed != null && LastMouseButtonPressed == cev.ButtonState) {
mf = (MouseFlags)cev.ButtonState;
}
}
LastMouseButtonPressed = null;
return mf;
}
private MouseFlags ProcessButtonReleasedEvent (Curses.MouseEvent cev, MouseFlags mf)
{
mf = (MouseFlags)cev.ButtonState;
mouseHandler (ProcessButtonState (cev, mf));
if (!cancelButtonClicked && LastMouseButtonPressed == null)
mf = GetButtonState (cev);
else
cancelButtonClicked = false;
return mf;
}
MouseFlags GetButtonState (Curses.MouseEvent cev, bool pressed = false)
{
MouseFlags mf = default;
switch (cev.ButtonState) {
case Curses.Event.Button1Clicked:
if (pressed)
mf = MouseFlags.Button1Pressed;
else
mf = MouseFlags.Button1Released;
break;
case Curses.Event.Button2Clicked:
if (pressed)
mf = MouseFlags.Button2Pressed;
else
mf = MouseFlags.Button2Released;
break;
case Curses.Event.Button3Clicked:
if (pressed)
mf = MouseFlags.Button3Pressed;
else
mf = MouseFlags.Button3Released;
break;
case Curses.Event.Button1Released:
mf = MouseFlags.Button1Clicked;
break;
case Curses.Event.Button2Released:
mf = MouseFlags.Button2Clicked;
break;
case Curses.Event.Button3Released:
mf = MouseFlags.Button3Clicked;
break;
}
return mf;
}
MouseEvent ProcessButtonState (Curses.MouseEvent cev, MouseFlags mf)
{
return new MouseEvent () {
X = cev.X,
Y = cev.Y,
Flags = (MouseFlags)cev.ButtonState
Flags = mf
};
}
@@ -245,12 +419,17 @@ namespace Terminal.Gui {
keyHandler (new KeyEvent ((Key)wch));
}
Action<MouseEvent> mouseHandler;
MainLoop mainLoop;
public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
{
// Note: Curses doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
Curses.timeout (-1);
Curses.timeout (0);
this.mouseHandler = mouseHandler;
this.mainLoop = mainLoop;
(mainLoop.Driver as Mono.Terminal.UnixMainLoop).AddWatch (0, Mono.Terminal.UnixMainLoop.Condition.PollIn, x => {
(mainLoop.Driver as Mono.Terminal.UnixMainLoop).AddWatch (0, Mono.Terminal.UnixMainLoop.Condition.PollIn, x => {
ProcessInput (keyHandler, mouseHandler);
return true;
});
@@ -418,21 +597,21 @@ namespace Terminal.Gui {
Console.Out.Flush ();
}
int lastMouseInterval;
bool mouseGrabbed;
//int lastMouseInterval;
//bool mouseGrabbed;
public override void UncookMouse ()
{
if (mouseGrabbed)
return;
lastMouseInterval = Curses.mouseinterval (0);
mouseGrabbed = true;
//if (mouseGrabbed)
// return;
//lastMouseInterval = Curses.mouseinterval (0);
//mouseGrabbed = true;
}
public override void CookMouse ()
{
mouseGrabbed = false;
Curses.mouseinterval (lastMouseInterval);
//mouseGrabbed = false;
//Curses.mouseinterval (lastMouseInterval);
}
}

View File

@@ -2,6 +2,8 @@
* This file is autogenerated by the attrib.c program, do not edit
*/
#define XTERM1006
using System;
namespace Unix.Terminal {
@@ -76,6 +78,15 @@ namespace Unix.Terminal {
ReportMousePosition = unchecked((int)0x8000000),
AllEvents = unchecked((int)0x7ffffff),
}
#if XTERM1006
public const int LeftRightUpNPagePPage= unchecked((int)0x8);
public const int DownEnd = unchecked((int)0x6);
public const int Home = unchecked((int)0x7);
#else
public const int LeftRightUpNPagePPage= unchecked((int)0x0);
public const int DownEnd = unchecked((int)0x0);
public const int Home = unchecked((int)0x0);
#endif
public const int ERR = unchecked((int)0xffffffff);
public const int KeyBackspace = unchecked((int)0x107);
public const int KeyUp = unchecked((int)0x103);
@@ -109,30 +120,30 @@ namespace Unix.Terminal {
public const int ShiftKeyPPage = unchecked((int)0x18e);
public const int ShiftKeyHome = unchecked((int)0x187);
public const int ShiftKeyEnd = unchecked((int)0x182);
public const int AltKeyUp = unchecked((int)0x234);
public const int AltKeyDown = unchecked((int)0x20b);
public const int AltKeyLeft = unchecked((int)0x21f);
public const int AltKeyRight = unchecked((int)0x22e);
public const int AltKeyNPage = unchecked((int)0x224);
public const int AltKeyPPage = unchecked((int)0x229);
public const int AltKeyHome = unchecked((int)0x215);
public const int AltKeyEnd = unchecked((int)0x210);
public const int CtrlKeyUp = unchecked((int)0x236);
public const int CtrlKeyDown = unchecked((int)0x20d);
public const int CtrlKeyLeft = unchecked((int)0x221);
public const int CtrlKeyRight = unchecked((int)0x230);
public const int CtrlKeyNPage = unchecked((int)0x226);
public const int CtrlKeyPPage = unchecked((int)0x22b);
public const int CtrlKeyHome = unchecked((int)0x217);
public const int CtrlKeyEnd = unchecked((int)0x212);
public const int ShiftCtrlKeyUp = unchecked((int)0x237);
public const int ShiftCtrlKeyDown = unchecked((int)0x20e);
public const int ShiftCtrlKeyLeft = unchecked((int)0x222);
public const int ShiftCtrlKeyRight = unchecked((int)0x231);
public const int ShiftCtrlKeyNPage = unchecked((int)0x227);
public const int ShiftCtrlKeyPPage = unchecked((int)0x22c);
public const int ShiftCtrlKeyHome = unchecked((int)0x218);
public const int ShiftCtrlKeyEnd = unchecked((int)0x213);
public const int AltKeyUp = unchecked((int)0x234 + LeftRightUpNPagePPage);
public const int AltKeyDown = unchecked((int)0x20b + DownEnd);
public const int AltKeyLeft = unchecked((int)0x21f + LeftRightUpNPagePPage);
public const int AltKeyRight = unchecked((int)0x22e + LeftRightUpNPagePPage);
public const int AltKeyNPage = unchecked((int)0x224 + LeftRightUpNPagePPage);
public const int AltKeyPPage = unchecked((int)0x229 + LeftRightUpNPagePPage);
public const int AltKeyHome = unchecked((int)0x215 + Home);
public const int AltKeyEnd = unchecked((int)0x210 + DownEnd);
public const int CtrlKeyUp = unchecked((int)0x236 + LeftRightUpNPagePPage);
public const int CtrlKeyDown = unchecked((int)0x20d + DownEnd);
public const int CtrlKeyLeft = unchecked((int)0x221 + LeftRightUpNPagePPage);
public const int CtrlKeyRight = unchecked((int)0x230 + LeftRightUpNPagePPage);
public const int CtrlKeyNPage = unchecked((int)0x226 + LeftRightUpNPagePPage);
public const int CtrlKeyPPage = unchecked((int)0x22b + LeftRightUpNPagePPage);
public const int CtrlKeyHome = unchecked((int)0x217 + Home);
public const int CtrlKeyEnd = unchecked((int)0x212 + DownEnd);
public const int ShiftCtrlKeyUp = unchecked((int)0x237 + LeftRightUpNPagePPage);
public const int ShiftCtrlKeyDown = unchecked((int)0x20e + DownEnd);
public const int ShiftCtrlKeyLeft = unchecked((int)0x222 + LeftRightUpNPagePPage);
public const int ShiftCtrlKeyRight = unchecked((int)0x231 + LeftRightUpNPagePPage);
public const int ShiftCtrlKeyNPage = unchecked((int)0x227 + LeftRightUpNPagePPage);
public const int ShiftCtrlKeyPPage = unchecked((int)0x22c + LeftRightUpNPagePPage);
public const int ShiftCtrlKeyHome = unchecked((int)0x218 + Home);
public const int ShiftCtrlKeyEnd = unchecked((int)0x213 + DownEnd);
public const int LC_ALL = 6;
static public int ColorPair(int n){