Forráskód Böngészése

Merge pull request #584 from BDisp/keys-modifiers

Added class KeyModifiers which improvements better control over the combinations keys.
Charlie Kindel 5 éve
szülő
commit
a33fd89a9c

+ 2 - 1
Example/demo.cs

@@ -469,7 +469,8 @@ static class Demo {
 				if ((keyEvent.Key & Key.AltMask) != 0)
 					msg += "Alt ";
 				msg += $"{(((uint)keyEvent.KeyValue & (uint)Key.CharMask) > 26 ? $"{(char)keyEvent.KeyValue}" : $"{keyEvent.Key}")}";
-				list.Add (msg);
+				//list.Add (msg);
+				list.Add (keyEvent.ToString ());
 
 				break;
 

+ 61 - 26
Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs

@@ -379,12 +379,33 @@ namespace Terminal.Gui {
 			};
 		}
 
+		KeyModifiers keyModifiers;
+
+		KeyModifiers MapKeyModifiers (Key key)
+		{
+			if (keyModifiers == null)
+				keyModifiers = new KeyModifiers ();
+
+			if (!keyModifiers.Shift && key.HasFlag (Key.ShiftMask))
+				keyModifiers.Shift = true;
+			if (!keyModifiers.Alt && key.HasFlag (Key.AltMask))
+				keyModifiers.Alt = true;
+			if (!keyModifiers.Ctrl && key.HasFlag (Key.CtrlMask))
+				keyModifiers.Ctrl = true;
+
+			return keyModifiers;
+		}
+
 		void ProcessInput (Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
 		{
 			int wch;
 			var code = Curses.get_wch (out wch);
 			if (code == Curses.ERR)
 				return;
+
+			keyModifiers = new KeyModifiers ();
+			Key k;
+
 			if (code == Curses.KEY_CODE_YES) {
 				if (wch == Curses.KeyResize) {
 					if (Curses.CheckWinChange ()) {
@@ -398,8 +419,8 @@ namespace Terminal.Gui {
 					mouseHandler (ToDriverMouse (ev));
 					return;
 				}
-				keyHandler (new KeyEvent (MapCursesKey (wch)));
-				keyUpHandler (new KeyEvent (MapCursesKey (wch)));
+				keyHandler (new KeyEvent (MapCursesKey (wch), keyModifiers));
+				keyUpHandler (new KeyEvent (MapCursesKey (wch), keyModifiers));
 				return;
 			}
 
@@ -408,43 +429,57 @@ namespace Terminal.Gui {
 				Curses.timeout (200);
 
 				code = Curses.get_wch (out int wch2);
-				if (code == Curses.KEY_CODE_YES)
-					keyHandler (new KeyEvent (Key.AltMask | MapCursesKey (wch)));
+
+				if (code == Curses.KEY_CODE_YES) {
+					k = Key.AltMask | MapCursesKey (wch);
+					keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
+				}
 				if (code == 0) {
 					KeyEvent key;
 
 					// The ESC-number handling, debatable.
 					// Simulates the AltMask itself by pressing Alt + Space.
-					if (wch2 == (int)Key.Space)
-						key = new KeyEvent (Key.AltMask);
-					else if (wch2 - (int)Key.Space >= 'A' && wch2 - (int)Key.Space <= 'Z')
-						key = new KeyEvent ((Key)((uint)Key.AltMask + (wch2 - (int)Key.Space)));
-					else if (wch2 >= '1' && wch <= '9')
-						key = new KeyEvent ((Key)((int)Key.F1 + (wch2 - '0' - 1)));
-					else if (wch2 == '0')
-						key = new KeyEvent (Key.F10);
-					else if (wch2 == 27)
-						key = new KeyEvent ((Key)wch2);
-					else
-						key = new KeyEvent (Key.AltMask | (Key)wch2);
+					if (wch2 == (int)Key.Space) {
+						k = Key.AltMask;
+						key = new KeyEvent (k, MapKeyModifiers (k));
+					} else if (wch2 - (int)Key.Space >= 'A' && wch2 - (int)Key.Space <= 'Z') {
+						k = (Key)((uint)Key.AltMask + (wch2 - (int)Key.Space));
+						key = new KeyEvent (k, MapKeyModifiers (k));
+					} else if (wch2 >= '1' && wch <= '9') {
+						k = (Key)((int)Key.F1 + (wch2 - '0' - 1));
+						key = new KeyEvent (k, MapKeyModifiers (k));
+					} else if (wch2 == '0') {
+						k = Key.F10;
+						key = new KeyEvent (k, MapKeyModifiers (k));
+					} else if (wch2 == 27) {
+						k = (Key)wch2;
+						key = new KeyEvent (k, MapKeyModifiers (k));
+					} else {
+						k = Key.AltMask | (Key)wch2;
+						key = new KeyEvent (k, MapKeyModifiers (k));
+					}
 					keyHandler (key);
 				} else {
-					keyHandler (new KeyEvent (Key.Esc));
+					k = Key.Esc;
+					keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
 				}
 			} else if (wch == Curses.KeyTab) {
-				keyDownHandler (new KeyEvent (MapCursesKey (wch)));
-				keyHandler (new KeyEvent (MapCursesKey (wch)));
+				k = MapCursesKey (wch);
+				keyDownHandler (new KeyEvent (k, MapKeyModifiers (k)));
+				keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
 			} else {
-				keyDownHandler (new KeyEvent ((Key)wch));
-				keyHandler (new KeyEvent ((Key)wch));
+				k = (Key)wch;
+				keyDownHandler (new KeyEvent (k, MapKeyModifiers (k)));
+				keyHandler (new KeyEvent (k, MapKeyModifiers (k)));
 			}
 			// Cause OnKeyUp and OnKeyPressed. Note that the special handling for ESC above 
 			// will not impact KeyUp.
-			if (wch == Curses.KeyTab) {
-				keyUpHandler (new KeyEvent (MapCursesKey (wch)));
-			} else {
-				keyUpHandler (new KeyEvent ((Key)wch));
-			}
+			// This is causing ESC firing even if another keystroke was handled.
+			//if (wch == Curses.KeyTab) {
+			//	keyUpHandler (new KeyEvent (MapCursesKey (wch), keyModifiers));
+			//} else {
+			//	keyUpHandler (new KeyEvent ((Key)wch, keyModifiers));
+			//}
 		}
 
 		Action<MouseEvent> mouseHandler;

+ 4 - 2
Terminal.Gui/ConsoleDrivers/NetDriver.cs

@@ -335,6 +335,8 @@ namespace Terminal.Gui {
 			return (Key)(0xffffffff);
 		}
 
+		KeyModifiers keyModifiers = new KeyModifiers ();
+
 		public override void PrepareToRun (MainLoop mainLoop, Action<KeyEvent> keyHandler, Action<KeyEvent> keyDownHandler, Action<KeyEvent> keyUpHandler, Action<MouseEvent> mouseHandler)
 		{
 			// Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
@@ -342,8 +344,8 @@ namespace Terminal.Gui {
 				var map = MapKey (consoleKey);
 				if (map == (Key)0xffffffff)
 					return;
-				keyHandler (new KeyEvent (map));
-				keyUpHandler (new KeyEvent (map));
+				keyHandler (new KeyEvent (map, keyModifiers));
+				keyUpHandler (new KeyEvent (map, keyModifiers));
 			};
 		}
 

+ 31 - 13
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -646,17 +646,17 @@ namespace Terminal.Gui {
 						WindowsConsole.ControlKeyState.LeftControlPressed |
 						WindowsConsole.ControlKeyState.EnhancedKey:
 					case WindowsConsole.ControlKeyState.EnhancedKey:
-						key = new KeyEvent (Key.CtrlMask | Key.AltMask);
+						key = new KeyEvent (Key.CtrlMask | Key.AltMask, keyModifiers);
 						break;
 					case WindowsConsole.ControlKeyState.LeftAltPressed:
-						key = new KeyEvent (Key.AltMask);
+						key = new KeyEvent (Key.AltMask, keyModifiers);
 						break;
 					case WindowsConsole.ControlKeyState.RightControlPressed:
 					case WindowsConsole.ControlKeyState.LeftControlPressed:
-						key = new KeyEvent (Key.CtrlMask);
+						key = new KeyEvent (Key.CtrlMask, keyModifiers);
 						break;
 					case WindowsConsole.ControlKeyState.ShiftPressed:
-						key = new KeyEvent (Key.ShiftMask);
+						key = new KeyEvent (Key.ShiftMask, keyModifiers);
 						break;
 					case WindowsConsole.ControlKeyState.NumlockOn:
 						break;
@@ -667,16 +667,16 @@ namespace Terminal.Gui {
 					default:
 						switch (inputEvent.KeyEvent.wVirtualKeyCode) {
 						case 0x10:
-							key = new KeyEvent (Key.ShiftMask);
+							key = new KeyEvent (Key.ShiftMask, keyModifiers);
 							break;
 						case 0x11:
-							key = new KeyEvent (Key.CtrlMask);
+							key = new KeyEvent (Key.CtrlMask, keyModifiers);
 							break;
 						case 0x12:
-							key = new KeyEvent (Key.AltMask);
+							key = new KeyEvent (Key.AltMask, keyModifiers);
 							break;
 						default:
-							key = new KeyEvent (Key.Unknown);
+							key = new KeyEvent (Key.Unknown, keyModifiers);
 							break;
 						}
 						break;
@@ -689,12 +689,13 @@ namespace Terminal.Gui {
 				} else {
 					if (inputEvent.KeyEvent.bKeyDown) {
 						// Key Down - Fire KeyDown Event and KeyStroke (ProcessKey) Event
-						keyDownHandler (new KeyEvent (map));
-						keyHandler (new KeyEvent (map));
+						keyDownHandler (new KeyEvent (map, keyModifiers));
+						keyHandler (new KeyEvent (map, keyModifiers));
 					} else {
-						keyUpHandler (new KeyEvent (map));
+						keyUpHandler (new KeyEvent (map, keyModifiers));
 					}
 				}
+				keyModifiers = null;
 				break;
 
 			case WindowsConsole.EventType.Mouse:
@@ -906,6 +907,8 @@ namespace Terminal.Gui {
 			return mouseFlag;
 		}
 
+		KeyModifiers keyModifiers;
+
 		public ConsoleKeyInfoEx ToConsoleKeyInfoEx (WindowsConsole.KeyEventRecord keyEvent)
 		{
 			var state = keyEvent.dwControlKeyState;
@@ -915,6 +918,22 @@ namespace Terminal.Gui {
 			bool control = (state & (WindowsConsole.ControlKeyState.LeftControlPressed | WindowsConsole.ControlKeyState.RightControlPressed)) != 0;
 			bool capslock = (state & (WindowsConsole.ControlKeyState.CapslockOn)) != 0;
 			bool numlock = (state & (WindowsConsole.ControlKeyState.NumlockOn)) != 0;
+			bool scrolllock = (state & (WindowsConsole.ControlKeyState.ScrolllockOn)) != 0;
+
+			if (keyModifiers == null)
+				keyModifiers = new KeyModifiers ();
+			if (shift)
+				keyModifiers.Shift = shift;
+			if (alt)
+				keyModifiers.Alt = alt;
+			if (control)
+				keyModifiers.Ctrl = control;
+			if (capslock)
+				keyModifiers.Capslock = capslock;
+			if (numlock)
+				keyModifiers.Numlock = numlock;
+			if (scrolllock)
+				keyModifiers.Scrolllock = scrolllock;
 
 			var ConsoleKeyInfo = new ConsoleKeyInfo (keyEvent.UnicodeChar, (ConsoleKey)keyEvent.wVirtualKeyCode, shift, alt, control);
 			return new ConsoleKeyInfoEx (ConsoleKeyInfo, capslock, numlock);
@@ -1029,7 +1048,7 @@ namespace Terminal.Gui {
 			return (Key)(0xffffffff);
 		}
 
-		private static Key MapKeyModifiers (ConsoleKeyInfo keyInfo, Key key)
+		private Key MapKeyModifiers (ConsoleKeyInfo keyInfo, Key key)
 		{
 			Key keyMod = new Key ();
 			if (keyInfo.Modifiers.HasFlag (ConsoleModifiers.Shift))
@@ -1048,7 +1067,6 @@ namespace Terminal.Gui {
 			SetupColorsAndBorders ();
 		}
 
-
 		void ResizeScreen ()
 		{
 			OutputBuffer = new WindowsConsole.CharInfo [Rows * Cols];

+ 71 - 13
Terminal.Gui/Core/Event.cs

@@ -8,6 +8,36 @@ using System;
 
 namespace Terminal.Gui {
 
+	/// <summary>
+	/// Identifies the state of the "shift"-keys within a event.
+	/// </summary>
+	public class KeyModifiers {
+		/// <summary>
+		/// Check if the Shift key was pressed or not.
+		/// </summary>
+		public bool Shift;
+		/// <summary>
+		/// Check if the Alt key was pressed or not.
+		/// </summary>
+		public bool Alt;
+		/// <summary>
+		/// Check if the Ctrl key was pressed or not.
+		/// </summary>
+		public bool Ctrl;
+		/// <summary>
+		/// Check if the Caps lock key was pressed or not.
+		/// </summary>
+		public bool Capslock;
+		/// <summary>
+		/// Check if the Num lock key was pressed or not.
+		/// </summary>
+		public bool Numlock;
+		/// <summary>
+		/// Check if the Scroll lock key was pressed or not.
+		/// </summary>
+		public bool Scrolllock;
+	}
+
 	/// <summary>
 	/// The <see cref="Key"/> enumeration contains special encoding for some keys, but can also
 	/// encode all the unicode values that can be passed.   
@@ -297,6 +327,8 @@ namespace Terminal.Gui {
 	/// Describes a keyboard event.
 	/// </summary>
 	public class KeyEvent {
+		KeyModifiers keyModifiers;
+
 		/// <summary>
 		/// Symb olid definition for the key.
 		/// </summary>
@@ -313,20 +345,38 @@ namespace Terminal.Gui {
 		/// Gets a value indicating whether the Shift key was pressed.
 		/// </summary>
 		/// <value><c>true</c> if is shift; otherwise, <c>false</c>.</value>
-		public bool IsShift => (Key & Key.ShiftMask) != 0;
+		public bool IsShift => keyModifiers.Shift;
 
 		/// <summary>
 		/// Gets a value indicating whether the Alt key was pressed (real or synthesized)
 		/// </summary>
 		/// <value><c>true</c> if is alternate; otherwise, <c>false</c>.</value>
-		public bool IsAlt => (Key & Key.AltMask) != 0;
+		public bool IsAlt => keyModifiers.Alt;
 
 		/// <summary>
 		/// Determines whether the value is a control key (and NOT just the ctrl key)
 		/// </summary>
 		/// <value><c>true</c> if is ctrl; otherwise, <c>false</c>.</value>
 		//public bool IsCtrl => ((uint)Key >= 1) && ((uint)Key <= 26);
-		public bool IsCtrl => (Key & Key.CtrlMask) != 0;
+		public bool IsCtrl => keyModifiers.Ctrl;
+
+		/// <summary>
+		/// Gets a value indicating whether the Caps lock key was pressed (real or synthesized)
+		/// </summary>
+		/// <value><c>true</c> if is alternate; otherwise, <c>false</c>.</value>
+		public bool IsCapslock => keyModifiers.Capslock;
+
+		/// <summary>
+		/// Gets a value indicating whether the Num lock key was pressed (real or synthesized)
+		/// </summary>
+		/// <value><c>true</c> if is alternate; otherwise, <c>false</c>.</value>
+		public bool IsNumlock => keyModifiers.Numlock;
+
+		/// <summary>
+		/// Gets a value indicating whether the Scroll lock key was pressed (real or synthesized)
+		/// </summary>
+		/// <value><c>true</c> if is alternate; otherwise, <c>false</c>.</value>
+		public bool IsScrolllock => keyModifiers.Scrolllock;
 
 		/// <summary>
 		/// Constructs a new <see cref="KeyEvent"/>
@@ -334,14 +384,16 @@ namespace Terminal.Gui {
 		public KeyEvent ()
 		{
 			Key = Key.Unknown;
+			keyModifiers = new KeyModifiers ();
 		}
 
 		/// <summary>
 		///   Constructs a new <see cref="KeyEvent"/> from the provided Key value - can be a rune cast into a Key value
 		/// </summary>
-		public KeyEvent (Key k)
+		public KeyEvent (Key k, KeyModifiers km)
 		{
 			Key = k;
+			keyModifiers = km;
 		}
 
 		///<inheritdoc cref="ToString"/>
@@ -349,21 +401,27 @@ namespace Terminal.Gui {
 		{
 			string msg = "";
 			var key = this.Key;
-			if ((this.Key & Key.ShiftMask) != 0) {
+			if (keyModifiers.Shift) {
 				msg += "Shift-";
 			}
-			if ((this.Key & Key.CtrlMask) != 0) {
+			if (keyModifiers.Alt) {
+				msg += "Alt-";
+			}
+			if (keyModifiers.Ctrl) {
 				msg += "Ctrl-";
 			}
-			if ((this.Key & Key.AltMask) != 0) {
-				msg += "Alt-";
+			if (keyModifiers.Capslock) {
+				msg += "Capslock-";
 			}
-
-			if (string.IsNullOrEmpty (msg)) {
-				msg += $"{(((uint)this.KeyValue & (uint)Key.CharMask) > 27 ? $"{(char)this.KeyValue}" : $"{key}")}";
-			} else {
-				msg += $"{(((uint)this.KeyValue & (uint)Key.CharMask) > 27 ? $"{(char)this.KeyValue}" : $"")}";
+			if (keyModifiers.Numlock) {
+				msg += "Numlock-";
+			}
+			if (keyModifiers.Scrolllock) {
+				msg += "Scrolllock-";
 			}
+
+			msg += $"{(((uint)this.KeyValue & (uint)Key.CharMask) > 27 ? $"{(char)this.KeyValue}" : $"{key}")}";
+
 			return msg;
 		}
 	}

+ 7 - 3
Terminal.Gui/Views/HexView.cs

@@ -312,9 +312,13 @@ namespace Terminal.Gui {
 				MoveUp (bytesPerLine);
 				break;
 			case Key.Tab:
-				leftSide = !leftSide;
-				RedisplayLine (position);
-				firstNibble = true;
+				if (keyEvent.IsCtrl) {
+					SuperView.FocusNext ();
+				} else {
+					leftSide = !leftSide;
+					RedisplayLine (position);
+					firstNibble = true;
+				}
 				break;
 			case ((int)'v' + Key.AltMask):
 			case Key.PageUp:

+ 1 - 1
Terminal.Gui/Views/StatusBar.cs

@@ -47,7 +47,7 @@ namespace Terminal.Gui {
 		/// A <see cref="StatusItem.Title"/> set to `~F1~ Help` will render as *F1* using <see cref="ColorScheme.HotNormal"/> and
 		/// *Help* as <see cref="ColorScheme.HotNormal"/>.
 		/// </remarks>
-		public ustring Title { get; }
+		public ustring Title { get; set;}
 
 		/// <summary>
 		/// Gets or sets the action to be invoked when the statusbar item is triggered

+ 19 - 17
UICatalog/Scenarios/Keys.cs

@@ -83,7 +83,6 @@ namespace UICatalog {
 				Y = Pos.Top (editLabel) + 2,
 			};
 			Win.Add (keyPressedLabel);
-			// BUGBUG: Label is not positioning right with Pos, so using TextField instead
 			var labelKeypress = new Label ("") {
 				X = Pos.Left (edit),
 				Y = Pos.Top (keyPressedLabel),
@@ -107,25 +106,13 @@ namespace UICatalog {
 			var keyStrokeListView = new ListView (keyStrokelist) {
 				X = 0,
 				Y = Pos.Top (keyLogLabel) + yOffset,
-				Width = 25,
+				Width = Dim.Percent (40),
 				Height = Dim.Fill (),
 			};
 			keyStrokeListView.ColorScheme = Colors.TopLevel;
 			Win.Add (keyStrokeListView);
 
-			void KeyDownPressUp (KeyEvent keyEvent, string updown)
-			{
-				var msg = $"Key{updown,-5}: {keyEvent.ToString ()}";
-				keyStrokelist.Add (msg);
-				keyStrokeListView.MoveDown ();
-			}
-
-			Win.KeyDown += (sender, a) => KeyDownPressUp (a.KeyEvent, "Down");
-			Win.KeyPress += (sender, a) => KeyDownPressUp (a.KeyEvent, "Press");
-			Win.KeyUp += (sender, a) => KeyDownPressUp (a.KeyEvent, "Up");
-
 			// ProcessKey log:
-			// BUGBUG: Label is not positioning right with Pos, so using TextField instead
 			var processKeyLogLabel = new Label ("ProcessKey log:") {
 				X = Pos.Right (keyStrokeListView) + 1,
 				Y = Pos.Top (editLabel) + 4,
@@ -136,7 +123,7 @@ namespace UICatalog {
 			var processKeyListView = new ListView (_processKeyList) {
 				X = Pos.Left (processKeyLogLabel),
 				Y = Pos.Top (processKeyLogLabel) + yOffset,
-				Width = 25,
+				Width = Dim.Percent (60),
 				Height = Dim.Fill (),
 			};
 			processKeyListView.ColorScheme = Colors.TopLevel;
@@ -154,7 +141,7 @@ namespace UICatalog {
 			var processHotKeyListView = new ListView (_processHotKeyList) {
 				X = Pos.Left (processHotKeyLogLabel),
 				Y = Pos.Top (processHotKeyLogLabel) + yOffset,
-				Width = 25,
+				Width = Dim.Percent (50),
 				Height = Dim.Fill (),
 			};
 			processHotKeyListView.ColorScheme = Colors.TopLevel;
@@ -172,9 +159,24 @@ namespace UICatalog {
 			var processColdKeyListView = new ListView (_processColdKeyList) {
 				X = Pos.Left (processColdKeyLogLabel),
 				Y = Pos.Top (processColdKeyLogLabel) + yOffset,
-				Width = 25,
+				Width = Dim.Fill (),
 				Height = Dim.Fill (),
 			};
+
+			Win.KeyDown += (sender, a) => KeyDownPressUp (a.KeyEvent, "Down");
+			Win.KeyPress += (sender, a) => KeyDownPressUp (a.KeyEvent, "Press");
+			Win.KeyUp += (sender, a) => KeyDownPressUp (a.KeyEvent, "Up");
+
+			void KeyDownPressUp (KeyEvent keyEvent, string updown)
+			{
+				var msg = $"Key{updown,-5}: {keyEvent}";
+				keyStrokelist.Add (msg);
+				keyStrokeListView.MoveDown ();
+				processKeyListView.MoveDown ();
+				processColdKeyListView.MoveDown ();
+				processHotKeyListView.MoveDown ();
+			}
+
 			processColdKeyListView.ColorScheme = Colors.TopLevel;
 			Win.Add (processColdKeyListView);
 		}

+ 34 - 2
UICatalog/UICatalog.cs

@@ -50,6 +50,9 @@ namespace UICatalog {
 		private static List<Type> _scenarios;
 		private static ListView _scenarioListView;
 		private static StatusBar _statusBar;
+		private static StatusItem _capslock;
+		private static StatusItem _numlock;
+		private static StatusItem _scrolllock;
 
 		private static Scenario _runningScenario = null;
 
@@ -151,6 +154,10 @@ namespace UICatalog {
 			_categoryListView.SelectedItem = 0;
 			_categoryListView.OnSelectedChanged ();
 
+			_capslock = new StatusItem (Key.CharMask, "CapslockOff", null);
+			_numlock = new StatusItem (Key.CharMask, "NumlockOff", null);
+			_scrolllock = new StatusItem (Key.CharMask, "ScrolllockOff", null);
+
 			_statusBar = new StatusBar (new StatusItem [] {
 				//new StatusItem(Key.F1, "~F1~ Help", () => Help()),
 				new StatusItem(Key.ControlQ, "~CTRL-Q~ Quit", () => {
@@ -162,9 +169,10 @@ namespace UICatalog {
 						_runningScenario.RequestStop();
 					}
 				}),
+				_capslock,
+				_numlock,
+				_scrolllock
 			});
-
-
 		}
 
 		/// <summary>
@@ -292,6 +300,30 @@ namespace UICatalog {
 				else
 					_top.SetFocus (_leftPane);
 			}
+
+			if (a.KeyEvent.IsCapslock) {
+				_capslock.Title = "CapslockOn";
+				_statusBar.SetNeedsDisplay ();
+			} else {
+				_capslock.Title = "CapslockOff";
+				_statusBar.SetNeedsDisplay ();
+			}
+
+			if (a.KeyEvent.IsNumlock) {
+				_numlock.Title = "NumlockOn";
+				_statusBar.SetNeedsDisplay ();
+			} else {
+				_numlock.Title = "NumlockOff";
+				_statusBar.SetNeedsDisplay ();
+			}
+
+			if (a.KeyEvent.IsScrolllock) {
+				_scrolllock.Title = "ScrolllockOn";
+				_statusBar.SetNeedsDisplay ();
+			} else {
+				_scrolllock.Title = "ScrolllockOff";
+				_statusBar.SetNeedsDisplay ();
+			}
 		}
 
 		private static void CategoryListView_SelectedChanged (object sender, ListViewItemEventArgs e)