Browse Source

Merge branch 'master' of tig:migueldeicaza/gui.cs

Charlie Kindel 5 years ago
parent
commit
aa63d4e2f5

+ 611 - 0
Example/demo.cs.orig

@@ -0,0 +1,611 @@
+using Terminal.Gui;
+using System;
+using Mono.Terminal;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Reflection;
+using NStack;
+using System.Text;
+
+static class Demo {
+	//class Box10x : View, IScrollView {
+	class Box10x : View {
+		int w = 40;
+		int h = 50;
+
+		public bool WantCursorPosition { get; set; } = false;
+
+		public Box10x (int x, int y) : base (new Rect (x, y, 20, 10))
+		{
+		}
+
+		public Size GetContentSize ()
+		{
+			return new Size (w, h);
+		}
+
+		public void SetCursorPosition (Point pos)
+		{
+			throw new NotImplementedException ();
+		}
+
+		public override void Redraw (Rect region)
+		{
+			//Point pos = new Point (region.X, region.Y);
+			Driver.SetAttribute (ColorScheme.Focus);
+
+			for (int y = 0; y < h; y++) {
+				Move (0, y);
+				Driver.AddStr (y.ToString ());
+				for (int x = 0; x < w - y.ToString ().Length; x++) {
+					//Driver.AddRune ((Rune)('0' + (x + y) % 10));
+					if (y.ToString ().Length < w)
+						Driver.AddStr (" ");
+				}
+			}
+			//Move (pos.X, pos.Y);
+		}
+	}
+
+	class Filler : View {
+		public Filler (Rect rect) : base (rect)
+		{
+		}
+
+		public override void Redraw (Rect region)
+		{
+			Driver.SetAttribute (ColorScheme.Focus);
+			var f = Frame;
+
+			for (int y = 0; y < f.Width; y++) {
+				Move (0, y);
+				for (int x = 0; x < f.Height; x++) {
+					Rune r;
+					switch (x % 3) {
+					case 0:
+						Driver.AddRune (y.ToString ().ToCharArray (0, 1) [0]);
+						if (y > 9)
+							Driver.AddRune (y.ToString ().ToCharArray (1, 1) [0]);
+						r = '.';
+						break;
+					case 1:
+						r = 'o';
+						break;
+					default:
+						r = 'O';
+						break;
+					}
+					Driver.AddRune (r);
+				}
+			}
+		}
+	}
+
+	static void ShowTextAlignments ()
+	{
+<<<<<<< HEAD
+		var container = new Window ($"Show Text Alignments") {
+			X = 0,
+			Y = 0,
+			Width = Dim.Fill (),
+			Height = Dim.Fill ()
+		};
+		container.OnKeyUp += (KeyEvent ke) => {
+			if (ke.Key == Key.Esc)
+				container.Running = false;
+		};
+=======
+		var container = new Dialog (
+			"Text Alignments", 70, 20,
+			new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } },
+			new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } });
+
+>>>>>>> cb40c5c2491a559658481d20dd4b6a3343c0183f
+
+		int i = 0;
+		string txt = "Hello world, how are you doing today?";
+		container.Add (
+<<<<<<< HEAD
+				new Label ($"{i+1}-{txt}") { TextAlignment = TextAlignment.Left,      Y = 3, Width = Dim.Fill () },
+				new Label ($"{i+2}-{txt}") { TextAlignment = TextAlignment.Right,     Y = 5, Width = Dim.Fill () },
+				new Label ($"{i+3}-{txt}") { TextAlignment = TextAlignment.Centered,  Y = 7, Width = Dim.Fill () },
+				new Label ($"{i+4}-{txt}") { TextAlignment = TextAlignment.Justified, Y = 9, Width = Dim.Fill () }
+=======
+				new Label (new Rect (0, 1, 50, 3), $"{i+1}-{txt}") { TextAlignment = TextAlignment.Left },
+				new Label (new Rect (0, 3, 50, 3), $"{i+2}-{txt}") { TextAlignment = TextAlignment.Right },
+				new Label (new Rect (0, 5, 50, 3), $"{i+3}-{txt}") { TextAlignment = TextAlignment.Centered },
+				new Label (new Rect (0, 7, 50, 3), $"{i+4}-{txt}") { TextAlignment = TextAlignment.Justified }
+>>>>>>> cb40c5c2491a559658481d20dd4b6a3343c0183f
+			);
+
+		Application.Run (container);
+	}
+
+	static void ShowEntries (View container)
+	{
+		var scrollView = new ScrollView (new Rect (50, 10, 20, 8)) {
+			ContentSize = new Size (20, 50),
+			//ContentOffset = new Point (0, 0),
+			ShowVerticalScrollIndicator = true,
+			ShowHorizontalScrollIndicator = true
+		};
+#if false
+		scrollView.Add (new Box10x (0, 0));
+#else
+		scrollView.Add (new Filler (new Rect (0, 0, 40, 40)));
+#endif
+
+		// This is just to debug the visuals of the scrollview when small
+		var scrollView2 = new ScrollView (new Rect (72, 10, 3, 3)) {
+			ContentSize = new Size (100, 100),
+			ShowVerticalScrollIndicator = true,
+			ShowHorizontalScrollIndicator = true
+		};
+		scrollView2.Add (new Box10x (0, 0));
+		var progress = new ProgressBar (new Rect (68, 1, 10, 1));
+		bool timer (MainLoop caller)
+		{
+			progress.Pulse ();
+			return true;
+		}
+
+		Application.MainLoop.AddTimeout (TimeSpan.FromMilliseconds (300), timer);
+
+
+		// A little convoluted, this is because I am using this to test the
+		// layout based on referencing elements of another view:
+
+		var login = new Label ("Login: ") { X = 3, Y = 6 };
+		var password = new Label ("Password: ") {
+			X = Pos.Left (login),
+			Y = Pos.Bottom (login) + 1
+		};
+		var loginText = new TextField ("") {
+			X = Pos.Right (password),
+			Y = Pos.Top (login),
+			Width = 40
+		};
+
+		var passText = new TextField ("") {
+			Secret = true,
+			X = Pos.Left (loginText),
+			Y = Pos.Top (password),
+			Width = Dim.Width (loginText)
+		};
+
+		var tf = new Button (3, 19, "Ok");
+		// Add some content
+		container.Add (
+			login,
+			loginText,
+			password,
+			passText,
+			new FrameView (new Rect (3, 10, 25, 6), "Options"){
+				new CheckBox (1, 0, "Remember me"),
+				new RadioGroup (1, 2, new [] { "_Personal", "_Company" }),
+			},
+			new ListView (new Rect (59, 6, 16, 4), new string [] {
+				"First row",
+				"<>",
+				"This is a very long row that should overflow what is shown",
+				"4th",
+				"There is an empty slot on the second row",
+				"Whoa",
+				"This is so cool"
+			}),
+			scrollView,
+			scrollView2,
+			tf,
+			new Button (10, 19, "Cancel"),
+			new TimeField (3, 20, DateTime.Now),
+			new TimeField (23, 20, DateTime.Now, true),
+			new DateField (3, 22, DateTime.Now),
+			new DateField (23, 22, DateTime.Now, true),
+			progress,
+			new Label (3, 24, "Press F9 (on Unix, ESC+9 is an alias) to activate the menubar"),
+			menuKeysStyle,
+			menuAutoMouseNav
+
+		);
+		container.SendSubviewToBack (tf);
+	}
+
+	public static Label ml2;
+
+	static void NewFile ()
+	{
+		var d = new Dialog (
+			"New File", 50, 20,
+			new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } },
+			new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } });
+		ml2 = new Label (1, 1, "Mouse Debug Line");
+		d.Add (ml2);
+		Application.Run (d);
+	}
+
+	//
+	// Creates a nested editor
+	static void Editor (Toplevel top)
+	{
+		var tframe = top.Frame;
+		var ntop = new Toplevel (tframe);
+		var menu = new MenuBar (new MenuBarItem [] {
+			new MenuBarItem ("_File", new MenuItem [] {
+				new MenuItem ("_Close", "", () => {Application.RequestStop ();}),
+			}),
+			new MenuBarItem ("_Edit", new MenuItem [] {
+				new MenuItem ("_Copy", "", null),
+				new MenuItem ("C_ut", "", null),
+				new MenuItem ("_Paste", "", null)
+			}),
+		});
+		ntop.Add (menu);
+
+		string fname = null;
+		foreach (var s in new [] { "/etc/passwd", "c:\\windows\\win.ini" })
+			if (System.IO.File.Exists (s)) {
+				fname = s;
+				break;
+			}
+
+		var win = new Window (fname ?? "Untitled") {
+			X = 0,
+			Y = 1,
+			Width = Dim.Fill (),
+			Height = Dim.Fill ()
+		};
+		ntop.Add (win);
+
+		var text = new TextView (new Rect (0, 0, tframe.Width - 2, tframe.Height - 3));
+
+		if (fname != null)
+			text.Text = System.IO.File.ReadAllText (fname);
+		win.Add (text);
+
+		Application.Run (ntop);
+	}
+
+	static bool Quit ()
+	{
+		var n = MessageBox.Query (50, 7, "Quit Demo", "Are you sure you want to quit this demo?", "Yes", "No");
+		return n == 0;
+	}
+
+	static void Close ()
+	{
+		MessageBox.ErrorQuery (50, 7, "Error", "There is nothing to close", "Ok");
+	}
+
+	// Watch what happens when I try to introduce a newline after the first open brace
+	// it introduces a new brace instead, and does not indent.  Then watch me fight
+	// the editor as more oddities happen.
+
+	public static void Open ()
+	{
+		var d = new OpenDialog ("Open", "Open a file") { AllowsMultipleSelection = true };
+		Application.Run (d);
+
+		if (!d.Canceled)
+			MessageBox.Query (50, 7, "Selected File", string.Join (", ", d.FilePaths), "Ok");
+	}
+
+	public static void ShowHex (Toplevel top)
+	{
+		var tframe = top.Frame;
+		var ntop = new Toplevel (tframe);
+		var menu = new MenuBar (new MenuBarItem [] {
+			new MenuBarItem ("_File", new MenuItem [] {
+				new MenuItem ("_Close", "", () => {Application.RequestStop ();}),
+			}),
+		});
+		ntop.Add (menu);
+
+		var win = new Window ("/etc/passwd") {
+			X = 0,
+			Y = 1,
+			Width = Dim.Fill (),
+			Height = Dim.Fill ()
+		};
+		ntop.Add (win);
+
+		var source = System.IO.File.OpenRead ("/etc/passwd");
+		var hex = new HexView (source) {
+			X = 0,
+			Y = 0,
+			Width = Dim.Fill (),
+			Height = Dim.Fill ()
+		};
+		win.Add (hex);
+		Application.Run (ntop);
+
+	}
+
+	public class MenuItemDetails : MenuItem {
+		ustring title;
+		string help;
+		Action action;
+
+		public MenuItemDetails (ustring title, string help, Action action) : base (title, help, action)
+		{
+			this.title = title;
+			this.help = help;
+			this.action = action;
+		}
+
+		public static MenuItemDetails Instance (MenuItem mi)
+		{
+			return (MenuItemDetails)mi.GetMenuItem ();
+		}
+	}
+
+	public delegate MenuItem MenuItemDelegate (MenuItemDetails menuItem);
+
+	public static void ShowMenuItem (MenuItem mi)
+	{
+		BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
+		MethodInfo minfo = typeof (MenuItemDetails).GetMethod ("Instance", flags);
+		MenuItemDelegate mid = (MenuItemDelegate)Delegate.CreateDelegate (typeof (MenuItemDelegate), minfo);
+		MessageBox.Query (70, 7, mi.Title.ToString (),
+			$"{mi.Title.ToString ()} selected. Is from submenu: {mi.GetMenuBarItem ()}", "Ok");
+	}
+
+	static void MenuKeysStyle_Toggled (object sender, EventArgs e)
+	{
+		menu.UseKeysUpDownAsKeysLeftRight = menuKeysStyle.Checked;
+	}
+
+	static void MenuAutoMouseNav_Toggled (object sender, EventArgs e)
+	{
+		menu.WantMousePositionReports = menuAutoMouseNav.Checked;
+	}
+
+
+	static void Copy ()
+	{
+		TextField textField = menu.LastFocused as TextField;
+		if (textField != null && textField.SelectedLength != 0) {
+			textField.Copy ();
+		}
+	}
+
+	static void Cut ()
+	{
+		TextField textField = menu.LastFocused as TextField;
+		if (textField != null && textField.SelectedLength != 0) {
+			textField.Cut ();
+		}
+	}
+
+	static void Paste ()
+	{
+		TextField textField = menu.LastFocused as TextField;
+		if (textField != null) {
+			textField.Paste ();
+		}
+	}
+
+	static void Help ()
+	{
+		MessageBox.Query (50, 7, "Help", "This is a small help\nBe kind.", "Ok");
+	}
+
+	#region Selection Demo
+
+	static void ListSelectionDemo (bool multiple)
+	{
+		var d = new Dialog ("Selection Demo", 60, 20,
+			new Button ("Ok", is_default: true) { Clicked = () => { Application.RequestStop (); } },
+			new Button ("Cancel") { Clicked = () => { Application.RequestStop (); } });
+
+		var animals = new List<string> () { "Alpaca", "Llama", "Lion", "Shark", "Goat" };
+		var msg = new Label ("Use space bar or control-t to toggle selection") {
+			X = 1,
+			Y = 1,
+			Width = Dim.Fill () - 1,
+			Height = 1
+		};
+
+		var list = new ListView (animals) {
+			X = 1,
+			Y = 3,
+			Width = Dim.Fill () - 4,
+			Height = Dim.Fill () - 4,
+			AllowsMarking = true,
+			AllowsMultipleSelection = multiple
+		};
+		d.Add (msg, list);
+		Application.Run (d);
+
+		var result = "";
+		for (int i = 0; i < animals.Count; i++) {
+			if (list.Source.IsMarked (i)) {
+				result += animals [i] + " ";
+			}
+		}
+		MessageBox.Query (60, 10, "Selected Animals", result == "" ? "No animals selected" : result, "Ok");
+	}
+	#endregion
+
+
+	#region OnKeyDown / OnKeyUp Demo
+	private static void OnKeyDownUpDemo ()
+	{
+		var container = new Dialog (
+			"OnKeyDown & OnKeyUp demo", 80, 20,
+			new Button ("Close") { Clicked = () => { Application.RequestStop (); } }) {
+			Width = Dim.Fill (),
+			Height = Dim.Fill (),
+		};
+
+		var list = new List<string> ();
+		var listView = new ListView (list) {
+			X = 0,
+			Y = 0,
+			Width = Dim.Fill () - 1,
+			Height = Dim.Fill () - 2,
+		};
+		listView.ColorScheme = Colors.TopLevel;
+		container.Add (listView);
+
+		void KeyUpDown (KeyEvent keyEvent, string updown)
+		{
+			if ((keyEvent.Key & Key.CtrlMask) != 0) {
+				list.Add ($"Key{updown,-4}: Ctrl ");
+			} else if ((keyEvent.Key & Key.AltMask) != 0) {
+				list.Add ($"Key{updown,-4}: Alt ");
+			} else {
+				list.Add ($"Key{updown,-4}: {(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}");
+			}
+			listView.MoveDown ();
+		}
+
+		container.OnKeyDown += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Down");
+		container.OnKeyUp += (KeyEvent keyEvent) => KeyUpDown (keyEvent, "Up");
+		Application.Run (container);
+	}
+	#endregion
+
+	public static Label ml;
+	public static MenuBar menu;
+	public static CheckBox menuKeysStyle;
+	public static CheckBox menuAutoMouseNav;
+	static void Main ()
+	{
+		if (Debugger.IsAttached)
+			CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
+
+		//Application.UseSystemConsole = true;
+
+		Application.Init ();
+
+		var top = Application.Top;
+
+		//Open ();
+#if true
+		int margin = 3;
+		var win = new Window ("Hello") {
+			X = 1,
+			Y = 1,
+
+			Width = Dim.Fill () - margin,
+			Height = Dim.Fill () - margin
+		};
+#else
+		var tframe = top.Frame;
+
+		var win = new Window (new Rect (0, 1, tframe.Width, tframe.Height - 1), "Hello");
+#endif
+		MenuItemDetails [] menuItems = {
+			new MenuItemDetails ("F_ind", "", null),
+			new MenuItemDetails ("_Replace", "", null),
+			new MenuItemDetails ("_Item1", "", null),
+			new MenuItemDetails ("_Not From Sub Menu", "", null)
+		};
+
+		menuItems [0].Action = () => ShowMenuItem (menuItems [0]);
+		menuItems [1].Action = () => ShowMenuItem (menuItems [1]);
+		menuItems [2].Action = () => ShowMenuItem (menuItems [2]);
+		menuItems [3].Action = () => ShowMenuItem (menuItems [3]);
+
+		menu = new MenuBar (new MenuBarItem [] {
+			new MenuBarItem ("_File", new MenuItem [] {
+				new MenuItem ("Text _Editor Demo", "", () => { Editor (top); }),
+				new MenuItem ("_New", "Creates new file", NewFile),
+				new MenuItem ("_Open", "", Open),
+				new MenuItem ("_Hex", "", () => ShowHex (top)),
+				new MenuItem ("_Close", "", () => Close ()),
+				new MenuItem ("_Disabled", "", () => { }, () => false),
+				null,
+				new MenuItem ("_Quit", "", () => { if (Quit ()) top.Running = false; })
+			}),
+			new MenuBarItem ("_Edit", new MenuItem [] {
+				new MenuItem ("_Copy", "", Copy),
+				new MenuItem ("C_ut", "", Cut),
+				new MenuItem ("_Paste", "", Paste),
+				new MenuItem ("_Find and Replace",
+					new MenuBarItem (new MenuItem[] {menuItems [0], menuItems [1] })),
+				menuItems[3]
+			}),
+			new MenuBarItem ("_List Demos", new MenuItem [] {
+				new MenuItem ("Select _Multiple Items", "", () => ListSelectionDemo (true)),
+				new MenuItem ("Select _Single Item", "", () => ListSelectionDemo (false)),
+			}),
+			new MenuBarItem ("A_ssorted", new MenuItem [] {
+				new MenuItem ("_Show text alignments", "", () => ShowTextAlignments ()),
+				new MenuItem ("_OnKeyDown/Up", "", () => OnKeyDownUpDemo ())
+			}),
+			new MenuBarItem ("_Test Menu and SubMenus", new MenuItem [] {
+				new MenuItem ("SubMenu1Item_1",
+					new MenuBarItem (new MenuItem[] {
+						new MenuItem ("SubMenu2Item_1",
+							new MenuBarItem (new MenuItem [] {
+								new MenuItem ("SubMenu3Item_1",
+									new MenuBarItem (new MenuItem [] { menuItems [2] })
+								)
+							})
+						)
+					})
+				)
+			}),
+			new MenuBarItem ("_About...", "Demonstrates top-level menu item", () =>  MessageBox.ErrorQuery (50, 7, "About Demo", "This is a demo app for gui.cs", "Ok")),
+		});
+
+		menuKeysStyle = new CheckBox (3, 25, "UseKeysUpDownAsKeysLeftRight", true);
+		menuKeysStyle.Toggled += MenuKeysStyle_Toggled;
+		menuAutoMouseNav = new CheckBox (40, 25, "UseMenuAutoNavigation", true);
+		menuAutoMouseNav.Toggled += MenuAutoMouseNav_Toggled;
+
+		ShowEntries (win);
+
+		int count = 0;
+		ml = new Label (new Rect (3, 17, 47, 1), "Mouse: ");
+		Application.RootMouseEvent += delegate (MouseEvent me) {
+			ml.TextColor = Colors.TopLevel.Normal;
+			ml.Text = $"Mouse: ({me.X},{me.Y}) - {me.Flags} {count++}";
+		};
+
+		var test = new Label (3, 18, "Se iniciará el análisis");
+		win.Add (test);
+		win.Add (ml);
+
+		var drag = new Label ("Drag: ") { X = 70, Y = 24 };
+		var dragText = new TextField ("") {
+			X = Pos.Right (drag),
+			Y = Pos.Top (drag),
+			Width = 40
+		};
+
+		var statusBar = new StatusBar (new StatusItem [] {
+			new StatusItem(Key.F1, "~F1~ Help", () => Help()),
+			new StatusItem(Key.F2, "~F2~ Load", null),
+			new StatusItem(Key.F3, "~F3~ Save", null),
+			new StatusItem(Key.ControlX, "~^X~ Quit", () => { if (Quit ()) top.Running = false; }),
+		}) {
+			Parent = null,
+		};
+
+		win.Add (drag, dragText);
+#if true
+		// FIXED: This currently causes a stack overflow, because it is referencing a window that has not had its size allocated yet
+
+		var bottom = new Label ("This should go on the bottom of the same top-level!");
+		win.Add (bottom);
+		var bottom2 = new Label ("This should go on the bottom of another top-level!");
+		top.Add (bottom2);
+
+		Application.OnLoad = () => {
+			bottom.X = win.X;
+			bottom.Y = Pos.Bottom (win) - Pos.Top (win) - margin;
+			bottom2.X = Pos.Left (win);
+			bottom2.Y = Pos.Bottom (win);
+		};
+#endif
+
+
+		top.Add (win);
+		//top.Add (menu);
+		top.Add (menu, statusBar);
+		Application.Run ();
+	}
+}

+ 190 - 11
Terminal.Gui/Drivers/CursesDriver.cs

@@ -7,6 +7,7 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
+using System.Threading.Tasks;
 using Mono.Terminal;
 using Mono.Terminal;
 using NStack;
 using NStack;
 using Unix.Terminal;
 using Unix.Terminal;
@@ -183,12 +184,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 () {
 			return new MouseEvent () {
 				X = cev.X,
 				X = cev.X,
 				Y = cev.Y,
 				Y = cev.Y,
-				Flags = (MouseFlags)cev.ButtonState
+				Flags = mf
 			};
 			};
 		}
 		}
 
 
@@ -252,10 +426,15 @@ namespace Terminal.Gui {
 			keyUpHandler (new KeyEvent ((Key)wch));
 			keyUpHandler (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)
 		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
 			// 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, keyUpHandler, mouseHandler);
 				ProcessInput (keyHandler, keyUpHandler, mouseHandler);
@@ -425,21 +604,21 @@ namespace Terminal.Gui {
 			Console.Out.Flush ();
 			Console.Out.Flush ();
 		}
 		}
 
 
-		int lastMouseInterval;
-		bool mouseGrabbed;
+		//int lastMouseInterval;
+		//bool mouseGrabbed;
 
 
 		public override void UncookMouse ()
 		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 ()
 		public override void CookMouse ()
 		{
 		{
-			mouseGrabbed = false;
-			Curses.mouseinterval (lastMouseInterval);
+			//mouseGrabbed = false;
+			//Curses.mouseinterval (lastMouseInterval);
 		}
 		}
 	}
 	}
 
 

+ 2 - 0
Terminal.Gui/Drivers/WindowsDriver.cs

@@ -677,6 +677,8 @@ namespace Terminal.Gui {
 						keyHandler (new KeyEvent (map));
 						keyHandler (new KeyEvent (map));
 						keyDownHandler (new KeyEvent (map));
 						keyDownHandler (new KeyEvent (map));
 					} else {
 					} else {
+						// Key Up - Fire KeyDown Event and KeyStroke (ProcessKey) Event
+						keyHandler (new KeyEvent (map));
 						keyUpHandler (new KeyEvent (map));
 						keyUpHandler (new KeyEvent (map));
 					}
 					}
 				}
 				}

+ 35 - 24
Terminal.Gui/MonoCurses/constants.cs

@@ -2,6 +2,8 @@
  * This file is autogenerated by the attrib.c program, do not edit
  * This file is autogenerated by the attrib.c program, do not edit
  */
  */
 
 
+#define XTERM1006
+
 using System;
 using System;
 
 
 namespace Unix.Terminal {
 namespace Unix.Terminal {
@@ -77,6 +79,15 @@ namespace Unix.Terminal {
 			ReportMousePosition = unchecked((int)0x8000000),
 			ReportMousePosition = unchecked((int)0x8000000),
 			AllEvents = unchecked((int)0x7ffffff),
 			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 ERR = unchecked((int)0xffffffff);
 		public const int KeyBackspace = unchecked((int)0x107);
 		public const int KeyBackspace = unchecked((int)0x107);
 		public const int KeyUp = unchecked((int)0x103);
 		public const int KeyUp = unchecked((int)0x103);
@@ -110,30 +121,30 @@ namespace Unix.Terminal {
 		public const int ShiftKeyPPage = unchecked((int)0x18e);
 		public const int ShiftKeyPPage = unchecked((int)0x18e);
 		public const int ShiftKeyHome = unchecked((int)0x187);
 		public const int ShiftKeyHome = unchecked((int)0x187);
 		public const int ShiftKeyEnd = unchecked((int)0x182);
 		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;
 		public const int LC_ALL = 6;
 		static public int ColorPair(int n){
 		static public int ColorPair(int n){

+ 1 - 0
Terminal.Gui/Views/Menu.cs

@@ -562,6 +562,7 @@ namespace Terminal.Gui {
 		}
 		}
 
 
 		bool openedByAltKey;
 		bool openedByAltKey;
+
 		///<inheritdoc cref="OnKeyDown"/>
 		///<inheritdoc cref="OnKeyDown"/>
 		public override bool OnKeyDown (KeyEvent keyEvent)
 		public override bool OnKeyDown (KeyEvent keyEvent)
 		{
 		{

+ 1 - 0
UICatalog/Program.cs

@@ -148,6 +148,7 @@ namespace UICatalog {
 			}
 			}
 
 
 			_top = Application.Top;
 			_top = Application.Top;
+
 			_top.KeyUp += KeyUpHandler;
 			_top.KeyUp += KeyUpHandler;
 			_top.Add (_menu);
 			_top.Add (_menu);
 			_top.Add (_leftPane);
 			_top.Add (_leftPane);

+ 1 - 1
UICatalog/Scenarios/Keys.cs

@@ -43,8 +43,8 @@ namespace UICatalog {
 			public override bool ProcessColdKey (KeyEvent keyEvent)
 			public override bool ProcessColdKey (KeyEvent keyEvent)
 			{
 			{
 				_processColdKeyList.Add (keyEvent.ToString ());
 				_processColdKeyList.Add (keyEvent.ToString ());
-				return base.ProcessColdKey (keyEvent);
 
 
+				return base.ProcessColdKey (keyEvent);
 			}
 			}
 		}
 		}