Browse Source

Merge pull request #956 from BDisp/mouse-events-fix

Fixes #933. Updated to work with libncurses 6.2
Charlie Kindel 4 years ago
parent
commit
e0761c8b01

+ 75 - 22
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -189,7 +189,6 @@ namespace Terminal.Gui {
 		Curses.Event? LastMouseButtonPressed;
 		bool IsButtonPressed;
 		bool cancelButtonClicked;
-		bool canWheeledDown;
 		bool isReportMousePosition;
 		Point point;
 
@@ -214,14 +213,14 @@ namespace Terminal.Gui {
 				cev.ButtonState == Curses.Event.Button3Pressed) && LastMouseButtonPressed == null) ||
 				IsButtonPressed && cev.ButtonState == Curses.Event.ReportMousePosition) {
 
-				mouseFlag = (MouseFlags)cev.ButtonState;
+				mouseFlag = MapCursesButton (cev.ButtonState);
 				if (cev.ButtonState != Curses.Event.ReportMousePosition)
 					LastMouseButtonPressed = cev.ButtonState;
 				IsButtonPressed = true;
 				isReportMousePosition = false;
 
 				if (cev.ButtonState == Curses.Event.ReportMousePosition) {
-					mouseFlag = (MouseFlags)LastMouseButtonPressed | MouseFlags.ReportMousePosition;
+					mouseFlag = MapCursesButton ((Curses.Event)LastMouseButtonPressed) | MouseFlags.ReportMousePosition;
 					point = new Point ();
 					//cancelButtonClicked = true;
 				} else {
@@ -258,32 +257,40 @@ namespace Terminal.Gui {
 
 				mouseFlag = ProcessButtonReleasedEvent (cev);
 				IsButtonPressed = false;
-				canWheeledDown = false;
 
-			} else if (cev.ButtonState == Curses.Event.Button4Pressed) {
+			} else if (cev.ButtonState == Curses.Event.ButtonWheeledUp) {
 
 				mouseFlag = MouseFlags.WheeledUp;
 
-			} else if (cev.ButtonState == Curses.Event.ReportMousePosition && cev.X == point.X && cev.Y == point.Y &&
-				canWheeledDown) {
+			} else if (cev.ButtonState == Curses.Event.ButtonWheeledDown) {
 
 				mouseFlag = MouseFlags.WheeledDown;
-				canWheeledDown = true;
 
-			}
-			else if (cev.ButtonState == Curses.Event.ReportMousePosition && !canWheeledDown) {
+			} else if ((cev.ButtonState & (Curses.Event.ButtonWheeledUp & Curses.Event.ButtonShift)) != 0) {
+
+				mouseFlag = MouseFlags.WheeledLeft;
+
+			} else if ((cev.ButtonState & (Curses.Event.ButtonWheeledDown & Curses.Event.ButtonShift)) != 0) {
+
+				mouseFlag = MouseFlags.WheeledRight;
+
+			} else if (cev.ButtonState == Curses.Event.ReportMousePosition) {
 
 				mouseFlag = MouseFlags.ReportMousePosition;
-				canWheeledDown = true;
 				isReportMousePosition = true;
 
 			} else {
-				mouseFlag = (MouseFlags)cev.ButtonState;
-				canWheeledDown = false;
-				if (cev.ButtonState == Curses.Event.ReportMousePosition)
-					isReportMousePosition = true;
+				mouseFlag = 0;
+				var eFlags = cev.ButtonState;
+				foreach (Enum value in Enum.GetValues (eFlags.GetType ())) {
+					if (eFlags.HasFlag (value)) {
+						mouseFlag |= MapCursesButton ((Curses.Event)value);
+					}
+				}
 			}
 
+			mouseFlag = SetControlKeyStates (cev, mouseFlag);
+
 			point = new Point () {
 				X = cev.X,
 				Y = cev.Y
@@ -292,7 +299,7 @@ namespace Terminal.Gui {
 			return new MouseEvent () {
 				X = cev.X,
 				Y = cev.Y,
-				//Flags = (MouseFlags)cev.ButtonState
+				//Flags = MapCursesButton (cev.ButtonState)
 				Flags = mouseFlag
 			};
 		}
@@ -306,17 +313,16 @@ namespace Terminal.Gui {
 				mf = GetButtonState (cev, false);
 				mouseHandler (ProcessButtonState (cev, mf));
 				if (LastMouseButtonPressed != null && LastMouseButtonPressed == cev.ButtonState) {
-					mf = (MouseFlags)cev.ButtonState;
+					mf = MapCursesButton (cev.ButtonState);
 				}
 			}
 			LastMouseButtonPressed = null;
-			canWheeledDown = false;
 			return mf;
 		}
 
 		private MouseFlags ProcessButtonReleasedEvent (Curses.MouseEvent cev)
 		{
-			var mf = (MouseFlags)cev.ButtonState;
+			var mf = MapCursesButton (cev.ButtonState);
 			if (!cancelButtonClicked && LastMouseButtonPressed == null && !isReportMousePosition) {
 				mouseHandler (ProcessButtonState (cev, mf));
 				mf = GetButtonState (cev);
@@ -324,7 +330,6 @@ namespace Terminal.Gui {
 				mf = MouseFlags.ReportMousePosition;
 			}
 			cancelButtonClicked = false;
-			canWheeledDown = false;
 			return mf;
 		}
 
@@ -379,6 +384,54 @@ namespace Terminal.Gui {
 			};
 		}
 
+		MouseFlags MapCursesButton (Curses.Event cursesButton)
+		{
+			switch (cursesButton) {
+			case Curses.Event.Button1Pressed: return MouseFlags.Button1Pressed;
+			case Curses.Event.Button1Released: return MouseFlags.Button1Released;
+			case Curses.Event.Button1Clicked: return MouseFlags.Button1Clicked;
+			case Curses.Event.Button1DoubleClicked: return MouseFlags.Button1DoubleClicked;
+			case Curses.Event.Button1TripleClicked: return MouseFlags.Button1TripleClicked;
+			case Curses.Event.Button2Pressed: return MouseFlags.Button2Pressed;
+			case Curses.Event.Button2Released: return MouseFlags.Button2Released;
+			case Curses.Event.Button2Clicked: return MouseFlags.Button2Clicked;
+			case Curses.Event.Button2DoubleClicked: return MouseFlags.Button2DoubleClicked;
+			case Curses.Event.Button2TrippleClicked: return MouseFlags.Button2TripleClicked;
+			case Curses.Event.Button3Pressed: return MouseFlags.Button3Pressed;
+			case Curses.Event.Button3Released: return MouseFlags.Button3Released;
+			case Curses.Event.Button3Clicked: return MouseFlags.Button3Clicked;
+			case Curses.Event.Button3DoubleClicked: return MouseFlags.Button3DoubleClicked;
+			case Curses.Event.Button3TripleClicked: return MouseFlags.Button3TripleClicked;
+			case Curses.Event.ButtonWheeledUp: return MouseFlags.WheeledUp;
+			case Curses.Event.ButtonWheeledDown: return MouseFlags.WheeledDown;
+			case Curses.Event.Button4Pressed: return MouseFlags.Button4Pressed;
+			case Curses.Event.Button4Released: return MouseFlags.Button4Released;
+			case Curses.Event.Button4Clicked: return MouseFlags.Button4Clicked;
+			case Curses.Event.Button4DoubleClicked: return MouseFlags.Button4DoubleClicked;
+			case Curses.Event.Button4TripleClicked: return MouseFlags.Button4TripleClicked;
+			case Curses.Event.ButtonShift: return MouseFlags.ButtonShift;
+			case Curses.Event.ButtonCtrl: return MouseFlags.ButtonCtrl;
+			case Curses.Event.ButtonAlt: return MouseFlags.ButtonAlt;
+			case Curses.Event.ReportMousePosition: return MouseFlags.ReportMousePosition;
+			case Curses.Event.AllEvents: return MouseFlags.AllEvents;
+			default: return 0;
+			}
+		}
+
+		static MouseFlags SetControlKeyStates (Curses.MouseEvent cev, MouseFlags mouseFlag)
+		{
+			if ((cev.ButtonState & Curses.Event.ButtonCtrl) != 0 && (mouseFlag & MouseFlags.ButtonCtrl) == 0)
+				mouseFlag |= MouseFlags.ButtonCtrl;
+
+			if ((cev.ButtonState & Curses.Event.ButtonShift) != 0 && (mouseFlag & MouseFlags.ButtonShift) == 0)
+				mouseFlag |= MouseFlags.ButtonShift;
+
+			if ((cev.ButtonState & Curses.Event.ButtonAlt) != 0 && (mouseFlag & MouseFlags.ButtonAlt) == 0)
+				mouseFlag |= MouseFlags.ButtonAlt;
+			return mouseFlag;
+		}
+
+
 		KeyModifiers keyModifiers;
 
 		KeyModifiers MapKeyModifiers (Key key)
@@ -414,8 +467,8 @@ namespace Terminal.Gui {
 					}
 				}
 				if (wch == Curses.KeyMouse) {
-					Curses.MouseEvent ev;
-					Curses.getmouse (out ev);
+					Curses.getmouse (out Curses.MouseEvent ev);
+					//System.Diagnostics.Debug.WriteLine ($"ButtonState: {ev.ButtonState}; ID: {ev.ID}; X: {ev.X}; Y: {ev.Y}; Z: {ev.Z}");
 					mouseHandler (ToDriverMouse (ev));
 					return;
 				}

+ 20 - 16
Terminal.Gui/ConsoleDrivers/CursesDriver/constants.cs

@@ -2,7 +2,7 @@
  * This file is autogenerated by the attrib.c program, do not edit
  */
 
-#define XTERM1006
+//#define XTERM1006
 
 using System;
 
@@ -52,31 +52,35 @@ namespace Unix.Terminal {
 		public const int COLOR_CYAN = unchecked((int)0x6);
 		public const int COLOR_WHITE = unchecked((int)0x7);
 		public const int KEY_CODE_YES = unchecked((int)0x100);
+
+		[Flags]
 		public enum Event : long {
 			Button1Pressed = unchecked((int)0x2),
 			Button1Released = unchecked((int)0x1),
 			Button1Clicked = unchecked((int)0x4),
 			Button1DoubleClicked = unchecked((int)0x8),
 			Button1TripleClicked = unchecked((int)0x10),
-			Button2Pressed = unchecked((int)0x80),
-			Button2Released = unchecked((int)0x40),
-			Button2Clicked = unchecked((int)0x100),
-			Button2DoubleClicked = unchecked((int)0x200),
-			Button2TrippleClicked = unchecked((int)0x400),
-			Button3Pressed = unchecked((int)0x2000),
-			Button3Released = unchecked((int)0x1000),
-			Button3Clicked = unchecked((int)0x4000),
-			Button3DoubleClicked = unchecked((int)0x8000),
-			Button3TripleClicked = unchecked((int)0x10000),
+			Button2Pressed = unchecked((int)0x40),
+			Button2Released = unchecked((int)0x20),
+			Button2Clicked = unchecked((int)0x80),
+			Button2DoubleClicked = unchecked((int)0x100),
+			Button2TrippleClicked = unchecked((int)0x200),
+			Button3Pressed = unchecked((int)0x800),
+			Button3Released = unchecked((int)0x400),
+			Button3Clicked = unchecked((int)0x1000),
+			Button3DoubleClicked = unchecked((int)0x2000),
+			Button3TripleClicked = unchecked((int)0x4000),
+			ButtonWheeledUp = unchecked((int)0x10000),
+			ButtonWheeledDown = unchecked((int)0x200000),
 			Button4Pressed = unchecked((int)0x80000),
 			Button4Released = unchecked((int)0x40000),
 			Button4Clicked = unchecked((int)0x100000),
-			Button4DoubleClicked = unchecked((int)0x200000),
+			Button4DoubleClicked = unchecked((int)0x20000),
 			Button4TripleClicked = unchecked((int)0x400000),
-			ButtonShift = unchecked((int)0x2000000),
-			ButtonCtrl = unchecked((int)0x1000000),
-			ButtonAlt = unchecked((int)0x4000000),
-			ReportMousePosition = unchecked((int)0x8000000),
+			ButtonShift = unchecked((int)0x4000000),
+			ButtonCtrl = unchecked((int)0x2000000),
+			ButtonAlt = unchecked((int)0x8000000),
+			ReportMousePosition = unchecked((int)0x10000000),
 			AllEvents = unchecked((int)0x7ffffff),
 		}
 #if XTERM1006

+ 12 - 0
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -933,6 +933,18 @@ namespace Terminal.Gui {
 					break;
 				}
 
+			} else if (mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseWheeled &&
+				mouseEvent.ControlKeyState == WindowsConsole.ControlKeyState.ShiftPressed) {
+				switch (mouseEvent.ButtonState) {
+				case WindowsConsole.ButtonState.WheeledUp:
+					mouseFlag = MouseFlags.WheeledLeft;
+					break;
+
+				case WindowsConsole.ButtonState.WheeledDown:
+					mouseFlag = MouseFlags.WheeledRight;
+					break;
+				}
+
 			} else if (mouseEvent.EventFlags == WindowsConsole.EventFlags.MouseMoved) {
 				if (mouseEvent.MousePosition.X != point.X || mouseEvent.MousePosition.Y != point.Y) {
 					mouseFlag = MouseFlags.ReportMousePosition;

+ 8 - 0
Terminal.Gui/Core/Event.cs

@@ -542,6 +542,14 @@ namespace Terminal.Gui {
 		/// </summary>
 		WheeledDown = unchecked((int)0x20000000),
 		/// <summary>
+		/// Vertical button wheeled up while pressing ButtonShift.
+		/// </summary>
+		WheeledLeft = ButtonShift | WheeledUp,
+		/// <summary>
+		/// Vertical button wheeled down while pressing ButtonShift.
+		/// </summary>
+		WheeledRight = ButtonShift | WheeledDown,
+		/// <summary>
 		/// Mask that captures all the events.
 		/// </summary>
 		AllEvents = unchecked((int)0x7ffffff),

+ 12 - 6
Terminal.Gui/Views/ScrollView.cs

@@ -768,19 +768,25 @@ namespace Terminal.Gui {
 		public override bool MouseEvent (MouseEvent me)
 		{
 			if (me.Flags != MouseFlags.WheeledDown && me.Flags != MouseFlags.WheeledUp &&
+				me.Flags != MouseFlags.WheeledRight && me.Flags != MouseFlags.WheeledLeft &&
 				me.Flags != MouseFlags.Button1Pressed && me.Flags != MouseFlags.Button1Clicked &&
-				!me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition))
+				!me.Flags.HasFlag (MouseFlags.Button1Pressed | MouseFlags.ReportMousePosition)) {
 				return false;
+			}
 
-			if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator)
+			if (me.Flags == MouseFlags.WheeledDown && ShowVerticalScrollIndicator) {
 				ScrollDown (1);
-			else if (me.Flags == MouseFlags.WheeledUp && ShowVerticalScrollIndicator)
+			} else if (me.Flags == MouseFlags.WheeledUp && ShowVerticalScrollIndicator) {
 				ScrollUp (1);
-			else if (me.X == vertical.Frame.X && ShowVerticalScrollIndicator)
+			} else if (me.Flags == MouseFlags.WheeledRight && showHorizontalScrollIndicator) {
+				ScrollRight (1);
+			} else if (me.Flags == MouseFlags.WheeledLeft && ShowVerticalScrollIndicator) {
+				ScrollLeft (1);
+			} else if (me.X == vertical.Frame.X && ShowVerticalScrollIndicator) {
 				vertical.MouseEvent (me);
-			else if (me.Y == horizontal.Frame.Y && ShowHorizontalScrollIndicator)
+			} else if (me.Y == horizontal.Frame.Y && ShowHorizontalScrollIndicator) {
 				horizontal.MouseEvent (me);
-			else if (IsOverridden (me.View)) {
+			} else if (IsOverridden (me.View)) {
 				Application.UngrabMouse ();
 				return false;
 			}